IDType `get_owner`: add an optional hint about owner ID.
In some cases, there is a chance code already knows who might be the owner of the given ID, in which case it can be more efficient to check it first (especially in cases like embedded node trees or scene collections, where the only other way is to loop over all possible owners currently). Will be used in next commit in some Outliner fix.
This commit is contained in:
parent
498e26fa0f
commit
12b3616895
|
@ -85,7 +85,11 @@ typedef void (*IDTypeForeachCacheFunction)(struct ID *id,
|
|||
|
||||
typedef void (*IDTypeForeachPathFunction)(struct ID *id, struct BPathForeachPathData *bpath_data);
|
||||
|
||||
typedef struct ID *(*IDTypeEmbeddedOwnerGetFunction)(struct Main *bmain, struct ID *id);
|
||||
/** \param owner_id_hint: If non-NULL, a potential owner of the given embedded ID. Can speed up
|
||||
* look-up of the owner ID in some cases. */
|
||||
typedef struct ID *(*IDTypeEmbeddedOwnerGetFunction)(struct Main *bmain,
|
||||
struct ID *id,
|
||||
struct ID *owner_id_hint);
|
||||
|
||||
typedef void (*IDTypeBlendWriteFunction)(struct BlendWriter *writer,
|
||||
struct ID *id,
|
||||
|
|
|
@ -66,10 +66,12 @@ void BKE_lib_override_library_free(struct IDOverrideLibrary **override, bool do_
|
|||
* \note This is especially useful when `id` is a non-real override (e.g. embedded ID like a master
|
||||
* collection or root node tree, or a shape key).
|
||||
*
|
||||
* \param owner_id_hint If not NULL, a potential owner for the given override-embedded `id`.
|
||||
* \param r_owner_id If given, will be set with the actual ID owning the return liboverride data.
|
||||
*/
|
||||
IDOverrideLibrary *BKE_lib_override_library_get(struct Main *bmain,
|
||||
struct ID *id,
|
||||
struct ID *owner_id_hint,
|
||||
struct ID **r_owner_id);
|
||||
|
||||
/**
|
||||
|
|
|
@ -162,7 +162,7 @@ static void collection_foreach_id(ID *id, LibraryForeachIDData *data)
|
|||
}
|
||||
}
|
||||
|
||||
static ID *collection_owner_get(Main *bmain, ID *id)
|
||||
static ID *collection_owner_get(Main *bmain, ID *id, ID *owner_id_hint)
|
||||
{
|
||||
if ((id->flag & LIB_EMBEDDED_DATA) == 0) {
|
||||
return id;
|
||||
|
@ -172,6 +172,11 @@ static ID *collection_owner_get(Main *bmain, ID *id)
|
|||
Collection *master_collection = (Collection *)id;
|
||||
BLI_assert((master_collection->flag & COLLECTION_IS_MASTER) != 0);
|
||||
|
||||
if (owner_id_hint != NULL && GS(owner_id_hint->name) == ID_SCE &&
|
||||
((Scene *)owner_id_hint)->master_collection == master_collection) {
|
||||
return owner_id_hint;
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
if (scene->master_collection == master_collection) {
|
||||
return &scene->id;
|
||||
|
@ -713,7 +718,8 @@ void BKE_collection_new_name_get(Collection *collection_parent, char *rname)
|
|||
name = BLI_strdup(DATA_("Collection"));
|
||||
}
|
||||
else if (collection_parent->flag & COLLECTION_IS_MASTER) {
|
||||
name = BLI_sprintfN(DATA_("Collection %d"), BLI_listbase_count(&collection_parent->children) + 1);
|
||||
name = BLI_sprintfN(DATA_("Collection %d"),
|
||||
BLI_listbase_count(&collection_parent->children) + 1);
|
||||
}
|
||||
else {
|
||||
const int number = BLI_listbase_count(&collection_parent->children) + 1;
|
||||
|
|
|
@ -91,7 +91,7 @@ static void shapekey_foreach_id(ID *id, LibraryForeachIDData *data)
|
|||
BKE_LIB_FOREACHID_PROCESS_ID(data, key->from, IDWALK_CB_LOOPBACK);
|
||||
}
|
||||
|
||||
static ID *shapekey_owner_get(Main *UNUSED(bmain), ID *id)
|
||||
static ID *shapekey_owner_get(Main *UNUSED(bmain), ID *id, ID *UNUSED(owner_id_hint))
|
||||
{
|
||||
return ((Key *)id)->from;
|
||||
}
|
||||
|
|
|
@ -94,6 +94,7 @@ BLI_INLINE void lib_override_object_posemode_transfer(ID *id_dst, ID *id_src)
|
|||
/** Get override data for a given ID. Needed because of our beloved shape keys snowflake. */
|
||||
BLI_INLINE const IDOverrideLibrary *BKE_lib_override_library_get(const Main *bmain,
|
||||
const ID *id,
|
||||
const ID *owner_id_hint,
|
||||
const ID **r_owner_id)
|
||||
{
|
||||
if (r_owner_id != nullptr) {
|
||||
|
@ -104,7 +105,8 @@ BLI_INLINE const IDOverrideLibrary *BKE_lib_override_library_get(const Main *bma
|
|||
if (id_type->owner_get != nullptr) {
|
||||
/* The #IDTypeInfo::owner_get callback should not modify the arguments, so casting away const
|
||||
* is okay. */
|
||||
const ID *owner_id = id_type->owner_get(const_cast<Main *>(bmain), const_cast<ID *>(id));
|
||||
const ID *owner_id = id_type->owner_get(
|
||||
const_cast<Main *>(bmain), const_cast<ID *>(id), const_cast<ID *>(owner_id_hint));
|
||||
if (r_owner_id != nullptr) {
|
||||
*r_owner_id = owner_id;
|
||||
}
|
||||
|
@ -115,13 +117,17 @@ BLI_INLINE const IDOverrideLibrary *BKE_lib_override_library_get(const Main *bma
|
|||
return id->override_library;
|
||||
}
|
||||
|
||||
IDOverrideLibrary *BKE_lib_override_library_get(Main *bmain, ID *id, ID **r_owner_id)
|
||||
IDOverrideLibrary *BKE_lib_override_library_get(Main *bmain,
|
||||
ID *id,
|
||||
ID *owner_id_hint,
|
||||
ID **r_owner_id)
|
||||
{
|
||||
/* Reuse the implementation of the const access function, which does not change the arguments.
|
||||
* Add const explicitly to make it clear to the compiler to avoid just calling this function. */
|
||||
return const_cast<IDOverrideLibrary *>(
|
||||
BKE_lib_override_library_get(const_cast<const Main *>(bmain),
|
||||
const_cast<const ID *>(id),
|
||||
const_cast<const ID *>(owner_id_hint),
|
||||
const_cast<const ID **>(r_owner_id)));
|
||||
}
|
||||
|
||||
|
@ -319,7 +325,7 @@ bool BKE_lib_override_library_is_system_defined(const Main *bmain, const ID *id)
|
|||
{
|
||||
if (ID_IS_OVERRIDE_LIBRARY(id)) {
|
||||
const ID *override_owner_id;
|
||||
BKE_lib_override_library_get(bmain, id, &override_owner_id);
|
||||
BKE_lib_override_library_get(bmain, id, nullptr, &override_owner_id);
|
||||
return (override_owner_id->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED) !=
|
||||
0;
|
||||
}
|
||||
|
@ -1087,8 +1093,9 @@ static void lib_override_overrides_group_tag_recursive(LibOverrideGroupTagData *
|
|||
}
|
||||
|
||||
const Library *reference_lib =
|
||||
BKE_lib_override_library_get(bmain, id_owner, nullptr)->reference->lib;
|
||||
const ID *to_id_reference = BKE_lib_override_library_get(bmain, to_id, nullptr)->reference;
|
||||
BKE_lib_override_library_get(bmain, id_owner, nullptr, nullptr)->reference->lib;
|
||||
const ID *to_id_reference =
|
||||
BKE_lib_override_library_get(bmain, to_id, nullptr, nullptr)->reference;
|
||||
if (to_id_reference->lib != reference_lib) {
|
||||
/* We do not override data-blocks from other libraries, nor do we process them. */
|
||||
continue;
|
||||
|
@ -1439,7 +1446,7 @@ static ID *lib_override_root_find(Main *bmain, ID *id, const int curr_level, int
|
|||
BLI_assert(id->flag & LIB_EMBEDDED_DATA_LIB_OVERRIDE);
|
||||
ID *id_owner;
|
||||
int best_level_placeholder = 0;
|
||||
BKE_lib_override_library_get(bmain, id, &id_owner);
|
||||
BKE_lib_override_library_get(bmain, id, nullptr, &id_owner);
|
||||
return lib_override_root_find(bmain, id_owner, curr_level + 1, &best_level_placeholder);
|
||||
}
|
||||
/* This way we won't process again that ID, should we encounter it again through another
|
||||
|
@ -1478,7 +1485,7 @@ static ID *lib_override_root_find(Main *bmain, ID *id, const int curr_level, int
|
|||
BLI_assert(id->flag & LIB_EMBEDDED_DATA_LIB_OVERRIDE);
|
||||
ID *id_owner;
|
||||
int best_level_placeholder = 0;
|
||||
BKE_lib_override_library_get(bmain, best_root_id_candidate, &id_owner);
|
||||
BKE_lib_override_library_get(bmain, best_root_id_candidate, nullptr, &id_owner);
|
||||
best_root_id_candidate = lib_override_root_find(
|
||||
bmain, id_owner, curr_level + 1, &best_level_placeholder);
|
||||
}
|
||||
|
@ -1795,7 +1802,8 @@ static bool lib_override_library_resync(Main *bmain,
|
|||
/* While this should not happen in typical cases (and won't be properly supported here),
|
||||
* user is free to do all kind of very bad things, including having different local
|
||||
* overrides of a same linked ID in a same hierarchy. */
|
||||
IDOverrideLibrary *id_override_library = BKE_lib_override_library_get(bmain, id, nullptr);
|
||||
IDOverrideLibrary *id_override_library = BKE_lib_override_library_get(
|
||||
bmain, id, nullptr, nullptr);
|
||||
|
||||
if (id_override_library->hierarchy_root != id_root->override_library->hierarchy_root) {
|
||||
continue;
|
||||
|
@ -2177,7 +2185,7 @@ static ID *lib_override_library_main_resync_root_get(Main *bmain, ID *id)
|
|||
if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
|
||||
const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
|
||||
if (id_type->owner_get != nullptr) {
|
||||
id = id_type->owner_get(bmain, id);
|
||||
id = id_type->owner_get(bmain, id, nullptr);
|
||||
}
|
||||
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id));
|
||||
}
|
||||
|
|
|
@ -713,7 +713,7 @@ static void lib_query_unused_ids_tag_recurse(Main *bmain,
|
|||
/* Directly 'by-pass' to actual real ID owner. */
|
||||
const IDTypeInfo *type_info_from = BKE_idtype_get_info_from_id(id_from);
|
||||
BLI_assert(type_info_from->owner_get != NULL);
|
||||
id_from = type_info_from->owner_get(bmain, id_from);
|
||||
id_from = type_info_from->owner_get(bmain, id_from, NULL);
|
||||
}
|
||||
|
||||
lib_query_unused_ids_tag_recurse(
|
||||
|
|
|
@ -404,7 +404,7 @@ static void node_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
|||
}
|
||||
}
|
||||
|
||||
static ID *node_owner_get(Main *bmain, ID *id)
|
||||
static ID *node_owner_get(Main *bmain, ID *id, ID *owner_id_hint)
|
||||
{
|
||||
if ((id->flag & LIB_EMBEDDED_DATA) == 0) {
|
||||
return id;
|
||||
|
@ -412,6 +412,12 @@ static ID *node_owner_get(Main *bmain, ID *id)
|
|||
/* TODO: Sort this NO_MAIN or not for embedded node trees. See T86119. */
|
||||
// BLI_assert((id->tag & LIB_TAG_NO_MAIN) == 0);
|
||||
|
||||
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
|
||||
|
||||
if (owner_id_hint != nullptr && ntreeFromID(owner_id_hint) == ntree) {
|
||||
return owner_id_hint;
|
||||
}
|
||||
|
||||
ListBase *lists[] = {&bmain->materials,
|
||||
&bmain->lights,
|
||||
&bmain->worlds,
|
||||
|
@ -421,7 +427,6 @@ static ID *node_owner_get(Main *bmain, ID *id)
|
|||
&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) {
|
||||
|
|
|
@ -663,7 +663,7 @@ static void template_id_liboverride_hierarchy_create(bContext *C,
|
|||
* system override with reset. */
|
||||
if (!ID_IS_LINKED(id) && ID_IS_OVERRIDE_LIBRARY(id)) {
|
||||
if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
|
||||
BKE_lib_override_library_get(bmain, id, &id);
|
||||
BKE_lib_override_library_get(bmain, id, NULL, &id);
|
||||
}
|
||||
if (id->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED) {
|
||||
id->override_library->flag &= ~IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED;
|
||||
|
|
|
@ -364,7 +364,7 @@ void outliner_collection_delete(
|
|||
const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(&parent->id);
|
||||
BLI_assert(id_type->owner_get != nullptr);
|
||||
|
||||
ID *scene_owner = id_type->owner_get(bmain, &parent->id);
|
||||
ID *scene_owner = id_type->owner_get(bmain, &parent->id, NULL);
|
||||
BLI_assert(GS(scene_owner->name) == ID_SCE);
|
||||
if (ID_IS_LINKED(scene_owner) || ID_IS_OVERRIDE_LIBRARY(scene_owner)) {
|
||||
skip = true;
|
||||
|
@ -597,7 +597,7 @@ static int collection_duplicate_exec(bContext *C, wmOperator *op)
|
|||
const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(&parent->id);
|
||||
BLI_assert(id_type->owner_get != nullptr);
|
||||
|
||||
Scene *scene_owner = (Scene *)id_type->owner_get(bmain, &parent->id);
|
||||
Scene *scene_owner = (Scene *)id_type->owner_get(bmain, &parent->id, NULL);
|
||||
BLI_assert(scene_owner != nullptr);
|
||||
BLI_assert(GS(scene_owner->id.name) == ID_SCE);
|
||||
|
||||
|
|
|
@ -942,7 +942,7 @@ ID *RNA_find_real_ID_and_path(Main *bmain, ID *id, const char **r_path)
|
|||
BLI_assert_msg(0, "Missing handling of embedded id type.");
|
||||
return id;
|
||||
}
|
||||
return id_type->owner_get(bmain, id);
|
||||
return id_type->owner_get(bmain, id, nullptr);
|
||||
}
|
||||
|
||||
static char *rna_prepend_real_ID_path(Main *bmain, ID *id, char *path, ID **r_real_id)
|
||||
|
|
|
@ -1478,7 +1478,7 @@ static void rna_ImageFormatSettings_color_management_set(PointerRNA *ptr, int va
|
|||
if (owner_id && GS(owner_id->name) == ID_NT) {
|
||||
/* For compositing nodes, find the corresponding scene. */
|
||||
const IDTypeInfo *type_info = BKE_idtype_get_info_from_id(owner_id);
|
||||
owner_id = type_info->owner_get(G_MAIN, owner_id);
|
||||
owner_id = type_info->owner_get(G_MAIN, owner_id, NULL);
|
||||
}
|
||||
if (owner_id && GS(owner_id->name) == ID_SCE) {
|
||||
BKE_image_format_color_management_copy_from_scene(imf, (Scene *)owner_id);
|
||||
|
|
Loading…
Reference in New Issue