Fix #122623: Partial Resync fails to remap all ID pointers to existing unchanged overrides.
Regression from fb8bf8b0c8: Now that the 'automatic override' relationships between IDs are much more strict, re-creating sub-hierarchies of overrides as part of the partial resync may not be able to 'find' all previously used overrides anymore. An additional remapping from linked (reference) data to existing, unchanged 'old' overrides is needed. In the report case, the root of the partial resync is the Curve obdata itself, which will imply resync of its material. But the Armature object used as dependency of the material (through the driver target) has already been checked as not needing resync, so it is not included as part of this partial resync sub-hierarchy anymore. However, it means that the newly resync material override will have a pointer to the linked armature object, which then needs to be remapped to the matching existing (unchanged) override. NOTE: this likely means that too many override IDs are still being resynced currently. In the report-s case e.g., the Material ID likely does not need to be resynced either.
This commit is contained in:
parent
265a25ee42
commit
34d157634a
@ -1955,45 +1955,66 @@ void BKE_lib_override_library_main_hierarchy_root_ensure(Main *bmain)
|
||||
BKE_main_relations_free(bmain);
|
||||
}
|
||||
|
||||
static void lib_override_library_remap(Main *bmain,
|
||||
const ID *id_root_reference,
|
||||
GHash *linkedref_to_old_override)
|
||||
static void lib_override_library_remap(
|
||||
Main *bmain,
|
||||
const ID *id_root_reference,
|
||||
blender::Vector<std::pair<ID *, ID *>> &references_and_new_overrides,
|
||||
GHash *linkedref_to_old_override)
|
||||
{
|
||||
ID *id;
|
||||
id::IDRemapper remapper;
|
||||
id::IDRemapper remapper_overrides_old_to_new;
|
||||
blender::Vector<ID *> nomain_ids;
|
||||
blender::Vector<ID *> new_overrides;
|
||||
|
||||
FOREACH_MAIN_ID_BEGIN (bmain, id) {
|
||||
if (id->tag & LIB_TAG_DOIT && id->newid != nullptr && id->lib == id_root_reference->lib) {
|
||||
ID *id_override_new = id->newid;
|
||||
ID *id_override_old = static_cast<ID *>(BLI_ghash_lookup(linkedref_to_old_override, id));
|
||||
if (id_override_old == nullptr) {
|
||||
continue;
|
||||
}
|
||||
remapper.add(id_override_old, id_override_new);
|
||||
}
|
||||
}
|
||||
FOREACH_MAIN_ID_END;
|
||||
/* Used to ensure that newly created overrides have all of their 'linked id' pointers remapped to
|
||||
* the matching override if it exists. Necessary because in partial resync case, some existing
|
||||
* liboverride may be used by the resynced ones, yet they would not be part of the resynced
|
||||
* partial hierarchy, so #BKE_lib_override_library_create_from_tag cannot find them and handle
|
||||
* their remapping. */
|
||||
id::IDRemapper remapper_overrides_reference_to_old;
|
||||
|
||||
/* Remap no-main override IDs we just created too. */
|
||||
GHashIterator linkedref_to_old_override_iter;
|
||||
GHASH_ITER (linkedref_to_old_override_iter, linkedref_to_old_override) {
|
||||
ID *id_override_old_iter = static_cast<ID *>(
|
||||
BLI_ghashIterator_getValue(&linkedref_to_old_override_iter));
|
||||
if ((id_override_old_iter->tag & LIB_TAG_NO_MAIN) == 0) {
|
||||
/* Add remapping from old to new overrides. */
|
||||
for (auto [id_reference, id_override_new] : references_and_new_overrides) {
|
||||
new_overrides.append(id_override_new);
|
||||
ID *id_override_old = static_cast<ID *>(
|
||||
BLI_ghash_lookup(linkedref_to_old_override, id_reference));
|
||||
if (id_override_old == nullptr) {
|
||||
continue;
|
||||
}
|
||||
remapper_overrides_old_to_new.add(id_override_old, id_override_new);
|
||||
}
|
||||
|
||||
nomain_ids.append(id_override_old_iter);
|
||||
GHashIterator linkedref_to_old_override_iter;
|
||||
GHASH_ITER (linkedref_to_old_override_iter, linkedref_to_old_override) {
|
||||
/* Remap no-main override IDs we just created too. */
|
||||
ID *id_override_old_iter = static_cast<ID *>(
|
||||
BLI_ghashIterator_getValue(&linkedref_to_old_override_iter));
|
||||
if ((id_override_old_iter->tag & LIB_TAG_NO_MAIN) != 0) {
|
||||
nomain_ids.append(id_override_old_iter);
|
||||
}
|
||||
/* And remap linked data to old (existing, unchanged) overrides, when no new one was created.
|
||||
*/
|
||||
ID *id_reference_iter = static_cast<ID *>(
|
||||
BLI_ghashIterator_getKey(&linkedref_to_old_override_iter));
|
||||
BLI_assert(id_reference_iter->lib == id_root_reference->lib);
|
||||
UNUSED_VARS_NDEBUG(id_root_reference);
|
||||
if (!id_reference_iter->newid) {
|
||||
remapper_overrides_reference_to_old.add(id_reference_iter, id_override_old_iter);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remap all IDs to use the new override. */
|
||||
BKE_libblock_remap_multiple(bmain, remapper, 0);
|
||||
BKE_libblock_remap_multiple(bmain, remapper_overrides_old_to_new, 0);
|
||||
BKE_libblock_relink_multiple(bmain,
|
||||
nomain_ids,
|
||||
ID_REMAP_TYPE_REMAP,
|
||||
remapper,
|
||||
remapper_overrides_old_to_new,
|
||||
ID_REMAP_FORCE_USER_REFCOUNT | ID_REMAP_FORCE_NEVER_NULL_USAGE);
|
||||
/* In new overrides, remap linked ID to their matching already existing overrides. */
|
||||
BKE_libblock_relink_multiple(bmain,
|
||||
new_overrides,
|
||||
ID_REMAP_TYPE_REMAP,
|
||||
remapper_overrides_reference_to_old,
|
||||
ID_REMAP_SKIP_OVERRIDE_LIBRARY);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2312,6 +2333,8 @@ static bool lib_override_library_resync(Main *bmain,
|
||||
* liboverrides' for newly created ones that do not already have one, in next step. */
|
||||
LibOverrideMissingIDsData missing_ids_data = lib_override_library_resync_build_missing_ids_data(
|
||||
bmain);
|
||||
/* Vector of pairs of reference IDs, and their new override IDs. */
|
||||
blender::Vector<std::pair<ID *, ID *>> references_and_new_overrides;
|
||||
|
||||
ListBase *lb;
|
||||
FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb) {
|
||||
@ -2323,6 +2346,8 @@ static bool lib_override_library_resync(Main *bmain,
|
||||
continue;
|
||||
}
|
||||
ID *id_override_new = id_reference_iter->newid;
|
||||
references_and_new_overrides.append(std::make_pair(id_reference_iter, id_override_new));
|
||||
|
||||
ID *id_override_old = static_cast<ID *>(
|
||||
BLI_ghash_lookup(linkedref_to_old_override, id_reference_iter));
|
||||
|
||||
@ -2412,9 +2437,16 @@ static bool lib_override_library_resync(Main *bmain,
|
||||
}
|
||||
FOREACH_MAIN_LISTBASE_END;
|
||||
|
||||
/* We remap old to new override usages in a separate loop, after all new overrides have
|
||||
* been added to Main. */
|
||||
lib_override_library_remap(bmain, id_root_reference, linkedref_to_old_override);
|
||||
/* We remap old to new override usages in a separate step, after all new overrides have
|
||||
* been added to Main.
|
||||
*
|
||||
* This function also ensures that newly created overrides get all their linked ID pointers
|
||||
* remapped to a valid override one, whether new or already existing. In partial resync case,
|
||||
* #BKE_lib_override_library_create_from_tag cannot reliably discover _all_ valid existing
|
||||
* overrides used by the newly resynced ones, since the local resynced hierarchy may not contain
|
||||
* them. */
|
||||
lib_override_library_remap(
|
||||
bmain, id_root_reference, references_and_new_overrides, linkedref_to_old_override);
|
||||
|
||||
BKE_main_collection_sync(bmain);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user