Refactor: Untangle confusing & unsafe outliner tree element data passing

The outliner tree element creation function passed a `void *idv`
argument and did weird and hard to follow stuff with it (like casting it
to `ID *` even though it wouldn't point to an ID, and further overriding
it based on the element type). This change tries to untangle this, so
that it's easy to follow what's going on, and so that a bunch of casts
from non-ID data to ID pointers are removed.

Basically the void pointer is split into an ID pointer for the owning ID
(if any) and a void pointer for custom data for the element creation.
This can be made type safe still, but that's for another commit. It also
allows us to remove some wrapper structs. The element creation function
itself no longer needs to know what kind of data is passed via the void
pointer. So this change has a number of benefits in fact.
Also improves/adds related comments.

Was quite careful to not cause behavioral changes.
This commit is contained in:
Julian Eisel
2023-09-01 19:43:30 +02:00
parent 1bcd812a75
commit 0a633a4e07
39 changed files with 494 additions and 354 deletions

View File

@@ -295,56 +295,6 @@ struct IDsSelectedData {
ListBase selected_array;
};
struct BoneElementCreateData {
ID *armature_id;
Bone *bone;
};
struct EditBoneElementCreateData {
ID *armature_id;
EditBone *ebone;
};
struct ConstraintElementCreateData {
Object *object;
bConstraint *con;
};
struct DeformGroupElementCreateData {
Object *object;
bDeformGroup *defgroup;
};
struct GPencilEffectElementCreateData {
Object *object;
ShaderFxData *fx;
};
struct ModifierCreateElementData {
Object *object;
ModifierDataStoreElem *md;
};
struct ParticleSystemElementCreateData {
Object *object;
ParticleSystem *psys;
};
struct PoseChannelElementCreateData {
Object *object;
bPoseChannel *pchan;
};
struct PoseGroupElementCreateData {
Object *object;
bActionGroup *agrp;
};
struct ViewLayerElementCreateData {
Scene *scene;
ViewLayer *view_layer;
};
TreeTraversalAction outliner_collect_selected_collections(TreeElement *te, void *customdata);
TreeTraversalAction outliner_collect_selected_objects(TreeElement *te, void *customdata);

View File

@@ -210,7 +210,8 @@ static void outliner_add_line_styles(SpaceOutliner *space_outliner,
continue;
}
linestyle->id.tag &= ~LIB_TAG_DOIT;
outliner_add_element(space_outliner, lb, linestyle, te, TSE_SOME_ID, 0);
outliner_add_element(
space_outliner, lb, reinterpret_cast<ID *>(linestyle), nullptr, te, TSE_SOME_ID, 0);
}
}
}
@@ -219,86 +220,46 @@ static void outliner_add_line_styles(SpaceOutliner *space_outliner,
TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
ListBase *lb,
void *idv,
ID *owner_id,
void *create_data,
TreeElement *parent,
short type,
short index,
const bool expand)
{
ID *id = static_cast<ID *>(idv);
/* Pointer to store in #TreeStoreElem.id to identify the element over rebuilds and reconstruct it
* on file read. */
/* FIXME: This is may be an arbitrary void pointer that is cast to an ID pointer. Could be a
* temporary stack pointer even. Often works reliably enough at runtime, and file reading handles
* cases where data can't be reconstructed just fine (pointer is null`ed). This is still
* completely type unsafe and error-prone. */
ID *persistent_dataptr = owner_id ? owner_id : static_cast<ID *>(create_data);
if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
id = ((PointerRNA *)idv)->owner_id;
if (!id) {
id = static_cast<ID *>(((PointerRNA *)idv)->data);
}
}
else if (type == TSE_GP_LAYER) {
/* idv is the layer itself */
id = TREESTORE(parent)->id;
}
else if (type == TSE_GREASE_PENCIL_NODE) {
/* idv is the layer itself */
id = TREESTORE(parent)->id;
}
else if (ELEM(type, TSE_GENERIC_LABEL)) {
id = nullptr;
}
else if (ELEM(type, TSE_LIBRARY_OVERRIDE, TSE_LIBRARY_OVERRIDE_OPERATION)) {
id = &static_cast<TreeElementOverridesData *>(idv)->id;
}
else if (type == TSE_BONE) {
id = static_cast<BoneElementCreateData *>(idv)->armature_id;
}
else if (type == TSE_EBONE) {
id = static_cast<EditBoneElementCreateData *>(idv)->armature_id;
}
else if (type == TSE_GPENCIL_EFFECT) {
id = &static_cast<GPencilEffectElementCreateData *>(idv)->object->id;
}
else if (type == TSE_DEFGROUP) {
id = &static_cast<DeformGroupElementCreateData *>(idv)->object->id;
}
else if (type == TSE_LINKED_PSYS) {
id = &static_cast<ParticleSystemElementCreateData *>(idv)->object->id;
}
else if (type == TSE_CONSTRAINT) {
id = &static_cast<ConstraintElementCreateData *>(idv)->object->id;
}
else if (type == TSE_POSEGRP) {
id = &static_cast<PoseGroupElementCreateData *>(idv)->object->id;
}
else if (type == TSE_R_LAYER) {
id = &static_cast<ViewLayerElementCreateData *>(idv)->scene->id;
}
else if (type == TSE_POSE_CHANNEL) {
id = &static_cast<PoseChannelElementCreateData *>(idv)->object->id;
}
else if (type == TSE_LAYER_COLLECTION) {
id = &static_cast<LayerCollection *>(idv)->collection->id;
}
else if (type == TSE_MODIFIER) {
id = &static_cast<ModifierCreateElementData *>(idv)->object->id;
if ((owner_id == nullptr) && ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
persistent_dataptr = static_cast<ID *>(((PointerRNA *)create_data)->data);
}
/* exceptions */
if (ELEM(type, TSE_ID_BASE, TSE_GENERIC_LABEL)) {
if (ELEM(type, TSE_ID_BASE)) {
/* pass */
}
else if (id == nullptr) {
else if (ELEM(type, TSE_GENERIC_LABEL)) {
persistent_dataptr = nullptr;
}
else if (persistent_dataptr == nullptr) {
return nullptr;
}
if (type == TSE_SOME_ID) {
/* Real ID, ensure we do not get non-outliner ID types here... */
BLI_assert(TREESTORE_ID_TYPE(id));
BLI_assert(TREESTORE_ID_TYPE(owner_id));
}
TreeElement *te = MEM_new<TreeElement>(__func__);
/* add to the visual tree */
BLI_addtail(lb, te);
/* add to the storage */
check_persistent(space_outliner, te, id, type, index);
check_persistent(space_outliner, te, persistent_dataptr, type, index);
TreeStoreElem *tselem = TREESTORE(te);
/* if we are searching for something expand to see child elements */
@@ -311,7 +272,7 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
/* New inheritance based element representation. Not all element types support this yet,
* eventually it should replace #TreeElement entirely. */
te->abstract_element = AbstractTreeElement::create_from_type(type, *te, idv);
te->abstract_element = AbstractTreeElement::create_from_type(type, *te, owner_id, create_data);
if (te->abstract_element) {
/* Element types ported to the new design are expected to have their name set at this point! */
BLI_assert(te->name != nullptr);
@@ -386,7 +347,7 @@ TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
/* The new type design sets the name already, don't override that here. We need to figure out
* how to deal with the idcode for non-TSE_SOME_ID types still. Some rely on it... */
te->idcode = GS(id->name);
te->idcode = GS(owner_id->name);
}
if (!expand) {
@@ -417,7 +378,8 @@ BLI_INLINE void outliner_add_collection_objects(SpaceOutliner *space_outliner,
TreeElement *parent)
{
LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
outliner_add_element(space_outliner, tree, cob->ob, parent, TSE_SOME_ID, 0);
outliner_add_element(
space_outliner, tree, reinterpret_cast<ID *>(cob->ob), nullptr, parent, TSE_SOME_ID, 0);
}
}
@@ -429,7 +391,7 @@ TreeElement *outliner_add_collection_recursive(SpaceOutliner *space_outliner,
LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
outliner_add_element(
space_outliner, &ten->subtree, &child->collection->id, ten, TSE_SOME_ID, 0);
space_outliner, &ten->subtree, &child->collection->id, nullptr, ten, TSE_SOME_ID, 0);
}
if (space_outliner->outlinevis != SO_SCENES) {

View File

@@ -32,7 +32,7 @@ ListBase TreeDisplayDataAPI::build_tree(const TreeSourceData &source_data)
RNA_main_pointer_create(source_data.bmain, &mainptr);
TreeElement *te = outliner_add_element(
&space_outliner_, &tree, (void *)&mainptr, nullptr, TSE_RNA_STRUCT, -1);
&space_outliner_, &tree, nullptr, (void *)&mainptr, nullptr, TSE_RNA_STRUCT, -1);
/* On first view open parent data elements */
const int show_opened = !space_outliner_.treestore ||

View File

@@ -137,10 +137,17 @@ TreeElement *TreeDisplayLibraries::add_library_contents(Main &mainvar, ListBase
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);
tenlib = outliner_add_element(&space_outliner_,
&lb,
reinterpret_cast<ID *>(lib),
nullptr,
nullptr,
TSE_SOME_ID,
0);
}
else {
tenlib = outliner_add_element(&space_outliner_, &lb, &mainvar, nullptr, TSE_ID_BASE, 0);
tenlib = outliner_add_element(
&space_outliner_, &lb, nullptr, &mainvar, nullptr, TSE_ID_BASE, 0);
tenlib->name = IFACE_("Current File");
}
}
@@ -153,15 +160,21 @@ TreeElement *TreeDisplayLibraries::add_library_contents(Main &mainvar, ListBase
ten = tenlib;
}
else {
ten = outliner_add_element(
&space_outliner_, &tenlib->subtree, lib, nullptr, TSE_ID_BASE, a);
ten = outliner_add_element(&space_outliner_,
&tenlib->subtree,
reinterpret_cast<ID *>(lib),
nullptr,
nullptr,
TSE_ID_BASE,
a);
ten->directdata = lbarray[a];
ten->name = outliner_idcode_to_plural(GS(id->name));
}
for (ID *id : List<ID>(lbarray[a])) {
if (library_id_filter_poll(lib, id)) {
outliner_add_element(&space_outliner_, &ten->subtree, id, ten, TSE_SOME_ID, 0);
outliner_add_element(
&space_outliner_, &ten->subtree, id, nullptr, ten, TSE_SOME_ID, 0);
}
}
}

