Fix #109670: attribute shared between geometries even when edited

The RNA attribute API did not make sure that attributes are unshared when
the data is accessed. This is necessary to avoid accidentally changing data
on other geometries.

Unfortunately, we currently can't detect if the access is read-only or if the
attribute data is modified. Therefore, the data is always copied when it
was shared. This makes it a little bit less efficient in some cases, but that
should still be ok. The old behavior could by brought back by implementing
#112150.

Pull Request: https://projects.blender.org/blender/blender/pulls/111514
This commit is contained in:
Jacques Lucke 2023-09-12 13:03:01 +02:00
parent 127eee87ce
commit 34b4487844
3 changed files with 12 additions and 0 deletions

View File

@ -429,6 +429,12 @@ void CustomData_bmesh_interp(struct CustomData *data,
*/
void CustomData_swap_corners(struct CustomData *data, int index, const int *corner_indices);
/**
* Custom data layers can be shared through implicit sharing (`BLI_implicit_sharing.h`). This
* 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);
/**
* Retrieve a pointer to an element of the active layer of the given \a type, chosen by the
* \a index, if it exists.

View File

@ -2414,6 +2414,11 @@ static void ensure_layer_data_is_mutable(CustomDataLayer &layer, const int totel
}
}
void CustomData_ensure_data_is_mutable(CustomDataLayer *layer, const int totelem)
{
ensure_layer_data_is_mutable(*layer, totelem);
}
void CustomData_realloc(CustomData *data, const int old_size, const int new_size)
{
BLI_assert(new_size >= 0);

View File

@ -289,6 +289,7 @@ static void rna_Attribute_data_begin(CollectionPropertyIterator *iter, PointerRN
const int length = BKE_id_attribute_data_length(id, layer);
const size_t struct_size = CustomData_get_elem_size(layer);
CustomData_ensure_data_is_mutable(layer, length);
rna_iterator_array_begin(iter, layer->data, struct_size, length, 0, nullptr);
}