From 7c9131d11eb01a70db440fac7bb3f4b3833d544a Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Wed, 7 Oct 2020 14:27:33 +0200 Subject: Refactor `BKE_id_copy_ex` to return the new ID pointer. Note that possibility to pass the new ID pointer as parameter was kept, as this is needed for some rather specific cases (like in depsgraph/COW, when copying into already allocated memory). Part of T71219. --- source/blender/blenkernel/intern/lib_id.c | 55 ++++++++++++++++++------------- 1 file changed, 32 insertions(+), 23 deletions(-) (limited to 'source/blender/blenkernel/intern/lib_id.c') diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index fd127f5871f..f69bada0fe8 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -530,51 +530,55 @@ bool BKE_id_copy_is_allowed(const ID *id) /** * Generic entry point for copying a data-block (new API). * - * \note Copy is only affecting given data-block + * \note Copy is generally only affecting the given data-block * (no ID used by copied one will be affected, besides usercount). - * There is only one exception, if #LIB_ID_COPY_ACTIONS is defined, - * actions used by animdata will be duplicated. + * There are exceptions though: + * - Embedded IDs (root node trees and master collections) are always copied with their owner. + * - If #LIB_ID_COPY_ACTIONS is defined, actions used by animdata will be duplicated. + * - If #LIB_ID_COPY_SHAPEKEY is defined, shapekeys will be duplicated. + * - If #LIB_ID_CREATE_LOCAL is defined, root node trees will be deep-duplicated recursively. * * \note Usercount of new copy is always set to 1. * * \param bmain: Main database, may be NULL only if LIB_ID_CREATE_NO_MAIN is specified. * \param id: Source data-block. - * \param r_newid: Pointer to new (copied) ID pointer. - * \param flag: Set of copy options, see DNA_ID.h enum for details - * (leave to zero for default, full copy). - * \return False when copying that ID type is not supported, true otherwise. + * \param r_newid: Pointer to new (copied) ID pointer, may be NULL. Used to allow copying into + * already allocated memory. + * \param flag: Set of copy options, see DNA_ID.h enum for details (leave to zero for default, + * full copy). + * \return NULL when copying that ID type is not supported, the new copy otherwise. */ -bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag) +ID *BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag) { - BLI_assert(r_newid != NULL); + ID *newid = (r_newid != NULL) ? *r_newid : NULL; /* Make sure destination pointer is all good. */ if ((flag & LIB_ID_CREATE_NO_ALLOCATE) == 0) { - *r_newid = NULL; + newid = NULL; } else { - if (*r_newid != NULL) { + if (newid != NULL) { /* Allow some garbage non-initialized memory to go in, and clean it up here. */ const size_t size = BKE_libblock_get_alloc_info(GS(id->name), NULL); - memset(*r_newid, 0, size); + memset(newid, 0, size); } } /* Early output is source is NULL. */ if (id == NULL) { - return false; + return NULL; } const IDTypeInfo *idtype_info = BKE_idtype_get_info_from_id(id); if (idtype_info != NULL) { if ((idtype_info->flags & IDTYPE_FLAGS_NO_COPY) != 0) { - return false; + return NULL; } - BKE_libblock_copy_ex(bmain, id, r_newid, flag); + BKE_libblock_copy_ex(bmain, id, &newid, flag); if (idtype_info->copy_data != NULL) { - idtype_info->copy_data(bmain, *r_newid, id, flag); + idtype_info->copy_data(bmain, newid, id, flag); } } else { @@ -584,22 +588,26 @@ bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag) /* Update ID refcount, remap pointers to self in new ID. */ struct IDCopyLibManagementData data = { .id_src = id, - .id_dst = *r_newid, + .id_dst = newid, .flag = flag, }; - BKE_library_foreach_ID_link(bmain, *r_newid, id_copy_libmanagement_cb, &data, IDWALK_NOP); + BKE_library_foreach_ID_link(bmain, newid, id_copy_libmanagement_cb, &data, IDWALK_NOP); /* Do not make new copy local in case we are copying outside of main... * XXX TODO: is this behavior OK, or should we need own flag to control that? */ if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) { BLI_assert((flag & LIB_ID_COPY_KEEP_LIB) == 0); - lib_id_copy_ensure_local(bmain, id, *r_newid); + lib_id_copy_ensure_local(bmain, id, newid); } else { - (*r_newid)->lib = id->lib; + newid->lib = id->lib; } - return true; + if (r_newid != NULL) { + *r_newid = newid; + } + + return newid; } /** @@ -608,7 +616,7 @@ bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag) */ bool BKE_id_copy(Main *bmain, const ID *id, ID **newid) { - return BKE_id_copy_ex(bmain, id, newid, LIB_ID_COPY_DEFAULT); + return (BKE_id_copy_ex(bmain, id, newid, LIB_ID_COPY_DEFAULT) != NULL); } /** @@ -729,7 +737,8 @@ bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop) if (RNA_property_editable(ptr, prop)) { Main *bmain = CTX_data_main(C); /* copy animation actions too */ - if (BKE_id_copy_ex(bmain, id, &newid, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS) && newid) { + newid = BKE_id_copy_ex(bmain, id, NULL, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS); + if (newid != NULL) { /* us is 1 by convention with new IDs, but RNA_property_pointer_set * will also increment it, decrement it here. */ id_us_min(newid); -- cgit v1.2.3