34 std::optional<bke::AttributeMetaData> meta_data = attributes.
lookup_meta_data(
".selection");
46 const IndexRange points = points_by_curve[curve];
50 return point_selection.
as_span().contains(
true);
73 selection_by_attribute.
append(
96 static const std::array<StringRef, 1> selection_attribute_names{
".selection"};
99 selection_attribute_names;
104 static const std::array<StringRef, 3> selection_attribute_names{
105 ".selection",
".selection_handle_left",
".selection_handle_right"};
106 return selection_attribute_names;
111 static const std::array<StringRef, 2> selection_attribute_names{
".selection_handle_left",
112 ".selection_handle_right"};
114 return (attributes.
contains(
"handle_type_left") && attributes.
contains(
"handle_type_right")) ?
115 selection_attribute_names :
122 for (
const StringRef selection_name : selection_attribute_names) {
123 attributes.
remove(selection_name);
132 if (attribute_name ==
".selection") {
135 if (attribute_name ==
".selection_handle_left") {
136 return curves.handle_positions_left();
138 if (attribute_name ==
".selection_handle_right") {
139 return curves.handle_positions_right();
151 for (
const int i : selection_attribute_names.
index_range()) {
153 curves, selection_domain, create_type, selection_attribute_names[
i]));
160 for (
auto &attribute_writer : attribute_writers) {
161 attribute_writer.finish();
173 if (attribute_name.
size() == selection_attribute_names[index].
size()) {
174 return selections[index];
178 return selections[0];
189 fn(selection_writer);
205 if (handle_display != eHandleDisplay::CURVE_HANDLE_NONE && r_bezier_attribute_names.
size() > 0) {
206 r_bezier_handle_positions[0] =
curves.handle_positions_left();
207 r_bezier_handle_positions[1] =
curves.handle_positions_right();
219 std::array<Span<float3>, 2> bezier_handle_positions;
225 bezier_attribute_names,
227 bezier_handle_positions,
231 range_consumer(
curves.points_range(), positions,
".selection");
233 if (handle_display == eHandleDisplay::CURVE_HANDLE_NONE) {
238 for (
const int attribute_i : bezier_attribute_names.
index_range()) {
240 range_consumer(points_by_curve[curve],
241 bezier_handle_positions[attribute_i],
242 bezier_attribute_names[attribute_i]);
254 std::array<Span<float3>, 2> bezier_handle_positions;
260 bezier_attribute_names,
262 bezier_handle_positions,
266 range_consumer(
curves.curves_range(), positions,
".selection");
267 if (handle_display == eHandleDisplay::CURVE_HANDLE_NONE) {
271 for (
const int attribute_i : bezier_attribute_names.
index_range()) {
274 curves_range, bezier_handle_positions[attribute_i], bezier_attribute_names[attribute_i]);
285 if (attributes.
contains(attribute_name)) {
288 if (selection_attr.
domain == selection_domain) {
289 return selection_attr;
292 attributes.
remove(attribute_name);
294 const int domain_size = attributes.
domain_size(selection_domain);
295 switch (create_type) {
297 attributes.
add(attribute_name,
303 attributes.
add(attribute_name,
316 if (selection.
type().
is<
bool>()) {
317 selection.
typed<
bool>().fill(
false);
319 else if (selection.
type().
is<
float>()) {
320 selection.
typed<
float>().fill(0.0f);
326 if (selection.
type().
is<
bool>()) {
327 selection.
typed<
bool>().fill(
true);
329 else if (selection.
type().
is<
float>()) {
330 selection.
typed<
float>().fill(1.0f);
336 if (selection.
type().
is<
bool>()) {
337 selection.
typed<
bool>().fill(value);
339 else if (selection.
type().
is<
float>()) {
340 selection.
typed<
float>().fill(value ? 1.0f : 0.0f);
346 if (selection.
type().
is<
bool>()) {
349 else if (selection.
type().
is<
float>()) {
356 if (selection.
type().
is<
bool>()) {
359 else if (selection.
type().
is<
float>()) {
370 return *
static_cast<const bool *
>(info.
data) == value;
383 if (std::optional<IndexRange> range = sliced_mask.to_range()) {
384 return span.slice(*range).contains(value);
387 const IndexMaskSegment segment = sliced_mask.segment(segment_i);
388 for (const int i : segment) {
389 if (span[i] == value) {
399 indices_to_check.index_range(),
406 constexpr int64_t MaxChunkSize = 512;
408 for (
int64_t start = range.
start(); start < slice_end; start += MaxChunkSize) {
409 const int64_t end = std::min<int64_t>(start + MaxChunkSize, slice_end);
410 const int64_t size = end - start;
411 const IndexMask sliced_mask = indices_to_check.slice(start, size);
412 std::array<bool, MaxChunkSize> values;
413 auto values_end = values.begin() + size;
414 varray.materialize_compressed(sliced_mask, values);
415 if (std::find(values.begin(), values_end, value) != values_end) {
431 return contains(varray, range_to_check,
true);
436 return contains(varray, indices_to_check,
true);
467 if (selection.
type().
is<
bool>()) {
470 if (selection.
type().
is<
float>()) {
471 for (
const float elem : selection.
typed<
float>()) {
488 if (selection.
type().
is<
bool>()) {
491 else if (selection.
type().
is<
float>()) {
507 std::optional<IndexRange> range =
mask.to_range();
508 if (range.has_value() &&
533 const IndexRange selection(
curves.attributes().domain_size(selection_domain));
552 const IndexRange points = points_by_curve[curve];
554 for (
const int i : curve_writers) {
559 for (
const int j : curve_writers) {
579 const bool deselect_ends)
592 const IndexRange points = points_by_curve[curve];
597 const int half_of_size = points.
size() / 2;
601 const int index =
i * 2;
602 selection_typed[selected[index]] =
true;
603 selection_typed[deselected[index]] =
false;
606 selection_typed[points.
first()] = !deselect_ends;
607 const bool end_parity_to_selected = bool(points.
size() % 2);
608 const bool selected_end = cyclic[curve] || end_parity_to_selected;
609 selection_typed[points.
last()] = !deselect_ends && selected_end;
613 if (!deselect_ends && cyclic[curve] && !curve_body.
is_empty()) {
614 selection_typed[curve_body.
last()] =
false;
642 const IndexRange points = points_by_curve[curve];
643 const int first_point = points.
first();
644 const int last_point = points.
last();
647 for (
int point = first_point; point < last_point; point++) {
648 if (!selection_typed[point] && selection_typed[point + 1]) {
649 selection_typed[point] =
true;
654 for (
int point = last_point; point > first_point; point--) {
655 if (!selection_typed[point] && selection_typed[point - 1]) {
656 selection_typed[point] =
true;
660 if (!selection_typed[first_point]) {
661 selection_typed[first_point] =
true;
663 if (!selection_typed[last_point]) {
664 selection_typed[last_point] =
true;
669 if (selection_typed[first_point] != selection_typed[last_point]) {
670 selection_typed[first_point] =
true;
671 selection_typed[last_point] =
true;
679 const IndexRange points = points_by_curve[curve];
680 const int first_point = points.
first();
681 const int last_point = points.
last();
684 for (
int point_i = first_point; point_i < last_point; point_i++) {
685 if ((selection_typed[point_i] == 0.0f) && (selection_typed[point_i + 1] > 0.0f)) {
686 selection_typed[point_i] = 1.0f;
691 for (
int point_i = last_point; point_i > first_point; point_i--) {
692 if ((selection_typed[point_i] == 0.0f) && (selection_typed[point_i - 1] > 0.0f)) {
693 selection_typed[point_i] = 1.0f;
699 if (selection_typed[first_point] != selection_typed[last_point]) {
700 selection_typed[first_point] = 1.0f;
701 selection_typed[last_point] = 1.0f;
723 if (selection.
type().
is<
bool>()) {
728 selection_typed[index] =
true;
731 selection_typed[index] =
false;
734 selection_typed[index] = !selection_typed[index];
740 else if (selection.
type().
is<
float>()) {
745 selection_typed[index] = 1.0f;
748 selection_typed[index] = 0.0f;
751 selection_typed[index] = 1.0f - selection_typed[index];
776 const float radius_sq =
pow2f(radius);
782 FindClosestData best_match = init;
783 points_mask.slice(range).foreach_index([&](const int point) {
784 const float3 &pos = positions[point];
785 const float2 pos_proj = ED_view3d_project_float_v2_m4(region, pos, projection);
787 const float distance_proj_sq = math::distance_squared(pos_proj, mouse_pos);
788 if (distance_proj_sq > radius_sq || distance_proj_sq > best_match.distance_sq) {
792 best_match = {point, distance_proj_sq};
798 if (new_closest_data.distance_sq < initial_closest.distance_sq) {
799 return new_closest_data;
816 const float radius_sq =
pow2f(radius);
823 FindClosestData best_match = init;
824 curves_mask.slice(range).foreach_index([&](const int curve) {
825 const IndexRange points = points_by_curve[curve];
827 if (points.size() == 1) {
828 const float3 &pos = positions[points.first()];
829 const float2 pos_proj = ED_view3d_project_float_v2_m4(region, pos, projection);
831 const float distance_proj_sq = math::distance_squared(pos_proj, mouse_pos);
832 if (distance_proj_sq > radius_sq || distance_proj_sq > best_match.distance_sq) {
836 best_match = {curve, distance_proj_sq};
840 auto process_segment = [&](const int segment_i, const int next_i) {
841 const float3 &pos1 = positions[segment_i];
842 const float3 &pos2 = positions[next_i];
843 const float2 pos1_proj = ED_view3d_project_float_v2_m4(region, pos1, projection);
844 const float2 pos2_proj = ED_view3d_project_float_v2_m4(region, pos2, projection);
846 const float distance_proj_sq = dist_squared_to_line_segment_v2(
847 mouse_pos, pos1_proj, pos2_proj);
848 if (distance_proj_sq > radius_sq || distance_proj_sq > best_match.distance_sq) {
852 best_match = {curve, distance_proj_sq};
854 for (const int segment_i : points.drop_back(1)) {
855 process_segment(segment_i, segment_i + 1);
858 process_segment(points.last(), points.first());
865 if (new_closest_data.distance_sq < initial_closest.distance_sq) {
866 return new_closest_data;
921 bool changed =
false;
935 const IndexMask &mask = (selection_attribute_name ==
".selection") ? selection_mask :
937 mask.slice_content(range).foreach_index(GrainSize(1024), [&](const int point) {
938 const float2 pos_proj = ED_view3d_project_float_v2_m4(
939 vc.region, positions[point], projection);
940 if (BLI_rcti_isect_pt_v(&rect, int2(pos_proj))) {
941 apply_selection_operation_at_index(
942 selection_attribute_writer_by_name(selection_writers, selection_attribute_name)
954 foreach_selectable_curve_range(
961 const IndexMask &mask = selection_mask;
962 mask.slice_content(range).foreach_index(GrainSize(512), [&](const int curve) {
963 const IndexRange points = points_by_curve[curve];
964 if (points.size() == 1) {
965 const float2 pos_proj = ED_view3d_project_float_v2_m4(
966 vc.region, positions[points.first()], projection);
967 if (BLI_rcti_isect_pt_v(&rect, int2(pos_proj))) {
968 for (bke::GSpanAttributeWriter &selection : selection_writers) {
969 apply_selection_operation_at_index(selection.span, curve, sel_op);
975 auto process_segment = [&](const int segment_i, const int next_i) {
976 const float3 &pos1 = positions[segment_i];
977 const float3 &pos2 = positions[next_i];
978 const float2 pos1_proj = ED_view3d_project_float_v2_m4(vc.region, pos1, projection);
979 const float2 pos2_proj = ED_view3d_project_float_v2_m4(vc.region, pos2, projection);
981 if (BLI_rcti_isect_segment(&rect, int2(pos1_proj), int2(pos2_proj))) {
982 for (bke::GSpanAttributeWriter &selection : selection_writers) {
983 apply_selection_operation_at_index(selection.span, curve, sel_op);
990 bool segment_selected = false;
991 for (const int segment_i : points.drop_back(1)) {
992 if (process_segment(segment_i, segment_i + 1)) {
993 segment_selected = true;
997 if (!segment_selected && cyclic[curve]) {
998 process_segment(points.last(), points.first());
1003 finish_attribute_writers(selection_writers);
1021 bool changed =
false;
1035 const IndexMask &mask = (selection_attribute_name ==
".selection") ? selection_mask :
1037 mask.slice_content(range).foreach_index(GrainSize(1024), [&](const int point) {
1038 const float2 pos_proj = ED_view3d_project_float_v2_m4(
1039 vc.region, positions[point], projection);
1041 if (BLI_rcti_isect_pt_v(&bbox, int2(pos_proj)) &&
1042 BLI_lasso_is_point_inside(
1043 lasso_coords, int(pos_proj.x), int(pos_proj.y), IS_CLIPPED))
1045 apply_selection_operation_at_index(
1046 selection_attribute_writer_by_name(selection_writers, selection_attribute_name)
1058 foreach_selectable_curve_range(
1065 const IndexMask &mask = selection_mask;
1066 mask.slice_content(range).foreach_index(GrainSize(512), [&](const int curve) {
1067 const IndexRange points = points_by_curve[curve];
1068 if (points.size() == 1) {
1069 const float2 pos_proj = ED_view3d_project_float_v2_m4(
1070 vc.region, positions[points.first()], projection);
1072 if (BLI_rcti_isect_pt_v(&bbox, int2(pos_proj)) &&
1073 BLI_lasso_is_point_inside(
1074 lasso_coords, int(pos_proj.x), int(pos_proj.y), IS_CLIPPED))
1076 for (bke::GSpanAttributeWriter &selection : selection_writers) {
1077 apply_selection_operation_at_index(selection.span, curve, sel_op);
1083 auto process_segment = [&](const int segment_i, const int next_i) {
1084 const float3 &pos1 = positions[segment_i];
1085 const float3 &pos2 = positions[next_i];
1086 const float2 pos1_proj = ED_view3d_project_float_v2_m4(vc.region, pos1, projection);
1087 const float2 pos2_proj = ED_view3d_project_float_v2_m4(vc.region, pos2, projection);
1090 if (BLI_rcti_isect_segment(&bbox, int2(pos1_proj), int2(pos2_proj)) &&
1091 BLI_lasso_is_edge_inside(lasso_coords,
1098 for (bke::GSpanAttributeWriter &selection : selection_writers) {
1099 apply_selection_operation_at_index(selection.span, curve, sel_op);
1106 bool segment_selected = false;
1107 for (const int segment_i : points.drop_back(cyclic[curve] ? 0 : 1)) {
1108 if (process_segment(segment_i, segment_i + 1)) {
1109 segment_selected = true;
1113 if (!segment_selected && cyclic[curve]) {
1114 process_segment(points.last(), points.first());
1119 finish_attribute_writers(selection_writers);
1134 const float radius_sq =
pow2f(radius);
1137 bool changed =
false;
1151 const IndexMask &mask = (selection_attribute_name ==
".selection") ? selection_mask :
1153 mask.slice_content(range).foreach_index(GrainSize(1024), [&](const int point) {
1154 const float2 pos_proj = ED_view3d_project_float_v2_m4(
1155 vc.region, positions[point], projection);
1156 if (math::distance_squared(pos_proj, float2(coord)) <= radius_sq) {
1157 apply_selection_operation_at_index(
1158 selection_attribute_writer_by_name(selection_writers, selection_attribute_name)
1170 foreach_selectable_curve_range(
1177 const IndexMask &mask = selection_mask;
1178 mask.slice_content(range).foreach_index(GrainSize(512), [&](const int curve) {
1179 const IndexRange points = points_by_curve[curve];
1180 if (points.size() == 1) {
1181 const float2 pos_proj = ED_view3d_project_float_v2_m4(
1182 vc.region, positions[points.first()], projection);
1183 if (math::distance_squared(pos_proj, float2(coord)) <= radius_sq) {
1184 for (bke::GSpanAttributeWriter &selection : selection_writers) {
1185 apply_selection_operation_at_index(selection.span, curve, sel_op);
1191 auto process_segments = [&](const int segment_i, const int next_i) {
1192 const float3 &pos1 = positions[segment_i];
1193 const float3 &pos2 = positions[next_i];
1194 const float2 pos1_proj = ED_view3d_project_float_v2_m4(vc.region, pos1, projection);
1195 const float2 pos2_proj = ED_view3d_project_float_v2_m4(vc.region, pos2, projection);
1197 const float distance_proj_sq = dist_squared_to_line_segment_v2(
1198 float2(coord), pos1_proj, pos2_proj);
1199 if (distance_proj_sq <= radius_sq) {
1200 for (bke::GSpanAttributeWriter &selection : selection_writers) {
1201 apply_selection_operation_at_index(selection.span, curve, sel_op);
1208 bool segment_selected = false;
1209 for (const int segment_i : points.drop_back(1)) {
1210 if (process_segments(segment_i, segment_i + 1)) {
1211 segment_selected = true;
1215 if (!segment_selected && cyclic[curve]) {
1216 process_segments(points.last(), points.first());
1221 finish_attribute_writers(selection_writers);
1225template<
typename Po
intSelectFn,
typename LineSelectFn>
1230 PointSelectFn &&point_predicate,
1231 LineSelectFn &&line_predicate)
1244 [&](
const int curve) ->
bool {
1245 const IndexRange points = points_by_curve[curve];
1250 if (points.
size() == 1) {
1251 return point_predicate(points.
first());
1254 for (
const int point : points.
drop_back(1)) {
1255 if (line_predicate(curve, point, point + 1)) {
1260 if (line_predicate(curve, points.
last(), points.
first()))
1274 const bool deselect,
1286 auto is_point_changed1 = [&](
const int point,
const int neighbor) {
1287 return deselect ? (selection[point] && !selection[neighbor]) :
1288 (!selection[point] && selection[neighbor]);
1290 auto is_point_changed2 = [&](
const int point,
const int neighbor1,
const int neighbor2) {
1291 return deselect ? (selection[point] && (!selection[neighbor1] || !selection[neighbor2])) :
1292 (!selection[point] && (selection[neighbor1] || selection[neighbor2]));
1296 const IndexRange points = points_by_curve[curve];
1297 if (points.
size() == 1) {
1302 if (cyclic[curve]) {
1303 changed_points[points.
first()] = is_point_changed2(
1306 changed_points[point] = is_point_changed2(point, point - 1, point + 1);
1308 changed_points[points.
last()] = is_point_changed2(
1312 changed_points[points.
first()] = is_point_changed1(points.
first(), points.
first() + 1);
1314 changed_points[point] = is_point_changed2(point, point - 1, point + 1);
1316 changed_points[points.
last()] = is_point_changed1(points.
last(), points.
last() - 1);
1325 const bool deselect,
1343 curves, deformation, attribute_name);
1345 auto point_predicate = [&](
const int point) {
1350 auto line_predicate = [&](
const int ,
const int point,
const int next_point_i) {
1353 vc.
region, positions[next_point_i], projection);
1358 attribute_name ==
".selection") ?
1362 curves,
mask, selection_domain, memory, point_predicate, line_predicate);
1379 curves, deformation, attribute_name);
1381 auto point_predicate = [&](
const int point) {
1387 auto line_predicate = [&](
const int ,
const int point,
const int next_point_i) {
1390 vc.
region, positions[next_point_i], projection);
1395 int(next_pos_proj.x),
1396 int(next_pos_proj.y),
1401 attribute_name ==
".selection") ?
1405 curves,
mask, selection_domain, memory, point_predicate, line_predicate);
1420 const float radius_sq =
pow2f(radius);
1422 curves, deformation, attribute_name);
1424 auto point_predicate = [&](
const int point) {
1427 return distance_proj_sq <= radius_sq;
1429 auto line_predicate = [&](
const int ,
const int point,
const int next_point_i) {
1432 vc.
region, positions[next_point_i], projection);
1434 float2(coord), pos_proj, next_pos_proj);
1435 return distance_proj_sq <= radius_sq;
1439 attribute_name ==
".selection") ?
1443 curves,
mask, selection_domain, memory, point_predicate, line_predicate);
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()
for(;discarded_id_iter !=nullptr;discarded_id_iter=static_cast< ID * >(discarded_id_iter->next))
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 int64_t one_after_last() 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 int64_t start() 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
CommonVArrayInfo common_info() const
static VArray ForSingle(T value, const int64_t size)
void append(const T &value)
bool contains(StringRef attribute_id) const
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
int domain_size(const AttrDomain domain) const
std::optional< AttributeMetaData > lookup_meta_data(StringRef attribute_id) const
bool remove(const StringRef attribute_id)
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
GSpanAttributeWriter lookup_for_write_span(StringRef attribute_id)
IndexMask slice(IndexRange range) const
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)
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_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)
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::array< Span< float3 >, 2 > &r_bezier_handle_positions, IndexMaskMemory &r_memory, IndexMask &r_bezier_curves)
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)
Span< float3 > get_selection_attribute_positions(const bke::CurvesGeometry &curves, const bke::crazyspace::GeometryDeformation &deformation, const StringRef attribute_name)
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)
IndexMask retrieve_all_selected_points(const bke::CurvesGeometry &curves, IndexMaskMemory &memory)
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 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)
bke::GSpanAttributeWriter ensure_selection_attribute(bke::CurvesGeometry &curves, bke::AttrDomain selection_domain, eCustomDataType create_type, StringRef attribute_name)
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)
static bool contains(const VArray< bool > &varray, const IndexMask &indices_to_check, const bool value)
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)