bevy_transform split up to allow feature gate modularity (#13599)
# Objective Part of https://github.com/bevyengine/bevy/issues/13529 Helps https://github.com/bevyengine/bevy/pull/13533 Splitting up `bevy_transform` makes it easier to selectively include or exclude parts of it in such a way that it's possible to include only a small part with a small dependency tree. ## Solution Make the crate more modular. --------- Signed-off-by: Torstein Grindvik <torstein.grindvik@muybridge.com> Co-authored-by: Torstein Grindvik <torstein.grindvik@muybridge.com>
This commit is contained in:
		
							parent
							
								
									0f03e1d46e
								
							
						
					
					
						commit
						76d12fa2b3
					
				
							
								
								
									
										59
									
								
								crates/bevy_transform/src/bundles.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								crates/bevy_transform/src/bundles.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | |||||||
|  | use bevy_ecs::bundle::Bundle; | ||||||
|  | 
 | ||||||
|  | use crate::prelude::{GlobalTransform, Transform}; | ||||||
|  | 
 | ||||||
|  | /// A [`Bundle`] of the [`Transform`] and [`GlobalTransform`]
 | ||||||
|  | /// [`Component`]s, which describe the position of an entity.
 | ||||||
|  | ///
 | ||||||
|  | /// * To place or move an entity, you should set its [`Transform`].
 | ||||||
|  | /// * To get the global transform of an entity, you should get its [`GlobalTransform`].
 | ||||||
|  | /// * For transform hierarchies to work correctly, you must have both a [`Transform`] and a [`GlobalTransform`].
 | ||||||
|  | ///   * You may use the [`TransformBundle`] to guarantee this.
 | ||||||
|  | ///
 | ||||||
|  | /// ## [`Transform`] and [`GlobalTransform`]
 | ||||||
|  | ///
 | ||||||
|  | /// [`Transform`] is the position of an entity relative to its parent position, or the reference
 | ||||||
|  | /// frame if it doesn't have a parent.
 | ||||||
|  | ///
 | ||||||
|  | /// [`GlobalTransform`] is the position of an entity relative to the reference frame.
 | ||||||
|  | ///
 | ||||||
|  | /// [`GlobalTransform`] is updated from [`Transform`] by systems in the system set
 | ||||||
|  | /// [`TransformPropagate`](TransformSystem::TransformPropagate).
 | ||||||
|  | ///
 | ||||||
|  | /// This system runs during [`PostUpdate`]. If you
 | ||||||
|  | /// update the [`Transform`] of an entity in this schedule or after, you will notice a 1 frame lag
 | ||||||
|  | /// before the [`GlobalTransform`] is updated.
 | ||||||
|  | #[derive(Clone, Copy, Debug, Default, Bundle)] | ||||||
|  | pub struct TransformBundle { | ||||||
|  |     /// The transform of the entity.
 | ||||||
|  |     pub local: Transform, | ||||||
|  |     /// The global transform of the entity.
 | ||||||
|  |     pub global: GlobalTransform, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl TransformBundle { | ||||||
|  |     /// An identity [`TransformBundle`] with no translation, rotation, and a scale of 1 on all axes.
 | ||||||
|  |     pub const IDENTITY: Self = TransformBundle { | ||||||
|  |         local: Transform::IDENTITY, | ||||||
|  |         global: GlobalTransform::IDENTITY, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     /// Creates a new [`TransformBundle`] from a [`Transform`].
 | ||||||
|  |     ///
 | ||||||
|  |     /// This initializes [`GlobalTransform`] as identity, to be updated later by the
 | ||||||
|  |     /// [`PostUpdate`] schedule.
 | ||||||
|  |     #[inline] | ||||||
|  |     pub const fn from_transform(transform: Transform) -> Self { | ||||||
|  |         TransformBundle { | ||||||
|  |             local: transform, | ||||||
|  |             ..Self::IDENTITY | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl From<Transform> for TransformBundle { | ||||||
|  |     #[inline] | ||||||
|  |     fn from(transform: Transform) -> Self { | ||||||
|  |         Self::from_transform(transform) | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -1,11 +1,10 @@ | |||||||
| //! Extension to [`EntityCommands`] to modify `bevy_hierarchy` hierarchies
 | //! Extension to [`EntityCommands`] to modify `bevy_hierarchy` hierarchies
 | ||||||
| //! while preserving [`GlobalTransform`].
 | //! while preserving [`GlobalTransform`].
 | ||||||
| 
 | 
 | ||||||
|  | use crate::prelude::{GlobalTransform, Transform}; | ||||||
| use bevy_ecs::{prelude::Entity, system::EntityCommands, world::Command, world::World}; | use bevy_ecs::{prelude::Entity, system::EntityCommands, world::Command, world::World}; | ||||||
| use bevy_hierarchy::{PushChild, RemoveParent}; | use bevy_hierarchy::{PushChild, RemoveParent}; | ||||||
| 
 | 
 | ||||||
| use crate::{GlobalTransform, Transform}; |  | ||||||
| 
 |  | ||||||
| /// Command similar to [`PushChild`], but updating the child transform to keep
 | /// Command similar to [`PushChild`], but updating the child transform to keep
 | ||||||
| /// it at the same [`GlobalTransform`].
 | /// it at the same [`GlobalTransform`].
 | ||||||
| ///
 | ///
 | ||||||
|  | |||||||
| @ -88,9 +88,10 @@ mod tests { | |||||||
|     use bevy_math::{Quat, Vec3}; |     use bevy_math::{Quat, Vec3}; | ||||||
| 
 | 
 | ||||||
|     use crate::{ |     use crate::{ | ||||||
|  |         bundles::TransformBundle, | ||||||
|         components::{GlobalTransform, Transform}, |         components::{GlobalTransform, Transform}, | ||||||
|         helper::TransformHelper, |         helper::TransformHelper, | ||||||
|         TransformBundle, TransformPlugin, |         plugins::TransformPlugin, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
|  | |||||||
| @ -8,166 +8,31 @@ | |||||||
| pub mod commands; | pub mod commands; | ||||||
| /// The basic components of the transform crate
 | /// The basic components of the transform crate
 | ||||||
| pub mod components; | pub mod components; | ||||||
|  | 
 | ||||||
|  | /// Transform related bundles
 | ||||||
|  | pub mod bundles; | ||||||
|  | 
 | ||||||
|  | /// Transform related traits
 | ||||||
|  | pub mod traits; | ||||||
|  | 
 | ||||||
|  | /// Transform related plugins
 | ||||||
|  | pub mod plugins; | ||||||
|  | 
 | ||||||
|  | /// Helpers related to computing global transforms
 | ||||||
| pub mod helper; | pub mod helper; | ||||||
| /// Systems responsible for transform propagation
 | /// Systems responsible for transform propagation
 | ||||||
| pub mod systems; | pub mod systems; | ||||||
| 
 | 
 | ||||||
| #[doc(hidden)] | #[doc(hidden)] | ||||||
| pub mod prelude { | pub mod prelude { | ||||||
|  |     #[doc(hidden)] | ||||||
|  |     pub use crate::components::*; | ||||||
|  | 
 | ||||||
|     #[doc(hidden)] |     #[doc(hidden)] | ||||||
|     pub use crate::{ |     pub use crate::{ | ||||||
|         commands::BuildChildrenTransformExt, components::*, helper::TransformHelper, |         bundles::TransformBundle, commands::BuildChildrenTransformExt, helper::TransformHelper, | ||||||
|         TransformBundle, TransformPlugin, TransformPoint, |         plugins::TransformPlugin, plugins::TransformSystem, traits::TransformPoint, | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| use bevy_app::prelude::*; | pub use prelude::{TransformPlugin, TransformPoint, TransformSystem}; | ||||||
| use bevy_ecs::prelude::*; |  | ||||||
| use bevy_hierarchy::ValidParentCheckPlugin; |  | ||||||
| use bevy_math::{Affine3A, Mat4, Vec3}; |  | ||||||
| 
 |  | ||||||
| use prelude::{GlobalTransform, Transform}; |  | ||||||
| use systems::{propagate_transforms, sync_simple_transforms}; |  | ||||||
| 
 |  | ||||||
| /// A [`Bundle`] of the [`Transform`] and [`GlobalTransform`]
 |  | ||||||
| /// [`Component`]s, which describe the position of an entity.
 |  | ||||||
| ///
 |  | ||||||
| /// * To place or move an entity, you should set its [`Transform`].
 |  | ||||||
| /// * To get the global transform of an entity, you should get its [`GlobalTransform`].
 |  | ||||||
| /// * For transform hierarchies to work correctly, you must have both a [`Transform`] and a [`GlobalTransform`].
 |  | ||||||
| ///   * You may use the [`TransformBundle`] to guarantee this.
 |  | ||||||
| ///
 |  | ||||||
| /// ## [`Transform`] and [`GlobalTransform`]
 |  | ||||||
| ///
 |  | ||||||
| /// [`Transform`] is the position of an entity relative to its parent position, or the reference
 |  | ||||||
| /// frame if it doesn't have a parent.
 |  | ||||||
| ///
 |  | ||||||
| /// [`GlobalTransform`] is the position of an entity relative to the reference frame.
 |  | ||||||
| ///
 |  | ||||||
| /// [`GlobalTransform`] is updated from [`Transform`] by systems in the system set
 |  | ||||||
| /// [`TransformPropagate`](TransformSystem::TransformPropagate).
 |  | ||||||
| ///
 |  | ||||||
| /// This system runs during [`PostUpdate`]. If you
 |  | ||||||
| /// update the [`Transform`] of an entity in this schedule or after, you will notice a 1 frame lag
 |  | ||||||
| /// before the [`GlobalTransform`] is updated.
 |  | ||||||
| #[derive(Bundle, Clone, Copy, Debug, Default)] |  | ||||||
| pub struct TransformBundle { |  | ||||||
|     /// The transform of the entity.
 |  | ||||||
|     pub local: Transform, |  | ||||||
|     /// The global transform of the entity.
 |  | ||||||
|     pub global: GlobalTransform, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl TransformBundle { |  | ||||||
|     /// An identity [`TransformBundle`] with no translation, rotation, and a scale of 1 on all axes.
 |  | ||||||
|     pub const IDENTITY: Self = TransformBundle { |  | ||||||
|         local: Transform::IDENTITY, |  | ||||||
|         global: GlobalTransform::IDENTITY, |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     /// Creates a new [`TransformBundle`] from a [`Transform`].
 |  | ||||||
|     ///
 |  | ||||||
|     /// This initializes [`GlobalTransform`] as identity, to be updated later by the
 |  | ||||||
|     /// [`PostUpdate`] schedule.
 |  | ||||||
|     #[inline] |  | ||||||
|     pub const fn from_transform(transform: Transform) -> Self { |  | ||||||
|         TransformBundle { |  | ||||||
|             local: transform, |  | ||||||
|             ..Self::IDENTITY |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl From<Transform> for TransformBundle { |  | ||||||
|     #[inline] |  | ||||||
|     fn from(transform: Transform) -> Self { |  | ||||||
|         Self::from_transform(transform) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| /// Set enum for the systems relating to transform propagation
 |  | ||||||
| #[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)] |  | ||||||
| pub enum TransformSystem { |  | ||||||
|     /// Propagates changes in transform to children's [`GlobalTransform`]
 |  | ||||||
|     TransformPropagate, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /// The base plugin for handling [`Transform`] components
 |  | ||||||
| #[derive(Default)] |  | ||||||
| pub struct TransformPlugin; |  | ||||||
| 
 |  | ||||||
| impl Plugin for TransformPlugin { |  | ||||||
|     fn build(&self, app: &mut App) { |  | ||||||
|         // A set for `propagate_transforms` to mark it as ambiguous with `sync_simple_transforms`.
 |  | ||||||
|         // Used instead of the `SystemTypeSet` as that would not allow multiple instances of the system.
 |  | ||||||
|         #[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)] |  | ||||||
|         struct PropagateTransformsSet; |  | ||||||
| 
 |  | ||||||
|         app.register_type::<Transform>() |  | ||||||
|             .register_type::<GlobalTransform>() |  | ||||||
|             .add_plugins(ValidParentCheckPlugin::<GlobalTransform>::default()) |  | ||||||
|             .configure_sets( |  | ||||||
|                 PostStartup, |  | ||||||
|                 PropagateTransformsSet.in_set(TransformSystem::TransformPropagate), |  | ||||||
|             ) |  | ||||||
|             // add transform systems to startup so the first update is "correct"
 |  | ||||||
|             .add_systems( |  | ||||||
|                 PostStartup, |  | ||||||
|                 ( |  | ||||||
|                     sync_simple_transforms |  | ||||||
|                         .in_set(TransformSystem::TransformPropagate) |  | ||||||
|                         // FIXME: https://github.com/bevyengine/bevy/issues/4381
 |  | ||||||
|                         // These systems cannot access the same entities,
 |  | ||||||
|                         // due to subtle query filtering that is not yet correctly computed in the ambiguity detector
 |  | ||||||
|                         .ambiguous_with(PropagateTransformsSet), |  | ||||||
|                     propagate_transforms.in_set(PropagateTransformsSet), |  | ||||||
|                 ), |  | ||||||
|             ) |  | ||||||
|             .configure_sets( |  | ||||||
|                 PostUpdate, |  | ||||||
|                 PropagateTransformsSet.in_set(TransformSystem::TransformPropagate), |  | ||||||
|             ) |  | ||||||
|             .add_systems( |  | ||||||
|                 PostUpdate, |  | ||||||
|                 ( |  | ||||||
|                     sync_simple_transforms |  | ||||||
|                         .in_set(TransformSystem::TransformPropagate) |  | ||||||
|                         .ambiguous_with(PropagateTransformsSet), |  | ||||||
|                     propagate_transforms.in_set(PropagateTransformsSet), |  | ||||||
|                 ), |  | ||||||
|             ); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /// A trait for point transformation methods.
 |  | ||||||
| pub trait TransformPoint { |  | ||||||
|     /// Transform a point.
 |  | ||||||
|     fn transform_point(&self, point: impl Into<Vec3>) -> Vec3; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl TransformPoint for Transform { |  | ||||||
|     #[inline] |  | ||||||
|     fn transform_point(&self, point: impl Into<Vec3>) -> Vec3 { |  | ||||||
|         self.transform_point(point.into()) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl TransformPoint for GlobalTransform { |  | ||||||
|     #[inline] |  | ||||||
|     fn transform_point(&self, point: impl Into<Vec3>) -> Vec3 { |  | ||||||
|         self.transform_point(point.into()) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl TransformPoint for Mat4 { |  | ||||||
|     #[inline] |  | ||||||
|     fn transform_point(&self, point: impl Into<Vec3>) -> Vec3 { |  | ||||||
|         self.transform_point3(point.into()) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl TransformPoint for Affine3A { |  | ||||||
|     #[inline] |  | ||||||
|     fn transform_point(&self, point: impl Into<Vec3>) -> Vec3 { |  | ||||||
|         self.transform_point3(point.into()) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | |||||||
							
								
								
									
										62
									
								
								crates/bevy_transform/src/plugins.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								crates/bevy_transform/src/plugins.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,62 @@ | |||||||
|  | use bevy_app::{App, Plugin, PostStartup, PostUpdate}; | ||||||
|  | use bevy_ecs::schedule::{IntoSystemConfigs, IntoSystemSetConfigs, SystemSet}; | ||||||
|  | use bevy_hierarchy::ValidParentCheckPlugin; | ||||||
|  | 
 | ||||||
|  | use crate::{ | ||||||
|  |     prelude::{GlobalTransform, Transform}, | ||||||
|  |     systems::{propagate_transforms, sync_simple_transforms}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /// Set enum for the systems relating to transform propagation
 | ||||||
|  | #[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)] | ||||||
|  | pub enum TransformSystem { | ||||||
|  |     /// Propagates changes in transform to children's [`GlobalTransform`]
 | ||||||
|  |     TransformPropagate, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// The base plugin for handling [`Transform`] components
 | ||||||
|  | #[derive(Default)] | ||||||
|  | pub struct TransformPlugin; | ||||||
|  | 
 | ||||||
|  | impl Plugin for TransformPlugin { | ||||||
|  |     fn build(&self, app: &mut App) { | ||||||
|  |         // A set for `propagate_transforms` to mark it as ambiguous with `sync_simple_transforms`.
 | ||||||
|  |         // Used instead of the `SystemTypeSet` as that would not allow multiple instances of the system.
 | ||||||
|  |         #[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)] | ||||||
|  |         struct PropagateTransformsSet; | ||||||
|  | 
 | ||||||
|  |         app.register_type::<Transform>() | ||||||
|  |             .register_type::<GlobalTransform>() | ||||||
|  |             .add_plugins(ValidParentCheckPlugin::<GlobalTransform>::default()) | ||||||
|  |             .configure_sets( | ||||||
|  |                 PostStartup, | ||||||
|  |                 PropagateTransformsSet.in_set(TransformSystem::TransformPropagate), | ||||||
|  |             ) | ||||||
|  |             // add transform systems to startup so the first update is "correct"
 | ||||||
|  |             .add_systems( | ||||||
|  |                 PostStartup, | ||||||
|  |                 ( | ||||||
|  |                     sync_simple_transforms | ||||||
|  |                         .in_set(TransformSystem::TransformPropagate) | ||||||
|  |                         // FIXME: https://github.com/bevyengine/bevy/issues/4381
 | ||||||
|  |                         // These systems cannot access the same entities,
 | ||||||
|  |                         // due to subtle query filtering that is not yet correctly computed in the ambiguity detector
 | ||||||
|  |                         .ambiguous_with(PropagateTransformsSet), | ||||||
|  |                     propagate_transforms.in_set(PropagateTransformsSet), | ||||||
|  |                 ), | ||||||
|  |             ) | ||||||
|  |             .configure_sets( | ||||||
|  |                 PostUpdate, | ||||||
|  |                 PropagateTransformsSet.in_set(TransformSystem::TransformPropagate), | ||||||
|  |             ) | ||||||
|  |             .add_systems( | ||||||
|  |                 PostUpdate, | ||||||
|  |                 ( | ||||||
|  |                     sync_simple_transforms | ||||||
|  |                         .in_set(TransformSystem::TransformPropagate) | ||||||
|  |                         .ambiguous_with(PropagateTransformsSet), | ||||||
|  |                     propagate_transforms.in_set(PropagateTransformsSet), | ||||||
|  |                 ), | ||||||
|  |             ); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -188,8 +188,8 @@ mod test { | |||||||
|     use bevy_math::{vec3, Vec3}; |     use bevy_math::{vec3, Vec3}; | ||||||
|     use bevy_tasks::{ComputeTaskPool, TaskPool}; |     use bevy_tasks::{ComputeTaskPool, TaskPool}; | ||||||
| 
 | 
 | ||||||
|  |     use crate::bundles::TransformBundle; | ||||||
|     use crate::systems::*; |     use crate::systems::*; | ||||||
|     use crate::TransformBundle; |  | ||||||
|     use bevy_hierarchy::{BuildChildren, BuildWorldChildren}; |     use bevy_hierarchy::{BuildChildren, BuildWorldChildren}; | ||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
|  | |||||||
							
								
								
									
										37
									
								
								crates/bevy_transform/src/traits.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								crates/bevy_transform/src/traits.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | |||||||
|  | use bevy_math::{Affine3A, Mat4, Vec3}; | ||||||
|  | 
 | ||||||
|  | use crate::prelude::{GlobalTransform, Transform}; | ||||||
|  | 
 | ||||||
|  | /// A trait for point transformation methods.
 | ||||||
|  | pub trait TransformPoint { | ||||||
|  |     /// Transform a point.
 | ||||||
|  |     fn transform_point(&self, point: impl Into<Vec3>) -> Vec3; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl TransformPoint for Transform { | ||||||
|  |     #[inline] | ||||||
|  |     fn transform_point(&self, point: impl Into<Vec3>) -> Vec3 { | ||||||
|  |         self.transform_point(point.into()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl TransformPoint for GlobalTransform { | ||||||
|  |     #[inline] | ||||||
|  |     fn transform_point(&self, point: impl Into<Vec3>) -> Vec3 { | ||||||
|  |         self.transform_point(point.into()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl TransformPoint for Mat4 { | ||||||
|  |     #[inline] | ||||||
|  |     fn transform_point(&self, point: impl Into<Vec3>) -> Vec3 { | ||||||
|  |         self.transform_point3(point.into()) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl TransformPoint for Affine3A { | ||||||
|  |     #[inline] | ||||||
|  |     fn transform_point(&self, point: impl Into<Vec3>) -> Vec3 { | ||||||
|  |         self.transform_point3(point.into()) | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Torstein Grindvik
						Torstein Grindvik