diff --git a/crates/bevy_transform/Cargo.toml b/crates/bevy_transform/Cargo.toml index 7dd2545a7ecbc..06f33f14f15e8 100644 --- a/crates/bevy_transform/Cargo.toml +++ b/crates/bevy_transform/Cargo.toml @@ -29,6 +29,7 @@ bevy_math = { path = "../bevy_math", version = "0.19.0-dev", default-features = "approx", ] } approx = "0.5.1" +ron = "0.8" [features] # Turning off default features leaves you with a barebones diff --git a/crates/bevy_transform/src/components/transform.rs b/crates/bevy_transform/src/components/transform.rs index 4685e8d7c8311..2974ccac6a612 100644 --- a/crates/bevy_transform/src/components/transform.rs +++ b/crates/bevy_transform/src/components/transform.rs @@ -68,6 +68,7 @@ fn assert_is_normalized(message: &str, length_squared: f32) { /// [transform_example]: https://github.com/bevyengine/bevy/blob/latest/examples/transforms/transform.rs #[derive(Debug, PartialEq, Clone, Copy)] #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serialize", serde(default))] #[cfg_attr( feature = "bevy-support", derive(Component), @@ -670,3 +671,82 @@ impl Mul for Transform { reflect(Serialize, Deserialize) )] pub struct TransformTreeChanged; + +#[cfg(all(test, feature = "serialize"))] +mod tests { + use super::*; + use ron; + + // use "serialize" feature flag for these + + // make sure an empty config will serialize and deserialize properly + #[test] + fn test_empty_transform_defaults() { + let ron_data = "()"; + + let transform: Transform = ron::de::from_str(ron_data).unwrap(); + + assert_eq!(transform, Transform::IDENTITY); + } + + #[test] + fn test_missing_rotation_and_scale() { + let ron_data = r#" + ( + translation: (5.0, -2.0, 10.0), + ) + "#; + + let transform: Transform = ron::de::from_str(ron_data).unwrap(); + + assert_eq!(transform.translation, Vec3::new(5.0, -2.0, 10.0)); + assert_eq!(transform.rotation, Quat::IDENTITY); + assert_eq!(transform.scale, Vec3::ONE); + } + + #[test] + fn test_only_scale_provided() { + let ron_data = r#" + ( + scale: (3.0, 4.0, 5.0), + ) + "#; + + let transform: Transform = ron::de::from_str(ron_data).unwrap(); + + assert_eq!(transform.translation, Vec3::ZERO); + assert_eq!(transform.rotation, Quat::IDENTITY); + assert_eq!(transform.scale, Vec3::new(3.0, 4.0, 5.0)); + } + + // round trip + #[test] + fn test_roundtrip_preserves_values() { + let original = Transform { + translation: Vec3::new(1.0, 2.0, 3.0), + rotation: Quat::IDENTITY, + scale: Vec3::splat(2.0), + }; + + let ron = ron::ser::to_string(&original).unwrap(); + let deserialized: Transform = ron::de::from_str(&ron).unwrap(); + + assert_eq!(original, deserialized); + } + + #[test] + fn test_partial_values_mix() { + let ron_data = r#" + ( + translation: (9.0, 8.0, 7.0), + scale: (0.5, 0.5, 0.5), + ) + "#; + + let transform: Transform = ron::de::from_str(ron_data).unwrap(); + + assert_eq!(transform.translation, Vec3::new(9.0, 8.0, 7.0)); + assert_eq!(transform.scale, Vec3::splat(0.5)); + assert_eq!(transform.rotation, Quat::IDENTITY); + } +}