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 /source/blender/blenkernel
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.
Diffstat (limited to 'source/blender/blenkernel')
-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
3 files changed, 85 insertions, 32 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);
+}