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_edit.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_edit.c')
-rw-r--r-- | source/blender/editors/space_outliner/outliner_edit.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 7d801318c33..2ab506ea746 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -198,6 +198,50 @@ TreeElement *outliner_find_item_at_x_in_row(const SpaceOops *soops, const TreeEl return (TreeElement *)parent_te; } +/** + * Iterate over all tree elements (pre-order traversal), executing \a func callback for + * each tree element matching the optional filters. + * + * \param filter_te_flag: If not 0, only TreeElements with this flag will be visited. + * \param filter_tselem_flag: Same as \a filter_te_flag, but for the TreeStoreElem. + * \param func: Custom callback to execute for each visited item. + */ +bool outliner_tree_traverse(const SpaceOops *soops, ListBase *tree, int filter_te_flag, int filter_tselem_flag, + TreeTraversalFunc func, void *customdata) +{ + for (TreeElement *te = tree->first, *te_next; te; te = te_next) { + TreeTraversalReturn func_retval = TRAVERSE_CONTINUE; + /* in case te is freed in callback */ + TreeStoreElem *tselem = TREESTORE(te); + ListBase subtree = te->subtree; + te_next = te->next; + + if (filter_te_flag && (te->flag & filter_te_flag) == 0) { + /* skip */ + } + else if (filter_tselem_flag && (tselem->flag & filter_tselem_flag) == 0) { + /* skip */ + } + else { + func_retval = func(te, customdata); + } + /* Don't access te or tselem from now on! Might've been freed... */ + + if (func_retval == TRAVERSE_BREAK) { + return false; + } + + if (func_retval == TRAVERSE_SKIP_CHILDS) { + /* skip */ + } + else if (!outliner_tree_traverse(soops, &subtree, filter_te_flag, filter_tselem_flag, func, customdata)) { + return false; + } + } + + return true; +} + /* ************************************************************** */ |