Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c32
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h3
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c38
3 files changed, 51 insertions, 22 deletions
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 239e6a9b0fc..2f4d8cc60cb 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -628,6 +628,26 @@ static TreeTraversalAction collection_find_data_to_delete(TreeElement *te, void
}
else {
BLI_gset_add(data->collections_to_delete, scene_collection);
+ return TRAVERSE_SKIP_CHILDS; /* Childs will be gone anyway, no need to recurse deeper. */
+ }
+
+ return TRAVERSE_CONTINUE;
+}
+
+static TreeTraversalAction collection_delete_elements_from_collection(TreeElement *te, void *customdata)
+{
+ struct CollectionDeleteData *data = customdata;
+ SceneCollection *scene_collection = outliner_scene_collection_from_tree_element(te);
+
+ if (!scene_collection) {
+ return TRAVERSE_SKIP_CHILDS;
+ }
+
+ const bool will_be_deleted = BLI_gset_haskey(data->collections_to_delete, scene_collection);
+ if (will_be_deleted) {
+ outliner_free_tree_element(te, te->parent ? &te->parent->subtree : &data->soops->tree);
+ /* Childs are freed now, so don't recurse into them. */
+ return TRAVERSE_SKIP_CHILDS;
}
return TRAVERSE_CONTINUE;
@@ -635,9 +655,7 @@ static TreeTraversalAction collection_find_data_to_delete(TreeElement *te, void
static int collection_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
- Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
SpaceOops *soops = CTX_wm_space_outliner(C);
struct CollectionDeleteData data = {.scene = scene, .soops = soops};
@@ -648,21 +666,20 @@ static int collection_delete_exec(bContext *C, wmOperator *UNUSED(op))
/* We first walk over and find the SceneCollections we actually want to delete (ignoring duplicates). */
outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_data_to_delete, &data);
+ /* Now, delete all tree elements representing a collection that will be deleted. We'll look for a
+ * new element to select in a few lines, so we can't wait until the tree is recreated on redraw. */
+ outliner_tree_traverse(soops, &soops->tree, 0, 0, collection_delete_elements_from_collection, &data);
+
/* Effectively delete the collections. */
GSetIterator collections_to_delete_iter;
GSET_ITER(collections_to_delete_iter, data.collections_to_delete) {
-
SceneCollection *sc = BLI_gsetIterator_getKey(&collections_to_delete_iter);
BKE_collection_remove(&data.scene->id, sc);
}
BLI_gset_free(data.collections_to_delete, NULL);
- /* Rebuild the outliner tree before we select the tree element */
- outliner_build_tree(bmain, scene, view_layer, soops);
-
TreeElement *select_te = outliner_tree_element_from_layer_collection(C);
-
if (select_te) {
outliner_item_select(soops, select_te, false, false);
}
@@ -672,6 +689,7 @@ static int collection_delete_exec(bContext *C, wmOperator *UNUSED(op))
/* TODO(sergey): Use proper flag for tagging here. */
DEG_id_tag_update(&scene->id, 0);
+ soops->storeflag |= SO_TREESTORE_REDRAW;
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index f2457b30a15..66f6c7026e6 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -178,8 +178,9 @@ typedef enum {
/* outliner_tree.c ----------------------------------------------- */
-void outliner_free_tree(ListBase *lb);
+void outliner_free_tree(ListBase *tree);
void outliner_cleanup_tree(struct SpaceOops *soops);
+void outliner_free_tree_element(TreeElement *element, ListBase *parent_subtree);
void outliner_remove_treestore_element(struct SpaceOops *soops, TreeStoreElem *tselem);
void outliner_build_tree(struct Main *mainvar, struct Scene *scene, struct ViewLayer *view_layer, struct SpaceOops *soops);
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 3a97964e538..4097751fd0c 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -189,16 +189,11 @@ static void check_persistent(SpaceOops *soops, TreeElement *te, ID *id, short ty
/* ********************************************************* */
/* Tree Management */
-void outliner_free_tree(ListBase *lb)
+void outliner_free_tree(ListBase *tree)
{
- while (lb->first) {
- TreeElement *te = lb->first;
-
- outliner_free_tree(&te->subtree);
- BLI_remlink(lb, te);
-
- if (te->flag & TE_FREE_NAME) MEM_freeN((void *)te->name);
- MEM_freeN(te);
+ for (TreeElement *element = tree->first, *element_next; element; element = element_next) {
+ element_next = element->next;
+ outliner_free_tree_element(element, tree);
}
}
@@ -208,6 +203,25 @@ void outliner_cleanup_tree(SpaceOops *soops)
outliner_storage_cleanup(soops);
}
+/**
+ * Free \a element and its sub-tree and remove its link in \a parent_subtree.
+ *
+ * \note Does not remove the TreeStoreElem of \a element!
+ * \param parent_subtree Subtree of the parent element, so the list containing \a element.
+ */
+void outliner_free_tree_element(TreeElement *element, ListBase *parent_subtree)
+{
+ BLI_assert(BLI_findindex(parent_subtree, element) > -1);
+ BLI_remlink(parent_subtree, element);
+
+ outliner_free_tree(&element->subtree);
+
+ if (element->flag & TE_FREE_NAME) {
+ MEM_freeN((void *)element->name);
+ }
+ MEM_freeN(element);
+}
+
/* ********************************************************* */
@@ -1780,11 +1794,7 @@ static int outliner_filter_tree(SpaceOops *soops, ListBase *lb)
tselem->flag &= ~TSE_SEARCHMATCH;
if ((!TSELEM_OPEN(tselem, soops)) || outliner_filter_tree(soops, &te->subtree) == 0) {
- outliner_free_tree(&te->subtree);
- BLI_remlink(lb, te);
-
- if (te->flag & TE_FREE_NAME) MEM_freeN((void *)te->name);
- MEM_freeN(te);
+ outliner_free_tree_element(te, lb);
}
}
else {