Outliner: Port RNA elements to new tree-element design
Continuation of work started in2e221de4ce
and249e4df110
. 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.
This commit is contained in:
parent
1bf6a880ab
commit
9bce134e56
Notes:
blender-bot
2023-02-14 05:12:59 +01:00
Referenced by commit d74c2b5c1f
, Outliner: Add missing sanity checks for RNA tree-elements
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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<PropertyRNA *>(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<PropertyRNA *>(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<PropertyRNA *>(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<PropertyRNA *>(parent->directdata);
|
||||
|
||||
te->directdata = prop;
|
||||
te->rnaptr = *ptr;
|
||||
te->index = index;
|
||||
|
||||
char c = RNA_property_array_item_char(prop, index);
|
||||
|
||||
te->name = reinterpret_cast<char *>(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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue