diff --git a/crates/bevy_transform/src/components/transform.rs b/crates/bevy_transform/src/components/transform.rs index e7507c08b892e4..d77770b18a01ff 100644 --- a/crates/bevy_transform/src/components/transform.rs +++ b/crates/bevy_transform/src/components/transform.rs @@ -4,9 +4,10 @@ use std::fmt; #[derive(Debug, PartialEq, Clone, Copy, Properties)] pub struct Transform { - pub translation: Vec3, - pub rotation: Quat, - pub scale: Vec3, + translation: Vec3, + rotation: Quat, + scale: Vec3, + matrix_cache: Option, } impl Transform { @@ -16,6 +17,7 @@ impl Transform { translation: Vec3::zero(), rotation: Quat::identity(), scale: Vec3::one(), + matrix_cache: Some(Mat4::identity()), } } @@ -26,12 +28,14 @@ impl Transform { translation, rotation, scale, + matrix_cache: Some(matrix), } } pub fn from_translation(translation: Vec3) -> Self { Transform { translation, + matrix_cache: None, ..Default::default() } } @@ -39,6 +43,7 @@ impl Transform { pub fn from_rotation(rotation: Quat) -> Self { Transform { rotation, + matrix_cache: None, ..Default::default() } } @@ -46,6 +51,7 @@ impl Transform { pub fn from_scale(scale: f32) -> Self { Transform { scale: Vec3::one() * scale, + matrix_cache: None, ..Default::default() } } @@ -53,6 +59,7 @@ impl Transform { pub fn from_non_uniform_scale(scale: Vec3) -> Self { Transform { scale, + matrix_cache: None, ..Default::default() } } @@ -61,27 +68,32 @@ impl Transform { Transform { translation, rotation, + matrix_cache: None, ..Default::default() } } pub fn with_translation(mut self, translation: Vec3) -> Self { self.translation = translation; + self.matrix_cache = None; self } pub fn with_rotation(mut self, rotation: Quat) -> Self { self.rotation = rotation; + self.matrix_cache = None; self } pub fn with_scale(mut self, scale: f32) -> Self { self.scale = Vec3::one() * scale; + self.matrix_cache = None; self } pub fn with_non_uniform_scale(mut self, scale: Vec3) -> Self { self.scale = scale; + self.matrix_cache = None; self } @@ -93,11 +105,46 @@ impl Transform { /// Returns transform with the same translation and scale, but rotation so that transform.forward() points at target pub fn looking_at(mut self, target: Vec3, up: Vec3) -> Self { self.look_at(target, up); + self.matrix_cache = None; self } - pub fn compute_matrix(&self) -> Mat4 { - Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation) + pub fn translation(&self) -> &Vec3 { + &self.translation + } + + pub fn translation_mut(&mut self) -> &mut Vec3 { + self.matrix_cache = None; + &mut self.translation + } + + pub fn rotation(&self) -> &Quat { + &self.rotation + } + + pub fn rotation_mut(&mut self) -> &mut Quat { + self.matrix_cache = None; + &mut self.rotation + } + + pub fn scale(&self) -> &Vec3 { + &self.scale + } + + pub fn scale_mut(&mut self) -> &mut Vec3 { + self.matrix_cache = None; + &mut self.scale + } + + pub fn matrix(&mut self) -> Mat4 { + if self.matrix_cache.is_none() { + self.matrix_cache = Some(Mat4::from_scale_rotation_translation( + self.scale, + self.rotation, + self.translation, + )); + } + self.matrix_cache.unwrap() } pub fn forward(&self) -> Vec3 { @@ -107,19 +154,23 @@ impl Transform { /// Translates the transform by the given translation relative to its orientation pub fn translate(&mut self, translation: Vec3) { self.translation += self.rotation * translation; + self.matrix_cache = None; } /// Rotate the transform by the given rotation pub fn rotate(&mut self, rotation: Quat) { self.rotation *= rotation; + self.matrix_cache = None; } pub fn apply_scale(&mut self, scale: f32) { self.scale *= scale; + self.matrix_cache = None; } pub fn apply_non_uniform_scale(&mut self, scale: Vec3) { self.scale *= scale; + self.matrix_cache = None; } pub fn look_at(&mut self, target: Vec3, up: Vec3) { @@ -127,6 +178,7 @@ impl Transform { let right = up.cross(forward).normalize(); let up = forward.cross(right); self.rotation = Quat::from_rotation_mat3(&Mat3::from_cols(right, up, forward)); + self.matrix_cache = None; } } @@ -138,6 +190,17 @@ impl Default for Transform { impl fmt::Display for Transform { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.compute_matrix()) + write!( + f, + "translation: {}\nrotation: {}\nscale: {}\nmatrix {}computed", + self.translation, + self.rotation, + self.scale, + if self.matrix_cache.is_none() { + "not " + } else { + "" + } + ) } } diff --git a/crates/bevy_transform/src/transform_propagate_system.rs b/crates/bevy_transform/src/transform_propagate_system.rs index 4eff1a1b6ac562..fff9f49873763f 100644 --- a/crates/bevy_transform/src/transform_propagate_system.rs +++ b/crates/bevy_transform/src/transform_propagate_system.rs @@ -3,11 +3,13 @@ use bevy_ecs::prelude::*; use bevy_math::Mat4; pub fn transform_propagate_system( - mut root_query: Query, &Transform, &mut GlobalTransform)>>, - mut transform_query: Query<(&Transform, &mut GlobalTransform, Option<&Children>)>, + mut root_query: Query< + Without, &mut Transform, &mut GlobalTransform)>, + >, + mut transform_query: Query<(&mut Transform, &mut GlobalTransform, Option<&Children>)>, ) { - for (children, transform, mut global_transform) in &mut root_query.iter() { - global_transform.value = transform.compute_matrix(); + for (children, mut transform, mut global_transform) in &mut root_query.iter() { + global_transform.value = transform.matrix(); if let Some(children) = children { for child in children.0.iter() { @@ -19,17 +21,17 @@ pub fn transform_propagate_system( fn propagate_recursive( parent: &Mat4, - transform_query: &mut Query<(&Transform, &mut GlobalTransform, Option<&Children>)>, + transform_query: &mut Query<(&mut Transform, &mut GlobalTransform, Option<&Children>)>, entity: Entity, ) { log::trace!("Updating Transform for {:?}", entity); let global_matrix = { - if let (Ok(transform), Ok(mut global_transform)) = ( - transform_query.get::(entity), + if let (Ok(mut transform), Ok(mut global_transform)) = ( + transform_query.get_mut::(entity), transform_query.get_mut::(entity), ) { - global_transform.value = *parent * transform.compute_matrix(); + global_transform.value = *parent * transform.matrix(); global_transform.value } else { return; diff --git a/crates/bevy_ui/src/flex/mod.rs b/crates/bevy_ui/src/flex/mod.rs index a7882d96b1ceb1..9efe3a43c19966 100644 --- a/crates/bevy_ui/src/flex/mod.rs +++ b/crates/bevy_ui/src/flex/mod.rs @@ -193,7 +193,7 @@ pub fn flex_node_system( for (entity, mut node, mut transform, parent) in &mut node_transform_query.iter() { let layout = flex_surface.get_layout(entity).unwrap(); node.size = Vec2::new(layout.size.width, layout.size.height); - let position = &mut transform.translation; + let position = transform.translation_mut(); position.set_x(layout.location.x + layout.size.width / 2.0); position.set_y(layout.location.y + layout.size.height / 2.0); if let Some(parent) = parent { diff --git a/crates/bevy_ui/src/update.rs b/crates/bevy_ui/src/update.rs index bafa9fa9c01e1a..4723091be49939 100644 --- a/crates/bevy_ui/src/update.rs +++ b/crates/bevy_ui/src/update.rs @@ -47,7 +47,7 @@ fn update_node_entity( let global_z = z + parent_global_z; let mut transform = node_query.get_mut::(entity).ok()?; - transform.translation.set_z(z); + transform.translation_mut().set_z(z); Some(global_z) } diff --git a/examples/ecs/parallel_query.rs b/examples/ecs/parallel_query.rs index ea1b4b4d2fcb90..65981a18c88755 100644 --- a/examples/ecs/parallel_query.rs +++ b/examples/ecs/parallel_query.rs @@ -60,10 +60,10 @@ fn bounce_system( .par_iter(32) // Filter out sprites that don't need to be bounced .filter(|(transform, _)| { - !(left < transform.translation.x() - && transform.translation.x() < right - && bottom < transform.translation.y() - && transform.translation.y() < top) + !(left < transform.translation().x() + && transform.translation().x() < right + && bottom < transform.translation().y() + && transform.translation().y() < top) }) // For simplicity, just reverse the velocity; don't use realistic bounces .for_each(&pool, |(_, mut v)| { diff --git a/examples/game/breakout.rs b/examples/game/breakout.rs index eee28f7f1486da..e79262530da859 100644 --- a/examples/game/breakout.rs +++ b/examples/game/breakout.rs @@ -170,7 +170,7 @@ fn paddle_movement_system( direction += 1.0; } - let translation = &mut transform.translation; + let translation = transform.translation_mut(); // move the paddle horizontally *translation.x_mut() += time.delta_seconds * direction * paddle.speed; // bound the paddle within the walls @@ -206,9 +206,9 @@ fn ball_collision_system( // check collision with walls for (collider_entity, collider, transform, sprite) in &mut collider_query.iter() { let collision = collide( - ball_transform.translation, + *ball_transform.translation(), ball_size, - transform.translation, + *transform.translation(), sprite.size, ); if let Some(collision) = collision {