Cleanup: Various changes in curves selection code
- Change variable names for consistency - Split common code to function - Create simple struct with curly brackets - Avoid random access to IndexMask - Remove obvious comments - Use const references for float3
This commit is contained in:
@@ -44,8 +44,8 @@ IndexMask retrieve_selected_curves(const bke::CurvesGeometry &curves, IndexMaskM
|
||||
}
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
return IndexMask::from_predicate(
|
||||
curves_range, GrainSize(512), memory, [&](const int64_t curve_i) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
curves_range, GrainSize(512), memory, [&](const int64_t curve) {
|
||||
const IndexRange points = points_by_curve[curve];
|
||||
/* The curve is selected if any of its points are selected. */
|
||||
Array<bool, 32> point_selection(points.size());
|
||||
selection.materialize_compressed(points, point_selection);
|
||||
@@ -228,8 +228,8 @@ void foreach_selectable_point_range(const bke::CurvesGeometry &curves,
|
||||
|
||||
OffsetIndices<int> points_by_curve = curves.points_by_curve();
|
||||
for (const int attribute_i : bezier_attribute_names.index_range()) {
|
||||
bezier_curves.foreach_index(GrainSize(512), [&](const int64_t curve_i) {
|
||||
range_consumer(points_by_curve[curve_i],
|
||||
bezier_curves.foreach_index(GrainSize(512), [&](const int64_t curve) {
|
||||
range_consumer(points_by_curve[curve],
|
||||
bezier_handle_positions[attribute_i],
|
||||
bezier_attribute_names[attribute_i]);
|
||||
});
|
||||
@@ -548,21 +548,21 @@ void select_linked(bke::CurvesGeometry &curves, const IndexMask &curves_mask)
|
||||
Vector<bke::GSpanAttributeWriter> selection_writers = init_selection_writers(
|
||||
curves, bke::AttrDomain::Point);
|
||||
|
||||
curves_mask.foreach_index(GrainSize(256), [&](const int64_t curve_i) {
|
||||
curves_mask.foreach_index(GrainSize(256), [&](const int64_t curve) {
|
||||
for (const int i : selection_writers.index_range()) {
|
||||
bke::GSpanAttributeWriter &selection = selection_writers[i];
|
||||
GMutableSpan selection_curve = selection.span.slice(points_by_curve[curve_i]);
|
||||
GMutableSpan selection_curve = selection.span.slice(points_by_curve[curve]);
|
||||
if (has_anything_selected(selection_curve)) {
|
||||
fill_selection_true(selection_curve);
|
||||
for (const int j : selection_writers.index_range()) {
|
||||
if (j == i) {
|
||||
continue;
|
||||
}
|
||||
fill_selection_true(selection_writers[j].span.slice(points_by_curve[curve_i]));
|
||||
fill_selection_true(selection_writers[j].span.slice(points_by_curve[curve]));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (curve_types[curve_i] != CURVE_TYPE_BEZIER) {
|
||||
if (curve_types[curve] != CURVE_TYPE_BEZIER) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -589,8 +589,8 @@ void select_alternate(bke::CurvesGeometry &curves,
|
||||
const VArray<bool> cyclic = curves.cyclic();
|
||||
|
||||
MutableSpan<bool> selection_typed = selection.span.typed<bool>();
|
||||
curves_mask.foreach_index([&](const int64_t curve_i) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
curves_mask.foreach_index([&](const int64_t curve) {
|
||||
const IndexRange points = points_by_curve[curve];
|
||||
if (!has_anything_selected(selection.span.slice(points))) {
|
||||
return;
|
||||
}
|
||||
@@ -606,12 +606,12 @@ void select_alternate(bke::CurvesGeometry &curves,
|
||||
|
||||
selection_typed[points.first()] = !deselect_ends;
|
||||
const bool end_parity_to_selected = bool(points.size() % 2);
|
||||
const bool selected_end = cyclic[curve_i] || end_parity_to_selected;
|
||||
const bool selected_end = cyclic[curve] || end_parity_to_selected;
|
||||
selection_typed[points.last()] = !deselect_ends && selected_end;
|
||||
|
||||
/* Selected last one require to deselect pre-last one point which is not first. */
|
||||
const IndexRange curve_body = points.drop_front(1).drop_back(1);
|
||||
if (!deselect_ends && cyclic[curve_i] && !curve_body.is_empty()) {
|
||||
if (!deselect_ends && cyclic[curve] && !curve_body.is_empty()) {
|
||||
selection_typed[curve_body.last()] = false;
|
||||
}
|
||||
});
|
||||
@@ -639,22 +639,22 @@ void select_adjacent(bke::CurvesGeometry &curves,
|
||||
|
||||
if (selection.span.type().is<bool>()) {
|
||||
MutableSpan<bool> selection_typed = selection.span.typed<bool>();
|
||||
curves_mask.foreach_index([&](const int64_t curve_i) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
curves_mask.foreach_index([&](const int64_t curve) {
|
||||
const IndexRange points = points_by_curve[curve];
|
||||
const int first_point = points.first();
|
||||
const int last_point = points.last();
|
||||
|
||||
/* Handle all cases in the forward direction. */
|
||||
for (int point_i = first_point; point_i < last_point; point_i++) {
|
||||
if (!selection_typed[point_i] && selection_typed[point_i + 1]) {
|
||||
selection_typed[point_i] = true;
|
||||
for (int point = first_point; point < last_point; point++) {
|
||||
if (!selection_typed[point] && selection_typed[point + 1]) {
|
||||
selection_typed[point] = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle all cases in the backwards direction. */
|
||||
for (int point_i = last_point; point_i > first_point; point_i--) {
|
||||
if (!selection_typed[point_i] && selection_typed[point_i - 1]) {
|
||||
selection_typed[point_i] = true;
|
||||
for (int point = last_point; point > first_point; point--) {
|
||||
if (!selection_typed[point] && selection_typed[point - 1]) {
|
||||
selection_typed[point] = true;
|
||||
}
|
||||
}
|
||||
if (deselect) {
|
||||
@@ -666,7 +666,7 @@ void select_adjacent(bke::CurvesGeometry &curves,
|
||||
}
|
||||
}
|
||||
/* Handle cyclic curve case. */
|
||||
if (cyclic[curve_i]) {
|
||||
if (cyclic[curve]) {
|
||||
if (selection_typed[first_point] != selection_typed[last_point]) {
|
||||
selection_typed[first_point] = true;
|
||||
selection_typed[last_point] = true;
|
||||
@@ -676,8 +676,8 @@ void select_adjacent(bke::CurvesGeometry &curves,
|
||||
}
|
||||
else if (selection.span.type().is<float>()) {
|
||||
MutableSpan<float> selection_typed = selection.span.typed<float>();
|
||||
curves_mask.foreach_index([&](const int64_t curve_i) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
curves_mask.foreach_index([&](const int64_t curve) {
|
||||
const IndexRange points = points_by_curve[curve];
|
||||
const int first_point = points.first();
|
||||
const int last_point = points.last();
|
||||
|
||||
@@ -696,7 +696,7 @@ void select_adjacent(bke::CurvesGeometry &curves,
|
||||
}
|
||||
|
||||
/* Handle cyclic curve case. */
|
||||
if (cyclic[curve_i]) {
|
||||
if (cyclic[curve]) {
|
||||
if (selection_typed[first_point] != selection_typed[last_point]) {
|
||||
selection_typed[first_point] = 1.0f;
|
||||
selection_typed[last_point] = 1.0f;
|
||||
@@ -757,6 +757,14 @@ void apply_selection_operation_at_index(GMutableSpan selection,
|
||||
}
|
||||
}
|
||||
|
||||
static FindClosestData closer_elem(const FindClosestData &a, const FindClosestData &b)
|
||||
{
|
||||
if (a.distance < b.distance) {
|
||||
return a;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
static std::optional<FindClosestData> find_closest_point_to_screen_co(
|
||||
const ARegion *region,
|
||||
const Span<float3> positions,
|
||||
@@ -771,13 +779,11 @@ static std::optional<FindClosestData> find_closest_point_to_screen_co(
|
||||
points_mask.index_range(),
|
||||
1024,
|
||||
initial_closest,
|
||||
[&](const IndexRange point_indicies_range, const FindClosestData &init) {
|
||||
[&](const IndexRange range, const FindClosestData &init) {
|
||||
FindClosestData best_match = init;
|
||||
for (const int index : point_indicies_range) {
|
||||
const int point_i = points_mask[index];
|
||||
const float3 pos = positions[point_i];
|
||||
|
||||
/* Find the position of the point in screen space. */
|
||||
for (const int index : range) {
|
||||
const int point = points_mask[index];
|
||||
const float3 &pos = positions[point];
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(region, pos, projection);
|
||||
|
||||
const float distance_proj_sq = math::distance_squared(pos_proj, mouse_pos);
|
||||
@@ -788,20 +794,11 @@ static std::optional<FindClosestData> find_closest_point_to_screen_co(
|
||||
continue;
|
||||
}
|
||||
|
||||
FindClosestData better_candidate;
|
||||
better_candidate.index = point_i;
|
||||
better_candidate.distance = std::sqrt(distance_proj_sq);
|
||||
|
||||
best_match = better_candidate;
|
||||
best_match = {point, std::sqrt(distance_proj_sq)};
|
||||
}
|
||||
return best_match;
|
||||
},
|
||||
[](const FindClosestData &a, const FindClosestData &b) {
|
||||
if (a.distance < b.distance) {
|
||||
return a;
|
||||
}
|
||||
return b;
|
||||
});
|
||||
closer_elem);
|
||||
|
||||
if (new_closest_data.distance < initial_closest.distance) {
|
||||
return new_closest_data;
|
||||
@@ -827,37 +824,29 @@ static std::optional<FindClosestData> find_closest_curve_to_screen_co(
|
||||
curves_mask.index_range(),
|
||||
256,
|
||||
initial_closest,
|
||||
[&](const IndexRange curves_indices_range, const FindClosestData &init) {
|
||||
[&](const IndexRange range, const FindClosestData &init) {
|
||||
FindClosestData best_match = init;
|
||||
for (const int index : curves_indices_range) {
|
||||
const int curve_i = curves_mask[index];
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
if (points.size() == 1) {
|
||||
const float3 pos = positions[points.first()];
|
||||
curves_mask.slice(range).foreach_index([&](const int curve) {
|
||||
const IndexRange points = points_by_curve[curve];
|
||||
|
||||
/* Find the position of the point in screen space. */
|
||||
if (points.size() == 1) {
|
||||
const float3 &pos = positions[points.first()];
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(region, pos, projection);
|
||||
|
||||
const float distance_proj_sq = math::distance_squared(pos_proj, mouse_pos);
|
||||
if (distance_proj_sq > radius_sq ||
|
||||
distance_proj_sq > best_match.distance * best_match.distance)
|
||||
{
|
||||
/* Ignore the point because it's too far away or there is already a better point.
|
||||
*/
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
FindClosestData better_candidate;
|
||||
better_candidate.index = curve_i;
|
||||
better_candidate.distance = std::sqrt(distance_proj_sq);
|
||||
|
||||
best_match = better_candidate;
|
||||
continue;
|
||||
best_match = {curve, std::sqrt(distance_proj_sq)};
|
||||
return;
|
||||
}
|
||||
|
||||
auto process_segment = [&](const int segment_i, const int next_i) {
|
||||
const float3 pos1 = positions[segment_i];
|
||||
const float3 pos2 = positions[next_i];
|
||||
const float3 &pos1 = positions[segment_i];
|
||||
const float3 &pos2 = positions[next_i];
|
||||
const float2 pos1_proj = ED_view3d_project_float_v2_m4(region, pos1, projection);
|
||||
const float2 pos2_proj = ED_view3d_project_float_v2_m4(region, pos2, projection);
|
||||
|
||||
@@ -866,32 +855,21 @@ static std::optional<FindClosestData> find_closest_curve_to_screen_co(
|
||||
if (distance_proj_sq > radius_sq ||
|
||||
distance_proj_sq > best_match.distance * best_match.distance)
|
||||
{
|
||||
/* Ignore the segment because it's too far away or there is already a better point.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
FindClosestData better_candidate;
|
||||
better_candidate.index = curve_i;
|
||||
better_candidate.distance = std::sqrt(distance_proj_sq);
|
||||
|
||||
best_match = better_candidate;
|
||||
best_match = {curve, std::sqrt(distance_proj_sq)};
|
||||
};
|
||||
for (const int segment_i : points.drop_back(1)) {
|
||||
process_segment(segment_i, segment_i + 1);
|
||||
}
|
||||
if (cyclic[curve_i]) {
|
||||
if (cyclic[curve]) {
|
||||
process_segment(points.last(), points.first());
|
||||
}
|
||||
}
|
||||
});
|
||||
return best_match;
|
||||
},
|
||||
[](const FindClosestData &a, const FindClosestData &b) {
|
||||
if (a.distance < b.distance) {
|
||||
return a;
|
||||
}
|
||||
return b;
|
||||
});
|
||||
closer_elem);
|
||||
|
||||
if (new_closest_data.distance < initial_closest.distance) {
|
||||
return new_closest_data;
|
||||
@@ -965,14 +943,14 @@ bool select_box(const ViewContext &vc,
|
||||
[&](IndexRange range, Span<float3> positions, StringRef selection_attribute_name) {
|
||||
const IndexMask &mask = (selection_attribute_name == ".selection") ? selection_mask :
|
||||
bezier_mask;
|
||||
mask.slice_content(range).foreach_index(GrainSize(1024), [&](const int point_i) {
|
||||
mask.slice_content(range).foreach_index(GrainSize(1024), [&](const int point) {
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(
|
||||
vc.region, positions[point_i], projection);
|
||||
vc.region, positions[point], projection);
|
||||
if (BLI_rcti_isect_pt_v(&rect, int2(pos_proj))) {
|
||||
apply_selection_operation_at_index(
|
||||
selection_attribute_writer_by_name(selection_writers, selection_attribute_name)
|
||||
.span,
|
||||
point_i,
|
||||
point,
|
||||
sel_op);
|
||||
changed = true;
|
||||
}
|
||||
@@ -990,29 +968,28 @@ bool select_box(const ViewContext &vc,
|
||||
const Span<float3> positions,
|
||||
StringRef /* selection_attribute_name */) {
|
||||
const IndexMask &mask = selection_mask;
|
||||
mask.slice_content(range).foreach_index(GrainSize(512), [&](const int curve_i) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
mask.slice_content(range).foreach_index(GrainSize(512), [&](const int curve) {
|
||||
const IndexRange points = points_by_curve[curve];
|
||||
if (points.size() == 1) {
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(
|
||||
vc.region, positions[points.first()], projection);
|
||||
if (BLI_rcti_isect_pt_v(&rect, int2(pos_proj))) {
|
||||
for (bke::GSpanAttributeWriter &selection : selection_writers) {
|
||||
apply_selection_operation_at_index(selection.span, curve_i, sel_op);
|
||||
apply_selection_operation_at_index(selection.span, curve, sel_op);
|
||||
};
|
||||
changed = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto process_segment = [&](const int segment_i, const int next_i) {
|
||||
const float3 pos1 = positions[segment_i];
|
||||
const float3 pos2 = positions[next_i];
|
||||
|
||||
const float3 &pos1 = positions[segment_i];
|
||||
const float3 &pos2 = positions[next_i];
|
||||
const float2 pos1_proj = ED_view3d_project_float_v2_m4(vc.region, pos1, projection);
|
||||
const float2 pos2_proj = ED_view3d_project_float_v2_m4(vc.region, pos2, projection);
|
||||
|
||||
if (BLI_rcti_isect_segment(&rect, int2(pos1_proj), int2(pos2_proj))) {
|
||||
for (bke::GSpanAttributeWriter &selection : selection_writers) {
|
||||
apply_selection_operation_at_index(selection.span, curve_i, sel_op);
|
||||
apply_selection_operation_at_index(selection.span, curve, sel_op);
|
||||
};
|
||||
changed = true;
|
||||
return true;
|
||||
@@ -1026,7 +1003,7 @@ bool select_box(const ViewContext &vc,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!segment_selected && cyclic[curve_i]) {
|
||||
if (!segment_selected && cyclic[curve]) {
|
||||
process_segment(points.last(), points.first());
|
||||
}
|
||||
});
|
||||
@@ -1039,7 +1016,7 @@ bool select_box(const ViewContext &vc,
|
||||
bool select_lasso(const ViewContext &vc,
|
||||
bke::CurvesGeometry &curves,
|
||||
const bke::crazyspace::GeometryDeformation &deformation,
|
||||
const float4x4 &projection_matrix,
|
||||
const float4x4 &projection,
|
||||
const IndexMask &selection_mask,
|
||||
const IndexMask &bezier_mask,
|
||||
const bke::AttrDomain selection_domain,
|
||||
@@ -1066,9 +1043,9 @@ bool select_lasso(const ViewContext &vc,
|
||||
[&](IndexRange range, Span<float3> positions, StringRef selection_attribute_name) {
|
||||
const IndexMask &mask = (selection_attribute_name == ".selection") ? selection_mask :
|
||||
bezier_mask;
|
||||
mask.slice_content(range).foreach_index(GrainSize(1024), [&](const int point_i) {
|
||||
mask.slice_content(range).foreach_index(GrainSize(1024), [&](const int point) {
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(
|
||||
vc.region, positions[point_i], projection_matrix);
|
||||
vc.region, positions[point], projection);
|
||||
/* Check the lasso bounding box first as an optimization. */
|
||||
if (BLI_rcti_isect_pt_v(&bbox, int2(pos_proj)) &&
|
||||
BLI_lasso_is_point_inside(
|
||||
@@ -1077,7 +1054,7 @@ bool select_lasso(const ViewContext &vc,
|
||||
apply_selection_operation_at_index(
|
||||
selection_attribute_writer_by_name(selection_writers, selection_attribute_name)
|
||||
.span,
|
||||
point_i,
|
||||
point,
|
||||
sel_op);
|
||||
changed = true;
|
||||
}
|
||||
@@ -1095,31 +1072,28 @@ bool select_lasso(const ViewContext &vc,
|
||||
const Span<float3> positions,
|
||||
StringRef /* selection_attribute_name */) {
|
||||
const IndexMask &mask = selection_mask;
|
||||
mask.slice_content(range).foreach_index(GrainSize(512), [&](const int curve_i) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
mask.slice_content(range).foreach_index(GrainSize(512), [&](const int curve) {
|
||||
const IndexRange points = points_by_curve[curve];
|
||||
if (points.size() == 1) {
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(
|
||||
vc.region, positions[points.first()], projection_matrix);
|
||||
vc.region, positions[points.first()], projection);
|
||||
/* Check the lasso bounding box first as an optimization. */
|
||||
if (BLI_rcti_isect_pt_v(&bbox, int2(pos_proj)) &&
|
||||
BLI_lasso_is_point_inside(
|
||||
lasso_coords, int(pos_proj.x), int(pos_proj.y), IS_CLIPPED))
|
||||
{
|
||||
for (bke::GSpanAttributeWriter &selection : selection_writers) {
|
||||
apply_selection_operation_at_index(selection.span, curve_i, sel_op);
|
||||
apply_selection_operation_at_index(selection.span, curve, sel_op);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto process_segment = [&](const int segment_i, const int next_i) {
|
||||
const float3 pos1 = positions[segment_i];
|
||||
const float3 pos2 = positions[next_i];
|
||||
|
||||
const float2 pos1_proj = ED_view3d_project_float_v2_m4(
|
||||
vc.region, pos1, projection_matrix);
|
||||
const float2 pos2_proj = ED_view3d_project_float_v2_m4(
|
||||
vc.region, pos2, projection_matrix);
|
||||
const float3 &pos1 = positions[segment_i];
|
||||
const float3 &pos2 = positions[next_i];
|
||||
const float2 pos1_proj = ED_view3d_project_float_v2_m4(vc.region, pos1, projection);
|
||||
const float2 pos2_proj = ED_view3d_project_float_v2_m4(vc.region, pos2, projection);
|
||||
|
||||
/* Check the lasso bounding box first as an optimization. */
|
||||
if (BLI_rcti_isect_segment(&bbox, int2(pos1_proj), int2(pos2_proj)) &&
|
||||
@@ -1131,7 +1105,7 @@ bool select_lasso(const ViewContext &vc,
|
||||
IS_CLIPPED))
|
||||
{
|
||||
for (bke::GSpanAttributeWriter &selection : selection_writers) {
|
||||
apply_selection_operation_at_index(selection.span, curve_i, sel_op);
|
||||
apply_selection_operation_at_index(selection.span, curve, sel_op);
|
||||
}
|
||||
changed = true;
|
||||
return true;
|
||||
@@ -1139,13 +1113,13 @@ bool select_lasso(const ViewContext &vc,
|
||||
return false;
|
||||
};
|
||||
bool segment_selected = false;
|
||||
for (const int segment_i : points.drop_back(cyclic[curve_i] ? 0 : 1)) {
|
||||
for (const int segment_i : points.drop_back(cyclic[curve] ? 0 : 1)) {
|
||||
if (process_segment(segment_i, segment_i + 1)) {
|
||||
segment_selected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!segment_selected && cyclic[curve_i]) {
|
||||
if (!segment_selected && cyclic[curve]) {
|
||||
process_segment(points.last(), points.first());
|
||||
}
|
||||
});
|
||||
@@ -1185,14 +1159,14 @@ bool select_circle(const ViewContext &vc,
|
||||
[&](IndexRange range, Span<float3> positions, StringRef selection_attribute_name) {
|
||||
const IndexMask &mask = (selection_attribute_name == ".selection") ? selection_mask :
|
||||
bezier_mask;
|
||||
mask.slice_content(range).foreach_index(GrainSize(1024), [&](const int point_i) {
|
||||
mask.slice_content(range).foreach_index(GrainSize(1024), [&](const int point) {
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(
|
||||
vc.region, positions[point_i], projection);
|
||||
vc.region, positions[point], projection);
|
||||
if (math::distance_squared(pos_proj, float2(coord)) <= radius_sq) {
|
||||
apply_selection_operation_at_index(
|
||||
selection_attribute_writer_by_name(selection_writers, selection_attribute_name)
|
||||
.span,
|
||||
point_i,
|
||||
point,
|
||||
sel_op);
|
||||
changed = true;
|
||||
}
|
||||
@@ -1210,23 +1184,22 @@ bool select_circle(const ViewContext &vc,
|
||||
const Span<float3> positions,
|
||||
StringRef /* selection_attribute_name */) {
|
||||
const IndexMask &mask = selection_mask;
|
||||
mask.slice_content(range).foreach_index(GrainSize(512), [&](const int curve_i) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
mask.slice_content(range).foreach_index(GrainSize(512), [&](const int curve) {
|
||||
const IndexRange points = points_by_curve[curve];
|
||||
if (points.size() == 1) {
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(
|
||||
vc.region, positions[points.first()], projection);
|
||||
if (math::distance_squared(pos_proj, float2(coord)) <= radius_sq) {
|
||||
for (bke::GSpanAttributeWriter &selection : selection_writers) {
|
||||
apply_selection_operation_at_index(selection.span, curve_i, sel_op);
|
||||
apply_selection_operation_at_index(selection.span, curve, sel_op);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto process_segments = [&](const int segment_i, const int next_i) {
|
||||
const float3 pos1 = positions[segment_i];
|
||||
const float3 pos2 = positions[next_i];
|
||||
|
||||
const float3 &pos1 = positions[segment_i];
|
||||
const float3 &pos2 = positions[next_i];
|
||||
const float2 pos1_proj = ED_view3d_project_float_v2_m4(vc.region, pos1, projection);
|
||||
const float2 pos2_proj = ED_view3d_project_float_v2_m4(vc.region, pos2, projection);
|
||||
|
||||
@@ -1234,7 +1207,7 @@ bool select_circle(const ViewContext &vc,
|
||||
float2(coord), pos1_proj, pos2_proj);
|
||||
if (distance_proj_sq <= radius_sq) {
|
||||
for (bke::GSpanAttributeWriter &selection : selection_writers) {
|
||||
apply_selection_operation_at_index(selection.span, curve_i, sel_op);
|
||||
apply_selection_operation_at_index(selection.span, curve, sel_op);
|
||||
}
|
||||
changed = true;
|
||||
return true;
|
||||
@@ -1248,7 +1221,7 @@ bool select_circle(const ViewContext &vc,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!segment_selected && cyclic[curve_i]) {
|
||||
if (!segment_selected && cyclic[curve]) {
|
||||
process_segments(points.last(), points.first());
|
||||
}
|
||||
});
|
||||
@@ -1274,31 +1247,32 @@ IndexMask select_mask_from_predicates(const bke::CurvesGeometry &curves,
|
||||
mask.slice_content(curves.points_range()), GrainSize(1024), memory, point_predicate);
|
||||
}
|
||||
if (selection_domain == bke::AttrDomain::Curve) {
|
||||
return IndexMask::from_predicate(
|
||||
mask.slice_content(curves.curves_range()),
|
||||
GrainSize(512),
|
||||
memory,
|
||||
[&](const int curve_i) -> bool {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
const bool is_cyclic = cyclic[curve_i];
|
||||
return IndexMask::from_predicate(mask.slice_content(curves.curves_range()),
|
||||
GrainSize(512),
|
||||
memory,
|
||||
[&](const int curve) -> bool {
|
||||
const IndexRange points = points_by_curve[curve];
|
||||
const bool is_cyclic = cyclic[curve];
|
||||
|
||||
/* Single-point curve can still be selected in curve mode. */
|
||||
if (points.size() == 1) {
|
||||
return point_predicate(points.first());
|
||||
}
|
||||
/* Single-point curve can still be selected in curve mode.
|
||||
*/
|
||||
if (points.size() == 1) {
|
||||
return point_predicate(points.first());
|
||||
}
|
||||
|
||||
for (const int point_i : points.drop_back(1)) {
|
||||
if (line_predicate(curve_i, point_i, point_i + 1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (is_cyclic) {
|
||||
if (line_predicate(curve_i, points.last(), points.first())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
for (const int point : points.drop_back(1)) {
|
||||
if (line_predicate(curve, point, point + 1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (is_cyclic) {
|
||||
if (line_predicate(curve, points.last(), points.first()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@@ -1327,26 +1301,26 @@ IndexMask select_adjacent_mask(const bke::CurvesGeometry &curves,
|
||||
(!selection[point] && (selection[neighbor1] || selection[neighbor2]));
|
||||
};
|
||||
|
||||
curves_mask.foreach_index([&](const int64_t curve_i) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
curves_mask.foreach_index([&](const int64_t curve) {
|
||||
const IndexRange points = points_by_curve[curve];
|
||||
if (points.size() == 1) {
|
||||
/* Single point curve does not add anything to the mask. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (cyclic[curve_i]) {
|
||||
if (cyclic[curve]) {
|
||||
changed_points[points.first()] = is_point_changed2(
|
||||
points.first(), points.last(), points.first() + 1);
|
||||
for (const int point_i : points.drop_front(1).drop_back(1)) {
|
||||
changed_points[point_i] = is_point_changed2(point_i, point_i - 1, point_i + 1);
|
||||
for (const int point : points.drop_front(1).drop_back(1)) {
|
||||
changed_points[point] = is_point_changed2(point, point - 1, point + 1);
|
||||
}
|
||||
changed_points[points.last()] = is_point_changed2(
|
||||
points.last(), points.last() - 1, points.first());
|
||||
}
|
||||
else {
|
||||
changed_points[points.first()] = is_point_changed1(points.first(), points.first() + 1);
|
||||
for (const int point_i : points.drop_front(1).drop_back(1)) {
|
||||
changed_points[point_i] = is_point_changed2(point_i, point_i - 1, point_i + 1);
|
||||
for (const int point : points.drop_front(1).drop_back(1)) {
|
||||
changed_points[point] = is_point_changed2(point, point - 1, point + 1);
|
||||
}
|
||||
changed_points[points.last()] = is_point_changed1(points.last(), points.last() - 1);
|
||||
}
|
||||
@@ -1377,15 +1351,13 @@ IndexMask select_box_mask(const ViewContext &vc,
|
||||
const Span<float3> positions = get_selection_attribute_positions(
|
||||
curves, deformation, attribute_name);
|
||||
|
||||
auto point_predicate = [&](const int point_i) {
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(
|
||||
vc.region, positions[point_i], projection);
|
||||
auto point_predicate = [&](const int point) {
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(vc.region, positions[point], projection);
|
||||
/* Check the lasso bounding box first as an optimization. */
|
||||
return BLI_rcti_isect_pt_v(&rect, int2(pos_proj));
|
||||
};
|
||||
auto line_predicate = [&](const int /*curve_i*/, const int point_i, const int next_point_i) {
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(
|
||||
vc.region, positions[point_i], projection);
|
||||
auto line_predicate = [&](const int /*curve*/, const int point, const int next_point_i) {
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(vc.region, positions[point], projection);
|
||||
const float2 next_pos_proj = ED_view3d_project_float_v2_m4(
|
||||
vc.region, positions[next_point_i], projection);
|
||||
return BLI_rcti_isect_segment(&rect, int2(pos_proj), int2(next_pos_proj));
|
||||
@@ -1415,16 +1387,14 @@ IndexMask select_lasso_mask(const ViewContext &vc,
|
||||
const Span<float3> positions = get_selection_attribute_positions(
|
||||
curves, deformation, attribute_name);
|
||||
|
||||
auto point_predicate = [&](const int point_i) {
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(
|
||||
vc.region, positions[point_i], projection);
|
||||
auto point_predicate = [&](const int point) {
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(vc.region, positions[point], projection);
|
||||
/* Check the lasso bounding box first as an optimization. */
|
||||
return BLI_rcti_isect_pt_v(&bbox, int2(pos_proj)) &&
|
||||
BLI_lasso_is_point_inside(lasso_coords, int(pos_proj.x), int(pos_proj.y), IS_CLIPPED);
|
||||
};
|
||||
auto line_predicate = [&](const int /*curve_i*/, const int point_i, const int next_point_i) {
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(
|
||||
vc.region, positions[point_i], projection);
|
||||
auto line_predicate = [&](const int /*curve*/, const int point, const int next_point_i) {
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(vc.region, positions[point], projection);
|
||||
const float2 next_pos_proj = ED_view3d_project_float_v2_m4(
|
||||
vc.region, positions[next_point_i], projection);
|
||||
return BLI_rcti_isect_segment(&bbox, int2(pos_proj), int2(next_pos_proj)) &&
|
||||
@@ -1460,15 +1430,13 @@ IndexMask select_circle_mask(const ViewContext &vc,
|
||||
const Span<float3> positions = get_selection_attribute_positions(
|
||||
curves, deformation, attribute_name);
|
||||
|
||||
auto point_predicate = [&](const int point_i) {
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(
|
||||
vc.region, positions[point_i], projection);
|
||||
auto point_predicate = [&](const int point) {
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(vc.region, positions[point], projection);
|
||||
const float distance_proj_sq = math::distance_squared(pos_proj, float2(coord));
|
||||
return distance_proj_sq <= radius_sq;
|
||||
};
|
||||
auto line_predicate = [&](const int /*curve_i*/, const int point_i, const int next_point_i) {
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(
|
||||
vc.region, positions[point_i], projection);
|
||||
auto line_predicate = [&](const int /*curve*/, const int point, const int next_point_i) {
|
||||
const float2 pos_proj = ED_view3d_project_float_v2_m4(vc.region, positions[point], projection);
|
||||
const float2 next_pos_proj = ED_view3d_project_float_v2_m4(
|
||||
vc.region, positions[next_point_i], projection);
|
||||
const float distance_proj_sq = dist_squared_to_line_segment_v2(
|
||||
|
||||
@@ -340,7 +340,7 @@ bool select_box(const ViewContext &vc,
|
||||
bool select_lasso(const ViewContext &vc,
|
||||
bke::CurvesGeometry &curves,
|
||||
const bke::crazyspace::GeometryDeformation &deformation,
|
||||
const float4x4 &projection_matrix,
|
||||
const float4x4 &projection,
|
||||
const IndexMask &selection_mask,
|
||||
const IndexMask &bezier_mask,
|
||||
bke::AttrDomain selection_domain,
|
||||
|
||||
Reference in New Issue
Block a user