Refactor: Pass deformed positions to curve selection

This refactor pulls the call to get the `deformation` data from inside the selection function to the outside.
Instead, the deformed positions are now passed directly to the selection functions.

This means that the selection functions become more independent of the object type, which was the original intent.
Otherwise, using these functions with e.g. Grease Pencil will crash.

Pull Request: https://projects.blender.org/blender/blender/pulls/108650
This commit is contained in:
Falk David
2023-06-06 14:28:03 +02:00
committed by Falk David
parent 693a921f02
commit fa0fe6f55e
3 changed files with 57 additions and 40 deletions

View File

@@ -439,11 +439,11 @@ void apply_selection_operation_at_index(GMutableSpan selection,
}
static std::optional<FindClosestData> find_closest_point_to_screen_co(
const Depsgraph &depsgraph,
const ARegion *region,
const RegionView3D *rv3d,
const Object &object,
const bke::CurvesGeometry &curves,
Span<float3> deformed_positions,
float2 mouse_pos,
float radius,
const FindClosestData &initial_closest)
@@ -451,9 +451,6 @@ static std::optional<FindClosestData> find_closest_point_to_screen_co(
float4x4 projection;
ED_view3d_ob_project_mat_get(rv3d, &object, projection.ptr());
const bke::crazyspace::GeometryDeformation deformation =
bke::crazyspace::get_evaluated_curves_deformation(depsgraph, object);
const float radius_sq = pow2f(radius);
const FindClosestData new_closest_data = threading::parallel_reduce(
curves.points_range(),
@@ -462,7 +459,7 @@ static std::optional<FindClosestData> find_closest_point_to_screen_co(
[&](const IndexRange point_range, const FindClosestData &init) {
FindClosestData best_match = init;
for (const int point_i : point_range) {
const float3 pos = deformation.positions[point_i];
const float3 pos = deformed_positions[point_i];
/* Find the position of the point in screen space. */
float2 pos_proj;
@@ -498,11 +495,11 @@ static std::optional<FindClosestData> find_closest_point_to_screen_co(
}
static std::optional<FindClosestData> find_closest_curve_to_screen_co(
const Depsgraph &depsgraph,
const ARegion *region,
const RegionView3D *rv3d,
const Object &object,
const bke::CurvesGeometry &curves,
Span<float3> deformed_positions,
float2 mouse_pos,
float radius,
const FindClosestData &initial_closest)
@@ -510,9 +507,6 @@ static std::optional<FindClosestData> find_closest_curve_to_screen_co(
float4x4 projection;
ED_view3d_ob_project_mat_get(rv3d, &object, projection.ptr());
const bke::crazyspace::GeometryDeformation deformation =
bke::crazyspace::get_evaluated_curves_deformation(depsgraph, object);
const float radius_sq = pow2f(radius);
const OffsetIndices points_by_curve = curves.points_by_curve();
@@ -525,7 +519,7 @@ static std::optional<FindClosestData> find_closest_curve_to_screen_co(
for (const int curve_i : curves_range) {
const IndexRange points = points_by_curve[curve_i];
if (points.size() == 1) {
const float3 pos = deformation.positions[points.first()];
const float3 pos = deformed_positions[points.first()];
/* Find the position of the point in screen space. */
float2 pos_proj;
@@ -548,8 +542,8 @@ static std::optional<FindClosestData> find_closest_curve_to_screen_co(
}
for (const int segment_i : points.drop_back(1)) {
const float3 pos1 = deformation.positions[segment_i];
const float3 pos2 = deformation.positions[segment_i + 1];
const float3 pos1 = deformed_positions[segment_i];
const float3 pos2 = deformed_positions[segment_i + 1];
float2 pos1_proj, pos2_proj;
ED_view3d_project_float_v2_m4(region, pos1, pos1_proj, projection.ptr());
@@ -591,26 +585,27 @@ std::optional<FindClosestData> closest_elem_find_screen_space(
const ViewContext &vc,
const Object &object,
bke::CurvesGeometry &curves,
const Span<float3> deformed_positions,
const eAttrDomain domain,
const int2 coord,
const FindClosestData &initial_closest)
{
switch (domain) {
case ATTR_DOMAIN_POINT:
return find_closest_point_to_screen_co(*vc.depsgraph,
vc.region,
return find_closest_point_to_screen_co(vc.region,
vc.rv3d,
object,
curves,
deformed_positions,
float2(coord),
ED_view3d_select_dist_px(),
initial_closest);
case ATTR_DOMAIN_CURVE:
return find_closest_curve_to_screen_co(*vc.depsgraph,
vc.region,
return find_closest_curve_to_screen_co(vc.region,
vc.rv3d,
object,
curves,
deformed_positions,
float2(coord),
ED_view3d_select_dist_px(),
initial_closest);
@@ -622,6 +617,7 @@ std::optional<FindClosestData> closest_elem_find_screen_space(
bool select_box(const ViewContext &vc,
bke::CurvesGeometry &curves,
const Span<float3> deformed_positions,
const eAttrDomain selection_domain,
const rcti &rect,
const eSelectOp sel_op)
@@ -638,15 +634,13 @@ bool select_box(const ViewContext &vc,
float4x4 projection;
ED_view3d_ob_project_mat_get(vc.rv3d, vc.obact, projection.ptr());
const bke::crazyspace::GeometryDeformation deformation =
bke::crazyspace::get_evaluated_curves_deformation(*vc.depsgraph, *vc.obact);
const OffsetIndices points_by_curve = curves.points_by_curve();
if (selection_domain == ATTR_DOMAIN_POINT) {
threading::parallel_for(curves.points_range(), 1024, [&](const IndexRange point_range) {
for (const int point_i : point_range) {
float2 pos_proj;
ED_view3d_project_float_v2_m4(
vc.region, deformation.positions[point_i], pos_proj, projection.ptr());
vc.region, deformed_positions[point_i], pos_proj, projection.ptr());
if (BLI_rcti_isect_pt_v(&rect, int2(pos_proj))) {
apply_selection_operation_at_index(selection.span, point_i, sel_op);
changed = true;
@@ -661,7 +655,7 @@ bool select_box(const ViewContext &vc,
if (points.size() == 1) {
float2 pos_proj;
ED_view3d_project_float_v2_m4(
vc.region, deformation.positions[points.first()], pos_proj, projection.ptr());
vc.region, deformed_positions[points.first()], pos_proj, projection.ptr());
if (BLI_rcti_isect_pt_v(&rect, int2(pos_proj))) {
apply_selection_operation_at_index(selection.span, curve_i, sel_op);
changed = true;
@@ -669,8 +663,8 @@ bool select_box(const ViewContext &vc,
continue;
}
for (const int segment_i : points.drop_back(1)) {
const float3 pos1 = deformation.positions[segment_i];
const float3 pos2 = deformation.positions[segment_i + 1];
const float3 pos1 = deformed_positions[segment_i];
const float3 pos2 = deformed_positions[segment_i + 1];
float2 pos1_proj, pos2_proj;
ED_view3d_project_float_v2_m4(vc.region, pos1, pos1_proj, projection.ptr());
@@ -692,6 +686,7 @@ bool select_box(const ViewContext &vc,
bool select_lasso(const ViewContext &vc,
bke::CurvesGeometry &curves,
const Span<float3> deformed_positions,
const eAttrDomain selection_domain,
const Span<int2> coords,
const eSelectOp sel_op)
@@ -712,15 +707,13 @@ bool select_lasso(const ViewContext &vc,
float4x4 projection;
ED_view3d_ob_project_mat_get(vc.rv3d, vc.obact, projection.ptr());
const bke::crazyspace::GeometryDeformation deformation =
bke::crazyspace::get_evaluated_curves_deformation(*vc.depsgraph, *vc.obact);
const OffsetIndices points_by_curve = curves.points_by_curve();
if (selection_domain == ATTR_DOMAIN_POINT) {
threading::parallel_for(curves.points_range(), 1024, [&](const IndexRange point_range) {
for (const int point_i : point_range) {
float2 pos_proj;
ED_view3d_project_float_v2_m4(
vc.region, deformation.positions[point_i], pos_proj, projection.ptr());
vc.region, deformed_positions[point_i], pos_proj, projection.ptr());
/* Check the lasso bounding box first as an optimization. */
if (BLI_rcti_isect_pt_v(&bbox, int2(pos_proj)) &&
BLI_lasso_is_point_inside(
@@ -739,7 +732,7 @@ bool select_lasso(const ViewContext &vc,
if (points.size() == 1) {
float2 pos_proj;
ED_view3d_project_float_v2_m4(
vc.region, deformation.positions[points.first()], pos_proj, projection.ptr());
vc.region, deformed_positions[points.first()], pos_proj, projection.ptr());
/* Check the lasso bounding box first as an optimization. */
if (BLI_rcti_isect_pt_v(&bbox, int2(pos_proj)) &&
BLI_lasso_is_point_inside(
@@ -751,8 +744,8 @@ bool select_lasso(const ViewContext &vc,
continue;
}
for (const int segment_i : points.drop_back(1)) {
const float3 pos1 = deformation.positions[segment_i];
const float3 pos2 = deformation.positions[segment_i + 1];
const float3 pos1 = deformed_positions[segment_i];
const float3 pos2 = deformed_positions[segment_i + 1];
float2 pos1_proj, pos2_proj;
ED_view3d_project_float_v2_m4(vc.region, pos1, pos1_proj, projection.ptr());
@@ -783,6 +776,7 @@ bool select_lasso(const ViewContext &vc,
bool select_circle(const ViewContext &vc,
bke::CurvesGeometry &curves,
const Span<float3> deformed_positions,
const eAttrDomain selection_domain,
const int2 coord,
const float radius,
@@ -801,15 +795,13 @@ bool select_circle(const ViewContext &vc,
float4x4 projection;
ED_view3d_ob_project_mat_get(vc.rv3d, vc.obact, projection.ptr());
const bke::crazyspace::GeometryDeformation deformation =
bke::crazyspace::get_evaluated_curves_deformation(*vc.depsgraph, *vc.obact);
const OffsetIndices points_by_curve = curves.points_by_curve();
if (selection_domain == ATTR_DOMAIN_POINT) {
threading::parallel_for(curves.points_range(), 1024, [&](const IndexRange point_range) {
for (const int point_i : point_range) {
float2 pos_proj;
ED_view3d_project_float_v2_m4(
vc.region, deformation.positions[point_i], pos_proj, projection.ptr());
vc.region, deformed_positions[point_i], pos_proj, projection.ptr());
if (math::distance_squared(pos_proj, float2(coord)) <= radius_sq) {
apply_selection_operation_at_index(selection.span, point_i, sel_op);
changed = true;
@@ -824,7 +816,7 @@ bool select_circle(const ViewContext &vc,
if (points.size() == 1) {
float2 pos_proj;
ED_view3d_project_float_v2_m4(
vc.region, deformation.positions[points.first()], pos_proj, projection.ptr());
vc.region, deformed_positions[points.first()], pos_proj, projection.ptr());
if (math::distance_squared(pos_proj, float2(coord)) <= radius_sq) {
apply_selection_operation_at_index(selection.span, curve_i, sel_op);
changed = true;
@@ -832,8 +824,8 @@ bool select_circle(const ViewContext &vc,
continue;
}
for (const int segment_i : points.drop_back(1)) {
const float3 pos1 = deformation.positions[segment_i];
const float3 pos2 = deformation.positions[segment_i + 1];
const float3 pos1 = deformed_positions[segment_i];
const float3 pos2 = deformed_positions[segment_i + 1];
float2 pos1_proj, pos2_proj;
ED_view3d_project_float_v2_m4(vc.region, pos1, pos1_proj, projection.ptr());

View File

@@ -54,12 +54,13 @@ int *ED_curves_offsets_for_write(struct Curves *curves_id);
#ifdef __cplusplus
# include "BKE_attribute.hh"
# include "BKE_crazyspace.hh"
# include "BKE_curves.hh"
# include "BLI_index_mask.hh"
# include "BLI_vector.hh"
# include "BLI_vector_set.hh"
# include "BKE_curves.hh"
# include "ED_select_utils.h"
namespace blender::ed::curves {
@@ -192,6 +193,7 @@ struct FindClosestData {
std::optional<FindClosestData> closest_elem_find_screen_space(const ViewContext &vc,
const Object &object,
bke::CurvesGeometry &curves,
Span<float3> deformed_positions,
eAttrDomain domain,
int2 coord,
const FindClosestData &initial);
@@ -201,6 +203,7 @@ std::optional<FindClosestData> closest_elem_find_screen_space(const ViewContext
*/
bool select_box(const ViewContext &vc,
bke::CurvesGeometry &curves,
Span<float3> deformed_positions,
eAttrDomain selection_domain,
const rcti &rect,
eSelectOp sel_op);
@@ -210,6 +213,7 @@ bool select_box(const ViewContext &vc,
*/
bool select_lasso(const ViewContext &vc,
bke::CurvesGeometry &curves,
Span<float3> deformed_positions,
eAttrDomain selection_domain,
Span<int2> coords,
eSelectOp sel_op);
@@ -219,6 +223,7 @@ bool select_lasso(const ViewContext &vc,
*/
bool select_circle(const ViewContext &vc,
bke::CurvesGeometry &curves,
Span<float3> deformed_positions,
eAttrDomain selection_domain,
int2 coord,
float radius,

View File

@@ -50,6 +50,7 @@
#include "BKE_armature.h"
#include "BKE_attribute.hh"
#include "BKE_context.h"
#include "BKE_crazyspace.hh"
#include "BKE_curve.h"
#include "BKE_editmesh.h"
#include "BKE_layer.h"
@@ -1370,9 +1371,12 @@ static bool view3d_lasso_select(bContext *C,
case OB_CURVES: {
Curves &curves_id = *static_cast<Curves *>(vc->obedit->data);
bke::CurvesGeometry &curves = curves_id.geometry.wrap();
bke::crazyspace::GeometryDeformation deformation =
bke::crazyspace::get_evaluated_curves_deformation(*vc->depsgraph, *vc->obedit);
changed = ed::curves::select_lasso(
*vc,
curves,
deformation.positions,
eAttrDomain(curves_id.selection_domain),
Span<int2>(reinterpret_cast<const int2 *>(mcoords), mcoords_len),
sel_op);
@@ -3029,10 +3033,13 @@ static bool ed_curves_select_pick(bContext &C, const int mval[2], const SelectPi
for (Base *base : bases.slice(range)) {
Object &curves_ob = *base->object;
Curves &curves_id = *static_cast<Curves *>(curves_ob.data);
bke::crazyspace::GeometryDeformation deformation =
bke::crazyspace::get_evaluated_curves_deformation(*vc.depsgraph, *vc.obedit);
std::optional<ed::curves::FindClosestData> new_closest_elem =
ed::curves::closest_elem_find_screen_space(vc,
curves_ob,
curves_id.geometry.wrap(),
deformation.positions,
selection_domain,
mval,
new_closest.elem);
@@ -4090,8 +4097,14 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
case OB_CURVES: {
Curves &curves_id = *static_cast<Curves *>(vc.obedit->data);
bke::CurvesGeometry &curves = curves_id.geometry.wrap();
changed = ed::curves::select_box(
vc, curves, eAttrDomain(curves_id.selection_domain), rect, sel_op);
bke::crazyspace::GeometryDeformation deformation =
bke::crazyspace::get_evaluated_curves_deformation(*vc.depsgraph, *vc.obedit);
changed = ed::curves::select_box(vc,
curves,
deformation.positions,
eAttrDomain(curves_id.selection_domain),
rect,
sel_op);
if (changed) {
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a
* generic attribute for now. */
@@ -4860,8 +4873,15 @@ static bool obedit_circle_select(bContext *C,
case OB_CURVES: {
Curves &curves_id = *static_cast<Curves *>(vc->obedit->data);
bke::CurvesGeometry &curves = curves_id.geometry.wrap();
changed = ed::curves::select_circle(
*vc, curves, eAttrDomain(curves_id.selection_domain), mval, rad, sel_op);
bke::crazyspace::GeometryDeformation deformation =
bke::crazyspace::get_evaluated_curves_deformation(*vc->depsgraph, *vc->obedit);
changed = ed::curves::select_circle(*vc,
curves,
deformation.positions,
eAttrDomain(curves_id.selection_domain),
mval,
rad,
sel_op);
if (changed) {
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a
* generic attribute for now. */