[Bf-blender-cvs] [db15c9d1bd9] master: ID Management: Allow unique name check for linked IDs too.

Bastien Montagne noreply at git.blender.org
Tue Jun 1 12:30:57 CEST 2021


Commit: db15c9d1bd9dd85ef1db0df24f4ad56c0b2012fe
Author: Bastien Montagne
Date:   Tue Jun 1 11:39:28 2021 +0200
Branches: master
https://developer.blender.org/rBdb15c9d1bd9dd85ef1db0df24f4ad56c0b2012fe

ID Management: Allow unique name check for linked IDs too.

This is mandatory for liboverride resync, since this feature may imply
we have to create linked overrides in libraries, and there may be
several copies of those.

This is also a first step to a more general support of IDmanagement-editing
library data.

Note that this commit should have absolutely no effect on current code,
as the only function allowed to check unique names for linked IDs
currently is `BKE_libblock_management_main_add`, which is unused.

This commit also adds some basic testing for `BKE_id_new_name_validate`.

===================================================================

M	source/blender/blenkernel/BKE_lib_id.h
M	source/blender/blenkernel/intern/lib_id.c
M	source/blender/blenkernel/intern/lib_id_test.cc
M	source/blender/blenloader/intern/versioning_250.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h
index 7ac45ac4883..e16507bf3cc 100644
--- a/source/blender/blenkernel/BKE_lib_id.h
+++ b/source/blender/blenkernel/BKE_lib_id.h
@@ -258,8 +258,10 @@ void BKE_lib_id_swap_full(struct Main *bmain, struct ID *id_a, struct ID *id_b);
 void id_sort_by_name(struct ListBase *lb, struct ID *id, struct ID *id_sorting_hint);
 void BKE_lib_id_expand_local(struct Main *bmain, struct ID *id);
 
-bool BKE_id_new_name_validate(struct ListBase *lb, struct ID *id, const char *name)
-    ATTR_NONNULL(1, 2);
+bool BKE_id_new_name_validate(struct ListBase *lb,
+                              struct ID *id,
+                              const char *name,
+                              const bool do_linked_data) ATTR_NONNULL(1, 2);
 void BKE_lib_id_clear_library_data(struct Main *bmain, struct ID *id);
 
 /* Affect whole Main database. */
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index f93bf494ee9..8a6fb5b3e9e 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;
     }
   }
@@ -833,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;
@@ -989,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);
@@ -1092,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);
@@ -1557,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;
@@ -1613,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, '.') ==
@@ -1702,15 +1704,18 @@ 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 = false;
   char name[MAX_ID_NAME - 2];
 
