From 76d12fa2b3ae88277eef65537997ef4dd95b359b Mon Sep 17 00:00:00 2001 From: Torstein Grindvik <52322338+torsteingrindvik@users.noreply.github.com> Date: Fri, 31 May 2024 18:40:36 +0200 Subject: [PATCH] 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 Co-authored-by: Torstein Grindvik --- crates/bevy_transform/src/bundles.rs | 59 +++++++++ crates/bevy_transform/src/commands.rs | 3 +- crates/bevy_transform/src/helper.rs | 3 +- crates/bevy_transform/src/lib.rs | 169 +++----------------------- crates/bevy_transform/src/plugins.rs | 62 ++++++++++ crates/bevy_transform/src/systems.rs | 2 +- crates/bevy_transform/src/traits.rs | 37 ++++++ 7 files changed, 179 insertions(+), 156 deletions(-) create mode 100644 crates/bevy_transform/src/bundles.rs create mode 100644 crates/bevy_transform/src/plugins.rs create mode 100644 crates/bevy_transform/src/traits.rs diff --git a/crates/bevy_transform/src/bundles.rs b/crates/bevy_transform/src/bundles.rs new file mode 100644 index 0000000000..480aa6c236 --- /dev/null +++ b/crates/bevy_transform/src/bundles.rs @@ -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 for TransformBundle { + #[inline] + fn from(transform: Transform) -> Self { + Self::from_transform(transform) + } +} diff --git a/crates/bevy_transform/src/commands.rs b/crates/bevy_transform/src/commands.rs index 8cbad487ba..ec0ef0bc2e 100644 --- a/crates/bevy_transform/src/commands.rs +++ b/crates/bevy_transform/src/commands.rs @@ -1,11 +1,10 @@ //! Extension to [`EntityCommands`] to modify `bevy_hierarchy` hierarchies //! while preserving [`GlobalTransform`]. +use crate::prelude::{GlobalTransform, Transform}; use bevy_ecs::{prelude::Entity, system::EntityCommands, world::Command, world::World}; use bevy_hierarchy::{PushChild, RemoveParent}; -use crate::{GlobalTransform, Transform}; - /// Command similar to [`PushChild`], but updating the child transform to keep /// it at the same [`GlobalTransform`]. /// diff --git a/crates/bevy_transform/src/helper.rs b/crates/bevy_transform/src/helper.rs index b1be978f19..0aa3195444 100644 --- a/crates/bevy_transform/src/helper.rs +++ b/crates/bevy_transform/src/helper.rs @@ -88,9 +88,10 @@ mod tests { use bevy_math::{Quat, Vec3}; use crate::{ + bundles::TransformBundle, components::{GlobalTransform, Transform}, helper::TransformHelper, - TransformBundle, TransformPlugin, + plugins::TransformPlugin, }; #[test] diff --git a/crates/bevy_transform/src/lib.rs b/crates/bevy_transform/src/lib.rs index 2d7338cc7d..9176a0f4d5 100644 --- a/crates/bevy_transform/src/lib.rs +++ b/crates/bevy_transform/src/lib.rs @@ -8,166 +8,31 @@ pub mod commands; /// The basic components of the transform crate 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; /// Systems responsible for transform propagation pub mod systems; #[doc(hidden)] pub mod prelude { + #[doc(hidden)] + pub use crate::components::*; + #[doc(hidden)] pub use crate::{ - commands::BuildChildrenTransformExt, components::*, helper::TransformHelper, - TransformBundle, TransformPlugin, TransformPoint, + bundles::TransformBundle, commands::BuildChildrenTransformExt, helper::TransformHelper, + plugins::TransformPlugin, plugins::TransformSystem, traits::TransformPoint, }; } -use bevy_app::prelude::*; -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 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::() - .register_type::() - .add_plugins(ValidParentCheckPlugin::::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; -} - -impl TransformPoint for Transform { - #[inline] - fn transform_point(&self, point: impl Into) -> Vec3 { - self.transform_point(point.into()) - } -} - -impl TransformPoint for GlobalTransform { - #[inline] - fn transform_point(&self, point: impl Into) -> Vec3 { - self.transform_point(point.into()) - } -} - -impl TransformPoint for Mat4 { - #[inline] - fn transform_point(&self, point: impl Into) -> Vec3 { - self.transform_point3(point.into()) - } -} - -impl TransformPoint for Affine3A { - #[inline] - fn transform_point(&self, point: impl Into) -> Vec3 { - self.transform_point3(point.into()) - } -} +pub use prelude::{TransformPlugin, TransformPoint, TransformSystem}; diff --git a/crates/bevy_transform/src/plugins.rs b/crates/bevy_transform/src/plugins.rs new file mode 100644 index 0000000000..07bb35c311 --- /dev/null +++ b/crates/bevy_transform/src/plugins.rs @@ -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::() + .register_type::() + .add_plugins(ValidParentCheckPlugin::::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), + ), + ); + } +} diff --git a/crates/bevy_transform/src/systems.rs b/crates/bevy_transform/src/systems.rs index 401a32cb22..8ddba24780 100644 --- a/crates/bevy_transform/src/systems.rs +++ b/crates/bevy_transform/src/systems.rs @@ -188,8 +188,8 @@ mod test { use bevy_math::{vec3, Vec3}; use bevy_tasks::{ComputeTaskPool, TaskPool}; + use crate::bundles::TransformBundle; use crate::systems::*; - use crate::TransformBundle; use bevy_hierarchy::{BuildChildren, BuildWorldChildren}; #[test] diff --git a/crates/bevy_transform/src/traits.rs b/crates/bevy_transform/src/traits.rs new file mode 100644 index 0000000000..f0984272ab --- /dev/null +++ b/crates/bevy_transform/src/traits.rs @@ -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; +} + +impl TransformPoint for Transform { + #[inline] + fn transform_point(&self, point: impl Into) -> Vec3 { + self.transform_point(point.into()) + } +} + +impl TransformPoint for GlobalTransform { + #[inline] + fn transform_point(&self, point: impl Into) -> Vec3 { + self.transform_point(point.into()) + } +} + +impl TransformPoint for Mat4 { + #[inline] + fn transform_point(&self, point: impl Into) -> Vec3 { + self.transform_point3(point.into()) + } +} + +impl TransformPoint for Affine3A { + #[inline] + fn transform_point(&self, point: impl Into) -> Vec3 { + self.transform_point3(point.into()) + } +}