View File

@@ -58,7 +58,8 @@ ListBase TreeDisplayIDOrphans::build_tree(const TreeSourceData &source_data)
TreeElement *te = nullptr;
if (!filter_id_type) {
ID *id = (ID *)lbarray[a]->first;
te = outliner_add_element(&space_outliner_, &tree, lbarray[a], nullptr, TSE_ID_BASE, 0);
te = outliner_add_element(
&space_outliner_, &tree, nullptr, lbarray[a], nullptr, TSE_ID_BASE, 0);
te->directdata = lbarray[a];
te->name = outliner_idcode_to_plural(GS(id->name));
}
@@ -67,7 +68,7 @@ ListBase TreeDisplayIDOrphans::build_tree(const TreeSourceData &source_data)
for (ID *id : List<ID>(lbarray[a])) {
if (ID_REAL_USERS(id) <= 0) {
outliner_add_element(
&space_outliner_, (te) ? &te->subtree : &tree, id, te, TSE_SOME_ID, 0);
&space_outliner_, (te) ? &te->subtree : &tree, id, nullptr, te, TSE_SOME_ID, 0);
}
}
}

View File

@@ -41,7 +41,7 @@ ListBase TreeDisplayOverrideLibraryHierarchies::build_tree(const TreeSourceData
/* First step: Build "Current File" hierarchy. */
TreeElement *current_file_te = outliner_add_element(
&space_outliner_, &tree, source_data.bmain, nullptr, TSE_ID_BASE, -1);
&space_outliner_, &tree, nullptr, source_data.bmain, nullptr, TSE_ID_BASE, -1);
current_file_te->name = IFACE_("Current File");
AbstractTreeElement::uncollapse_by_default(current_file_te);
{
@@ -49,8 +49,13 @@ ListBase TreeDisplayOverrideLibraryHierarchies::build_tree(const TreeSourceData
/* Add dummy child if there's nothing to display. */
if (BLI_listbase_is_empty(&current_file_te->subtree)) {
TreeElement *dummy_te = outliner_add_element(
&space_outliner_, &current_file_te->subtree, nullptr, current_file_te, TSE_ID_BASE, 0);
TreeElement *dummy_te = outliner_add_element(&space_outliner_,
&current_file_te->subtree,
nullptr,
nullptr,
current_file_te,
TSE_ID_BASE,
0);
dummy_te->name = IFACE_("No Library Overrides");
}
}
@@ -60,7 +65,7 @@ ListBase TreeDisplayOverrideLibraryHierarchies::build_tree(const TreeSourceData
lib = (Library *)lib->id.next)
{
TreeElement *tenlib = outliner_add_element(
&space_outliner_, &tree, lib, nullptr, TSE_SOME_ID, 0);
&space_outliner_, &tree, reinterpret_cast<ID *>(lib), nullptr, nullptr, TSE_SOME_ID, 0);
build_hierarchy_for_lib_or_main(source_data.bmain, *tenlib, lib);
}
@@ -146,7 +151,8 @@ ListBase TreeDisplayOverrideLibraryHierarchies::build_hierarchy_for_lib_or_main(
TreeElement *new_base_te = id_base_te_map.lookup_or_add_cb(GS(iter_id->name), [&]() {
TreeElement *new_te = outliner_add_element(&space_outliner_,
&parent_te.subtree,
lib ? (void *)lib : bmain,
reinterpret_cast<ID *>(lib),
bmain,
&parent_te,
TSE_ID_BASE,
base_index++);
@@ -154,8 +160,14 @@ ListBase TreeDisplayOverrideLibraryHierarchies::build_hierarchy_for_lib_or_main(
return new_te;
});
TreeElement *new_id_te = outliner_add_element(
&space_outliner_, &new_base_te->subtree, iter_id, new_base_te, TSE_SOME_ID, 0, false);
TreeElement *new_id_te = outliner_add_element(&space_outliner_,
&new_base_te->subtree,
iter_id,
nullptr,
new_base_te,
TSE_SOME_ID,
0,
false);
builder.build_hierarchy_for_ID(*iter_id, *new_id_te);
}
@@ -222,8 +234,14 @@ void OverrideIDHierarchyBuilder::build_hierarchy_for_ID_recursive(const ID &pare
return FOREACH_BREAK;
}
TreeElement *new_te = outliner_add_element(
&space_outliner_, &te_to_expand.subtree, &id, &te_to_expand, TSE_SOME_ID, 0, false);
TreeElement *new_te = outliner_add_element(&space_outliner_,
&te_to_expand.subtree,
&id,
nullptr,
&te_to_expand,
TSE_SOME_ID,
0,
false);
build_data.sibling_ids.add(&id);

View File

@@ -88,7 +88,7 @@ ListBase TreeDisplayOverrideLibraryProperties::add_library_contents(Main &mainva
if (!filter_id_type) {
id_base_te = outliner_add_element(
&space_outliner_, &tree, lbarray[a], nullptr, TSE_ID_BASE, 0);
&space_outliner_, &tree, nullptr, lbarray[a], nullptr, TSE_ID_BASE, 0);
id_base_te->directdata = lbarray[a];
id_base_te->name = outliner_idcode_to_plural(GS(id->name));
@@ -98,7 +98,7 @@ ListBase TreeDisplayOverrideLibraryProperties::add_library_contents(Main &mainva
for (ID *id : List<ID>(lbarray[a])) {
if (ID_IS_OVERRIDE_LIBRARY_REAL(id) && !ID_IS_LINKED(id)) {
TreeElement *override_tree_element = outliner_add_element(
&space_outliner_, lb_to_expand, id, id_base_te, TSE_LIBRARY_OVERRIDE_BASE, 0);
&space_outliner_, lb_to_expand, id, nullptr, id_base_te, TSE_LIBRARY_OVERRIDE_BASE, 0);
if (BLI_listbase_is_empty(&override_tree_element->subtree)) {
outliner_free_tree_element(override_tree_element, lb_to_expand);

View File

@@ -43,7 +43,7 @@ ListBase TreeDisplayScenes::build_tree(const TreeSourceData &source_data)
for (ID *id : List<ID>(source_data.bmain->scenes)) {
Scene *scene = reinterpret_cast<Scene *>(id);
TreeElement *te = outliner_add_element(
&space_outliner_, &tree, scene, nullptr, TSE_SOME_ID, 0);
&space_outliner_, &tree, reinterpret_cast<ID *>(scene), nullptr, nullptr, TSE_SOME_ID, 0);
TreeStoreElem *tselem = TREESTORE(te);
/* New scene elements open by default */

View File

@@ -42,11 +42,11 @@ ListBase TreeDisplaySequencer::build_tree(const TreeSourceData &source_data)
for (Sequence *seq : List<Sequence>(ed->seqbasep)) {
SequenceAddOp op = need_add_seq_dup(seq);
if (op == SEQUENCE_DUPLICATE_NONE) {
outliner_add_element(&space_outliner_, &tree, seq, nullptr, TSE_SEQUENCE, 0);
outliner_add_element(&space_outliner_, &tree, nullptr, seq, nullptr, TSE_SEQUENCE, 0);
}
else if (op == SEQUENCE_DUPLICATE_ADD) {
TreeElement *te = outliner_add_element(
&space_outliner_, &tree, seq, nullptr, TSE_SEQUENCE_DUP, 0);
&space_outliner_, &tree, nullptr, seq, nullptr, TSE_SEQUENCE_DUP, 0);
add_seq_dup(seq, te, 0);
}
}
@@ -103,7 +103,8 @@ void TreeDisplaySequencer::add_seq_dup(Sequence *seq, TreeElement *te, short ind
}
if (STREQ(p->strip->stripdata->filename, seq->strip->stripdata->filename)) {
outliner_add_element(&space_outliner_, &te->subtree, (void *)p, te, TSE_SEQUENCE, index);
outliner_add_element(
&space_outliner_, &te->subtree, nullptr, (void *)p, te, TSE_SEQUENCE, index);
}
p = p->next;
}

View File

@@ -80,9 +80,13 @@ ListBase TreeDisplayViewLayer::build_tree(const TreeSourceData &source_data)
add_view_layer(*scene, tree, (TreeElement *)nullptr);
}
else {
ViewLayerElementCreateData view_layer_data = {scene, view_layer};
TreeElement &te_view_layer = *outliner_add_element(
&space_outliner_, &tree, &view_layer_data, nullptr, TSE_R_LAYER, 0);
TreeElement &te_view_layer = *outliner_add_element(&space_outliner_,
&tree,
reinterpret_cast<ID *>(scene),
&view_layer,
nullptr,
TSE_R_LAYER,
0);
TreeStoreElem *tselem = TREESTORE(&te_view_layer);
@@ -108,8 +112,13 @@ void TreeDisplayViewLayer::add_view_layer(Scene &scene, ListBase &tree, TreeElem
/* Show objects in the view layer. */
BKE_view_layer_synced_ensure(&scene, view_layer_);
for (Base *base : List<Base>(*BKE_view_layer_object_bases_get(view_layer_))) {
TreeElement *te_object = outliner_add_element(
&space_outliner_, &tree, base->object, parent, TSE_SOME_ID, 0);
TreeElement *te_object = outliner_add_element(&space_outliner_,
&tree,
reinterpret_cast<ID *>(base->object),
nullptr,
parent,
TSE_SOME_ID,
0);
te_object->directdata = base;
}
@@ -120,7 +129,7 @@ void TreeDisplayViewLayer::add_view_layer(Scene &scene, ListBase &tree, TreeElem
else {
/* Show collections in the view layer. */
TreeElement &ten = *outliner_add_element(
&space_outliner_, &tree, &scene, parent, TSE_VIEW_COLLECTION_BASE, 0);
&space_outliner_, &tree, &scene.id, nullptr, parent, TSE_VIEW_COLLECTION_BASE, 0);
TREESTORE(&ten)->flag &= ~TSE_CLOSED;
/* First layer collection is for master collection, don't show it. */
@@ -153,7 +162,7 @@ void TreeDisplayViewLayer::add_layer_collections_recursive(ListBase &tree,
else {
ID *id = &lc->collection->id;
ten = outliner_add_element(
&space_outliner_, &tree, lc, &parent_ten, TSE_LAYER_COLLECTION, 0);
&space_outliner_, &tree, id, lc, &parent_ten, TSE_LAYER_COLLECTION, 0);
/* Open by default, except linked collections, which may contain many elements. */
TreeStoreElem *tselem = TREESTORE(ten);
@@ -176,8 +185,13 @@ void TreeDisplayViewLayer::add_layer_collection_objects(ListBase &tree,
BKE_view_layer_synced_ensure(scene_, view_layer_);
for (CollectionObject *cob : List<CollectionObject>(lc.collection->gobject)) {
Base *base = BKE_view_layer_base_find(view_layer_, cob->ob);
TreeElement *te_object = outliner_add_element(
&space_outliner_, &tree, base->object, &ten, TSE_SOME_ID, 0);
TreeElement *te_object = outliner_add_element(&space_outliner_,
&tree,
reinterpret_cast<ID *>(base->object),
nullptr,
&ten,
TSE_SOME_ID,
0);
te_object->directdata = base;
}
}
@@ -281,7 +295,8 @@ void ObjectsChildrenBuilder::make_object_parent_hierarchy_collections()
* We don't expand its sub-tree though, to make it less prominent. */
TreeElement *child_ob_tree_element = outliner_add_element(&outliner_,
&parent_ob_tree_element->subtree,
child,
reinterpret_cast<ID *>(child),
nullptr,
parent_ob_tree_element,
TSE_SOME_ID,
0,

View File

@@ -51,16 +51,18 @@ namespace blender::ed::outliner {
std::unique_ptr<AbstractTreeElement> AbstractTreeElement::create_from_type(const int type,
TreeElement &legacy_te,
void *idv)
ID *owner_id,
void *create_data)
{
if (idv == nullptr) {
if (owner_id == nullptr && create_data == nullptr) {
return nullptr;
}
/*
* The following calls make an implicit assumption about what data was passed to the `idv`
* argument of #outliner_add_element(). The old code does this already, here we just centralize
* it as much as possible for now. Would be nice to entirely get rid of that, no more `void *`.
* The following calls make an implicit assumption about what data was passed to the
* `create_data` argument of #outliner_add_element(). The old code does this already, here we
* just centralize it as much as possible for now. Would be nice to entirely get rid of that, no
* more `void *`.
*
* Once #outliner_add_element() is sufficiently simplified, it should be replaced by a C++ call.
* It could take the derived type as template parameter (e.g. #TreeElementAnimData) and use C++
@@ -71,126 +73,131 @@ std::unique_ptr<AbstractTreeElement> AbstractTreeElement::create_from_type(const
switch (type) {
case TSE_SOME_ID:
return TreeElementID::create_from_id(legacy_te, *static_cast<ID *>(idv));
return TreeElementID::create_from_id(legacy_te, *owner_id);
case TSE_GENERIC_LABEL:
return std::make_unique<TreeElementLabel>(legacy_te, static_cast<const char *>(idv));
return std::make_unique<TreeElementLabel>(legacy_te, static_cast<const char *>(create_data));
case TSE_ANIM_DATA:
return std::make_unique<TreeElementAnimData>(legacy_te,
*static_cast<IdAdtTemplate *>(idv)->adt);
*static_cast<AnimData *>(create_data));
case TSE_DRIVER_BASE:
return std::make_unique<TreeElementDriverBase>(legacy_te, *static_cast<AnimData *>(idv));
return std::make_unique<TreeElementDriverBase>(legacy_te,
*static_cast<AnimData *>(create_data));
case TSE_NLA:
return std::make_unique<TreeElementNLA>(legacy_te, *static_cast<AnimData *>(idv));
return std::make_unique<TreeElementNLA>(legacy_te, *static_cast<AnimData *>(create_data));
case TSE_NLA_TRACK:
return std::make_unique<TreeElementNLATrack>(legacy_te, *static_cast<NlaTrack *>(idv));
return std::make_unique<TreeElementNLATrack>(legacy_te,
*static_cast<NlaTrack *>(create_data));
case TSE_NLA_ACTION:
return std::make_unique<TreeElementNLAAction>(legacy_te, *static_cast<bAction *>(idv));
return std::make_unique<TreeElementNLAAction>(legacy_te,
*reinterpret_cast<bAction *>(owner_id));
case TSE_GP_LAYER:
return std::make_unique<TreeElementGPencilLayer>(legacy_te, *static_cast<bGPDlayer *>(idv));
return std::make_unique<TreeElementGPencilLayer>(legacy_te,
*static_cast<bGPDlayer *>(create_data));
case TSE_GREASE_PENCIL_NODE:
return std::make_unique<TreeElementGreasePencilNode>(
legacy_te, *static_cast<bke::greasepencil::TreeNode *>(idv));
legacy_te,
*reinterpret_cast<GreasePencil *>(owner_id),
*static_cast<bke::greasepencil::TreeNode *>(create_data));
case TSE_R_LAYER_BASE:
return std::make_unique<TreeElementViewLayerBase>(legacy_te, *static_cast<Scene *>(idv));
case TSE_R_LAYER: {
ViewLayerElementCreateData *view_layer_data = static_cast<ViewLayerElementCreateData *>(idv);
return std::make_unique<TreeElementViewLayerBase>(legacy_te,
*reinterpret_cast<Scene *>(owner_id));
case TSE_R_LAYER:
return std::make_unique<TreeElementViewLayer>(
legacy_te, *view_layer_data->scene, *view_layer_data->view_layer);
}
legacy_te, *reinterpret_cast<Scene *>(owner_id), *static_cast<ViewLayer *>(create_data));
case TSE_SCENE_COLLECTION_BASE:
return std::make_unique<TreeElementCollectionBase>(legacy_te, *static_cast<Scene *>(idv));
return std::make_unique<TreeElementCollectionBase>(legacy_te,
*reinterpret_cast<Scene *>(owner_id));
case TSE_SCENE_OBJECTS_BASE:
return std::make_unique<TreeElementSceneObjectsBase>(legacy_te, *static_cast<Scene *>(idv));
return std::make_unique<TreeElementSceneObjectsBase>(legacy_te,
*reinterpret_cast<Scene *>(owner_id));
case TSE_LIBRARY_OVERRIDE_BASE:
return std::make_unique<TreeElementOverridesBase>(legacy_te, *static_cast<ID *>(idv));
return std::make_unique<TreeElementOverridesBase>(legacy_te, *owner_id);
case TSE_LIBRARY_OVERRIDE:
return std::make_unique<TreeElementOverridesProperty>(
legacy_te, *static_cast<TreeElementOverridesData *>(idv));
legacy_te, *static_cast<TreeElementOverridesData *>(create_data));
case TSE_LIBRARY_OVERRIDE_OPERATION:
return std::make_unique<TreeElementOverridesPropertyOperation>(
legacy_te, *static_cast<TreeElementOverridesData *>(idv));
legacy_te, *static_cast<TreeElementOverridesData *>(create_data));
case TSE_RNA_STRUCT:
return std::make_unique<TreeElementRNAStruct>(legacy_te, *static_cast<PointerRNA *>(idv));
return std::make_unique<TreeElementRNAStruct>(legacy_te,
*static_cast<PointerRNA *>(create_data));
case TSE_RNA_PROPERTY:
return std::make_unique<TreeElementRNAProperty>(
legacy_te, *static_cast<PointerRNA *>(idv), legacy_te.index);
legacy_te, *static_cast<PointerRNA *>(create_data), legacy_te.index);
case TSE_RNA_ARRAY_ELEM:
return std::make_unique<TreeElementRNAArrayElement>(
legacy_te, *static_cast<PointerRNA *>(idv), legacy_te.index);
legacy_te, *static_cast<PointerRNA *>(create_data), legacy_te.index);
case TSE_SEQUENCE:
return std::make_unique<TreeElementSequence>(legacy_te, *static_cast<Sequence *>(idv));
return std::make_unique<TreeElementSequence>(legacy_te,
*static_cast<Sequence *>(create_data));
case TSE_SEQ_STRIP:
return std::make_unique<TreeElementSequenceStrip>(legacy_te, *static_cast<Strip *>(idv));
return std::make_unique<TreeElementSequenceStrip>(legacy_te,
*static_cast<Strip *>(create_data));
case TSE_SEQUENCE_DUP:
return std::make_unique<TreeElementSequenceStripDuplicate>(legacy_te,
*static_cast<Sequence *>(idv));
case TSE_BONE: {
BoneElementCreateData *bone_data = static_cast<BoneElementCreateData *>(idv);
return std::make_unique<TreeElementSequenceStripDuplicate>(
legacy_te, *static_cast<Sequence *>(create_data));
case TSE_BONE:
return std::make_unique<TreeElementBone>(
legacy_te, *bone_data->armature_id, *bone_data->bone);
}
case TSE_EBONE: {
EditBoneElementCreateData *ebone_data = static_cast<EditBoneElementCreateData *>(idv);
legacy_te, *owner_id, *static_cast<Bone *>(create_data));
case TSE_EBONE:
return std::make_unique<TreeElementEditBone>(
legacy_te, *ebone_data->armature_id, *ebone_data->ebone);
}
case TSE_GPENCIL_EFFECT: {
GPencilEffectElementCreateData *gp_effect_data =
static_cast<GPencilEffectElementCreateData *>(idv);
return std::make_unique<TreeElementGPencilEffect>(
legacy_te, *gp_effect_data->object, *gp_effect_data->fx);
}
legacy_te, *owner_id, *static_cast<EditBone *>(create_data));
case TSE_GPENCIL_EFFECT:
return std::make_unique<TreeElementGPencilEffect>(legacy_te,
*reinterpret_cast<Object *>(owner_id),
*static_cast<ShaderFxData *>(create_data));
case TSE_GPENCIL_EFFECT_BASE:
return std::make_unique<TreeElementGPencilEffectBase>(legacy_te,
*static_cast<Object *>(idv));
*reinterpret_cast<Object *>(owner_id));
case TSE_DEFGROUP_BASE:
return std::make_unique<TreeElementDeformGroupBase>(legacy_te, *static_cast<Object *>(idv));
case TSE_DEFGROUP: {
DeformGroupElementCreateData *defgroup_data = static_cast<DeformGroupElementCreateData *>(
idv);
return std::make_unique<TreeElementDeformGroup>(
legacy_te, *defgroup_data->object, *defgroup_data->defgroup);
}
case TSE_LINKED_PSYS: {
ParticleSystemElementCreateData *psys_data = static_cast<ParticleSystemElementCreateData *>(
idv);
return std::make_unique<TreeElementDeformGroupBase>(legacy_te,
*reinterpret_cast<Object *>(owner_id));
case TSE_DEFGROUP:
return std::make_unique<TreeElementDeformGroup>(legacy_te,
*reinterpret_cast<Object *>(owner_id),
*static_cast<bDeformGroup *>(create_data));
case TSE_LINKED_PSYS:
return std::make_unique<TreeElementParticleSystem>(
legacy_te, *psys_data->object, *psys_data->psys);
}
legacy_te,
*reinterpret_cast<Object *>(owner_id),
*static_cast<ParticleSystem *>(create_data));
case TSE_CONSTRAINT_BASE:
return std::make_unique<TreeElementConstraintBase>(legacy_te, *static_cast<Object *>(idv));
case TSE_CONSTRAINT: {
ConstraintElementCreateData *con_data = static_cast<ConstraintElementCreateData *>(idv);
return std::make_unique<TreeElementConstraint>(legacy_te, *con_data->object, *con_data->con);
}
return std::make_unique<TreeElementConstraintBase>(legacy_te,
*reinterpret_cast<Object *>(owner_id));
case TSE_CONSTRAINT:
return std::make_unique<TreeElementConstraint>(legacy_te,
*reinterpret_cast<Object *>(owner_id),
*static_cast<bConstraint *>(create_data));
case TSE_POSE_BASE:
return std::make_unique<TreeElementPoseBase>(legacy_te, *static_cast<Object *>(idv));
case TSE_POSE_CHANNEL: {
PoseChannelElementCreateData *pchan_data = static_cast<PoseChannelElementCreateData *>(idv);
return std::make_unique<TreeElementPoseChannel>(
legacy_te, *pchan_data->object, *pchan_data->pchan);
}
return std::make_unique<TreeElementPoseBase>(legacy_te,
*reinterpret_cast<Object *>(owner_id));
case TSE_POSE_CHANNEL:
return std::make_unique<TreeElementPoseChannel>(legacy_te,
*reinterpret_cast<Object *>(owner_id),
*static_cast<bPoseChannel *>(create_data));
case TSE_POSEGRP_BASE:
return std::make_unique<TreeElementPoseGroupBase>(legacy_te, *static_cast<Object *>(idv));
case TSE_POSEGRP: {
PoseGroupElementCreateData *posegrp_data = static_cast<PoseGroupElementCreateData *>(idv);
return std::make_unique<TreeElementPoseGroup>(
legacy_te, *posegrp_data->object, *posegrp_data->agrp);
}
return std::make_unique<TreeElementPoseGroupBase>(legacy_te,
*reinterpret_cast<Object *>(owner_id));
case TSE_POSEGRP:
return std::make_unique<TreeElementPoseGroup>(legacy_te,
*reinterpret_cast<Object *>(owner_id),
*static_cast<bActionGroup *>(create_data));
case TSE_MODIFIER_BASE:
return std::make_unique<TreeElementModifierBase>(legacy_te, *static_cast<Object *>(idv));
case TSE_MODIFIER: {
ModifierCreateElementData *md_data = static_cast<ModifierCreateElementData *>(idv);
return std::make_unique<TreeElementModifier>(legacy_te, *md_data->object, *md_data->md);
}
return std::make_unique<TreeElementModifierBase>(legacy_te,
*reinterpret_cast<Object *>(owner_id));
case TSE_MODIFIER:
return std::make_unique<TreeElementModifier>(
legacy_te,
*reinterpret_cast<Object *>(owner_id),
*static_cast<ModifierDataStoreElem *>(create_data));
case TSE_LINKED_OB:
return std::make_unique<TreeElementLinkedObject>(legacy_te, *static_cast<ID *>(idv));
return std::make_unique<TreeElementLinkedObject>(legacy_te, *owner_id);
case TSE_VIEW_COLLECTION_BASE:
return std::make_unique<TreeElementViewCollectionBase>(legacy_te,
*static_cast<Scene *>(idv));
*reinterpret_cast<Scene *>(owner_id));
case TSE_LAYER_COLLECTION:
return std::make_unique<TreeElementLayerCollection>(legacy_te,
*static_cast<LayerCollection *>(idv));
return std::make_unique<TreeElementLayerCollection>(
legacy_te, *static_cast<LayerCollection *>(create_data));
default:
break;
}

View File

@@ -14,6 +14,7 @@
#include "BLI_string_ref.hh"
#include "UI_resources.hh"
struct ID;
struct ListBase;
struct SpaceOutliner;
@@ -38,7 +39,8 @@ class AbstractTreeElement {
static std::unique_ptr<AbstractTreeElement> create_from_type(int type,
TreeElement &legacy_te,
void *idv);
ID *owner_id,
void *create_data);
/**
* Check if the type is expandable in current context.
@@ -100,12 +102,18 @@ class AbstractTreeElement {
};
/**
* TODO: this function needs to be split up! It's getting a bit too large...
*
* \note "ID" is not always a real ID.
* \note If child items are only added to the tree if the item is open,
* the `TSE_` type _must_ be added to #outliner_element_needs_rebuild_on_open_change().
* \note If child items are only added to the tree if the item is open, the `TSE_` type _must_ be
* added to #outliner_element_needs_rebuild_on_open_change().
*
* \param owner_id: The ID owning the represented data (or the ID itself if the element represents
* an ID directly). This is crucial to recognize tree elements over rebuilds, so
* that state like opened and selected is preserved. If this is not null, the \a
* create_data pointer will be used instead, refer to its description.
* \param create_data: Data passed to the constructor of the corresponding #AbstractTreeElement
* sub-type. If \a owner_id is not set, this pointer will be stored in an
* attempt to identify the element over rebuilds, so that state like opened and
* selected is preserved. Of course that won't work for volatile data (like
* stack variables).
* \param expand: If true, the element may add its own sub-tree. E.g. objects will list their
* animation data, object data, constraints, modifiers, ... This often adds visual
* noise, and can be expensive to add in big scenes. So prefer setting this to
@@ -113,7 +121,8 @@ class AbstractTreeElement {
*/
TreeElement *outliner_add_element(SpaceOutliner *space_outliner,
ListBase *lb,
void *idv,
ID *owner_id,
void *create_data,
TreeElement *parent,
short type,
short index,

View File

@@ -31,9 +31,18 @@ TreeElementAnimData::TreeElementAnimData(TreeElement &legacy_te, AnimData &anim_
void TreeElementAnimData::expand(SpaceOutliner &space_outliner) const
{
if (!anim_data_.action) {
return;
}
/* Animation data-block itself. */
outliner_add_element(
&space_outliner, &legacy_te_.subtree, anim_data_.action, &legacy_te_, TSE_SOME_ID, 0);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
reinterpret_cast<ID *>(anim_data_.action),
nullptr,
&legacy_te_,
TSE_SOME_ID,
0);
expand_drivers(space_outliner);
expand_NLA_tracks(space_outliner);
@@ -45,7 +54,7 @@ void TreeElementAnimData::expand_drivers(SpaceOutliner &space_outliner) const
return;
}
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &anim_data_, &legacy_te_, TSE_DRIVER_BASE, 0);
&space_outliner, &legacy_te_.subtree, nullptr, &anim_data_, &legacy_te_, TSE_DRIVER_BASE, 0);
}
void TreeElementAnimData::expand_NLA_tracks(SpaceOutliner &space_outliner) const
@@ -53,7 +62,8 @@ void TreeElementAnimData::expand_NLA_tracks(SpaceOutliner &space_outliner) const
if (BLI_listbase_is_empty(&anim_data_.nla_tracks)) {
return;
}
outliner_add_element(&space_outliner, &legacy_te_.subtree, &anim_data_, &legacy_te_, TSE_NLA, 0);
outliner_add_element(
&space_outliner, &legacy_te_.subtree, nullptr, &anim_data_, &legacy_te_, TSE_NLA, 0);
}
} // namespace blender::ed::outliner

View File

@@ -33,10 +33,13 @@ void TreeElementDeformGroupBase::expand(SpaceOutliner &space_outliner) const
int index;
LISTBASE_FOREACH_INDEX (bDeformGroup *, defgroup, defbase, index) {
DeformGroupElementCreateData defgroup_data = {&object_, defgroup};
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &defgroup_data, &legacy_te_, TSE_DEFGROUP, index);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
&object_.id,
defgroup,
&legacy_te_,
TSE_DEFGROUP,
index);
}
}

View File

@@ -42,8 +42,13 @@ void TreeElementDriverBase::expand(SpaceOutliner &space_outliner) const
DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
if (lastadded != dtar->id) {
/* XXX this lastadded check is rather lame, and also fails quite badly... */
outliner_add_element(
&space_outliner, &legacy_te_.subtree, dtar->id, &legacy_te_, TSE_LINKED_OB, 0);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
dtar->id,
nullptr,
&legacy_te_,
TSE_LINKED_OB,
0);
lastadded = dtar->id;
}
}

