mirror of
https://github.com/bevyengine/bevy
synced 2024-12-18 09:03:07 +00:00
Move clone_entity
commands to EntityCommands
(#16672)
## Objective I was resolving a conflict between #16132 and my PR #15929 and thought the `clone_entity` commands made more sense in `EntityCommands`. ## Solution Moved `Commands::clone_entity` to `EntityCommands::clone`, moved `Commands::clone_entity_with` to `EntityCommands::clone_with`. ## Testing Ran the two tests that used the old methods. ## Showcase ``` // Create a new entity and keep its EntityCommands. let mut entity = commands.spawn((ComponentA(10), ComponentB(20))); // Create a clone of the first entity let mut entity_clone = entity.clone(); ``` The only potential downside is that the method name is now the same as the one from the `Clone` trait. `EntityCommands` doesn't implement `Clone` though, so there's no actual conflict. Maybe I'm biased because this'll work better with my PR, but I think the UX is nicer regardless.
This commit is contained in:
parent
10e3cc72ad
commit
d0afdc6b45
2 changed files with 82 additions and 65 deletions
|
@ -272,69 +272,6 @@ impl<'w, 's> Commands<'w, 's> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clones an entity and allows configuring cloning behavior using [`EntityCloneBuilder`], returning [`EntityCommands`] of the cloned entity.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use bevy_ecs::prelude::*;
|
|
||||||
///
|
|
||||||
/// #[derive(Component, Clone)]
|
|
||||||
/// struct ComponentA(u32);
|
|
||||||
/// #[derive(Component, Clone)]
|
|
||||||
/// struct ComponentB(u32);
|
|
||||||
///
|
|
||||||
/// fn example_system(mut commands: Commands) {
|
|
||||||
/// // Create a new entity and retrieve its id.
|
|
||||||
/// let entity = commands.spawn((ComponentA(10), ComponentB(20))).id();
|
|
||||||
///
|
|
||||||
/// // Create a clone of the first entity, but without ComponentB
|
|
||||||
/// let entity_clone = commands.clone_entity_with(entity, |builder| {
|
|
||||||
/// builder.deny::<ComponentB>();
|
|
||||||
/// }).id();
|
|
||||||
/// }
|
|
||||||
/// # bevy_ecs::system::assert_is_system(example_system);
|
|
||||||
pub fn clone_entity_with(
|
|
||||||
&mut self,
|
|
||||||
entity: Entity,
|
|
||||||
f: impl FnOnce(&mut EntityCloneBuilder) + Send + Sync + 'static,
|
|
||||||
) -> EntityCommands<'_> {
|
|
||||||
let cloned_entity = self.spawn_empty().id();
|
|
||||||
self.queue(move |world: &mut World| {
|
|
||||||
let mut builder = EntityCloneBuilder::new(world);
|
|
||||||
f(&mut builder);
|
|
||||||
builder.clone_entity(entity, cloned_entity);
|
|
||||||
});
|
|
||||||
EntityCommands {
|
|
||||||
commands: self.reborrow(),
|
|
||||||
entity: cloned_entity,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Clones an entity and returns [`EntityCommands`] of the cloned entity.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use bevy_ecs::prelude::*;
|
|
||||||
///
|
|
||||||
/// #[derive(Component, Clone)]
|
|
||||||
/// struct ComponentA(u32);
|
|
||||||
/// #[derive(Component, Clone)]
|
|
||||||
/// struct ComponentB(u32);
|
|
||||||
///
|
|
||||||
/// fn example_system(mut commands: Commands) {
|
|
||||||
/// // Create a new entity and retrieve its id.
|
|
||||||
/// let entity = commands.spawn((ComponentA(10), ComponentB(20))).id();
|
|
||||||
///
|
|
||||||
/// // Create a clone of the first entity
|
|
||||||
/// let entity_clone = commands.clone_entity(entity).id();
|
|
||||||
/// }
|
|
||||||
/// # bevy_ecs::system::assert_is_system(example_system);
|
|
||||||
pub fn clone_entity(&mut self, entity: Entity) -> EntityCommands<'_> {
|
|
||||||
self.clone_entity_with(entity, |_| {})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reserves a new empty [`Entity`] to be spawned, and returns its corresponding [`EntityCommands`].
|
/// Reserves a new empty [`Entity`] to be spawned, and returns its corresponding [`EntityCommands`].
|
||||||
///
|
///
|
||||||
/// See [`World::spawn_empty`] for more details.
|
/// See [`World::spawn_empty`] for more details.
|
||||||
|
@ -1780,6 +1717,73 @@ impl<'a> EntityCommands<'a> {
|
||||||
) -> &mut Self {
|
) -> &mut Self {
|
||||||
self.queue(observe(system))
|
self.queue(observe(system))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clones an entity and returns the [`EntityCommands`] of the clone.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// The command will panic when applied if the original entity does not exist.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use bevy_ecs::prelude::*;
|
||||||
|
///
|
||||||
|
/// #[derive(Component, Clone)]
|
||||||
|
/// struct ComponentA(u32);
|
||||||
|
/// #[derive(Component, Clone)]
|
||||||
|
/// struct ComponentB(u32);
|
||||||
|
///
|
||||||
|
/// fn example_system(mut commands: Commands) {
|
||||||
|
/// // Create a new entity and keep its EntityCommands.
|
||||||
|
/// let mut entity = commands.spawn((ComponentA(10), ComponentB(20)));
|
||||||
|
///
|
||||||
|
/// // Create a clone of the first entity
|
||||||
|
/// let entity_clone = entity.clone();
|
||||||
|
/// }
|
||||||
|
/// # bevy_ecs::system::assert_is_system(example_system);
|
||||||
|
pub fn clone(&mut self) -> EntityCommands<'_> {
|
||||||
|
self.clone_with(|_| {})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clones an entity and allows configuring cloning behavior using [`EntityCloneBuilder`],
|
||||||
|
/// returning the [`EntityCommands`] of the clone.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// The command will panic when applied if the original entity does not exist.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use bevy_ecs::prelude::*;
|
||||||
|
///
|
||||||
|
/// #[derive(Component, Clone)]
|
||||||
|
/// struct ComponentA(u32);
|
||||||
|
/// #[derive(Component, Clone)]
|
||||||
|
/// struct ComponentB(u32);
|
||||||
|
///
|
||||||
|
/// fn example_system(mut commands: Commands) {
|
||||||
|
/// // Create a new entity and keep its EntityCommands.
|
||||||
|
/// let mut entity = commands.spawn((ComponentA(10), ComponentB(20)));
|
||||||
|
///
|
||||||
|
/// // Create a clone of the first entity, but without ComponentB
|
||||||
|
/// let entity_clone = entity.clone_with(|builder| {
|
||||||
|
/// builder.deny::<ComponentB>();
|
||||||
|
/// });
|
||||||
|
/// }
|
||||||
|
/// # bevy_ecs::system::assert_is_system(example_system);
|
||||||
|
pub fn clone_with(
|
||||||
|
&mut self,
|
||||||
|
f: impl FnOnce(&mut EntityCloneBuilder) + Send + Sync + 'static,
|
||||||
|
) -> EntityCommands<'_> {
|
||||||
|
let entity_clone = self.commands().spawn_empty().id();
|
||||||
|
self.queue(clone_entity_with(entity_clone, f));
|
||||||
|
EntityCommands {
|
||||||
|
commands: self.commands_mut().reborrow(),
|
||||||
|
entity: entity_clone,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wrapper around [`EntityCommands`] with convenience methods for working with a specified component type.
|
/// A wrapper around [`EntityCommands`] with convenience methods for working with a specified component type.
|
||||||
|
@ -2254,6 +2258,17 @@ fn observe<E: Event, B: Bundle, M>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clone_entity_with(
|
||||||
|
entity_clone: Entity,
|
||||||
|
f: impl FnOnce(&mut EntityCloneBuilder) + Send + Sync + 'static,
|
||||||
|
) -> impl EntityCommand {
|
||||||
|
move |entity: Entity, world: &mut World| {
|
||||||
|
let mut builder = EntityCloneBuilder::new(world);
|
||||||
|
f(&mut builder);
|
||||||
|
builder.clone_entity(entity, entity_clone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[allow(clippy::float_cmp, clippy::approx_constant)]
|
#[allow(clippy::float_cmp, clippy::approx_constant)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -443,7 +443,8 @@ mod tests {
|
||||||
})
|
})
|
||||||
.id();
|
.id();
|
||||||
let e_clone = commands
|
let e_clone = commands
|
||||||
.clone_entity_with(e, |builder| {
|
.entity(e)
|
||||||
|
.clone_with(|builder| {
|
||||||
builder.recursive(true);
|
builder.recursive(true);
|
||||||
})
|
})
|
||||||
.id();
|
.id();
|
||||||
|
@ -481,7 +482,8 @@ mod tests {
|
||||||
let parent = commands.spawn_empty().add_child(child).id();
|
let parent = commands.spawn_empty().add_child(child).id();
|
||||||
|
|
||||||
let child_clone = commands
|
let child_clone = commands
|
||||||
.clone_entity_with(child, |builder| {
|
.entity(child)
|
||||||
|
.clone_with(|builder| {
|
||||||
builder.as_child(true);
|
builder.as_child(true);
|
||||||
})
|
})
|
||||||
.id();
|
.id();
|
||||||
|
|
Loading…
Reference in a new issue