Commit: 923ccf6b106ad3cb3900eb1062ac82ef21e3bb7e
Author: Bastien Montagne
Date: Wed Jan 12 12:27:44 2022 +0100
Branches: master
https://developer.blender.org/rB923ccf6b106ad3cb3900eb1062ac82ef21e3bb7e
LibOverride: Use new 'hierarchy root' info in relevant override code.
This new info simplifies greatly the handling of resync and deleting
liboverride hierarchies, and makes those operations more robust to
complex dependencies cases between different hierarchies.
Related to T95283.
===================================================================
M source/blender/blenkernel/intern/lib_override.c
===================================================================
diff --git a/source/blender/blenkernel/intern/lib_override.c
b/source/blender/blenkernel/intern/lib_override.c
index 31e8e105eb6..7158b71d7f1 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -468,6 +468,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. */
@@ -778,6 +779,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;
@@ -809,9 +812,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;
@@ -841,6 +850,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;
}
@@ -1242,189 +1256,6 @@ void
BKE_lib_override_library_main_hierarchy_root_ensure(Main *bmain)
BKE_main_relations_free(bmain);
}
-static ID *lib_override_root_find(Main *bmain, ID *id, const int curr_level,
int *r_best_level)
-{
- 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;
- }
-
- if (!ID_IS_OVERRIDE_LIBRARY(id)) {
- BLI_assert(0);
- return NULL;
- }
-
- MainIDRelationsEntry *entry =
BLI_ghash_lookup(bmain->relations->relations_from_pointers, id);
- BLI_assert(entry != NULL);
-
- int best_level_candidate = curr_level;
- ID *best_root_id_candidate = id;
-
- 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;
- }
-
- 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;
- }
- }
-
- *r_best_level = best_level_candidate;
- return best_root_id_candidate;
-}
-
-static void lib_override_root_hierarchy_set(Main *bmain, ID *id_root, ID *id,
ID *id_from)
-{
- 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;
- }
-
- /* Hierarchy root already set, and not matching currently propsed 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;
- }
-
- 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);
-
- 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;
- }
-
- 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;
- }
- }
-
- 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;
- }
- }
-
- 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;
- }
-
- 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);
- }
-}
-
-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 (!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,
const ID *id_root_reference,
GHash *linkedref_to_old_override)
@@ -1490,6 +1321,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,
@@ -1911,46 +1743,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;
@@ Diff output truncated at 10240 characters. @@
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
List details, subscription details or unsubscribe:
https://lists.blender.org/mailman/listinfo/bf-blender-cvs