View File

@@ -31,11 +31,10 @@ void TreeElementGPencilEffectBase::expand(SpaceOutliner &space_outliner) const
{
int index;
LISTBASE_FOREACH_INDEX (ShaderFxData *, fx, &object_.shader_fx, index) {
GPencilEffectElementCreateData gp_effect_data = {&object_, fx};
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
&gp_effect_data,
&object_.id,
fx,
&legacy_te_,
TSE_GPENCIL_EFFECT,
index);
@@ -57,7 +56,8 @@ void TreeElementGPencilEffect::expand(SpaceOutliner &space_outliner) const
if (fx_.type == eShaderFxType_Swirl) {
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
((SwirlShaderFxData *)(&fx_))->object,
reinterpret_cast<ID *>(((SwirlShaderFxData *)(&fx_))->object),
nullptr,
&legacy_te_,
TSE_LINKED_OB,
0);

View File

@@ -17,8 +17,9 @@
namespace blender::ed::outliner {
TreeElementGreasePencilNode::TreeElementGreasePencilNode(TreeElement &legacy_te,
GreasePencil &owner_grease_pencil,
bke::greasepencil::TreeNode &node)
: AbstractTreeElement(legacy_te), node_(node)
: AbstractTreeElement(legacy_te), owner_grease_pencil_(owner_grease_pencil), node_(node)
{
BLI_assert(legacy_te.store_elem->type == TSE_GREASE_PENCIL_NODE);
legacy_te.name = node.name().c_str();
@@ -30,8 +31,13 @@ void TreeElementGreasePencilNode::expand(SpaceOutliner &space_outliner) const
return;
}
LISTBASE_FOREACH_BACKWARD (GreasePencilLayerTreeNode *, child, &node_.as_group().children) {
outliner_add_element(
&space_outliner, &legacy_te_.subtree, child, &legacy_te_, TSE_GREASE_PENCIL_NODE, 0);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
&owner_grease_pencil_.id,
child,
&legacy_te_,
TSE_GREASE_PENCIL_NODE,
0);
}
}

