30 const IndexRange curves_range = curves.curves_range();
36 std::optional<bke::AttributeMetaData> meta_data = attributes.
lookup_meta_data(
".selection");
40 const VArray<bool> selection = *attributes.lookup_or_default<
bool>(
42 if (selection.is_single()) {
45 const OffsetIndices points_by_curve = curves.points_by_curve();
48 const IndexRange points = points_by_curve[curve_i];
51 selection.materialize_compressed(points, point_selection);
52 return point_selection.
as_span().contains(
true);
55 const VArray<bool> selection = *attributes.lookup_or_default<
bool>(
88 static const std::array<StringRef, 1> selection_attribute_names{
".selection"};
90 return (attributes.contains(
"handle_type_left") && attributes.contains(
"handle_type_right")) ?
92 selection_attribute_names;
97 static const std::array<StringRef, 3> selection_attribute_names{
98 ".selection",
".selection_handle_left",
".selection_handle_right"};
99 return selection_attribute_names;
104 static const std::array<StringRef, 2> selection_attribute_names{
".selection_handle_left",
105 ".selection_handle_right"};
107 return (attributes.contains(
"handle_type_left") && attributes.contains(
"handle_type_right")) ?
108 selection_attribute_names :
115 for (
const StringRef selection_name : selection_attribute_names) {
116 attributes.remove(selection_name);
125 if (attribute_name ==
".selection") {
126 return deformation.positions;
128 if (attribute_name ==
".selection_handle_left") {
129 return curves.handle_positions_left();
131 if (attribute_name ==
".selection_handle_right") {
132 return curves.handle_positions_right();
144 for (
const int i : selection_attribute_names.
index_range()) {
146 curves, selection_domain, create_type, selection_attribute_names[i]));
153 for (
auto &attribute_writer : attribute_writers) {
154 attribute_writer.finish();
166 if (attribute_name.
size() == selection_attribute_names[index].
size()) {
167 return selections[index];
171 return selections[0];
182 fn(selection_writer);
196 r_positions = deformation.positions;
197 if (r_bezier_attribute_names.
size() > 0) {
198 r_bezier_handle_positions[0] = curves.handle_positions_left();
199 r_bezier_handle_positions[1] = curves.handle_positions_right();
210 std::array<Span<float3>, 2> bezier_handle_positions;
215 bezier_attribute_names,
217 bezier_handle_positions,
221 range_consumer(curves.points_range(), positions,
".selection");
224 for (
const int attribute_i : bezier_attribute_names.
index_range()) {
226 range_consumer(points_by_curve[curve_i],
227 bezier_handle_positions[attribute_i],
228 bezier_attribute_names[attribute_i]);
239 std::array<Span<float3>, 2> bezier_handle_positions;
244 bezier_attribute_names,
246 bezier_handle_positions,
250 range_consumer(curves.curves_range(), positions,
".selection");
252 for (
const int attribute_i : bezier_attribute_names.
index_range()) {
255 curves_range, bezier_handle_positions[attribute_i], bezier_attribute_names[attribute_i]);
266 if (attributes.contains(attribute_name)) {
269 if (selection_attr.
domain == selection_domain) {
270 return selection_attr;
273 attributes.remove(attribute_name);
275 const int domain_size = attributes.domain_size(selection_domain);
276 switch (create_type) {
278 attributes.add(attribute_name,
284 attributes.add(attribute_name,
292 return attributes.lookup_for_write_span(attribute_name);
297 if (selection.type().is<
bool>()) {
298 selection.typed<
bool>().fill(
false);
300 else if (selection.type().is<
float>()) {
301 selection.typed<
float>().fill(0.0f);
307 if (selection.type().is<
bool>()) {
308 selection.typed<
bool>().fill(
true);
310 else if (selection.type().is<
float>()) {
311 selection.typed<
float>().fill(1.0f);
317 if (selection.type().is<
bool>()) {
318 selection.typed<
bool>().fill(value);
320 else if (selection.type().is<
float>()) {
321 selection.typed<
float>().fill(value ? 1.0f : 0.0f);
327 if (selection.type().is<
bool>()) {
330 else if (selection.type().is<
float>()) {
337 if (selection.type().is<
bool>()) {
340 else if (selection.type().is<
float>()) {
351 return *
static_cast<const bool *
>(info.
data) == value;
364 if (std::optional<IndexRange> range = sliced_mask.to_range()) {
369 for (
const int i : segment) {
370 if (span[i] == value) {
380 indices_to_check.index_range(),
387 constexpr int64_t MaxChunkSize = 512;
388 const int64_t slice_end = range.one_after_last();
389 for (
int64_t start = range.start(); start < slice_end; start += MaxChunkSize) {
390 const int64_t end = std::min<int64_t>(start + MaxChunkSize, slice_end);
391 const int64_t size = end - start;
392 const IndexMask sliced_mask = indices_to_check.
slice(start, size);
393 std::array<bool, MaxChunkSize> values;
394 auto values_end = values.begin() +
size;
395 varray.materialize_compressed(sliced_mask, values);
396 if (std::find(values.begin(), values_end, value) != values_end) {
407 return contains(varray,
IndexMask(range_to_check), value);
412 return contains(varray, range_to_check,
true);
417 return contains(varray, indices_to_check,
true);
422 const VArray<bool> selection = *curves.attributes().lookup<
bool>(
".selection");
423 return !selection || contains(selection, selection.index_range(),
true);
429 curves, selection_domain,
IndexRange(curves.attributes().domain_size(selection_domain)));
437 const VArray<bool> selection = *curves.attributes().lookup<
bool>(selection_name,
439 if (!selection || contains(selection, mask,
true)) {
448 if (selection.type().is<
bool>()) {
449 return selection.typed<
bool>().contains(
true);
451 else if (selection.type().is<
float>()) {
452 for (
const float elem : selection.typed<
float>()) {
463 threading::parallel_for(selection.index_range(), 2048, [&](
IndexRange range) {
464 for (const int i : range) {
465 selection[i] = 1.0f - selection[i];
472 if (selection.type().is<
bool>()) {
473 array_utils::invert_booleans(selection.typed<
bool>());
475 else if (selection.type().is<
float>()) {
482 mask.foreach_index_optimized<
int64_t>(
483 GrainSize(2048), [&](
const int64_t i) { selection[i] = 1.0f - selection[i]; });
488 if (selection.type().is<
bool>()) {
489 array_utils::invert_booleans(selection.typed<
bool>(), mask);
491 else if (selection.type().is<
float>()) {
502 std::optional<IndexRange> range = mask.to_range();
503 if (range.has_value() &&
504 (*range ==
IndexRange(curves.attributes().domain_size(selection_domain))))
529 select_all(curves, selection, selection_domain, action);
534 const OffsetIndices points_by_curve = curves.points_by_curve();
538 curves, bke::AttrDomain::Point);
541 for (
const int i : selection_writers.
index_range()) {
546 for (
const int j : selection_writers.
index_range()) {
569 const bool deselect_ends)
575 const OffsetIndices points_by_curve = curves.points_by_curve();
582 const IndexRange points = points_by_curve[curve_i];
587 const int half_of_size = points.
size() / 2;
590 for (
const int i :
IndexRange(half_of_size)) {
591 const int index = i * 2;
592 selection_typed[selected[index]] =
true;
593 selection_typed[deselected[index]] =
false;
596 selection_typed[points.first()] = !deselect_ends;
597 const bool end_parity_to_selected = bool(points.size() % 2);
598 const bool selected_end = cyclic[curve_i] || end_parity_to_selected;
599 selection_typed[points.last()] = !deselect_ends && selected_end;
603 if (!deselect_ends && cyclic[curve_i] && !curve_body.
is_empty()) {
604 selection_typed[curve_body.
last()] =
false;
620 const OffsetIndices points_by_curve = curves.points_by_curve();
629 if (selection.span.type().is<
bool>()) {
632 const IndexRange points = points_by_curve[curve_i];
633 const int first_point = points.first();
634 const int last_point = points.last();
637 for (
int point_i = first_point; point_i < last_point; point_i++) {
638 if (!selection_typed[point_i] && selection_typed[point_i + 1]) {
639 selection_typed[point_i] =
true;
644 for (
int point_i = last_point; point_i > first_point; point_i--) {
645 if (!selection_typed[point_i] && selection_typed[point_i - 1]) {
646 selection_typed[point_i] =
true;
650 if (!selection_typed[first_point]) {
651 selection_typed[first_point] =
true;
653 if (!selection_typed[last_point]) {
654 selection_typed[last_point] =
true;
658 if (cyclic[curve_i]) {
659 if (selection_typed[first_point] != selection_typed[last_point]) {
660 selection_typed[first_point] =
true;
661 selection_typed[last_point] =
true;
666 else if (selection.span.type().is<
float>()) {
669 const IndexRange points = points_by_curve[curve_i];
670 const int first_point = points.first();
671 const int last_point = points.last();
674 for (
int point_i = first_point; point_i < last_point; point_i++) {
675 if ((selection_typed[point_i] == 0.0f) && (selection_typed[point_i + 1] > 0.0f)) {
676 selection_typed[point_i] = 1.0f;
681 for (
int point_i = last_point; point_i > first_point; point_i--) {
682 if ((selection_typed[point_i] == 0.0f) && (selection_typed[point_i - 1] > 0.0f)) {
683 selection_typed[point_i] = 1.0f;
688 if (cyclic[curve_i]) {
689 if (selection_typed[first_point] != selection_typed[last_point]) {
690 selection_typed[first_point] = 1.0f;
691 selection_typed[last_point] = 1.0f;
713 if (selection.type().is<
bool>()) {
718 selection_typed[index] =
true;
721 selection_typed[index] =
false;
724 selection_typed[index] = !selection_typed[index];
730 else if (selection.type().is<
float>()) {
735 selection_typed[index] = 1.0f;
738 selection_typed[index] = 0.0f;
741 selection_typed[index] = 1.0f - selection_typed[index];
758 const float radius_sq =
pow2f(radius);
764 FindClosestData best_match = init;
765 for (const int index : point_indicies_range) {
766 const int point_i = points_mask[index];
767 const float3 pos = positions[point_i];
770 const float2 pos_proj = ED_view3d_project_float_v2_m4(region, pos, projection);
772 const float distance_proj_sq = math::distance_squared(pos_proj, mouse_pos);
773 if (distance_proj_sq > radius_sq ||
774 distance_proj_sq > best_match.distance * best_match.distance)
780 FindClosestData better_candidate;
781 better_candidate.index = point_i;
782 better_candidate.distance = std::sqrt(distance_proj_sq);
784 best_match = better_candidate;
788 [](
const FindClosestData &a,
const FindClosestData &
b) {
789 if (a.distance <
b.distance) {
795 if (new_closest_data.distance < initial_closest.distance) {
796 return new_closest_data;
813 const float radius_sq =
pow2f(radius);
820 FindClosestData best_match = init;
821 for (const int index : curves_indices_range) {
822 const int curve_i = curves_mask[index];
823 const IndexRange points = points_by_curve[curve_i];
824 if (points.size() == 1) {
825 const float3 pos = positions[points.first()];
828 const float2 pos_proj = ED_view3d_project_float_v2_m4(region, pos, projection);
830 const float distance_proj_sq = math::distance_squared(pos_proj, mouse_pos);
831 if (distance_proj_sq > radius_sq ||
832 distance_proj_sq > best_match.distance * best_match.distance)
839 FindClosestData better_candidate;
840 better_candidate.index = curve_i;
841 better_candidate.distance = std::sqrt(distance_proj_sq);
843 best_match = better_candidate;
847 auto process_segment = [&](const int segment_i, const int next_i) {
848 const float3 pos1 = positions[segment_i];
849 const float3 pos2 = positions[next_i];
850 const float2 pos1_proj = ED_view3d_project_float_v2_m4(region, pos1, projection);
851 const float2 pos2_proj = ED_view3d_project_float_v2_m4(region, pos2, projection);
853 const float distance_proj_sq = dist_squared_to_line_segment_v2(
854 mouse_pos, pos1_proj, pos2_proj);
855 if (distance_proj_sq > radius_sq ||
856 distance_proj_sq > best_match.distance * best_match.distance)
863 FindClosestData better_candidate;
864 better_candidate.index = curve_i;
865 better_candidate.distance = std::sqrt(distance_proj_sq);
867 best_match = better_candidate;
869 for (const int segment_i : points.drop_back(1)) {
870 process_segment(segment_i, segment_i + 1);
872 if (cyclic[curve_i]) {
873 process_segment(points.last(), points.first());
878 [](
const FindClosestData &a,
const FindClosestData &
b) {
879 if (a.distance <
b.distance) {
885 if (new_closest_data.distance < initial_closest.distance) {
886 return new_closest_data;
904 case bke::AttrDomain::Point:
912 case bke::AttrDomain::Curve:
941 bool changed =
false;
949 if (selection_domain == bke::AttrDomain::Point) {
954 const IndexMask &mask = (selection_attribute_name ==
".selection") ? selection_mask :
958 vc.
region, positions[point_i], projection);
970 else if (selection_domain == bke::AttrDomain::Curve) {
971 const OffsetIndices points_by_curve = curves.points_by_curve();
981 const IndexRange points = points_by_curve[curve_i];
982 if (points.size() == 1) {
983 const float2 pos_proj = ED_view3d_project_float_v2_m4(
984 vc.region, positions[points.first()], projection);
985 if (BLI_rcti_isect_pt_v(&rect, int2(pos_proj))) {
986 for (bke::GSpanAttributeWriter &selection : selection_writers) {
987 apply_selection_operation_at_index(selection.span, curve_i, sel_op);
993 auto process_segment = [&](
const int segment_i,
const int next_i) {
994 const float3 pos1 = positions[segment_i];
995 const float3 pos2 = positions[next_i];
1009 bool segment_selected =
false;
1010 for (
const int segment_i : points.drop_back(1)) {
1011 if (process_segment(segment_i, segment_i + 1)) {
1012 segment_selected =
true;
1016 if (!segment_selected && cyclic[curve_i]) {
1017 process_segment(points.last(), points.first());
1022 finish_attribute_writers(selection_writers);
1040 bool changed =
false;
1048 if (selection_domain == bke::AttrDomain::Point) {
1053 const IndexMask &mask = (selection_attribute_name ==
".selection") ? selection_mask :
1057 vc.
region, positions[point_i], projection_matrix);
1061 lasso_coords,
int(pos_proj.x),
int(pos_proj.y),
IS_CLIPPED))
1073 else if (selection_domain == bke::AttrDomain::Curve) {
1074 const OffsetIndices points_by_curve = curves.points_by_curve();
1084 const IndexRange points = points_by_curve[curve_i];
1085 if (points.size() == 1) {
1086 const float2 pos_proj = ED_view3d_project_float_v2_m4(
1087 vc.region, positions[points.first()], projection_matrix);
1089 if (BLI_rcti_isect_pt_v(&bbox, int2(pos_proj)) &&
1090 BLI_lasso_is_point_inside(
1091 lasso_coords, int(pos_proj.x), int(pos_proj.y), IS_CLIPPED))
1093 for (bke::GSpanAttributeWriter &selection : selection_writers) {
1094 apply_selection_operation_at_index(selection.span, curve_i, sel_op);
1100 auto process_segment = [&](
const int segment_i,
const int next_i) {
1101 const float3 pos1 = positions[segment_i];
1102 const float3 pos2 = positions[next_i];
1105 vc.
region, pos1, projection_matrix);
1107 vc.
region, pos2, projection_matrix);
1126 bool segment_selected =
false;
1127 for (
const int segment_i : points.drop_back(cyclic[curve_i] ? 0 : 1)) {
1128 if (process_segment(segment_i, segment_i + 1)) {
1129 segment_selected =
true;
1133 if (!segment_selected && cyclic[curve_i]) {
1134 process_segment(points.last(), points.first());
1139 finish_attribute_writers(selection_writers);
1154 const float radius_sq =
pow2f(radius);
1157 bool changed =
false;
1165 if (selection_domain == bke::AttrDomain::Point) {
1170 const IndexMask &mask = (selection_attribute_name ==
".selection") ? selection_mask :
1174 vc.
region, positions[point_i], projection);
1186 else if (selection_domain == bke::AttrDomain::Curve) {
1187 const OffsetIndices points_by_curve = curves.points_by_curve();
1197 const IndexRange points = points_by_curve[curve_i];
1198 if (points.size() == 1) {
1199 const float2 pos_proj = ED_view3d_project_float_v2_m4(
1200 vc.region, positions[points.first()], projection);
1201 if (math::distance_squared(pos_proj, float2(coord)) <= radius_sq) {
1202 for (bke::GSpanAttributeWriter &selection : selection_writers) {
1203 apply_selection_operation_at_index(selection.span, curve_i, sel_op);
1209 auto process_segments = [&](
const int segment_i,
const int next_i) {
1210 const float3 pos1 = positions[segment_i];
1211 const float3 pos2 = positions[next_i];
1217 float2(coord), pos1_proj, pos2_proj);
1218 if (distance_proj_sq <= radius_sq) {
1227 bool segment_selected =
false;
1228 for (
const int segment_i : points.drop_back(1)) {
1229 if (process_segments(segment_i, segment_i + 1)) {
1230 segment_selected =
true;
1234 if (!segment_selected && cyclic[curve_i]) {
1235 process_segments(points.last(), points.first());
1240 finish_attribute_writers(selection_writers);
1244template<
typename Po
intSelectFn,
typename LineSelectFn>
1249 PointSelectFn &&point_predicate,
1250 LineSelectFn &&line_predicate)
1252 const OffsetIndices points_by_curve = curves.points_by_curve();
1255 if (selection_domain == bke::AttrDomain::Point) {
1256 return IndexMask::from_predicate(
1257 mask.slice_content(curves.points_range()),
GrainSize(1024), memory, point_predicate);
1259 if (selection_domain == bke::AttrDomain::Curve) {
1260 return IndexMask::from_predicate(
1261 mask.slice_content(curves.curves_range()),
1264 [&](
const int curve_i) ->
bool {
1265 const IndexRange points = points_by_curve[curve_i];
1269 if (points.size() == 1) {
1270 return point_predicate(points.first());
1273 for (
const int point_i : points.drop_back(1)) {
1274 if (line_predicate(curve_i, point_i, point_i + 1)) {
1279 if (line_predicate(curve_i, points.last(), points.first())) {
1292 const bool deselect,
1295 const OffsetIndices points_by_curve = curves.points_by_curve();
1299 attribute_name, bke::AttrDomain::Point,
true);
1304 auto is_point_changed1 = [&](
const int point,
const int neighbor) {
1305 return deselect ? (selection[
point] && !selection[neighbor]) :
1306 (!selection[
point] && selection[neighbor]);
1308 auto is_point_changed2 = [&](
const int point,
const int neighbor1,
const int neighbor2) {
1309 return deselect ? (selection[
point] && (!selection[neighbor1] || !selection[neighbor2])) :
1310 (!selection[
point] && (selection[neighbor1] || selection[neighbor2]));
1314 const IndexRange points = points_by_curve[curve_i];
1315 if (points.size() == 1) {
1320 if (cyclic[curve_i]) {
1321 changed_points[points.first()] = is_point_changed2(
1322 points.first(), points.last(), points.first() + 1);
1323 for (
const int point_i : points.drop_front(1).drop_back(1)) {
1324 changed_points[point_i] = is_point_changed2(point_i, point_i - 1, point_i + 1);
1326 changed_points[points.last()] = is_point_changed2(
1327 points.last(), points.last() - 1, points.first());
1330 changed_points[points.first()] = is_point_changed1(points.first(), points.first() + 1);
1331 for (
const int point_i : points.drop_front(1).drop_back(1)) {
1332 changed_points[point_i] = is_point_changed2(point_i, point_i - 1, point_i + 1);
1334 changed_points[points.last()] = is_point_changed1(points.last(), points.last() - 1);
1338 return IndexMask::from_bools(changed_points, memory);
1343 const bool deselect,
1361 curves, deformation, attribute_name);
1363 auto point_predicate = [&](
const int point_i) {
1365 vc.
region, positions[point_i], projection);
1369 auto line_predicate = [&](
const int ,
const int point_i,
const int next_point_i) {
1371 vc.
region, positions[point_i], projection);
1373 vc.
region, positions[next_point_i], projection);
1377 const IndexMask &mask = (selection_domain != bke::AttrDomain::Point ||
1378 attribute_name ==
".selection") ?
1382 curves, mask, selection_domain, memory, point_predicate, line_predicate);
1399 curves, deformation, attribute_name);
1401 auto point_predicate = [&](
const int point_i) {
1403 vc.
region, positions[point_i], projection);
1408 auto line_predicate = [&](
const int ,
const int point_i,
const int next_point_i) {
1410 vc.
region, positions[point_i], projection);
1412 vc.
region, positions[next_point_i], projection);
1417 int(next_pos_proj.x),
1418 int(next_pos_proj.y),
1422 const IndexMask &mask = (selection_domain != bke::AttrDomain::Point ||
1423 attribute_name ==
".selection") ?
1427 curves, mask, selection_domain, memory, point_predicate, line_predicate);
1442 const float radius_sq =
pow2f(radius);
1444 curves, deformation, attribute_name);
1446 auto point_predicate = [&](
const int point_i) {
1448 vc.
region, positions[point_i], projection);
1450 return distance_proj_sq <= radius_sq;
1452 auto line_predicate = [&](
const int ,
const int point_i,
const int next_point_i) {
1454 vc.
region, positions[point_i], projection);
1456 vc.
region, positions[next_point_i], projection);
1458 float2(coord), pos_proj, next_pos_proj);
1459 return distance_proj_sq <= radius_sq;
1462 const IndexMask &mask = (selection_domain != bke::AttrDomain::Point ||
1463 attribute_name ==
".selection") ?
1467 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()
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Span< T > as_span() const
GMutableSpan slice(const int64_t start, int64_t size) 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 bool is_empty() const
constexpr IndexRange drop_front(int64_t n) const
constexpr IndexRange index_range() const
constexpr Span slice(int64_t start, int64_t size) const
constexpr int64_t size() const
constexpr IndexRange index_range() const
constexpr bool contains(const T &value) const
constexpr int64_t size() const
T get_internal_single() const
CommonVArrayInfo common_info() const
void append(const T &value)
IndexRange index_range() const
std::optional< AttributeMetaData > lookup_meta_data(const StringRef attribute_id) const
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
IndexMask slice_content(IndexRange range) const
IndexMask slice(IndexRange range) const
IndexRange index_range() const
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
void foreach_range(Fn &&fn) const
void foreach_index(Fn &&fn) const
local_group_size(16, 16) .push_constant(Type b
static bool is_cyclic(const Nurb *nu)
bool has_anything_selected(const VArray< bool > &varray, const IndexRange range_to_check)
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)
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 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, float radius, const FindClosestData &initial_closest)
IndexMask retrieve_selected_curves(const bke::CurvesGeometry &curves, IndexMaskMemory &memory)
void remove_selection_attributes(bke::MutableAttributeAccessor &attributes, Span< StringRef > selection_attribute_names)
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)
Span< float3 > get_selection_attribute_positions(const bke::CurvesGeometry &curves, const bke::crazyspace::GeometryDeformation &deformation, const StringRef attribute_name)
static void invert_selection(MutableSpan< float > selection)
static void init_selectable_foreach(const bke::CurvesGeometry &curves, const bke::crazyspace::GeometryDeformation &deformation, 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 foreach_selectable_point_range(const bke::CurvesGeometry &curves, const bke::crazyspace::GeometryDeformation &deformation, 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)
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)
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)
void foreach_selectable_curve_range(const bke::CurvesGeometry &curves, const bke::crazyspace::GeometryDeformation &deformation, SelectionRangeFn range_consumer)
bool select_lasso(const ViewContext &vc, bke::CurvesGeometry &curves, const bke::crazyspace::GeometryDeformation &deformation, const float4x4 &projection_matrix, const IndexMask &selection_mask, const IndexMask &bezier_mask, const bke::AttrDomain selection_domain, const Span< int2 > lasso_coords, const eSelectOp sel_op)
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)
GPU_SHADER_INTERFACE_INFO(overlay_edit_curve_handle_iface, "vert").flat(Type pos vertex_in(1, Type::UINT, "data") .vertex_out(overlay_edit_curve_handle_iface) .geometry_layout(PrimitiveIn Frequency::GEOMETRY storage_buf(1, Qualifier::READ, "uint", "data[]", Frequency::GEOMETRY) .push_constant(Type Frequency::GEOMETRY selection[]