Mesh: 5.0 changes for mask, custom normals, UV seam
Complete the versioning and writing changes from these commits: -f9b627d29c-f2bcd73bd2-c5ba8bd7c24.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
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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<CustomDataLayer> corner_layers);
|
||||
void mesh_custom_normals_to_generic(Mesh &mesh);
|
||||
|
||||
void mesh_sculpt_mask_to_legacy(MutableSpan<CustomDataLayer> 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;
|
||||
|
||||
@@ -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<CustomDataLayer> vert_layers,
|
||||
MutableSpan<CustomDataLayer> edge_layers,
|
||||
const Span<CustomDataLayer> face_layers,
|
||||
const Span<CustomDataLayer> 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;
|
||||
|
||||
@@ -2462,27 +2462,6 @@ void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain)
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
void mesh_sculpt_mask_to_legacy(MutableSpan<CustomDataLayer> 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<CustomDataLayer> 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")) {
|
||||
|
||||
@@ -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<StringRef> 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.
|
||||
|
||||
@@ -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<StringRef> 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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user