diff options
Diffstat (limited to 'source/blender/editors/space_outliner/outliner_tree.c')
-rw-r--r-- | source/blender/editors/space_outliner/outliner_tree.c | 324 |
1 files changed, 40 insertions, 284 deletions
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 159511546be..7308b161d18 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -80,12 +80,11 @@ #include "RNA_access.h" -#include "SEQ_sequencer.h" - #include "UI_interface.h" #include "outliner_intern.h" #include "tree/tree_display.h" +#include "tree/tree_element.h" #ifdef WIN32 # include "BLI_math_base.h" /* M_PI */ @@ -132,9 +131,9 @@ static void outliner_storage_cleanup(SpaceOutliner *space_outliner) if (BLI_mempool_len(ts) == unused) { BLI_mempool_destroy(ts); space_outliner->treestore = NULL; - if (space_outliner->treehash) { - BKE_outliner_treehash_free(space_outliner->treehash); - space_outliner->treehash = NULL; + if (space_outliner->runtime->treehash) { + BKE_outliner_treehash_free(space_outliner->runtime->treehash); + space_outliner->runtime->treehash = NULL; } } else { @@ -150,16 +149,16 @@ static void outliner_storage_cleanup(SpaceOutliner *space_outliner) } BLI_mempool_destroy(ts); space_outliner->treestore = new_ts; - if (space_outliner->treehash) { + if (space_outliner->runtime->treehash) { /* update hash table to fix broken pointers */ - BKE_outliner_treehash_rebuild_from_treestore(space_outliner->treehash, + BKE_outliner_treehash_rebuild_from_treestore(space_outliner->runtime->treehash, space_outliner->treestore); } } } } - else if (space_outliner->treehash) { - BKE_outliner_treehash_clear_used(space_outliner->treehash); + else if (space_outliner->runtime->treehash) { + BKE_outliner_treehash_clear_used(space_outliner->runtime->treehash); } } } @@ -174,14 +173,14 @@ static void check_persistent( space_outliner->treestore = BLI_mempool_create( sizeof(TreeStoreElem), 1, 512, BLI_MEMPOOL_ALLOW_ITER); } - if (space_outliner->treehash == NULL) { - space_outliner->treehash = BKE_outliner_treehash_create_from_treestore( + if (space_outliner->runtime->treehash == NULL) { + space_outliner->runtime->treehash = BKE_outliner_treehash_create_from_treestore( space_outliner->treestore); } /* find any unused tree element in treestore and mark it as used * (note that there may be multiple unused elements in case of linked objects) */ - tselem = BKE_outliner_treehash_lookup_unused(space_outliner->treehash, type, nr, id); + tselem = BKE_outliner_treehash_lookup_unused(space_outliner->runtime->treehash, type, nr, id); if (tselem) { te->store_elem = tselem; tselem->used = 1; @@ -196,7 +195,7 @@ static void check_persistent( tselem->used = 0; tselem->flag = TSE_CLOSED; te->store_elem = tselem; - BKE_outliner_treehash_add_element(space_outliner->treehash, tselem); + BKE_outliner_treehash_add_element(space_outliner->runtime->treehash, tselem); } /* ********************************************************* */ @@ -232,6 +231,7 @@ void outliner_free_tree_element(TreeElement *element, ListBase *parent_subtree) if (element->flag & TE_FREE_NAME) { MEM_freeN((void *)element->name); } + outliner_tree_element_type_free(&element->type); MEM_freeN(element); } @@ -961,13 +961,18 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, te->parent = parent; te->index = index; /* For data arrays. */ + + /* New C++ based type handle (`TreeElementType` in C, `AbstractTreeElement` in C++). Only some + * support this, eventually this should replace `TreeElement` entirely. */ + te->type = outliner_tree_element_type_create(type, te, idv); + if (ELEM(type, TSE_SEQUENCE, TSE_SEQ_STRIP, TSE_SEQUENCE_DUP)) { /* pass */ } else if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) { /* pass */ } - else if (type == TSE_ANIM_DATA) { + else if (ELEM(type, TSE_ANIM_DATA, TSE_NLA, TSE_NLA_TRACK, TSE_DRIVER_BASE)) { /* pass */ } else if (type == TSE_GP_LAYER) { @@ -979,7 +984,13 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, else if (type == TSE_ID_BASE) { /* pass */ } + else if (ELEM(type, TSE_KEYMAP, TSE_KEYMAP_ITEM)) { + /* pass */ + } else { + /* Other cases must be caught above. */ + BLI_assert(TSE_IS_REAL_ID(tselem)); + /* do here too, for blend file viewer, own ID_LI then shows file name */ if (GS(id->name) == ID_LI) { te->name = ((Library *)id)->filepath; @@ -990,7 +1001,10 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, te->idcode = GS(id->name); } - if (type == 0) { + if (te->type) { + outliner_tree_element_type_expand(te->type, space_outliner); + } + else if (type == 0) { TreeStoreElem *tsepar = parent ? TREESTORE(parent) : NULL; /* ID data-block. */ @@ -998,73 +1012,9 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, outliner_add_id_contents(space_outliner, te, tselem, id); } } - else if (type == TSE_ANIM_DATA) { - IdAdtTemplate *iat = (IdAdtTemplate *)idv; - AnimData *adt = (AnimData *)iat->adt; - - /* this element's info */ - te->name = IFACE_("Animation"); - te->directdata = adt; - - /* Action */ - outliner_add_element(space_outliner, &te->subtree, adt->action, te, 0, 0); - - /* Drivers */ - if (adt->drivers.first) { - TreeElement *ted = outliner_add_element( - space_outliner, &te->subtree, adt, te, TSE_DRIVER_BASE, 0); - ID *lastadded = NULL; - FCurve *fcu; - - ted->name = IFACE_("Drivers"); - - for (fcu = adt->drivers.first; fcu; fcu = fcu->next) { - if (fcu->driver && fcu->driver->variables.first) { - ChannelDriver *driver = fcu->driver; - DriverVar *dvar; - - for (dvar = driver->variables.first; dvar; dvar = dvar->next) { - /* loop over all targets used here */ - DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { - if (lastadded != dtar->id) { - /* XXX this lastadded check is rather lame, and also fails quite badly... */ - outliner_add_element( - space_outliner, &ted->subtree, dtar->id, ted, TSE_LINKED_OB, 0); - lastadded = dtar->id; - } - } - DRIVER_TARGETS_LOOPER_END; - } - } - } - } - - /* NLA Data */ - if (adt->nla_tracks.first) { - TreeElement *tenla = outliner_add_element(space_outliner, &te->subtree, adt, te, TSE_NLA, 0); - NlaTrack *nlt; - int a = 0; - - tenla->name = IFACE_("NLA Tracks"); - - for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { - TreeElement *tenlt = outliner_add_element( - space_outliner, &tenla->subtree, nlt, tenla, TSE_NLA_TRACK, a); - NlaStrip *strip; - TreeElement *ten; - int b = 0; - - tenlt->name = nlt->name; - - for (strip = nlt->strips.first; strip; strip = strip->next, b++) { - ten = outliner_add_element( - space_outliner, &tenlt->subtree, strip->act, tenlt, TSE_NLA_ACTION, b); - if (ten) { - ten->directdata = strip; - } - } - } - } + else if (ELEM(type, TSE_ANIM_DATA, TSE_DRIVER_BASE, TSE_NLA, TSE_NLA_ACTION, TSE_NLA_TRACK)) { + /* Should already use new AbstractTreeElement design. */ + BLI_assert(0); } else if (type == TSE_GP_LAYER) { bGPDlayer *gpl = (bGPDlayer *)idv; @@ -1314,125 +1264,6 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, } /* ======================================================= */ -/* Sequencer mode tree building */ - -/* Helped function to put duplicate sequence in the same tree. */ -static int need_add_seq_dup(Sequence *seq) -{ - Sequence *p; - - if ((!seq->strip) || (!seq->strip->stripdata)) { - return 1; - } - - /* - * First check backward, if we found a duplicate - * sequence before this, don't need it, just return. - */ - p = seq->prev; - while (p) { - if ((!p->strip) || (!p->strip->stripdata)) { - p = p->prev; - continue; - } - - if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) { - return 2; - } - p = p->prev; - } - - p = seq->next; - while (p) { - if ((!p->strip) || (!p->strip->stripdata)) { - p = p->next; - continue; - } - - if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) { - return 0; - } - p = p->next; - } - return 1; -} - -static void outliner_add_seq_dup(SpaceOutliner *space_outliner, - Sequence *seq, - TreeElement *te, - short index) -{ - /* TreeElement *ch; */ /* UNUSED */ - Sequence *p; - - p = seq; - while (p) { - if ((!p->strip) || (!p->strip->stripdata) || (p->strip->stripdata->name[0] == '\0')) { - p = p->next; - continue; - } - - if (STREQ(p->strip->stripdata->name, seq->strip->stripdata->name)) { - /* ch = */ /* UNUSED */ outliner_add_element( - space_outliner, &te->subtree, (void *)p, te, TSE_SEQUENCE, index); - } - p = p->next; - } -} - -/* ----------------------------------------------- */ - -static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOutliner *space_outliner) -{ - TreeElement *ten; - 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; - - /* check if there are any data-blocks of this type which are orphans */ - for (; id; id = id->next) { - if (ID_REAL_USERS(id) <= 0) { - break; - } - } - - if (id) { - /* header for this type of data-block */ - if (filter_id_type) { - ten = NULL; - } - else { - ten = outliner_add_element( - space_outliner, &space_outliner->tree, lbarray[a], NULL, TSE_ID_BASE, 0); - ten->directdata = lbarray[a]; - ten->name = outliner_idcode_to_plural(GS(id->name)); - } - - /* add the orphaned data-blocks - these will not be added with any subtrees attached */ - for (id = lbarray[a]->first; id; id = id->next) { - if (ID_REAL_USERS(id) <= 0) { - outliner_add_element( - space_outliner, (ten) ? &ten->subtree : &space_outliner->tree, id, ten, 0, 0); - } - } - } - } - } -} BLI_INLINE void outliner_add_collection_init(TreeElement *te, Collection *collection) { @@ -2175,18 +2006,12 @@ static void outliner_filter_tree(SpaceOutliner *space_outliner, ViewLayer *view_ /* Main Tree Building API */ /* Main entry point for building the tree data-structure that the outliner represents. */ -/* TODO: split each mode into its own function? */ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, SpaceOutliner *space_outliner, ARegion *region) { - TreeElement *te = NULL, *ten; - TreeStoreElem *tselem; - /* on first view, we open scenes */ - int show_opened = !space_outliner->treestore || !BLI_mempool_len(space_outliner->treestore); - /* Are we looking for something - we want to tag parents to filter child matches * - NOT in data-blocks view - searching all data-blocks takes way too long to be useful * - this variable is only set once per tree build */ @@ -2197,12 +2022,12 @@ void outliner_build_tree(Main *mainvar, space_outliner->search_flags &= ~SO_SEARCH_RECURSIVE; } - if (space_outliner->treehash && (space_outliner->storeflag & SO_TREESTORE_REBUILD) && + if (space_outliner->runtime->treehash && (space_outliner->storeflag & SO_TREESTORE_REBUILD) && space_outliner->treestore) { - space_outliner->storeflag &= ~SO_TREESTORE_REBUILD; - BKE_outliner_treehash_rebuild_from_treestore(space_outliner->treehash, + BKE_outliner_treehash_rebuild_from_treestore(space_outliner->runtime->treehash, space_outliner->treestore); } + space_outliner->storeflag &= ~SO_TREESTORE_REBUILD; if (region->do_draw & RGN_DRAW_NO_REBUILD) { return; @@ -2217,82 +2042,13 @@ void outliner_build_tree(Main *mainvar, 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); - } - 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; - for (sce = mainvar->scenes.first; sce; sce = sce->id.next) { - te = outliner_add_element(space_outliner, &space_outliner->tree, sce, NULL, 0, 0); - tselem = TREESTORE(te); - - /* New scene elements open by default */ - if ((sce == scene && show_opened) || !tselem->used) { - tselem->flag &= ~TSE_CLOSED; - } - - outliner_make_object_parent_hierarchy(&te->subtree); - } - } - else if (space_outliner->outlinevis == SO_SEQUENCE) { - Sequence *seq; - Editing *ed = BKE_sequencer_editing_get(scene, false); - int op; - - if (ed == NULL) { - return; - } - - seq = ed->seqbasep->first; - if (!seq) { - return; - } - - while (seq) { - op = need_add_seq_dup(seq); - if (op == 1) { - /* ten = */ outliner_add_element( - space_outliner, &space_outliner->tree, (void *)seq, NULL, TSE_SEQUENCE, 0); - } - else if (op == 0) { - ten = outliner_add_element( - space_outliner, &space_outliner->tree, (void *)seq, NULL, TSE_SEQUENCE_DUP, 0); - outliner_add_seq_dup(space_outliner, seq, ten, 0); - } - seq = seq->next; - } - } - else if (space_outliner->outlinevis == SO_DATA_API) { - PointerRNA mainptr; + /* All tree displays should be created as sub-classes of AbstractTreeDisplay. */ + BLI_assert(space_outliner->runtime->tree_display != NULL); - RNA_main_pointer_create(mainvar, &mainptr); - - ten = outliner_add_element( - space_outliner, &space_outliner->tree, (void *)&mainptr, NULL, TSE_RNA_STRUCT, -1); - - if (show_opened) { - tselem = TREESTORE(ten); - tselem->flag &= ~TSE_CLOSED; - } - } - else if (space_outliner->outlinevis == SO_ID_ORPHANS) { - outliner_add_orphaned_datablocks(mainvar, space_outliner); - } - else if (space_outliner->outlinevis == SO_VIEW_LAYER) { - /* Ported to new tree-display, should be built there already. */ - BLI_assert(false); - } + 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); if ((space_outliner->flag & SO_SKIP_SORT_ALPHA) == 0) { outliner_sort(&space_outliner->tree); |