Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Montagne <bastien@blender.org>2020-10-07 15:27:33 +0300
committerBastien Montagne <bastien@blender.org>2020-10-07 19:05:06 +0300
commit7c9131d11eb01a70db440fac7bb3f4b3833d544a (patch)
treec7c495566a3f111c8c495f1daa207292bab9c43a /source/blender/blenkernel/intern/lib_id.c
parent1f50beb9f28edd2fe54d97647222ad6ee5808c1c (diff)
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.
Diffstat (limited to 'source/blender/blenkernel/intern/lib_id.c')
-rw-r--r--source/blender/blenkernel/intern/lib_id.c55
1 files changed, 32 insertions, 23 deletions
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);