From 9bce134e56c28045aee37080f5c5b6622a07927b Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 26 Jan 2022 11:44:58 +0100 Subject: 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. --- .../blender/editors/space_outliner/CMakeLists.txt | 2 + .../editors/space_outliner/outliner_intern.hh | 2 +- .../editors/space_outliner/outliner_tree.cc | 138 ------------ .../editors/space_outliner/tree/tree_element.cc | 10 + .../space_outliner/tree/tree_element_rna.cc | 249 +++++++++++++++++++++ .../space_outliner/tree/tree_element_rna.hh | 75 +++++++ 6 files changed, 337 insertions(+), 139 deletions(-) create mode 100644 source/blender/editors/space_outliner/tree/tree_element_rna.cc create mode 100644 source/blender/editors/space_outliner/tree/tree_element_rna.hh (limited to 'source/blender') diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt index cac9d4131f8..60b881fb32b 100644 --- a/source/blender/editors/space_outliner/CMakeLists.txt +++ b/source/blender/editors/space_outliner/CMakeLists.txt @@ -65,6 +65,7 @@ set(SRC tree/tree_element_id_scene.cc tree/tree_element_nla.cc tree/tree_element_overrides.cc + tree/tree_element_rna.cc tree/tree_element_scene_objects.cc tree/tree_element_view_layer.cc @@ -81,6 +82,7 @@ set(SRC tree/tree_element_id_scene.hh tree/tree_element_nla.hh tree/tree_element_overrides.hh + tree/tree_element_rna.hh tree/tree_element_scene_objects.hh tree/tree_element_view_layer.hh ) diff --git a/source/blender/editors/space_outliner/outliner_intern.hh b/source/blender/editors/space_outliner/outliner_intern.hh index 9065f7f9cc1..a62d35131ca 100644 --- a/source/blender/editors/space_outliner/outliner_intern.hh +++ b/source/blender/editors/space_outliner/outliner_intern.hh @@ -225,7 +225,7 @@ typedef enum { * - not searching into RNA items helps but isn't the complete solution */ -#define SEARCHING_OUTLINER(sov) (sov->search_flags & SO_SEARCH_RECURSIVE) +#define SEARCHING_OUTLINER(sov) ((sov)->search_flags & SO_SEARCH_RECURSIVE) /* is the current element open? if so we also show children */ #define TSELEM_OPEN(telm, sv) \ diff --git a/source/blender/editors/space_outliner/outliner_tree.cc b/source/blender/editors/space_outliner/outliner_tree.cc index 3454a27ce13..be792be95a9 100644 --- a/source/blender/editors/space_outliner/outliner_tree.cc +++ b/source/blender/editors/space_outliner/outliner_tree.cc @@ -977,144 +977,6 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner, te->directdata = seq; te->name = seq->strip->stripdata->name; } - else if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) { - PointerRNA *ptr = (PointerRNA *)idv; - - /* 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(te->index) == 2, "Index is no longer short!") - const int tot_limit = SHRT_MAX; - - /* we do lazy build, for speed and to avoid infinite recursion */ - - if (ptr->data == nullptr) { - te->name = IFACE_("(empty)"); - } - else if (type == TSE_RNA_STRUCT) { - /* struct */ - te->name = RNA_struct_name_get_alloc(ptr, nullptr, 0, nullptr); - - if (te->name) { - te->flag |= TE_FREE_NAME; - } - else { - te->name = RNA_struct_ui_name(ptr->type); - } - - /* If searching don't expand RNA entries */ - if (SEARCHING_OUTLINER(space_outliner) && BLI_strcasecmp("RNA", 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, tot_limit); - - /* auto open these cases */ - if (!parent || (RNA_property_type(reinterpret_cast(parent->directdata))) == - PROP_POINTER) { - if (!tselem->used) { - tselem->flag &= ~TSE_CLOSED; - } - } - - if (TSELEM_OPEN(tselem, space_outliner)) { - for (int a = 0; a < tot; a++) { - PointerRNA propptr; - RNA_property_collection_lookup_int(ptr, iterprop, a, &propptr); - if (!(RNA_property_flag(reinterpret_cast(propptr.data)) & PROP_HIDDEN)) { - outliner_add_element( - space_outliner, &te->subtree, (void *)ptr, te, TSE_RNA_PROPERTY, a); - } - } - } - else if (tot) { - te->flag |= TE_LAZY_CLOSED; - } - - te->rnaptr = *ptr; - } - else if (type == TSE_RNA_PROPERTY) { - /* property */ - PointerRNA propptr; - PropertyRNA *iterprop = RNA_struct_iterator_property(ptr->type); - RNA_property_collection_lookup_int(ptr, iterprop, index, &propptr); - - PropertyRNA *prop = reinterpret_cast(propptr.data); - PropertyType proptype = RNA_property_type(prop); - - te->name = RNA_property_ui_name(prop); - te->directdata = prop; - te->rnaptr = *ptr; - - /* If searching don't expand RNA entries */ - if (SEARCHING_OUTLINER(space_outliner) && BLI_strcasecmp("RNA", te->name) == 0) { - tselem->flag &= ~TSE_CHILDSEARCH; - } - - if (proptype == PROP_POINTER) { - PointerRNA pptr = RNA_property_pointer_get(ptr, prop); - - if (pptr.data) { - if (TSELEM_OPEN(tselem, space_outliner)) { - outliner_add_element( - space_outliner, &te->subtree, (void *)&pptr, te, TSE_RNA_STRUCT, -1); - } - else { - te->flag |= TE_LAZY_CLOSED; - } - } - } - else if (proptype == PROP_COLLECTION) { - int tot = RNA_property_collection_length(ptr, prop); - CLAMP_MAX(tot, tot_limit); - - if (TSELEM_OPEN(tselem, space_outliner)) { - for (int a = 0; a < tot; a++) { - PointerRNA pptr; - RNA_property_collection_lookup_int(ptr, prop, a, &pptr); - outliner_add_element( - space_outliner, &te->subtree, (void *)&pptr, te, TSE_RNA_STRUCT, a); - } - } - else if (tot) { - te->flag |= TE_LAZY_CLOSED; - } - } - else if (ELEM(proptype, PROP_BOOLEAN, PROP_INT, PROP_FLOAT)) { - int tot = RNA_property_array_length(ptr, prop); - CLAMP_MAX(tot, tot_limit); - - if (TSELEM_OPEN(tselem, space_outliner)) { - for (int a = 0; a < tot; a++) { - outliner_add_element( - space_outliner, &te->subtree, (void *)ptr, te, TSE_RNA_ARRAY_ELEM, a); - } - } - else if (tot) { - te->flag |= TE_LAZY_CLOSED; - } - } - } - else if (type == TSE_RNA_ARRAY_ELEM) { - PropertyRNA *prop = reinterpret_cast(parent->directdata); - - te->directdata = prop; - te->rnaptr = *ptr; - te->index = index; - - char c = RNA_property_array_item_char(prop, index); - - te->name = reinterpret_cast(MEM_callocN(sizeof(char[20]), "OutlinerRNAArrayName")); - if (c) { - sprintf((char *)te->name, " %c", c); - } - else { - sprintf((char *)te->name, " %d", index + 1); - } - te->flag |= TE_FREE_NAME; - } - } if (tree_element_warnings_get(te, nullptr, nullptr)) { te->flag |= TE_HAS_WARNING; 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::createFromType(const i case TSE_LIBRARY_OVERRIDE: return std::make_unique( legacy_te, *static_cast(idv)); + case TSE_RNA_STRUCT: + return std::make_unique(legacy_te, + *reinterpret_cast(idv)); + case TSE_RNA_PROPERTY: + return std::make_unique( + legacy_te, *reinterpret_cast(idv), legacy_te.index); + case TSE_RNA_ARRAY_ELEM: + return std::make_unique( + legacy_te, *reinterpret_cast(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 +#include + +#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(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(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(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(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( + 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 + +#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::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 -- cgit v1.2.3