diff options
author | Julian Eisel <julian@blender.org> | 2022-01-26 13:44:58 +0300 |
---|---|---|
committer | Julian Eisel <julian@blender.org> | 2022-01-26 13:44:58 +0300 |
commit | 9bce134e56c28045aee37080f5c5b6622a07927b (patch) | |
tree | e91a6eae7f00d2f0bfb4753a33dcc285018faaf5 /source/blender/editors/space_outliner/tree | |
parent | 1bf6a880ab4fc1d0f1e6b2bb7cc0354b4e18f45b (diff) |
Outliner: Port RNA elements to new tree-element design
Continuation of work started in 2e221de4ceee and 249e4df110e0.
Adds new tree-element classes for RNA structs, properties and array
elements. This isn't exactly a copy and paste, even though logic should
effectively be the same. Further cleanups are included to share code in
a nice way, improve code with simple C++ features, etc.
Diffstat (limited to 'source/blender/editors/space_outliner/tree')
3 files changed, 334 insertions, 0 deletions
diff --git a/source/blender/editors/space_outliner/tree/tree_element.cc b/source/blender/editors/space_outliner/tree/tree_element.cc index ea78f70f86d..bed28e59f0b 100644 --- a/source/blender/editors/space_outliner/tree/tree_element.cc +++ b/source/blender/editors/space_outliner/tree/tree_element.cc @@ -33,6 +33,7 @@ #include "tree_element_id.hh" #include "tree_element_nla.hh" #include "tree_element_overrides.hh" +#include "tree_element_rna.hh" #include "tree_element_scene_objects.hh" #include "tree_element_view_layer.hh" @@ -86,6 +87,15 @@ std::unique_ptr<AbstractTreeElement> AbstractTreeElement::createFromType(const i case TSE_LIBRARY_OVERRIDE: return std::make_unique<TreeElementOverridesProperty>( legacy_te, *static_cast<TreeElementOverridesData *>(idv)); + case TSE_RNA_STRUCT: + return std::make_unique<TreeElementRNAStruct>(legacy_te, + *reinterpret_cast<PointerRNA *>(idv)); + case TSE_RNA_PROPERTY: + return std::make_unique<TreeElementRNAProperty>( + legacy_te, *reinterpret_cast<PointerRNA *>(idv), legacy_te.index); + case TSE_RNA_ARRAY_ELEM: + return std::make_unique<TreeElementRNAArrayElement>( + legacy_te, *reinterpret_cast<PointerRNA *>(idv), legacy_te.index); default: break; } diff --git a/source/blender/editors/space_outliner/tree/tree_element_rna.cc b/source/blender/editors/space_outliner/tree/tree_element_rna.cc new file mode 100644 index 00000000000..0152f59268d --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_element_rna.cc @@ -0,0 +1,249 @@ +/* + * 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 <climits> +#include <iostream> + +#include "BLI_listbase.h" +#include "BLI_string.h" + +#include "BLT_translation.h" + +#include "DNA_outliner_types.h" +#include "DNA_space_types.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_access.h" + +#include "../outliner_intern.hh" + +#include "tree_element_rna.hh" + +namespace blender::ed::outliner { + +/* Don't display arrays larger, weak but index is stored as a short, + * also the outliner isn't intended for editing such large data-sets. */ +BLI_STATIC_ASSERT(sizeof(TreeElement::index) == 2, "Index is no longer short!") + +/* -------------------------------------------------------------------- */ +/* Common functionality (#TreeElementRNACommon Base Class) */ + +TreeElementRNACommon::TreeElementRNACommon(TreeElement &legacy_te, PointerRNA &rna_ptr) + : AbstractTreeElement(legacy_te), rna_ptr_(rna_ptr) +{ + /* Create an empty tree-element. */ + if (!isRNAValid()) { + legacy_te_.name = IFACE_("(empty)"); + return; + } + + legacy_te_.rnaptr = rna_ptr; +} + +bool TreeElementRNACommon::isExpandValid() const +{ + return true; +} + +bool TreeElementRNACommon::isRNAValid() const +{ + return rna_ptr_.data != nullptr; +} + +bool TreeElementRNACommon::expandPoll(const SpaceOutliner &) const +{ + return isRNAValid(); +} + +/* -------------------------------------------------------------------- */ +/* RNA Struct */ + +TreeElementRNAStruct::TreeElementRNAStruct(TreeElement &legacy_te, PointerRNA &rna_ptr) + : TreeElementRNACommon(legacy_te, rna_ptr) +{ + if (!isRNAValid()) { + return; + } + + legacy_te_.name = RNA_struct_name_get_alloc(&rna_ptr, nullptr, 0, nullptr); + if (legacy_te_.name) { + legacy_te_.flag |= TE_FREE_NAME; + } + else { + legacy_te_.name = RNA_struct_ui_name(rna_ptr.type); + } +} + +void TreeElementRNAStruct::expand(SpaceOutliner &space_outliner) const +{ + TreeStoreElem &tselem = *TREESTORE(&legacy_te_); + PointerRNA *ptr = &legacy_te_.rnaptr; + + /* If searching don't expand RNA entries */ + if (SEARCHING_OUTLINER(&space_outliner) && BLI_strcasecmp("RNA", legacy_te_.name) == 0) { + tselem.flag &= ~TSE_CHILDSEARCH; + } + + PropertyRNA *iterprop = RNA_struct_iterator_property(ptr->type); + int tot = RNA_property_collection_length(ptr, iterprop); + CLAMP_MAX(tot, max_index); + + /* auto open these cases */ + if (!legacy_te_.parent || + (RNA_property_type(reinterpret_cast<PropertyRNA *>(legacy_te_.parent->directdata))) == + PROP_POINTER) { + if (!tselem.used) { + tselem.flag &= ~TSE_CLOSED; + } + } + + if (TSELEM_OPEN(&tselem, &space_outliner)) { + for (int index = 0; index < tot; index++) { + PointerRNA propptr; + RNA_property_collection_lookup_int(ptr, iterprop, index, &propptr); + if (!(RNA_property_flag(reinterpret_cast<PropertyRNA *>(propptr.data)) & PROP_HIDDEN)) { + outliner_add_element(&space_outliner, + &legacy_te_.subtree, + (void *)ptr, + &legacy_te_, + TSE_RNA_PROPERTY, + index); + } + } + } + else if (tot) { + legacy_te_.flag |= TE_LAZY_CLOSED; + } +} + +/* -------------------------------------------------------------------- */ +/* RNA Property */ + +TreeElementRNAProperty::TreeElementRNAProperty(TreeElement &legacy_te, + PointerRNA &rna_ptr, + const int index) + : TreeElementRNACommon(legacy_te, rna_ptr) +{ + if (!isRNAValid()) { + return; + } + + PointerRNA propptr; + PropertyRNA *iterprop = RNA_struct_iterator_property(rna_ptr.type); + RNA_property_collection_lookup_int(&rna_ptr, iterprop, index, &propptr); + + PropertyRNA *prop = reinterpret_cast<PropertyRNA *>(propptr.data); + + legacy_te_.name = RNA_property_ui_name(prop); + legacy_te_.directdata = prop; + rna_prop_ = prop; +} + +void TreeElementRNAProperty::expand(SpaceOutliner &space_outliner) const +{ + TreeStoreElem &tselem = *TREESTORE(&legacy_te_); + PointerRNA rna_ptr = rna_ptr_; + PropertyType proptype = RNA_property_type(rna_prop_); + + /* If searching don't expand RNA entries */ + if (SEARCHING_OUTLINER(&space_outliner) && BLI_strcasecmp("RNA", legacy_te_.name) == 0) { + tselem.flag &= ~TSE_CHILDSEARCH; + } + + if (proptype == PROP_POINTER) { + PointerRNA pptr = RNA_property_pointer_get(&rna_ptr, rna_prop_); + + if (pptr.data) { + if (TSELEM_OPEN(&tselem, &space_outliner)) { + outliner_add_element( + &space_outliner, &legacy_te_.subtree, (void *)&pptr, &legacy_te_, TSE_RNA_STRUCT, -1); + } + else { + legacy_te_.flag |= TE_LAZY_CLOSED; + } + } + } + else if (proptype == PROP_COLLECTION) { + int tot = RNA_property_collection_length(&rna_ptr, rna_prop_); + CLAMP_MAX(tot, max_index); + + if (TSELEM_OPEN(&tselem, &space_outliner)) { + for (int index = 0; index < tot; index++) { + PointerRNA pptr; + RNA_property_collection_lookup_int(&rna_ptr, rna_prop_, index, &pptr); + outliner_add_element(&space_outliner, + &legacy_te_.subtree, + (void *)&pptr, + &legacy_te_, + TSE_RNA_STRUCT, + index); + } + } + else if (tot) { + legacy_te_.flag |= TE_LAZY_CLOSED; + } + } + else if (ELEM(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) { + int tot = RNA_property_array_length(&rna_ptr, rna_prop_); + CLAMP_MAX(tot, max_index); + + if (TSELEM_OPEN(&tselem, &space_outliner)) { + for (int index = 0; index < tot; index++) { + outliner_add_element(&space_outliner, + &legacy_te_.subtree, + &rna_ptr, + &legacy_te_, + TSE_RNA_ARRAY_ELEM, + index); + } + } + else if (tot) { + legacy_te_.flag |= TE_LAZY_CLOSED; + } + } +} + +/* -------------------------------------------------------------------- */ +/* RNA Array Element */ + +TreeElementRNAArrayElement::TreeElementRNAArrayElement(TreeElement &legacy_te, + PointerRNA &rna_ptr, + const int index) + : TreeElementRNACommon(legacy_te, rna_ptr) +{ + PropertyRNA *prop = reinterpret_cast<PropertyRNA *>(legacy_te_.parent->directdata); + legacy_te_.directdata = prop; + legacy_te_.index = index; + + char c = RNA_property_array_item_char(prop, index); + + legacy_te_.name = reinterpret_cast<char *>( + MEM_callocN(sizeof(char[20]), "OutlinerRNAArrayName")); + if (c) { + sprintf((char *)legacy_te_.name, " %c", c); + } + else { + sprintf((char *)legacy_te_.name, " %d", index + 1); + } + legacy_te_.flag |= TE_FREE_NAME; +} + +} // namespace blender::ed::outliner diff --git a/source/blender/editors/space_outliner/tree/tree_element_rna.hh b/source/blender/editors/space_outliner/tree/tree_element_rna.hh new file mode 100644 index 00000000000..352b8763acb --- /dev/null +++ b/source/blender/editors/space_outliner/tree/tree_element_rna.hh @@ -0,0 +1,75 @@ +/* + * 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 + */ + +#pragma once + +#include <limits> + +#include "RNA_types.h" + +#include "tree_element.hh" + +struct PointerRNA; + +namespace blender::ed::outliner { + +/** + * Base class for common behavior of RNA tree elements. + */ +class TreeElementRNACommon : public AbstractTreeElement { + protected: + constexpr static int max_index = std::numeric_limits<short>::max(); + PointerRNA rna_ptr_; + + public: + TreeElementRNACommon(TreeElement &legacy_te, PointerRNA &rna_ptr); + bool isExpandValid() const override; + bool expandPoll(const SpaceOutliner &) const override; + + bool isRNAValid() const; +}; + +/* -------------------------------------------------------------------- */ + +class TreeElementRNAStruct : public TreeElementRNACommon { + public: + TreeElementRNAStruct(TreeElement &legacy_te, PointerRNA &rna_ptr); + void expand(SpaceOutliner &space_outliner) const override; +}; + +/* -------------------------------------------------------------------- */ + +class TreeElementRNAProperty : public TreeElementRNACommon { + private: + PropertyRNA *rna_prop_ = nullptr; + + public: + TreeElementRNAProperty(TreeElement &legacy_te, PointerRNA &rna_ptr, int index); + void expand(SpaceOutliner &space_outliner) const override; +}; + +/* -------------------------------------------------------------------- */ + +class TreeElementRNAArrayElement : public TreeElementRNACommon { + public: + TreeElementRNAArrayElement(TreeElement &legacy_te, PointerRNA &rna_ptr, int index); +}; + +} // namespace blender::ed::outliner |