diff options
author | Julian Eisel <eiseljulian@gmail.com> | 2017-02-28 22:37:14 +0300 |
---|---|---|
committer | Julian Eisel <eiseljulian@gmail.com> | 2017-02-28 23:15:51 +0300 |
commit | c0e055fa7e4b171b9a188bc2328c6c11d2af22ab (patch) | |
tree | c00febbae447a1a533af520ef8480d19ce38f4be /source/blender/editors/space_outliner/outliner_collections.c | |
parent | 5e889ebf19ae1bd3daf6930473dc1d19029bf837 (diff) |
Outliner: Delete all selected collections, not just active one
There were some issues with how we store outliner tree elements:
Apparently the only removable elements have been data-blocks so far.
When recreating the TreeElements, their TreeStoreElem instances were
mainly identified by their ID pointer. However non-data-blocks mostly
depend on an index. For collections, such an index isn't a reliable
measure though if we want to allow removing items. Depending on it for
identifying the TreeStoreElem instance would cause some quite noticeable
glitches (wrong highlights, two elements sharing highlight, etc).
For now I've solved that by actually removing the TreeStoreElem that
represents the removed element. A little limitation of this is that
after undoing the removal, some information might get lost, like
flags to store selection, or opened/closed state.
A better solution that would also fix this issue would be having a real
unique identifier for each non-data-block element, like an idname or even
its data-pointer. Not sure if we can get those to work reliable with
file read/write though, would have to investigate...
Also added a general Outliner tree traversal utility.
Diffstat (limited to 'source/blender/editors/space_outliner/outliner_collections.c')
-rw-r--r-- | source/blender/editors/space_outliner/outliner_collections.c | 64 |
1 files changed, 36 insertions, 28 deletions
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c index cf63e17870f..889fb6dd36f 100644 --- a/source/blender/editors/space_outliner/outliner_collections.c +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -54,12 +54,14 @@ static LayerCollection *outliner_collection_active(bContext *C) return CTX_data_layer_collection(C); } +#if 0 static CollectionOverride *outliner_override_active(bContext *UNUSED(C)) { TODO_LAYER_OPERATORS; TODO_LAYER_OVERRIDE; return NULL; } +#endif /* -------------------------------------------------------------------- */ /* collection manager operators */ @@ -283,55 +285,61 @@ void OUTLINER_OT_collection_override_new(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/** - * Returns true if selected element is a collection - * or an override, but not a master collection - */ -static int collection_delete_poll(bContext *C) +struct CollectionDeleteData { + Scene *scene; + SpaceOops *soops; +}; + +static TreeTraversalReturn collection_delete_cb(TreeElement *te, void *customdata) { - LayerCollection *lc = outliner_collection_active(C); + struct CollectionDeleteData *data = customdata; + TreeStoreElem *tselem = TREESTORE(te); + LayerCollection *lc = te->directdata; - if (lc == NULL) { - /* try override */ - return outliner_override_active(C) ? 1 : 0; + if (tselem->type != TSE_LAYER_COLLECTION) { + /* skip */ + } + else if (lc->scene_collection == BKE_collection_master(data->scene)) { + /* skip - showing warning/error message might be missleading + * when deleting multiple collections, so just do nothing */ + } + else { + /* XXX removing the treestore element shouldn't be done, it makes us loose information after + * undo/file-read. We do need it here however, because non-ID elements don't have an ID pointer + * that can be used to lookup the TreeStoreElem when recreating the TreeElement. This index + * won't be correct after removing a collection from the list though. + * This works as workaround, but having a proper way to find the TreeStoreElem for a recreated + * TreeElement would be better. It could use an idname or the directdata pointer for that. */ + outliner_remove_treestore_element(data->soops, tselem); + BKE_collection_remove(data->scene, lc->scene_collection); } - return (lc->scene_collection == BKE_collection_master(CTX_data_scene(C))) ? 0 : 1; + return TRAVERSE_CONTINUE; } -static int collection_delete_exec(bContext *C, wmOperator *op) +static int collection_delete_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - LayerCollection *lc = outliner_collection_active(C); + SpaceOops *soops = CTX_wm_space_outliner(C); + struct CollectionDeleteData data = {.scene = scene, .soops = soops}; TODO_LAYER_OVERRIDE; /* handle operators */ - - if (lc == NULL) { - BKE_report(op->reports, RPT_ERROR, "Active element is not a collection"); - return OPERATOR_CANCELLED; - } - - if (lc->scene_collection == BKE_collection_master(scene)) { - BKE_report(op->reports, RPT_ERROR, "You cannot delete the master collection, try unliking it instead"); - return OPERATOR_CANCELLED; - } - - BKE_collection_remove(scene, lc->scene_collection); + outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_delete_cb, &data); WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); + return OPERATOR_FINISHED; } -void OUTLINER_OT_collection_delete(wmOperatorType *ot) +void OUTLINER_OT_collections_delete(wmOperatorType *ot) { /* identifiers */ ot->name = "Delete"; - ot->idname = "OUTLINER_OT_collection_delete"; - ot->description = "Delete active override or collection"; + ot->idname = "OUTLINER_OT_collections_delete"; + ot->description = "Delete selected overrides or collections"; /* api callbacks */ ot->exec = collection_delete_exec; - ot->poll = collection_delete_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; |