-  /* If library, don't rename, but do ensure proper sorting. */
-  if (ID_IS_LINKED(id)) {
+  /* If library, don't rename (unless explicitely required), but do ensure proper sorting. */
+  if (!do_linked_data && ID_IS_LINKED(id)) {
     id_sort_by_name(lb, id, NULL);
 
     return result;
@@ -2195,7 +2200,7 @@ void BLI_libblock_ensure_unique_name(Main *bmain, const char *name)
   idtest = BLI_findstring(lb, name + 2, offsetof(ID, name) + 2);
   if (idtest != NULL) {
     /* 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;
   }
 }
@@ -2206,7 +2211,7 @@ void BLI_libblock_ensure_unique_name(Main *bmain, const char *name)
 void BKE_libblock_rename(Main *bmain, ID *id, const char *name)
 {
   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;
   }
 }
diff --git a/source/blender/blenkernel/intern/lib_id_test.cc b/source/blender/blenkernel/intern/lib_id_test.cc
index fbe4a15da1c..8e21ae88aa6 100644
--- a/source/blender/blenkernel/intern/lib_id_test.cc
+++ b/source/blender/blenkernel/intern/lib_id_test.cc
@@ -20,6 +20,7 @@
 #include "MEM_guardedalloc.h"
 
 #include "BLI_listbase.h"
+#include "BLI_string.h"
 
 #include "BKE_idtype.h"
 #include "BKE_lib_id.h"
@@ -110,4 +111,63 @@ TEST(lib_id_main_sort, linked_ids_1)
   test_lib_id_main_sort_free(&ctx);
 }
 
+TEST(lib_id_main_unique_name, local_ids_1)
+{
+  LibIDMainSortTestContext ctx = {nullptr};
+  test_lib_id_main_sort_init(&ctx);
+  EXPECT_TRUE(BLI_listbase_is_empty(&ctx.bmain->libraries));
+
+  ID *id_c = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_C"));
+  ID *id_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_A"));
+  ID *id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_B"));
+  test_lib_id_main_sort_check_order({id_a, id_b, id_c});
+
+  BLI_strncpy(id_c->name, id_a->name, sizeof(id_c->name));
+  BKE_id_new_name_validate(&ctx.bmain->objects, id_c, NULL, false);
+  EXPECT_TRUE(strcmp(id_c->name + 2, "OB_A.001") == 0);
+  EXPECT_TRUE(strcmp(id_a->name + 2, "OB_A") == 0);
+  EXPECT_TRUE(ctx.bmain->objects.first == id_a);
+  EXPECT_TRUE(ctx.bmain->objects.last == id_b);
+  test_lib_id_main_sort_check_order({id_a, id_c, id_b});
+
+  test_lib_id_main_sort_free(&ctx);
+}
+
+TEST(lib_id_main_unique_name, linked_ids_1)
+{
+  LibIDMainSortTestContext ctx = {nullptr};
+  test_lib_id_main_sort_init(&ctx);
+  EXPECT_TRUE(BLI_listbase_is_empty(&ctx.bmain->libraries));
+
+  Library *lib_a = static_cast<Library *>(BKE_id_new(ctx.bmain, ID_LI, "LI_A"));
+  Library *lib_b = static_cast<Library *>(BKE_id_new(ctx.bmain, ID_LI, "LI_B"));
+  ID *id_c = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_C"));
+  ID *id_a = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_A"));
+  ID *id_b = static_cast<ID *>(BKE_id_new(ctx.bmain, ID_OB, "OB_B"));
+
+  id_a->lib = lib_a;
+  id_sort_by_name(&ctx.bmain->objects, id_a, nullptr);
+  id_b->lib = lib_a;
+  id_sort_by_name(&ctx.bmain->objects, id_b, nullptr);
+  BLI_strncpy(id_b->name, id_a->name, sizeof(id_b->name));
+  BKE_id_new_name_validate(&ctx.bmain->objects, id_b, NULL, true);
+  EXPECT_TRUE(strcmp(id_b->name + 2, "OB_A.001") == 0);
+  EXPECT_TRUE(strcmp(id_a->name + 2, "OB_A") == 0);
+  EXPECT_TRUE(ctx.bmain->objects.first == id_c);
+  EXPECT_TRUE(ctx.bmain->objects.last == id_b);
+  test_lib_id_main_sort_check_order({id_c, id_a, id_b});
+
+  id_b->lib = lib_b;
+  id_sort_by_name(&ctx.bmain->objects, id_b, nullptr);
+  BLI_strncpy(id_b->name, id_a->name, sizeof(id_b->name));
+  BKE_id_new_name_validate(&ctx.bmain->objects, id_b, NULL, true);
+  EXPECT_TRUE(strcmp(id_b->name + 2, "OB_A") == 0);
+  EXPECT_TRUE(strcmp(id_a->name + 2, "OB_A") == 0);
+  EXPECT_TRUE(ctx.bmain->objects.first == id_c);
+  EXPECT_TRUE(ctx.bmain->objects.last == id_b);
+  test_lib_id_main_sort_check_order({id_c, id_a, id_b});
+
+  test_lib_id_main_sort_free(&ctx);
+}
+
 }  // namespace blender::bke::tests
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 6338dc95aba..990fc1d65d7 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -446,7 +446,7 @@ static void versions_gpencil_add_main(ListBase *lb, ID *id, const char *name)
   id->flag = LIB_FAKEUSER;
   *((short *)id->name) = ID_GD;
 
-  BKE_id_new_name_validate(lb, id, name);
+  BKE_id_new_name_validate(lb, id, name, false);
   /* alphabetic insertion: is in BKE_id_new_name_validate */
 
   if ((id->tag & LIB_TAG_TEMP_MAIN) == 0) {



More information about the Bf-blender-cvs mailing list