Curves: Use simpler "set" behavior for handle position attributes

The handle position attributes `handle_left` and `handle_right` had
rather complex behavior to get expected behavior when aligned or auto/
vector handles were used. In order to simplify the attribtue API and
make the transition to the new curves data structure simpler, this
commit moves that behavior from the attribute to the "Set Handle
Positions" node. When that node is used, the behavior should be the
same as before. However, if the modifier's output attributes were used
to set handle positions, the behavior may be different. That situation
is expected to be very rare though.
This commit is contained in:
Hans Goudey 2022-02-23 15:44:55 -05:00
parent 756f7fb23e
commit f8fe0e831e
Notes: blender-bot 2023-02-14 07:25:51 +01:00
Referenced by issue #95941, Change curve component to store Curves data
2 changed files with 35 additions and 22 deletions

View File

@ -973,10 +973,10 @@ class VArrayImpl_For_BezierHandles final : public VMutableArrayImpl<float3> {
if (spline.type() == CURVE_TYPE_BEZIER) {
BezierSpline &bezier_spline = static_cast<BezierSpline &>(spline);
if (is_right_) {
bezier_spline.set_handle_position_right(indices.point_index, value);
bezier_spline.handle_positions_right()[indices.point_index] = value;
}
else {
bezier_spline.set_handle_position_left(indices.point_index, value);
bezier_spline.handle_positions_left()[indices.point_index] = value;
}
bezier_spline.mark_cache_invalid();
}
@ -992,12 +992,12 @@ class VArrayImpl_For_BezierHandles final : public VMutableArrayImpl<float3> {
BezierSpline &bezier_spline = static_cast<BezierSpline &>(spline);
if (is_right_) {
for (const int i : IndexRange(bezier_spline.size())) {
bezier_spline.set_handle_position_right(i, src[offset + i]);
bezier_spline.handle_positions_right()[i] = src[offset + i];
}
}
else {
for (const int i : IndexRange(bezier_spline.size())) {
bezier_spline.set_handle_position_left(i, src[offset + i]);
bezier_spline.handle_positions_left()[i] = src[offset + i];
}
}
bezier_spline.mark_cache_invalid();

View File

@ -53,36 +53,31 @@ static void set_position_in_component(const GeometryNodeCurveHandleMode mode,
evaluator.evaluate();
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
CurveComponent *curve_component = static_cast<CurveComponent *>(&component);
CurveEval *curve = curve_component->get_for_write();
StringRef side = mode & GEO_NODE_CURVE_HANDLE_LEFT ? "handle_left" : "handle_right";
CurveComponent &curve_component = *static_cast<CurveComponent *>(&component);
CurveEval *curve = curve_component.get_for_write();
int current_point = 0;
int current_mask = 0;
for (const SplinePtr &spline : curve->splines()) {
if (spline->type() == CURVE_TYPE_BEZIER) {
BezierSpline &bezier = static_cast<BezierSpline &>(*spline);
for (int i : bezier.positions().index_range()) {
bezier.ensure_auto_handles();
for (const int i : bezier.positions().index_range()) {
if (current_mask < selection.size() && selection[current_mask] == current_point) {
if (mode & GEO_NODE_CURVE_HANDLE_LEFT) {
if (bezier.handle_types_left()[i] == BEZIER_HANDLE_VECTOR) {
bezier.ensure_auto_handles();
bezier.handle_types_left()[i] = BEZIER_HANDLE_FREE;
}
else if (bezier.handle_types_left()[i] == BEZIER_HANDLE_AUTO) {
bezier.ensure_auto_handles();
bezier.handle_types_left()[i] = BEZIER_HANDLE_ALIGN;
}
}
else {
if (bezier.handle_types_right()[i] == BEZIER_HANDLE_VECTOR) {
bezier.ensure_auto_handles();
bezier.handle_types_right()[i] = BEZIER_HANDLE_FREE;
}
else if (bezier.handle_types_right()[i] == BEZIER_HANDLE_AUTO) {
bezier.ensure_auto_handles();
bezier.handle_types_right()[i] = BEZIER_HANDLE_ALIGN;
}
}
@ -104,15 +99,33 @@ static void set_position_in_component(const GeometryNodeCurveHandleMode mode,
const VArray<float3> &positions_input = evaluator.get_evaluated<float3>(0);
const VArray<float3> &offsets_input = evaluator.get_evaluated<float3>(1);
OutputAttribute_Typed<float3> positions = component.attribute_try_get_for_output<float3>(
side, ATTR_DOMAIN_POINT, {0, 0, 0});
MutableSpan<float3> position_mutable = positions.as_span();
for (int i : selection) {
position_mutable[i] = positions_input[i] + offsets_input[i];
current_point = 0;
current_mask = 0;
for (const SplinePtr &spline : curve->splines()) {
if (spline->type() == CURVE_TYPE_BEZIER) {
BezierSpline &bezier = static_cast<BezierSpline &>(*spline);
for (const int i : bezier.positions().index_range()) {
if (current_mask < selection.size() && selection[current_mask] == current_point) {
if (mode & GEO_NODE_CURVE_HANDLE_LEFT) {
bezier.set_handle_position_left(i, positions_input[i] + offsets_input[i]);
}
else {
bezier.set_handle_position_right(i, positions_input[i] + offsets_input[i]);
}
current_mask++;
}
current_point++;
}
}
else {
for ([[maybe_unused]] int i : spline->positions().index_range()) {
if (current_mask < selection.size() && selection[current_mask] == current_point) {
current_mask++;
}
current_point++;
}
}
}
positions.save();
}
static void node_geo_exec(GeoNodeExecParams params)