diff options
Diffstat (limited to 'source/blender/editors/space_outliner/tree')
5 files changed, 259 insertions, 8 deletions
diff --git a/source/blender/editors/space_outliner/tree/tree_display.cc b/source/blender/editors/space_outliner/tree/tree_display.cc index 4395383e838..003afd5bdec 100644 --- a/source/blender/editors/space_outliner/tree/tree_display.cc +++ b/source/blender/editors/space_outliner/tree/tree_display.cc @@ -44,6 +44,9 @@ TreeDisplay *outliner_tree_display_create(eSpaceOutliner_Mode mode, SpaceOutline case SO_ID_ORPHANS: tree_display = new TreeDisplayIDOrphans(*space_outliner); break; + case SO_OVERRIDES_LIBRARY: + tree_display = new TreeDisplayOverrideLibrary(*space_outliner); + break; case SO_VIEW_LAYER: default: tree_display = new TreeDisplayViewLayer(*space_outliner); diff --git a/source/blender/editors/space_outliner/tree/tree_display.hh b/source/blender/editors/space_outliner/tree/tree_display.hh index b6183050e82..f089a149805 100644 --- a/source/blender/editors/space_outliner/tree/tree_display.hh +++ b/source/blender/editors/space_outliner/tree/tree_display.hh @@ -111,6 +111,24 @@ class TreeDisplayLibraries final : public AbstractTreeDisplay { }; /* -------------------------------------------------------------------- */ +/* Library Overrides Tree-Display. */ + +/** + * \brief Tree-Display for the Library Overrides display mode. + */ +class TreeDisplayOverrideLibrary final : public AbstractTreeDisplay { + public: + TreeDisplayOverrideLibrary(SpaceOutliner &space_outliner); + + ListBase buildTree(const TreeSourceData &source_data) override; + + private: + TreeElement *add_library_contents(Main &, ListBase &, Library *) const; + bool override_library_id_filter_poll(Library *lib, ID *id) const; + short id_filter_get() const; +}; + +/* -------------------------------------------------------------------- */ /* Video Sequencer Tree-Display */ enum SequenceAddOp { diff --git a/source/blender/editors/space_outliner/tree/tree_display_override_library.cc b/source/blender/editors/space_outliner/tree/tree_display_override_library.cc new file mode 100644 index 00000000000..3059f8bfe0c --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_display_override_library.cc @@ -0,0 +1,204 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup spoutliner + */ + +#include "BLI_listbase.h" +#include "BLI_listbase_wrapper.hh" + +#include "BKE_collection.h" +#include "BKE_main.h" + +#include "DNA_collection_types.h" + +#include "BLT_translation.h" + +#include "../outliner_intern.h" +#include "tree_display.hh" + +namespace blender::ed::outliner { + +/* Convenience/readability. */ +template<typename T> using List = ListBaseWrapper<T>; + +TreeDisplayOverrideLibrary::TreeDisplayOverrideLibrary(SpaceOutliner &space_outliner) + : AbstractTreeDisplay(space_outliner) +{ +} + +ListBase TreeDisplayOverrideLibrary::buildTree(const TreeSourceData &source_data) +{ + ListBase tree = {nullptr}; + + { + /* current file first - mainvar provides tselem with unique pointer - not used */ + TreeElement *ten = add_library_contents(*source_data.bmain, tree, nullptr); + TreeStoreElem *tselem; + + if (ten) { + tselem = TREESTORE(ten); + if (!tselem->used) { + tselem->flag &= ~TSE_CLOSED; + } + } + } + + for (ID *id : List<ID>(source_data.bmain->libraries)) { + Library *lib = reinterpret_cast<Library *>(id); + TreeElement *ten = add_library_contents(*source_data.bmain, tree, lib); + /* NULL-check matters, due to filtering there may not be a new element. */ + if (ten) { + lib->id.newid = (ID *)ten; + } + } + + /* make hierarchy */ + for (TreeElement *ten : List<TreeElement>(tree)) { + if (ten == tree.first) { + /* First item is main, skip. */ + continue; + } + + TreeStoreElem *tselem = TREESTORE(ten); + Library *lib = (Library *)tselem->id; + BLI_assert(!lib || (GS(lib->id.name) == ID_LI)); + if (!lib || !lib->parent) { + continue; + } + + TreeElement *parent = (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(&tree, ten); + BLI_addtail(&parent->subtree, ten); + ten->parent = parent; + } + else { + /* Else, make a new copy of the libtree for our parent. */ + TreeElement *dupten = add_library_contents(*source_data.bmain, parent->subtree, lib); + if (dupten) { + dupten->parent = parent; + } + } + } + /* restore newid pointers */ + for (ID *library_id : List<ID>(source_data.bmain->libraries)) { + library_id->newid = nullptr; + } + + return tree; +} + +TreeElement *TreeDisplayOverrideLibrary::add_library_contents(Main &mainvar, + ListBase &lb, + Library *lib) const +{ + const short filter_id_type = id_filter_get(); + + ListBase *lbarray[INDEX_ID_MAX]; + int tot; + if (filter_id_type) { + lbarray[0] = which_libbase(&mainvar, space_outliner_.filter_id_type); + tot = 1; + } + else { + tot = set_listbasepointers(&mainvar, lbarray); + } + + TreeElement *tenlib = nullptr; + for (int a = 0; a < tot; a++) { + if (!lbarray[a] || !lbarray[a]->first) { + continue; + } + + ID *id = nullptr; + + /* check if there's data in current lib */ + for (ID *id_iter : List<ID>(lbarray[a])) { + if (id_iter->lib == lib && ID_IS_OVERRIDE_LIBRARY_REAL(id_iter)) { + id = id_iter; + break; + } + } + + if (id != nullptr) { + 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, nullptr, TSE_SOME_ID, 0); + } + else { + tenlib = outliner_add_element(&space_outliner_, &lb, &mainvar, nullptr, TSE_ID_BASE, 0); + tenlib->name = IFACE_("Current File"); + } + } + + /* Create data-block list parent element on demand. */ + if (id != nullptr) { + TreeElement *ten; + + if (filter_id_type) { + ten = tenlib; + } + else { + ten = outliner_add_element( + &space_outliner_, &tenlib->subtree, lbarray[a], nullptr, TSE_ID_BASE, 0); + ten->directdata = lbarray[a]; + ten->name = outliner_idcode_to_plural(GS(id->name)); + } + + for (ID *id : List<ID>(lbarray[a])) { + if (override_library_id_filter_poll(lib, id)) { + TreeElement *override_tree_element = outliner_add_element( + &space_outliner_, &ten->subtree, id, ten, TSE_LIBRARY_OVERRIDE_BASE, 0); + + if (BLI_listbase_is_empty(&override_tree_element->subtree)) { + outliner_free_tree_element(override_tree_element, &ten->subtree); + } + } + } + } + } + } + + return tenlib; +} + +short TreeDisplayOverrideLibrary::id_filter_get() const +{ + if (space_outliner_.filter & SO_FILTER_ID_TYPE) { + return space_outliner_.filter_id_type; + } + return 0; +} + +bool TreeDisplayOverrideLibrary::override_library_id_filter_poll(Library *lib, ID *id) const +{ + if (id->lib != lib) { + return false; + } + + if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { + return false; + } + + return true; +} + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_element_overrides.cc b/source/blender/editors/space_outliner/tree/tree_element_overrides.cc index 6b222e877b1..3c561702a43 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_overrides.cc +++ b/source/blender/editors/space_outliner/tree/tree_element_overrides.cc @@ -40,13 +40,24 @@ TreeElementOverridesBase::TreeElementOverridesBase(TreeElement &legacy_te, ID &i : AbstractTreeElement(legacy_te), id_(id) { BLI_assert(legacy_te.store_elem->type == TSE_LIBRARY_OVERRIDE_BASE); - legacy_te.name = IFACE_("Library Overrides"); + if (legacy_te.parent != nullptr && + ELEM(legacy_te.parent->store_elem->type, TSE_SOME_ID, TSE_LAYER_COLLECTION)) + + { + legacy_te.name = IFACE_("Library Overrides"); + } + else { + legacy_te.name = id.name + 2; + } } void TreeElementOverridesBase::expand(SpaceOutliner &space_outliner) const { BLI_assert(id_.override_library != nullptr); + const bool show_system_overrides = (SUPPORT_FILTER_OUTLINER(&space_outliner) && + (space_outliner.filter & SO_FILTER_SHOW_SYSTEM_OVERRIDES) != + 0); PointerRNA idpoin; RNA_id_pointer_create(&id_, &idpoin); @@ -56,15 +67,26 @@ void TreeElementOverridesBase::expand(SpaceOutliner &space_outliner) const for (auto *override_prop : ListBaseWrapper<IDOverrideLibraryProperty>(id_.override_library->properties)) { - if (!BKE_lib_override_rna_property_find( - &idpoin, override_prop, &override_rna_ptr, &override_rna_prop)) { - /* This is fine, override properties list is not always fully up-to-date with current - * RNA/IDProps etc., this gets cleaned up when re-generating the overrides rules, - * no error here. */ - continue; + const bool is_rna_path_valid = BKE_lib_override_rna_property_find( + &idpoin, override_prop, &override_rna_ptr, &override_rna_prop); + if (is_rna_path_valid && !show_system_overrides && + ELEM(override_prop->rna_prop_type, PROP_POINTER, PROP_COLLECTION) && + RNA_struct_is_ID(RNA_property_pointer_type(&override_rna_ptr, override_rna_prop))) { + bool do_continue = true; + for (auto *override_prop_op : + ListBaseWrapper<IDOverrideLibraryPropertyOperation>(override_prop->operations)) { + if ((override_prop_op->flag & IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE) == 0) { + do_continue = false; + break; + } + } + + if (do_continue) { + continue; + } } - TreeElementOverridesData data = {id_, *override_prop}; + TreeElementOverridesData data = {id_, *override_prop, is_rna_path_valid}; outliner_add_element( &space_outliner, &legacy_te_.subtree, &data, &legacy_te_, TSE_LIBRARY_OVERRIDE, index++); } @@ -79,6 +101,9 @@ TreeElementOverridesProperty::TreeElementOverridesProperty(TreeElement &legacy_t BLI_assert(legacy_te.store_elem->type == TSE_LIBRARY_OVERRIDE); legacy_te.name = override_prop_.rna_path; + /* Abusing this for now, better way to do it is also pending current refacor of the whole tree + * code to use CPP... */ + legacy_te.directdata = POINTER_FROM_UINT(override_data.is_rna_path_valid); } } // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_element_overrides.hh b/source/blender/editors/space_outliner/tree/tree_element_overrides.hh index b5c772f5b33..c3caab8e268 100644 --- a/source/blender/editors/space_outliner/tree/tree_element_overrides.hh +++ b/source/blender/editors/space_outliner/tree/tree_element_overrides.hh @@ -27,6 +27,7 @@ namespace blender::ed::outliner { struct TreeElementOverridesData { ID &id; IDOverrideLibraryProperty &override_property; + bool is_rna_path_valid; }; class TreeElementOverridesBase final : public AbstractTreeElement { |