Skip to content

Commit a304fd9

Browse files
alice-i-cecilecart
andcommitted
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<Transform>`, 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 #4141 (comment) and #2758 (comment) - preparation for more advanced / cleaner hierarchy tools: go read bevyengine/rfcs#53 ! - originally attempted by @finegeometer in #2789. It was a great idea, just needed more discussion! Co-authored-by: Carter Anderson <[email protected]>
1 parent a291b5a commit a304fd9

File tree

29 files changed

+225
-205
lines changed

29 files changed

+225
-205
lines changed

crates/bevy_gltf/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ bevy_app = { path = "../bevy_app", version = "0.6.0" }
1414
bevy_asset = { path = "../bevy_asset", version = "0.6.0" }
1515
bevy_core = { path = "../bevy_core", version = "0.6.0" }
1616
bevy_ecs = { path = "../bevy_ecs", version = "0.6.0" }
17+
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.6.0" }
1718
bevy_pbr = { path = "../bevy_pbr", version = "0.6.0" }
1819
bevy_reflect = { path = "../bevy_reflect", version = "0.6.0", features = ["bevy"] }
1920
bevy_render = { path = "../bevy_render", version = "0.6.0" }

crates/bevy_gltf/src/loader.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use bevy_asset::{
44
};
55
use bevy_core::Name;
66
use bevy_ecs::world::World;
7+
use bevy_hierarchy::{BuildWorldChildren, WorldChildBuilder};
78
use bevy_log::warn;
89
use bevy_math::{Mat4, Vec3};
910
use bevy_pbr::{
@@ -24,11 +25,8 @@ use bevy_render::{
2425
view::VisibleEntities,
2526
};
2627
use bevy_scene::Scene;
27-
use bevy_transform::{
28-
hierarchy::{BuildWorldChildren, WorldChildBuilder},
29-
prelude::Transform,
30-
TransformBundle,
31-
};
28+
use bevy_transform::{components::Transform, TransformBundle};
29+
3230
use bevy_utils::{HashMap, HashSet};
3331
use gltf::{
3432
mesh::Mode,

crates/bevy_hierarchy/Cargo.toml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[package]
2+
name = "bevy_hierarchy"
3+
version = "0.6.0"
4+
edition = "2021"
5+
description = "Provides hierarchy functionality for Bevy Engine"
6+
homepage = "https://bevyengine.org"
7+
repository = "https://github.com/bevyengine/bevy"
8+
license = "MIT OR Apache-2.0"
9+
keywords = ["bevy"]
10+
11+
[dependencies]
12+
# bevy
13+
bevy_app = { path = "../bevy_app", version = "0.6.0" }
14+
bevy_ecs = { path = "../bevy_ecs", version = "0.6.0", features = ["bevy_reflect"] }
15+
bevy_reflect = { path = "../bevy_reflect", version = "0.6.0", features = ["bevy"] }
16+
bevy_utils = { path = "../bevy_utils", version = "0.6.0" }
17+
18+
# other
19+
smallvec = { version = "1.6", features = ["serde", "union", "const_generics"] }
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
mod children;
2+
mod parent;
3+
4+
pub use children::Children;
5+
pub use parent::{Parent, PreviousParent};

crates/bevy_transform/src/hierarchy/hierarchy.rs renamed to crates/bevy_hierarchy/src/hierarchy.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ mod tests {
116116
};
117117

118118
use super::DespawnRecursiveExt;
119-
use crate::{components::Children, hierarchy::BuildChildren};
119+
use crate::{child_builder::BuildChildren, components::Children};
120120

121121
#[derive(Component, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Debug)]
122122
struct Idx(u32);

crates/bevy_hierarchy/src/lib.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#![warn(missing_docs)]
2+
//! `bevy_hierarchy` can be used to define hierarchies of entities.
3+
//!
4+
//! Most commonly, these hierarchies are used for inheriting `Transform` values
5+
//! from the [`Parent`] to its [`Children`].
6+
7+
mod components;
8+
pub use components::*;
9+
10+
mod hierarchy;
11+
pub use hierarchy::*;
12+
13+
mod child_builder;
14+
pub use child_builder::*;
15+
16+
mod systems;
17+
pub use systems::*;
18+
19+
#[doc(hidden)]
20+
pub mod prelude {
21+
#[doc(hidden)]
22+
pub use crate::{child_builder::*, components::*, hierarchy::*, HierarchyPlugin};
23+
}
24+
25+
use bevy_app::prelude::*;
26+
use bevy_ecs::prelude::*;
27+
28+
/// The base plugin for handling [`Parent`] and [`Children`] components
29+
#[derive(Default)]
30+
pub struct HierarchyPlugin;
31+
32+
/// Label enum for the systems relating to hierarchy upkeep
33+
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemLabel)]
34+
pub enum HierarchySystem {
35+
/// Updates [`Parent`] when changes in the hierarchy occur
36+
ParentUpdate,
37+
}
38+
39+
impl Plugin for HierarchyPlugin {
40+
fn build(&self, app: &mut App) {
41+
app.register_type::<Children>()
42+
.register_type::<Parent>()
43+
.register_type::<PreviousParent>()
44+
.add_startup_system_to_stage(
45+
StartupStage::PostStartup,
46+
parent_update_system.label(HierarchySystem::ParentUpdate),
47+
)
48+
.add_system_to_stage(
49+
CoreStage::PostUpdate,
50+
parent_update_system.label(HierarchySystem::ParentUpdate),
51+
);
52+
}
53+
}

crates/bevy_transform/src/hierarchy/hierarchy_maintenance_system.rs renamed to crates/bevy_hierarchy/src/systems.rs

Lines changed: 0 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -70,101 +70,3 @@ pub fn parent_update_system(
7070
commands.entity(*e).insert(Children::with(v));
7171
});
7272
}
73-
#[cfg(test)]
74-
mod test {
75-
use bevy_ecs::{
76-
schedule::{Schedule, Stage, SystemStage},
77-
system::CommandQueue,
78-
world::World,
79-
};
80-
81-
use super::*;
82-
use crate::{hierarchy::BuildChildren, transform_propagate_system::transform_propagate_system};
83-
84-
#[test]
85-
fn correct_children() {
86-
let mut world = World::default();
87-
88-
let mut update_stage = SystemStage::parallel();
89-
update_stage.add_system(parent_update_system);
90-
update_stage.add_system(transform_propagate_system);
91-
92-
let mut schedule = Schedule::default();
93-
schedule.add_stage("update", update_stage);
94-
95-
// Add parent entities
96-
let mut command_queue = CommandQueue::default();
97-
let mut commands = Commands::new(&mut command_queue, &world);
98-
let mut children = Vec::new();
99-
let parent = commands
100-
.spawn()
101-
.insert(Transform::from_xyz(1.0, 0.0, 0.0))
102-
.id();
103-
commands.entity(parent).with_children(|parent| {
104-
children.push(
105-
parent
106-
.spawn()
107-
.insert(Transform::from_xyz(0.0, 2.0, 0.0))
108-
.id(),
109-
);
110-
children.push(
111-
parent
112-
.spawn()
113-
.insert(Transform::from_xyz(0.0, 3.0, 0.0))
114-
.id(),
115-
);
116-
});
117-
command_queue.apply(&mut world);
118-
schedule.run(&mut world);
119-
120-
assert_eq!(
121-
world
122-
.get::<Children>(parent)
123-
.unwrap()
124-
.0
125-
.iter()
126-
.cloned()
127-
.collect::<Vec<_>>(),
128-
children,
129-
);
130-
131-
// Parent `e1` to `e2`.
132-
(*world.get_mut::<Parent>(children[0]).unwrap()).0 = children[1];
133-
134-
schedule.run(&mut world);
135-
136-
assert_eq!(
137-
world
138-
.get::<Children>(parent)
139-
.unwrap()
140-
.iter()
141-
.cloned()
142-
.collect::<Vec<_>>(),
143-
vec![children[1]]
144-
);
145-
146-
assert_eq!(
147-
world
148-
.get::<Children>(children[1])
149-
.unwrap()
150-
.iter()
151-
.cloned()
152-
.collect::<Vec<_>>(),
153-
vec![children[0]]
154-
);
155-
156-
assert!(world.despawn(children[0]));
157-
158-
schedule.run(&mut world);
159-
160-
assert_eq!(
161-
world
162-
.get::<Children>(parent)
163-
.unwrap()
164-
.iter()
165-
.cloned()
166-
.collect::<Vec<_>>(),
167-
vec![children[1]]
168-
);
169-
}
170-
}

crates/bevy_internal/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ bevy_core = { path = "../bevy_core", version = "0.6.0" }
5656
bevy_derive = { path = "../bevy_derive", version = "0.6.0" }
5757
bevy_diagnostic = { path = "../bevy_diagnostic", version = "0.6.0" }
5858
bevy_ecs = { path = "../bevy_ecs", version = "0.6.0" }
59+
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.6.0" }
5960
bevy_input = { path = "../bevy_input", version = "0.6.0" }
6061
bevy_log = { path = "../bevy_log", version = "0.6.0" }
6162
bevy_math = { path = "../bevy_math", version = "0.6.0" }

crates/bevy_internal/src/default_plugins.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use bevy_app::{PluginGroup, PluginGroupBuilder};
44
/// * [`LogPlugin`](bevy_log::LogPlugin)
55
/// * [`CorePlugin`](bevy_core::CorePlugin)
66
/// * [`TransformPlugin`](bevy_transform::TransformPlugin)
7+
/// * [`HierarchyPlugin`](bevy_hierarchy::HierarchyPlugin)
78
/// * [`DiagnosticsPlugin`](bevy_diagnostic::DiagnosticsPlugin)
89
/// * [`InputPlugin`](bevy_input::InputPlugin)
910
/// * [`WindowPlugin`](bevy_window::WindowPlugin)
@@ -27,6 +28,7 @@ impl PluginGroup for DefaultPlugins {
2728
group.add(bevy_log::LogPlugin::default());
2829
group.add(bevy_core::CorePlugin::default());
2930
group.add(bevy_transform::TransformPlugin::default());
31+
group.add(bevy_hierarchy::HierarchyPlugin::default());
3032
group.add(bevy_diagnostic::DiagnosticsPlugin::default());
3133
group.add(bevy_input::InputPlugin::default());
3234
group.add(bevy_window::WindowPlugin::default());

crates/bevy_internal/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ pub mod tasks {
6565
pub use bevy_tasks::*;
6666
}
6767

68+
pub mod hierarchy {
69+
//! Entity hierarchies and property inheritance
70+
pub use bevy_hierarchy::*;
71+
}
72+
6873
pub mod transform {
6974
//! Local and global transforms (e.g. translation, scale, rotation).
7075
pub use bevy_transform::*;

crates/bevy_internal/src/prelude.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#[doc(hidden)]
22
pub use crate::{
3-
app::prelude::*, asset::prelude::*, core::prelude::*, ecs::prelude::*, input::prelude::*,
4-
log::prelude::*, math::prelude::*, reflect::prelude::*, scene::prelude::*,
3+
app::prelude::*, asset::prelude::*, core::prelude::*, ecs::prelude::*, hierarchy::prelude::*,
4+
input::prelude::*, log::prelude::*, math::prelude::*, reflect::prelude::*, scene::prelude::*,
55
transform::prelude::*, utils::prelude::*, window::prelude::*, DefaultPlugins, MinimalPlugins,
66
};
77

crates/bevy_render/src/view/visibility/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ use bevy_app::{CoreStage, Plugin};
66
use bevy_asset::{Assets, Handle};
77
use bevy_ecs::prelude::*;
88
use bevy_reflect::Reflect;
9-
use bevy_transform::{components::GlobalTransform, TransformSystem};
9+
use bevy_transform::components::GlobalTransform;
10+
use bevy_transform::TransformSystem;
1011

1112
use crate::{
1213
camera::{Camera, CameraProjection, OrthographicProjection, PerspectiveProjection},

crates/bevy_scene/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ bevy_app = { path = "../bevy_app", version = "0.6.0" }
1414
bevy_asset = { path = "../bevy_asset", version = "0.6.0" }
1515
bevy_ecs = { path = "../bevy_ecs", version = "0.6.0" }
1616
bevy_reflect = { path = "../bevy_reflect", version = "0.6.0", features = ["bevy"] }
17-
bevy_transform = { path = "../bevy_transform", version = "0.6.0" }
17+
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.6.0" }
1818
bevy_utils = { path = "../bevy_utils", version = "0.6.0" }
1919

2020
# other

crates/bevy_scene/src/command.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use bevy_ecs::{
44
system::{Command, Commands},
55
world::World,
66
};
7-
use bevy_transform::hierarchy::ChildBuilder;
7+
use bevy_hierarchy::ChildBuilder;
88

99
use crate::{Scene, SceneSpawner};
1010

crates/bevy_scene/src/scene_spawner.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use bevy_ecs::{
77
system::Command,
88
world::{Mut, World},
99
};
10+
use bevy_hierarchy::{AddChild, Parent};
1011
use bevy_reflect::TypeRegistryArc;
11-
use bevy_transform::{hierarchy::AddChild, prelude::Parent};
1212
use bevy_utils::{tracing::error, HashMap};
1313
use thiserror::Error;
1414
use uuid::Uuid;

crates/bevy_transform/.gitignore

Lines changed: 0 additions & 24 deletions
This file was deleted.

crates/bevy_transform/Cargo.toml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "bevy_transform"
33
version = "0.6.0"
44
edition = "2021"
5-
description = "Provides hierarchy and transform functionality for Bevy Engine"
5+
description = "Provides transform functionality for Bevy Engine"
66
homepage = "https://bevyengine.org"
77
repository = "https://github.com/bevyengine/bevy"
88
license = "MIT OR Apache-2.0"
@@ -12,9 +12,6 @@ keywords = ["bevy"]
1212
# bevy
1313
bevy_app = { path = "../bevy_app", version = "0.6.0" }
1414
bevy_ecs = { path = "../bevy_ecs", version = "0.6.0", features = ["bevy_reflect"] }
15+
bevy_hierarchy = { path = "../bevy_hierarchy", version = "0.6.0"}
1516
bevy_math = { path = "../bevy_math", version = "0.6.0" }
1617
bevy_reflect = { path = "../bevy_reflect", version = "0.6.0", features = ["bevy"] }
17-
bevy_utils = { path = "../bevy_utils", version = "0.6.0" }
18-
19-
# other
20-
smallvec = { version = "1.6", features = ["serde", "union", "const_generics"] }

crates/bevy_transform/src/components/global_transform.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ use std::ops::Mul;
1414
/// ## [`Transform`] and [`GlobalTransform`]
1515
///
1616
/// [`Transform`] is the position of an entity relative to its parent position, or the reference
17-
/// frame if it doesn't have a [`Parent`](super::Parent).
17+
/// frame if it doesn't have a [`Parent`](bevy_hierarchy::Parent).
1818
///
1919
/// [`GlobalTransform`] is the position of an entity relative to the reference frame.
2020
///
2121
/// [`GlobalTransform`] is updated from [`Transform`] in the system
22-
/// [`transform_propagate_system`](crate::transform_propagate_system::transform_propagate_system).
22+
/// [`transform_propagate_system`](crate::transform_propagate_system).
2323
///
2424
/// This system runs in stage [`CoreStage::PostUpdate`](crate::CoreStage::PostUpdate). If you
2525
/// update the[`Transform`] of an entity in this stage or after, you will notice a 1 frame lag
Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
mod children;
21
mod global_transform;
3-
mod parent;
42
mod transform;
53

6-
pub use children::Children;
74
pub use global_transform::*;
8-
pub use parent::{Parent, PreviousParent};
95
pub use transform::*;

crates/bevy_transform/src/components/transform.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ use std::ops::Mul;
1515
/// ## [`Transform`] and [`GlobalTransform`]
1616
///
1717
/// [`Transform`] is the position of an entity relative to its parent position, or the reference
18-
/// frame if it doesn't have a [`Parent`](super::Parent).
18+
/// frame if it doesn't have a [`Parent`](bevy_hierarchy::Parent).
1919
///
2020
/// [`GlobalTransform`] is the position of an entity relative to the reference frame.
2121
///
2222
/// [`GlobalTransform`] is updated from [`Transform`] in the system
23-
/// [`transform_propagate_system`](crate::transform_propagate_system::transform_propagate_system).
23+
/// [`transform_propagate_system`](crate::transform_propagate_system).
2424
///
2525
/// This system runs in stage [`CoreStage::PostUpdate`](crate::CoreStage::PostUpdate). If you
2626
/// update the[`Transform`] of an entity in this stage or after, you will notice a 1 frame lag

crates/bevy_transform/src/hierarchy/mod.rs

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)