diff --git a/source/blender/editors/grease_pencil/intern/grease_pencil_select.cc b/source/blender/editors/grease_pencil/intern/grease_pencil_select.cc index fd24870fa23..776ef923475 100644 --- a/source/blender/editors/grease_pencil/intern/grease_pencil_select.cc +++ b/source/blender/editors/grease_pencil/intern/grease_pencil_select.cc @@ -586,30 +586,43 @@ static const EnumPropertyItem select_similar_mode_items[] = { }; template -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 &r_value_set) { T default_value; CPPType::get().default_construct(&default_value); + const bke::CurvesGeometry &curves = info.drawing.strokes(); const bke::AttributeAccessor attributes = curves.attributes(); - const VArraySpan selection = *attributes.lookup_or_default( - ".selection", domain, true); const VArraySpan values = *attributes.lookup_or_default( attribute_id, domain, default_value); threading::EnumerableThreadSpecific> value_set_by_thread; - threading::parallel_for( - IndexRange(attributes.domain_size(domain)), 1024, [&](const IndexRange range) { - Set &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 &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 &local_value_set = value_set_by_thread.local(); + local_value_set.add(values[index]); + }); + } + else { + BLI_assert_unreachable(); + } for (const Set &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 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 selection = selection_writer.span.typed(); - const VArraySpan values = *curves.attributes().lookup_or_default( - 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 values = *curves.attributes().lookup_or_default( + 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 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 selection = selection_writer.span.typed(); + + 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(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;