Skip to content

Commit ace4eaa

Browse files
authored
Merge BuildWorldChildren and BuildChildren traits. (#14052)
# Objective The `BuildChildren` and `BuildWorldChildren` traits are mostly identical, so I decided to try and merge them. I'm not sure of the history, maybe they were added before GATs existed. ## Solution - Add an associated type to `BuildChildren` which reflects the prior differences between the `BuildChildren` and `BuildWorldChildren` traits. - Add `ChildBuild` trait that is the bounds for `BuildChildren::Builder`, with impls for `ChildBuilder` and `WorldChildBuilder`. - Remove `BuildWorldChildren` trait and replace it with an impl of `BuildChildren` for `EntityWorldMut`. ## Testing I ran several of the examples that use entity hierarchies, mainly UI. --- ## Changelog n/a ## Migration Guide n/a
1 parent 6dcff2b commit ace4eaa

File tree

12 files changed

+82
-106
lines changed

12 files changed

+82
-106
lines changed

crates/bevy_dev_tools/src/fps_overlay.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use bevy_ecs::{
1010
schedule::{common_conditions::resource_changed, IntoSystemConfigs},
1111
system::{Commands, Query, Res, Resource},
1212
};
13-
use bevy_hierarchy::BuildChildren;
13+
use bevy_hierarchy::{BuildChildren, ChildBuild};
1414
use bevy_text::{Font, Text, TextSection, TextStyle};
1515
use bevy_ui::{
1616
node_bundles::{NodeBundle, TextBundle},

crates/bevy_gltf/src/loader.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use bevy_core::Name;
1313
use bevy_core_pipeline::prelude::Camera3dBundle;
1414
use bevy_ecs::entity::EntityHashMap;
1515
use bevy_ecs::{entity::Entity, world::World};
16-
use bevy_hierarchy::{BuildWorldChildren, WorldChildBuilder};
16+
use bevy_hierarchy::{BuildChildren, ChildBuild, WorldChildBuilder};
1717
use bevy_math::{Affine2, Mat4, Vec3};
1818
use bevy_pbr::{
1919
DirectionalLight, DirectionalLightBundle, PbrBundle, PointLight, PointLightBundle, SpotLight,

crates/bevy_hierarchy/src/child_builder.rs

Lines changed: 65 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ impl Command for RemoveParent {
261261
/// ```
262262
/// # use bevy_ecs::bundle::Bundle;
263263
/// # use bevy_ecs::system::Commands;
264-
/// # use bevy_hierarchy::BuildChildren;
264+
/// # use bevy_hierarchy::{ChildBuild, BuildChildren};
265265
/// # #[derive(Bundle)]
266266
/// # struct MyBundle {}
267267
/// # #[derive(Bundle)]
@@ -279,39 +279,68 @@ pub struct ChildBuilder<'a> {
279279
push_children: PushChildren,
280280
}
281281

282-
impl ChildBuilder<'_> {
282+
/// Trait for building children entities and adding them to a parent entity. This is used in
283+
/// implementations of [`BuildChildren`] as a bound on the [`Builder`](BuildChildren::Builder)
284+
/// associated type. The closure passed to [`BuildChildren::with_children`] accepts an
285+
/// implementation of `ChildBuild` so that children can be spawned via [`ChildBuild::spawn`].
286+
pub trait ChildBuild {
287+
/// Spawn output type. Both [`spawn`](Self::spawn) and [`spawn_empty`](Self::spawn_empty) return
288+
/// an implementation of this type so that children can be operated on via method-chaining.
289+
/// Implementations of `ChildBuild` reborrow `self` when spawning entities (see
290+
/// [`Commands::spawn_empty`] and [`World::get_entity_mut`]). Lifetime `'a` corresponds to this
291+
/// reborrowed self, and `Self` outlives it.
292+
type SpawnOutput<'a>: BuildChildren
293+
where
294+
Self: 'a;
295+
283296
/// Spawns an entity with the given bundle and inserts it into the parent entity's [`Children`].
284297
/// Also adds [`Parent`] component to the created entity.
285-
pub fn spawn(&mut self, bundle: impl Bundle) -> EntityCommands {
298+
fn spawn(&mut self, bundle: impl Bundle) -> Self::SpawnOutput<'_>;
299+
300+
/// Spawns an [`Entity`] with no components and inserts it into the parent entity's [`Children`].
301+
/// Also adds [`Parent`] component to the created entity.
302+
fn spawn_empty(&mut self) -> Self::SpawnOutput<'_>;
303+
304+
/// Returns the parent entity.
305+
fn parent_entity(&self) -> Entity;
306+
307+
/// Adds a command to be executed, like [`Commands::add`].
308+
fn add_command<C: Command>(&mut self, command: C) -> &mut Self;
309+
}
310+
311+
impl ChildBuild for ChildBuilder<'_> {
312+
type SpawnOutput<'a> = EntityCommands<'a> where Self: 'a;
313+
314+
fn spawn(&mut self, bundle: impl Bundle) -> EntityCommands {
286315
let e = self.commands.spawn(bundle);
287316
self.push_children.children.push(e.id());
288317
e
289318
}
290319

291-
/// Spawns an [`Entity`] with no components and inserts it into the parent entity's [`Children`].
292-
/// Also adds [`Parent`] component to the created entity.
293-
pub fn spawn_empty(&mut self) -> EntityCommands {
320+
fn spawn_empty(&mut self) -> EntityCommands {
294321
let e = self.commands.spawn_empty();
295322
self.push_children.children.push(e.id());
296323
e
297324
}
298325

299-
/// Returns the parent entity of this [`ChildBuilder`].
300-
pub fn parent_entity(&self) -> Entity {
326+
fn parent_entity(&self) -> Entity {
301327
self.push_children.parent
302328
}
303329

304-
/// Adds a command to be executed, like [`Commands::add`].
305-
pub fn add_command<C: Command>(&mut self, command: C) -> &mut Self {
330+
fn add_command<C: Command>(&mut self, command: C) -> &mut Self {
306331
self.commands.add(command);
307332
self
308333
}
309334
}
310335

311336
/// Trait for removing, adding and replacing children and parents of an entity.
312337
pub trait BuildChildren {
313-
/// Takes a closure which builds children for this entity using [`ChildBuilder`].
314-
fn with_children(&mut self, f: impl FnOnce(&mut ChildBuilder)) -> &mut Self;
338+
/// Child builder type.
339+
type Builder<'a>: ChildBuild;
340+
341+
/// Takes a closure which builds children for this entity using [`ChildBuild`].
342+
fn with_children(&mut self, f: impl FnOnce(&mut Self::Builder<'_>)) -> &mut Self;
343+
315344
/// Pushes children to the back of the builder's children. For any entities that are
316345
/// already a child of this one, this method does nothing.
317346
///
@@ -323,6 +352,7 @@ pub trait BuildChildren {
323352
///
324353
/// Panics if any of the children are the same as the parent.
325354
fn push_children(&mut self, children: &[Entity]) -> &mut Self;
355+
326356
/// Inserts children at the given index.
327357
///
328358
/// If the children were previously children of another parent, that parent's [`Children`] component
@@ -333,10 +363,12 @@ pub trait BuildChildren {
333363
///
334364
/// Panics if any of the children are the same as the parent.
335365
fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self;
366+
336367
/// Removes the given children
337368
///
338369
/// Removing all children from a parent causes its [`Children`] component to be removed from the entity.
339370
fn remove_children(&mut self, children: &[Entity]) -> &mut Self;
371+
340372
/// Adds a single child.
341373
///
342374
/// If the children were previously children of another parent, that parent's [`Children`] component
@@ -347,8 +379,10 @@ pub trait BuildChildren {
347379
///
348380
/// Panics if the child is the same as the parent.
349381
fn add_child(&mut self, child: Entity) -> &mut Self;
382+
350383
/// Removes all children from this entity. The [`Children`] component will be removed if it exists, otherwise this does nothing.
351384
fn clear_children(&mut self) -> &mut Self;
385+
352386
/// Removes all current children from this entity, replacing them with the specified list of entities.
353387
///
354388
/// The removed children will have their [`Parent`] component removed.
@@ -357,6 +391,7 @@ pub trait BuildChildren {
357391
///
358392
/// Panics if any of the children are the same as the parent.
359393
fn replace_children(&mut self, children: &[Entity]) -> &mut Self;
394+
360395
/// Sets the parent of this entity.
361396
///
362397
/// If this entity already had a parent, the parent's [`Children`] component will have this
@@ -367,6 +402,7 @@ pub trait BuildChildren {
367402
///
368403
/// Panics if the parent is the same as the child.
369404
fn set_parent(&mut self, parent: Entity) -> &mut Self;
405+
370406
/// Removes the [`Parent`] of this entity.
371407
///
372408
/// Also removes this entity from its parent's [`Children`] component. Removing all children from a parent causes
@@ -375,7 +411,9 @@ pub trait BuildChildren {
375411
}
376412

377413
impl BuildChildren for EntityCommands<'_> {
378-
fn with_children(&mut self, spawn_children: impl FnOnce(&mut ChildBuilder)) -> &mut Self {
414+
type Builder<'a> = ChildBuilder<'a>;
415+
416+
fn with_children(&mut self, spawn_children: impl FnOnce(&mut Self::Builder<'_>)) -> &mut Self {
379417
let parent = self.id();
380418
let mut builder = ChildBuilder {
381419
commands: self.commands(),
@@ -478,10 +516,10 @@ pub struct WorldChildBuilder<'w> {
478516
parent: Entity,
479517
}
480518

481-
impl<'w> WorldChildBuilder<'w> {
482-
/// Spawns an entity with the given bundle and inserts it into the parent entity's [`Children`].
483-
/// Also adds [`Parent`] component to the created entity.
484-
pub fn spawn(&mut self, bundle: impl Bundle) -> EntityWorldMut<'_> {
519+
impl ChildBuild for WorldChildBuilder<'_> {
520+
type SpawnOutput<'a> = EntityWorldMut<'a> where Self: 'a;
521+
522+
fn spawn(&mut self, bundle: impl Bundle) -> EntityWorldMut {
485523
let entity = self.world.spawn((bundle, Parent(self.parent))).id();
486524
push_child_unchecked(self.world, self.parent, entity);
487525
push_events(
@@ -494,9 +532,7 @@ impl<'w> WorldChildBuilder<'w> {
494532
self.world.entity_mut(entity)
495533
}
496534

497-
/// Spawns an [`Entity`] with no components and inserts it into the parent entity's [`Children`].
498-
/// Also adds [`Parent`] component to the created entity.
499-
pub fn spawn_empty(&mut self) -> EntityWorldMut<'_> {
535+
fn spawn_empty(&mut self) -> EntityWorldMut {
500536
let entity = self.world.spawn(Parent(self.parent)).id();
501537
push_child_unchecked(self.world, self.parent, entity);
502538
push_events(
@@ -509,83 +545,19 @@ impl<'w> WorldChildBuilder<'w> {
509545
self.world.entity_mut(entity)
510546
}
511547

512-
/// Returns the parent entity of this [`WorldChildBuilder`].
513-
pub fn parent_entity(&self) -> Entity {
548+
fn parent_entity(&self) -> Entity {
514549
self.parent
515550
}
516-
}
517-
518-
/// Trait that defines adding, changing and children and parents of an entity directly through the [`World`].
519-
pub trait BuildWorldChildren {
520-
/// Takes a closure which builds children for this entity using [`WorldChildBuilder`].
521-
fn with_children(&mut self, spawn_children: impl FnOnce(&mut WorldChildBuilder)) -> &mut Self;
522-
523-
/// Adds a single child.
524-
///
525-
/// If the children were previously children of another parent, that parent's [`Children`] component
526-
/// will have those children removed from its list. Removing all children from a parent causes its
527-
/// [`Children`] component to be removed from the entity.
528-
///
529-
/// # Panics
530-
///
531-
/// Panics if the child is the same as the parent.
532-
fn add_child(&mut self, child: Entity) -> &mut Self;
533-
534-
/// Pushes children to the back of the builder's children. For any entities that are
535-
/// already a child of this one, this method does nothing.
536-
///
537-
/// If the children were previously children of another parent, that parent's [`Children`] component
538-
/// will have those children removed from its list. Removing all children from a parent causes its
539-
/// [`Children`] component to be removed from the entity.
540-
///
541-
/// # Panics
542-
///
543-
/// Panics if any of the children are the same as the parent.
544-
fn push_children(&mut self, children: &[Entity]) -> &mut Self;
545-
/// Inserts children at the given index.
546-
///
547-
/// If the children were previously children of another parent, that parent's [`Children`] component
548-
/// will have those children removed from its list. Removing all children from a parent causes its
549-
/// [`Children`] component to be removed from the entity.
550-
///
551-
/// # Panics
552-
///
553-
/// Panics if any of the children are the same as the parent.
554-
fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self;
555-
/// Removes the given children
556-
///
557-
/// Removing all children from a parent causes its [`Children`] component to be removed from the entity.
558-
fn remove_children(&mut self, children: &[Entity]) -> &mut Self;
559-
560-
/// Sets the parent of this entity.
561-
///
562-
/// If this entity already had a parent, the parent's [`Children`] component will have this
563-
/// child removed from its list. Removing all children from a parent causes its [`Children`]
564-
/// component to be removed from the entity.
565-
///
566-
/// # Panics
567-
///
568-
/// Panics if the parent is the same as the child.
569-
fn set_parent(&mut self, parent: Entity) -> &mut Self;
570551

571-
/// Removes the [`Parent`] of this entity.
572-
///
573-
/// Also removes this entity from its parent's [`Children`] component. Removing all children from a parent causes
574-
/// its [`Children`] component to be removed from the entity.
575-
fn remove_parent(&mut self) -> &mut Self;
576-
/// Removes all children from this entity. The [`Children`] component will be removed if it exists, otherwise this does nothing.
577-
fn clear_children(&mut self) -> &mut Self;
578-
/// Removes all current children from this entity, replacing them with the specified list of entities.
579-
///
580-
/// The removed children will have their [`Parent`] component removed.
581-
///
582-
/// # Panics
583-
///
584-
/// Panics if any of the children are the same as the parent.
585-
fn replace_children(&mut self, children: &[Entity]) -> &mut Self;
552+
fn add_command<C: Command>(&mut self, command: C) -> &mut Self {
553+
command.apply(self.world);
554+
self
555+
}
586556
}
587557

588-
impl<'w> BuildWorldChildren for EntityWorldMut<'w> {
558+
impl BuildChildren for EntityWorldMut<'_> {
559+
type Builder<'a> = WorldChildBuilder<'a>;
560+
589561
fn with_children(&mut self, spawn_children: impl FnOnce(&mut WorldChildBuilder)) -> &mut Self {
590562
let parent = self.id();
591563
self.world_scope(|world| {
@@ -691,7 +663,7 @@ impl<'w> BuildWorldChildren for EntityWorldMut<'w> {
691663

692664
#[cfg(test)]
693665
mod tests {
694-
use super::{BuildChildren, BuildWorldChildren};
666+
use super::{BuildChildren, ChildBuild};
695667
use crate::{
696668
components::{Children, Parent},
697669
HierarchyEvent::{self, ChildAdded, ChildMoved, ChildRemoved},

crates/bevy_hierarchy/src/hierarchy.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,10 @@ mod tests {
146146
};
147147

148148
use super::DespawnRecursiveExt;
149-
use crate::{child_builder::BuildChildren, components::Children};
149+
use crate::{
150+
child_builder::{BuildChildren, ChildBuild},
151+
components::Children,
152+
};
150153

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

crates/bevy_hierarchy/src/lib.rs

100644100755
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
//! for managing parent-child relationships between entities.
1717
//! It provides two components, [`Parent`] and [`Children`],
1818
//! to store references to related entities.
19-
//! It also provides [command] and [world] API extensions
19+
//! It also provides [command and world] API extensions
2020
//! to set and clear those relationships.
2121
//!
2222
//! More advanced users may also appreciate
@@ -44,13 +44,12 @@
4444
//! In most cases, these operations will invalidate the hierarchy.
4545
//! Instead, you should use the provided [hierarchical despawn extension methods].
4646
//!
47-
//! [command]: BuildChildren
47+
//! [command and world]: BuildChildren
4848
//! [diagnostic plugin]: ValidParentCheckPlugin
4949
//! [events]: HierarchyEvent
5050
//! [hierarchical despawn extension methods]: DespawnRecursiveExt
5151
//! [plugin]: HierarchyPlugin
5252
//! [query extension methods]: HierarchyQueryExt
53-
//! [world]: BuildWorldChildren
5453
5554
mod components;
5655
pub use components::*;

crates/bevy_hierarchy/src/query_extension.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ mod tests {
161161
world::World,
162162
};
163163

164-
use crate::{query_extension::HierarchyQueryExt, BuildWorldChildren, Children, Parent};
164+
use crate::{query_extension::HierarchyQueryExt, BuildChildren, Children, Parent};
165165

166166
#[derive(Component, PartialEq, Debug)]
167167
struct A(usize);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ mod test {
501501

502502
use super::*;
503503

504-
use bevy_hierarchy::BuildWorldChildren;
504+
use bevy_hierarchy::BuildChildren;
505505

506506
fn visibility_bundle(visibility: Visibility) -> VisibilityBundle {
507507
VisibilityBundle {

crates/bevy_scene/src/scene_spawner.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use bevy_ecs::{
88
system::Resource,
99
world::{Command, Mut, World},
1010
};
11-
use bevy_hierarchy::{BuildWorldChildren, DespawnRecursiveExt, Parent, PushChild};
11+
use bevy_hierarchy::{BuildChildren, DespawnRecursiveExt, Parent, PushChild};
1212
use bevy_utils::{tracing::error, HashMap, HashSet};
1313
use thiserror::Error;
1414
use uuid::Uuid;

crates/bevy_transform/src/helper.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ mod tests {
8484

8585
use bevy_app::App;
8686
use bevy_ecs::system::SystemState;
87-
use bevy_hierarchy::BuildWorldChildren;
87+
use bevy_hierarchy::BuildChildren;
8888
use bevy_math::{Quat, Vec3};
8989

9090
use crate::{

crates/bevy_transform/src/systems.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ mod test {
190190

191191
use crate::bundles::TransformBundle;
192192
use crate::systems::*;
193-
use bevy_hierarchy::{BuildChildren, BuildWorldChildren};
193+
use bevy_hierarchy::{BuildChildren, ChildBuild};
194194

195195
#[test]
196196
fn correct_parent_removed() {

0 commit comments

Comments
 (0)