Refactor: IDTypeInfo: Add owner_get to get owner of embedded IDs.

This concerns currently only collections (`master_collection` of scenes)
and root node trees. It removes the matching type-specific helpers
(`BKE_collection_master_scene_search` and `BKE_node_tree_find_owner_ID`).

No functional change expected here.

NOTE: Current implementation of `owner_get` is far from optimal, we
could probably do it better, see {T69169}.

NOTE: While it could also have it, shapekeys IDTypeInfo was left out of
this change for now. Mainly because it sould not be used currently, and
we ultimately want to demote shape keys from ID status anyway.
This commit is contained in:
Bastien Montagne 2021-02-25 10:17:31 +01:00
parent b5d39f9b46
commit de25b79ff5
44 changed files with 138 additions and 64 deletions

View file

@ -77,8 +77,6 @@ struct Collection *BKE_collection_duplicate(struct Main *bmain,
/* Master Collection for Scene */
struct Collection *BKE_collection_master_add(void);
struct Scene *BKE_collection_master_scene_search(const struct Main *bmain,
const struct Collection *master_collection);
/* Collection Objects */

View file

@ -95,6 +95,8 @@ typedef void (*IDTypeForeachCacheFunction)(struct ID *id,
IDTypeForeachCacheFunctionCallback function_callback,
void *user_data);
typedef struct ID *(*IDTypeEmbeddedOwnerGetFunction)(struct Main *bmain, struct ID *id);
typedef void (*IDTypeBlendWriteFunction)(struct BlendWriter *writer,
struct ID *id,
const void *id_address);
@ -181,6 +183,11 @@ typedef struct IDTypeInfo {
*/
IDTypeForeachCacheFunction foreach_cache;
/**
* For embedded IDs, return their owner ID.
*/
IDTypeEmbeddedOwnerGetFunction owner_get;
/* ********** Callbacks for reading and writing .blend files. ********** */
/**

View file

@ -442,7 +442,6 @@ struct bNodeTree *ntreeCopyTree(struct Main *bmain, const struct bNodeTree *ntre
struct bNodeTree **BKE_ntree_ptr_from_id(struct ID *id);
struct bNodeTree *ntreeFromID(struct ID *id);
struct ID *BKE_node_tree_find_owner_ID(struct Main *bmain, struct bNodeTree *ntree);
void ntreeFreeLocalNode(struct bNodeTree *ntree, struct bNode *node);
void ntreeFreeLocalTree(struct bNodeTree *ntree);

View file

@ -303,6 +303,7 @@ IDTypeInfo IDType_ID_AC = {
.make_local = NULL,
.foreach_id = action_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = action_blend_write,
.blend_read_data = action_blend_read_data,

View file

@ -324,6 +324,7 @@ IDTypeInfo IDType_ID_AR = {
.make_local = NULL,
.foreach_id = armature_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = armature_blend_write,
.blend_read_data = armature_blend_read_data,

View file

@ -403,6 +403,7 @@ IDTypeInfo IDType_ID_BR = {
.make_local = brush_make_local,
.foreach_id = brush_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = brush_blend_write,
.blend_read_data = brush_blend_read_data,

View file

@ -135,6 +135,7 @@ IDTypeInfo IDType_ID_CF = {
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = cache_file_blend_write,
.blend_read_data = cache_file_blend_read_data,

View file

@ -196,6 +196,7 @@ IDTypeInfo IDType_ID_CA = {
.make_local = camera_make_local,
.foreach_id = camera_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = camera_blend_write,
.blend_read_data = camera_blend_read_data,

View file

@ -172,6 +172,26 @@ static void collection_foreach_id(ID *id, LibraryForeachIDData *data)
}
}
static ID *collection_owner_get(Main *bmain, ID *id)
{
if ((id->flag & LIB_EMBEDDED_DATA) == 0) {
return id;
}
BLI_assert((id->tag & LIB_TAG_NO_MAIN) == 0);
Collection *master_collection = (Collection *)id;
BLI_assert((master_collection->flag & COLLECTION_IS_MASTER) != 0);
for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) {
if (scene->master_collection == master_collection) {
return &scene->id;
}
}
BLI_assert(!"Embedded collection with no owner. Critical Main inconsistency.");
return NULL;
}
void BKE_collection_blend_write_nolib(BlendWriter *writer, Collection *collection)
{
BKE_id_blend_write(writer, &collection->id);
@ -355,6 +375,7 @@ IDTypeInfo IDType_ID_GR = {
.make_local = NULL,
.foreach_id = collection_foreach_id,
.foreach_cache = NULL,
.owner_get = collection_owner_get,
.blend_write = collection_blend_write,
.blend_read_data = collection_blend_read_data,
@ -839,19 +860,6 @@ Collection *BKE_collection_master_add()
return master_collection;
}
Scene *BKE_collection_master_scene_search(const Main *bmain, const Collection *master_collection)
{
BLI_assert((master_collection->flag & COLLECTION_IS_MASTER) != 0);
for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) {
if (scene->master_collection == master_collection) {
return scene;
}
}
return NULL;
}
/** \} */
/* -------------------------------------------------------------------- */

View file

@ -320,6 +320,7 @@ IDTypeInfo IDType_ID_CU = {
.make_local = NULL,
.foreach_id = curve_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = curve_blend_write,
.blend_read_data = curve_blend_read_data,

View file

@ -169,6 +169,7 @@ IDTypeInfo IDType_ID_VF = {
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = vfont_blend_write,
.blend_read_data = vfont_blend_read_data,

View file

@ -322,6 +322,7 @@ IDTypeInfo IDType_ID_GD = {
.make_local = NULL,
.foreach_id = greasepencil_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = greasepencil_blend_write,
.blend_read_data = greasepencil_blend_read_data,

View file

@ -190,6 +190,7 @@ IDTypeInfo IDType_ID_HA = {
.make_local = NULL,
.foreach_id = hair_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = hair_blend_write,
.blend_read_data = hair_blend_read_data,

View file

@ -331,6 +331,7 @@ IDTypeInfo IDType_ID_IM = {
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = image_foreach_cache,
.owner_get = NULL,
.blend_write = image_blend_write,
.blend_read_data = image_blend_read_data,

View file

@ -193,6 +193,7 @@ IDTypeInfo IDType_ID_IP = {
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = NULL,
.blend_read_data = ipo_blend_read_data,

View file

@ -216,6 +216,7 @@ IDTypeInfo IDType_ID_KE = {
.make_local = NULL,
.foreach_id = shapekey_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL, /* Could have one actually? */
.blend_write = shapekey_blend_write,
.blend_read_data = shapekey_blend_read_data,

View file

@ -198,6 +198,7 @@ IDTypeInfo IDType_ID_LT = {
.make_local = NULL,
.foreach_id = lattice_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = lattice_blend_write,
.blend_read_data = lattice_blend_read_data,

View file

@ -77,6 +77,7 @@ IDTypeInfo IDType_ID_LI = {
.make_local = NULL,
.foreach_id = library_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = NULL,
.blend_read_data = NULL,

View file

@ -202,6 +202,7 @@ IDTypeInfo IDType_ID_LA = {
.make_local = NULL,
.foreach_id = light_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = light_blend_write,
.blend_read_data = light_blend_read_data,

View file

@ -100,6 +100,7 @@ IDTypeInfo IDType_ID_LP = {
.make_local = NULL,
.foreach_id = lightprobe_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = lightprobe_blend_write,
.blend_read_data = lightprobe_blend_read_data,

View file

@ -760,6 +760,7 @@ IDTypeInfo IDType_ID_LS = {
.make_local = NULL,
.foreach_id = linestyle_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = linestyle_blend_write,
.blend_read_data = linestyle_blend_read_data,

View file

@ -263,6 +263,7 @@ IDTypeInfo IDType_ID_MSK = {
.make_local = NULL,
.foreach_id = mask_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = mask_blend_write,
.blend_read_data = mask_blend_read_data,

View file

@ -267,6 +267,7 @@ IDTypeInfo IDType_ID_MA = {
.make_local = NULL,
.foreach_id = material_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = material_blend_write,
.blend_read_data = material_blend_read_data,

View file

@ -197,6 +197,7 @@ IDTypeInfo IDType_ID_MB = {
.make_local = NULL,
.foreach_id = metaball_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = metaball_blend_write,
.blend_read_data = metaball_blend_read_data,

View file

@ -357,6 +357,7 @@ IDTypeInfo IDType_ID_ME = {
.make_local = NULL,
.foreach_id = mesh_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = mesh_blend_write,
.blend_read_data = mesh_blend_read_data,

View file

@ -355,6 +355,7 @@ IDTypeInfo IDType_ID_MC = {
.make_local = NULL,
.foreach_id = movie_clip_foreach_id,
.foreach_cache = movie_clip_foreach_cache,
.owner_get = NULL,
.blend_write = movieclip_blend_write,
.blend_read_data = movieclip_blend_read_data,

View file

@ -367,6 +367,35 @@ static void node_foreach_cache(ID *id,
}
}
static ID *node_owner_get(Main *bmain, ID *id)
{
if ((id->flag & LIB_EMBEDDED_DATA) == 0) {
return id;
}
BLI_assert((id->tag & LIB_TAG_NO_MAIN) == 0);
ListBase *lists[] = {&bmain->materials,
&bmain->lights,
&bmain->worlds,
&bmain->textures,
&bmain->scenes,
&bmain->linestyles,
&bmain->simulations,
nullptr};
bNodeTree *ntree = (bNodeTree *)id;
for (int i = 0; lists[i] != nullptr; i++) {
LISTBASE_FOREACH (ID *, id_iter, lists[i]) {
if (ntreeFromID(id_iter) == ntree) {
return id_iter;
}
}
}
BLI_assert(!"Embedded node tree with no owner. Critical Main inconsistency.");
return nullptr;
}
static void write_node_socket_default_value(BlendWriter *writer, bNodeSocket *sock)
{
if (sock->default_value == nullptr) {
@ -916,6 +945,7 @@ IDTypeInfo IDType_ID_NT = {
/* make_local */ nullptr,
/* foreach_id */ node_foreach_id,
/* foreach_cache */ node_foreach_cache,
/* owner_get */ node_owner_get,
/* blend_write */ ntree_blend_write,
/* blend_read_data */ ntree_blend_read_data,
@ -2980,29 +3010,6 @@ bNodeTree *ntreeFromID(ID *id)
return (nodetree != nullptr) ? *nodetree : nullptr;
}
/* Finds and returns the datablock that privately owns the given tree, or null. */
ID *BKE_node_tree_find_owner_ID(Main *bmain, struct bNodeTree *ntree)
{
ListBase *lists[] = {&bmain->materials,
&bmain->lights,
&bmain->worlds,
&bmain->textures,
&bmain->scenes,
&bmain->linestyles,
&bmain->simulations,
nullptr};
for (int i = 0; lists[i] != nullptr; i++) {
LISTBASE_FOREACH (ID *, id, lists[i]) {
if (ntreeFromID(id) == ntree) {
return id;
}
}
}
return nullptr;
}
bool ntreeNodeExists(const bNodeTree *ntree, const bNode *testnode)
{
LISTBASE_FOREACH (const bNode *, node, &ntree->nodes) {

View file

@ -1148,6 +1148,7 @@ IDTypeInfo IDType_ID_OB = {
.make_local = object_make_local,
.foreach_id = object_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = object_blend_write,
.blend_read_data = object_blend_read_data,

View file

@ -151,6 +151,7 @@ IDTypeInfo IDType_ID_PAL = {
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = palette_blend_write,
.blend_read_data = palette_blend_read_data,
@ -216,6 +217,7 @@ IDTypeInfo IDType_ID_PC = {
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = paint_curve_blend_write,
.blend_read_data = paint_curve_blend_read_data,

View file

@ -504,6 +504,7 @@ IDTypeInfo IDType_ID_PA = {
.make_local = NULL,
.foreach_id = particle_settings_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = particle_settings_blend_write,
.blend_read_data = particle_settings_blend_read_data,

View file

@ -183,6 +183,7 @@ IDTypeInfo IDType_ID_PT = {
/* make_local */ nullptr,
/* foreach_id */ pointcloud_foreach_id,
/* foreach_cache */ nullptr,
/* owner_get */ nullptr,
/* blend_write */ pointcloud_blend_write,
/* blend_read_data */ pointcloud_blend_read_data,

View file

@ -1718,6 +1718,7 @@ IDTypeInfo IDType_ID_SCE = {
.make_local = NULL,
.foreach_id = scene_foreach_id,
.foreach_cache = scene_foreach_cache,
.owner_get = NULL,
.blend_write = scene_blend_write,
.blend_read_data = scene_blend_read_data,

View file

@ -311,6 +311,7 @@ IDTypeInfo IDType_ID_SCR = {
.make_local = NULL,
.foreach_id = screen_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = screen_blend_write,
/* Cannot be used yet, because #direct_link_screen has a return value. */

View file

@ -166,6 +166,7 @@ IDTypeInfo IDType_ID_SIM = {
/* make_local */ nullptr,
/* foreach_id */ simulation_foreach_id,
/* foreach_cache */ nullptr,
/* owner_get */ nullptr,
/* blend_write */ simulation_blend_write,
/* blend_read_data */ simulation_blend_read_data,

View file

@ -214,6 +214,7 @@ IDTypeInfo IDType_ID_SO = {
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = sound_foreach_cache,
.owner_get = NULL,
.blend_write = sound_blend_write,
.blend_read_data = sound_blend_read_data,

View file

@ -107,6 +107,7 @@ IDTypeInfo IDType_ID_SPK = {
.make_local = NULL,
.foreach_id = speaker_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = speaker_blend_write,
.blend_read_data = speaker_blend_read_data,

View file

@ -251,6 +251,7 @@ IDTypeInfo IDType_ID_TXT = {
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = text_blend_write,
.blend_read_data = text_blend_read_data,

View file

@ -219,6 +219,7 @@ IDTypeInfo IDType_ID_TE = {
.make_local = NULL,
.foreach_id = texture_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = texture_blend_write,
.blend_read_data = texture_blend_read_data,

View file

@ -637,6 +637,7 @@ IDTypeInfo IDType_ID_VO = {
/* make_local */ nullptr,
/* foreach_id */ volume_foreach_id,
/* foreach_cache */ volume_foreach_cache,
/* owner_get */ nullptr,
/* blend_write */ volume_blend_write,
/* blend_read_data */ volume_blend_read_data,

View file

@ -185,6 +185,7 @@ IDTypeInfo IDType_ID_WS = {
.make_local = NULL,
.foreach_id = workspace_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = workspace_blend_write,
.blend_read_data = workspace_blend_read_data,

View file

@ -199,6 +199,7 @@ IDTypeInfo IDType_ID_WO = {
.make_local = NULL,
.foreach_id = world_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = world_blend_write,
.blend_read_data = world_blend_read_data,

View file

@ -28,6 +28,7 @@
#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_idtype.h"
#include "BKE_layer.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
@ -361,8 +362,14 @@ void outliner_collection_delete(
break;
}
if (parent->flag & COLLECTION_IS_MASTER) {
Scene *parent_scene = BKE_collection_master_scene_search(bmain, parent);
if (ID_IS_LINKED(parent_scene)) {
BLI_assert(parent->id.flag & LIB_EMBEDDED_DATA);
const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(&parent->id);
BLI_assert(id_type->owner_get != NULL);
ID *scene_owner = id_type->owner_get(bmain, &parent->id);
BLI_assert(GS(scene_owner->name) == ID_SCE);
if (ID_IS_LINKED(scene_owner)) {
skip = true;
break;
}
@ -592,11 +599,18 @@ static int collection_duplicate_exec(bContext *C, wmOperator *op)
scene->master_collection;
}
else if (parent != NULL && (parent->flag & COLLECTION_IS_MASTER) != 0) {
Scene *scene = BKE_collection_master_scene_search(bmain, parent);
BLI_assert(scene != NULL);
if (ID_IS_LINKED(scene) || ID_IS_OVERRIDE_LIBRARY(scene)) {
scene = CTX_data_scene(C);
parent = ID_IS_LINKED(scene) ? NULL : scene->master_collection;
BLI_assert(parent->id.flag & LIB_EMBEDDED_DATA);
const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(&parent->id);
BLI_assert(id_type->owner_get != NULL);
Scene *scene_owner = (Scene *)id_type->owner_get(bmain, &parent->id);
BLI_assert(scene_owner != NULL);
BLI_assert(GS(scene_owner->id.name) == ID_SCE);
if (ID_IS_LINKED(scene_owner) || ID_IS_OVERRIDE_LIBRARY(scene_owner)) {
scene_owner = CTX_data_scene(C);
parent = ID_IS_LINKED(scene_owner) ? NULL : scene_owner->master_collection;
}
}

View file

@ -5826,26 +5826,29 @@ ID *RNA_find_real_ID_and_path(Main *bmain, ID *id, const char **r_path)
*r_path = "";
}
if ((id != NULL) && (id->flag & LIB_EMBEDDED_DATA)) {
switch (GS(id->name)) {
case ID_NT:
if (r_path) {
*r_path = "node_tree";
}
return BKE_node_tree_find_owner_ID(bmain, (bNodeTree *)id);
case ID_GR:
if (r_path) {
*r_path = "collection";
}
return (ID *)BKE_collection_master_scene_search(bmain, (struct Collection *)id);
default:
return NULL;
}
}
else {
if ((id == NULL) || (id->flag & LIB_EMBEDDED_DATA) == 0) {
return id;
}
const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
if (r_path) {
switch (GS(id->name)) {
case ID_NT:
*r_path = "node_tree";
break;
case ID_GR:
*r_path = "collection";
break;
default:
BLI_assert(!"Missing handling of embedded id type.");
}
}
if (id_type->owner_get == NULL) {
BLI_assert(!"Missing handling of embedded id type.");
return id;
}
return id_type->owner_get(bmain, id);
}
static char *rna_prepend_real_ID_path(Main *bmain, ID *id, char *path, ID **r_real_id)

View file

@ -272,6 +272,7 @@ IDTypeInfo IDType_ID_WM = {
.make_local = NULL,
.foreach_id = window_manager_foreach_id,
.foreach_cache = NULL,
.owner_get = NULL,
.blend_write = window_manager_blend_write,
.blend_read_data = window_manager_blend_read_data,