From acae38201077c8ee7013d2d9ec608dc8ee5c49c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Botero?= <0xafbf@gmail.com> Date: Sat, 17 Jun 2023 14:28:05 -0500 Subject: [PATCH] Changed the way the rotation of a curve at a point is evaluated to match PathFollow2D --- doc/classes/Curve2D.xml | 10 ++++------ scene/2d/path_2d.cpp | 8 ++++---- scene/resources/curve.cpp | 2 +- tests/scene/test_curve_2d.h | 36 ++++++++++++++++++++++++++++-------- 4 files changed, 37 insertions(+), 19 deletions(-) diff --git a/doc/classes/Curve2D.xml b/doc/classes/Curve2D.xml index 197d03f0d87b..0e75c65f50a3 100644 --- a/doc/classes/Curve2D.xml +++ b/doc/classes/Curve2D.xml @@ -107,16 +107,14 @@ - 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] diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp index ee0ccc42ff89..a0e7e4cf2534 100644 --- a/scene/2d/path_2d.cpp +++ b/scene/2d/path_2d.cpp @@ -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; @@ -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); diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index d2aabf7d5c2a..869e15bb2c38 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -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 { diff --git a/tests/scene/test_curve_2d.h b/tests/scene/test_curve_2d.h index fc141f3d090c..099f6fefa9a6 100644 --- a/tests/scene/test_curve_2d.h +++ b/tests/scene/test_curve_2d.h @@ -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 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") {