View File

@@ -13,14 +13,18 @@
namespace blender::bke::greasepencil {
class TreeNode;
} // namespace blender::bke::greasepencil
struct GreasePencil;
namespace blender::ed::outliner {
class TreeElementGreasePencilNode final : public AbstractTreeElement {
GreasePencil &owner_grease_pencil_;
blender::bke::greasepencil::TreeNode &node_;
public:
TreeElementGreasePencilNode(TreeElement &legacy_te, blender::bke::greasepencil::TreeNode &node);
TreeElementGreasePencilNode(TreeElement &legacy_te,
GreasePencil &owner_grease_pencil,
blender::bke::greasepencil::TreeNode &node);
void expand(SpaceOutliner &) const override;

View File

@@ -129,18 +129,17 @@ bool TreeElementID::expand_poll(const SpaceOutliner &space_outliner) const
void TreeElementID::expand(SpaceOutliner &space_outliner) const
{
/* Not all IDs support animation data. Will be null then. */
const AnimData *anim_data = BKE_animdata_from_id(&id_);
AnimData *anim_data = BKE_animdata_from_id(&id_);
if (anim_data) {
expand_animation_data(space_outliner, anim_data);
}
}
void TreeElementID::expand_animation_data(SpaceOutliner &space_outliner,
const AnimData *anim_data) const
void TreeElementID::expand_animation_data(SpaceOutliner &space_outliner, AnimData *anim_data) const
{
if (outliner_animdata_test(anim_data)) {
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &id_, &legacy_te_, TSE_ANIM_DATA, 0);
&space_outliner, &legacy_te_.subtree, &id_, anim_data, &legacy_te_, TSE_ANIM_DATA, 0);
}
}

