[Bf-blender-cvs] [9ac81ed6abf] master: Fix corrupted blend files after issues from new name_map code.

Bastien Montagne noreply at git.blender.org
Wed Jul 27 15:33:36 CEST 2022


Commit: 9ac81ed6abfbd431aafd75969f8590703ebe122f
Author: Bastien Montagne
Date:   Wed Jul 27 15:29:49 2022 +0200
Branches: master
https://developer.blender.org/rB9ac81ed6abfbd431aafd75969f8590703ebe122f

Fix corrupted blend files after issues from new name_map code.

Add a version of #BKE_main_namemap_validate that also fixes the issues,
and call it in a do_version to fix recent .blend files saved after the
regression introduced in rB7f8d05131a77.

This is mandatory to fix some production files here at the studio, among
other things.

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

M	source/blender/blenkernel/BKE_blender_version.h
M	source/blender/blenkernel/BKE_main_namemap.h
M	source/blender/blenkernel/intern/main_namemap.cc
M	source/blender/blenloader/intern/versioning_300.c

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

diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index efe44ec657b..8b924bfc71d 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -31,7 +31,7 @@ extern "C" {
  * version. Older Blender versions will test this and show a warning if the file
  * was written with too new a version. */
 #define BLENDER_FILE_MIN_VERSION 300
-#define BLENDER_FILE_MIN_SUBVERSION 43
+#define BLENDER_FILE_MIN_SUBVERSION 44
 
 /** User readable version string. */
 const char *BKE_blender_version_string(void);
diff --git a/source/blender/blenkernel/BKE_main_namemap.h b/source/blender/blenkernel/BKE_main_namemap.h
index c5fce803a03..d6f184b4b30 100644
--- a/source/blender/blenkernel/BKE_main_namemap.h
+++ b/source/blender/blenkernel/BKE_main_namemap.h
@@ -54,6 +54,13 @@ void BKE_main_namemap_remove_name(struct Main *bmain, struct ID *id, const char
  */
 bool BKE_main_namemap_validate(struct Main *bmain) ATTR_NONNULL();
 
+/** Same as #BKE_main_namemap_validate, but also fixes any issue by re-generating all name maps,
+ * and ensuring again all ID names are unique.
+ *
+ * This is typically only used in `do_versions` code to fix broken files.
+ */
+bool BKE_main_namemap_validate_and_fix(struct Main *bmain) ATTR_NONNULL();
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/blenkernel/intern/main_namemap.cc b/source/blender/blenkernel/intern/main_namemap.cc
index 3a7b325b3d2..a164633af09 100644
--- a/source/blender/blenkernel/intern/main_namemap.cc
+++ b/source/blender/blenkernel/intern/main_namemap.cc
@@ -5,6 +5,7 @@
  */
 
 #include "BKE_idtype.h"
+#include "BKE_lib_id.h"
 #include "BKE_main.h"
 #include "BKE_main_namemap.h"
 
@@ -382,43 +383,60 @@ struct Uniqueness_Key {
   }
 };
 
-bool BKE_main_namemap_validate(Main *bmain)
+static bool main_namemap_validate_and_fix(Main *bmain, const bool do_fix)
 {
   Set<Uniqueness_Key> id_names_libs;
   bool is_valid = true;
-  ID *id_iter;
-  FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
-    Uniqueness_Key key;
-    BLI_strncpy(key.name, id_iter->name, MAX_ID_NAME);
-    key.lib = id_iter->lib;
-    if (!id_names_libs.add(key)) {
-      is_valid = false;
-      CLOG_ERROR(&LOG,
-                 "ID name '%s' (from library '%s') is found more than once",
-                 id_iter->name,
-                 id_iter->lib != nullptr ? id_iter->lib->filepath : "<None>");
-    }
-
-    UniqueName_Map *name_map = get_namemap_for(bmain, id_iter, false);
-    if (name_map == nullptr) {
-      continue;
-    }
-    UniqueName_TypeMap *type_map = name_map->find_by_type(GS(id_iter->name));
-    BLI_assert(type_map != nullptr);
+  ListBase *lb_iter;
+  FOREACH_MAIN_LISTBASE_BEGIN (bmain, lb_iter) {
+    LISTBASE_FOREACH_MUTABLE (ID *, id_iter, lb_iter) {
+      Uniqueness_Key key;
+      BLI_strncpy(key.name, id_iter->name, MAX_ID_NAME);
+      key.lib = id_iter->lib;
+      if (!id_names_libs.add(key)) {
+        is_valid = false;
+        CLOG_ERROR(&LOG,
+                   "ID name '%s' (from library '%s') is found more than once",
+                   id_iter->name,
+                   id_iter->lib != nullptr ? id_iter->lib->filepath : "<None>");
+        if (do_fix) {
+          /* NOTE: this may imply moving this ID in its listbase, however re-checking it later is
+           * not really an issue. */
+          BKE_id_new_name_validate(
+              bmain, which_libbase(bmain, GS(id_iter->name)), id_iter, nullptr, true);
+          BLI_strncpy(key.name, id_iter->name, MAX_ID_NAME);
+          if (!id_names_libs.add(key)) {
+            CLOG_ERROR(&LOG,
+                       "\tID has been renamed to '%s', but it still seems to be already in use",
+                       id_iter->name);
+          }
+          else {
+            CLOG_WARN(&LOG, "\tID has been renamed to '%s'", id_iter->name);
+          }
+        }
+      }
 
-    UniqueName_Key key_namemap;
-    /* Remove full name from the set. */
-    BLI_strncpy(key_namemap.name, id_iter->name + 2, MAX_NAME);
-    if (!type_map->full_names.contains(key_namemap)) {
-      is_valid = false;
-      CLOG_ERROR(&LOG,
-                 "ID name '%s' (from library '%s') exists in current Main, but is not listed in "
-                 "the namemap",
-                 id_iter->name,
-                 id_iter->lib != nullptr ? id_iter->lib->filepath : "<None>");
+      UniqueName_Map *name_map = get_namemap_for(bmain, id_iter, false);
+      if (name_map == nullptr) {
+        continue;
+      }
+      UniqueName_TypeMap *type_map = name_map->find_by_type(GS(id_iter->name));
+      BLI_assert(type_map != nullptr);
+
+      UniqueName_Key key_namemap;
+      /* Remove full name from the set. */
+      BLI_strncpy(key_namemap.name, id_iter->name + 2, MAX_NAME);
+      if (!type_map->full_names.contains(key_namemap)) {
+        is_valid = false;
+        CLOG_ERROR(&LOG,
+                   "ID name '%s' (from library '%s') exists in current Main, but is not listed in "
+                   "the namemap",
+                   id_iter->name,
+                   id_iter->lib != nullptr ? id_iter->lib->filepath : "<None>");
+      }
     }
   }
-  FOREACH_MAIN_ID_END;
+  FOREACH_MAIN_LISTBASE_END;
 
   Library *lib = nullptr;
   UniqueName_Map *name_map = bmain->name_map;
@@ -450,5 +468,33 @@ bool BKE_main_namemap_validate(Main *bmain)
     name_map = (lib != nullptr) ? lib->runtime.name_map : nullptr;
   } while (lib != nullptr);
 
+  if (is_valid || !do_fix) {
+    return is_valid;
+  }
+
+  /* Clear all existing namemaps. */
+  lib = nullptr;
+  UniqueName_Map **name_map_p = &bmain->name_map;
+  do {
+    BLI_assert(name_map_p != nullptr);
+    if (*name_map_p != nullptr) {
+      BKE_main_namemap_destroy(name_map_p);
+    }
+    lib = static_cast<Library *>((lib == nullptr) ? bmain->libraries.first : lib->id.next);
+    name_map_p = (lib != nullptr) ? &lib->runtime.name_map : nullptr;
+  } while (lib != nullptr);
+
+  return is_valid;
+}
+
+bool BKE_main_namemap_validate_and_fix(Main *bmain)
+{
+  const bool is_valid = main_namemap_validate_and_fix(bmain, true);
+  BLI_assert(main_namemap_validate_and_fix(bmain, false));
   return is_valid;
 }
+
+bool BKE_main_namemap_validate(Main *bmain)
+{
+  return main_namemap_validate_and_fix(bmain, false);
+}
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index fa3789ea590..fd5f93c3e29 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -57,6 +57,7 @@
 #include "BKE_lib_id.h"
 #include "BKE_lib_override.h"
 #include "BKE_main.h"
+#include "BKE_main_namemap.h"
 #include "BKE_modifier.h"
 #include "BKE_node.h"
 #include "BKE_screen.h"
@@ -3285,18 +3286,8 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
       }
     }
   }
-  /**
-   * Versioning code until next subversion bump goes here.
-   *
-   * \note Be sure to check when bumping the version:
-   * - "versioning_userdef.c", #blo_do_versions_userdef
-   * - "versioning_userdef.c", #do_versions_theme
-   *
-   * \note Keep this message at the bottom of the function.
-   */
-  {
-    /* Keep this block, even when empty. */
 
+  if (!MAIN_VERSION_ATLEAST(bmain, 303, 44)) {
     /* Initialize brush curves sculpt settings. */
     LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
       if (brush->ob_mode != OB_MODE_SCULPT_CURVES) {
@@ -3312,5 +3303,20 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
         ob->dtx &= ~OB_DRAWBOUNDOX;
       }
     }
+
+    BKE_main_namemap_validate_and_fix(bmain);
+  }
+
+  /**
+   * Versioning code until next subversion bump goes here.
+   *
+   * \note Be sure to check when bumping the version:
+   * - "versioning_userdef.c", #blo_do_versions_userdef
+   * - "versioning_userdef.c", #do_versions_theme
+   *
+   * \note Keep this message at the bottom of the function.
+   */
+  {
+    /* Keep this block, even when empty. */
   }
 }



More information about the Bf-blender-cvs mailing list