diff options
Diffstat (limited to 'source/blender/editors/space_outliner/outliner_tree.c')
-rw-r--r-- | source/blender/editors/space_outliner/outliner_tree.c | 401 |
1 files changed, 25 insertions, 376 deletions
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 9cd38ac07f5..83be26793ee 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -85,6 +85,7 @@ #include "UI_interface.h" #include "outliner_intern.h" +#include "tree/tree_display.h" #ifdef WIN32 # include "BLI_math_base.h" /* M_PI */ @@ -94,7 +95,6 @@ static TreeElement *outliner_add_collection_recursive(SpaceOutliner *space_outliner, Collection *collection, TreeElement *ten); -static void outliner_make_object_parent_hierarchy(ListBase *lb); static int outliner_exclude_filter_get(const SpaceOutliner *space_outliner); /* ********************************************************* */ @@ -237,14 +237,6 @@ void outliner_free_tree_element(TreeElement *element, ListBase *parent_subtree) /* ********************************************************* */ -/* Prototype, see functions below */ -static TreeElement *outliner_add_element(SpaceOutliner *space_outliner, - ListBase *lb, - void *idv, - TreeElement *parent, - short type, - short index); - /* -------------------------------------------------------- */ bool outliner_requires_rebuild_on_select_or_active_change(const SpaceOutliner *space_outliner) @@ -920,12 +912,12 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner, * \note: If child items are only added to the tree if the item is open, the TSE_ type _must_ be * added to #outliner_element_needs_rebuild_on_open_change(). */ -static TreeElement *outliner_add_element(SpaceOutliner *space_outliner, - ListBase *lb, - void *idv, - TreeElement *parent, - short type, - short index) +TreeElement *outliner_add_element(SpaceOutliner *space_outliner, + ListBase *lb, + void *idv, + TreeElement *parent, + short type, + short index) { TreeElement *te; TreeStoreElem *tselem; @@ -1390,110 +1382,6 @@ static void outliner_add_seq_dup(SpaceOutliner *space_outliner, /* ----------------------------------------------- */ -static const char *outliner_idcode_to_plural(short idcode) -{ - const char *propname = BKE_idtype_idcode_to_name_plural(idcode); - PropertyRNA *prop = RNA_struct_type_find_property(&RNA_BlendData, propname); - return (prop) ? RNA_property_ui_name(prop) : "UNKNOWN"; -} - -static bool outliner_library_id_show(Library *lib, ID *id, short filter_id_type) -{ - if (id->lib != lib) { - return false; - } - - if (filter_id_type == ID_GR) { - /* Don't show child collections of non-scene master collection, - * they are already shown as children. */ - Collection *collection = (Collection *)id; - bool has_non_scene_parent = false; - - LISTBASE_FOREACH (CollectionParent *, cparent, &collection->parents) { - if (!(cparent->collection->flag & COLLECTION_IS_MASTER)) { - has_non_scene_parent = true; - } - } - - if (has_non_scene_parent) { - return false; - } - } - - return true; -} - -static TreeElement *outliner_add_library_contents(Main *mainvar, - SpaceOutliner *space_outliner, - ListBase *lb, - Library *lib) -{ - TreeElement *ten, *tenlib = NULL; - ListBase *lbarray[MAX_LIBARRAY]; - int a, tot; - short filter_id_type = (space_outliner->filter & SO_FILTER_ID_TYPE) ? - space_outliner->filter_id_type : - 0; - - if (filter_id_type) { - lbarray[0] = which_libbase(mainvar, space_outliner->filter_id_type); - tot = 1; - } - else { - tot = set_listbasepointers(mainvar, lbarray); - } - - for (a = 0; a < tot; a++) { - if (lbarray[a] && lbarray[a]->first) { - ID *id = lbarray[a]->first; - const bool is_library = (GS(id->name) == ID_LI) && (lib != NULL); - - /* check if there's data in current lib */ - for (; id; id = id->next) { - if (id->lib == lib) { - break; - } - } - - /* We always want to create an entry for libraries, even if/when we have no more IDs from - * them. This invalid state is important to show to user as well.*/ - if (id != NULL || is_library) { - if (!tenlib) { - /* Create library tree element on demand, depending if there are any data-blocks. */ - if (lib) { - tenlib = outliner_add_element(space_outliner, lb, lib, NULL, 0, 0); - } - else { - tenlib = outliner_add_element(space_outliner, lb, mainvar, NULL, TSE_ID_BASE, 0); - tenlib->name = IFACE_("Current File"); - } - } - - /* Create data-block list parent element on demand. */ - if (id != NULL) { - if (filter_id_type) { - ten = tenlib; - } - else { - ten = outliner_add_element( - space_outliner, &tenlib->subtree, lbarray[a], NULL, TSE_ID_BASE, 0); - ten->directdata = lbarray[a]; - ten->name = outliner_idcode_to_plural(GS(id->name)); - } - - for (id = lbarray[a]->first; id; id = id->next) { - if (outliner_library_id_show(lib, id, filter_id_type)) { - outliner_add_element(space_outliner, &ten->subtree, id, ten, 0, 0); - } - } - } - } - } - } - - return tenlib; -} - static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOutliner *space_outliner) { TreeElement *ten; @@ -1546,82 +1434,6 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOutliner *space } } -static void outliner_add_layer_collection_objects(SpaceOutliner *space_outliner, - ListBase *tree, - ViewLayer *layer, - LayerCollection *lc, - TreeElement *ten) -{ - LISTBASE_FOREACH (CollectionObject *, cob, &lc->collection->gobject) { - Base *base = BKE_view_layer_base_find(layer, cob->ob); - TreeElement *te_object = outliner_add_element(space_outliner, tree, base->object, ten, 0, 0); - te_object->directdata = base; - - if (!(base->flag & BASE_VISIBLE_VIEWLAYER)) { - te_object->flag |= TE_DISABLED; - } - } -} - -static void outliner_add_layer_collections_recursive(SpaceOutliner *space_outliner, - ListBase *tree, - ViewLayer *layer, - ListBase *layer_collections, - TreeElement *parent_ten, - const bool show_objects) -{ - LISTBASE_FOREACH (LayerCollection *, lc, layer_collections) { - const bool exclude = (lc->flag & LAYER_COLLECTION_EXCLUDE) != 0; - TreeElement *ten; - - if (exclude && ((space_outliner->show_restrict_flags & SO_RESTRICT_ENABLE) == 0)) { - ten = parent_ten; - } - else { - ID *id = &lc->collection->id; - ten = outliner_add_element(space_outliner, tree, id, parent_ten, TSE_LAYER_COLLECTION, 0); - - ten->name = id->name + 2; - ten->directdata = lc; - - /* Open by default, except linked collections, which may contain many elements. */ - TreeStoreElem *tselem = TREESTORE(ten); - if (!(tselem->used || ID_IS_LINKED(id) || ID_IS_OVERRIDE_LIBRARY(id))) { - tselem->flag &= ~TSE_CLOSED; - } - - if (exclude || (lc->runtime_flag & LAYER_COLLECTION_VISIBLE_VIEW_LAYER) == 0) { - ten->flag |= TE_DISABLED; - } - } - - outliner_add_layer_collections_recursive( - space_outliner, &ten->subtree, layer, &lc->layer_collections, ten, show_objects); - if (!exclude && show_objects) { - outliner_add_layer_collection_objects(space_outliner, &ten->subtree, layer, lc, ten); - } - } -} - -static void outliner_add_view_layer(SpaceOutliner *space_outliner, - ListBase *tree, - TreeElement *parent, - ViewLayer *layer, - const bool show_objects) -{ - /* First layer collection is for master collection, don't show it. */ - LayerCollection *lc = layer->layer_collections.first; - if (lc == NULL) { - return; - } - - outliner_add_layer_collections_recursive( - space_outliner, tree, layer, &lc->layer_collections, parent, show_objects); - if (show_objects) { - outliner_add_layer_collection_objects(space_outliner, tree, layer, lc, parent); - } -} - BLI_INLINE void outliner_add_collection_init(TreeElement *te, Collection *collection) { te->name = BKE_collection_ui_name_get(collection); @@ -1661,7 +1473,7 @@ static TreeElement *outliner_add_collection_recursive(SpaceOutliner *space_outli /* Hierarchy --------------------------------------------- */ /* make sure elements are correctly nested */ -static void outliner_make_object_parent_hierarchy(ListBase *lb) +void outliner_make_object_parent_hierarchy(ListBase *lb) { TreeElement *te, *ten, *tep; TreeStoreElem *tselem; @@ -1686,103 +1498,6 @@ static void outliner_make_object_parent_hierarchy(ListBase *lb) } } -/** - * For all objects in the tree, lookup the parent in this map, - * and move or add tree elements as needed. - */ -static void outliner_make_object_parent_hierarchy_collections(SpaceOutliner *space_outliner, - GHash *object_tree_elements_hash) -{ - GHashIterator gh_iter; - GHASH_ITER (gh_iter, object_tree_elements_hash) { - Object *child = BLI_ghashIterator_getKey(&gh_iter); - - if (child->parent == NULL) { - continue; - } - - ListBase *child_ob_tree_elements = BLI_ghashIterator_getValue(&gh_iter); - ListBase *parent_ob_tree_elements = BLI_ghash_lookup(object_tree_elements_hash, child->parent); - if (parent_ob_tree_elements == NULL) { - continue; - } - - LISTBASE_FOREACH (LinkData *, link, parent_ob_tree_elements) { - TreeElement *parent_ob_tree_element = link->data; - TreeElement *parent_ob_collection_tree_element = NULL; - bool found = false; - - /* We always want to remove the child from the direct collection its parent is nested under. - * This is particularly important when dealing with multi-level nesting (grandchildren). */ - parent_ob_collection_tree_element = parent_ob_tree_element->parent; - while (!ELEM(TREESTORE(parent_ob_collection_tree_element)->type, - TSE_VIEW_COLLECTION_BASE, - TSE_LAYER_COLLECTION)) { - parent_ob_collection_tree_element = parent_ob_collection_tree_element->parent; - } - - LISTBASE_FOREACH (LinkData *, link_iter, child_ob_tree_elements) { - TreeElement *child_ob_tree_element = link_iter->data; - - if (child_ob_tree_element->parent == parent_ob_collection_tree_element) { - /* Move from the collection subtree into the parent object subtree. */ - BLI_remlink(&parent_ob_collection_tree_element->subtree, child_ob_tree_element); - BLI_addtail(&parent_ob_tree_element->subtree, child_ob_tree_element); - child_ob_tree_element->parent = parent_ob_tree_element; - found = true; - break; - } - } - - if (!found) { - /* We add the child in the tree even if it is not in the collection. - * We deliberately clear its sub-tree though, to make it less prominent. */ - TreeElement *child_ob_tree_element = outliner_add_element( - space_outliner, &parent_ob_tree_element->subtree, child, parent_ob_tree_element, 0, 0); - outliner_free_tree(&child_ob_tree_element->subtree); - child_ob_tree_element->flag |= TE_CHILD_NOT_IN_COLLECTION; - BLI_addtail(child_ob_tree_elements, BLI_genericNodeN(child_ob_tree_element)); - } - } - } -} - -/** - * Build a map from Object* to a list of TreeElement* matching the object. - */ -static void outliner_object_tree_elements_lookup_create_recursive(GHash *object_tree_elements_hash, - TreeElement *te_parent) -{ - LISTBASE_FOREACH (TreeElement *, te, &te_parent->subtree) { - TreeStoreElem *tselem = TREESTORE(te); - - if (tselem->type == TSE_LAYER_COLLECTION) { - outliner_object_tree_elements_lookup_create_recursive(object_tree_elements_hash, te); - } - else if (tselem->type == 0 && te->idcode == ID_OB) { - Object *ob = (Object *)tselem->id; - ListBase *tree_elements = BLI_ghash_lookup(object_tree_elements_hash, ob); - - if (tree_elements == NULL) { - tree_elements = MEM_callocN(sizeof(ListBase), __func__); - BLI_ghash_insert(object_tree_elements_hash, ob, tree_elements); - } - - BLI_addtail(tree_elements, BLI_genericNodeN(te)); - outliner_object_tree_elements_lookup_create_recursive(object_tree_elements_hash, te); - } - } -} - -static void outliner_object_tree_elements_lookup_free(GHash *object_tree_elements_hash) -{ - GHASH_FOREACH_BEGIN (ListBase *, tree_elements, object_tree_elements_hash) { - BLI_freelistN(tree_elements); - MEM_freeN(tree_elements); - } - GHASH_FOREACH_END(); -} - /* Sorting ------------------------------------------------------ */ typedef struct tTreeSort { @@ -2499,59 +2214,23 @@ void outliner_build_tree(Main *mainvar, outliner_free_tree(&space_outliner->tree); outliner_storage_cleanup(space_outliner); + outliner_tree_display_destroy(&space_outliner->runtime->tree_display); - /* options */ - if (space_outliner->outlinevis == SO_LIBRARIES) { - Library *lib; - - /* current file first - mainvar provides tselem with unique pointer - not used */ - ten = outliner_add_library_contents(mainvar, space_outliner, &space_outliner->tree, NULL); - if (ten) { - tselem = TREESTORE(ten); - if (!tselem->used) { - tselem->flag &= ~TSE_CLOSED; - } - } + space_outliner->runtime->tree_display = outliner_tree_display_create(space_outliner->outlinevis, + space_outliner); + if (space_outliner->runtime->tree_display) { + TreeSourceData source_data = {.bmain = mainvar, .scene = scene, .view_layer = view_layer}; + space_outliner->tree = outliner_tree_display_build_tree(space_outliner->runtime->tree_display, + &source_data); + } - for (lib = mainvar->libraries.first; lib; lib = lib->id.next) { - ten = outliner_add_library_contents(mainvar, space_outliner, &space_outliner->tree, lib); - /* NULL-check matters, due to filtering there may not be a new element. */ - if (ten) { - lib->id.newid = (ID *)ten; - } - } - /* make hierarchy */ - ten = space_outliner->tree.first; - if (ten != NULL) { - ten = ten->next; /* first one is main */ - while (ten) { - TreeElement *nten = ten->next, *par; - tselem = TREESTORE(ten); - lib = (Library *)tselem->id; - if (lib && lib->parent) { - par = (TreeElement *)lib->parent->id.newid; - if (tselem->id->tag & LIB_TAG_INDIRECT) { - /* Only remove from 'first level' if lib is not also directly used. */ - BLI_remlink(&space_outliner->tree, ten); - BLI_addtail(&par->subtree, ten); - ten->parent = par; - } - else { - /* Else, make a new copy of the libtree for our parent. */ - TreeElement *dupten = outliner_add_library_contents( - mainvar, space_outliner, &par->subtree, lib); - if (dupten) { - dupten->parent = par; - } - } - } - ten = nten; - } - } - /* restore newid pointers */ - for (lib = mainvar->libraries.first; lib; lib = lib->id.next) { - lib->id.newid = NULL; - } + if (space_outliner->runtime->tree_display) { + /* Skip if there's a tree-display that's responsible for adding all elements. */ + } + /* options */ + else if (space_outliner->outlinevis == SO_LIBRARIES) { + /* Ported to new tree-display, should be built there already. */ + BLI_assert(false); } else if (space_outliner->outlinevis == SO_SCENES) { Scene *sce; @@ -2612,38 +2291,8 @@ void outliner_build_tree(Main *mainvar, outliner_add_orphaned_datablocks(mainvar, space_outliner); } else if (space_outliner->outlinevis == SO_VIEW_LAYER) { - if (space_outliner->filter & SO_FILTER_NO_COLLECTION) { - /* Show objects in the view layer. */ - LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { - TreeElement *te_object = outliner_add_element( - space_outliner, &space_outliner->tree, base->object, NULL, 0, 0); - te_object->directdata = base; - } - - if ((space_outliner->filter & SO_FILTER_NO_CHILDREN) == 0) { - outliner_make_object_parent_hierarchy(&space_outliner->tree); - } - } - else { - /* Show collections in the view layer. */ - ten = outliner_add_element( - space_outliner, &space_outliner->tree, scene, NULL, TSE_VIEW_COLLECTION_BASE, 0); - ten->name = IFACE_("Scene Collection"); - TREESTORE(ten)->flag &= ~TSE_CLOSED; - - bool show_objects = !(space_outliner->filter & SO_FILTER_NO_OBJECT); - outliner_add_view_layer(space_outliner, &ten->subtree, ten, view_layer, show_objects); - - if ((space_outliner->filter & SO_FILTER_NO_CHILDREN) == 0) { - GHash *object_tree_elements_hash = BLI_ghash_new( - BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__); - outliner_object_tree_elements_lookup_create_recursive(object_tree_elements_hash, ten); - outliner_make_object_parent_hierarchy_collections(space_outliner, - object_tree_elements_hash); - outliner_object_tree_elements_lookup_free(object_tree_elements_hash); - BLI_ghash_free(object_tree_elements_hash, NULL, NULL); - } - } + /* Ported to new tree-display, should be built there already. */ + BLI_assert(false); } if ((space_outliner->flag & SO_SKIP_SORT_ALPHA) == 0) { |