diff options
Diffstat (limited to 'source/blender/blenkernel/intern/lib_id.c')
-rw-r--r-- | source/blender/blenkernel/intern/lib_id.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 3778e308db6..5a394a05d86 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -59,6 +59,7 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_query.h" #include "RNA_access.h" @@ -708,6 +709,58 @@ ID *BKE_id_copy_for_duplicate(Main *bmain, return id->newid; } +static int foreach_assign_id_to_orig_callback(LibraryIDLinkCallbackData *cb_data) +{ + ID **id_p = cb_data->id_pointer; + + if (*id_p) { + ID *id = *id_p; + *id_p = DEG_get_original_id(id); + + /* If the ID changes increase the user count. + * + * This means that the reference to evaluated ID has been changed with a reference to the + * original ID which implies that the user count of the original ID is increased. + * + * The evaluated IDs do not maintain their user counter, so do not change it to avoid issues + * with the user counter going negative. */ + if (*id_p != id) { + if ((cb_data->cb_flag & IDWALK_CB_USER) != 0) { + id_us_plus(*id_p); + } + } + } + + return IDWALK_RET_NOP; +} + +ID *BKE_id_copy_for_use_in_bmain(Main *bmain, const ID *id) +{ + ID *newid = BKE_id_copy(bmain, id); + + if (newid == NULL) { + return newid; + } + + /* Assign ID references directly used by the given ID to their original complementary parts. + * + * For example, when is called on an evaluated object will assign object->data to its original + * pointer, the evaluated object->data will be kept unchanged. */ + BKE_library_foreach_ID_link(NULL, newid, foreach_assign_id_to_orig_callback, NULL, IDWALK_NOP); + + /* Shape keys reference on evaluated ID is preserved to keep driver paths available, but the key + * data is likely to be invalid now due to modifiers, so clear the shape key reference avoiding + * any possible shape corruption. */ + if (DEG_is_evaluated_id(id)) { + Key **key_p = BKE_key_from_id_p(newid); + if (key_p) { + *key_p = NULL; + } + } + + return newid; +} + /** * Does a mere memory swap over the whole IDs data (including type-specific memory). * \note Most internal ID data itself is not swapped (only IDProperties are). |