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:
committed by
Falk David
parent
8650068f0c
commit
e864cb0614
@@ -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)
|
||||
|
||||
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user