deprecate Transform2D::from_rotation_translation_scale and add from_scale_rotation_origin
@@ -76,6 +76,14 @@ impl Transform2D {
}
/// Constructs the transform from a given angle (in radians), translation, and scale.
+ ///
+ /// # Deprecation
+ /// 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.
+ ///
+ /// Consider using [`Transform2D::from_scale_rotation_origin`] or applying transformations manually.
+ #[deprecated(
+ 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."
+ )]
#[inline]
pub fn from_rotation_translation_scale(
translation: Vector2,
@@ -88,6 +96,23 @@ impl Transform2D {
.scaled(scale)
}
+ /// Constructs the transform from a given scale, angle (in radians), and origin.
+ ///
+ /// 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.
+ ///
+ /// [`rotated`]: Self::rotated
+ /// [`scaled`]: Self::scaled
+ /// [`translated`]: Self::translated
+ #[inline]
+ pub fn from_scale_rotation_origin(scale: Vector2, rotation: f32, origin: Vector2) -> Self {
+ let mut tr = Self::IDENTITY;
+ tr.set_scale(scale);
+ tr.set_rotation(rotation);
+ tr.origin = origin;
+
+ tr
+ }
+
/// Returns the inverse of the transform, under the assumption that the transformation is composed of rotation, scaling and translation.
#[inline]
pub fn affine_inverse(&self) -> Self {
@@ -164,7 +189,7 @@ impl Transform2D {
self.set_scale(scale);
}
- /// Rotates the transform by the given angle (in radians), using matrix multiplication.
+ /// Rotates the transform by the given angle (in radians), using matrix multiplication. This will modify the transform's origin.
#[inline]
pub fn rotated(&self, rotation: f32) -> Self {
let mut tr = Self::IDENTITY;
@@ -186,7 +211,7 @@ impl Transform2D {
self.b = self.b.normalized() * scale.y;
}
- /// Scales the transform by the given scale factor, using matrix multiplication.
+ /// Scales the transform by the given scale factor, using matrix multiplication. This will modify the transform's origin.
#[inline]
pub fn scaled(&self, scale: Vector2) -> Self {
let mut new = *self;
@@ -445,3 +470,25 @@ godot_test!(
test_transform2d_behavior_impl()
}
);
+
+#[test]
+fn test_transform2d_constructor() {
+ use std::f32::consts::PI;
+
+ let scale = Vector2::new(2.0, 0.5);
+ let rotation = PI / 4.0;
+ let origin = Vector2::new(250.0, 150.0);
+
+ let tr = Transform2D::from_scale_rotation_origin(scale, rotation, origin);
+
+ assert_eq!(tr.origin, origin);
+
+ let actual_local_right = tr.basis_xform(Vector2::RIGHT);
+ let expected_local_right = Vector2::RIGHT.rotated(-rotation) * scale;
+ assert!(
+ actual_local_right.is_equal_approx(expected_local_right),
+ "{:?} != {:?}",
+ actual_local_right,
+ expected_local_right
+ );
+}