View File

@@ -37,7 +37,7 @@ class TreeElementID : public AbstractTreeElement {
protected:
/* ID types with animation data can use this. */
void expand_animation_data(SpaceOutliner &, const AnimData *) const;
void expand_animation_data(SpaceOutliner &, AnimData *) const;
};
} // namespace blender::ed::outliner

View File

@@ -52,9 +52,8 @@ void TreeElementIDArmature::expand_edit_bones(SpaceOutliner &space_outiner) cons
{
int a = 0;
LISTBASE_FOREACH_INDEX (EditBone *, ebone, arm_.edbo, a) {
EditBoneElementCreateData ebone_data = {&arm_.id, ebone};
TreeElement *ten = outliner_add_element(
&space_outiner, &legacy_te_.subtree, &ebone_data, &legacy_te_, TSE_EBONE, a);
&space_outiner, &legacy_te_.subtree, &arm_.id, &ebone, &legacy_te_, TSE_EBONE, a);
ebone->temp.p = ten;
}
/* make hierarchy */
@@ -82,9 +81,7 @@ static void outliner_add_bone(SpaceOutliner *space_outliner,
TreeElement *parent,
int *a)
{
BoneElementCreateData bone_data = {id, curBone};
TreeElement *te = outliner_add_element(space_outliner, lb, &bone_data, parent, TSE_BONE, *a);
TreeElement *te = outliner_add_element(space_outliner, lb, id, curBone, parent, TSE_BONE, *a);
(*a)++;

View File

@@ -31,8 +31,13 @@ void TreeElementIDCurve::expand(SpaceOutliner &space_outliner) const
void TreeElementIDCurve::expand_materials(SpaceOutliner &space_outliner) const
{
for (int a = 0; a < curve_.totcol; a++) {
outliner_add_element(
&space_outliner, &legacy_te_.subtree, curve_.mat[a], &legacy_te_, TSE_SOME_ID, a);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
reinterpret_cast<ID *>(curve_.mat[a]),
nullptr,
&legacy_te_,
TSE_SOME_ID,
a);
}
}

