Fix #113386: separating by loose parts removes attribute data

The issue was that custom data layers were modified without checking
that the data was not shared. Now the data is unshared first.

I also added an assert to catches this kind of issue more directly.
This commit is contained in:
Jacques Lucke 2023-10-11 11:34:29 +02:00
parent 1242512ff2
commit 535d211c94
3 changed files with 25 additions and 1 deletions

View File

@ -379,7 +379,8 @@ void CustomData_copy_layer_type_data(const struct CustomData *source,
int count);
/**
* Frees data in a #CustomData object.
* Frees data in a #CustomData object. This is only expected to be called if the data layers are
* not shared (#CustomData_ensure_layers_are_mutable).
*/
void CustomData_free_elem(struct CustomData *data, int index, int count);
@ -434,6 +435,7 @@ void CustomData_swap_corners(struct CustomData *data, int index, const int *corn
* function makes sure that the layer is unshared if it was shared, which makes it mutable.
*/
void CustomData_ensure_data_is_mutable(struct CustomDataLayer *layer, int totelem);
void CustomData_ensure_layers_are_mutable(struct CustomData *data, int totelem);
/**
* Retrieve a pointer to an element of the active layer of the given \a type, chosen by the

View File

@ -2414,11 +2414,26 @@ static void ensure_layer_data_is_mutable(CustomDataLayer &layer, const int totel
}
}
static bool layer_is_mutable(CustomDataLayer &layer)
{
if (layer.sharing_info == nullptr) {
return true;
}
return layer.sharing_info->is_mutable();
}
void CustomData_ensure_data_is_mutable(CustomDataLayer *layer, const int totelem)
{
ensure_layer_data_is_mutable(*layer, totelem);
}
void CustomData_ensure_layers_are_mutable(struct CustomData *data, int totelem)
{
for (const int i : IndexRange(data->totlayer)) {
ensure_layer_data_is_mutable(data->layers[i], totelem);
}
}
void CustomData_realloc(CustomData *data, const int old_size, const int new_size)
{
BLI_assert(new_size >= 0);
@ -3292,6 +3307,8 @@ void CustomData_copy_data_layer(const CustomData *source,
{
const LayerTypeInfo *typeInfo;
BLI_assert(layer_is_mutable(dest->layers[dst_layer_index]));
const void *src_data = source->layers[src_layer_index].data;
void *dst_data = dest->layers[dst_layer_index].data;
@ -3407,6 +3424,7 @@ void CustomData_free_elem(CustomData *data, const int index, const int count)
if (typeInfo->free) {
size_t offset = size_t(index) * typeInfo->size;
BLI_assert(layer_is_mutable(data->layers[i]));
typeInfo->free(POINTER_OFFSET(data->layers[i].data, offset), count, typeInfo->size);
}

View File

@ -997,6 +997,7 @@ static void mesh_remove_verts(Mesh *mesh, int len)
if (len == 0) {
return;
}
CustomData_ensure_layers_are_mutable(&mesh->vert_data, mesh->totvert);
const int totvert = mesh->totvert - len;
CustomData_free_elem(&mesh->vert_data, totvert, len);
mesh->totvert = totvert;
@ -1007,6 +1008,7 @@ static void mesh_remove_edges(Mesh *mesh, int len)
if (len == 0) {
return;
}
CustomData_ensure_layers_are_mutable(&mesh->edge_data, mesh->totedge);
const int totedge = mesh->totedge - len;
CustomData_free_elem(&mesh->edge_data, totedge, len);
mesh->totedge = totedge;
@ -1017,6 +1019,7 @@ static void mesh_remove_loops(Mesh *mesh, int len)
if (len == 0) {
return;
}
CustomData_ensure_layers_are_mutable(&mesh->loop_data, mesh->totloop);
const int totloop = mesh->totloop - len;
CustomData_free_elem(&mesh->loop_data, totloop, len);
mesh->totloop = totloop;
@ -1027,6 +1030,7 @@ static void mesh_remove_faces(Mesh *mesh, int len)
if (len == 0) {
return;
}
CustomData_ensure_layers_are_mutable(&mesh->face_data, mesh->faces_num);
const int faces_num = mesh->faces_num - len;
CustomData_free_elem(&mesh->face_data, faces_num, len);
mesh->faces_num = faces_num;