Outliner performance: Only expand sub-trees if needed

Before this, we would build the sub-trees of some elements, just to
remove them afterwards. In big files, this would sometimes build ten
thousands of elements unnecessarily. Now support not building those
sub-trees in the first place.

Performance tests in a Sprite Fright production file (release build):
- View Layer display mode, reduced Outliner tree rebuilding from ~45ms
  to 12-17ms
- Library Overrides display mode, Hierarchies view, reduced tree
  rebuilding from 5-6s(!) to 220ms
This commit is contained in:
Julian Eisel 2022-06-13 15:38:03 +02:00
parent 988fc24930
commit afde12e066
4 changed files with 17 additions and 18 deletions

View File

@ -802,7 +802,8 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
void *idv,
TreeElement *parent,
short type,
short index)
short index,
const bool expand)
{
ID *id = reinterpret_cast<ID *>(idv);
@ -894,10 +895,10 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
te->idcode = GS(id->name);
}
if (te->abstract_element && te->abstract_element->isExpandValid()) {
if (expand && te->abstract_element && te->abstract_element->isExpandValid()) {
tree_element_expand(*te->abstract_element, *space_outliner);
}
else if (type == TSE_SOME_ID) {
else if (expand && (type == TSE_SOME_ID)) {
/* ID types not (fully) ported to new design yet. */
if (te->abstract_element->expandPoll(*space_outliner)) {
outliner_add_id_contents(space_outliner, te, tselem, id);

View File

@ -34,13 +34,6 @@ TreeDisplayOverrideLibraryHierarchies::TreeDisplayOverrideLibraryHierarchies(
{
}
/* XXX Remove expanded subtree, we add our own items here. Expanding should probably be
* optional. */
static void remove_expanded_children(TreeElement &te)
{
outliner_free_tree(&te.subtree);
}
ListBase TreeDisplayOverrideLibraryHierarchies::buildTree(const TreeSourceData &source_data)
{
ListBase tree = {nullptr};
@ -114,8 +107,7 @@ ListBase TreeDisplayOverrideLibraryHierarchies::build_hierarchy_for_lib_or_main(
});
TreeElement *new_id_te = outliner_add_element(
&space_outliner_, &new_base_te->subtree, iter_id, new_base_te, TSE_SOME_ID, 0);
remove_expanded_children(*new_id_te);
&space_outliner_, &new_base_te->subtree, iter_id, new_base_te, TSE_SOME_ID, 0, false);
build_hierarchy_for_ID(bmain, *iter_id, *tree_element_cast<TreeElementID>(new_id_te));
}
@ -193,8 +185,8 @@ static int build_hierarchy_foreach_ID_cb(LibraryIDLinkCallbackData *cb_data)
&id,
&build_data.parent_te->getLegacyElement(),
TSE_SOME_ID,
0);
remove_expanded_children(*new_te);
0,
false);
build_data.sibling_ids.add(&id);
BuildHierarchyForeachIDCbData child_build_data{build_data.bmain,

View File

@ -271,14 +271,14 @@ void ObjectsChildrenBuilder::make_object_parent_hierarchy_collections()
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. */
* We don't expand its sub-tree though, to make it less prominent. */
TreeElement *child_ob_tree_element = outliner_add_element(&outliner_,
&parent_ob_tree_element->subtree,
child,
parent_ob_tree_element,
TSE_SOME_ID,
0);
outliner_free_tree(&child_ob_tree_element->subtree);
0,
false);
child_ob_tree_element->flag |= TE_CHILD_NOT_IN_COLLECTION;
child_ob_tree_elements.append(child_ob_tree_element);
}

View File

@ -94,13 +94,19 @@ class AbstractTreeElement {
* \note "ID" is not always a real ID.
* \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().
*
* \param expand: If true, the element may add its own sub-tree. E.g. objects will list their
* animation data, object data, constraints, modifiers, ... This often adds visual
* noise, and can be expensive to add in big scenes. So prefer setting this to
* false.
*/
struct TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
ListBase *lb,
void *idv,
struct TreeElement *parent,
short type,
short index);
short index,
const bool expand = true);
void tree_element_expand(const AbstractTreeElement &tree_element, SpaceOutliner &space_outliner);