Fix #126271: Prevent comparing a curve index mask to a point span

The `has_anything_selected` function has a variant that takes just an
index mask and compares that to all selection attributes it can find,
regardless of which domain they are on. In this case the bezier handle
selection attributes were stored on the Curve domain while the selection
domain has already been switched to Point.

Now the `has_anything_selected` function always expects a domain so it
can check for attributes on that same domain.

Bezier handle selection does not make sense on the point domain, but the
way curve selection is written makes it difficult to prevent the
creation of the attribute on Curve domain. It's also not generally
prohibited (user can still create that attribute) so selection code
should handle this case robustly.

Pull Request: https://projects.blender.org/blender/blender/pulls/126543
This commit is contained in:
Lukas Tönne
2024-08-20 12:00:37 +02:00
parent 1fb849b98e
commit ec82ccb4b4
4 changed files with 16 additions and 17 deletions

View File

@@ -404,21 +404,18 @@ bool has_anything_selected(const bke::CurvesGeometry &curves)
}
bool has_anything_selected(const bke::CurvesGeometry &curves, bke::AttrDomain selection_domain)
{
return has_anything_selected(
curves, selection_domain, IndexRange(curves.attributes().domain_size(selection_domain)));
}
bool has_anything_selected(const bke::CurvesGeometry &curves,
bke::AttrDomain selection_domain,
const IndexMask &mask)
{
for (const StringRef selection_name : get_curves_selection_attribute_names(curves)) {
const VArray<bool> selection = *curves.attributes().lookup<bool>(selection_name,
selection_domain);
if (!selection || contains(selection, selection.index_range(), true)) {
return true;
}
}
return false;
}
bool has_anything_selected(const bke::CurvesGeometry &curves, const IndexMask &mask)
{
for (const StringRef selection_name : get_curves_selection_attribute_names(curves)) {
const VArray<bool> selection = *curves.attributes().lookup<bool>(selection_name);
if (!selection || contains(selection, mask, true)) {
return true;
}

View File

@@ -212,8 +212,8 @@ static int select_random_exec(bContext *C, wmOperator *op)
ratio,
memory);
const bool was_anything_selected = ed::curves::has_anything_selected(curves,
selectable_elements);
const bool was_anything_selected = ed::curves::has_anything_selected(
curves, selection_domain, selectable_elements);
bke::GSpanAttributeWriter selection = ed::curves::ensure_selection_attribute(
curves, selection_domain, CD_PROP_BOOL);
if (!was_anything_selected) {
@@ -307,8 +307,8 @@ static int select_ends_exec(bContext *C, wmOperator *op)
const IndexMask selectable_points = ed::greasepencil::retrieve_editable_points(
*object, info.drawing, info.layer_index, memory);
const bool was_anything_selected = ed::curves::has_anything_selected(curves,
selectable_points);
const bool was_anything_selected = ed::curves::has_anything_selected(
curves, bke::AttrDomain::Point, selectable_points);
bke::GSpanAttributeWriter selection = ed::curves::ensure_selection_attribute(
curves, bke::AttrDomain::Point, CD_PROP_BOOL);
if (!was_anything_selected) {

View File

@@ -193,7 +193,9 @@ void fill_selection_true(GMutableSpan selection, const IndexMask &mask);
*/
bool has_anything_selected(const bke::CurvesGeometry &curves);
bool has_anything_selected(const bke::CurvesGeometry &curves, bke::AttrDomain selection_domain);
bool has_anything_selected(const bke::CurvesGeometry &curves, const IndexMask &mask);
bool has_anything_selected(const bke::CurvesGeometry &curves,
bke::AttrDomain selection_domain,
const IndexMask &mask);
/**
* Return true if any element in the span is selected, on either domain with either type.

View File

@@ -3320,7 +3320,7 @@ static bool ed_grease_pencil_select_pick(bContext *C,
continue;
}
bke::CurvesGeometry &curves = info.drawing.strokes_for_write();
if (!ed::curves::has_anything_selected(curves, elements)) {
if (!ed::curves::has_anything_selected(curves, selection_domain, elements)) {
continue;
}
ed::curves::foreach_selection_attribute_writer(