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>2022-07-27 16:29:49 +0300
committerBastien Montagne <bastien@blender.org>2022-07-27 16:33:29 +0300
commit9ac81ed6abfbd431aafd75969f8590703ebe122f (patch)
tree1e9d5abaa12992127dfe6048b9a15220821fed89
parent9f53272df461ef040aed422e7fdbdaf390e23341 (diff)
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.
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_main_namemap.h7
-rw-r--r--source/blender/blenkernel/intern/main_namemap.cc108
-rw-r--r--source/blender/blenloader/intern/versioning_300.c28
4 files changed, 102 insertions, 43 deletions
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. */
}
}