From 2e8b7004860074cf7ccaba850968828cf1e1b06d Mon Sep 17 00:00:00 2001 From: Falk David Date: Fri, 24 Feb 2023 16:41:06 +0100 Subject: [PATCH 1/4] Fix #105109: Pick selection with multi object edit Pick selection for the Curves object was not considering multi object editing. Only the active object was considered. This fix introduces pick selection for Curves for multi object editing --- .../editors/curves/intern/curves_selection.cc | 25 ++++---- source/blender/editors/include/ED_curves.h | 12 +++- .../editors/space_view3d/view3d_select.cc | 57 +++++++++++++++---- 3 files changed, 67 insertions(+), 27 deletions(-) diff --git a/source/blender/editors/curves/intern/curves_selection.cc b/source/blender/editors/curves/intern/curves_selection.cc index df990ed505b..06ccfbca9e9 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,7 +531,7 @@ 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(), 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..1539b99629a 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 *params) { 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); + + bool changed = false; + 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); + + 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, ¶ms); } } else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) { -- 2.30.2 From c0e0928ea97610f305480fcae85d79db292c94d6 Mon Sep 17 00:00:00 2001 From: Falk David Date: Wed, 1 Mar 2023 12:47:08 +0100 Subject: [PATCH 2/4] Renaming --- source/blender/editors/curves/intern/curves_selection.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/curves/intern/curves_selection.cc b/source/blender/editors/curves/intern/curves_selection.cc index 06ccfbca9e9..a164e00a121 100644 --- a/source/blender/editors/curves/intern/curves_selection.cc +++ b/source/blender/editors/curves/intern/curves_selection.cc @@ -538,14 +538,14 @@ bool select_pick(const ViewContext &vc, 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); fill_selection_false(selection.span); selection.finish(); - changed = true; + deselected = true; } } @@ -556,7 +556,7 @@ bool select_pick(const ViewContext &vc, selection.finish(); } - return changed || found; + return deselected || found; } bool select_box(const ViewContext &vc, -- 2.30.2 From 2b54cd81eb94212ed6d369482dec7fd3a6070074 Mon Sep 17 00:00:00 2001 From: Falk David Date: Wed, 1 Mar 2023 12:47:25 +0100 Subject: [PATCH 3/4] Use references instead of pointers --- .../blender/editors/space_view3d/view3d_select.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc index 1539b99629a..3c91480b6cc 100644 --- a/source/blender/editors/space_view3d/view3d_select.cc +++ b/source/blender/editors/space_view3d/view3d_select.cc @@ -2990,19 +2990,19 @@ static bool ed_wpaint_vertex_select_pick(bContext *C, * * \returns true if the selection changed. */ -static bool ed_curves_select_pick(bContext *C, const int mval[2], const SelectPick_Params *params) +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); + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(&C); ViewContext vc; /* Setup view context for argument to callbacks. */ - ED_view3d_viewcontext_init(C, &vc, depsgraph); + ED_view3d_viewcontext_init(&C, &vc, depsgraph); - bool changed = false; 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]; @@ -3014,14 +3014,14 @@ static bool ed_curves_select_pick(bContext *C, const int mval[2], const SelectPi *curves_ob, curves, eAttrDomain(curves_id.selection_domain), - *params, + 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); + WM_event_add_notifier(&C, NC_GEOM | ND_DATA, &curves_id); } } @@ -3121,7 +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) { - changed = ed_curves_select_pick(C, mval, ¶ms); + changed = ed_curves_select_pick(*C, mval, params); } } else if (obact && obact->mode & OB_MODE_PARTICLE_EDIT) { -- 2.30.2 From b43dd400bacb1e60d19dd75dad047bee37850058 Mon Sep 17 00:00:00 2001 From: Falk David Date: Thu, 2 Mar 2023 14:41:20 +0100 Subject: [PATCH 4/4] Only mark as deselected if something was selected before --- .../blender/editors/curves/intern/curves_selection.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/curves/intern/curves_selection.cc b/source/blender/editors/curves/intern/curves_selection.cc index a164e00a121..4c3c3374f2e 100644 --- a/source/blender/editors/curves/intern/curves_selection.cc +++ b/source/blender/editors/curves/intern/curves_selection.cc @@ -515,8 +515,8 @@ bool select_pick(const ViewContext &vc, FindClosestData initial) { FindClosestData closest = initial; - bool found = false; + bool found = false; if (selection_domain == ATTR_DOMAIN_POINT) { found = find_closest_point_to_screen_co(*vc.depsgraph, vc.region, @@ -540,13 +540,13 @@ bool select_pick(const ViewContext &vc, 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(); deselected = true; } + selection.finish(); } if (found) { -- 2.30.2