Compare commits

...

11 Commits

Author SHA1 Message Date
22c056821e Silence warning 2022-03-22 19:05:45 +01:00
1551744a31 Merge branch 'master' into temp-library-overrides-outliner 2022-03-22 18:56:00 +01:00
86b83350ee Merge branch 'master' into temp-library-overrides-outliner 2022-03-07 17:44:05 +01:00
34df0c4e35 Fix glitchy highlighting of tree elements
Tree items need to be uniquely identifiable via type + data-pointer (the
ID pointer that isn't necessary an ID pointer) + index.
2022-03-03 17:43:12 +01:00
080de5d7e7 Merge branch 'master' into temp-library-overrides-outliner 2022-03-03 17:34:13 +01:00
072e19cdd9 Merge branch 'master' into temp-library-overrides-outliner 2022-03-02 15:06:55 +01:00
1383c53e18 Display modifiers and other collections with overrides in the tree
Rather than only displaying individual overriden modifier in the tree,
all are shown now, since the other modifiers add important context (e.g.
the order). This is especially important when a modifier was added
through an override. Same for constraints and in fact all other
collection properties now. The items are grouped together under a parent
item (e.g. "Modifiers").

Also:
- Path segments that define nested structs (RNA pointer properties where
  the pointer property itself isn't the override) will also be displayed
  as a parent item now, as explained in T95802, since this comes
  naturally from the code added for grouping collection items. If we end
  up not liking this, and rather display a single item with a sub-path,
  this can easily be done still.
2022-03-01 15:27:56 +01:00
7040f03f5a Merge branch 'master' into temp-library-overrides-outliner 2022-02-28 16:34:03 +01:00
11d7d56d3a Cleanup: Remove duplicated comment
Something went wrong here in 61776befc3.
2022-02-28 16:31:02 +01:00
0e38174ed6 Merge branch 'master' into temp-library-overrides-outliner 2022-02-28 14:31:58 +01:00
caa40c93eb Display buttons for properies in the Outliner Library Overrides mode
Part of T95802.
2022-02-25 20:15:56 +01:00
7 changed files with 225 additions and 11 deletions

View File

@@ -2591,6 +2591,12 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
case TSE_LIBRARY_OVERRIDE:
data.icon = ICON_LIBRARY_DATA_OVERRIDE;
break;
case TSE_LIBRARY_OVERRIDE_RNA_COLLECTION_ITEM: {
const auto &override_col_item = tree_element_cast<TreeElementOverrideRNACollectionItem>(
te);
data.icon = override_col_item->getIcon();
break;
}
case TSE_LINKED_OB:
data.icon = ICON_OBJECT_DATA;
break;
@@ -3305,7 +3311,11 @@ static void outliner_draw_tree_element(bContext *C,
offsx += UI_UNIT_X;
/* Data-type icon. */
if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE))) {
if (!(ELEM(tselem->type,
TSE_RNA_PROPERTY,
TSE_RNA_ARRAY_ELEM,
TSE_ID_BASE,
TSE_LIBRARY_OVERRIDE_RNA_CONTAINER))) {
tselem_draw_icon(block,
xmax,
(float)startx + offsx,

View File

@@ -64,6 +64,7 @@
#include "tree/common.hh"
#include "tree/tree_display.hh"
#include "tree/tree_element.hh"
#include "tree/tree_element_overrides.hh"
#ifdef WIN32
# include "BLI_math_base.h" /* M_PI */
@@ -815,6 +816,17 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
/* idv is the layer itself */
id = TREESTORE(parent)->id;
}
else if (ELEM(type,
TSE_LIBRARY_OVERRIDE,
TSE_LIBRARY_OVERRIDE_RNA_CONTAINER,
TSE_LIBRARY_OVERRIDE_RNA_COLLECTION_ITEM)) {
if (auto *override_base_te = tree_element_cast<TreeElementOverridesBase>(parent)) {
id = &override_base_te->id;
}
else if (auto *override_item_te = tree_element_cast<TreeElementOverridesItem>(parent)) {
id = override_item_te->getOverrideOwnerID();
}
}
/* exceptions */
if (type == TSE_ID_BASE) {
@@ -875,7 +887,11 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
BLI_assert_msg(0, "Expected this ID type to be ported to new Outliner tree-element design");
}
}
else if (ELEM(type, TSE_LIBRARY_OVERRIDE_BASE, TSE_LIBRARY_OVERRIDE)) {
else if (ELEM(type,
TSE_LIBRARY_OVERRIDE_BASE,
TSE_LIBRARY_OVERRIDE,
TSE_LIBRARY_OVERRIDE_RNA_CONTAINER,
TSE_LIBRARY_OVERRIDE_RNA_COLLECTION_ITEM)) {
if (!te->abstract_element) {
BLI_assert_msg(0,
"Expected override types to be ported to new Outliner tree-element design");

View File

@@ -74,6 +74,12 @@ 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_LIBRARY_OVERRIDE_RNA_CONTAINER:
return std::make_unique<TreeElementOverrideRNAContainer>(
legacy_te, *static_cast<PropertyPointerRNA *>(idv));
case TSE_LIBRARY_OVERRIDE_RNA_COLLECTION_ITEM:
return std::make_unique<TreeElementOverrideRNACollectionItem>(
legacy_te, *static_cast<PointerRNA *>(idv));
case TSE_RNA_STRUCT:
return std::make_unique<TreeElementRNAStruct>(legacy_te,
*reinterpret_cast<PointerRNA *>(idv));
@@ -98,6 +104,11 @@ std::unique_ptr<AbstractTreeElement> AbstractTreeElement::createFromType(const i
return nullptr;
}
TreeElement &AbstractTreeElement::getLegacyElement() const
{
return legacy_te_;
}
void tree_element_expand(const AbstractTreeElement &tree_element, SpaceOutliner &space_outliner)
{
/* Most types can just expand. IDs optionally expand (hence the poll) and do additional, common

View File

@@ -53,6 +53,8 @@ class AbstractTreeElement {
return true;
}
TreeElement &getLegacyElement() const;
friend void tree_element_expand(const AbstractTreeElement &tree_element,
SpaceOutliner &space_outliner);

View File

@@ -38,6 +38,69 @@ TreeElementOverridesBase::TreeElementOverridesBase(TreeElement &legacy_te, ID &i
}
}
static void expand_from_rna_path(SpaceOutliner &space_outliner,
TreeElement &path_root_te,
TreeElementOverridesData &override_data,
int *index)
{
PointerRNA idpoin;
RNA_id_pointer_create(&override_data.id, &idpoin);
TreeElement *parent_to_expand = &path_root_te;
ListBase path_elems{nullptr};
RNA_path_resolve_elements(&idpoin, override_data.override_property.rna_path, &path_elems);
/* Iterate the properties represented by the path. */
LISTBASE_FOREACH (PropertyElemRNA *, prop_ptr_from_path, &path_elems) {
/* Create containers for all items that are not leafs (i.e. that are not simple properties, but
* may contain child properties). */
if (prop_ptr_from_path->next) {
PropertyPointerRNA property_and_ptr = {prop_ptr_from_path->ptr, prop_ptr_from_path->prop};
TreeElement *container_te = outliner_add_element(&space_outliner,
&parent_to_expand->subtree,
&property_and_ptr,
parent_to_expand,
TSE_LIBRARY_OVERRIDE_RNA_CONTAINER,
(*index)++);
parent_to_expand = container_te;
/* Iterate over the children the container item expanded, and continue building the path for
* the item that matches the current path segment. */
LISTBASE_FOREACH (TreeElement *, container_item_te, &container_te->subtree) {
if (auto *col_item_te = tree_element_cast<TreeElementOverrideRNACollectionItem>(
container_item_te)) {
/* Does the collection item RNA pointer match the RNA pointer of the next property in the
* path? */
if (col_item_te->item_ptr.data == prop_ptr_from_path->next->ptr.data) {
parent_to_expand = &col_item_te->getLegacyElement();
}
}
}
/* All items within the same owning ID must have a unique index. If the container expands
* items, they count up based on the parent's index (or any preceding siblings if any). */
*index = BLI_listbase_is_empty(&container_te->subtree) ?
container_te->index + 1 :
((TreeElement *)container_te->subtree.last)->index + 1;
continue;
}
/* The actually overridden property. Must be a "leaf" property (end of the path). */
BLI_assert(prop_ptr_from_path->next == nullptr);
/* The actual override. */
outliner_add_element(&space_outliner,
&parent_to_expand->subtree,
&override_data,
parent_to_expand,
TSE_LIBRARY_OVERRIDE,
(*index)++);
}
BLI_freelistN(&path_elems);
}
void TreeElementOverridesBase::expand(SpaceOutliner &space_outliner) const
{
BLI_assert(id.override_library != nullptr);
@@ -50,9 +113,9 @@ void TreeElementOverridesBase::expand(SpaceOutliner &space_outliner) const
PointerRNA override_rna_ptr;
PropertyRNA *override_rna_prop;
short index = 0;
int index = 0;
for (auto *override_prop :
for (IDOverrideLibraryProperty *override_prop :
ListBaseWrapper<IDOverrideLibraryProperty>(id.override_library->properties)) {
const bool is_rna_path_valid = BKE_lib_override_rna_property_find(
&idpoin, override_prop, &override_rna_ptr, &override_rna_prop);
@@ -60,7 +123,7 @@ void TreeElementOverridesBase::expand(SpaceOutliner &space_outliner) const
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 :
for (IDOverrideLibraryPropertyOperation *override_prop_op :
ListBaseWrapper<IDOverrideLibraryPropertyOperation>(override_prop->operations)) {
if ((override_prop_op->flag & IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE) == 0) {
do_continue = false;
@@ -73,25 +136,93 @@ void TreeElementOverridesBase::expand(SpaceOutliner &space_outliner) const
}
}
TreeElementOverridesData data = {
TreeElementOverridesData override_data = {
id, *override_prop, override_rna_ptr, *override_rna_prop, is_rna_path_valid};
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &data, &legacy_te_, TSE_LIBRARY_OVERRIDE, index++);
expand_from_rna_path(space_outliner, legacy_te_, override_data, &index);
}
}
TreeElementOverridesProperty::TreeElementOverridesProperty(TreeElement &legacy_te,
TreeElementOverridesData &override_data)
: AbstractTreeElement(legacy_te),
: TreeElementOverridesItem(legacy_te),
override_prop_(override_data.override_property),
override_rna_ptr(override_data.override_rna_ptr),
override_rna_prop(override_data.override_rna_prop)
{
BLI_assert(legacy_te.store_elem->type == TSE_LIBRARY_OVERRIDE);
legacy_te.name = override_data.override_property.rna_path;
legacy_te.name = RNA_property_identifier(&override_rna_prop);
/* Abusing this for now, better way to do it is also pending current refactor of the whole tree
* code to use C++. */
legacy_te.directdata = POINTER_FROM_UINT(override_data.is_rna_path_valid);
}
TreeElementOverrideRNAContainer::TreeElementOverrideRNAContainer(
TreeElement &legacy_te, PropertyPointerRNA &container_prop_and_ptr)
: TreeElementOverridesItem(legacy_te),
container_ptr(container_prop_and_ptr.ptr),
container_prop(*container_prop_and_ptr.prop)
{
BLI_assert(legacy_te.store_elem->type == TSE_LIBRARY_OVERRIDE_RNA_CONTAINER);
legacy_te.name = RNA_property_ui_name(&container_prop);
}
void TreeElementOverrideRNAContainer::expand(SpaceOutliner &space_outliner) const
{
if (RNA_property_type(&container_prop) != PROP_COLLECTION) {
/* Only expand RNA collections. For them the exact item order may matter (e.g. for modifiers),
* so display them all to provide full context. */
return;
}
/* All items within the same owning ID must have a unique index. Count up based on the parent's
* index (or any preceding siblings if any). The parent increases the index counter to be higher
* than its last child too. */
int index = BLI_listbase_is_empty(&legacy_te_.subtree) ?
legacy_te_.parent->index :
((TreeElement *)legacy_te_.subtree.last)->index;
/* Non-const copy. */
PointerRNA ptr = container_ptr;
RNA_PROP_BEGIN (&ptr, itemptr, &container_prop) {
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
&itemptr,
&legacy_te_,
TSE_LIBRARY_OVERRIDE_RNA_COLLECTION_ITEM,
++index);
}
RNA_PROP_END;
}
ID *TreeElementOverridesItem::getOverrideOwnerID()
{
for (AbstractTreeElement *parent = tree_element_cast<AbstractTreeElement>(legacy_te_.parent);
parent;
parent = tree_element_cast<AbstractTreeElement>(parent->getLegacyElement().parent)) {
if (TreeElementOverridesBase *base_te = dynamic_cast<TreeElementOverridesBase *>(parent)) {
return &base_te->id;
}
}
return nullptr;
}
TreeElementOverrideRNACollectionItem::TreeElementOverrideRNACollectionItem(
TreeElement &legacy_te, const PointerRNA &item_ptr)
: TreeElementOverridesItem(legacy_te), item_ptr(item_ptr)
{
BLI_assert(legacy_te.store_elem->type == TSE_LIBRARY_OVERRIDE_RNA_COLLECTION_ITEM);
/* Non-const copy. */
PointerRNA ptr = item_ptr;
PropertyRNA *name_prop = RNA_struct_name_property(item_ptr.type);
legacy_te.name = RNA_property_string_get_alloc(&ptr, name_prop, nullptr, 0, nullptr);
legacy_te.flag |= TE_FREE_NAME;
}
int TreeElementOverrideRNACollectionItem::getIcon() const
{
return RNA_struct_ui_icon(item_ptr.type);
}
} // namespace blender::ed::outliner

View File

@@ -34,7 +34,21 @@ class TreeElementOverridesBase final : public AbstractTreeElement {
void expand(SpaceOutliner &) const override;
};
class TreeElementOverridesProperty final : public AbstractTreeElement {
/**
* Common interface for any item nested under #TreeElementOverridesBase. It gives access to the ID
* owning the override.
*/
class TreeElementOverridesItem : public AbstractTreeElement {
public:
ID *getOverrideOwnerID();
protected:
using AbstractTreeElement::AbstractTreeElement;
};
class TreeElementOverridesProperty final : public TreeElementOverridesItem {
[[maybe_unused]] IDOverrideLibraryProperty &override_prop_;
public:
PointerRNA override_rna_ptr;
PropertyRNA &override_rna_prop;
@@ -43,4 +57,30 @@ class TreeElementOverridesProperty final : public AbstractTreeElement {
TreeElementOverridesProperty(TreeElement &legacy_te, TreeElementOverridesData &override_data);
};
/**
* If the override is within some collection or pointer property, the collection/pointer gets its
* own parent item with items inside.
*/
class TreeElementOverrideRNAContainer final : public TreeElementOverridesItem {
public:
PointerRNA container_ptr;
PropertyRNA &container_prop;
public:
TreeElementOverrideRNAContainer(TreeElement &legacy_te,
PropertyPointerRNA &container_prop_and_ptr);
void expand(SpaceOutliner &) const override;
};
class TreeElementOverrideRNACollectionItem final : public TreeElementOverridesItem {
public:
PointerRNA item_ptr;
public:
TreeElementOverrideRNACollectionItem(TreeElement &legacy_te, const PointerRNA &item_ptr);
int getIcon() const;
};
} // namespace blender::ed::outliner

View File

@@ -114,6 +114,10 @@ typedef enum eTreeStoreElemType {
TSE_GPENCIL_EFFECT = 43,
TSE_LIBRARY_OVERRIDE_BASE = 44,
TSE_LIBRARY_OVERRIDE = 45,
/** Base item to add when the overridden property is within a nested struct or collection
property. */
TSE_LIBRARY_OVERRIDE_RNA_CONTAINER = 46,
TSE_LIBRARY_OVERRIDE_RNA_COLLECTION_ITEM = 47,
} eTreeStoreElemType;
/** Check whether given #TreeStoreElem should have a real ID in #TreeStoreElem.id member. */