diff options
-rw-r--r-- | source/blender/blenkernel/intern/lib_override.c | 14 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_ID.h | 4 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_access_compare_override.c | 39 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_rna.c | 17 |
4 files changed, 67 insertions, 7 deletions
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 95643773088..b9158697df9 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -909,6 +909,8 @@ bool BKE_lib_override_library_resync(Main *bmain, Scene *scene, ViewLayer *view_ ID *id_override_new = id->newid; ID *id_override_old = BLI_ghash_lookup(linkedref_to_old_override, id); + BLI_assert((id_override_new->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC) == 0); + if (id_override_old != NULL) { /* Swap the names between old override ID and new one. */ char id_name_buf[MAX_ID_NAME]; @@ -1920,6 +1922,14 @@ void BKE_lib_override_library_main_unused_cleanup(struct Main *bmain) FOREACH_MAIN_ID_END; } +static void lib_override_id_swap(Main *bmain, ID *id_local, ID *id_temp) +{ + BKE_lib_id_swap(bmain, id_local, id_temp); + /* We need to keep these tags from temp ID into orig one. + * ID swap does not swap most of ID data itself. */ + id_local->tag |= (id_temp->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC); +} + /** Update given override from its reference (re-applying overridden properties). */ void BKE_lib_override_library_update(Main *bmain, ID *local) { @@ -1988,11 +1998,11 @@ void BKE_lib_override_library_update(Main *bmain, ID *local) /* This also transfers all pointers (memory) owned by local to tmp_id, and vice-versa. * So when we'll free tmp_id, we'll actually free old, outdated data from local. */ - BKE_lib_id_swap(bmain, local, tmp_id); + lib_override_id_swap(bmain, local, tmp_id); if (local_key != NULL && tmp_key != NULL) { /* This is some kind of hard-coded 'always enforced override'. */ - BKE_lib_id_swap(bmain, &local_key->id, &tmp_key->id); + lib_override_id_swap(bmain, &local_key->id, &tmp_key->id); tmp_key->id.flag |= (local_key->id.flag & LIB_EMBEDDED_DATA_LIB_OVERRIDE); /* The swap of local and tmp_id inverted those pointers, we need to redefine proper * relationships. */ diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index c708219cfe8..077f9bf8bdc 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -572,6 +572,10 @@ enum { * When set #ID.session_uuid isn't initialized, since the data isn't part of the session. */ LIB_TAG_TEMP_MAIN = 1 << 20, + /** + * The data-block is a library override that needs re-sync to its linked reference. + */ + LIB_TAG_LIB_OVERRIDE_NEED_RESYNC = 1 << 21, }; /* Tag given ID for an update in all the dependency graphs. */ diff --git a/source/blender/makesrna/intern/rna_access_compare_override.c b/source/blender/makesrna/intern/rna_access_compare_override.c index 0f3b0a895db..6a8152d1139 100644 --- a/source/blender/makesrna/intern/rna_access_compare_override.c +++ b/source/blender/makesrna/intern/rna_access_compare_override.c @@ -61,7 +61,7 @@ static CLG_LogRef LOG = {"rna.access_compare_override"}; * Find the actual ID owner of the given \a ptr #PointerRNA, in override sense, and generate the * full rna path from it to given \a prop #PropertyRNA if \a rna_path is given. * - * \note this is slightly different than 'generic' RNA 'id owner' as returned by + * \note This is slightly different than 'generic' RNA 'id owner' as returned by * #RNA_find_real_ID_and_path, since in overrides we also consider shape keys as embedded data, not * only root node trees and master collections. */ @@ -104,10 +104,6 @@ static ID *rna_property_override_property_real_id_owner(Main *bmain, } } - if (!ID_IS_OVERRIDE_LIBRARY_REAL(owner_id)) { - return NULL; - } - if (r_rna_path == NULL) { return owner_id; } @@ -1158,6 +1154,39 @@ void RNA_struct_override_apply(Main *bmain, ptr_storage, op->rna_path, &data_storage, &prop_storage, &data_item_storage); } + /* Check if an overridden ID pointer supposed to be in sync with linked data gets out of + * sync. */ + if ((ptr_dst->owner_id->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC) == 0 && + op->rna_prop_type == PROP_POINTER && + (((IDOverrideLibraryPropertyOperation *)op->operations.first)->flag & + IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE) != 0) { + BLI_assert(ptr_src->owner_id == + rna_property_override_property_real_id_owner(bmain, &data_src, NULL, NULL)); + BLI_assert(ptr_dst->owner_id == + rna_property_override_property_real_id_owner(bmain, &data_dst, NULL, NULL)); + + PointerRNA prop_ptr_src = RNA_property_pointer_get(&data_src, prop_src); + PointerRNA prop_ptr_dst = RNA_property_pointer_get(&data_dst, prop_dst); + ID *id_src = rna_property_override_property_real_id_owner( + bmain, &prop_ptr_src, NULL, NULL); + ID *id_dst = rna_property_override_property_real_id_owner( + bmain, &prop_ptr_dst, NULL, NULL); + + BLI_assert(id_src == NULL || ID_IS_OVERRIDE_LIBRARY_REAL(id_src)); + + if (/* We might be in a case where id_dst has already been processed and its usages + * remapped to its new local override. In that case overrides and linked data are + * always properly matching. */ + id_src != id_dst && + /* If one of the pointers is NULL and not the other, or if linked reference ID of + * `id_src` is not `id_dst`, we are in a non-matching case. */ + (ELEM(NULL, id_src, id_dst) || id_src->override_library->reference != id_dst)) { + ptr_dst->owner_id->tag |= LIB_TAG_LIB_OVERRIDE_NEED_RESYNC; + CLOG_INFO( + &LOG, 3, "Local override %s detected as needing resync", ptr_dst->owner_id->name); + } + } + rna_property_override_apply_ex(bmain, &data_dst, &data_src, diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index d553ead1e45..d8336e79064 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -1238,6 +1238,8 @@ static bool rna_property_override_diff_propptr_validate_diffing(PointerRNA *prop /* Used for both Pointer and Collection properties. */ static int rna_property_override_diff_propptr(Main *bmain, + ID *owner_id_a, + ID *owner_id_b, PointerRNA *propptr_a, PointerRNA *propptr_b, eRNACompareMode mode, @@ -1359,6 +1361,17 @@ static int rna_property_override_diff_propptr(Main *bmain, * override is not matching its reference anymore. */ opop->flag &= ~IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE; } + else if ((owner_id_a->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC) != 0 || + (owner_id_b->tag & LIB_TAG_LIB_OVERRIDE_NEED_RESYNC) != 0) { + /* In case one of the owner of the checked property is tagged as needing resync, do + * not change the 'match reference' status of its ID pointer properties overrides, + * since many non-matching ones are likely due to missing resync. */ + printf( + "%s: Not checking matching ID pointer properties, since owner %s is tagged as " + "needing resync.\n", + __func__, + id_a->name); + } else if (id_a->override_library != NULL && id_a->override_library->reference == id_b) { opop->flag |= IDOVERRIDE_LIBRARY_FLAG_IDPOINTER_MATCH_REFERENCE; } @@ -1778,6 +1791,8 @@ int rna_property_override_diff_default(Main *bmain, PointerRNA propptr_a = RNA_property_pointer_get(ptr_a, rawprop_a); PointerRNA propptr_b = RNA_property_pointer_get(ptr_b, rawprop_b); return rna_property_override_diff_propptr(bmain, + ptr_a->owner_id, + ptr_b->owner_id, &propptr_a, &propptr_b, mode, @@ -1934,6 +1949,8 @@ int rna_property_override_diff_default(Main *bmain, else if (is_id || is_valid_for_diffing) { if (equals || do_create) { const int eq = rna_property_override_diff_propptr(bmain, + ptr_a->owner_id, + ptr_b->owner_id, &iter_a.ptr, &iter_b.ptr, mode, |