View File

@@ -36,7 +36,7 @@ void TreeElementIDGPLegacy::expand_layers(SpaceOutliner &space_outliner) const
int index = 0;
LISTBASE_FOREACH_BACKWARD (bGPDlayer *, gpl, &gpd_.layers) {
outliner_add_element(
&space_outliner, &legacy_te_.subtree, gpl, &legacy_te_, TSE_GP_LAYER, index);
&space_outliner, &legacy_te_.subtree, &gpd_.id, gpl, &legacy_te_, TSE_GP_LAYER, index);
index++;
}
}

View File

@@ -34,8 +34,13 @@ void TreeElementIDGreasePencil::expand_layer_tree(SpaceOutliner &space_outliner)
LISTBASE_FOREACH_BACKWARD (
GreasePencilLayerTreeNode *, child, &grease_pencil_.root_group().children)
{
outliner_add_element(
&space_outliner, &legacy_te_.subtree, child, &legacy_te_, TSE_GREASE_PENCIL_NODE, 0);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
&grease_pencil_.id,
child,
&legacy_te_,
TSE_GREASE_PENCIL_NODE,
0);
}
}

View File

@@ -37,7 +37,8 @@ void TreeElementIDLineStyle::expand_textures(SpaceOutliner &space_outliner) cons
if (linestyle_.mtex[a]) {
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
(linestyle_.mtex[a])->tex,
reinterpret_cast<ID *>((linestyle_.mtex[a])->tex),
nullptr,
&legacy_te_,
TSE_SOME_ID,
a);

View File

@@ -31,15 +31,25 @@ void TreeElementIDMesh::expand(SpaceOutliner &space_outliner) const
void TreeElementIDMesh::expand_key(SpaceOutliner &space_outliner) const
{
outliner_add_element(
&space_outliner, &legacy_te_.subtree, mesh_.key, &legacy_te_, TSE_SOME_ID, 0);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
reinterpret_cast<ID *>(mesh_.key),
nullptr,
&legacy_te_,
TSE_SOME_ID,
0);
}
void TreeElementIDMesh::expand_materials(SpaceOutliner &space_outliner) const
{
for (int a = 0; a < mesh_.totcol; a++) {
outliner_add_element(
&space_outliner, &legacy_te_.subtree, mesh_.mat[a], &legacy_te_, TSE_SOME_ID, a);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
reinterpret_cast<ID *>(mesh_.mat[a]),
nullptr,
&legacy_te_,
TSE_SOME_ID,
a);
}
}

View File

@@ -31,8 +31,13 @@ void TreeElementIDMetaBall::expand(SpaceOutliner &space_outliner) const
void TreeElementIDMetaBall::expand_materials(SpaceOutliner &space_outliner) const
{
for (int a = 0; a < metaball_.totcol; a++) {
outliner_add_element(
&space_outliner, &legacy_te_.subtree, metaball_.mat[a], &legacy_te_, TSE_SOME_ID, a);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
reinterpret_cast<ID *>(metaball_.mat[a]),
nullptr,
&legacy_te_,
TSE_SOME_ID,
a);
}
}

View File

@@ -53,8 +53,13 @@ void TreeElementIDObject::expand(SpaceOutliner &space_outliner) const
void TreeElementIDObject::expand_data(SpaceOutliner &space_outliner) const
{
outliner_add_element(
&space_outliner, &legacy_te_.subtree, object_.data, &legacy_te_, TSE_SOME_ID, 0);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
static_cast<ID *>(object_.data),
nullptr,
&legacy_te_,
TSE_SOME_ID,
0);
}
void TreeElementIDObject::expand_pose(SpaceOutliner &space_outliner) const
@@ -63,20 +68,30 @@ void TreeElementIDObject::expand_pose(SpaceOutliner &space_outliner) const
return;
}
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &object_, &legacy_te_, TSE_POSE_BASE, 0);
&space_outliner, &legacy_te_.subtree, &object_.id, nullptr, &legacy_te_, TSE_POSE_BASE, 0);
/* Pose Groups */
if (!BLI_listbase_is_empty(&object_.pose->agroups)) {
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &object_, &legacy_te_, TSE_POSEGRP_BASE, 0);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
&object_.id,
nullptr,
&legacy_te_,
TSE_POSEGRP_BASE,
0);
}
}
void TreeElementIDObject::expand_materials(SpaceOutliner &space_outliner) const
{
for (int a = 0; a < object_.totcol; a++) {
outliner_add_element(
&space_outliner, &legacy_te_.subtree, object_.mat[a], &legacy_te_, TSE_SOME_ID, a);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
reinterpret_cast<ID *>(object_.mat[a]),
nullptr,
&legacy_te_,
TSE_SOME_ID,
a);
}
}
@@ -85,15 +100,18 @@ void TreeElementIDObject::expand_constraints(SpaceOutliner &space_outliner) cons
if (BLI_listbase_is_empty(&object_.constraints)) {
return;
}
TreeElement *tenla = outliner_add_element(
&space_outliner, &legacy_te_.subtree, &object_, &legacy_te_, TSE_CONSTRAINT_BASE, 0);
TreeElement *tenla = outliner_add_element(&space_outliner,
&legacy_te_.subtree,
&object_.id,
nullptr,
&legacy_te_,
TSE_CONSTRAINT_BASE,
0);
int index;
LISTBASE_FOREACH_INDEX (bConstraint *, con, &object_.constraints, index) {
ConstraintElementCreateData con_data = {&object_, con};
outliner_add_element(
&space_outliner, &tenla->subtree, &con_data, tenla, TSE_CONSTRAINT, index);
&space_outliner, &tenla->subtree, &object_.id, con, tenla, TSE_CONSTRAINT, index);
/* possible add all other types links? */
}
}
@@ -103,8 +121,13 @@ void TreeElementIDObject::expand_modifiers(SpaceOutliner &space_outliner) const
if (BLI_listbase_is_empty(&object_.modifiers)) {
return;
}
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &object_, &legacy_te_, TSE_MODIFIER_BASE, 0);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
&object_.id,
nullptr,
&legacy_te_,
TSE_MODIFIER_BASE,
0);
}
void TreeElementIDObject::expand_gpencil_modifiers(SpaceOutliner &space_outliner) const
@@ -112,8 +135,13 @@ void TreeElementIDObject::expand_gpencil_modifiers(SpaceOutliner &space_outliner
if (BLI_listbase_is_empty(&object_.greasepencil_modifiers)) {
return;
}
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &object_, &legacy_te_, TSE_MODIFIER_BASE, 0);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
&object_.id,
nullptr,
&legacy_te_,
TSE_MODIFIER_BASE,
0);
}
void TreeElementIDObject::expand_gpencil_effects(SpaceOutliner &space_outliner) const
@@ -121,8 +149,13 @@ void TreeElementIDObject::expand_gpencil_effects(SpaceOutliner &space_outliner)
if (BLI_listbase_is_empty(&object_.shader_fx)) {
return;
}
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &object_, &legacy_te_, TSE_GPENCIL_EFFECT_BASE, 0);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
&object_.id,
nullptr,
&legacy_te_,
TSE_GPENCIL_EFFECT_BASE,
0);
}
void TreeElementIDObject::expand_vertex_groups(SpaceOutliner &space_outliner) const
@@ -134,8 +167,13 @@ void TreeElementIDObject::expand_vertex_groups(SpaceOutliner &space_outliner) co
if (BLI_listbase_is_empty(defbase)) {
return;
}
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &object_, &legacy_te_, TSE_DEFGROUP_BASE, 0);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
&object_.id,
nullptr,
&legacy_te_,
TSE_DEFGROUP_BASE,
0);
}
void TreeElementIDObject::expand_duplicated_group(SpaceOutliner &space_outliner) const
@@ -143,7 +181,8 @@ void TreeElementIDObject::expand_duplicated_group(SpaceOutliner &space_outliner)
if (object_.instance_collection && (object_.transflag & OB_DUPLICOLLECTION)) {
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
object_.instance_collection,
reinterpret_cast<ID *>(object_.instance_collection),
nullptr,
&legacy_te_,
TSE_SOME_ID,
0);

