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:
parent
1242512ff2
commit
535d211c94
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue