From 84bee96757423ffed5a364cab7087ee5a50e8063 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 4 Jun 2025 17:46:48 +0200 Subject: [PATCH] Mesh: 5.0 changes for mask, custom normals, UV seam Complete the versioning and writing changes from these commits: - f9b627d29ca74e71c51c9406d50126e2be8a6ed3 - f2bcd73bd25625d6b5c1194a4199e96fc5fafa2e - c5ba8bd7c29ba0ce51eaa8d8829e6d9b68cba68c 4.5 has the forward compatibility handling to support reading files written by 5.0. This removes the conversion when writing files and removes the lookup of ".uv_seam" as a fallback for "uv_seam". Pull Request: https://projects.blender.org/blender/blender/pulls/139841 --- .../blender/blenkernel/BKE_blender_version.h | 2 +- .../blenkernel/BKE_mesh_legacy_convert.hh | 10 +-- source/blender/blenkernel/intern/mesh.cc | 54 --------------- .../blenkernel/intern/mesh_legacy_convert.cc | 42 ------------ .../blenloader/intern/versioning_450.cc | 58 ---------------- .../blenloader/intern/versioning_500.cc | 67 ++++++++++++++++++- .../blender/makesrna/intern/rna_attribute.cc | 11 --- 7 files changed, 69 insertions(+), 175 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index b8df0c99dc7..38033aeefb6 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,7 +27,7 @@ /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 0 +#define BLENDER_FILE_SUBVERSION 1 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and cancel loading the file, showing a warning to diff --git a/source/blender/blenkernel/BKE_mesh_legacy_convert.hh b/source/blender/blenkernel/BKE_mesh_legacy_convert.hh index 439134a89fd..af46feb0a3b 100644 --- a/source/blender/blenkernel/BKE_mesh_legacy_convert.hh +++ b/source/blender/blenkernel/BKE_mesh_legacy_convert.hh @@ -8,8 +8,6 @@ * \ingroup bke */ -#include "BLI_span.hh" - struct CustomData; struct Main; struct Mesh; @@ -18,10 +16,8 @@ struct CustomDataLayer; namespace blender::bke { -void mesh_custom_normals_to_legacy(MutableSpan corner_layers); void mesh_custom_normals_to_generic(Mesh &mesh); -void mesh_sculpt_mask_to_legacy(MutableSpan vert_layers); void mesh_sculpt_mask_to_generic(Mesh &mesh); } // namespace blender::bke @@ -129,9 +125,9 @@ void BKE_mesh_calc_edges_tessface(Mesh *mesh); /* NOTE(@sybren): Instead of -1 that function uses ORIGINDEX_NONE as defined in BKE_customdata.hh, * but I don't want to force every user of BKE_mesh.h to also include that file. */ -BLI_INLINE int BKE_mesh_origindex_mface_mpoly(const int *index_mf_to_mpoly, - const int *index_mp_to_orig, - const int i) +inline int BKE_mesh_origindex_mface_mpoly(const int *index_mf_to_mpoly, + const int *index_mp_to_orig, + const int i) { const int j = index_mf_to_mpoly[i]; return (j != -1) ? (index_mp_to_orig ? index_mp_to_orig[j] : j) : -1; diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 9bc14b79ddd..7be462f0299 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -284,53 +284,6 @@ static void mesh_foreach_path(ID *id, BPathForeachPathData *bpath_data) } } -static void rename_seam_layer_to_old_name(const ListBase vertex_groups, - const Span vert_layers, - MutableSpan edge_layers, - const Span face_layers, - const Span corner_layers) -{ - CustomDataLayer *seam_layer = nullptr; - for (CustomDataLayer &layer : edge_layers) { - if (STREQ(layer.name, ".uv_seam")) { - return; - } - if (layer.type == CD_PROP_BOOL && STREQ(layer.name, "uv_seam")) { - seam_layer = &layer; - } - } - - if (!seam_layer) { - return; - } - - /* Current files are not expected to have a ".uv_seam" attribute (the old name) except in the - * rare case users created it themselves. If that happens, avoid renaming the current UV seam - * attribute so that at least it's not hidden in the old version. */ - for (const CustomDataLayer &layer : vert_layers) { - if (STREQ(layer.name, ".uv_seam")) { - return; - } - } - for (const CustomDataLayer &layer : face_layers) { - if (STREQ(layer.name, ".uv_seam")) { - return; - } - } - for (const CustomDataLayer &layer : corner_layers) { - if (STREQ(layer.name, ".uv_seam")) { - return; - } - } - LISTBASE_FOREACH (const bDeformGroup *, vertex_group, &vertex_groups) { - if (STREQ(vertex_group->name, ".uv_seam")) { - return; - } - } - - STRNCPY(seam_layer->name, ".uv_seam"); -} - static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address) { using namespace blender; @@ -382,13 +335,6 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address mesh->corner_data, AttrDomain::Corner, mesh->corners_num, loop_layers, attribute_data); mesh->attribute_storage.dna_attributes = attribute_data.attributes.data(); mesh->attribute_storage.dna_attributes_num = attribute_data.attributes.size(); - if (!is_undo) { - /* Write forward compatible format. To be removed in 5.0. */ - rename_seam_layer_to_old_name( - mesh->vertex_group_names, vert_layers, edge_layers, face_layers, loop_layers); - mesh_sculpt_mask_to_legacy(vert_layers); - mesh_custom_normals_to_legacy(loop_layers); - } } const blender::bke::MeshRuntime *mesh_runtime = mesh->runtime; diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index a8a1f67a00b..3526799a3eb 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -2462,27 +2462,6 @@ void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain) namespace blender::bke { -void mesh_sculpt_mask_to_legacy(MutableSpan vert_layers) -{ - bool changed = false; - for (CustomDataLayer &layer : vert_layers) { - if (StringRef(layer.name) == ".sculpt_mask") { - layer.type = CD_PAINT_MASK; - layer.name[0] = '\0'; - changed = true; - break; - } - } - if (!changed) { - return; - } - /* #CustomData expects the layers to be sorted in increasing order based on type. */ - std::stable_sort( - vert_layers.begin(), - vert_layers.end(), - [](const CustomDataLayer &a, const CustomDataLayer &b) { return a.type < b.type; }); -} - void mesh_sculpt_mask_to_generic(Mesh &mesh) { if (mesh.attributes().contains(".sculpt_mask")) { @@ -2510,27 +2489,6 @@ void mesh_sculpt_mask_to_generic(Mesh &mesh) } } -void mesh_custom_normals_to_legacy(MutableSpan corner_layers) -{ - bool changed = false; - for (CustomDataLayer &layer : corner_layers) { - if (StringRef(layer.name) == "custom_normal" && layer.type == CD_PROP_INT16_2D) { - layer.type = CD_CUSTOMLOOPNORMAL; - layer.name[0] = '\0'; - changed = true; - break; - } - } - if (!changed) { - return; - } - /* #CustomData expects the layers to be sorted in increasing order based on type. */ - std::stable_sort( - corner_layers.begin(), - corner_layers.end(), - [](const CustomDataLayer &a, const CustomDataLayer &b) { return a.type < b.type; }); -} - void mesh_custom_normals_to_generic(Mesh &mesh) { if (mesh.attributes().contains("custom_normal")) { diff --git a/source/blender/blenloader/intern/versioning_450.cc b/source/blender/blenloader/intern/versioning_450.cc index 7ba0ed7d857..a05bdfac38e 100644 --- a/source/blender/blenloader/intern/versioning_450.cc +++ b/source/blender/blenloader/intern/versioning_450.cc @@ -4957,55 +4957,6 @@ void do_versions_after_linking_450(FileData * /*fd*/, Main *bmain) */ } -static CustomDataLayer *find_old_seam_layer(CustomData &custom_data, const blender::StringRef name) -{ - for (CustomDataLayer &layer : blender::MutableSpan(custom_data.layers, custom_data.totlayer)) { - if (layer.name == name) { - return &layer; - } - } - return nullptr; -} - -static void rename_mesh_uv_seam_attribute(Mesh &mesh) -{ - using namespace blender; - CustomDataLayer *old_seam_layer = find_old_seam_layer(mesh.edge_data, ".uv_seam"); - if (!old_seam_layer) { - return; - } - Set names; - for (const CustomDataLayer &layer : Span(mesh.vert_data.layers, mesh.vert_data.totlayer)) { - if (layer.type & CD_MASK_PROP_ALL) { - names.add(layer.name); - } - } - for (const CustomDataLayer &layer : Span(mesh.edge_data.layers, mesh.edge_data.totlayer)) { - if (layer.type & CD_MASK_PROP_ALL) { - names.add(layer.name); - } - } - for (const CustomDataLayer &layer : Span(mesh.face_data.layers, mesh.face_data.totlayer)) { - if (layer.type & CD_MASK_PROP_ALL) { - names.add(layer.name); - } - } - for (const CustomDataLayer &layer : Span(mesh.corner_data.layers, mesh.corner_data.totlayer)) { - if (layer.type & CD_MASK_PROP_ALL) { - names.add(layer.name); - } - } - LISTBASE_FOREACH (const bDeformGroup *, vertex_group, &mesh.vertex_group_names) { - names.add(vertex_group->name); - } - - /* If the new UV name is already taken, still rename the attribute so it becomes visible in the - * list. Then the user can deal with the name conflict themselves. */ - const std::string new_name = BLI_uniquename_cb( - [&](const StringRef name) { return names.contains(name); }, '.', "uv_seam"); - STRNCPY(old_seam_layer->name, new_name.c_str()); -} - static void do_version_node_curve_to_mesh_scale_input(bNodeTree *tree) { using namespace blender; @@ -6184,15 +6135,6 @@ void blo_do_versions_450(FileData * /*fd*/, Library * /*lib*/, Main *bmain) FOREACH_NODETREE_END; } - /* Always run this versioning (keep at the bottom of the function). Meshes are written with the - * legacy format which always needs to be converted to the new format on file load. To be moved - * to a subversion check in 5.0. */ - LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) { - blender::bke::mesh_sculpt_mask_to_generic(*mesh); - blender::bke::mesh_custom_normals_to_generic(*mesh); - rename_mesh_uv_seam_attribute(*mesh); - } - /** * Always bump subversion in BKE_blender_version.h when adding versioning * code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check. diff --git a/source/blender/blenloader/intern/versioning_500.cc b/source/blender/blenloader/intern/versioning_500.cc index 9d057619e73..56843be44f1 100644 --- a/source/blender/blenloader/intern/versioning_500.cc +++ b/source/blender/blenloader/intern/versioning_500.cc @@ -9,10 +9,15 @@ #define DNA_DEPRECATED_ALLOW #include "DNA_ID.h" +#include "DNA_mesh_types.h" -#include "BLI_sys_types.h" +#include "BLI_listbase.h" +#include "BLI_set.hh" +#include "BLI_string.h" +#include "BLI_string_utils.hh" #include "BKE_main.hh" +#include "BKE_mesh_legacy_convert.hh" #include "readfile.hh" @@ -21,6 +26,55 @@ // #include "CLG_log.h" // static CLG_LogRef LOG = {"blo.readfile.doversion"}; +static CustomDataLayer *find_old_seam_layer(CustomData &custom_data, const blender::StringRef name) +{ + for (CustomDataLayer &layer : blender::MutableSpan(custom_data.layers, custom_data.totlayer)) { + if (layer.name == name) { + return &layer; + } + } + return nullptr; +} + +static void rename_mesh_uv_seam_attribute(Mesh &mesh) +{ + using namespace blender; + CustomDataLayer *old_seam_layer = find_old_seam_layer(mesh.edge_data, ".uv_seam"); + if (!old_seam_layer) { + return; + } + Set names; + for (const CustomDataLayer &layer : Span(mesh.vert_data.layers, mesh.vert_data.totlayer)) { + if (layer.type & CD_MASK_PROP_ALL) { + names.add(layer.name); + } + } + for (const CustomDataLayer &layer : Span(mesh.edge_data.layers, mesh.edge_data.totlayer)) { + if (layer.type & CD_MASK_PROP_ALL) { + names.add(layer.name); + } + } + for (const CustomDataLayer &layer : Span(mesh.face_data.layers, mesh.face_data.totlayer)) { + if (layer.type & CD_MASK_PROP_ALL) { + names.add(layer.name); + } + } + for (const CustomDataLayer &layer : Span(mesh.corner_data.layers, mesh.corner_data.totlayer)) { + if (layer.type & CD_MASK_PROP_ALL) { + names.add(layer.name); + } + } + LISTBASE_FOREACH (const bDeformGroup *, vertex_group, &mesh.vertex_group_names) { + names.add(vertex_group->name); + } + + /* If the new UV name is already taken, still rename the attribute so it becomes visible in the + * list. Then the user can deal with the name conflict themselves. */ + const std::string new_name = BLI_uniquename_cb( + [&](const StringRef name) { return names.contains(name); }, '.', "uv_seam"); + STRNCPY(old_seam_layer->name, new_name.c_str()); +} + void do_versions_after_linking_500(FileData * /*fd*/, Main * /*bmain*/) { /** @@ -31,8 +85,17 @@ void do_versions_after_linking_500(FileData * /*fd*/, Main * /*bmain*/) */ } -void blo_do_versions_500(FileData * /*fd*/, Library * /*lib*/, Main * /*bmain*/) +void blo_do_versions_500(FileData * /*fd*/, Library * /*lib*/, Main *bmain) { + using namespace blender; + if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 1)) { + LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) { + bke::mesh_sculpt_mask_to_generic(*mesh); + bke::mesh_custom_normals_to_generic(*mesh); + rename_mesh_uv_seam_attribute(*mesh); + } + } + /** * Always bump subversion in BKE_blender_version.h when adding versioning * code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check. diff --git a/source/blender/makesrna/intern/rna_attribute.cc b/source/blender/makesrna/intern/rna_attribute.cc index b49655d0631..0bee0378ad7 100644 --- a/source/blender/makesrna/intern/rna_attribute.cc +++ b/source/blender/makesrna/intern/rna_attribute.cc @@ -653,17 +653,6 @@ bool rna_AttributeGroup_lookup_string(PointerRNA *ptr, const char *key, PointerR return true; } - /* Support retrieving UV seam name convention with older name. To be removed as part of 5.0 - * breaking changes. */ - if (STREQ(key, ".uv_seam")) { - if (CustomDataLayer *layer = BKE_attribute_search_for_write( - owner, "uv_seam", CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL)) - { - rna_pointer_create_with_ancestors(*ptr, &RNA_Attribute, layer, *r_ptr); - return true; - } - } - *r_ptr = PointerRNA_NULL; return false; }