View File

@@ -34,25 +34,40 @@ void TreeElementIDScene::expand(SpaceOutliner &space_outliner) const
void TreeElementIDScene::expand_view_layers(SpaceOutliner &space_outliner) const
{
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &scene_, &legacy_te_, TSE_R_LAYER_BASE, 0);
&space_outliner, &legacy_te_.subtree, &scene_.id, nullptr, &legacy_te_, TSE_R_LAYER_BASE, 0);
}
void TreeElementIDScene::expand_world(SpaceOutliner &space_outliner) const
{
outliner_add_element(
&space_outliner, &legacy_te_.subtree, scene_.world, &legacy_te_, TSE_SOME_ID, 0);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
reinterpret_cast<ID *>(scene_.world),
nullptr,
&legacy_te_,
TSE_SOME_ID,
0);
}
void TreeElementIDScene::expand_collections(SpaceOutliner &space_outliner) const
{
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &scene_, &legacy_te_, TSE_SCENE_COLLECTION_BASE, 0);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
&scene_.id,
nullptr,
&legacy_te_,
TSE_SCENE_COLLECTION_BASE,
0);
}
void TreeElementIDScene::expand_objects(SpaceOutliner &space_outliner) const
{
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &scene_, &legacy_te_, TSE_SCENE_OBJECTS_BASE, 0);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
&scene_.id,
nullptr,
&legacy_te_,
TSE_SCENE_OBJECTS_BASE,
0);
}
} // namespace blender::ed::outliner

View File

@@ -30,8 +30,13 @@ void TreeElementIDTexture::expand(SpaceOutliner &space_outliner) const
void TreeElementIDTexture::expand_image(SpaceOutliner &space_outliner) const
{
outliner_add_element(
&space_outliner, &legacy_te_.subtree, texture_.ima, &legacy_te_, TSE_SOME_ID, 0);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
reinterpret_cast<ID *>(texture_.ima),
nullptr,
&legacy_te_,
TSE_SOME_ID,
0);
}
} // namespace blender::ed::outliner

View File

@@ -33,18 +33,24 @@ void TreeElementModifierBase::expand(SpaceOutliner &space_outliner) const
LISTBASE_FOREACH_INDEX (ModifierData *, md, &object_.modifiers, index) {
ModifierDataStoreElem md_store(md);
ModifierCreateElementData md_data = {&object_, &md_store};
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &md_data, &legacy_te_, TSE_MODIFIER, index);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
&object_.id,
&md_store,
&legacy_te_,
TSE_MODIFIER,
index);
}
LISTBASE_FOREACH_INDEX (GpencilModifierData *, md, &object_.greasepencil_modifiers, index) {
ModifierDataStoreElem md_store(md);
ModifierCreateElementData md_data = {&object_, &md_store};
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &md_data, &legacy_te_, TSE_MODIFIER, index);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
&object_.id,
&md_store,
&legacy_te_,
TSE_MODIFIER,
index);
}
}
@@ -70,7 +76,8 @@ void TreeElementModifier::expand(SpaceOutliner &space_outliner) const
if (md->type == eModifierType_Lattice) {
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
((LatticeModifierData *)md)->object,
reinterpret_cast<ID *>(((LatticeModifierData *)md)->object),
nullptr,
&legacy_te_,
TSE_LINKED_OB,
0);
@@ -78,7 +85,8 @@ void TreeElementModifier::expand(SpaceOutliner &space_outliner) const
else if (md->type == eModifierType_Curve) {
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
((CurveModifierData *)md)->object,
reinterpret_cast<ID *>(((CurveModifierData *)md)->object),
nullptr,
&legacy_te_,
TSE_LINKED_OB,
0);
@@ -86,7 +94,8 @@ void TreeElementModifier::expand(SpaceOutliner &space_outliner) const
else if (md->type == eModifierType_Armature) {
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
((ArmatureModifierData *)md)->object,
reinterpret_cast<ID *>(((ArmatureModifierData *)md)->object),
nullptr,
&legacy_te_,
TSE_LINKED_OB,
0);
@@ -94,7 +103,8 @@ void TreeElementModifier::expand(SpaceOutliner &space_outliner) const
else if (md->type == eModifierType_Hook) {
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
((HookModifierData *)md)->object,
reinterpret_cast<ID *>(((HookModifierData *)md)->object),
nullptr,
&legacy_te_,
TSE_LINKED_OB,
0);
@@ -102,10 +112,13 @@ void TreeElementModifier::expand(SpaceOutliner &space_outliner) const
else if (md->type == eModifierType_ParticleSystem) {
ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys;
ParticleSystemElementCreateData psys_data = {&object_, psys};
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &psys_data, &legacy_te_, TSE_LINKED_PSYS, 0);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
&object_.id,
psys,
&legacy_te_,
TSE_LINKED_PSYS,
0);
}
}
if (md_.type == GPENCIL_MODIFIER_TYPE) {
@@ -113,7 +126,8 @@ void TreeElementModifier::expand(SpaceOutliner &space_outliner) const
if (md->type == eGpencilModifierType_Armature) {
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
((ArmatureGpencilModifierData *)md)->object,
reinterpret_cast<ID *>(((ArmatureGpencilModifierData *)md)->object),
nullptr,
&legacy_te_,
TSE_LINKED_OB,
0);
@@ -121,7 +135,8 @@ void TreeElementModifier::expand(SpaceOutliner &space_outliner) const
else if (md->type == eGpencilModifierType_Hook) {
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
((HookGpencilModifierData *)md)->object,
reinterpret_cast<ID *>(((HookGpencilModifierData *)md)->object),
nullptr,
&legacy_te_,
TSE_LINKED_OB,
0);
@@ -129,7 +144,8 @@ void TreeElementModifier::expand(SpaceOutliner &space_outliner) const
else if (md->type == eGpencilModifierType_Lattice) {
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
((LatticeGpencilModifierData *)md)->object,
reinterpret_cast<ID *>(((LatticeGpencilModifierData *)md)->object),
nullptr,
&legacy_te_,
TSE_LINKED_OB,
0);

View File

@@ -32,7 +32,8 @@ void TreeElementNLA::expand(SpaceOutliner &space_outliner) const
{
int a = 0;
for (NlaTrack *nlt : ListBaseWrapper<NlaTrack>(anim_data_.nla_tracks)) {
outliner_add_element(&space_outliner, &legacy_te_.subtree, nlt, &legacy_te_, TSE_NLA_TRACK, a);
outliner_add_element(
&space_outliner, &legacy_te_.subtree, nullptr, nlt, &legacy_te_, TSE_NLA_TRACK, a);
a++;
}
}
@@ -50,8 +51,13 @@ void TreeElementNLATrack::expand(SpaceOutliner &space_outliner) const
{
int a = 0;
for (NlaStrip *strip : ListBaseWrapper<NlaStrip>(track_.strips)) {
outliner_add_element(
&space_outliner, &legacy_te_.subtree, strip->act, &legacy_te_, TSE_NLA_ACTION, a);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
reinterpret_cast<ID *>(strip->act),
nullptr,
&legacy_te_,
TSE_NLA_ACTION,
a);
a++;
}
}

