From 316fe6729504e7ac5613c823e21ee98d6359a23b Mon Sep 17 00:00:00 2001 From: Casey Bianco-Davis Date: Fri, 17 Oct 2025 17:21:33 +0200 Subject: [PATCH] Fix #147756: Grease Pencil: Join Operator crash because of `resolution` attribute When strokes from to different layers get joined together, if one layer had the `resolution` attribute and the other did not. The new `resolution` attribute would be left with uninitialized values and then a crash would happen. This fixes this by filling all attributes that didn't exist with their default value. This also ensures that when strokes are removed, the drawing is tagged as dirty. Pull Request: https://projects.blender.org/blender/blender/pulls/147948 --- .../blenkernel/intern/attribute_access.cc | 19 +++++++++++++++++++ .../intern/grease_pencil_join_selection.cc | 1 + 2 files changed, 20 insertions(+) diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index 0ea228a7a05..4bbd47a3e3f 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -1135,11 +1135,30 @@ void copy_attributes_group_to_group(const AttributeAccessor src_attributes, return; } const GVArraySpan src = *iter.get(src_domain); + const bool dst_already_exists = dst_attributes.contains(iter.name); GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span( iter.name, dst_domain, iter.data_type); if (!dst) { return; } + if (!dst_already_exists) { + /* Skip filling with the default value if all of the data is going to be filled. */ + if (!(dst_offsets.total_size() == dst.span.size() && selection.size() == dst_offsets.size())) + { + const CPPType &type = dst.span.type(); + if (dst_attributes.is_builtin(iter.name)) { + if (const GPointer value = dst_attributes.get_builtin_default(iter.name)) { + type.fill_construct_n(value.get(), dst.span.data(), dst.span.size()); + } + else { + type.fill_construct_n(type.default_value(), dst.span.data(), dst.span.size()); + } + } + else { + type.fill_construct_n(type.default_value(), dst.span.data(), dst.span.size()); + } + } + } array_utils::copy_group_to_group(src_offsets, dst_offsets, selection, src, dst.span); dst.finish(); }); diff --git a/source/blender/editors/grease_pencil/intern/grease_pencil_join_selection.cc b/source/blender/editors/grease_pencil/intern/grease_pencil_join_selection.cc index 8c94666ef1f..712bfb6b5ee 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_join_selection.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_join_selection.cc @@ -437,6 +437,7 @@ void remove_selected_points(Span ranges_selected) IndexMaskMemory memory; const IndexMask combined_mask = IndexMask::from_union(item.value, memory); dst_curves.remove_points(combined_mask, {}); + item.key->tag_topology_changed(); } }