Rename EntityCommands::clone to clone_and_spawn (#16696)

## Objective

Follow-up to #16672.

`EntityCommands::clone` looks the same as the `Clone` trait, which could
be confusing. A discord discussion has made me realize that's probably a
bigger problem than I thought. Oops :P

## Solution

Renamed `EntityCommands::clone` to `EntityCommands::clone_and_spawn`,
renamed `EntityCommands::clone_with` to
`EntityCommands::clone_and_spawn_with`. Also added some docs explaining
the commands' relation to `Clone` (components need to implement it (or
`Reflect`)).

## 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_and_spawn();
```

## The Bikeshed

- `clone_and_spawn` (Alice's suggestion)
- `spawn_clone` (benfrankel's suggestion)
- `spawn_cloned` (rparrett's suggestion)
This commit is contained in:
JaySpruce 2024-12-09 21:26:15 -06:00 committed by GitHub
parent 1c86cb5d9c
commit db4c468fe2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 24 additions and 11 deletions

View file

@ -1720,6 +1720,12 @@ impl<'a> EntityCommands<'a> {
/// Clones an entity and returns the [`EntityCommands`] of the clone. /// Clones an entity and returns the [`EntityCommands`] of the clone.
/// ///
/// The clone will receive all the components of the original that implement
/// [`Clone`] or [`Reflect`](bevy_reflect::Reflect).
///
/// To configure cloning behavior (such as only cloning certain components),
/// use [`EntityCommands::clone_and_spawn_with`].
///
/// # Panics /// # Panics
/// ///
/// The command will panic when applied if the original entity does not exist. /// The command will panic when applied if the original entity does not exist.
@ -1735,20 +1741,27 @@ impl<'a> EntityCommands<'a> {
/// struct ComponentB(u32); /// struct ComponentB(u32);
/// ///
/// fn example_system(mut commands: Commands) { /// fn example_system(mut commands: Commands) {
/// // Create a new entity and keep its EntityCommands. /// // Create a new entity and keep its EntityCommands
/// let mut entity = commands.spawn((ComponentA(10), ComponentB(20))); /// let mut entity = commands.spawn((ComponentA(10), ComponentB(20)));
/// ///
/// // Create a clone of the first entity /// // Create a clone of the first entity
/// let entity_clone = entity.clone(); /// let mut entity_clone = entity.clone_and_spawn();
/// } /// }
/// # bevy_ecs::system::assert_is_system(example_system); /// # bevy_ecs::system::assert_is_system(example_system);
pub fn clone(&mut self) -> EntityCommands<'_> { pub fn clone_and_spawn(&mut self) -> EntityCommands<'_> {
self.clone_with(|_| {}) self.clone_and_spawn_with(|_| {})
} }
/// Clones an entity and allows configuring cloning behavior using [`EntityCloneBuilder`], /// Clones an entity and allows configuring cloning behavior using [`EntityCloneBuilder`],
/// returning the [`EntityCommands`] of the clone. /// returning the [`EntityCommands`] of the clone.
/// ///
/// By default, the clone will receive all the components of the original that implement
/// [`Clone`] or [`Reflect`](bevy_reflect::Reflect).
///
/// To exclude specific components, use [`EntityCloneBuilder::deny`].
/// To only include specific components, use [`EntityCloneBuilder::deny_all`]
/// followed by [`EntityCloneBuilder::allow`].
///
/// # Panics /// # Panics
/// ///
/// The command will panic when applied if the original entity does not exist. /// The command will panic when applied if the original entity does not exist.
@ -1764,21 +1777,21 @@ impl<'a> EntityCommands<'a> {
/// struct ComponentB(u32); /// struct ComponentB(u32);
/// ///
/// fn example_system(mut commands: Commands) { /// fn example_system(mut commands: Commands) {
/// // Create a new entity and keep its EntityCommands. /// // Create a new entity and keep its EntityCommands
/// let mut entity = commands.spawn((ComponentA(10), ComponentB(20))); /// let mut entity = commands.spawn((ComponentA(10), ComponentB(20)));
/// ///
/// // Create a clone of the first entity, but without ComponentB /// // Create a clone of the first entity, but without ComponentB
/// let entity_clone = entity.clone_with(|builder| { /// let mut entity_clone = entity.clone_and_spawn_with(|builder| {
/// builder.deny::<ComponentB>(); /// builder.deny::<ComponentB>();
/// }); /// });
/// } /// }
/// # bevy_ecs::system::assert_is_system(example_system); /// # bevy_ecs::system::assert_is_system(example_system);
pub fn clone_with( pub fn clone_and_spawn_with(
&mut self, &mut self,
f: impl FnOnce(&mut EntityCloneBuilder) + Send + Sync + 'static, f: impl FnOnce(&mut EntityCloneBuilder) + Send + Sync + 'static,
) -> EntityCommands<'_> { ) -> EntityCommands<'_> {
let entity_clone = self.commands().spawn_empty().id(); let entity_clone = self.commands().spawn_empty().id();
self.queue(clone_entity_with(entity_clone, f)); self.queue(clone_and_spawn_with(entity_clone, f));
EntityCommands { EntityCommands {
commands: self.commands_mut().reborrow(), commands: self.commands_mut().reborrow(),
entity: entity_clone, entity: entity_clone,
@ -2258,7 +2271,7 @@ fn observe<E: Event, B: Bundle, M>(
} }
} }
fn clone_entity_with( fn clone_and_spawn_with(
entity_clone: Entity, entity_clone: Entity,
f: impl FnOnce(&mut EntityCloneBuilder) + Send + Sync + 'static, f: impl FnOnce(&mut EntityCloneBuilder) + Send + Sync + 'static,
) -> impl EntityCommand { ) -> impl EntityCommand {

View file

@ -444,7 +444,7 @@ mod tests {
.id(); .id();
let e_clone = commands let e_clone = commands
.entity(e) .entity(e)
.clone_with(|builder| { .clone_and_spawn_with(|builder| {
builder.recursive(true); builder.recursive(true);
}) })
.id(); .id();
@ -483,7 +483,7 @@ mod tests {
let child_clone = commands let child_clone = commands
.entity(child) .entity(child)
.clone_with(|builder| { .clone_and_spawn_with(|builder| {
builder.as_child(true); builder.as_child(true);
}) })
.id(); .id();