View File

@@ -378,6 +378,7 @@ void OverrideRNAPathTreeBuilder::build_path(TreeElement &parent,
else if (!path_te_map.contains(override_data.override_property.rna_path)) {
outliner_add_element(&space_outliner_,
&te_to_expand->subtree,
&override_data.id,
&override_data,
te_to_expand,
TSE_LIBRARY_OVERRIDE,
@@ -434,6 +435,7 @@ void OverrideRNAPathTreeBuilder::ensure_entire_collection(
current_te = outliner_add_element(&space_outliner_,
&te_to_expand.subtree,
&override_op_data.id,
/* Element will store a copy. */
&override_op_data,
&te_to_expand,
@@ -477,6 +479,7 @@ TreeElement &OverrideRNAPathTreeBuilder::ensure_label_element_for_prop(
return *path_te_map.lookup_or_add_cb(elem_path, [&]() {
TreeElement *new_te = outliner_add_element(&space_outliner_,
&parent.subtree,
nullptr,
(void *)RNA_property_ui_name(&prop),
&parent,
TSE_GENERIC_LABEL,
@@ -500,6 +503,7 @@ TreeElement &OverrideRNAPathTreeBuilder::ensure_label_element_for_ptr(TreeElemen
TreeElement *new_te = outliner_add_element(
&space_outliner_,
&parent.subtree,
nullptr,
(void *)(dyn_name ? dyn_name : RNA_struct_ui_name(ptr.type)),
&parent,
TSE_GENERIC_LABEL,

View File

@@ -37,23 +37,29 @@ void TreeElementPoseBase::expand(SpaceOutliner &space_outliner) const
int const_index = 1000; /* ensure unique id for bone constraints */
int a;
LISTBASE_FOREACH_INDEX (bPoseChannel *, pchan, &object_.pose->chanbase, a) {
PoseChannelElementCreateData pchan_data = {&object_, pchan};
TreeElement *ten = outliner_add_element(
&space_outliner, &legacy_te_.subtree, &pchan_data, &legacy_te_, TSE_POSE_CHANNEL, a);
TreeElement *ten = outliner_add_element(&space_outliner,
&legacy_te_.subtree,
&object_.id,
pchan,
&legacy_te_,
TSE_POSE_CHANNEL,
a);
pchan->temp = (void *)ten;
if (!BLI_listbase_is_empty(&pchan->constraints)) {
/* Object *target; */
TreeElement *tenla1 = outliner_add_element(
&space_outliner, &ten->subtree, &object_, ten, TSE_CONSTRAINT_BASE, 0);
&space_outliner, &ten->subtree, &object_.id, nullptr, ten, TSE_CONSTRAINT_BASE, 0);
/* char *str; */
LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) {
ConstraintElementCreateData con_data = {&object_, con};
outliner_add_element(
&space_outliner, &tenla1->subtree, &con_data, tenla1, TSE_CONSTRAINT, const_index);
outliner_add_element(&space_outliner,
&tenla1->subtree,
&object_.id,
con,
tenla1,
TSE_CONSTRAINT,
const_index);
/* possible add all other types links? */
}
const_index++;

View File

@@ -31,10 +31,8 @@ void TreeElementPoseGroupBase::expand(SpaceOutliner &space_outliner) const
{
int index;
LISTBASE_FOREACH_INDEX (bActionGroup *, agrp, &object_.pose->agroups, index) {
PoseGroupElementCreateData posegrp_data = {&object_, agrp};
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &posegrp_data, &legacy_te_, TSE_POSEGRP, index);
&space_outliner, &legacy_te_.subtree, &object_.id, agrp, &legacy_te_, TSE_POSEGRP, index);
}
}

View File

@@ -115,8 +115,13 @@ void TreeElementRNAStruct::expand(SpaceOutliner &space_outliner) const
PointerRNA propptr;
RNA_property_collection_lookup_int(&ptr, iterprop, index, &propptr);
if (!(RNA_property_flag(static_cast<PropertyRNA *>(propptr.data)) & PROP_HIDDEN)) {
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &ptr, &legacy_te_, TSE_RNA_PROPERTY, index);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
ptr.owner_id,
&ptr,
&legacy_te_,
TSE_RNA_PROPERTY,
index);
}
}
}
@@ -165,8 +170,13 @@ void TreeElementRNAProperty::expand(SpaceOutliner &space_outliner) const
if (pptr.data) {
if (TSELEM_OPEN(&tselem, &space_outliner)) {
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &pptr, &legacy_te_, TSE_RNA_STRUCT, -1);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
pptr.owner_id,
&pptr,
&legacy_te_,
TSE_RNA_STRUCT,
-1);
}
else {
legacy_te_.flag |= TE_PRETEND_HAS_CHILDREN;
@@ -181,8 +191,13 @@ void TreeElementRNAProperty::expand(SpaceOutliner &space_outliner) const
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, &pptr, &legacy_te_, TSE_RNA_STRUCT, index);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
pptr.owner_id,
&pptr,
&legacy_te_,
TSE_RNA_STRUCT,
index);
}
}
else if (tot) {
@@ -197,6 +212,7 @@ void TreeElementRNAProperty::expand(SpaceOutliner &space_outliner) const
for (int index = 0; index < tot; index++) {
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
rna_ptr.owner_id,
&rna_ptr,
&legacy_te_,
TSE_RNA_ARRAY_ELEM,

View File

@@ -31,7 +31,13 @@ TreeElementSceneObjectsBase::TreeElementSceneObjectsBase(TreeElement &legacy_te,
void TreeElementSceneObjectsBase::expand(SpaceOutliner &space_outliner) const
{
FOREACH_SCENE_OBJECT_BEGIN (&scene_, ob) {
outliner_add_element(&space_outliner, &legacy_te_.subtree, ob, &legacy_te_, TSE_SOME_ID, 0);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
reinterpret_cast<ID *>(ob),
nullptr,
&legacy_te_,
TSE_SOME_ID,
0);
}
FOREACH_SCENE_OBJECT_END;
outliner_make_object_parent_hierarchy(&legacy_te_.subtree);

View File

@@ -41,12 +41,17 @@ void TreeElementSequence::expand(SpaceOutliner &space_outliner) const
if (sequence_.type == SEQ_TYPE_META) {
LISTBASE_FOREACH (Sequence *, child, &sequence_.seqbase) {
outliner_add_element(
&space_outliner, &legacy_te_.subtree, child, &legacy_te_, TSE_SEQUENCE, 0);
&space_outliner, &legacy_te_.subtree, nullptr, child, &legacy_te_, TSE_SEQUENCE, 0);
}
}
else {
outliner_add_element(
&space_outliner, &legacy_te_.subtree, sequence_.strip, &legacy_te_, TSE_SEQ_STRIP, 0);
outliner_add_element(&space_outliner,
&legacy_te_.subtree,
nullptr,
sequence_.strip,
&legacy_te_,
TSE_SEQ_STRIP,
0);
}
}

View File

@@ -30,10 +30,8 @@ TreeElementViewLayerBase::TreeElementViewLayerBase(TreeElement &legacy_te, Scene
void TreeElementViewLayerBase::expand(SpaceOutliner &space_outliner) const
{
for (auto *view_layer : ListBaseWrapper<ViewLayer>(scene_.view_layers)) {
ViewLayerElementCreateData view_layer_data = {&scene_, view_layer};
outliner_add_element(
&space_outliner, &legacy_te_.subtree, &view_layer_data, &legacy_te_, TSE_R_LAYER, 0);
&space_outliner, &legacy_te_.subtree, &scene_.id, view_layer, &legacy_te_, TSE_R_LAYER, 0);
}
}