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.c120
1 files changed, 77 insertions, 43 deletions
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index af921307bfb..f26b85338f0 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -164,7 +164,7 @@ static void lib_id_clear_library_data_ex(Main *bmain, ID *id)
id->tag &= ~(LIB_TAG_INDIRECT | LIB_TAG_EXTERN);
id->flag &= ~LIB_INDIRECT_WEAK_LINK;
if (id_in_mainlist) {
- if (BKE_id_new_name_validate(which_libbase(bmain, GS(id->name)), id, NULL)) {
+ if (BKE_id_new_name_validate(which_libbase(bmain, GS(id->name)), id, NULL, false)) {
bmain->is_memfile_undo_written = false;
}
}
@@ -525,7 +525,13 @@ static int id_copy_libmanagement_cb(LibraryIDLinkCallbackData *cb_data)
/* Increase used IDs refcount if needed and required. */
if ((data->flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0 && (cb_flag & IDWALK_CB_USER)) {
- id_us_plus(id);
+ if ((data->flag & LIB_ID_CREATE_NO_MAIN) != 0) {
+ BLI_assert(cb_data->id_self->tag & LIB_TAG_NO_MAIN);
+ id_us_plus_no_lib(id);
+ }
+ else {
+ id_us_plus(id);
+ }
}
return IDWALK_RET_NOP;
@@ -578,7 +584,7 @@ ID *BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag)
}
}
- /* Early output is source is NULL. */
+ /* Early output if source is NULL. */
if (id == NULL) {
return NULL;
}
@@ -827,7 +833,9 @@ void BKE_libblock_management_main_add(Main *bmain, void *idv)
ListBase *lb = which_libbase(bmain, GS(id->name));
BKE_main_lock(bmain);
BLI_addtail(lb, id);
- BKE_id_new_name_validate(lb, id, NULL);
+ /* We need to allow adding extra datablocks into libraries too, e.g. to support generating new
+ * overrides for recursive resync. */
+ BKE_id_new_name_validate(lb, id, NULL, true);
/* alphabetic insertion: is in new_id */
id->tag &= ~(LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT);
bmain->is_memfile_undo_written = false;
@@ -983,7 +991,7 @@ void BKE_main_id_repair_duplicate_names_listbase(ListBase *lb)
}
for (i = 0; i < lb_len; i++) {
if (!BLI_gset_add(gset, id_array[i]->name + 2)) {
- BKE_id_new_name_validate(lb, id_array[i], NULL);
+ BKE_id_new_name_validate(lb, id_array[i], NULL, false);
}
}
BLI_gset_free(gset, NULL);
@@ -1086,7 +1094,7 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int fl
BKE_main_lock(bmain);
BLI_addtail(lb, id);
- BKE_id_new_name_validate(lb, id, name);
+ BKE_id_new_name_validate(lb, id, name, false);
bmain->is_memfile_undo_written = false;
/* alphabetic insertion: is in new_id */
BKE_main_unlock(bmain);
@@ -1215,14 +1223,6 @@ 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... */
- BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) == 0 ||
- (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) != 0);
- }
- /* Never implicitly copy shapekeys when generating temp data outside of Main database. */
- BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) == 0 || (flag & LIB_ID_COPY_SHAPEKEY) == 0);
/* 'Private ID' data handling. */
if ((bmain != NULL) && is_private_id_data) {
@@ -1245,6 +1245,13 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int ori
}
BLI_assert(new_id != NULL);
+ if ((flag & LIB_ID_COPY_SET_COPIED_ON_WRITE) != 0) {
+ new_id->tag |= LIB_TAG_COPIED_ON_WRITE;
+ }
+ else {
+ new_id->tag &= ~LIB_TAG_COPIED_ON_WRITE;
+ }
+
const size_t id_len = BKE_libblock_get_alloc_info(GS(new_id->name), NULL);
const size_t id_offset = sizeof(ID);
if ((int)id_len - (int)id_offset > 0) { /* signed to allow neg result */ /* XXX ????? */
@@ -1264,9 +1271,7 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int ori
new_id->properties = IDP_CopyProperty_ex(id->properties, copy_data_flag);
}
- /* We may need our own flag to control that at some point, but for now 'no main' one should be
- * good enough. */
- if ((orig_flag & LIB_ID_CREATE_NO_MAIN) == 0) {
+ if ((orig_flag & LIB_ID_COPY_NO_LIB_OVERRIDE) == 0) {
if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
/* We do not want to copy existing override rules here, as they would break the proper
* remapping between IDs. Proper overrides rules will be re-generated anyway. */
@@ -1350,12 +1355,12 @@ 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 (!ELEM(id_sorting_hint, NULL, id)) {
+ if (!ELEM(id_sorting_hint, NULL, id) && id_sorting_hint->lib == id->lib) {
BLI_assert(BLI_findindex(lb, id_sorting_hint) >= 0);
ID *id_sorting_hint_next = id_sorting_hint->next;
if (BLI_strcasecmp(id_sorting_hint->name, id->name) < 0 &&
- (id_sorting_hint_next == NULL ||
+ (id_sorting_hint_next == NULL || id_sorting_hint_next->lib != id->lib ||
BLI_strcasecmp(id_sorting_hint_next->name, id->name) > 0)) {
BLI_insertlinkafter(lb, id_sorting_hint, id);
return;
@@ -1363,7 +1368,7 @@ void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint)
ID *id_sorting_hint_prev = id_sorting_hint->prev;
if (BLI_strcasecmp(id_sorting_hint->name, id->name) > 0 &&
- (id_sorting_hint_prev == NULL ||
+ (id_sorting_hint_prev == NULL || id_sorting_hint_prev->lib != id->lib ||
BLI_strcasecmp(id_sorting_hint_prev->name, id->name) < 0)) {
BLI_insertlinkbefore(lb, id_sorting_hint, id);
return;
@@ -1378,16 +1383,33 @@ void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint)
/* Note: We start from the end, because in typical 'heavy' case (insertion of lots of IDs at
* once using the same base name), newly inserted items will generally be towards the end
* (higher extension numbers). */
- for (idtest = lb->last, item_array_index = ID_SORT_STEP_SIZE - 1; idtest != NULL;
- idtest = idtest->prev, item_array_index--) {
+ bool is_in_library = false;
+ item_array_index = ID_SORT_STEP_SIZE - 1;
+ for (idtest = lb->last; idtest != NULL; idtest = idtest->prev) {
+ if (is_in_library) {
+ if (idtest->lib != id->lib) {
+ /* We got out of expected library 'range' in the list, so we are done here and can move on
+ * to the next step. */
+ break;
+ }
+ }
+ else if (idtest->lib == id->lib) {
+ /* We are entering the expected library 'range' of IDs in the list. */
+ is_in_library = true;
+ }
+
+ if (!is_in_library) {
+ continue;
+ }
+
item_array[item_array_index] = idtest;
if (item_array_index == 0) {
- if ((idtest->lib == NULL && id->lib != NULL) ||
- BLI_strcasecmp(idtest->name, id->name) <= 0) {
+ if (BLI_strcasecmp(idtest->name, id->name) <= 0) {
break;
}
item_array_index = ID_SORT_STEP_SIZE;
}
+ item_array_index--;
}
/* Step two: we go forward in the selected chunk of items and check all of them, as we know
@@ -1399,7 +1421,7 @@ void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint)
* So we can increment that index in any case. */
for (item_array_index++; item_array_index < ID_SORT_STEP_SIZE; item_array_index++) {
idtest = item_array[item_array_index];
- if ((idtest->lib != NULL && id->lib == NULL) || BLI_strcasecmp(idtest->name, id->name) > 0) {
+ if (BLI_strcasecmp(idtest->name, id->name) > 0) {
BLI_insertlinkbefore(lb, idtest, id);
break;
}
@@ -1407,12 +1429,18 @@ void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint)
if (item_array_index == ID_SORT_STEP_SIZE) {
if (idtest == NULL) {
/* If idtest is NULL here, it means that in the first loop, the last comparison was
- * performed exactly on the first item of the list, and that it also failed. In other
- * words, all items in the list are greater than inserted one, so we can put it at the
- * start of the list. */
- /* Note that BLI_insertlinkafter() would have same behavior in that case, but better be
- * explicit here. */
- BLI_addhead(lb, id);
+ * performed exactly on the first item of the list, and that it also failed. And that the
+ * second loop was not walked at all.
+ *
+ * In other words, if `id` is local, all the items in the list are greater than the inserted
+ * one, so we can put it at the start of the list. Or, if `id` is linked, it is the first one
+ * of its library, and we can put it at the very end of the list. */
+ if (ID_IS_LINKED(id)) {
+ BLI_addtail(lb, id);
+ }
+ else {
+ BLI_addhead(lb, id);
+ }
}
else {
BLI_insertlinkafter(lb, idtest, id);
@@ -1531,7 +1559,7 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_
* and that current one is not. */
bool is_valid = false;
for (id_test = lb->first; id_test; id_test = id_test->next) {
- if (id != id_test && !ID_IS_LINKED(id_test)) {
+ if (id != id_test && id_test->lib == id->lib) {
if (id_test->name[2] == final_name[0] && STREQ(final_name, id_test->name + 2)) {
/* We expect final_name to not be already used, so this is a failure. */
is_valid = false;
@@ -1587,7 +1615,7 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_
for (id_test = lb->first; id_test; id_test = id_test->next) {
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]) &&
+ if ((id != id_test) && (id_test->lib == id->lib) && (name[0] == id_test->name[2]) &&
(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, '.') ==
@@ -1676,16 +1704,21 @@ static bool check_for_dupid(ListBase *lb, ID *id, char *name, ID **r_id_sorting_
*
* Only for local IDs (linked ones already have a unique ID in their library).
*
+ * \param do_linked_data if true, also ensure a unique name in case the given \a id is linked
+ * (otherwise, just ensure that it is properly sorted).
+ *
* \return true if a new name had to be created.
*/
-bool BKE_id_new_name_validate(ListBase *lb, ID *id, const char *tname)
+bool BKE_id_new_name_validate(ListBase *lb, ID *id, const char *tname, const bool do_linked_data)
{
- bool result;
+ bool result = false;
char name[MAX_ID_NAME - 2];
- /* if library, don't rename */
- if (ID_IS_LINKED(id)) {
- return false;
+ /* If library, don't rename (unless explicitly required), but do ensure proper sorting. */
+ if (!do_linked_data && ID_IS_LINKED(id)) {
+ id_sort_by_name(lb, id, NULL);
+
+ return result;
}
/* if no name given, use name of current ID
@@ -1726,7 +1759,7 @@ bool BKE_id_new_name_validate(ListBase *lb, ID *id, const char *tname)
}
/* next to indirect usage in read/writefile also in editobject.c scene.c */
-void BKE_main_id_clear_newpoins(Main *bmain)
+void BKE_main_id_newptr_and_tag_clear(Main *bmain)
{
ID *id;
@@ -2140,7 +2173,7 @@ void BKE_library_make_local(Main *bmain,
TIMEIT_VALUE_PRINT(make_local);
#endif
- BKE_main_id_clear_newpoins(bmain);
+ BKE_main_id_newptr_and_tag_clear(bmain);
BLI_memarena_free(linklist_mem);
#ifdef DEBUG_TIME
@@ -2165,9 +2198,9 @@ void BLI_libblock_ensure_unique_name(Main *bmain, const char *name)
/* search for id */
idtest = BLI_findstring(lb, name + 2, offsetof(ID, name) + 2);
- if (idtest != NULL) {
+ if (idtest != NULL && !ID_IS_LINKED(idtest)) {
/* BKE_id_new_name_validate also takes care of sorting. */
- BKE_id_new_name_validate(lb, idtest, NULL);
+ BKE_id_new_name_validate(lb, idtest, NULL, false);
bmain->is_memfile_undo_written = false;
}
}
@@ -2177,8 +2210,9 @@ void BLI_libblock_ensure_unique_name(Main *bmain, const char *name)
*/
void BKE_libblock_rename(Main *bmain, ID *id, const char *name)
{
+ BLI_assert(!ID_IS_LINKED(id));
ListBase *lb = which_libbase(bmain, GS(id->name));
- if (BKE_id_new_name_validate(lb, id, name)) {
+ if (BKE_id_new_name_validate(lb, id, name, false)) {
bmain->is_memfile_undo_written = false;
}
}