mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 23:24:44 +00:00
Support returning data out of with_children (#4708)
# Objective Support returning data out of with_children to enable the use case of changing the parent commands with data created inside the child builder. ## Solution Change the with_children closure to return T. Closes https://github.com/bevyengine/bevy/pull/2817. --- ## Changelog `BuildChildren::add_children` was added with the ability to return data to use outside the closure (for spawning a new child builder on a returned entity for example).
This commit is contained in:
parent
7da21b12f7
commit
a0a14aa615
1 changed files with 65 additions and 22 deletions
|
@ -1,11 +1,13 @@
|
||||||
use crate::prelude::{Children, Parent, PreviousParent};
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
bundle::Bundle,
|
bundle::Bundle,
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
system::{Command, Commands, EntityCommands},
|
system::{Command, Commands, EntityCommands},
|
||||||
world::{EntityMut, World},
|
world::{EntityMut, World},
|
||||||
};
|
};
|
||||||
use smallvec::SmallVec;
|
|
||||||
|
use crate::prelude::{Children, Parent, PreviousParent};
|
||||||
|
|
||||||
/// Command that adds a child to an entity
|
/// Command that adds a child to an entity
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -165,7 +167,40 @@ impl<'w, 's, 'a> ChildBuilder<'w, 's, 'a> {
|
||||||
/// Trait defining how to build children
|
/// Trait defining how to build children
|
||||||
pub trait BuildChildren {
|
pub trait BuildChildren {
|
||||||
/// Creates a [`ChildBuilder`] with the given children built in the given closure
|
/// Creates a [`ChildBuilder`] with the given children built in the given closure
|
||||||
|
///
|
||||||
|
/// Compared to [`add_children`][BuildChildren::add_children], this method returns self
|
||||||
|
/// to allow chaining.
|
||||||
fn with_children(&mut self, f: impl FnOnce(&mut ChildBuilder)) -> &mut Self;
|
fn with_children(&mut self, f: impl FnOnce(&mut ChildBuilder)) -> &mut Self;
|
||||||
|
/// Creates a [`ChildBuilder`] with the given children built in the given closure
|
||||||
|
///
|
||||||
|
/// Compared to [`with_children`][BuildChildren::with_children], this method returns the
|
||||||
|
/// the value returned from the closure, but doesn't allow chaining.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// # use bevy_ecs::prelude::*;
|
||||||
|
/// # use bevy_hierarchy::*;
|
||||||
|
/// #
|
||||||
|
/// # #[derive(Component)]
|
||||||
|
/// # struct SomethingElse;
|
||||||
|
/// #
|
||||||
|
/// # #[derive(Component)]
|
||||||
|
/// # struct MoreStuff;
|
||||||
|
/// #
|
||||||
|
/// # fn foo(mut commands: Commands) {
|
||||||
|
/// let mut parent_commands = commands.spawn();
|
||||||
|
/// let child_id = parent_commands.add_children(|parent| {
|
||||||
|
/// parent.spawn().id()
|
||||||
|
/// });
|
||||||
|
///
|
||||||
|
/// parent_commands.insert(SomethingElse);
|
||||||
|
/// commands.entity(child_id).with_children(|parent| {
|
||||||
|
/// parent.spawn().insert(MoreStuff);
|
||||||
|
/// });
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
fn add_children<T>(&mut self, f: impl FnOnce(&mut ChildBuilder) -> T) -> T;
|
||||||
/// Pushes children to the back of the builder's children
|
/// Pushes children to the back of the builder's children
|
||||||
fn push_children(&mut self, children: &[Entity]) -> &mut Self;
|
fn push_children(&mut self, children: &[Entity]) -> &mut Self;
|
||||||
/// Inserts children at the given index
|
/// Inserts children at the given index
|
||||||
|
@ -178,8 +213,12 @@ pub trait BuildChildren {
|
||||||
|
|
||||||
impl<'w, 's, 'a> BuildChildren for EntityCommands<'w, 's, 'a> {
|
impl<'w, 's, 'a> BuildChildren for EntityCommands<'w, 's, 'a> {
|
||||||
fn with_children(&mut self, spawn_children: impl FnOnce(&mut ChildBuilder)) -> &mut Self {
|
fn with_children(&mut self, spawn_children: impl FnOnce(&mut ChildBuilder)) -> &mut Self {
|
||||||
|
self.add_children(spawn_children);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_children<T>(&mut self, spawn_children: impl FnOnce(&mut ChildBuilder) -> T) -> T {
|
||||||
let parent = self.id();
|
let parent = self.id();
|
||||||
let push_children = {
|
|
||||||
let mut builder = ChildBuilder {
|
let mut builder = ChildBuilder {
|
||||||
commands: self.commands(),
|
commands: self.commands(),
|
||||||
push_children: PushChildren {
|
push_children: PushChildren {
|
||||||
|
@ -187,12 +226,12 @@ impl<'w, 's, 'a> BuildChildren for EntityCommands<'w, 's, 'a> {
|
||||||
parent,
|
parent,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
spawn_children(&mut builder);
|
|
||||||
builder.push_children
|
|
||||||
};
|
|
||||||
|
|
||||||
self.commands().add(push_children);
|
let result = spawn_children(&mut builder);
|
||||||
self
|
let children = builder.push_children;
|
||||||
|
self.commands().add(children);
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_children(&mut self, children: &[Entity]) -> &mut Self {
|
fn push_children(&mut self, children: &[Entity]) -> &mut Self {
|
||||||
|
@ -460,15 +499,18 @@ impl<'w> BuildWorldChildren for WorldChildBuilder<'w> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{BuildChildren, BuildWorldChildren};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use crate::prelude::{Children, Parent, PreviousParent};
|
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
component::Component,
|
component::Component,
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
system::{CommandQueue, Commands},
|
system::{CommandQueue, Commands},
|
||||||
world::World,
|
world::World,
|
||||||
};
|
};
|
||||||
use smallvec::{smallvec, SmallVec};
|
|
||||||
|
use crate::prelude::{Children, Parent, PreviousParent};
|
||||||
|
|
||||||
|
use super::{BuildChildren, BuildWorldChildren};
|
||||||
|
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
struct C(u32);
|
struct C(u32);
|
||||||
|
@ -479,12 +521,13 @@ mod tests {
|
||||||
let mut queue = CommandQueue::default();
|
let mut queue = CommandQueue::default();
|
||||||
let mut commands = Commands::new(&mut queue, &world);
|
let mut commands = Commands::new(&mut queue, &world);
|
||||||
|
|
||||||
let mut children = Vec::new();
|
|
||||||
let parent = commands.spawn().insert(C(1)).id();
|
let parent = commands.spawn().insert(C(1)).id();
|
||||||
commands.entity(parent).with_children(|parent| {
|
let children = commands.entity(parent).add_children(|parent| {
|
||||||
children.push(parent.spawn().insert(C(2)).id());
|
[
|
||||||
children.push(parent.spawn().insert(C(3)).id());
|
parent.spawn().insert(C(2)).id(),
|
||||||
children.push(parent.spawn().insert(C(4)).id());
|
parent.spawn().insert(C(3)).id(),
|
||||||
|
parent.spawn().insert(C(4)).id(),
|
||||||
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
queue.apply(&mut world);
|
queue.apply(&mut world);
|
||||||
|
|
Loading…
Reference in a new issue