Mesh: Add versioning to convert old face maps to boolean attributes #113769

Merged
Hans Goudey merged 1 commits from HooglyBoogly/blender:face-maps-versioning-booleans into blender-v4.0-release 2023-10-17 09:17:17 +02:00
6 changed files with 68 additions and 11 deletions

View File

@ -29,7 +29,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 33
#define BLENDER_FILE_SUBVERSION 34
/* 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

View File

@ -72,7 +72,7 @@ void BKE_mesh_legacy_convert_polys_to_offsets(Mesh *mesh);
void BKE_mesh_legacy_convert_loops_to_corners(Mesh *mesh);
void BKE_mesh_legacy_face_map_to_generic(Mesh *mesh);
void BKE_mesh_legacy_face_map_to_generic(Main *bmain);
/**
* Recreate #MFace Tessellation.

View File

@ -16,11 +16,14 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "BLI_array_utils.hh"
#include "BLI_listbase.h"
#include "BLI_map.hh"
#include "BLI_math_geom.h"
#include "BLI_math_matrix.h"
#include "BLI_math_vector_types.hh"
#include "BLI_memarena.h"
#include "BLI_multi_value_map.hh"
#include "BLI_polyfill_2d.h"
#include "BLI_resource_scope.hh"
#include "BLI_string.h"
@ -30,6 +33,7 @@
#include "BKE_attribute.hh"
#include "BKE_customdata.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_mesh.hh"
#include "BKE_mesh_legacy_convert.hh"
#include "BKE_multires.hh"
@ -1345,18 +1349,18 @@ void BKE_mesh_legacy_face_set_to_generic(Mesh *mesh)
/** \name Face Map Conversion
* \{ */
void BKE_mesh_legacy_face_map_to_generic(Mesh *mesh)
static void move_face_map_data_to_attributes(Mesh *mesh)
{
using namespace blender;
if (mesh->attributes().contains("face_maps")) {
return;
}
void *data = nullptr;
int *data = nullptr;
const ImplicitSharingInfo *sharing_info = nullptr;
for (const int i : IndexRange(mesh->face_data.totlayer)) {
CustomDataLayer &layer = mesh->face_data.layers[i];
if (layer.type == CD_FACEMAP) {
data = layer.data;
data = static_cast<int *>(layer.data);
sharing_info = layer.sharing_info;
layer.data = nullptr;
layer.sharing_info = nullptr;
@ -1364,13 +1368,53 @@ void BKE_mesh_legacy_face_map_to_generic(Mesh *mesh)
break;
}
}
if (data != nullptr) {
CustomData_add_layer_named_with_data(
&mesh->face_data, CD_PROP_INT32, data, mesh->faces_num, "face_maps", sharing_info);
if (!data) {
return;
}
CustomData_add_layer_named_with_data(
&mesh->face_data, CD_PROP_INT32, data, mesh->faces_num, "face_maps", sharing_info);
if (sharing_info != nullptr) {
sharing_info->remove_user_and_delete_if_last();
}
MultiValueMap<int, int> groups;
for (const int i : IndexRange(mesh->faces_num)) {
if (data[i] == -1) {
/* -1 values "didn't have" a face map. */
continue;
}
groups.add(data[i], i);
}
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
for (const auto item : groups.items()) {
bke::SpanAttributeWriter<bool> attribute = attributes.lookup_or_add_for_write_span<bool>(
".temp_face_map_" + std::to_string(item.key), ATTR_DOMAIN_FACE);
if (attribute) {
attribute.span.fill_indices(item.value.as_span(), true);
attribute.finish();
}
}
}
void BKE_mesh_legacy_face_map_to_generic(Main *bmain)
{
LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
move_face_map_data_to_attributes(mesh);
}
LISTBASE_FOREACH (Object *, object, &bmain->objects) {
if (object->type != OB_MESH) {
continue;
}
Mesh *mesh = static_cast<Mesh *>(object->data);
int i;
LISTBASE_FOREACH_INDEX (bFaceMap *, face_map, &object->fmaps, i) {
mesh->attributes_for_write().rename(".temp_face_map_" + std::to_string(i), face_map->name);
}
BLI_freelistN(&object->fmaps);
}
}
/** \} */

View File

@ -707,6 +707,7 @@ static void object_blend_read_data(BlendDataReader *reader, ID *id)
/* Only for versioning, vertex group names are now stored on object data. */
BLO_read_list(reader, &ob->defbase);
BLO_read_list(reader, &ob->fmaps);
/* XXX deprecated - old animation system <<< */
direct_link_nlastrips(reader, &ob->nlastrips);

View File

@ -311,6 +311,10 @@ void do_versions_after_linking_400(FileData *fd, Main *bmain)
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 34)) {
BKE_mesh_legacy_face_map_to_generic(bmain);
}
/**
* Versioning code until next subversion bump goes here.
*
@ -1097,9 +1101,6 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 6)) {
LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
BKE_mesh_legacy_face_map_to_generic(mesh);
}
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
versioning_replace_legacy_glossy_node(ntree);
versioning_remove_microfacet_sharp_distribution(ntree);

View File

@ -60,6 +60,16 @@ typedef struct bDeformGroup {
char flag, _pad0[7];
} bDeformGroup;
#ifdef DNA_DEPRECATED_ALLOW
typedef struct bFaceMap {
struct bFaceMap *next, *prev;
/** MAX_VGROUP_NAME. */
char name[64];
char flag;
char _pad0[7];
} bFaceMap;
#endif
#define MAX_VGROUP_NAME 64
/** #bDeformGroup::flag */
@ -346,6 +356,7 @@ typedef struct Object {
ListBase constraintChannels DNA_DEPRECATED; /* XXX deprecated... old animation system */
ListBase effect DNA_DEPRECATED; /* XXX deprecated... keep for readfile */
ListBase defbase DNA_DEPRECATED; /* Only for versioning, moved to object data. */
ListBase fmaps DNA_DEPRECATED; /* For versioning, moved to generic attributes. */
/** List of ModifierData structures. */
ListBase modifiers;
/** List of GpencilModifierData structures. */