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-
}

0 commit comments

Comments
 (0)