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:
Diffstat (limited to 'source/blender/blenkernel/intern/lib_id.c')
-rw-r--r--source/blender/blenkernel/intern/lib_id.c103
1 files changed, 64 insertions, 39 deletions
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index f8f171bd9d7..cf9fff811ce 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -24,7 +24,6 @@
* allocate and free of all library data
*/
-#include <assert.h>
#include <ctype.h>
#include <stddef.h>
#include <stdio.h>
@@ -102,6 +101,15 @@ IDTypeInfo IDType_ID_LINK_PLACEHOLDER = {
.copy_data = NULL,
.free_data = NULL,
.make_local = NULL,
+ .foreach_id = NULL,
+ .foreach_cache = NULL,
+
+ .blend_write = NULL,
+ .blend_read_data = NULL,
+ .blend_read_lib = NULL,
+ .blend_read_expand = NULL,
+
+ .blend_read_undo_preserve = NULL,
};
/* GS reads the memory pointed at in a specific ordering.
@@ -282,15 +290,15 @@ void id_us_min(ID *id)
const int limit = ID_FAKE_USERS(id);
if (id->us <= limit) {
- CLOG_ERROR(&LOG,
- "ID user decrement error: %s (from '%s'): %d <= %d",
- id->name,
- id->lib ? id->lib->filepath_abs : "[Main]",
- id->us,
- limit);
if (GS(id->name) != ID_IP) {
/* Do not assert on deprecated ID types, we cannot really ensure that their ID refcounting
* is valid... */
+ CLOG_ERROR(&LOG,
+ "ID user decrement error: %s (from '%s'): %d <= %d",
+ id->name,
+ id->lib ? id->lib->filepath_abs : "[Main]",
+ id->us,
+ limit);
BLI_assert(0);
}
id->us = limit;
@@ -415,11 +423,11 @@ void BKE_lib_id_make_local_generic(Main *bmain, ID *id, const int flags)
BKE_lib_id_expand_local(bmain, id);
}
else {
- ID *id_new;
+ ID *id_new = BKE_id_copy(bmain, id);
/* Should not fail in expected use cases,
* but a few ID types cannot be copied (LIB, WM, SCR...). */
- if (BKE_id_copy(bmain, id, &id_new)) {
+ if (id_new != NULL) {
id_new->us = 0;
/* setting newid is mandatory for complex make_lib_local logic... */
@@ -531,51 +539,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 {
@@ -585,31 +597,35 @@ 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;
}
/**
* Invokes the appropriate copy method for the block and returns the result in
* newid, unless test. Returns true if the block can be copied.
*/
-bool BKE_id_copy(Main *bmain, const ID *id, ID **newid)
+ID *BKE_id_copy(Main *bmain, const ID *id)
{
- return BKE_id_copy_ex(bmain, id, newid, LIB_ID_COPY_DEFAULT);
+ return BKE_id_copy_ex(bmain, id, NULL, LIB_ID_COPY_DEFAULT);
}
/**
@@ -627,8 +643,7 @@ ID *BKE_id_copy_for_duplicate(Main *bmain, ID *id, const eDupli_ID_Flags duplica
return id;
}
- ID *id_new;
- BKE_id_copy(bmain, id, &id_new);
+ ID *id_new = BKE_id_copy(bmain, id);
/* Copying add one user by default, need to get rid of that one. */
id_us_min(id_new);
ID_NEW_SET(id, id_new);
@@ -730,7 +745,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);
@@ -1036,6 +1052,8 @@ void *BKE_libblock_alloc_notest(short type)
void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int flag)
{
BLI_assert((flag & LIB_ID_CREATE_NO_ALLOCATE) == 0);
+ BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || bmain != NULL);
+ BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || (flag & LIB_ID_CREATE_LOCAL) == 0);
ID *id = BKE_libblock_alloc_notest(type);
@@ -1046,6 +1064,9 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int fl
if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) != 0) {
id->tag |= LIB_TAG_NO_USER_REFCOUNT;
}
+ if (flag & LIB_ID_CREATE_LOCAL) {
+ id->tag |= LIB_TAG_LOCALIZED;
+ }
id->icon_id = 0;
*((short *)id->name) = type;
@@ -1181,6 +1202,7 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int ori
BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || bmain != NULL);
BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || (flag & LIB_ID_CREATE_NO_ALLOCATE) == 0);
+ BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || (flag & LIB_ID_CREATE_LOCAL) == 0);
if (!is_private_id_data) {
/* When we are handling private ID data, we might still want to manage usercounts, even
* though that ID data-block is actually outside of Main... */
@@ -1309,7 +1331,7 @@ void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint)
BLI_remlink(lb, id);
/* Check if we can actually insert id before or after id_sorting_hint, if given. */
- if (id_sorting_hint != NULL && id_sorting_hint != id) {
+ if (!ELEM(id_sorting_hint, NULL, id)) {
BLI_assert(BLI_findindex(lb, id_sorting_hint) >= 0);
ID *id_sorting_hint_next = id_sorting_hint->next;
@@ -1547,7 +1569,7 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_
char base_name_test[MAX_ID_NAME - 2];
int number_test;
if ((id != id_test) && !ID_IS_LINKED(id_test) && (name[0] == id_test->name[2]) &&
- (id_test->name[base_name_len + 2] == '.' || id_test->name[base_name_len + 2] == '\0') &&
+ (ELEM(id_test->name[base_name_len + 2], '.', '\0')) &&
STREQLEN(name, id_test->name + 2, base_name_len) &&
(BLI_split_name_num(base_name_test, &number_test, id_test->name + 2, '.') ==
base_name_len)) {
@@ -1871,6 +1893,9 @@ void BKE_library_make_local(Main *bmain,
if (id->lib == NULL) {
id->tag &= ~(LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW);
id->flag &= ~LIB_INDIRECT_WEAK_LINK;
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ BKE_lib_override_library_free(&id->override_library, true);
+ }
}
/* The check on the fourth line (LIB_TAG_PRE_EXISTING) is done so it's possible to tag data
* you don't want to be made local, used for appending data,
@@ -2037,7 +2062,7 @@ void BKE_library_make_local(Main *bmain,
/* Proxies only work when the proxified object is linked-in from a library. */
if (ob->proxy->id.lib == NULL) {
CLOG_WARN(&LOG,
- "proxy object %s will loose its link to %s, because the "
+ "proxy object %s will lose its link to %s, because the "
"proxified object is local.",
id->newid->name,
ob->proxy->id.name);
@@ -2051,7 +2076,7 @@ void BKE_library_make_local(Main *bmain,
* was not used locally would be a nasty bug! */
if (is_local || is_lib) {
CLOG_WARN(&LOG,
- "made-local proxy object %s will loose its link to %s, "
+ "made-local proxy object %s will lose its link to %s, "
"because the linked-in proxy is referenced (is_local=%i, is_lib=%i).",
id->newid->name,
ob->proxy->id.name,