GPv3: Bezier handles selection in pick operator

This modifies the Grease Pencil `pick` selection operator to use bezier handles as points to be selected.

Pull Request: https://projects.blender.org/blender/blender/pulls/125398
This commit is contained in:
Casey Bianco-Davis
2024-07-26 12:19:10 +02:00
committed by Falk David
parent 8650068f0c
commit e864cb0614
2 changed files with 70 additions and 27 deletions

View File

@@ -408,16 +408,22 @@ bool has_anything_selected(const bke::CurvesGeometry &curves, bke::AttrDomain se
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))
if (!selection || contains(selection, selection.index_range(), true)) {
return true;
}
}
return false;
}
bool has_anything_selected(const bke::CurvesGeometry &curves, const IndexMask &mask)
{
const VArray<bool> selection = *curves.attributes().lookup<bool>(".selection");
return !selection || contains(selection, mask, true);
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;
}
}
return false;
}
bool has_anything_selected(const GSpan selection)

View File

@@ -3075,7 +3075,7 @@ static bool ed_wpaint_vertex_select_pick(bContext *C,
}
struct ClosestCurveDataBlock {
blender::StringRef selection_name;
blender::StringRef selection_attribute_name;
Curves *curves_id = nullptr;
blender::ed::curves::FindClosestData elem = {};
};
@@ -3126,7 +3126,7 @@ static bool ed_curves_select_pick(bContext &C, const int mval[2], const SelectPi
mval,
new_closest.elem);
if (new_closest_elem) {
new_closest.selection_name = selection_attribute_name;
new_closest.selection_attribute_name = selection_attribute_name;
new_closest.elem = *new_closest_elem;
new_closest.curves_id = &curves_id;
}
@@ -3178,7 +3178,7 @@ static bool ed_curves_select_pick(bContext &C, const int mval[2], const SelectPi
closest.curves_id->geometry.wrap(),
bke::AttrDomain::Point,
CD_PROP_BOOL,
closest.selection_name);
closest.selection_attribute_name);
ed::curves::apply_selection_operation_at_index(
selection.span, closest.elem.index, params.sel_op);
selection.finish();
@@ -3202,6 +3202,7 @@ static bool ed_curves_select_pick(bContext &C, const int mval[2], const SelectPi
}
struct ClosestGreasePencilDrawing {
blender::StringRef selection_attribute_name;
blender::bke::greasepencil::Drawing *drawing = nullptr;
blender::ed::curves::FindClosestData elem = {};
};
@@ -3250,22 +3251,44 @@ static bool ed_grease_pencil_select_pick(bContext *C,
if (elements.is_empty()) {
continue;
}
/* Bezier handles are only visible when the control point is selected. */
const IndexMask visible_handle_elements =
ed::greasepencil::retrieve_editable_and_selected_elements(
*vc.obedit, info.drawing, info.layer_index, selection_domain, memory);
const bke::CurvesGeometry &curves = info.drawing.strokes();
const float4x4 layer_to_world = layer.to_world_space(*ob_eval);
const float4x4 projection = ED_view3d_ob_project_mat_get_from_obmat(vc.rv3d,
layer_to_world);
std::optional<ed::curves::FindClosestData> new_closest_elem =
ed::curves::closest_elem_find_screen_space(vc,
info.drawing.strokes().points_by_curve(),
deformation.positions,
projection,
elements,
selection_domain,
mval,
new_closest.elem);
if (new_closest_elem) {
new_closest.elem = *new_closest_elem;
new_closest.drawing = &info.drawing;
const auto range_consumer = [&](const IndexRange range,
const Span<float3> positions,
const StringRef selection_attribute_name) {
/* The control point must be visible for the Bezier handle attributes. */
const IndexMask mask = (selection_attribute_name != ".selection") ?
visible_handle_elements.slice_content(range) :
elements.slice_content(range);
std::optional<ed::curves::FindClosestData> new_closest_elem =
ed::curves::closest_elem_find_screen_space(vc,
curves.points_by_curve(),
positions,
projection,
mask,
selection_domain,
mval,
new_closest.elem);
if (new_closest_elem) {
new_closest.selection_attribute_name = selection_attribute_name;
new_closest.elem = *new_closest_elem;
new_closest.drawing = &info.drawing;
}
};
if (selection_domain == bke::AttrDomain::Point) {
ed::curves::foreach_selectable_point_range(curves, deformation, range_consumer);
}
else if (selection_domain == bke::AttrDomain::Curve) {
ed::curves::foreach_selectable_curve_range(curves, deformation, range_consumer);
};
}
return new_closest;
},
@@ -3288,10 +3311,10 @@ static bool ed_grease_pencil_select_pick(bContext *C,
if (!ed::curves::has_anything_selected(curves, elements)) {
continue;
}
bke::GSpanAttributeWriter selection = ed::curves::ensure_selection_attribute(
curves, selection_domain, CD_PROP_BOOL);
ed::curves::fill_selection_false(selection.span, elements);
selection.finish();
ed::curves::foreach_selection_attribute_writer(
curves, selection_domain, [](bke::GSpanAttributeWriter &selection) {
ed::curves::fill_selection_false(selection.span);
});
deselected = true;
}
@@ -3308,11 +3331,25 @@ static bool ed_grease_pencil_select_pick(bContext *C,
return deselected;
}
bke::GSpanAttributeWriter selection = ed::curves::ensure_selection_attribute(
closest.drawing->strokes_for_write(), selection_domain, CD_PROP_BOOL);
ed::curves::apply_selection_operation_at_index(
selection.span, closest.elem.index, params.sel_op);
selection.finish();
if (selection_domain == bke::AttrDomain::Point) {
bke::GSpanAttributeWriter selection = ed::curves::ensure_selection_attribute(
closest.drawing->strokes_for_write(),
bke::AttrDomain::Point,
CD_PROP_BOOL,
closest.selection_attribute_name);
ed::curves::apply_selection_operation_at_index(
selection.span, closest.elem.index, params.sel_op);
selection.finish();
}
else if (selection_domain == bke::AttrDomain::Curve) {
ed::curves::foreach_selection_attribute_writer(
closest.drawing->strokes_for_write(),
bke::AttrDomain::Curve,
[&](bke::GSpanAttributeWriter &selection) {
ed::curves::apply_selection_operation_at_index(
selection.span, closest.elem.index, params.sel_op);
});
}
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a
* generic attribute for now. */