mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 20:23:28 +00:00
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
This commit is contained in:
parent
6dcff2bfe8
commit
ace4eaaf0e
12 changed files with 82 additions and 106 deletions
|
@ -10,7 +10,7 @@ use bevy_ecs::{
|
|||
schedule::{common_conditions::resource_changed, IntoSystemConfigs},
|
||||
system::{Commands, Query, Res, Resource},
|
||||
};
|
||||
use bevy_hierarchy::BuildChildren;
|
||||
use bevy_hierarchy::{BuildChildren, ChildBuild};
|
||||
use bevy_text::{Font, Text, TextSection, TextStyle};
|
||||
use bevy_ui::{
|
||||
node_bundles::{NodeBundle, TextBundle},
|
||||
|
|
|
@ -13,7 +13,7 @@ use bevy_core::Name;
|
|||
use bevy_core_pipeline::prelude::Camera3dBundle;
|
||||
use bevy_ecs::entity::EntityHashMap;
|
||||
use bevy_ecs::{entity::Entity, world::World};
|
||||
use bevy_hierarchy::{BuildWorldChildren, WorldChildBuilder};
|
||||
use bevy_hierarchy::{BuildChildren, ChildBuild, WorldChildBuilder};
|
||||
use bevy_math::{Affine2, Mat4, Vec3};
|
||||
use bevy_pbr::{
|
||||
DirectionalLight, DirectionalLightBundle, PbrBundle, PointLight, PointLightBundle, SpotLight,
|
||||
|
|
|
@ -261,7 +261,7 @@ impl Command for RemoveParent {
|
|||
/// ```
|
||||
/// # use bevy_ecs::bundle::Bundle;
|
||||
/// # use bevy_ecs::system::Commands;
|
||||
/// # use bevy_hierarchy::BuildChildren;
|
||||
/// # use bevy_hierarchy::{ChildBuild, BuildChildren};
|
||||
/// # #[derive(Bundle)]
|
||||
/// # struct MyBundle {}
|
||||
/// # #[derive(Bundle)]
|
||||
|
@ -279,30 +279,55 @@ pub struct ChildBuilder<'a> {
|
|||
push_children: PushChildren,
|
||||
}
|
||||
|
||||
impl ChildBuilder<'_> {
|
||||
/// Trait for building children entities and adding them to a parent entity. This is used in
|
||||
/// implementations of [`BuildChildren`] as a bound on the [`Builder`](BuildChildren::Builder)
|
||||
/// associated type. The closure passed to [`BuildChildren::with_children`] accepts an
|
||||
/// implementation of `ChildBuild` so that children can be spawned via [`ChildBuild::spawn`].
|
||||
pub trait ChildBuild {
|
||||
/// Spawn output type. Both [`spawn`](Self::spawn) and [`spawn_empty`](Self::spawn_empty) return
|
||||
/// an implementation of this type so that children can be operated on via method-chaining.
|
||||
/// Implementations of `ChildBuild` reborrow `self` when spawning entities (see
|
||||
/// [`Commands::spawn_empty`] and [`World::get_entity_mut`]). Lifetime `'a` corresponds to this
|
||||
/// reborrowed self, and `Self` outlives it.
|
||||
type SpawnOutput<'a>: BuildChildren
|
||||
where
|
||||
Self: 'a;
|
||||
|
||||
/// Spawns an entity with the given bundle and inserts it into the parent entity's [`Children`].
|
||||
/// Also adds [`Parent`] component to the created entity.
|
||||
pub fn spawn(&mut self, bundle: impl Bundle) -> EntityCommands {
|
||||
fn spawn(&mut self, bundle: impl Bundle) -> Self::SpawnOutput<'_>;
|
||||
|
||||
/// Spawns an [`Entity`] with no components and inserts it into the parent entity's [`Children`].
|
||||
/// Also adds [`Parent`] component to the created entity.
|
||||
fn spawn_empty(&mut self) -> Self::SpawnOutput<'_>;
|
||||
|
||||
/// Returns the parent entity.
|
||||
fn parent_entity(&self) -> Entity;
|
||||
|
||||
/// Adds a command to be executed, like [`Commands::add`].
|
||||
fn add_command<C: Command>(&mut self, command: C) -> &mut Self;
|
||||
}
|
||||
|
||||
impl ChildBuild for ChildBuilder<'_> {
|
||||
type SpawnOutput<'a> = EntityCommands<'a> where Self: 'a;
|
||||
|
||||
fn spawn(&mut self, bundle: impl Bundle) -> EntityCommands {
|
||||
let e = self.commands.spawn(bundle);
|
||||
self.push_children.children.push(e.id());
|
||||
e
|
||||
}
|
||||
|
||||
/// Spawns an [`Entity`] with no components and inserts it into the parent entity's [`Children`].
|
||||
/// Also adds [`Parent`] component to the created entity.
|
||||
pub fn spawn_empty(&mut self) -> EntityCommands {
|
||||
fn spawn_empty(&mut self) -> EntityCommands {
|
||||
let e = self.commands.spawn_empty();
|
||||
self.push_children.children.push(e.id());
|
||||
e
|
||||
}
|
||||
|
||||
/// Returns the parent entity of this [`ChildBuilder`].
|
||||
pub fn parent_entity(&self) -> Entity {
|
||||
fn parent_entity(&self) -> Entity {
|
||||
self.push_children.parent
|
||||
}
|
||||
|
||||
/// Adds a command to be executed, like [`Commands::add`].
|
||||
pub fn add_command<C: Command>(&mut self, command: C) -> &mut Self {
|
||||
fn add_command<C: Command>(&mut self, command: C) -> &mut Self {
|
||||
self.commands.add(command);
|
||||
self
|
||||
}
|
||||
|
@ -310,8 +335,12 @@ impl ChildBuilder<'_> {
|
|||
|
||||
/// Trait for removing, adding and replacing children and parents of an entity.
|
||||
pub trait BuildChildren {
|
||||
/// Takes a closure which builds children for this entity using [`ChildBuilder`].
|
||||
fn with_children(&mut self, f: impl FnOnce(&mut ChildBuilder)) -> &mut Self;
|
||||
/// Child builder type.
|
||||
type Builder<'a>: ChildBuild;
|
||||
|
||||
/// Takes a closure which builds children for this entity using [`ChildBuild`].
|
||||
fn with_children(&mut self, f: impl FnOnce(&mut Self::Builder<'_>)) -> &mut Self;
|
||||
|
||||
/// Pushes children to the back of the builder's children. For any entities that are
|
||||
/// already a child of this one, this method does nothing.
|
||||
///
|
||||
|
@ -323,6 +352,7 @@ pub trait BuildChildren {
|
|||
///
|
||||
/// Panics if any of the children are the same as the parent.
|
||||
fn push_children(&mut self, children: &[Entity]) -> &mut Self;
|
||||
|
||||
/// Inserts children at the given index.
|
||||
///
|
||||
/// If the children were previously children of another parent, that parent's [`Children`] component
|
||||
|
@ -333,10 +363,12 @@ pub trait BuildChildren {
|
|||
///
|
||||
/// Panics if any of the children are the same as the parent.
|
||||
fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self;
|
||||
|
||||
/// Removes the given children
|
||||
///
|
||||
/// Removing all children from a parent causes its [`Children`] component to be removed from the entity.
|
||||
fn remove_children(&mut self, children: &[Entity]) -> &mut Self;
|
||||
|
||||
/// Adds a single child.
|
||||
///
|
||||
/// If the children were previously children of another parent, that parent's [`Children`] component
|
||||
|
@ -347,8 +379,10 @@ pub trait BuildChildren {
|
|||
///
|
||||
/// Panics if the child is the same as the parent.
|
||||
fn add_child(&mut self, child: Entity) -> &mut Self;
|
||||
|
||||
/// Removes all children from this entity. The [`Children`] component will be removed if it exists, otherwise this does nothing.
|
||||
fn clear_children(&mut self) -> &mut Self;
|
||||
|
||||
/// Removes all current children from this entity, replacing them with the specified list of entities.
|
||||
///
|
||||
/// The removed children will have their [`Parent`] component removed.
|
||||
|
@ -357,6 +391,7 @@ pub trait BuildChildren {
|
|||
///
|
||||
/// Panics if any of the children are the same as the parent.
|
||||
fn replace_children(&mut self, children: &[Entity]) -> &mut Self;
|
||||
|
||||
/// Sets the parent of this entity.
|
||||
///
|
||||
/// If this entity already had a parent, the parent's [`Children`] component will have this
|
||||
|
@ -367,6 +402,7 @@ pub trait BuildChildren {
|
|||
///
|
||||
/// Panics if the parent is the same as the child.
|
||||
fn set_parent(&mut self, parent: Entity) -> &mut Self;
|
||||
|
||||
/// Removes the [`Parent`] of this entity.
|
||||
///
|
||||
/// Also removes this entity from its parent's [`Children`] component. Removing all children from a parent causes
|
||||
|
@ -375,7 +411,9 @@ pub trait BuildChildren {
|
|||
}
|
||||
|
||||
impl BuildChildren for EntityCommands<'_> {
|
||||
fn with_children(&mut self, spawn_children: impl FnOnce(&mut ChildBuilder)) -> &mut Self {
|
||||
type Builder<'a> = ChildBuilder<'a>;
|
||||
|
||||
fn with_children(&mut self, spawn_children: impl FnOnce(&mut Self::Builder<'_>)) -> &mut Self {
|
||||
let parent = self.id();
|
||||
let mut builder = ChildBuilder {
|
||||
commands: self.commands(),
|
||||
|
@ -478,10 +516,10 @@ pub struct WorldChildBuilder<'w> {
|
|||
parent: Entity,
|
||||
}
|
||||
|
||||
impl<'w> WorldChildBuilder<'w> {
|
||||
/// Spawns an entity with the given bundle and inserts it into the parent entity's [`Children`].
|
||||
/// Also adds [`Parent`] component to the created entity.
|
||||
pub fn spawn(&mut self, bundle: impl Bundle) -> EntityWorldMut<'_> {
|
||||
impl ChildBuild for WorldChildBuilder<'_> {
|
||||
type SpawnOutput<'a> = EntityWorldMut<'a> where Self: 'a;
|
||||
|
||||
fn spawn(&mut self, bundle: impl Bundle) -> EntityWorldMut {
|
||||
let entity = self.world.spawn((bundle, Parent(self.parent))).id();
|
||||
push_child_unchecked(self.world, self.parent, entity);
|
||||
push_events(
|
||||
|
@ -494,9 +532,7 @@ impl<'w> WorldChildBuilder<'w> {
|
|||
self.world.entity_mut(entity)
|
||||
}
|
||||
|
||||
/// Spawns an [`Entity`] with no components and inserts it into the parent entity's [`Children`].
|
||||
/// Also adds [`Parent`] component to the created entity.
|
||||
pub fn spawn_empty(&mut self) -> EntityWorldMut<'_> {
|
||||
fn spawn_empty(&mut self) -> EntityWorldMut {
|
||||
let entity = self.world.spawn(Parent(self.parent)).id();
|
||||
push_child_unchecked(self.world, self.parent, entity);
|
||||
push_events(
|
||||
|
@ -509,83 +545,19 @@ impl<'w> WorldChildBuilder<'w> {
|
|||
self.world.entity_mut(entity)
|
||||
}
|
||||
|
||||
/// Returns the parent entity of this [`WorldChildBuilder`].
|
||||
pub fn parent_entity(&self) -> Entity {
|
||||
fn parent_entity(&self) -> Entity {
|
||||
self.parent
|
||||
}
|
||||
|
||||
fn add_command<C: Command>(&mut self, command: C) -> &mut Self {
|
||||
command.apply(self.world);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait that defines adding, changing and children and parents of an entity directly through the [`World`].
|
||||
pub trait BuildWorldChildren {
|
||||
/// Takes a closure which builds children for this entity using [`WorldChildBuilder`].
|
||||
fn with_children(&mut self, spawn_children: impl FnOnce(&mut WorldChildBuilder)) -> &mut Self;
|
||||
impl BuildChildren for EntityWorldMut<'_> {
|
||||
type Builder<'a> = WorldChildBuilder<'a>;
|
||||
|
||||
/// Adds a single child.
|
||||
///
|
||||
/// If the children were previously children of another parent, that parent's [`Children`] component
|
||||
/// will have those children removed from its list. Removing all children from a parent causes its
|
||||
/// [`Children`] component to be removed from the entity.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the child is the same as the parent.
|
||||
fn add_child(&mut self, child: Entity) -> &mut Self;
|
||||
|
||||
/// Pushes children to the back of the builder's children. For any entities that are
|
||||
/// already a child of this one, this method does nothing.
|
||||
///
|
||||
/// If the children were previously children of another parent, that parent's [`Children`] component
|
||||
/// will have those children removed from its list. Removing all children from a parent causes its
|
||||
/// [`Children`] component to be removed from the entity.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if any of the children are the same as the parent.
|
||||
fn push_children(&mut self, children: &[Entity]) -> &mut Self;
|
||||
/// Inserts children at the given index.
|
||||
///
|
||||
/// If the children were previously children of another parent, that parent's [`Children`] component
|
||||
/// will have those children removed from its list. Removing all children from a parent causes its
|
||||
/// [`Children`] component to be removed from the entity.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if any of the children are the same as the parent.
|
||||
fn insert_children(&mut self, index: usize, children: &[Entity]) -> &mut Self;
|
||||
/// Removes the given children
|
||||
///
|
||||
/// Removing all children from a parent causes its [`Children`] component to be removed from the entity.
|
||||
fn remove_children(&mut self, children: &[Entity]) -> &mut Self;
|
||||
|
||||
/// Sets the parent of this entity.
|
||||
///
|
||||
/// If this entity already had a parent, the parent's [`Children`] component will have this
|
||||
/// child removed from its list. Removing all children from a parent causes its [`Children`]
|
||||
/// component to be removed from the entity.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the parent is the same as the child.
|
||||
fn set_parent(&mut self, parent: Entity) -> &mut Self;
|
||||
|
||||
/// Removes the [`Parent`] of this entity.
|
||||
///
|
||||
/// Also removes this entity from its parent's [`Children`] component. Removing all children from a parent causes
|
||||
/// its [`Children`] component to be removed from the entity.
|
||||
fn remove_parent(&mut self) -> &mut Self;
|
||||
/// Removes all children from this entity. The [`Children`] component will be removed if it exists, otherwise this does nothing.
|
||||
fn clear_children(&mut self) -> &mut Self;
|
||||
/// Removes all current children from this entity, replacing them with the specified list of entities.
|
||||
///
|
||||
/// The removed children will have their [`Parent`] component removed.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if any of the children are the same as the parent.
|
||||
fn replace_children(&mut self, children: &[Entity]) -> &mut Self;
|
||||
}
|
||||
|
||||
impl<'w> BuildWorldChildren for EntityWorldMut<'w> {
|
||||
fn with_children(&mut self, spawn_children: impl FnOnce(&mut WorldChildBuilder)) -> &mut Self {
|
||||
let parent = self.id();
|
||||
self.world_scope(|world| {
|
||||
|
@ -691,7 +663,7 @@ impl<'w> BuildWorldChildren for EntityWorldMut<'w> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{BuildChildren, BuildWorldChildren};
|
||||
use super::{BuildChildren, ChildBuild};
|
||||
use crate::{
|
||||
components::{Children, Parent},
|
||||
HierarchyEvent::{self, ChildAdded, ChildMoved, ChildRemoved},
|
||||
|
|
|
@ -146,7 +146,10 @@ mod tests {
|
|||
};
|
||||
|
||||
use super::DespawnRecursiveExt;
|
||||
use crate::{child_builder::BuildChildren, components::Children};
|
||||
use crate::{
|
||||
child_builder::{BuildChildren, ChildBuild},
|
||||
components::Children,
|
||||
};
|
||||
|
||||
#[derive(Component, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Debug)]
|
||||
struct Idx(u32);
|
||||
|
|
5
crates/bevy_hierarchy/src/lib.rs
Normal file → Executable file
5
crates/bevy_hierarchy/src/lib.rs
Normal file → Executable file
|
@ -16,7 +16,7 @@
|
|||
//! for managing parent-child relationships between entities.
|
||||
//! It provides two components, [`Parent`] and [`Children`],
|
||||
//! to store references to related entities.
|
||||
//! It also provides [command] and [world] API extensions
|
||||
//! It also provides [command and world] API extensions
|
||||
//! to set and clear those relationships.
|
||||
//!
|
||||
//! More advanced users may also appreciate
|
||||
|
@ -44,13 +44,12 @@
|
|||
//! In most cases, these operations will invalidate the hierarchy.
|
||||
//! Instead, you should use the provided [hierarchical despawn extension methods].
|
||||
//!
|
||||
//! [command]: BuildChildren
|
||||
//! [command and world]: BuildChildren
|
||||
//! [diagnostic plugin]: ValidParentCheckPlugin
|
||||
//! [events]: HierarchyEvent
|
||||
//! [hierarchical despawn extension methods]: DespawnRecursiveExt
|
||||
//! [plugin]: HierarchyPlugin
|
||||
//! [query extension methods]: HierarchyQueryExt
|
||||
//! [world]: BuildWorldChildren
|
||||
|
||||
mod components;
|
||||
pub use components::*;
|
||||
|
|
|
@ -161,7 +161,7 @@ mod tests {
|
|||
world::World,
|
||||
};
|
||||
|
||||
use crate::{query_extension::HierarchyQueryExt, BuildWorldChildren, Children, Parent};
|
||||
use crate::{query_extension::HierarchyQueryExt, BuildChildren, Children, Parent};
|
||||
|
||||
#[derive(Component, PartialEq, Debug)]
|
||||
struct A(usize);
|
||||
|
|
|
@ -501,7 +501,7 @@ mod test {
|
|||
|
||||
use super::*;
|
||||
|
||||
use bevy_hierarchy::BuildWorldChildren;
|
||||
use bevy_hierarchy::BuildChildren;
|
||||
|
||||
fn visibility_bundle(visibility: Visibility) -> VisibilityBundle {
|
||||
VisibilityBundle {
|
||||
|
|
|
@ -8,7 +8,7 @@ use bevy_ecs::{
|
|||
system::Resource,
|
||||
world::{Command, Mut, World},
|
||||
};
|
||||
use bevy_hierarchy::{BuildWorldChildren, DespawnRecursiveExt, Parent, PushChild};
|
||||
use bevy_hierarchy::{BuildChildren, DespawnRecursiveExt, Parent, PushChild};
|
||||
use bevy_utils::{tracing::error, HashMap, HashSet};
|
||||
use thiserror::Error;
|
||||
use uuid::Uuid;
|
||||
|
|
|
@ -84,7 +84,7 @@ mod tests {
|
|||
|
||||
use bevy_app::App;
|
||||
use bevy_ecs::system::SystemState;
|
||||
use bevy_hierarchy::BuildWorldChildren;
|
||||
use bevy_hierarchy::BuildChildren;
|
||||
use bevy_math::{Quat, Vec3};
|
||||
|
||||
use crate::{
|
||||
|
|
|
@ -190,7 +190,7 @@ mod test {
|
|||
|
||||
use crate::bundles::TransformBundle;
|
||||
use crate::systems::*;
|
||||
use bevy_hierarchy::{BuildChildren, BuildWorldChildren};
|
||||
use bevy_hierarchy::{BuildChildren, ChildBuild};
|
||||
|
||||
#[test]
|
||||
fn correct_parent_removed() {
|
||||
|
|
|
@ -357,7 +357,9 @@ mod tests {
|
|||
use bevy_ecs::schedule::Schedule;
|
||||
use bevy_ecs::system::RunSystemOnce;
|
||||
use bevy_ecs::world::World;
|
||||
use bevy_hierarchy::{despawn_with_children_recursive, BuildWorldChildren, Children, Parent};
|
||||
use bevy_hierarchy::{
|
||||
despawn_with_children_recursive, BuildChildren, ChildBuild, Children, Parent,
|
||||
};
|
||||
use bevy_math::{vec2, Rect, UVec2, Vec2};
|
||||
use bevy_render::camera::ManualTextureViews;
|
||||
use bevy_render::camera::OrthographicProjection;
|
||||
|
|
|
@ -158,7 +158,7 @@ mod tests {
|
|||
system::Commands,
|
||||
world::{CommandQueue, World},
|
||||
};
|
||||
use bevy_hierarchy::BuildChildren;
|
||||
use bevy_hierarchy::{BuildChildren, ChildBuild};
|
||||
|
||||
use crate::{Node, UiStack, ZIndex};
|
||||
|
||||
|
|
Loading…
Reference in a new issue