Fix: Grease Pencil: Select Grouped not selecting bezier handles

This makes it so that the `Select Grouped` operator will selected Bezier
handles. And Points with handles selected will be used included in the
group.

Part of #121574

Pull Request: https://projects.blender.org/blender/blender/pulls/144894
This commit is contained in:
Casey Bianco-Davis
2025-08-25 23:24:21 +02:00
committed by casey-bianco-davis
parent 4d7042a46e
commit 899a8bcdac

View File

@@ -586,30 +586,43 @@ static const EnumPropertyItem select_similar_mode_items[] = {
};
template<typename T>
void insert_selected_values(const bke::CurvesGeometry &curves,
void insert_selected_values(Object *object,
const MutableDrawingInfo &info,
const bke::AttrDomain domain,
const StringRef attribute_id,
const int handle_display,
blender::Set<T> &r_value_set)
{
T default_value;
CPPType::get<T>().default_construct(&default_value);
const bke::CurvesGeometry &curves = info.drawing.strokes();
const bke::AttributeAccessor attributes = curves.attributes();
const VArraySpan<bool> selection = *attributes.lookup_or_default<bool>(
".selection", domain, true);
const VArraySpan<T> values = *attributes.lookup_or_default<T>(
attribute_id, domain, default_value);
threading::EnumerableThreadSpecific<Set<T>> value_set_by_thread;
threading::parallel_for(
IndexRange(attributes.domain_size(domain)), 1024, [&](const IndexRange range) {
Set<T> &local_value_set = value_set_by_thread.local();
for (const int i : range) {
if (selection[i]) {
local_value_set.add(values[i]);
}
}
});
IndexMaskMemory memory;
if (domain == bke::AttrDomain::Point) {
const IndexMask points = ed::greasepencil::retrieve_editable_and_all_selected_points(
*object, info.drawing, info.layer_index, handle_display, memory);
points.foreach_index(GrainSize(1024), [&](const int index) {
Set<T> &local_value_set = value_set_by_thread.local();
local_value_set.add(values[index]);
});
}
else if (domain == bke::AttrDomain::Curve) {
const IndexMask strokes = ed::greasepencil::retrieve_editable_and_selected_strokes(
*object, info.drawing, info.layer_index, memory);
strokes.foreach_index(GrainSize(1024), [&](const int index) {
Set<T> &local_value_set = value_set_by_thread.local();
local_value_set.add(values[index]);
});
}
else {
BLI_assert_unreachable();
}
for (const Set<T> &local_value_set : value_set_by_thread) {
/* TODO is there a union function that can do this more efficiently? */
@@ -625,6 +638,7 @@ static void select_similar_by_value(Scene *scene,
GreasePencil &grease_pencil,
const bke::AttrDomain selection_domain,
const StringRef attribute_id,
const int handle_display,
float threshold,
DistanceFn distance_fn)
{
@@ -639,33 +653,37 @@ static void select_similar_by_value(Scene *scene,
blender::Set<T> selected_values;
for (const MutableDrawingInfo &info : drawings) {
insert_selected_values(
info.drawing.strokes(), selection_domain, attribute_id, selected_values);
object, info, selection_domain, attribute_id, handle_display, selected_values);
}
threading::parallel_for_each(drawings, [&](const MutableDrawingInfo &info) {
bke::CurvesGeometry &curves = info.drawing.strokes_for_write();
bke::GSpanAttributeWriter selection_writer = ed::curves::ensure_selection_attribute(
curves, selection_domain, bke::AttrType::Bool);
MutableSpan<bool> selection = selection_writer.span.typed<bool>();
const VArraySpan<T> values = *curves.attributes().lookup_or_default<T>(
attribute_id, selection_domain, default_value);
IndexMaskMemory memory;
const IndexMask mask = ed::greasepencil::retrieve_editable_points(
*object, info.drawing, info.layer_index, memory);
bke::CurvesGeometry &curves = info.drawing.strokes_for_write();
const VArraySpan<T> values = *curves.attributes().lookup_or_default<T>(
attribute_id, selection_domain, default_value);
mask.foreach_index(GrainSize(1024), [&](const int index) {
if (selection[index]) {
return;
}
for (const T &test_value : selected_values) {
if (distance_fn(values[index], test_value) <= threshold) {
selection[index] = true;
Span<StringRef> selection_attribute_names = ed::curves::get_curves_selection_attribute_names(
curves);
for (const int i : selection_attribute_names.index_range()) {
bke::GSpanAttributeWriter selection_writer = ed::curves::ensure_selection_attribute(
curves, selection_domain, bke::AttrType::Bool, selection_attribute_names[i]);
MutableSpan<bool> selection = selection_writer.span.typed<bool>();
mask.foreach_index(GrainSize(1024), [&](const int index) {
if (selection[index]) {
return;
}
}
});
for (const T &test_value : selected_values) {
if (distance_fn(values[index], test_value) <= threshold) {
selection[index] = true;
}
}
});
selection_writer.finish();
selection_writer.finish();
}
});
}
@@ -710,10 +728,12 @@ static wmOperatorStatus select_similar_exec(bContext *C, wmOperator *op)
const SelectSimilarMode mode = SelectSimilarMode(RNA_enum_get(op->ptr, "mode"));
const float threshold = RNA_float_get(op->ptr, "threshold");
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
Object *object = CTX_data_active_object(C);
GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object->data);
bke::AttrDomain selection_domain = ED_grease_pencil_selection_domain_get(scene->toolsettings,
object);
const int handle_display = v3d->overlay.handle_display;
switch (mode) {
case SelectSimilarMode::LAYER:
@@ -726,6 +746,7 @@ static wmOperatorStatus select_similar_exec(bContext *C, wmOperator *op)
grease_pencil,
selection_domain,
"material_index",
handle_display,
threshold,
[](const int a, const int b) -> float { return float(math::distance(a, b)); });
break;
@@ -736,6 +757,7 @@ static wmOperatorStatus select_similar_exec(bContext *C, wmOperator *op)
grease_pencil,
selection_domain,
"vertex_color",
handle_display,
threshold,
[](const ColorGeometry4f &a, const ColorGeometry4f &b) -> float {
return math::distance(float4(a), float4(b));
@@ -748,6 +770,7 @@ static wmOperatorStatus select_similar_exec(bContext *C, wmOperator *op)
grease_pencil,
selection_domain,
"radius",
handle_display,
threshold,
[](const float a, const float b) -> float { return math::distance(a, b); });
break;
@@ -758,6 +781,7 @@ static wmOperatorStatus select_similar_exec(bContext *C, wmOperator *op)
grease_pencil,
selection_domain,
"opacity",
handle_display,
threshold,
[](const float a, const float b) -> float { return math::distance(a, b); });
break;