diff options
author | Hans Goudey <h.goudey@me.com> | 2022-10-13 20:42:12 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2022-10-13 20:43:04 +0300 |
commit | 6f190c669f3001f73e9051fc66e4d233957391c4 (patch) | |
tree | 5185ea6afdf5a1c7e4f340b56263ee8b6ae6e569 /source/blender/blenkernel/intern | |
parent | b2627dff4971ee9912fe8b41a09fcfa861eaadbb (diff) |
Fix: Attribute layers can be skipped in Mesh to BMesh conversion
In some situations, layers were filled with their default value
when converting from Mesh to BMesh (entering edit mode, for example).
This was caused by the recently added "copy mesh to bmesh" or "merge
mesh to bmesh" custom data functions creating a difference custom
data format than was used for the copying functions used later.
`CustomData_to_bmesh_block` is not robust enough to handle simple
differences in layout between the layout of the source and result
CustomData layers, because it relies on the order of the types and
the number of layers within each type.
As a fix, make the "mesh to bmesh" special case more explicit in
the conversion functions. This makes the difference in the API
smaller, which is a nice improvement anwyay.
Fixes T101796
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r-- | source/blender/blenkernel/intern/customdata.cc | 40 |
1 files changed, 11 insertions, 29 deletions
diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index be99a8ee87b..6f2390fc28f 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -2382,16 +2382,21 @@ static bool attribute_stored_in_bmesh_flag(const StringRef name) "material_index"); } -static CustomData shallow_copy_remove_non_bmesh_attributes(const CustomData &src) +CustomData CustomData_shallow_copy_remove_non_bmesh_attributes(const CustomData *src, + const eCustomDataMask mask) { Vector<CustomDataLayer> dst_layers; - for (const CustomDataLayer &layer : Span<CustomDataLayer>{src.layers, src.totlayer}) { - if (!attribute_stored_in_bmesh_flag(layer.name)) { - dst_layers.append(layer); + for (const CustomDataLayer &layer : Span<CustomDataLayer>{src->layers, src->totlayer}) { + if (attribute_stored_in_bmesh_flag(layer.name)) { + continue; + } + if (!(mask & CD_TYPE_AS_MASK(layer.type))) { + continue; } + dst_layers.append(layer); } - CustomData dst = src; + CustomData dst = *src; dst.layers = static_cast<CustomDataLayer *>( MEM_calloc_arrayN(dst_layers.size(), sizeof(CustomDataLayer), __func__)); dst.totlayer = dst_layers.size(); @@ -2402,18 +2407,6 @@ static CustomData shallow_copy_remove_non_bmesh_attributes(const CustomData &src return dst; } -bool CustomData_merge_mesh_to_bmesh(const CustomData *source, - CustomData *dest, - const eCustomDataMask mask, - const eCDAllocType alloctype, - const int totelem) -{ - CustomData source_copy = shallow_copy_remove_non_bmesh_attributes(*source); - const bool result = CustomData_merge(&source_copy, dest, mask, alloctype, totelem); - MEM_SAFE_FREE(source_copy.layers); - return result; -} - void CustomData_realloc(CustomData *data, const int old_size, const int new_size) { BLI_assert(new_size >= 0); @@ -2463,17 +2456,6 @@ void CustomData_copy(const CustomData *source, CustomData_merge(source, dest, mask, alloctype, totelem); } -void CustomData_copy_mesh_to_bmesh(const CustomData *source, - CustomData *dest, - const eCustomDataMask mask, - const eCDAllocType alloctype, - const int totelem) -{ - CustomData source_copy = shallow_copy_remove_non_bmesh_attributes(*source); - CustomData_copy(&source_copy, dest, mask, alloctype, totelem); - MEM_SAFE_FREE(source_copy.layers); -} - static void customData_free_layer__internal(CustomDataLayer *layer, const int totelem) { const LayerTypeInfo *typeInfo; @@ -3697,7 +3679,7 @@ bool CustomData_bmesh_merge(const CustomData *source, destold.layers = static_cast<CustomDataLayer *>(MEM_dupallocN(destold.layers)); } - if (CustomData_merge_mesh_to_bmesh(source, dest, mask, alloctype, 0) == false) { + if (CustomData_merge(source, dest, mask, alloctype, 0) == false) { if (destold.layers) { MEM_freeN(destold.layers); } |