Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed the way the rotation of a curve at a point is evaluated to match PathFollow2D #78378

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions doc/classes/Curve2D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,14 @@
<param index="0" name="offset" type="float" default="0.0" />
<param index="1" name="cubic" type="bool" default="false" />
<description>
Similar to [method sample_baked], but returns [Transform2D] that includes a rotation along the curve, with [member Transform2D.origin] as the point position, [member Transform2D.x] as the sideways vector, and [member Transform2D.y] as the forward vector. Returns an empty transform if the length of the curve is [code]0[/code].
Similar to [method sample_baked], but returns [Transform2D] that includes a rotation along the curve, with [member Transform2D.origin] as the point position and the [member Transform2D.x] vector pointing in the direction of the path at that point. Returns an empty transform if the length of the curve is [code]0[/code].
[codeblock]
var baked = curve.sample_baked_with_rotation(offset)
# This will rotate and position the node with the up direction pointing along the curve.
# The returned Transform2D can be set directly.
transform = baked
# You can also read the origin and rotation separately from the returned Transform2D.
position = baked.get_origin()
rotation = baked.get_rotation()
# Alternatively, not preserving scale.
transform = baked * Transform2D.FLIP_Y
# To match the rotation of PathFollow2D, not preserving scale.
transform = Transform2D(baked.y, baked.x, baked.origin)
[/codeblock]
</description>
</method>
Expand Down
8 changes: 4 additions & 4 deletions scene/2d/path_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@ void Path2D::_notification(int p_what) {

for (int i = 0; i < sample_count; i++) {
const Vector2 p = r[i].get_origin();
const Vector2 side = r[i].columns[0];
const Vector2 forward = r[i].columns[1];
const Vector2 side = r[i].columns[1];
const Vector2 forward = r[i].columns[0];

// Fish Bone.
w[0] = p + (side - forward) * 5;
Expand Down Expand Up @@ -232,8 +232,8 @@ void PathFollow2D::_update_transform() {

if (rotates) {
Transform2D xform = c->sample_baked_with_rotation(progress, cubic);
xform.translate_local(v_offset, h_offset);
set_rotation(xform[1].angle());
xform.translate_local(h_offset, v_offset);
set_rotation(xform[0].angle());
set_position(xform[2]);
} else {
Vector2 pos = c->sample_baked(progress, cubic);
Expand Down
2 changes: 1 addition & 1 deletion scene/resources/curve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -977,7 +977,7 @@ Transform2D Curve2D::_sample_posture(Interval p_interval) const {
const Vector2 forward = forward_begin.slerp(forward_end, frac).normalized();
const Vector2 side = Vector2(-forward.y, forward.x);

return Transform2D(side, forward, Vector2(0.0, 0.0));
return Transform2D(forward, side, Vector2(0.0, 0.0));
}

Vector2 Curve2D::sample_baked(real_t p_offset, bool p_cubic) const {
Expand Down
36 changes: 28 additions & 8 deletions tests/scene/test_curve_2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,17 +155,37 @@ TEST_CASE("[Curve2D] Sampling") {

SUBCASE("sample_baked_with_rotation") {
const real_t pi = 3.14159;
Transform2D t = curve->sample_baked_with_rotation(curve->get_closest_offset(Vector2(0, 0)));
CHECK(t.get_origin() == Vector2(0, 0));
CHECK(Math::is_equal_approx(t.get_rotation(), pi));

t = curve->sample_baked_with_rotation(curve->get_closest_offset(Vector2(0, 25)));
const real_t half_pi = pi * 0.5;
Ref<Curve2D> rot_curve = memnew(Curve2D);
Transform2D t;

rot_curve->clear_points();
rot_curve->add_point(Vector2());
rot_curve->add_point(Vector2(50, 0));
t = rot_curve->sample_baked_with_rotation(25);
CHECK(t.get_origin() == Vector2(25, 0));
CHECK(Math::is_equal_approx(t.get_rotation(), 0));

rot_curve->clear_points();
rot_curve->add_point(Vector2());
rot_curve->add_point(Vector2(0, 50));
t = rot_curve->sample_baked_with_rotation(25);
CHECK(t.get_origin() == Vector2(0, 25));
CHECK(Math::is_equal_approx(t.get_rotation(), pi));
CHECK(Math::is_equal_approx(t.get_rotation(), half_pi));

t = curve->sample_baked_with_rotation(curve->get_closest_offset(Vector2(0, 50)));
CHECK(t.get_origin() == Vector2(0, 50));
rot_curve->clear_points();
rot_curve->add_point(Vector2());
rot_curve->add_point(Vector2(-50, 0));
t = rot_curve->sample_baked_with_rotation(25);
CHECK(t.get_origin() == Vector2(-25, 0));
CHECK(Math::is_equal_approx(t.get_rotation(), pi));

rot_curve->clear_points();
rot_curve->add_point(Vector2());
rot_curve->add_point(Vector2(0, -50));
t = rot_curve->sample_baked_with_rotation(25);
CHECK(t.get_origin() == Vector2(0, -25));
CHECK(Math::is_equal_approx(t.get_rotation(), -half_pi));
}

SUBCASE("get_closest_point") {
Expand Down