Curves: Add box selection #104411
File diff suppressed because it is too large
Load Diff
|
@ -7,6 +7,7 @@
|
|||
#include "BLI_array_utils.hh"
|
||||
#include "BLI_index_mask_ops.hh"
|
||||
#include "BLI_rand.hh"
|
||||
#include "BLI_rect.h"
|
||||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_crazyspace.hh"
|
||||
|
@ -421,4 +422,102 @@ bool select_pick(const ViewContext &vc,
|
|||
return changed || found;
|
||||
}
|
||||
|
||||
bool select_box(const ViewContext &vc,
|
||||
bke::CurvesGeometry &curves,
|
||||
const eAttrDomain selection_domain,
|
||||
const struct rcti rect,
|
||||
const eSelectOp sel_op)
|
||||
{
|
||||
rctf rectf;
|
||||
BLI_rctf_rcti_copy(&rectf, &rect);
|
||||
|
||||
bke::GSpanAttributeWriter selection = ensure_selection_attribute(
|
||||
curves, selection_domain, CD_PROP_BOOL);
|
||||
|
||||
bool changed = false;
|
||||
if (sel_op == SEL_OP_SET) {
|
||||
fill_selection_false(selection.span);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
selection.span.type().to_static_type_tag<bool, float>([&](auto type_tag) {
|
||||
using T = typename decltype(type_tag)::type;
|
||||
if constexpr (std::is_void_v<T>) {
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
else {
|
||||
MutableSpan<T> selection_typed = selection.span.typed<T>();
|
||||
|
||||
float4x4 projection;
|
||||
ED_view3d_ob_project_mat_get(vc.rv3d, vc.obact, projection.ptr());
|
||||
|
||||
const bke::crazyspace::GeometryDeformation deformation =
|
||||
bke::crazyspace::get_evaluated_curves_deformation(*vc.depsgraph, *vc.obact);
|
||||
filedescriptor marked this conversation as resolved
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
if (selection_domain == ATTR_DOMAIN_POINT) {
|
||||
threading::parallel_for(curves.points_range(), 1024, [&](const IndexRange point_range) {
|
||||
for (const int point_i : point_range) {
|
||||
const float3 pos = deformation.positions[point_i];
|
||||
|
||||
/* Find the position of the point in screen space. */
|
||||
float2 pos_proj;
|
||||
ED_view3d_project_float_v2_m4(vc.region, pos, pos_proj, projection.ptr());
|
||||
filedescriptor marked this conversation as resolved
Hans Goudey
commented
It would be nice to extract this switch and share it with the select pick operator too, is that possible? It would be nice to extract this switch and share it with the select pick operator too, is that possible?
|
||||
if (BLI_rctf_isect_pt_v(&rectf, pos_proj)) {
|
||||
switch (sel_op) {
|
||||
case SEL_OP_ADD:
|
||||
case SEL_OP_SET:
|
||||
selection_typed[point_i] = T(1);
|
||||
break;
|
||||
case SEL_OP_SUB:
|
||||
selection_typed[point_i] = T(0);
|
||||
break;
|
||||
case SEL_OP_XOR:
|
||||
selection_typed[point_i] = T(1 - selection_typed[point_i]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (selection_domain == ATTR_DOMAIN_CURVE) {
|
||||
threading::parallel_for(curves.curves_range(), 512, [&](const IndexRange curves_range) {
|
||||
for (const int curve_i : curves_range) {
|
||||
for (const int point_i : points_by_curve[curve_i]) {
|
||||
const float3 pos = deformation.positions[point_i];
|
||||
|
||||
/* Find the position of the point in screen space. */
|
||||
float2 pos_proj;
|
||||
ED_view3d_project_float_v2_m4(vc.region, pos, pos_proj, projection.ptr());
|
||||
if (BLI_rctf_isect_pt_v(&rectf, pos_proj)) {
|
||||
switch (sel_op) {
|
||||
case SEL_OP_ADD:
|
||||
case SEL_OP_SET:
|
||||
selection_typed[curve_i] = T(1);
|
||||
break;
|
||||
case SEL_OP_SUB:
|
||||
selection_typed[curve_i] = T(0);
|
||||
break;
|
||||
case SEL_OP_XOR:
|
||||
selection_typed[curve_i] = T(1 - selection_typed[curve_i]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
selection.finish();
|
||||
return changed;
|
||||
}
|
||||
|
||||
} // namespace blender::ed::curves
|
||||
|
|
|
@ -11,6 +11,7 @@ struct Curves;
|
|||
struct UndoType;
|
||||
struct SelectPick_Params;
|
||||
struct ViewContext;
|
||||
struct rcti;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -46,6 +47,8 @@ float (*ED_curves_point_normals_array_create(const struct Curves *curves_id))[3]
|
|||
|
||||
# include "BKE_curves.hh"
|
||||
|
||||
# include "ED_select_utils.h"
|
||||
|
||||
namespace blender::ed::curves {
|
||||
|
||||
bool object_has_editable_curves(const Main &bmain, const Object &object);
|
||||
|
@ -146,6 +149,14 @@ bool select_pick(const ViewContext &vc,
|
|||
const SelectPick_Params ¶ms,
|
||||
const int2 mval);
|
||||
|
||||
/**
|
||||
* Select points or curves in a (screenspace) rectangle.
|
||||
*/
|
||||
bool select_box(const ViewContext &vc,
|
||||
bke::CurvesGeometry &curves,
|
||||
const eAttrDomain selection_domain,
|
||||
const struct rcti rect,
|
||||
filedescriptor marked this conversation as resolved
Hans Goudey
commented
I guess it passes, the "small" test, but maybe better to just default to const reference here. Also ` const rcti &rect, `
I guess it passes, the "small" test, but maybe better to just default to const reference here. Also `struct` is unnecessary in C++
|
||||
const eSelectOp sel_op);
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::ed::curves
|
||||
|
|
|
@ -3893,6 +3893,7 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e
|
|||
|
||||
static int view3d_box_select_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
using namespace blender;
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
ViewContext vc;
|
||||
rcti rect;
|
||||
|
@ -3955,6 +3956,19 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
|
|||
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
|
||||
}
|
||||
break;
|
||||
case OB_CURVES: {
|
||||
Curves &curves_id = *static_cast<Curves *>(vc.obact->data);
|
||||
bke::CurvesGeometry &curves = curves_id.geometry.wrap();
|
||||
changed = ed::curves::select_box(
|
||||
vc, curves, eAttrDomain(curves_id.selection_domain), rect, sel_op);
|
||||
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(static_cast<ID *>(vc.obedit->data), ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, vc.obedit->data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BLI_assert_msg(0, "box select on incorrect object type");
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue
Not sure if it would make a difference here, but it's usually preferred to move as much code as possible outside of the
to_static_type
lambda to avoid generating unnecessary code. That also makes the purpose of theto_static_type
clearer and makes it easier to replace it with a generic utility with a runtime type in the future.In this case, since this isn't really a performance bottleneck, it would probably be best for
apply_selection_operation
to take aGMutableSpan
and do the type switch itself.