diff options
author | Bastien Montagne <bastien@blender.org> | 2021-06-03 17:12:26 +0300 |
---|---|---|
committer | Bastien Montagne <bastien@blender.org> | 2021-06-03 17:12:26 +0300 |
commit | 826bed4349fa2adb8d0fccbb192a3e550030a28d (patch) | |
tree | 1bc3afaa9f471191472905e015b5b2b5f8944604 /source/blender | |
parent | 797f6e1483a12fe4797e7cf9d435c042ddda40c4 (diff) |
LibOverride: Fix some fail cases with auto-resync.
In some cases e.g. only objects would actually need resync, so
collections on the override character would not be resynced, and if some
objects were sharing relationships with others those could be
lost/destroyed.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/intern/lib_override.c | 90 |
1 files changed, 66 insertions, 24 deletions
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index b76e1b10ed5..80c544f8e5c 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -1316,6 +1316,66 @@ bool BKE_lib_override_library_resync(Main *bmain, return success; } +/* Also tag ancestors overrides for resync. + * + * WARNING: Expects `bmain` to have valid relation data. + * + * NOTE: Related to `lib_override_library_main_resync_find_root_recurse` below. + * + * TODO: This is a sub-optimal, simple solution. At some point, we should rather find a way to + * resync a set of 'sub-roots' overrides, instead of having to 'go back' to the real root and + * resync the whole hierarchy. + */ +static void lib_override_resync_tagging_finalize_recurse(Main *bmain, + ID *id, + const int library_indirect_level) +{ + if (id->lib != NULL && id->lib->temp_index > library_indirect_level) { + CLOG_ERROR( + &LOG, + "While processing indirect level %d, ID %s from lib %s of indirect level %d detected " + "as needing resync.", + library_indirect_level, + id->name, + id->lib->filepath, + id->lib->temp_index); + } + + MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, id); + BLI_assert(entry != NULL); + + if (entry->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) { + /* This ID has already been processed. */ + return; + } + /* This way we won't process again that ID, should we encounter it again through another + * relationship hierarchy. */ + entry->tags |= MAINIDRELATIONS_ENTRY_TAGS_PROCESSED; + + for (MainIDRelationsEntryItem *entry_item = entry->from_ids; entry_item != NULL; + entry_item = entry_item->next) { + if (entry_item->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE) { + continue; + } + ID *id_from = entry_item->id_pointer.from; + + /* Case where this ID pointer was to a linked ID, that now needs to be overridden. */ + if (ID_IS_OVERRIDE_LIBRARY_REAL(id_from) && id_from->lib == id->lib) { + id_from->tag |= LIB_TAG_LIB_OVERRIDE_NEED_RESYNC; + CLOG_INFO(&LOG, + 3, + "ID %s (%p) now tagged as needing resync because they use %s (%p) that needs to " + "be overridden", + id_from->name, + id_from->lib, + id->name, + id->lib); + lib_override_resync_tagging_finalize_recurse(bmain, id_from, library_indirect_level); + } + break; + } +} + /* Ensures parent collection (or objects) in the same override group are also tagged for resync. * * This is needed since otherwise, some (new) ID added in one sub-collection might be used in @@ -1323,9 +1383,8 @@ bool BKE_lib_override_library_resync(Main *bmain, * sub-collections would be unaware that this is the same ID, and would re-generate several * overrides for it. * - * TODO: This is a sub-optimal, simple solution. At some point, we should rather find a way to - * resync a set of 'sub-roots' overrides, instead of having to 'go back' to the real root and - * resync the whole hierarchy. */ + * NOTE: Related to `lib_override_resync_tagging_finalize` above. + */ static ID *lib_override_library_main_resync_find_root_recurse(ID *id, int *level) { (*level)++; @@ -1414,6 +1473,7 @@ static void lib_override_library_main_resync_on_library_indirect_level( /* Now check existing overrides, those needing resync will be the one either already tagged as * such, or the one using linked data that is now tagged as needing override. */ + BKE_main_relations_tag_set(bmain, MAINIDRELATIONS_ENTRY_TAGS_PROCESSED, false); FOREACH_MAIN_ID_BEGIN (bmain, id) { if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) { continue; @@ -1421,16 +1481,7 @@ static void lib_override_library_main_resync_on_library_indirect_level( if (id->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC) { CLOG_INFO(&LOG, 4, "ID %s (%p) was already tagged as needing resync", id->name, id->lib); - if (id->lib != NULL && id->lib->temp_index > library_indirect_level) { - CLOG_ERROR( - &LOG, - "While processing indirect level %d, ID %s from lib %s of indirect level %d detected " - "as needing resync.", - library_indirect_level, - id->name, - id->lib ? id->lib->filepath : "<LOCAL>", - id->lib ? id->lib->temp_index : 0); - } + lib_override_resync_tagging_finalize_recurse(bmain, id, library_indirect_level); continue; } @@ -1455,18 +1506,9 @@ static void lib_override_library_main_resync_on_library_indirect_level( id->lib, id_to->name, id_to->lib); - if (id->lib != NULL && id->lib->temp_index > library_indirect_level) { - CLOG_ERROR(&LOG, - "While processing indirect level %d, ID %s from lib %s of indirect level %d " - "detected " - "as needing resync.", - library_indirect_level, - id->name, - id->lib ? id->lib->filepath : "<LOCAL>", - id->lib ? id->lib->temp_index : 0); - } - break; + lib_override_resync_tagging_finalize_recurse(bmain, id, library_indirect_level); } + break; } } FOREACH_MAIN_ID_END; |