Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/lib_override.c')
-rw-r--r--source/blender/blenkernel/intern/lib_override.c365
1 files changed, 231 insertions, 134 deletions
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index 649e7dab5d1..59cb6b2036e 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -161,6 +161,8 @@ void BKE_lib_override_library_copy(ID *dst_id, const ID *src_id, const bool do_f
(ID *)src_id;
id_us_plus(dst_id->override_library->reference);
+ dst_id->override_library->hierarchy_root = src_id->override_library->hierarchy_root;
+
if (do_full_copy) {
BLI_duplicatelist(&dst_id->override_library->properties,
&src_id->override_library->properties);
@@ -211,6 +213,7 @@ void BKE_lib_override_library_free(struct IDOverrideLibrary **override, const bo
}
static ID *lib_override_library_create_from(Main *bmain,
+ Library *owner_library,
ID *reference_id,
const int lib_id_copy_flags)
{
@@ -227,6 +230,12 @@ static ID *lib_override_library_create_from(Main *bmain,
}
id_us_min(local_id);
+ /* TODO: Handle this properly in LIB_NO_MAIN case as well (i.e. resync case). Or offload to
+ * generic ID copy code? */
+ if ((lib_id_copy_flags & LIB_ID_CREATE_NO_MAIN) == 0) {
+ local_id->lib = owner_library;
+ }
+
BKE_lib_override_library_init(local_id, reference_id);
/* NOTE: From liboverride perspective (and RNA one), shape keys are considered as local embedded
@@ -281,11 +290,12 @@ ID *BKE_lib_override_library_create_from_id(Main *bmain,
BLI_assert(reference_id != NULL);
BLI_assert(ID_IS_LINKED(reference_id));
- ID *local_id = lib_override_library_create_from(bmain, reference_id, 0);
+ ID *local_id = lib_override_library_create_from(bmain, NULL, reference_id, 0);
/* We cannot allow automatic hierarchy resync on this ID, it is highly likely to generate a giant
* mess in case there are a lot of hidden, non-instantiated, non-properly organized dependencies.
* Ref T94650. */
local_id->override_library->flag |= IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY;
+ local_id->override_library->hierarchy_root = local_id;
if (do_tagged_remap) {
Key *reference_key, *local_key = NULL;
@@ -320,9 +330,19 @@ ID *BKE_lib_override_library_create_from_id(Main *bmain,
}
bool BKE_lib_override_library_create_from_tag(Main *bmain,
- const Library *reference_library,
+ Library *owner_library,
+ const ID *id_root_reference,
+ ID *id_hierarchy_root,
const bool do_no_main)
{
+ BLI_assert(id_root_reference != NULL);
+ BLI_assert(id_hierarchy_root != NULL || (id_root_reference->tag & LIB_TAG_DOIT) != 0);
+ BLI_assert(id_hierarchy_root == NULL ||
+ (ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root) &&
+ id_hierarchy_root->override_library->reference == id_root_reference));
+
+ const Library *reference_library = id_root_reference->lib;
+
ID *reference_id;
bool success = true;
@@ -351,7 +371,7 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain,
* This requires extra care further down the resync process,
* see: #BKE_lib_override_library_resync. */
reference_id->newid = lib_override_library_create_from(
- bmain, reference_id, do_no_main ? LIB_ID_CREATE_NO_MAIN : 0);
+ bmain, owner_library, reference_id, do_no_main ? LIB_ID_CREATE_NO_MAIN : 0);
if (reference_id->newid == NULL) {
success = false;
break;
@@ -375,6 +395,11 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain,
/* Only remap new local ID's pointers, we don't want to force our new overrides onto our whole
* existing linked IDs usages. */
if (success) {
+ if (id_root_reference->newid != NULL) {
+ id_hierarchy_root = id_root_reference->newid;
+ }
+ BLI_assert(id_hierarchy_root != NULL);
+
for (todo_id_iter = todo_ids.first; todo_id_iter != NULL; todo_id_iter = todo_id_iter->next) {
reference_id = todo_id_iter->data;
ID *local_id = reference_id->newid;
@@ -383,6 +408,8 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain,
continue;
}
+ local_id->override_library->hierarchy_root = id_hierarchy_root;
+
Key *reference_key, *local_key = NULL;
if ((reference_key = BKE_key_from_id(reference_id)) != NULL) {
local_key = BKE_key_from_id(reference_id->newid);
@@ -451,6 +478,7 @@ typedef struct LibOverrideGroupTagData {
Main *bmain;
Scene *scene;
ID *id_root;
+ ID *hierarchy_root_id;
uint tag;
uint missing_tag;
/* Whether we are looping on override data, or their references (linked) one. */
@@ -761,6 +789,8 @@ static void lib_override_overrides_group_tag_recursive(LibOverrideGroupTagData *
BLI_assert(ID_IS_OVERRIDE_LIBRARY(id_owner));
BLI_assert(data->is_override);
+ ID *id_hierarchy_root = data->hierarchy_root_id;
+
if (ID_IS_OVERRIDE_LIBRARY_REAL(id_owner) &&
(id_owner->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY) != 0) {
return;
@@ -792,9 +822,15 @@ static void lib_override_overrides_group_tag_recursive(LibOverrideGroupTagData *
if (ELEM(to_id, NULL, id_owner)) {
continue;
}
+ /* Different libraries or different hierarchy roots are break points in override hierarchies.
+ */
if (!ID_IS_OVERRIDE_LIBRARY(to_id) || (to_id->lib != id_owner->lib)) {
continue;
}
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(to_id) &&
+ to_id->override_library->hierarchy_root != id_hierarchy_root) {
+ continue;
+ }
Library *reference_lib = lib_override_get(bmain, id_owner)->reference->lib;
ID *to_id_reference = lib_override_get(bmain, to_id)->reference;
@@ -824,6 +860,11 @@ static void lib_override_overrides_group_tag(LibOverrideGroupTagData *data)
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root));
BLI_assert(data->is_override);
+ ID *id_hierarchy_root = data->hierarchy_root_id;
+ BLI_assert(id_hierarchy_root != NULL);
+ BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root));
+ UNUSED_VARS_NDEBUG(id_hierarchy_root);
+
if (id_root->override_library->reference->tag & LIB_TAG_MISSING) {
id_root->tag |= data->missing_tag;
}
@@ -835,7 +876,10 @@ static void lib_override_overrides_group_tag(LibOverrideGroupTagData *data)
lib_override_overrides_group_tag_recursive(data);
}
-static bool lib_override_library_create_do(Main *bmain, Scene *scene, ID *id_root)
+static bool lib_override_library_create_do(Main *bmain,
+ Scene *scene,
+ Library *owner_library,
+ ID *id_root)
{
BKE_main_relations_create(bmain, 0);
LibOverrideGroupTagData data = {.bmain = bmain,
@@ -854,12 +898,16 @@ static bool lib_override_library_create_do(Main *bmain, Scene *scene, ID *id_roo
BKE_main_relations_free(bmain);
lib_override_group_tag_data_clear(&data);
- return BKE_lib_override_library_create_from_tag(bmain, id_root->lib, false);
+ const bool success = BKE_lib_override_library_create_from_tag(
+ bmain, owner_library, id_root, NULL, false);
+
+ return success;
}
static void lib_override_library_create_post_process(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
+ const Library *owner_library,
ID *id_root,
ID *id_reference,
Collection *residual_storage,
@@ -881,7 +929,8 @@ static void lib_override_library_create_post_process(Main *bmain,
/* Instantiating the root collection or object should never be needed in resync case, since the
* old override would be remapped to the new one. */
- if (!is_resync && id_root != NULL && id_root->newid != NULL && !ID_IS_LINKED(id_root->newid)) {
+ if (!is_resync && id_root != NULL && id_root->newid != NULL &&
+ (!ID_IS_LINKED(id_root->newid) || id_root->newid->lib == owner_library)) {
switch (GS(id_root->name)) {
case ID_GR: {
Object *ob_reference = id_reference != NULL && GS(id_reference->name) == ID_OB ?
@@ -926,7 +975,7 @@ static void lib_override_library_create_post_process(Main *bmain,
Collection *default_instantiating_collection = residual_storage;
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
Object *ob_new = (Object *)ob->id.newid;
- if (ob_new == NULL || ID_IS_LINKED(ob_new)) {
+ if (ob_new == NULL || (ID_IS_LINKED(ob_new) && ob_new->id.lib != owner_library)) {
continue;
}
@@ -989,6 +1038,7 @@ static void lib_override_library_create_post_process(Main *bmain,
bool BKE_lib_override_library_create(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
+ Library *owner_library,
ID *id_root,
ID *id_reference,
ID **r_id_root_override)
@@ -997,7 +1047,7 @@ bool BKE_lib_override_library_create(Main *bmain,
*r_id_root_override = NULL;
}
- const bool success = lib_override_library_create_do(bmain, scene, id_root);
+ const bool success = lib_override_library_create_do(bmain, scene, owner_library, id_root);
if (!success) {
return success;
@@ -1008,7 +1058,7 @@ bool BKE_lib_override_library_create(Main *bmain,
}
lib_override_library_create_post_process(
- bmain, scene, view_layer, id_root, id_reference, NULL, false);
+ bmain, scene, view_layer, owner_library, id_root, id_reference, NULL, false);
/* Cleanup. */
BKE_main_id_newptr_and_tag_clear(bmain);
@@ -1033,120 +1083,187 @@ bool BKE_lib_override_library_template_create(struct ID *id)
return true;
}
-bool BKE_lib_override_library_proxy_convert(Main *bmain,
- Scene *scene,
- ViewLayer *view_layer,
- Object *ob_proxy)
+static ID *lib_override_root_find(Main *bmain, ID *id, const int curr_level, int *r_best_level)
{
- /* `proxy_group`, if defined, is the empty instantiating the collection from which the proxy is
- * coming. */
- Object *ob_proxy_group = ob_proxy->proxy_group;
- const bool is_override_instancing_object = ob_proxy_group != NULL;
- ID *id_root = is_override_instancing_object ? &ob_proxy_group->instance_collection->id :
- &ob_proxy->proxy->id;
- ID *id_reference = is_override_instancing_object ? &ob_proxy_group->id : &ob_proxy->id;
+ if (curr_level > 1000) {
+ CLOG_ERROR(&LOG,
+ "Levels of dependency relationships between library overrides IDs is way too high, "
+ "skipping further processing loops (involves at least '%s')",
+ id->name);
+ BLI_assert(0);
+ return NULL;
+ }
- /* In some cases the instance collection of a proxy object may be local (see e.g. T83875). Not
- * sure this is a valid state, but for now just abort the overriding process. */
- if (!ID_IS_OVERRIDABLE_LIBRARY(id_root)) {
- return false;
+ if (!ID_IS_OVERRIDE_LIBRARY(id)) {
+ BLI_assert(0);
+ return NULL;
}
- /* We manually convert the proxy object into a library override, further override handling will
- * then be handled by `BKE_lib_override_library_create()` just as for a regular override
- * creation.
- */
- ob_proxy->proxy->id.tag |= LIB_TAG_DOIT;
- ob_proxy->proxy->id.newid = &ob_proxy->id;
- BKE_lib_override_library_init(&ob_proxy->id, &ob_proxy->proxy->id);
+ MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, id);
+ BLI_assert(entry != NULL);
- ob_proxy->proxy->proxy_from = NULL;
- ob_proxy->proxy = ob_proxy->proxy_group = NULL;
+ int best_level_candidate = curr_level;
+ ID *best_root_id_candidate = id;
- DEG_id_tag_update(&ob_proxy->id, ID_RECALC_COPY_ON_WRITE);
+ for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != NULL;
+ from_id_entry = from_id_entry->next) {
+ if ((from_id_entry->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE) != 0) {
+ /* Never consider non-overridable relationships as actual dependencies. */
+ continue;
+ }
+
+ ID *from_id = from_id_entry->id_pointer.from;
+ if (ELEM(from_id, NULL, id)) {
+ continue;
+ }
+ if (!ID_IS_OVERRIDE_LIBRARY(from_id) || (from_id->lib != id->lib)) {
+ continue;
+ }
- /* In case of proxy conversion, remap all local ID usages to linked IDs to their newly created
- * overrides.
- * While this might not be 100% the desired behavior, it is likely to be the case most of the
- * time. Ref: T91711. */
- ID *id_iter;
- FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
- if (!ID_IS_LINKED(id_iter)) {
- id_iter->tag |= LIB_TAG_DOIT;
+ int level_candidate = curr_level + 1;
+ /* Recursively process the parent. */
+ ID *root_id_candidate = lib_override_root_find(
+ bmain, from_id, curr_level + 1, &level_candidate);
+ if (level_candidate > best_level_candidate && root_id_candidate != NULL) {
+ best_root_id_candidate = root_id_candidate;
+ best_level_candidate = level_candidate;
}
}
- FOREACH_MAIN_ID_END;
- return BKE_lib_override_library_create(bmain, scene, view_layer, id_root, id_reference, NULL);
+ *r_best_level = best_level_candidate;
+ return best_root_id_candidate;
}
-static void lib_override_library_proxy_convert_do(Main *bmain,
- Scene *scene,
- Object *ob_proxy,
- BlendFileReadReport *reports)
+static void lib_override_root_hierarchy_set(Main *bmain, ID *id_root, ID *id, ID *id_from)
{
- Object *ob_proxy_group = ob_proxy->proxy_group;
- const bool is_override_instancing_object = ob_proxy_group != NULL;
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ if (id->override_library->hierarchy_root == id_root) {
+ /* Already set, nothing else to do here, sub-hierarchy is also assumed to be properly set
+ * then. */
+ return;
+ }
- const bool success = BKE_lib_override_library_proxy_convert(bmain, scene, NULL, ob_proxy);
+ /* Hierarchy root already set, and not matching currently proposed one, try to find which is
+ * best. */
+ if (id->override_library->hierarchy_root != NULL) {
+ /* Check if given `id_from` matches with the hierarchy of the linked reference ID, in which
+ * case we assume that the given hierarchy root is the 'real' one.
+ *
+ * NOTE: This can fail if user mixed dependencies between several overrides of a same
+ * reference linked hierarchy. Not much to be done in that case, it's virtually impossible to
+ * fix this automatically in a reliable way. */
+ if (id_from == NULL || !ID_IS_OVERRIDE_LIBRARY_REAL(id_from)) {
+ /* Too complicated to deal with for now. */
+ CLOG_WARN(&LOG,
+ "Inconsistency in library override hierarchy of ID '%s'.\n"
+ "\tNot enough data to verify validity of current proposed root '%s', assuming "
+ "already set one '%s' is valid.",
+ id->name,
+ id_root->name,
+ id->override_library->hierarchy_root->name);
+ return;
+ }
- if (success) {
- CLOG_INFO(&LOG,
- 4,
- "Proxy object '%s' successfully converted to library overrides",
- ob_proxy->id.name);
- /* Remove the instance empty from this scene, the items now have an overridden collection
- * instead. */
- if (is_override_instancing_object) {
- BKE_scene_collections_object_remove(bmain, scene, ob_proxy_group, true);
- }
- reports->count.proxies_to_lib_overrides_success++;
- }
-}
+ ID *id_from_ref = id_from->override_library->reference;
+ MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers,
+ id->override_library->reference);
+ BLI_assert(entry != NULL);
-void BKE_lib_override_library_main_proxy_convert(Main *bmain, BlendFileReadReport *reports)
-{
- LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
- LinkNodePair proxy_objects = {NULL};
+ bool do_replace_root = false;
+ for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != NULL;
+ from_id_entry = from_id_entry->next) {
+ if ((from_id_entry->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE) != 0) {
+ /* Never consider non-overridable relationships as actual dependencies. */
+ continue;
+ }
- FOREACH_SCENE_OBJECT_BEGIN (scene, object) {
- if (object->proxy_group != NULL) {
- BLI_linklist_append(&proxy_objects, object);
+ if (id_from_ref == from_id_entry->id_pointer.from) {
+ /* A matching parent was found in reference linked data, assume given hierarchy root is
+ * the valid one. */
+ do_replace_root = true;
+ CLOG_WARN(
+ &LOG,
+ "Inconsistency in library override hierarchy of ID '%s'.\n"
+ "\tCurrent proposed root '%s' detected as valid, will replace already set one '%s'.",
+ id->name,
+ id_root->name,
+ id->override_library->hierarchy_root->name);
+ break;
+ }
}
- }
- FOREACH_SCENE_OBJECT_END;
- FOREACH_SCENE_OBJECT_BEGIN (scene, object) {
- if (object->proxy != NULL && object->proxy_group == NULL) {
- BLI_linklist_append(&proxy_objects, object);
+ if (!do_replace_root) {
+ CLOG_WARN(
+ &LOG,
+ "Inconsistency in library override hierarchy of ID '%s'.\n"
+ "\tCurrent proposed root '%s' not detected as valid, keeping already set one '%s'.",
+ id->name,
+ id_root->name,
+ id->override_library->hierarchy_root->name);
+ return;
}
}
- FOREACH_SCENE_OBJECT_END;
- for (LinkNode *proxy_object_iter = proxy_objects.list; proxy_object_iter != NULL;
- proxy_object_iter = proxy_object_iter->next) {
- Object *proxy_object = proxy_object_iter->link;
- lib_override_library_proxy_convert_do(bmain, scene, proxy_object, reports);
+ id->override_library->hierarchy_root = id_root;
+ }
+
+ MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, id);
+ BLI_assert(entry != NULL);
+
+ for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != NULL;
+ to_id_entry = to_id_entry->next) {
+ if ((to_id_entry->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE) != 0) {
+ /* Never consider non-overridable relationships as actual dependencies. */
+ continue;
}
- BLI_linklist_free(proxy_objects.list, NULL);
+ ID *to_id = *to_id_entry->id_pointer.to;
+ if (ELEM(to_id, NULL, id)) {
+ continue;
+ }
+ if (!ID_IS_OVERRIDE_LIBRARY(to_id) || (to_id->lib != id->lib)) {
+ continue;
+ }
+
+ /* Recursively process the sub-hierarchy. */
+ lib_override_root_hierarchy_set(bmain, id_root, to_id, id);
}
+}
- LISTBASE_FOREACH (Object *, object, &bmain->objects) {
- if (ID_IS_LINKED(object)) {
- if (object->proxy != NULL) {
- CLOG_WARN(&LOG, "Did not try to convert linked proxy object '%s'", object->id.name);
- reports->count.linked_proxies++;
- }
+void BKE_lib_override_library_main_hierarchy_root_ensure(Main *bmain)
+{
+ ID *id;
+
+ BKE_main_relations_create(bmain, 0);
+
+ FOREACH_MAIN_ID_BEGIN (bmain, id) {
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
continue;
}
+ if (id->override_library->hierarchy_root != NULL) {
+ continue;
+ }
+
+ int best_level = 0;
+ ID *id_root = lib_override_root_find(bmain, id, best_level, &best_level);
- if (object->proxy_group != NULL || object->proxy != NULL) {
- CLOG_WARN(
- &LOG, "Proxy object '%s' failed to be converted to library override", object->id.name);
- reports->count.proxies_to_lib_overrides_failures++;
+ if (!ELEM(id_root->override_library->hierarchy_root, id_root, NULL)) {
+ CLOG_WARN(&LOG,
+ "Potential inconsistency in library override hierarchy of ID '%s', detected as "
+ "part of the hierarchy of '%s', which has a different root '%s'",
+ id->name,
+ id_root->name,
+ id_root->override_library->hierarchy_root->name);
+ continue;
}
+
+ lib_override_root_hierarchy_set(bmain, id_root, id_root, NULL);
+
+ BLI_assert(id->override_library->hierarchy_root != NULL);
}
+ FOREACH_MAIN_ID_END;
+
+ BKE_main_relations_free(bmain);
}
static void lib_override_library_remap(Main *bmain,
@@ -1214,6 +1331,7 @@ static bool lib_override_library_resync(Main *bmain,
LibOverrideGroupTagData data = {.bmain = bmain,
.scene = scene,
.id_root = id_root,
+ .hierarchy_root_id = id_root->override_library->hierarchy_root,
.tag = LIB_TAG_DOIT,
.missing_tag = LIB_TAG_MISSING,
.is_override = true,
@@ -1316,7 +1434,7 @@ static bool lib_override_library_resync(Main *bmain,
* override IDs (including within the old overrides themselves, since those are tagged too
* above). */
const bool success = BKE_lib_override_library_create_from_tag(
- bmain, id_root_reference->lib, true);
+ bmain, NULL, id_root_reference, id_root->override_library->hierarchy_root, true);
if (!success) {
return success;
@@ -1530,6 +1648,7 @@ static bool lib_override_library_resync(Main *bmain,
lib_override_library_create_post_process(bmain,
scene,
view_layer,
+ NULL,
id_root_reference,
id_root,
override_resync_residual_storage,
@@ -1634,46 +1753,20 @@ static void lib_override_resync_tagging_finalize_recurse(Main *bmain,
*
* NOTE: Related to `lib_override_resync_tagging_finalize` above.
*/
-static ID *lib_override_library_main_resync_find_root_recurse(ID *id, int *level)
-{
- (*level)++;
- ID *return_id = id;
-
- switch (GS(id->name)) {
- case ID_GR: {
- /* Find the highest valid collection in the parenting hierarchy.
- * Note that in practice, in any decent common case there is only one well defined root
- * collection anyway. */
- int max_level = *level;
- Collection *collection = (Collection *)id;
- LISTBASE_FOREACH (CollectionParent *, collection_parent_iter, &collection->parents) {
- Collection *collection_parent = collection_parent_iter->collection;
- if (ID_IS_OVERRIDE_LIBRARY_REAL(collection_parent) &&
- collection_parent->id.lib == id->lib) {
- int tmp_level = *level;
- ID *tmp_id = lib_override_library_main_resync_find_root_recurse(&collection_parent->id,
- &tmp_level);
- if (tmp_level > max_level) {
- max_level = tmp_level;
- return_id = tmp_id;
- }
- }
- }
- break;
- }
- case ID_OB: {
- Object *object = (Object *)id;
- if (object->parent != NULL && ID_IS_OVERRIDE_LIBRARY_REAL(object->parent) &&
- object->parent->id.lib == id->lib) {
- return_id = lib_override_library_main_resync_find_root_recurse(&object->parent->id, level);
- }
- break;
+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 != NULL) {
+ id = id_type->owner_get(bmain, id);
}
- default:
- break;
+ BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id));
}
- return return_id;
+ ID *hierarchy_root_id = id->override_library->hierarchy_root;
+ BLI_assert(hierarchy_root_id != NULL);
+ BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(hierarchy_root_id));
+ return hierarchy_root_id;
}
/* Ensure resync of all overrides at one level of indirect usage.
@@ -1815,14 +1908,13 @@ static void lib_override_library_main_resync_on_library_indirect_level(
Library *library = id->lib;
- int level = 0;
/* In complex non-supported cases, with several different override hierarchies sharing
* relations between each-other, we may end up not actually updating/replacing the given
* root id (see e.g. pro/shots/110_rextoria/110_0150_A/110_0150_A.anim.blend of sprites
* project repository, r2687).
* This can lead to infinite loop here, at least avoid this. */
id->tag &= ~LIB_TAG_LIB_OVERRIDE_NEED_RESYNC;
- id = lib_override_library_main_resync_find_root_recurse(id, &level);
+ id = lib_override_library_main_resync_root_get(bmain, id);
id->tag &= ~LIB_TAG_LIB_OVERRIDE_NEED_RESYNC;
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id));
BLI_assert(id->lib == library);
@@ -1863,7 +1955,8 @@ static int lib_override_sort_libraries_func(LibraryIDLinkCallbackData *cb_data)
ID *id_owner = cb_data->id_owner;
ID *id = *cb_data->id_pointer;
if (id != NULL && ID_IS_LINKED(id) && id->lib != id_owner->lib) {
- const int owner_library_indirect_level = id_owner->lib != NULL ? id_owner->lib->temp_index : 0;
+ const int owner_library_indirect_level = ID_IS_LINKED(id_owner) ? id_owner->lib->temp_index :
+ 0;
if (owner_library_indirect_level > 10000) {
CLOG_ERROR(
&LOG,
@@ -1954,7 +2047,7 @@ void BKE_lib_override_library_main_resync(Main *bmain,
/* Essentially ensures that potentially new overrides of new objects will be instantiated. */
lib_override_library_create_post_process(
- bmain, scene, view_layer, NULL, NULL, override_resync_residual_storage, true);
+ bmain, scene, view_layer, NULL, NULL, NULL, override_resync_residual_storage, true);
if (BKE_collection_is_empty(override_resync_residual_storage)) {
BKE_collection_delete(bmain, override_resync_residual_storage, true);
@@ -1980,6 +2073,7 @@ void BKE_lib_override_library_delete(Main *bmain, ID *id_root)
LibOverrideGroupTagData data = {.bmain = bmain,
.scene = NULL,
.id_root = id_root,
+ .hierarchy_root_id = id_root->override_library->hierarchy_root,
.tag = LIB_TAG_DOIT,
.missing_tag = LIB_TAG_MISSING,
.is_override = true,
@@ -2904,6 +2998,8 @@ void BKE_lib_override_library_update(Main *bmain, ID *local)
return;
}
+ tmp_id->lib = local->lib;
+
/* This ID name is problematic, since it is an 'rna name property' it should not be editable or
* different from reference linked ID. But local ID names need to be unique in a given type
* list of Main, so we cannot always keep it identical, which is why we need this special
@@ -2916,6 +3012,7 @@ void BKE_lib_override_library_update(Main *bmain, ID *local)
Key *tmp_key = BKE_key_from_id(tmp_id);
if (local_key != NULL && tmp_key != NULL) {
tmp_key->id.flag |= (local_key->id.flag & LIB_EMBEDDED_DATA_LIB_OVERRIDE);
+ tmp_key->id.lib = local_key->id.lib;
}
PointerRNA rnaptr_src, rnaptr_dst, rnaptr_storage_stack, *rnaptr_storage = NULL;