[Bf-blender-cvs] [e7cd64d] master: Fix T46561: Crash in outliner delete hierarchy

Campbell Barton noreply at git.blender.org
Thu Oct 22 09:49:47 CEST 2015


Commit: e7cd64dc971286f2430be9ad652a3031f91068a2
Author: Campbell Barton
Date:   Thu Oct 22 18:42:44 2015 +1100
Branches: master
https://developer.blender.org/rBe7cd64dc971286f2430be9ad652a3031f91068a2

Fix T46561: Crash in outliner delete hierarchy

When children & parents were selected in the outliner,
it attempted to free the the object twice.

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

M	source/blender/editors/space_outliner/outliner_intern.h
M	source/blender/editors/space_outliner/outliner_tools.c

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

diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index c89a1bb..f10e6be 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -150,8 +150,15 @@ int outliner_item_do_activate(struct bContext *C, int x, int y, bool extend, boo
 
 /* outliner_edit.c ---------------------------------------------- */
 
-void outliner_do_object_operation(struct bContext *C, struct Scene *scene, struct SpaceOops *soops, struct ListBase *lb, 
-                                  void (*operation_cb)(struct bContext *C, struct Scene *scene, struct TreeElement *, struct TreeStoreElem *, TreeStoreElem *));
+void outliner_do_object_operation_ex(
+        struct bContext *C, struct Scene *scene, struct SpaceOops *soops, struct ListBase *lb,
+        void (*operation_cb)(struct bContext *C, struct Scene *scene,
+                             struct TreeElement *, struct TreeStoreElem *, TreeStoreElem *),
+        bool recurse_selected);
+void outliner_do_object_operation(
+        struct bContext *C, struct Scene *scene, struct SpaceOops *soops, struct ListBase *lb,
+        void (*operation_cb)(struct bContext *C, struct Scene *scene,
+                             struct TreeElement *, struct TreeStoreElem *, TreeStoreElem *));
 
 int common_restrict_check(struct bContext *C, struct Object *ob);
 
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 50171d7..863f09d 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -516,15 +516,20 @@ static void group_instance_cb(bContext *C, Scene *scene, TreeElement *UNUSED(te)
 	id_lib_extern(&group->id);
 }
 
-void outliner_do_object_operation(bContext *C, Scene *scene_act, SpaceOops *soops, ListBase *lb, 
-                                  void (*operation_cb)(bContext *C, Scene *scene, TreeElement *,
-                                                       TreeStoreElem *, TreeStoreElem *))
+/**
+ * \param select_recurse: Set to false for operations which are already recursively operating on their children.
+ */
+void outliner_do_object_operation_ex(
+        bContext *C, Scene *scene_act, SpaceOops *soops, ListBase *lb,
+        void (*operation_cb)(bContext *C, Scene *scene, TreeElement *,
+                             TreeStoreElem *, TreeStoreElem *),
+        bool select_recurse)
 {
 	TreeElement *te;
-	TreeStoreElem *tselem;
 	
 	for (te = lb->first; te; te = te->next) {
-		tselem = TREESTORE(te);
+		TreeStoreElem *tselem = TREESTORE(te);
+		bool select_handled = false;
 		if (tselem->flag & TSE_SELECTED) {
 			if (tselem->type == 0 && te->idcode == ID_OB) {
 				// when objects selected in other scenes... dunno if that should be allowed
@@ -536,14 +541,25 @@ void outliner_do_object_operation(bContext *C, Scene *scene_act, SpaceOops *soop
 				 * only use 'scene_act' when 'scene_owner' is NULL, which can happen when the
 				 * outliner isn't showing scenes: Visible Layer draw mode for eg. */
 				operation_cb(C, scene_owner ? scene_owner : scene_act, te, NULL, tselem);
+				select_handled = true;
 			}
 		}
 		if (TSELEM_OPEN(tselem, soops)) {
-			outliner_do_object_operation(C, scene_act, soops, &te->subtree, operation_cb);
+			if ((select_handled == false) || select_recurse) {
+				outliner_do_object_operation_ex(C, scene_act, soops, &te->subtree, operation_cb, select_recurse);
+			}
 		}
 	}
 }
 
+void outliner_do_object_operation(
+        bContext *C, Scene *scene_act, SpaceOops *soops, ListBase *lb,
+        void (*operation_cb)(bContext *C, Scene *scene, TreeElement *,
+                             TreeStoreElem *, TreeStoreElem *))
+{
+	outliner_do_object_operation_ex(C, scene_act, soops, lb, operation_cb, true);
+}
+
 /* ******************************************** */
 
 static void clear_animdata_cb(int UNUSED(event), TreeElement *UNUSED(te),
@@ -876,7 +892,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
 	}
 	else if (event == OL_OP_SELECT_HIERARCHY) {
 		Scene *sce = scene;  // to be able to delete, scenes are set...
-		outliner_do_object_operation(C, scene, soops, &soops->tree, object_select_hierarchy_cb);
+		outliner_do_object_operation_ex(C, scene, soops, &soops->tree, object_select_hierarchy_cb, false);
 		if (scene != sce) {
 			ED_screen_set_scene(C, CTX_wm_screen(C), sce);
 		}	
@@ -903,7 +919,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op)
 		WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
 	}
 	else if (event == OL_OP_DELETE_HIERARCHY) {
-		outliner_do_object_operation(C, scene, soops, &soops->tree, object_delete_hierarchy_cb);
+		outliner_do_object_operation_ex(C, scene, soops, &soops->tree, object_delete_hierarchy_cb, false);
 
 		/* XXX: See OL_OP_DELETE comment above. */
 		outliner_cleanup_tree(soops);




More information about the Bf-blender-cvs mailing list