37 std::optional<bke::AttributeMetaData> meta_data = attributes.
lookup_meta_data(
".selection");
55 const IndexRange points = points_by_curve[curve];
59 bool is_selected = point_selection.
as_span().contains(
true);
61 selection_left.materialize_compressed(points, point_selection);
62 is_selected |= point_selection.
as_span().contains(
true);
63 selection_right.materialize_compressed(points, point_selection);
64 is_selected |= point_selection.
as_span().contains(
true);
88 const int handle_display,
100 selection_by_attribute.
append(
114 if (attribute_name ==
".selection") {
129 static const std::array<StringRef, 1> selection_attribute_names{
".selection"};
132 selection_attribute_names;
137 static const std::array<StringRef, 3> selection_attribute_names{
138 ".selection",
".selection_handle_left",
".selection_handle_right"};
139 return selection_attribute_names;
144 static const std::array<StringRef, 2> selection_attribute_names{
".selection_handle_left",
145 ".selection_handle_right"};
147 return (attributes.
contains(
"handle_type_left") && attributes.
contains(
"handle_type_right")) ?
148 selection_attribute_names :
155 for (
const StringRef selection_name : selection_attribute_names) {
156 attributes.
remove(selection_name);
165 if (attribute_name ==
".selection") {
168 if (attribute_name ==
".selection_handle_left") {
169 return curves.handle_positions_left();
171 if (attribute_name ==
".selection_handle_right") {
172 return curves.handle_positions_right();
184 for (
const int i : selection_attribute_names.
index_range()) {
186 curves, selection_domain, create_type, selection_attribute_names[
i]));
193 for (
auto &attribute_writer : attribute_writers) {
194 attribute_writer.finish();
206 if (attribute_name.
size() == selection_attribute_names[index].
size()) {
207 return selections[index];
211 return selections[0];
222 fn(selection_writer);
233 std::optional<std::array<
Span<float3>, 2>> &r_bezier_handle_positions,
239 if (handle_display != eHandleDisplay::CURVE_HANDLE_NONE && r_bezier_attribute_names.
size() > 0) {
240 r_bezier_handle_positions = {*
curves.handle_positions_left(),
241 *
curves.handle_positions_right()};
245 r_bezier_handle_positions = std::nullopt;
256 std::optional<std::array<Span<float3>, 2>> bezier_handle_positions;
262 bezier_attribute_names,
264 bezier_handle_positions,
268 range_consumer(
curves.points_range(), positions,
".selection");
270 if (handle_display == eHandleDisplay::CURVE_HANDLE_NONE) {
275 for (
const int attribute_i : bezier_attribute_names.
index_range()) {
277 range_consumer(points_by_curve[curve],
278 (*bezier_handle_positions)[attribute_i],
279 bezier_attribute_names[attribute_i]);
291 std::optional<std::array<Span<float3>, 2>> bezier_handle_positions;
297 bezier_attribute_names,
299 bezier_handle_positions,
303 range_consumer(
curves.curves_range(), positions,
".selection");
304 if (handle_display == eHandleDisplay::CURVE_HANDLE_NONE) {
308 for (
const int attribute_i : bezier_attribute_names.
index_range()) {
310 range_consumer(curves_range,
311 (*bezier_handle_positions)[attribute_i],
312 bezier_attribute_names[attribute_i]);
323 if (attributes.
contains(attribute_name)) {
326 if (selection_attr.
domain == selection_domain) {
327 return selection_attr;
330 attributes.
remove(attribute_name);
332 const int domain_size = attributes.
domain_size(selection_domain);
333 switch (create_type) {
335 attributes.
add(attribute_name,
341 attributes.
add(attribute_name,
354 if (selection.
type().
is<
bool>()) {
355 selection.
typed<
bool>().fill(
false);
357 else if (selection.
type().
is<
float>()) {
358 selection.
typed<
float>().fill(0.0f);
364 if (selection.
type().
is<
bool>()) {
365 selection.
typed<
bool>().fill(
true);
367 else if (selection.
type().
is<
float>()) {
368 selection.
typed<
float>().fill(1.0f);
374 if (selection.
type().
is<
bool>()) {
375 selection.
typed<
bool>().fill(value);
377 else if (selection.
type().
is<
float>()) {
378 selection.
typed<
float>().fill(value ? 1.0f : 0.0f);
384 if (selection.
type().
is<
bool>()) {
387 else if (selection.
type().
is<
float>()) {
394 if (selection.
type().
is<
bool>()) {
397 else if (selection.
type().
is<
float>()) {
440 if (selection.
type().
is<
bool>()) {
441 return selection.
typed<
bool>().contains(
true);
443 if (selection.
type().
is<
float>()) {
444 for (
const float elem : selection.
typed<
float>()) {
461 if (selection.
type().
is<
bool>()) {
464 else if (selection.
type().
is<
float>()) {
480 std::optional<IndexRange> range =
mask.to_range();
481 if (range.has_value() &&
506 const IndexRange selection(
curves.attributes().domain_size(selection_domain));
525 const IndexRange points = points_by_curve[curve];
527 for (
const int i : curve_writers) {
532 for (
const int j : curve_writers) {
552 const bool deselect_ends)
564 const IndexRange points = points_by_curve[curve];
566 bool anything_selected =
false;
570 anything_selected = anything_selected || writer_has_anything_selected;
572 if (!anything_selected) {
579 const int half_of_size = points.
size() / 2;
583 const int index =
i * 2;
584 selection_typed[selected[index]] =
true;
585 selection_typed[deselected[index]] =
false;
588 selection_typed[points.
first()] = !deselect_ends;
589 const bool end_parity_to_selected = bool(points.
size() % 2);
590 const bool selected_end = cyclic[curve] || end_parity_to_selected;
591 selection_typed[points.
last()] = !deselect_ends && selected_end;
594 if (!deselect_ends && cyclic[curve] && !curve_body.
is_empty()) {
595 selection_typed[curve_body.
last()] =
false;
624 const IndexRange points = points_by_curve[curve];
625 const int first_point = points.
first();
626 const int last_point = points.
last();
629 for (
int point = first_point; point < last_point; point++) {
630 if (!selection_typed[point] && selection_typed[point + 1]) {
631 selection_typed[point] =
true;
636 for (
int point = last_point; point > first_point; point--) {
637 if (!selection_typed[point] && selection_typed[point - 1]) {
638 selection_typed[point] =
true;
642 if (!selection_typed[first_point]) {
643 selection_typed[first_point] =
true;
645 if (!selection_typed[last_point]) {
646 selection_typed[last_point] =
true;
651 if (selection_typed[first_point] != selection_typed[last_point]) {
652 selection_typed[first_point] =
true;
653 selection_typed[last_point] =
true;
661 const IndexRange points = points_by_curve[curve];
662 const int first_point = points.
first();
663 const int last_point = points.
last();
666 for (
int point_i = first_point; point_i < last_point; point_i++) {
667 if ((selection_typed[point_i] == 0.0f) && (selection_typed[point_i + 1] > 0.0f)) {
668 selection_typed[point_i] = 1.0f;
673 for (
int point_i = last_point; point_i > first_point; point_i--) {
674 if ((selection_typed[point_i] == 0.0f) && (selection_typed[point_i - 1] > 0.0f)) {
675 selection_typed[point_i] = 1.0f;
681 if (selection_typed[first_point] != selection_typed[last_point]) {
682 selection_typed[first_point] = 1.0f;
683 selection_typed[last_point] = 1.0f;
705 if (selection.
type().
is<
bool>()) {
710 selection_typed[index] =
true;
713 selection_typed[index] =
false;
716 selection_typed[index] = !selection_typed[index];
722 else if (selection.
type().
is<
float>()) {
727 selection_typed[index] = 1.0f;
730 selection_typed[index] = 0.0f;
733 selection_typed[index] = 1.0f - selection_typed[index];
758 const float radius_sq =
pow2f(radius);
764 FindClosestData best_match = init;
765 points_mask.slice(range).foreach_index([&](const int point) {
766 const float3 &pos = positions[point];
767 const float2 pos_proj = ED_view3d_project_float_v2_m4(region, pos, projection);
769 const float distance_proj_sq = math::distance_squared(pos_proj, mouse_pos);
770 if (distance_proj_sq > radius_sq || distance_proj_sq > best_match.distance_sq) {
774 best_match = {point, distance_proj_sq};
780 if (new_closest_data.distance_sq < initial_closest.distance_sq) {
781 return new_closest_data;
798 const float radius_sq =
pow2f(radius);
805 FindClosestData best_match = init;
806 curves_mask.slice(range).foreach_index([&](const int curve) {
807 const IndexRange points = points_by_curve[curve];
809 if (points.size() == 1) {
810 const float3 &pos = positions[points.first()];
811 const float2 pos_proj = ED_view3d_project_float_v2_m4(region, pos, projection);
813 const float distance_proj_sq = math::distance_squared(pos_proj, mouse_pos);
814 if (distance_proj_sq > radius_sq || distance_proj_sq > best_match.distance_sq) {
818 best_match = {curve, distance_proj_sq};
822 auto process_segment = [&](const int segment_i, const int next_i) {
823 const float3 &pos1 = positions[segment_i];
824 const float3 &pos2 = positions[next_i];
825 const float2 pos1_proj = ED_view3d_project_float_v2_m4(region, pos1, projection);
826 const float2 pos2_proj = ED_view3d_project_float_v2_m4(region, pos2, projection);
828 const float distance_proj_sq = dist_squared_to_line_segment_v2(
829 mouse_pos, pos1_proj, pos2_proj);
830 if (distance_proj_sq > radius_sq || distance_proj_sq > best_match.distance_sq) {
834 best_match = {curve, distance_proj_sq};
836 for (const int segment_i : points.drop_back(1)) {
837 process_segment(segment_i, segment_i + 1);
840 process_segment(points.last(), points.first());
847 if (new_closest_data.distance_sq < initial_closest.distance_sq) {
848 return new_closest_data;
903 bool changed =
false;
917 const IndexMask &mask = (selection_attribute_name ==
".selection") ? selection_mask :
919 mask.slice_content(range).foreach_index(GrainSize(1024), [&](const int point) {
920 const float2 pos_proj = ED_view3d_project_float_v2_m4(
921 vc.region, positions[point], projection);
922 if (BLI_rcti_isect_pt_v(&rect, int2(pos_proj))) {
923 apply_selection_operation_at_index(
924 selection_attribute_writer_by_name(selection_writers, selection_attribute_name)
936 foreach_selectable_curve_range(
943 const IndexMask &mask = selection_mask;
944 mask.slice_content(range).foreach_index(GrainSize(512), [&](const int curve) {
945 const IndexRange points = points_by_curve[curve];
946 if (points.size() == 1) {
947 const float2 pos_proj = ED_view3d_project_float_v2_m4(
948 vc.region, positions[points.first()], projection);
949 if (BLI_rcti_isect_pt_v(&rect, int2(pos_proj))) {
950 for (bke::GSpanAttributeWriter &selection : selection_writers) {
951 apply_selection_operation_at_index(selection.span, curve, sel_op);
957 auto process_segment = [&](const int segment_i, const int next_i) {
958 const float3 &pos1 = positions[segment_i];
959 const float3 &pos2 = positions[next_i];
960 const float2 pos1_proj = ED_view3d_project_float_v2_m4(vc.region, pos1, projection);
961 const float2 pos2_proj = ED_view3d_project_float_v2_m4(vc.region, pos2, projection);
963 if (BLI_rcti_isect_segment(&rect, int2(pos1_proj), int2(pos2_proj))) {
964 for (bke::GSpanAttributeWriter &selection : selection_writers) {
965 apply_selection_operation_at_index(selection.span, curve, sel_op);
972 bool segment_selected = false;
973 for (const int segment_i : points.drop_back(1)) {
974 if (process_segment(segment_i, segment_i + 1)) {
975 segment_selected = true;
979 if (!segment_selected && cyclic[curve]) {
980 process_segment(points.last(), points.first());
985 finish_attribute_writers(selection_writers);
1003 bool changed =
false;
1017 const IndexMask &mask = (selection_attribute_name ==
".selection") ? selection_mask :
1019 mask.slice_content(range).foreach_index(GrainSize(1024), [&](const int point) {
1020 const float2 pos_proj = ED_view3d_project_float_v2_m4(
1021 vc.region, positions[point], projection);
1023 if (BLI_rcti_isect_pt_v(&bbox, int2(pos_proj)) &&
1024 BLI_lasso_is_point_inside(
1025 lasso_coords, int(pos_proj.x), int(pos_proj.y), IS_CLIPPED))
1027 apply_selection_operation_at_index(
1028 selection_attribute_writer_by_name(selection_writers, selection_attribute_name)
1040 foreach_selectable_curve_range(
1047 const IndexMask &mask = selection_mask;
1048 mask.slice_content(range).foreach_index(GrainSize(512), [&](const int curve) {
1049 const IndexRange points = points_by_curve[curve];
1050 if (points.size() == 1) {
1051 const float2 pos_proj = ED_view3d_project_float_v2_m4(
1052 vc.region, positions[points.first()], projection);
1054 if (BLI_rcti_isect_pt_v(&bbox, int2(pos_proj)) &&
1055 BLI_lasso_is_point_inside(
1056 lasso_coords, int(pos_proj.x), int(pos_proj.y), IS_CLIPPED))
1058 for (bke::GSpanAttributeWriter &selection : selection_writers) {
1059 apply_selection_operation_at_index(selection.span, curve, sel_op);
1065 auto process_segment = [&](const int segment_i, const int next_i) {
1066 const float3 &pos1 = positions[segment_i];
1067 const float3 &pos2 = positions[next_i];
1068 const float2 pos1_proj = ED_view3d_project_float_v2_m4(vc.region, pos1, projection);
1069 const float2 pos2_proj = ED_view3d_project_float_v2_m4(vc.region, pos2, projection);
1072 if (BLI_rcti_isect_segment(&bbox, int2(pos1_proj), int2(pos2_proj)) &&
1073 BLI_lasso_is_edge_inside(lasso_coords,
1080 for (bke::GSpanAttributeWriter &selection : selection_writers) {
1081 apply_selection_operation_at_index(selection.span, curve, sel_op);
1088 bool segment_selected = false;
1089 for (const int segment_i : points.drop_back(cyclic[curve] ? 0 : 1)) {
1090 if (process_segment(segment_i, segment_i + 1)) {
1091 segment_selected = true;
1095 if (!segment_selected && cyclic[curve]) {
1096 process_segment(points.last(), points.first());
1101 finish_attribute_writers(selection_writers);
1116 const float radius_sq =
pow2f(radius);
1119 bool changed =
false;
1133 const IndexMask &mask = (selection_attribute_name ==
".selection") ? selection_mask :
1135 mask.slice_content(range).foreach_index(GrainSize(1024), [&](const int point) {
1136 const float2 pos_proj = ED_view3d_project_float_v2_m4(
1137 vc.region, positions[point], projection);
1138 if (math::distance_squared(pos_proj, float2(coord)) <= radius_sq) {
1139 apply_selection_operation_at_index(
1140 selection_attribute_writer_by_name(selection_writers, selection_attribute_name)
1152 foreach_selectable_curve_range(
1159 const IndexMask &mask = selection_mask;
1160 mask.slice_content(range).foreach_index(GrainSize(512), [&](const int curve) {
1161 const IndexRange points = points_by_curve[curve];
1162 if (points.size() == 1) {
1163 const float2 pos_proj = ED_view3d_project_float_v2_m4(
1164 vc.region, positions[points.first()], projection);
1165 if (math::distance_squared(pos_proj, float2(coord)) <= radius_sq) {
1166 for (bke::GSpanAttributeWriter &selection : selection_writers) {
1167 apply_selection_operation_at_index(selection.span, curve, sel_op);
1173 auto process_segments = [&](const int segment_i, const int next_i) {
1174 const float3 &pos1 = positions[segment_i];
1175 const float3 &pos2 = positions[next_i];
1176 const float2 pos1_proj = ED_view3d_project_float_v2_m4(vc.region, pos1, projection);
1177 const float2 pos2_proj = ED_view3d_project_float_v2_m4(vc.region, pos2, projection);
1179 const float distance_proj_sq = dist_squared_to_line_segment_v2(
1180 float2(coord), pos1_proj, pos2_proj);
1181 if (distance_proj_sq <= radius_sq) {
1182 for (bke::GSpanAttributeWriter &selection : selection_writers) {
1183 apply_selection_operation_at_index(selection.span, curve, sel_op);
1190 bool segment_selected = false;
1191 for (const int segment_i : points.drop_back(1)) {
1192 if (process_segments(segment_i, segment_i + 1)) {
1193 segment_selected = true;
1197 if (!segment_selected && cyclic[curve]) {
1198 process_segments(points.last(), points.first());
1203 finish_attribute_writers(selection_writers);
1207template<
typename Po
intSelectFn,
typename LineSelectFn>
1212 PointSelectFn &&point_predicate,
1213 LineSelectFn &&line_predicate)
1226 [&](
const int curve) ->
bool {
1227 const IndexRange points = points_by_curve[curve];
1232 if (points.
size() == 1) {
1233 return point_predicate(points.
first());
1236 for (
const int point : points.
drop_back(1)) {
1237 if (line_predicate(curve, point, point + 1)) {
1242 if (line_predicate(curve, points.
last(), points.
first()))
1256 const bool deselect,
1268 auto is_point_changed1 = [&](
const int point,
const int neighbor) {
1269 return deselect ? (selection[point] && !selection[neighbor]) :
1270 (!selection[point] && selection[neighbor]);
1272 auto is_point_changed2 = [&](
const int point,
const int neighbor1,
const int neighbor2) {
1273 return deselect ? (selection[point] && (!selection[neighbor1] || !selection[neighbor2])) :
1274 (!selection[point] && (selection[neighbor1] || selection[neighbor2]));
1278 const IndexRange points = points_by_curve[curve];
1279 if (points.
size() == 1) {
1284 if (cyclic[curve]) {
1285 changed_points[points.
first()] = is_point_changed2(
1288 changed_points[point] = is_point_changed2(point, point - 1, point + 1);
1290 changed_points[points.
last()] = is_point_changed2(
1294 changed_points[points.
first()] = is_point_changed1(points.
first(), points.
first() + 1);
1296 changed_points[point] = is_point_changed2(point, point - 1, point + 1);
1298 changed_points[points.
last()] = is_point_changed1(points.
last(), points.
last() - 1);
1307 const bool deselect,
1325 curves, deformation, attribute_name);
1326 if (!positions_opt) {
1331 auto point_predicate = [&](
const int point) {
1336 auto line_predicate = [&](
const int ,
const int point,
const int next_point_i) {
1339 vc.
region, positions[next_point_i], projection);
1344 attribute_name ==
".selection") ?
1348 curves,
mask, selection_domain, memory, point_predicate, line_predicate);
1365 curves, deformation, attribute_name);
1366 if (!positions_opt) {
1371 auto point_predicate = [&](
const int point) {
1377 auto line_predicate = [&](
const int ,
const int point,
const int next_point_i) {
1380 vc.
region, positions[next_point_i], projection);
1385 int(next_pos_proj.x),
1386 int(next_pos_proj.y),
1391 attribute_name ==
".selection") ?
1395 curves,
mask, selection_domain, memory, point_predicate, line_predicate);
1410 const float radius_sq =
pow2f(radius);
1412 curves, deformation, attribute_name);
1413 if (!positions_opt) {
1418 auto point_predicate = [&](
const int point) {
1421 return distance_proj_sq <= radius_sq;
1423 auto line_predicate = [&](
const int ,
const int point,
const int next_point_i) {
1426 vc.
region, positions[next_point_i], projection);
1428 float2(coord), pos_proj, next_pos_proj);
1429 return distance_proj_sq <= radius_sq;
1433 attribute_name ==
".selection") ?
1437 curves,
mask, selection_domain, memory, point_predicate, line_predicate);
Low-level operations for curves.
Low-level operations for curves.
#define BLI_assert_unreachable()
bool BLI_lasso_is_point_inside(blender::Span< blender::int2 > mcoords, int sx, int sy, int error_value)
void BLI_lasso_boundbox(rcti *rect, blender::Span< blender::int2 > mcoords)
bool BLI_lasso_is_edge_inside(blender::Span< blender::int2 > mcoords, int x0, int y0, int x1, int y1, int error_value)
MINLINE float pow2f(float x)
float dist_squared_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2])
bool BLI_rcti_isect_pt_v(const struct rcti *rect, const int xy[2])
bool BLI_rcti_isect_segment(const struct rcti *rect, const int s1[2], const int s2[2])
blender::float2 ED_view3d_project_float_v2_m4(const ARegion *region, const float co[3], const blender::float4x4 &mat)
float ED_view3d_select_dist_px()
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
Span< T > as_span() const
GMutableSpan slice(const int64_t start, int64_t size) const
const CPPType & type() const
MutableSpan< T > typed() const
const CPPType & type() const
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
static IndexMask from_union(const IndexMask &mask_a, const IndexMask &mask_b, IndexMaskMemory &memory)
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
constexpr int64_t first() const
constexpr IndexRange shift(int64_t n) const
constexpr IndexRange drop_back(int64_t n) const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr bool is_empty() const
constexpr IndexRange index_range() const
constexpr IndexRange drop_front(int64_t n) const
constexpr IndexRange index_range() const
constexpr int64_t size() const
constexpr IndexRange index_range() const
constexpr bool contains(const T &value) const
constexpr int64_t size() const
IndexRange index_range() const
T get_internal_single() const
void materialize_compressed(const IndexMask &mask, MutableSpan< T > r_span) const
static VArray from_single(T value, const int64_t size)
void append(const T &value)
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, AttrType data_type, const void *default_value=nullptr) const
bool contains(StringRef attribute_id) const
int domain_size(const AttrDomain domain) const
std::optional< AttributeMetaData > lookup_meta_data(StringRef attribute_id) const
bool add(const StringRef attribute_id, const AttrDomain domain, const AttrType data_type, const AttributeInit &initializer)
bool remove(const StringRef attribute_id)
GSpanAttributeWriter lookup_for_write_span(StringRef attribute_id)
IndexRange index_range() const
void foreach_range(Fn &&fn) const
void foreach_index(Fn &&fn) const
static bool is_cyclic(const Nurb *nu)
VecBase< float, 2 > float2
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
void invert_booleans(MutableSpan< bool > span)
bool contains(const VArray< bool > &varray, const IndexMask &indices_to_check, bool value)
IndexMask curve_type_point_selection(const bke::CurvesGeometry &curves, CurveType curve_type, IndexMaskMemory &memory)
void select_linked(bke::CurvesGeometry &curves, const IndexMask &curves_mask)
void apply_selection_operation_at_index(GMutableSpan selection, const int index, const eSelectOp sel_op)
void foreach_selectable_point_range(const bke::CurvesGeometry &curves, const bke::crazyspace::GeometryDeformation &deformation, eHandleDisplay handle_display, SelectionRangeFn range_consumer)
IndexMask select_circle_mask(const ViewContext &vc, const bke::CurvesGeometry &curves, const bke::crazyspace::GeometryDeformation &deformation, const float4x4 &projection, const IndexMask &selection_mask, const IndexMask &bezier_mask, const bke::AttrDomain selection_domain, const StringRef attribute_name, const int2 coord, const float radius, IndexMaskMemory &memory)
static bool has_anything_selected(const Span< Curves * > curves_ids)
IndexMask retrieve_all_selected_points(const bke::CurvesGeometry &curves, const int handle_display, IndexMaskMemory &memory)
IndexMask retrieve_selected_curves(const bke::CurvesGeometry &curves, IndexMaskMemory &memory)
void remove_selection_attributes(bke::MutableAttributeAccessor &attributes, Span< StringRef > selection_attribute_names)
static std::optional< FindClosestData > find_closest_point_to_screen_co(const ARegion *region, const Span< float3 > positions, const float4x4 &projection, const IndexMask &points_mask, const float2 mouse_pos, const float radius, const FindClosestData &initial_closest)
static Vector< bke::GSpanAttributeWriter > init_selection_writers(bke::CurvesGeometry &curves, bke::AttrDomain selection_domain)
void select_all(bke::CurvesGeometry &curves, const IndexMask &mask, const bke::AttrDomain selection_domain, int action)
IndexMask select_mask_from_predicates(const bke::CurvesGeometry &curves, const IndexMask &mask, const bke::AttrDomain selection_domain, IndexMaskMemory &memory, PointSelectFn &&point_predicate, LineSelectFn &&line_predicate)
void select_alternate(bke::CurvesGeometry &curves, const IndexMask &curves_mask, const bool deselect_ends)
void foreach_selectable_curve_range(const bke::CurvesGeometry &curves, const bke::crazyspace::GeometryDeformation &deformation, eHandleDisplay handle_display, SelectionRangeFn range_consumer)
void select_adjacent(bke::CurvesGeometry &curves, const IndexMask &curves_mask, const bool deselect)
void foreach_selection_attribute_writer(bke::CurvesGeometry &curves, bke::AttrDomain selection_domain, blender::FunctionRef< void(bke::GSpanAttributeWriter &selection)> fn)
static bke::GSpanAttributeWriter & selection_attribute_writer_by_name(MutableSpan< bke::GSpanAttributeWriter > selections, StringRef attribute_name)
static void invert_selection(MutableSpan< float > selection, const IndexMask &mask)
Span< StringRef > get_curves_bezier_selection_attribute_names(const bke::CurvesGeometry &curves)
void fill_selection_false(GMutableSpan selection)
IndexMask select_lasso_mask(const ViewContext &vc, const bke::CurvesGeometry &curves, const bke::crazyspace::GeometryDeformation &deformation, const float4x4 &projection, const IndexMask &selection_mask, const IndexMask &bezier_mask, const bke::AttrDomain selection_domain, const StringRef attribute_name, const Span< int2 > lasso_coords, IndexMaskMemory &memory)
bool select_circle(const ViewContext &vc, bke::CurvesGeometry &curves, const bke::crazyspace::GeometryDeformation &deformation, const float4x4 &projection, const IndexMask &selection_mask, const IndexMask &bezier_mask, const bke::AttrDomain selection_domain, const int2 coord, const float radius, const eSelectOp sel_op)
static void finish_attribute_writers(MutableSpan< bke::GSpanAttributeWriter > attribute_writers)
IndexMask select_adjacent_mask(const bke::CurvesGeometry &curves, const IndexMask &curves_mask, const StringRef attribute_name, const bool deselect, IndexMaskMemory &memory)
void fill_selection_true(GMutableSpan selection)
Span< StringRef > get_curves_selection_attribute_names(const bke::CurvesGeometry &curves)
void fill_selection(GMutableSpan selection, bool value)
std::optional< FindClosestData > closest_elem_find_screen_space(const ViewContext &vc, const OffsetIndices< int > points_by_curve, const Span< float3 > positions, const VArray< bool > &cyclic, const float4x4 &projection, const IndexMask &mask, const bke::AttrDomain domain, const int2 coord, const FindClosestData &initial_closest)
Span< StringRef > get_curves_all_selection_attribute_names()
static void init_selectable_foreach(const bke::CurvesGeometry &curves, const bke::crazyspace::GeometryDeformation &deformation, eHandleDisplay handle_display, Span< StringRef > &r_bezier_attribute_names, Span< float3 > &r_positions, std::optional< std::array< Span< float3 >, 2 > > &r_bezier_handle_positions, IndexMaskMemory &r_memory, IndexMask &r_bezier_curves)
static std::optional< FindClosestData > find_closest_curve_to_screen_co(const ARegion *region, const OffsetIndices< int > points_by_curve, const Span< float3 > positions, const VArray< bool > &cyclic, const float4x4 &projection, const IndexMask &curves_mask, const float2 mouse_pos, float radius, const FindClosestData &initial_closest)
IndexMask select_box_mask(const ViewContext &vc, const bke::CurvesGeometry &curves, const bke::crazyspace::GeometryDeformation &deformation, const float4x4 &projection, const IndexMask &selection_mask, const IndexMask &bezier_mask, const bke::AttrDomain selection_domain, const StringRef attribute_name, const rcti &rect, IndexMaskMemory &memory)
bool select_lasso(const ViewContext &vc, bke::CurvesGeometry &curves, const bke::crazyspace::GeometryDeformation &deformation, const float4x4 &projection, const IndexMask &selection_mask, const IndexMask &bezier_mask, const bke::AttrDomain selection_domain, const Span< int2 > lasso_coords, const eSelectOp sel_op)
std::optional< Span< float3 > > get_selection_attribute_positions(const bke::CurvesGeometry &curves, const bke::crazyspace::GeometryDeformation &deformation, const StringRef attribute_name)
bke::GSpanAttributeWriter ensure_selection_attribute(bke::CurvesGeometry &curves, bke::AttrDomain selection_domain, bke::AttrType create_type, StringRef attribute_name)
IndexMask retrieve_selected_points(const bke::CurvesGeometry &curves, IndexMaskMemory &memory)
static FindClosestData closer_elem(const FindClosestData &a, const FindClosestData &b)
FunctionRef< void( IndexRange range, Span< float3 > positions, StringRef selection_attribute_name)> SelectionRangeFn
bool select_box(const ViewContext &vc, bke::CurvesGeometry &curves, const bke::crazyspace::GeometryDeformation &deformation, const float4x4 &projection, const IndexMask &selection_mask, const IndexMask &bezier_mask, const bke::AttrDomain selection_domain, const rcti &rect, const eSelectOp sel_op)
void masked_fill(MutableSpan< T > data, const T &value, const IndexMask &mask)
T distance_squared(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
MatBase< float, 4, 4 > float4x4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
static void init(bNodeTree *, bNode *node)