From 191c12d4ee62ce70ec62d46e40ca249ff820f18b Mon Sep 17 00:00:00 2001 From: Alice Cecile Date: Tue, 15 Mar 2022 01:54:05 +0000 Subject: [PATCH] Split bevy_hierarchy out from bevy_transform (#4168) # Objective - Hierarchy tools are not just used for `Transform`: they are also used for scenes. - In the future there's interest in using them for other features, such as visiibility inheritance. - The fact that these tools are found in `bevy_transform` causes a great deal of user and developer confusion - Fixes #2758. ## Solution - Split `bevy_transform` into two! - Make everything work again. Note that this is a very tightly scoped PR: I *know* there are code quality and docs issues that existed in bevy_transform that I've just moved around. We should fix those in a seperate PR and try to merge this ASAP to reduce the bitrot involved in splitting an entire crate. ## Frustrations The API around `GlobalTransform` is a mess: we have massive code and docs duplication, no link between the two types and no clear way to extend this to other forms of inheritance. In the medium-term, I feel pretty strongly that `GlobalTransform` should be replaced by something like `Inherited`, which lives in `bevy_hierarchy`: - avoids code duplication - makes the inheritance pattern extensible - links the types at the type-level - allows us to remove all references to inheritance from `bevy_transform`, making it more useful as a standalone crate and cleaning up its docs ## Additional context - double-blessed by @cart in https://github.com/bevyengine/bevy/issues/4141#issuecomment-1063592414 and https://github.com/bevyengine/bevy/issues/2758#issuecomment-913810963 - preparation for more advanced / cleaner hierarchy tools: go read https://github.com/bevyengine/rfcs/pull/53 ! - originally attempted by @finegeometer in #2789. It was a great idea, just needed more discussion! Co-authored-by: Carter Anderson --- crates/bevy_gltf/Cargo.toml | 1 + crates/bevy_gltf/src/loader.rs | 8 +- crates/bevy_hierarchy/Cargo.toml | 19 ++++ .../src}/child_builder.rs | 0 .../src/components/children.rs | 0 crates/bevy_hierarchy/src/components/mod.rs | 5 + .../src/components/parent.rs | 0 .../src}/hierarchy.rs | 2 +- crates/bevy_hierarchy/src/lib.rs | 53 +++++++++ .../src/systems.rs} | 98 ----------------- crates/bevy_internal/Cargo.toml | 1 + crates/bevy_internal/src/default_plugins.rs | 2 + crates/bevy_internal/src/lib.rs | 5 + crates/bevy_internal/src/prelude.rs | 4 +- crates/bevy_render/src/view/visibility/mod.rs | 3 +- crates/bevy_scene/Cargo.toml | 2 +- crates/bevy_scene/src/command.rs | 2 +- crates/bevy_scene/src/scene_spawner.rs | 2 +- crates/bevy_transform/.gitignore | 24 ----- crates/bevy_transform/Cargo.toml | 7 +- .../src/components/global_transform.rs | 4 +- crates/bevy_transform/src/components/mod.rs | 4 - .../src/components/transform.rs | 4 +- crates/bevy_transform/src/hierarchy/mod.rs | 8 -- crates/bevy_transform/src/lib.rs | 57 ++++------ ...ansform_propagate_system.rs => systems.rs} | 102 ++++++++++++++++-- crates/bevy_ui/Cargo.toml | 1 + crates/bevy_ui/src/flex/mod.rs | 3 +- crates/bevy_ui/src/update.rs | 9 +- 29 files changed, 225 insertions(+), 205 deletions(-) create mode 100644 crates/bevy_hierarchy/Cargo.toml rename crates/{bevy_transform/src/hierarchy => bevy_hierarchy/src}/child_builder.rs (100%) rename crates/{bevy_transform => bevy_hierarchy}/src/components/children.rs (100%) create mode 100644 crates/bevy_hierarchy/src/components/mod.rs rename crates/{bevy_transform => bevy_hierarchy}/src/components/parent.rs (100%) rename crates/{bevy_transform/src/hierarchy => bevy_hierarchy/src}/hierarchy.rs (98%) create mode 100644 crates/bevy_hierarchy/src/lib.rs rename crates/{bevy_transform/src/hierarchy/hierarchy_maintenance_system.rs => bevy_hierarchy/src/systems.rs} (53%) delete mode 100644 crates/bevy_transform/.gitignore delete mode 100644 crates/bevy_transform/src/hierarchy/mod.rs rename crates/bevy_transform/src/{transform_propagate_system.rs => systems.rs} (66%) diff --git a/crates/bevy_gltf/Cargo.toml b/crates/bevy_gltf/Cargo.toml index 79d05e0708c219..4d9e96ab3c71c3 100644 --- a/crates/bevy_gltf/Cargo.toml +++ b/crates/bevy_gltf/Cargo.toml @@ -14,6 +14,7 @@ bevy_app = { path = "../bevy_app", version = "0.6.0" } bevy_asset = { path = "../bevy_asset", version = "0.6.0" } bevy_core = { path = "../bevy_core", version = "0.6.0" } bevy_ecs = { path = "../bevy_ecs", version = "0.6.0" } +bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.6.0" } bevy_pbr = { path = "../bevy_pbr", version = "0.6.0" } bevy_reflect = { path = "../bevy_reflect", version = "0.6.0", features = ["bevy"] } bevy_render = { path = "../bevy_render", version = "0.6.0" } diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index 293e4bece8dd1f..464f89c4a9be69 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -4,6 +4,7 @@ use bevy_asset::{ }; use bevy_core::Name; use bevy_ecs::world::World; +use bevy_hierarchy::{BuildWorldChildren, WorldChildBuilder}; use bevy_log::warn; use bevy_math::{Mat4, Vec3}; use bevy_pbr::{ @@ -24,11 +25,8 @@ use bevy_render::{ view::VisibleEntities, }; use bevy_scene::Scene; -use bevy_transform::{ - hierarchy::{BuildWorldChildren, WorldChildBuilder}, - prelude::Transform, - TransformBundle, -}; +use bevy_transform::{components::Transform, TransformBundle}; + use bevy_utils::{HashMap, HashSet}; use gltf::{ mesh::Mode, diff --git a/crates/bevy_hierarchy/Cargo.toml b/crates/bevy_hierarchy/Cargo.toml new file mode 100644 index 00000000000000..69290ddd68fb46 --- /dev/null +++ b/crates/bevy_hierarchy/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "bevy_hierarchy" +version = "0.6.0" +edition = "2021" +description = "Provides hierarchy functionality for Bevy Engine" +homepage = "https://bevyengine.org" +repository = "https://github.com/bevyengine/bevy" +license = "MIT OR Apache-2.0" +keywords = ["bevy"] + +[dependencies] +# bevy +bevy_app = { path = "../bevy_app", version = "0.6.0" } +bevy_ecs = { path = "../bevy_ecs", version = "0.6.0", features = ["bevy_reflect"] } +bevy_reflect = { path = "../bevy_reflect", version = "0.6.0", features = ["bevy"] } +bevy_utils = { path = "../bevy_utils", version = "0.6.0" } + +# other +smallvec = { version = "1.6", features = ["serde", "union", "const_generics"] } diff --git a/crates/bevy_transform/src/hierarchy/child_builder.rs b/crates/bevy_hierarchy/src/child_builder.rs similarity index 100% rename from crates/bevy_transform/src/hierarchy/child_builder.rs rename to crates/bevy_hierarchy/src/child_builder.rs diff --git a/crates/bevy_transform/src/components/children.rs b/crates/bevy_hierarchy/src/components/children.rs similarity index 100% rename from crates/bevy_transform/src/components/children.rs rename to crates/bevy_hierarchy/src/components/children.rs diff --git a/crates/bevy_hierarchy/src/components/mod.rs b/crates/bevy_hierarchy/src/components/mod.rs new file mode 100644 index 00000000000000..3d6928ea3f0ae2 --- /dev/null +++ b/crates/bevy_hierarchy/src/components/mod.rs @@ -0,0 +1,5 @@ +mod children; +mod parent; + +pub use children::Children; +pub use parent::{Parent, PreviousParent}; diff --git a/crates/bevy_transform/src/components/parent.rs b/crates/bevy_hierarchy/src/components/parent.rs similarity index 100% rename from crates/bevy_transform/src/components/parent.rs rename to crates/bevy_hierarchy/src/components/parent.rs diff --git a/crates/bevy_transform/src/hierarchy/hierarchy.rs b/crates/bevy_hierarchy/src/hierarchy.rs similarity index 98% rename from crates/bevy_transform/src/hierarchy/hierarchy.rs rename to crates/bevy_hierarchy/src/hierarchy.rs index 0820742c34b75d..56c9b0f8ad9389 100644 --- a/crates/bevy_transform/src/hierarchy/hierarchy.rs +++ b/crates/bevy_hierarchy/src/hierarchy.rs @@ -116,7 +116,7 @@ mod tests { }; use super::DespawnRecursiveExt; - use crate::{components::Children, hierarchy::BuildChildren}; + use crate::{child_builder::BuildChildren, components::Children}; #[derive(Component, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Debug)] struct Idx(u32); diff --git a/crates/bevy_hierarchy/src/lib.rs b/crates/bevy_hierarchy/src/lib.rs new file mode 100644 index 00000000000000..60fa42f525e97e --- /dev/null +++ b/crates/bevy_hierarchy/src/lib.rs @@ -0,0 +1,53 @@ +#![warn(missing_docs)] +//! `bevy_hierarchy` can be used to define hierarchies of entities. +//! +//! Most commonly, these hierarchies are used for inheriting `Transform` values +//! from the [`Parent`] to its [`Children`]. + +mod components; +pub use components::*; + +mod hierarchy; +pub use hierarchy::*; + +mod child_builder; +pub use child_builder::*; + +mod systems; +pub use systems::*; + +#[doc(hidden)] +pub mod prelude { + #[doc(hidden)] + pub use crate::{child_builder::*, components::*, hierarchy::*, HierarchyPlugin}; +} + +use bevy_app::prelude::*; +use bevy_ecs::prelude::*; + +/// The base plugin for handling [`Parent`] and [`Children`] components +#[derive(Default)] +pub struct HierarchyPlugin; + +/// Label enum for the systems relating to hierarchy upkeep +#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemLabel)] +pub enum HierarchySystem { + /// Updates [`Parent`] when changes in the hierarchy occur + ParentUpdate, +} + +impl Plugin for HierarchyPlugin { + fn build(&self, app: &mut App) { + app.register_type::() + .register_type::() + .register_type::() + .add_startup_system_to_stage( + StartupStage::PostStartup, + parent_update_system.label(HierarchySystem::ParentUpdate), + ) + .add_system_to_stage( + CoreStage::PostUpdate, + parent_update_system.label(HierarchySystem::ParentUpdate), + ); + } +} diff --git a/crates/bevy_transform/src/hierarchy/hierarchy_maintenance_system.rs b/crates/bevy_hierarchy/src/systems.rs similarity index 53% rename from crates/bevy_transform/src/hierarchy/hierarchy_maintenance_system.rs rename to crates/bevy_hierarchy/src/systems.rs index dbbeacab12e8fb..194f0da0c2af4a 100644 --- a/crates/bevy_transform/src/hierarchy/hierarchy_maintenance_system.rs +++ b/crates/bevy_hierarchy/src/systems.rs @@ -70,101 +70,3 @@ pub fn parent_update_system( commands.entity(*e).insert(Children::with(v)); }); } -#[cfg(test)] -mod test { - use bevy_ecs::{ - schedule::{Schedule, Stage, SystemStage}, - system::CommandQueue, - world::World, - }; - - use super::*; - use crate::{hierarchy::BuildChildren, transform_propagate_system::transform_propagate_system}; - - #[test] - fn correct_children() { - let mut world = World::default(); - - let mut update_stage = SystemStage::parallel(); - update_stage.add_system(parent_update_system); - update_stage.add_system(transform_propagate_system); - - let mut schedule = Schedule::default(); - schedule.add_stage("update", update_stage); - - // Add parent entities - let mut command_queue = CommandQueue::default(); - let mut commands = Commands::new(&mut command_queue, &world); - let mut children = Vec::new(); - let parent = commands - .spawn() - .insert(Transform::from_xyz(1.0, 0.0, 0.0)) - .id(); - commands.entity(parent).with_children(|parent| { - children.push( - parent - .spawn() - .insert(Transform::from_xyz(0.0, 2.0, 0.0)) - .id(), - ); - children.push( - parent - .spawn() - .insert(Transform::from_xyz(0.0, 3.0, 0.0)) - .id(), - ); - }); - command_queue.apply(&mut world); - schedule.run(&mut world); - - assert_eq!( - world - .get::(parent) - .unwrap() - .0 - .iter() - .cloned() - .collect::>(), - children, - ); - - // Parent `e1` to `e2`. - (*world.get_mut::(children[0]).unwrap()).0 = children[1]; - - schedule.run(&mut world); - - assert_eq!( - world - .get::(parent) - .unwrap() - .iter() - .cloned() - .collect::>(), - vec![children[1]] - ); - - assert_eq!( - world - .get::(children[1]) - .unwrap() - .iter() - .cloned() - .collect::>(), - vec![children[0]] - ); - - assert!(world.despawn(children[0])); - - schedule.run(&mut world); - - assert_eq!( - world - .get::(parent) - .unwrap() - .iter() - .cloned() - .collect::>(), - vec![children[1]] - ); - } -} diff --git a/crates/bevy_internal/Cargo.toml b/crates/bevy_internal/Cargo.toml index 36642c9bc652c8..4b9891f3ff0658 100644 --- a/crates/bevy_internal/Cargo.toml +++ b/crates/bevy_internal/Cargo.toml @@ -56,6 +56,7 @@ bevy_core = { path = "../bevy_core", version = "0.6.0" } bevy_derive = { path = "../bevy_derive", version = "0.6.0" } bevy_diagnostic = { path = "../bevy_diagnostic", version = "0.6.0" } bevy_ecs = { path = "../bevy_ecs", version = "0.6.0" } +bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.6.0" } bevy_input = { path = "../bevy_input", version = "0.6.0" } bevy_log = { path = "../bevy_log", version = "0.6.0" } bevy_math = { path = "../bevy_math", version = "0.6.0" } diff --git a/crates/bevy_internal/src/default_plugins.rs b/crates/bevy_internal/src/default_plugins.rs index 76ccb2954c4be7..d4badf887d49c2 100644 --- a/crates/bevy_internal/src/default_plugins.rs +++ b/crates/bevy_internal/src/default_plugins.rs @@ -4,6 +4,7 @@ use bevy_app::{PluginGroup, PluginGroupBuilder}; /// * [`LogPlugin`](bevy_log::LogPlugin) /// * [`CorePlugin`](bevy_core::CorePlugin) /// * [`TransformPlugin`](bevy_transform::TransformPlugin) +/// * [`HierarchyPlugin`](bevy_hierarchy::HierarchyPlugin) /// * [`DiagnosticsPlugin`](bevy_diagnostic::DiagnosticsPlugin) /// * [`InputPlugin`](bevy_input::InputPlugin) /// * [`WindowPlugin`](bevy_window::WindowPlugin) @@ -27,6 +28,7 @@ impl PluginGroup for DefaultPlugins { group.add(bevy_log::LogPlugin::default()); group.add(bevy_core::CorePlugin::default()); group.add(bevy_transform::TransformPlugin::default()); + group.add(bevy_hierarchy::HierarchyPlugin::default()); group.add(bevy_diagnostic::DiagnosticsPlugin::default()); group.add(bevy_input::InputPlugin::default()); group.add(bevy_window::WindowPlugin::default()); diff --git a/crates/bevy_internal/src/lib.rs b/crates/bevy_internal/src/lib.rs index 3df3d0c2c9ec72..bf65182c7f6621 100644 --- a/crates/bevy_internal/src/lib.rs +++ b/crates/bevy_internal/src/lib.rs @@ -65,6 +65,11 @@ pub mod tasks { pub use bevy_tasks::*; } +pub mod hierarchy { + //! Entity hierarchies and property inheritance + pub use bevy_hierarchy::*; +} + pub mod transform { //! Local and global transforms (e.g. translation, scale, rotation). pub use bevy_transform::*; diff --git a/crates/bevy_internal/src/prelude.rs b/crates/bevy_internal/src/prelude.rs index 7bd1170c05ef66..148d245beed45a 100644 --- a/crates/bevy_internal/src/prelude.rs +++ b/crates/bevy_internal/src/prelude.rs @@ -1,7 +1,7 @@ #[doc(hidden)] pub use crate::{ - app::prelude::*, asset::prelude::*, core::prelude::*, ecs::prelude::*, input::prelude::*, - log::prelude::*, math::prelude::*, reflect::prelude::*, scene::prelude::*, + app::prelude::*, asset::prelude::*, core::prelude::*, ecs::prelude::*, hierarchy::prelude::*, + input::prelude::*, log::prelude::*, math::prelude::*, reflect::prelude::*, scene::prelude::*, transform::prelude::*, utils::prelude::*, window::prelude::*, DefaultPlugins, MinimalPlugins, }; diff --git a/crates/bevy_render/src/view/visibility/mod.rs b/crates/bevy_render/src/view/visibility/mod.rs index cec6525d1acf20..860ebb2142dae1 100644 --- a/crates/bevy_render/src/view/visibility/mod.rs +++ b/crates/bevy_render/src/view/visibility/mod.rs @@ -6,7 +6,8 @@ use bevy_app::{CoreStage, Plugin}; use bevy_asset::{Assets, Handle}; use bevy_ecs::prelude::*; use bevy_reflect::Reflect; -use bevy_transform::{components::GlobalTransform, TransformSystem}; +use bevy_transform::components::GlobalTransform; +use bevy_transform::TransformSystem; use crate::{ camera::{Camera, CameraProjection, OrthographicProjection, PerspectiveProjection}, diff --git a/crates/bevy_scene/Cargo.toml b/crates/bevy_scene/Cargo.toml index adecdd8f76cb4f..e63d7db638a2ad 100644 --- a/crates/bevy_scene/Cargo.toml +++ b/crates/bevy_scene/Cargo.toml @@ -14,7 +14,7 @@ bevy_app = { path = "../bevy_app", version = "0.6.0" } bevy_asset = { path = "../bevy_asset", version = "0.6.0" } bevy_ecs = { path = "../bevy_ecs", version = "0.6.0" } bevy_reflect = { path = "../bevy_reflect", version = "0.6.0", features = ["bevy"] } -bevy_transform = { path = "../bevy_transform", version = "0.6.0" } +bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.6.0" } bevy_utils = { path = "../bevy_utils", version = "0.6.0" } # other diff --git a/crates/bevy_scene/src/command.rs b/crates/bevy_scene/src/command.rs index 0bed5edf17e51c..55b8c4ec85db84 100644 --- a/crates/bevy_scene/src/command.rs +++ b/crates/bevy_scene/src/command.rs @@ -4,7 +4,7 @@ use bevy_ecs::{ system::{Command, Commands}, world::World, }; -use bevy_transform::hierarchy::ChildBuilder; +use bevy_hierarchy::ChildBuilder; use crate::{Scene, SceneSpawner}; diff --git a/crates/bevy_scene/src/scene_spawner.rs b/crates/bevy_scene/src/scene_spawner.rs index fdaedcead32fae..142d299743efd6 100644 --- a/crates/bevy_scene/src/scene_spawner.rs +++ b/crates/bevy_scene/src/scene_spawner.rs @@ -7,8 +7,8 @@ use bevy_ecs::{ system::Command, world::{Mut, World}, }; +use bevy_hierarchy::{AddChild, Parent}; use bevy_reflect::TypeRegistryArc; -use bevy_transform::{hierarchy::AddChild, prelude::Parent}; use bevy_utils::{tracing::error, HashMap}; use thiserror::Error; use uuid::Uuid; diff --git a/crates/bevy_transform/.gitignore b/crates/bevy_transform/.gitignore deleted file mode 100644 index af368c3d50227f..00000000000000 --- a/crates/bevy_transform/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -book/book -target -Cargo.lock -*.log - -# Backup files -.DS_Store -thumbs.db -*~ -*.rs.bk -*.swp - -# IDE / Editor files -*.iml -.idea -.vscode - - -#Added by cargo -# -#already existing elements are commented out - -/target -**/*.rs.bk diff --git a/crates/bevy_transform/Cargo.toml b/crates/bevy_transform/Cargo.toml index c09078e2114113..207a4291876808 100644 --- a/crates/bevy_transform/Cargo.toml +++ b/crates/bevy_transform/Cargo.toml @@ -2,7 +2,7 @@ name = "bevy_transform" version = "0.6.0" edition = "2021" -description = "Provides hierarchy and transform functionality for Bevy Engine" +description = "Provides transform functionality for Bevy Engine" homepage = "https://bevyengine.org" repository = "https://github.com/bevyengine/bevy" license = "MIT OR Apache-2.0" @@ -12,9 +12,6 @@ keywords = ["bevy"] # bevy bevy_app = { path = "../bevy_app", version = "0.6.0" } bevy_ecs = { path = "../bevy_ecs", version = "0.6.0", features = ["bevy_reflect"] } +bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.6.0"} bevy_math = { path = "../bevy_math", version = "0.6.0" } bevy_reflect = { path = "../bevy_reflect", version = "0.6.0", features = ["bevy"] } -bevy_utils = { path = "../bevy_utils", version = "0.6.0" } - -# other -smallvec = { version = "1.6", features = ["serde", "union", "const_generics"] } diff --git a/crates/bevy_transform/src/components/global_transform.rs b/crates/bevy_transform/src/components/global_transform.rs index 68664507d4455c..f1bce519939149 100644 --- a/crates/bevy_transform/src/components/global_transform.rs +++ b/crates/bevy_transform/src/components/global_transform.rs @@ -14,12 +14,12 @@ use std::ops::Mul; /// ## [`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`](super::Parent). +/// frame if it doesn't have a [`Parent`](bevy_hierarchy::Parent). /// /// [`GlobalTransform`] is the position of an entity relative to the reference frame. /// /// [`GlobalTransform`] is updated from [`Transform`] in the system -/// [`transform_propagate_system`](crate::transform_propagate_system::transform_propagate_system). +/// [`transform_propagate_system`](crate::transform_propagate_system). /// /// This system runs in stage [`CoreStage::PostUpdate`](crate::CoreStage::PostUpdate). If you /// update the[`Transform`] of an entity in this stage or after, you will notice a 1 frame lag diff --git a/crates/bevy_transform/src/components/mod.rs b/crates/bevy_transform/src/components/mod.rs index 67720a2b4e08e0..10d3f72e3a4630 100644 --- a/crates/bevy_transform/src/components/mod.rs +++ b/crates/bevy_transform/src/components/mod.rs @@ -1,9 +1,5 @@ -mod children; mod global_transform; -mod parent; mod transform; -pub use children::Children; pub use global_transform::*; -pub use parent::{Parent, PreviousParent}; pub use transform::*; diff --git a/crates/bevy_transform/src/components/transform.rs b/crates/bevy_transform/src/components/transform.rs index f0c6d536f3982b..80c80c7f54fbe7 100644 --- a/crates/bevy_transform/src/components/transform.rs +++ b/crates/bevy_transform/src/components/transform.rs @@ -15,12 +15,12 @@ use std::ops::Mul; /// ## [`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`](super::Parent). +/// frame if it doesn't have a [`Parent`](bevy_hierarchy::Parent). /// /// [`GlobalTransform`] is the position of an entity relative to the reference frame. /// /// [`GlobalTransform`] is updated from [`Transform`] in the system -/// [`transform_propagate_system`](crate::transform_propagate_system::transform_propagate_system). +/// [`transform_propagate_system`](crate::transform_propagate_system). /// /// This system runs in stage [`CoreStage::PostUpdate`](crate::CoreStage::PostUpdate). If you /// update the[`Transform`] of an entity in this stage or after, you will notice a 1 frame lag diff --git a/crates/bevy_transform/src/hierarchy/mod.rs b/crates/bevy_transform/src/hierarchy/mod.rs deleted file mode 100644 index 23e9108e2dec2c..00000000000000 --- a/crates/bevy_transform/src/hierarchy/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -mod child_builder; -#[allow(clippy::module_inception)] -mod hierarchy; -mod hierarchy_maintenance_system; - -pub use child_builder::*; -pub use hierarchy::*; -pub use hierarchy_maintenance_system::*; diff --git a/crates/bevy_transform/src/lib.rs b/crates/bevy_transform/src/lib.rs index 45ab1f2ab79883..a88017c7d7d60a 100644 --- a/crates/bevy_transform/src/lib.rs +++ b/crates/bevy_transform/src/lib.rs @@ -3,23 +3,19 @@ /// The basic components of the transform crate pub mod components; -/// Establishing and updating the transform hierarchy -pub mod hierarchy; -/// Propagating transform changes down the transform hierarchy -pub mod transform_propagate_system; +mod systems; +pub use crate::systems::transform_propagate_system; #[doc(hidden)] pub mod prelude { #[doc(hidden)] - pub use crate::{components::*, hierarchy::*, TransformBundle, TransformPlugin}; + pub use crate::{components::*, TransformBundle, TransformPlugin}; } use bevy_app::prelude::*; -use bevy_ecs::{ - bundle::Bundle, - schedule::{ParallelSystemDescriptorCoercion, SystemLabel}, -}; -use prelude::{parent_update_system, Children, GlobalTransform, Parent, PreviousParent, Transform}; +use bevy_ecs::prelude::*; +use bevy_hierarchy::HierarchySystem; +use prelude::{GlobalTransform, Transform}; /// A [`Bundle`] of the [`Transform`] and [`GlobalTransform`] /// [`Component`](bevy_ecs::component::Component)s, which describe the position of an entity. @@ -32,12 +28,12 @@ use prelude::{parent_update_system, Children, GlobalTransform, Parent, PreviousP /// ## [`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`](Parent). +/// 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`] in the system -/// [`transform_propagate_system`](crate::transform_propagate_system::transform_propagate_system). +/// [`transform_propagate_system`]. /// /// This system runs in stage [`CoreStage::PostUpdate`](crate::CoreStage::PostUpdate). If you /// update the[`Transform`] of an entity in this stage or after, you will notice a 1 frame lag @@ -81,46 +77,33 @@ impl From for TransformBundle { Self::from_transform(transform) } } -/// The base plugin for handling [`Transform`] components -#[derive(Default)] -pub struct TransformPlugin; - -/// Label enum for the types of systems relating to transform +/// Label enum for the systems relating to transform propagation #[derive(Debug, Hash, PartialEq, Eq, Clone, SystemLabel)] pub enum TransformSystem { - /// Propagates changes in transform to childrens' [`GlobalTransform`] + /// Propagates changes in transform to childrens' [`GlobalTransform`](crate::components::GlobalTransform) TransformPropagate, - /// Updates [`Parent`] when changes in the hierarchy occur - ParentUpdate, } +/// The base plugin for handling [`Transform`] components +#[derive(Default)] +pub struct TransformPlugin; + impl Plugin for TransformPlugin { fn build(&self, app: &mut App) { - app.register_type::() - .register_type::() - .register_type::() - .register_type::() + app.register_type::() .register_type::() - // add transform systems to startup so the first update is "correct" - .add_startup_system_to_stage( - StartupStage::PostStartup, - parent_update_system.label(TransformSystem::ParentUpdate), - ) + // Adding these to startup ensures the first update is "correct" .add_startup_system_to_stage( StartupStage::PostStartup, - transform_propagate_system::transform_propagate_system + systems::transform_propagate_system .label(TransformSystem::TransformPropagate) - .after(TransformSystem::ParentUpdate), - ) - .add_system_to_stage( - CoreStage::PostUpdate, - parent_update_system.label(TransformSystem::ParentUpdate), + .after(HierarchySystem::ParentUpdate), ) .add_system_to_stage( CoreStage::PostUpdate, - transform_propagate_system::transform_propagate_system + systems::transform_propagate_system .label(TransformSystem::TransformPropagate) - .after(TransformSystem::ParentUpdate), + .after(HierarchySystem::ParentUpdate), ); } } diff --git a/crates/bevy_transform/src/transform_propagate_system.rs b/crates/bevy_transform/src/systems.rs similarity index 66% rename from crates/bevy_transform/src/transform_propagate_system.rs rename to crates/bevy_transform/src/systems.rs index fb6ef6b1db7f89..9fb2e9a2d0ef9a 100644 --- a/crates/bevy_transform/src/transform_propagate_system.rs +++ b/crates/bevy_transform/src/systems.rs @@ -1,9 +1,10 @@ -use crate::components::{Children, GlobalTransform, Parent, Transform}; +use crate::components::{GlobalTransform, Transform}; use bevy_ecs::{ entity::Entity, query::{Changed, With, Without}, system::Query, }; +use bevy_hierarchy::{Children, Parent}; /// Update [`GlobalTransform`] component of entities based on entity hierarchy and /// [`Transform`] component. @@ -24,7 +25,7 @@ pub fn transform_propagate_system( } if let Some(children) = children { - for child in children.0.iter() { + for child in children.iter() { propagate_recursive( &global_transform, &changed_transform_query, @@ -60,7 +61,7 @@ fn propagate_recursive( }; if let Ok(Some(children)) = children_query.get(entity) { - for child in children.0.iter() { + for child in children.iter() { propagate_recursive( &global_matrix, changed_transform_query, @@ -81,10 +82,11 @@ mod test { world::World, }; - use super::*; - use crate::{ - hierarchy::{parent_update_system, BuildChildren, BuildWorldChildren}, - TransformBundle, + use crate::components::{GlobalTransform, Transform}; + use crate::systems::transform_propagate_system; + use crate::TransformBundle; + use bevy_hierarchy::{ + parent_update_system, BuildChildren, BuildWorldChildren, Children, Parent, }; #[test] @@ -174,4 +176,90 @@ mod test { GlobalTransform::from_xyz(1.0, 0.0, 0.0) * Transform::from_xyz(0.0, 0.0, 3.0) ); } + + #[test] + fn correct_children() { + let mut world = World::default(); + + let mut update_stage = SystemStage::parallel(); + update_stage.add_system(parent_update_system); + update_stage.add_system(transform_propagate_system); + + let mut schedule = Schedule::default(); + schedule.add_stage("update", update_stage); + + // Add parent entities + let mut command_queue = CommandQueue::default(); + let mut commands = Commands::new(&mut command_queue, &world); + let mut children = Vec::new(); + let parent = commands + .spawn() + .insert(Transform::from_xyz(1.0, 0.0, 0.0)) + .id(); + commands.entity(parent).with_children(|parent| { + children.push( + parent + .spawn() + .insert(Transform::from_xyz(0.0, 2.0, 0.0)) + .id(), + ); + children.push( + parent + .spawn() + .insert(Transform::from_xyz(0.0, 3.0, 0.0)) + .id(), + ); + }); + command_queue.apply(&mut world); + schedule.run(&mut world); + + assert_eq!( + world + .get::(parent) + .unwrap() + .iter() + .cloned() + .collect::>(), + children, + ); + + // Parent `e1` to `e2`. + (*world.get_mut::(children[0]).unwrap()).0 = children[1]; + + schedule.run(&mut world); + + assert_eq!( + world + .get::(parent) + .unwrap() + .iter() + .cloned() + .collect::>(), + vec![children[1]] + ); + + assert_eq!( + world + .get::(children[1]) + .unwrap() + .iter() + .cloned() + .collect::>(), + vec![children[0]] + ); + + assert!(world.despawn(children[0])); + + schedule.run(&mut world); + + assert_eq!( + world + .get::(parent) + .unwrap() + .iter() + .cloned() + .collect::>(), + vec![children[1]] + ); + } } diff --git a/crates/bevy_ui/Cargo.toml b/crates/bevy_ui/Cargo.toml index 6954fa9d1be48b..4a7fce13a4aaa2 100644 --- a/crates/bevy_ui/Cargo.toml +++ b/crates/bevy_ui/Cargo.toml @@ -16,6 +16,7 @@ bevy_core = { path = "../bevy_core", version = "0.6.0" } bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.6.0" } bevy_derive = { path = "../bevy_derive", version = "0.6.0" } bevy_ecs = { path = "../bevy_ecs", version = "0.6.0" } +bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.6.0" } bevy_input = { path = "../bevy_input", version = "0.6.0" } bevy_log = { path = "../bevy_log", version = "0.6.0" } bevy_math = { path = "../bevy_math", version = "0.6.0" } diff --git a/crates/bevy_ui/src/flex/mod.rs b/crates/bevy_ui/src/flex/mod.rs index cda1167e7446c4..63ccf94a2ca13f 100644 --- a/crates/bevy_ui/src/flex/mod.rs +++ b/crates/bevy_ui/src/flex/mod.rs @@ -7,9 +7,10 @@ use bevy_ecs::{ query::{Changed, FilterFetch, With, Without, WorldQuery}, system::{Query, Res, ResMut}, }; +use bevy_hierarchy::{Children, Parent}; use bevy_log::warn; use bevy_math::Vec2; -use bevy_transform::prelude::{Children, Parent, Transform}; +use bevy_transform::components::Transform; use bevy_utils::HashMap; use bevy_window::{Window, WindowId, WindowScaleFactorChanged, Windows}; use std::fmt; diff --git a/crates/bevy_ui/src/update.rs b/crates/bevy_ui/src/update.rs index 9fe53009b93a00..8af7d72caca628 100644 --- a/crates/bevy_ui/src/update.rs +++ b/crates/bevy_ui/src/update.rs @@ -8,12 +8,10 @@ use bevy_ecs::{ query::{With, Without}, system::{Commands, Query}, }; +use bevy_hierarchy::{Children, Parent}; use bevy_math::Vec2; use bevy_sprite::Rect; -use bevy_transform::{ - components::GlobalTransform, - prelude::{Children, Parent, Transform}, -}; +use bevy_transform::components::{GlobalTransform, Transform}; /// The resolution of Z values for UI pub const UI_Z_STEP: f32 = 0.001; @@ -141,7 +139,8 @@ mod tests { system::{CommandQueue, Commands}, world::World, }; - use bevy_transform::{components::Transform, hierarchy::BuildChildren}; + use bevy_hierarchy::BuildChildren; + use bevy_transform::components::Transform; use crate::Node;