[Bf-blender-cvs] [0964ae52665] blender-v2.82-release: Fix T73234: Undo/redo with local collection crashes

Campbell Barton noreply at git.blender.org
Tue Feb 4 08:49:13 CET 2020


Commit: 0964ae5266541f09a1d54d8941393bada97d08a2
Author: Campbell Barton
Date:   Tue Feb 4 18:26:57 2020 +1100
Branches: blender-v2.82-release
https://developer.blender.org/rB0964ae5266541f09a1d54d8941393bada97d08a2

Fix T73234: Undo/redo with local collection crashes

Resolves crashes when edit-mode undo data wasn't included
because it wasn't visible, also resolves T73416.

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

M	source/blender/editors/armature/editarmature_undo.c
M	source/blender/editors/curve/editcurve_undo.c
M	source/blender/editors/include/ED_undo.h
M	source/blender/editors/lattice/editlattice_undo.c
M	source/blender/editors/mesh/editmesh_undo.c
M	source/blender/editors/metaball/editmball_undo.c
M	source/blender/editors/undo/ed_undo.c

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

diff --git a/source/blender/editors/armature/editarmature_undo.c b/source/blender/editors/armature/editarmature_undo.c
index 4e3ab11a9f7..4753698ae40 100644
--- a/source/blender/editors/armature/editarmature_undo.c
+++ b/source/blender/editors/armature/editarmature_undo.c
@@ -108,7 +108,8 @@ static void undoarm_free_data(UndoArmature *uarm)
 
 static Object *editarm_object_from_context(bContext *C)
 {
-  Object *obedit = CTX_data_edit_object(C);
+  ViewLayer *view_layer = CTX_data_view_layer(C);
+  Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
   if (obedit && obedit->type == OB_ARMATURE) {
     bArmature *arm = obedit->data;
     if (arm->edbo != NULL) {
@@ -151,8 +152,7 @@ static bool armature_undosys_step_encode(struct bContext *C, struct Main *bmain,
    * outside of this list will be moved out of edit-mode when reading back undo steps. */
   ViewLayer *view_layer = CTX_data_view_layer(C);
   uint objects_len = 0;
-  Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
-      view_layer, NULL, &objects_len);
+  Object **objects = ED_undo_editmode_objects_from_view_layer(view_layer, &objects_len);
 
   us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
   us->elems_len = objects_len;
diff --git a/source/blender/editors/curve/editcurve_undo.c b/source/blender/editors/curve/editcurve_undo.c
index ff3a1386fd9..8bcabb5ed85 100644
--- a/source/blender/editors/curve/editcurve_undo.c
+++ b/source/blender/editors/curve/editcurve_undo.c
@@ -216,8 +216,7 @@ static bool curve_undosys_step_encode(struct bContext *C, struct Main *bmain, Un
    * outside of this list will be moved out of edit-mode when reading back undo steps. */
   ViewLayer *view_layer = CTX_data_view_layer(C);
   uint objects_len = 0;
-  Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
-      view_layer, NULL, &objects_len);
+  Object **objects = ED_undo_editmode_objects_from_view_layer(view_layer, &objects_len);
 
   us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
   us->elems_len = objects_len;
diff --git a/source/blender/editors/include/ED_undo.h b/source/blender/editors/include/ED_undo.h
index fa2630ba726..1fbf2f96cfa 100644
--- a/source/blender/editors/include/ED_undo.h
+++ b/source/blender/editors/include/ED_undo.h
@@ -23,6 +23,7 @@
 
 #include "BLI_compiler_attrs.h"
 
+struct Base;
 struct CLG_LogRef;
 struct Object;
 struct UndoStack;
@@ -62,6 +63,10 @@ void ED_undo_object_editmode_restore_helper(struct bContext *C,
                                             uint object_array_len,
                                             uint object_array_stride);
 
+struct Object **ED_undo_editmode_objects_from_view_layer(struct ViewLayer *view_layer,
+                                                         uint *r_len);
+struct Base **ED_undo_editmode_bases_from_view_layer(struct ViewLayer *view_layer, uint *r_len);
+
 struct UndoStack *ED_undo_stack_get(void);
 
 /* helpers */
diff --git a/source/blender/editors/lattice/editlattice_undo.c b/source/blender/editors/lattice/editlattice_undo.c
index ed2560698b6..f90b70c492f 100644
--- a/source/blender/editors/lattice/editlattice_undo.c
+++ b/source/blender/editors/lattice/editlattice_undo.c
@@ -146,7 +146,8 @@ static int validate_undoLatt(void *data, void *edata)
 
 static Object *editlatt_object_from_context(bContext *C)
 {
-  Object *obedit = CTX_data_edit_object(C);
+  ViewLayer *view_layer = CTX_data_view_layer(C);
+  Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
   if (obedit && obedit->type == OB_LATTICE) {
     Lattice *lt = obedit->data;
     if (lt->editlatt != NULL) {
@@ -189,8 +190,7 @@ static bool lattice_undosys_step_encode(struct bContext *C, Main *bmain, UndoSte
    * outside of this list will be moved out of edit-mode when reading back undo steps. */
   ViewLayer *view_layer = CTX_data_view_layer(C);
   uint objects_len = 0;
-  Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
-      view_layer, NULL, &objects_len);
+  Object **objects = ED_undo_editmode_objects_from_view_layer(view_layer, &objects_len);
 
   us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
   us->elems_len = objects_len;
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index faa80341b0f..951efdc6127 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -672,7 +672,8 @@ static void undomesh_free_data(UndoMesh *um)
 
 static Object *editmesh_object_from_context(bContext *C)
 {
-  Object *obedit = CTX_data_edit_object(C);
+  ViewLayer *view_layer = CTX_data_view_layer(C);
+  Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
   if (obedit && obedit->type == OB_MESH) {
     Mesh *me = obedit->data;
     if (me->edit_mesh != NULL) {
@@ -715,8 +716,7 @@ static bool mesh_undosys_step_encode(struct bContext *C, struct Main *bmain, Und
    * outside of this list will be moved out of edit-mode when reading back undo steps. */
   ViewLayer *view_layer = CTX_data_view_layer(C);
   uint objects_len = 0;
-  Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
-      view_layer, NULL, &objects_len);
+  Object **objects = ED_undo_editmode_objects_from_view_layer(view_layer, &objects_len);
 
   us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
   us->elems_len = objects_len;
diff --git a/source/blender/editors/metaball/editmball_undo.c b/source/blender/editors/metaball/editmball_undo.c
index e8700e94e91..165db6c5a06 100644
--- a/source/blender/editors/metaball/editmball_undo.c
+++ b/source/blender/editors/metaball/editmball_undo.c
@@ -120,7 +120,8 @@ static void undomball_free_data(UndoMBall *umb)
 
 static Object *editmball_object_from_context(bContext *C)
 {
-  Object *obedit = CTX_data_edit_object(C);
+  ViewLayer *view_layer = CTX_data_view_layer(C);
+  Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
   if (obedit && obedit->type == OB_MBALL) {
     MetaBall *mb = obedit->data;
     if (mb->editelems != NULL) {
@@ -162,8 +163,7 @@ static bool mball_undosys_step_encode(struct bContext *C, struct Main *bmain, Un
    * outside of this list will be moved out of edit-mode when reading back undo steps. */
   ViewLayer *view_layer = CTX_data_view_layer(C);
   uint objects_len = 0;
-  Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
-      view_layer, NULL, &objects_len);
+  Object **objects = ED_undo_editmode_objects_from_view_layer(view_layer, &objects_len);
 
   us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
   us->elems_len = objects_len;
diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c
index 9770b52158a..d90590bce82 100644
--- a/source/blender/editors/undo/ed_undo.c
+++ b/source/blender/editors/undo/ed_undo.c
@@ -746,7 +746,7 @@ void ED_undo_object_editmode_restore_helper(struct bContext *C,
   uint bases_len = 0;
   /* Don't request unique data because we want to de-select objects when exiting edit-mode
    * for that to be done on all objects we can't skip ones that share data. */
-  Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(view_layer, NULL, &bases_len);
+  Base **bases = ED_undo_editmode_bases_from_view_layer(view_layer, &bases_len);
   for (uint i = 0; i < bases_len; i++) {
     ((ID *)bases[i]->object->data)->tag |= LIB_TAG_DOIT;
   }
@@ -770,3 +770,104 @@ void ED_undo_object_editmode_restore_helper(struct bContext *C,
 }
 
 /** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Undo View Layer Helper Functions
+ *
+ * Needed because view layer functions such as
+ * #BKE_view_layer_array_from_objects_in_edit_mode_unique_data also check visibility,
+ * which is not reliable when it comes to object undo operations,
+ * since hidden objects can be operated on in the properties editor,
+ * and local collections may be used.
+ * \{ */
+
+static int undo_editmode_objects_from_view_layer_prepare(ViewLayer *view_layer,
+                                                         Object *obact,
+                                                         int *r_active_index)
+{
+  const short object_type = obact->type;
+
+  for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+    Object *ob = base->object;
+    if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) {
+      ID *id = ob->data;
+      id->tag &= ~LIB_TAG_DOIT;
+    }
+  }
+
+  int len = 0;
+  for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+    Object *ob = base->object;
+    if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) {
+      if (ob == obact) {
+        *r_active_index = len;
+      }
+      ID *id = ob->data;
+      if ((id->tag & LIB_TAG_DOIT) == 0) {
+        len += 1;
+        id->tag |= LIB_TAG_DOIT;
+      }
+    }
+  }
+  return len;
+}
+
+Object **ED_undo_editmode_objects_from_view_layer(ViewLayer *view_layer, uint *r_len)
+{
+  Object *obact = OBACT(view_layer);
+  if ((obact == NULL) || (obact->mode & OB_MODE_EDIT) == 0) {
+    return MEM_mallocN(0, __func__);
+  }
+  int active_index = 0;
+  const int len = undo_editmode_objects_from_view_layer_prepare(view_layer, obact, &active_index);
+  const short object_type = obact->type;
+  int i = 0;
+  Object **objects = MEM_malloc_arrayN(len, sizeof(*objects), __func__);
+  for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+    Object *ob = base->object;
+    if ((ob->type == object_type) && (ob->mode & OB_MODE_EDIT)) {
+      ID *id = ob->data;
+      if (id->tag & LIB_TAG_DOIT) {
+        objects[i++] = ob;
+        id->tag &= ~LIB_TAG_DOIT;
+      }
+    }
+  }
+  BLI_assert(i == len);
+  if (active_index > 0) {
+    SWAP(Object *, objects[0], objects[active_index]);
+  }
+  *r_len = len;
+  return objects;
+}
+
+Base **ED_undo_editmode_bases_from_view_layer(ViewLayer *view_layer, uint *r_len)
+{
+  Object *obact = OBACT(view_layer);
+  if ((obact == NULL) || (obact->mode & OB_MODE_EDIT) == 0) {
+    return MEM_mallocN(0, __func__);
+  }
+  int active_index = 0;
+  const int len = undo_edi

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list