diff options
author | Campbell Barton <ideasman42@gmail.com> | 2015-10-22 10:42:44 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2015-10-22 10:42:44 +0300 |
commit | e7cd64dc971286f2430be9ad652a3031f91068a2 (patch) | |
tree | 0a45f108573d84ffd112b4f5d35f04a272b9c9a1 /source/blender/editors/space_outliner | |
parent | c6d98fa8418d16f124a2866adf8a5848734241fd (diff) |
Fix T46561: Crash in outliner delete hierarchy
When children & parents were selected in the outliner,
it attempted to free the the object twice.
Diffstat (limited to 'source/blender/editors/space_outliner')
-rw-r--r-- | source/blender/editors/space_outliner/outliner_intern.h | 11 | ||||
-rw-r--r-- | source/blender/editors/space_outliner/outliner_tools.c | 32 |
2 files changed, 33 insertions, 10 deletions
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index c89a1bb1b9f..f10e6be2fa9 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 50171d7f032..863f09d4039 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); |