Skip to content

Commit 8b2c97e

Browse files
committed
deprecate Transform2D::from_rotation_translation_scale and add from_scale_rotation_origin
1 parent d0b59e5 commit 8b2c97e

File tree

1 file changed

+49
-2
lines changed

1 file changed

+49
-2
lines changed

gdnative-core/src/core_types/geom/transform2d.rs

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,14 @@ impl Transform2D {
7676
}
7777

7878
/// Constructs the transform from a given angle (in radians), translation, and scale.
79+
///
80+
/// # Deprecation
81+
/// This constructor has been deprecated due to the order of transformations applied deviate from one's expectations. An identity transform is translated, rotated, and scaled. Using a non-zero rotation will affect the resulting transform's origin.
82+
///
83+
/// Consider using [`Transform2D::from_scale_rotation_origin`] or applying transformations manually.
84+
#[deprecated(
85+
note = "This constructor is misleading because a non-zero rotation would affect the resulting origin. Consider using Transform2D::from_scale_rotation_origin or apply transformations manually."
86+
)]
7987
#[inline]
8088
pub fn from_rotation_translation_scale(
8189
translation: Vector2,
@@ -88,6 +96,23 @@ impl Transform2D {
8896
.scaled(scale)
8997
}
9098

99+
/// Constructs the transform from a given scale, angle (in radians), and origin.
100+
///
101+
/// This is **NOT** equivalent to `Transform2D::IDENTITY.scaled(scale).rotated(rotation).translated(origin)` or `Transform2D::IDENTITY.translated(origin).rotated(rotation).scaled(scale)`. Those transformations do not preserve the given origin, see the documentation for [`rotated`], [`scaled`], and [`translated`] for more information.
102+
///
103+
/// [`rotated`]: Self::rotated
104+
/// [`scaled`]: Self::scaled
105+
/// [`translated`]: Self::translated
106+
#[inline]
107+
pub fn from_scale_rotation_origin(scale: Vector2, rotation: f32, origin: Vector2) -> Self {
108+
let mut tr = Self::IDENTITY;
109+
tr.set_scale(scale);
110+
tr.set_rotation(rotation);
111+
tr.origin = origin;
112+
113+
tr
114+
}
115+
91116
/// Returns the inverse of the transform, under the assumption that the transformation is composed of rotation, scaling and translation.
92117
#[inline]
93118
pub fn affine_inverse(&self) -> Self {
@@ -164,7 +189,7 @@ impl Transform2D {
164189
self.set_scale(scale);
165190
}
166191

167-
/// Rotates the transform by the given angle (in radians), using matrix multiplication.
192+
/// Rotates the transform by the given angle (in radians), using matrix multiplication. This will modify the transform's origin.
168193
#[inline]
169194
pub fn rotated(&self, rotation: f32) -> Self {
170195
let mut tr = Self::IDENTITY;
@@ -186,7 +211,7 @@ impl Transform2D {
186211
self.b = self.b.normalized() * scale.y;
187212
}
188213

189-
/// Scales the transform by the given scale factor, using matrix multiplication.
214+
/// Scales the transform by the given scale factor, using matrix multiplication. This will modify the transform's origin.
190215
#[inline]
191216
pub fn scaled(&self, scale: Vector2) -> Self {
192217
let mut new = *self;
@@ -445,3 +470,25 @@ godot_test!(
445470
test_transform2d_behavior_impl()
446471
}
447472
);
473+
474+
#[test]
475+
fn test_transform2d_constructor() {
476+
use std::f32::consts::PI;
477+
478+
let scale = Vector2::new(2.0, 0.5);
479+
let rotation = PI / 4.0;
480+
let origin = Vector2::new(250.0, 150.0);
481+
482+
let tr = Transform2D::from_scale_rotation_origin(scale, rotation, origin);
483+
484+
assert_eq!(tr.origin, origin);
485+
486+
let actual_local_right = tr.basis_xform(Vector2::RIGHT);
487+
let expected_local_right = Vector2::RIGHT.rotated(-rotation) * scale;
488+
assert!(
489+
actual_local_right.is_equal_approx(expected_local_right),
490+
"{:?} != {:?}",
491+
actual_local_right,
492+
expected_local_right
493+
);
494+
}

0 commit comments

Comments
 (0)