diff --git a/source/blender/editors/curves/intern/curves_selection.cc b/source/blender/editors/curves/intern/curves_selection.cc index df990ed505b..4c3c3374f2e 100644 --- a/source/blender/editors/curves/intern/curves_selection.cc +++ b/source/blender/editors/curves/intern/curves_selection.cc @@ -361,14 +361,6 @@ static void apply_selection_operation_at_index(GMutableSpan selection, } } -/** - * Helper struct for `select_pick`. - */ -struct FindClosestData { - int index = -1; - float distance = FLT_MAX; -}; - static bool find_closest_point_to_screen_co(const Depsgraph &depsgraph, const ARegion *region, const RegionView3D *rv3d, @@ -388,7 +380,7 @@ static bool find_closest_point_to_screen_co(const Depsgraph &depsgraph, closest_data = threading::parallel_reduce( curves.points_range(), 1024, - FindClosestData(), + closest_data, [&](const IndexRange point_range, const FindClosestData &init) { FindClosestData best_match = init; for (const int point_i : point_range) { @@ -419,7 +411,7 @@ static bool find_closest_point_to_screen_co(const Depsgraph &depsgraph, } return b; }); - if (closest_data.index > 0) { + if (closest_data.index >= 0) { return true; } @@ -447,7 +439,7 @@ static bool find_closest_curve_to_screen_co(const Depsgraph &depsgraph, closest_data = threading::parallel_reduce( curves.curves_range(), 256, - FindClosestData(), + closest_data, [&](const IndexRange curves_range, const FindClosestData &init) { FindClosestData best_match = init; for (const int curve_i : curves_range) { @@ -515,18 +507,21 @@ static bool find_closest_curve_to_screen_co(const Depsgraph &depsgraph, } bool select_pick(const ViewContext &vc, + const Object &object, bke::CurvesGeometry &curves, const eAttrDomain selection_domain, const SelectPick_Params ¶ms, - const int2 coord) + const int2 coord, + FindClosestData initial) { - FindClosestData closest; + FindClosestData closest = initial; + bool found = false; if (selection_domain == ATTR_DOMAIN_POINT) { found = find_closest_point_to_screen_co(*vc.depsgraph, vc.region, vc.rv3d, - *vc.obact, + object, curves, float2(coord), ED_view3d_select_dist_px(), @@ -536,22 +531,22 @@ bool select_pick(const ViewContext &vc, found = find_closest_curve_to_screen_co(*vc.depsgraph, vc.region, vc.rv3d, - *vc.obact, + object, curves, float2(coord), ED_view3d_select_dist_px(), closest); } - bool changed = false; + bool deselected = false; if (params.sel_op == SEL_OP_SET) { - if (found || params.deselect_all) { - bke::GSpanAttributeWriter selection = ensure_selection_attribute( - curves, selection_domain, CD_PROP_BOOL); + bke::GSpanAttributeWriter selection = ensure_selection_attribute( + curves, selection_domain, CD_PROP_BOOL); + if (found || ((params.deselect_all && has_anything_selected(selection.span)))) { fill_selection_false(selection.span); - selection.finish(); - changed = true; + deselected = true; } + selection.finish(); } if (found) { @@ -561,7 +556,7 @@ bool select_pick(const ViewContext &vc, selection.finish(); } - return changed || found; + return deselected || found; } bool select_box(const ViewContext &vc, diff --git a/source/blender/editors/include/ED_curves.h b/source/blender/editors/include/ED_curves.h index a8019646b8b..a3e9ed39736 100644 --- a/source/blender/editors/include/ED_curves.h +++ b/source/blender/editors/include/ED_curves.h @@ -148,14 +148,24 @@ void select_random(bke::CurvesGeometry &curves, uint32_t random_seed, float probability); +/** + * Helper struct for `select_pick`. + */ +struct FindClosestData { + int index = -1; + float distance = FLT_MAX; +}; + /** * Select point or curve at a (screen-space) point. */ bool select_pick(const ViewContext &vc, + const Object &object, bke::CurvesGeometry &curves, eAttrDomain selection_domain, const SelectPick_Params ¶ms, - int2 coord); + int2 coord, + FindClosestData initial = {}); /** * Select points or curves in a (screen-space) rectangle. diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc index efe003c8db9..3c91480b6cc 100644 --- a/source/blender/editors/space_view3d/view3d_select.cc +++ b/source/blender/editors/space_view3d/view3d_select.cc @@ -2985,9 +2985,53 @@ static bool ed_wpaint_vertex_select_pick(bContext *C, return changed || found; } -static int view3d_select_exec(bContext *C, wmOperator *op) +/** + * Cursor selection for the Curves object. + * + * \returns true if the selection changed. + */ +static bool ed_curves_select_pick(bContext &C, const int mval[2], const SelectPick_Params ¶ms) { using namespace blender; + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(&C); + ViewContext vc; + /* Setup view context for argument to callbacks. */ + ED_view3d_viewcontext_init(&C, &vc, depsgraph); + + uint bases_len; + Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data( + vc.scene, vc.view_layer, vc.v3d, &bases_len); + + bool changed = false; + ed::curves::FindClosestData closest_data; + for (uint base_index = 0; base_index < bases_len; base_index++) { + Base *base = bases[base_index]; + Object *curves_ob = base->object; + Curves &curves_id = *static_cast(curves_ob->data); + bke::CurvesGeometry &curves = curves_id.geometry.wrap(); + + if (ed::curves::select_pick(vc, + *curves_ob, + curves, + eAttrDomain(curves_id.selection_domain), + params, + mval, + closest_data)) { + changed = true; + /* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a + * generic attribute for now. */ + DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(&C, NC_GEOM | ND_DATA, &curves_id); + } + } + + MEM_freeN(bases); + + return changed; +} + +static int view3d_select_exec(bContext *C, wmOperator *op) +{ Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); Object *obact = CTX_data_active_object(C); @@ -3077,16 +3121,7 @@ static int view3d_select_exec(bContext *C, wmOperator *op) changed = ED_curve_editfont_select_pick(C, mval, ¶ms); } else if (obedit->type == OB_CURVES) { - Curves &curves_id = *static_cast(obact->data); - bke::CurvesGeometry &curves = curves_id.geometry.wrap(); - changed = ed::curves::select_pick( - vc, curves, eAttrDomain(curves_id.selection_domain), params, mval); - if (changed) { - /* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a - * generic attribute for now. */ - DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_GEOM | ND_DATA, &curves_id); - } + changed = ed_curves_select_pick(*C, mval, params); } } else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) {