[Bf-blender-cvs] [ec7199242f6] undo-experiments: undoexp: fix crashes with even trivial relationships (like parent ones).

Bastien Montagne noreply at git.blender.org
Thu Jan 2 17:04:57 CET 2020


Commit: ec7199242f6b361a14ac179494f2991bf9b4e1e7
Author: Bastien Montagne
Date:   Thu Jan 2 17:03:05 2020 +0100
Branches: undo-experiments
https://developer.blender.org/rBec7199242f6b361a14ac179494f2991bf9b4e1e7

undoexp: fix crashes with even trivial relationships (like parent ones).

Even if we re-used an old ID, it may have some pointers to other IDs
remapped to newly read data, e.g. the `parent` of an object...

So CoW/evaluated data in re-used despgraph needs to be flushed in those
cases.

===================================================================

M	source/blender/blenkernel/intern/undo_system.c

===================================================================

diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c
index 0a487c7bdf1..5d049e9fa3e 100644
--- a/source/blender/blenkernel/intern/undo_system.c
+++ b/source/blender/blenkernel/intern/undo_system.c
@@ -38,11 +38,15 @@
 
 #include "BKE_context.h"
 #include "BKE_global.h"
+#include "BKE_library.h"
 #include "BKE_library_override.h"
+#include "BKE_library_query.h"
 #include "BKE_main.h"
 #include "BKE_scene.h"
 #include "BKE_undo_system.h"
 
+#include "DEG_depsgraph.h"
+
 #include "MEM_guardedalloc.h"
 
 #define undo_stack _wm_undo_stack_disallow /* pass in as a variable always. */
@@ -178,6 +182,25 @@ static bool undosys_step_encode(bContext *C, Main *bmain, UndoStack *ustack, Und
   return ok;
 }
 
+static int undosys_step_id_reused_cb(void *user_data,
+                                     ID *id_self,
+                                     ID **id_pointer,
+                                     int UNUSED(cb_flag))
+{
+  BLI_assert((id_self->tag & LIB_TAG_UNDO_OLD_ID_REUSED) != 0);
+  Main *bmain = user_data;
+
+  ID *id = *id_pointer;
+  if (id != NULL && id->lib == NULL && (id->tag & LIB_TAG_UNDO_OLD_ID_REUSED) == 0) {
+    /* In case an old, re-used ID is using a newly read data-block (i.e. one of its ID pointers got
+     * updated), we have to tell the depsgraph about it. */
+    DEG_id_tag_update_ex(bmain, id_self, ID_RECALC_COPY_ON_WRITE);
+    return IDWALK_RET_STOP_ITER;
+  }
+
+  return IDWALK_RET_NOP;
+}
+
 static void undosys_step_decode(
     bContext *C, Main *bmain, UndoStack *ustack, UndoStep *us, int dir, bool is_final)
 {
@@ -220,6 +243,18 @@ static void undosys_step_decode(
   bmain = G_MAIN;
   BKE_scene_undo_depsgraphs_restore(bmain, depsgraphs);
 
+  /* We need to inform depsgraph about re-used old IDs that would be using newly read data-blocks,
+   * at least COW evaluated copies need to be updated... */
+  ID *id = NULL;
+  FOREACH_MAIN_ID_BEGIN (bmain, id) {
+    if (id->tag & LIB_TAG_UNDO_OLD_ID_REUSED) {
+      BKE_library_foreach_ID_link(bmain, id, undosys_step_id_reused_cb, bmain, IDWALK_READONLY);
+    }
+  }
+  FOREACH_MAIN_ID_END;
+
+  BKE_main_id_tag_all(bmain, LIB_TAG_UNDO_OLD_ID_REUSED, false);
+
 #ifdef WITH_GLOBAL_UNDO_CORRECT_ORDER
   if (us->type == BKE_UNDOSYS_TYPE_MEMFILE) {
     ustack->step_active_memfile = us;



More information about the Bf-blender-cvs mailing list