Skip to content

Commit d0afdc6

Browse files
authored
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.
1 parent 10e3cc7 commit d0afdc6

File tree

2 files changed

+82
-65
lines changed

2 files changed

+82
-65
lines changed

crates/bevy_ecs/src/system/commands/mod.rs

+78-63
Original file line numberDiff line numberDiff line change
@@ -272,69 +272,6 @@ impl<'w, 's> Commands<'w, 's> {
272272
}
273273
}
274274

275-
/// Clones an entity and allows configuring cloning behavior using [`EntityCloneBuilder`], returning [`EntityCommands`] of the cloned entity.
276-
///
277-
/// # Example
278-
///
279-
/// ```
280-
/// # use bevy_ecs::prelude::*;
281-
///
282-
/// #[derive(Component, Clone)]
283-
/// struct ComponentA(u32);
284-
/// #[derive(Component, Clone)]
285-
/// struct ComponentB(u32);
286-
///
287-
/// fn example_system(mut commands: Commands) {
288-
/// // Create a new entity and retrieve its id.
289-
/// let entity = commands.spawn((ComponentA(10), ComponentB(20))).id();
290-
///
291-
/// // Create a clone of the first entity, but without ComponentB
292-
/// let entity_clone = commands.clone_entity_with(entity, |builder| {
293-
/// builder.deny::<ComponentB>();
294-
/// }).id();
295-
/// }
296-
/// # bevy_ecs::system::assert_is_system(example_system);
297-
pub fn clone_entity_with(
298-
&mut self,
299-
entity: Entity,
300-
f: impl FnOnce(&mut EntityCloneBuilder) + Send + Sync + 'static,
301-
) -> EntityCommands<'_> {
302-
let cloned_entity = self.spawn_empty().id();
303-
self.queue(move |world: &mut World| {
304-
let mut builder = EntityCloneBuilder::new(world);
305-
f(&mut builder);
306-
builder.clone_entity(entity, cloned_entity);
307-
});
308-
EntityCommands {
309-
commands: self.reborrow(),
310-
entity: cloned_entity,
311-
}
312-
}
313-
314-
/// Clones an entity and returns [`EntityCommands`] of the cloned entity.
315-
///
316-
/// # Example
317-
///
318-
/// ```
319-
/// # use bevy_ecs::prelude::*;
320-
///
321-
/// #[derive(Component, Clone)]
322-
/// struct ComponentA(u32);
323-
/// #[derive(Component, Clone)]
324-
/// struct ComponentB(u32);
325-
///
326-
/// fn example_system(mut commands: Commands) {
327-
/// // Create a new entity and retrieve its id.
328-
/// let entity = commands.spawn((ComponentA(10), ComponentB(20))).id();
329-
///
330-
/// // Create a clone of the first entity
331-
/// let entity_clone = commands.clone_entity(entity).id();
332-
/// }
333-
/// # bevy_ecs::system::assert_is_system(example_system);
334-
pub fn clone_entity(&mut self, entity: Entity) -> EntityCommands<'_> {
335-
self.clone_entity_with(entity, |_| {})
336-
}
337-
338275
/// Reserves a new empty [`Entity`] to be spawned, and returns its corresponding [`EntityCommands`].
339276
///
340277
/// See [`World::spawn_empty`] for more details.
@@ -1780,6 +1717,73 @@ impl<'a> EntityCommands<'a> {
17801717
) -> &mut Self {
17811718
self.queue(observe(system))
17821719
}
1720+
1721+
/// Clones an entity and returns the [`EntityCommands`] of the clone.
1722+
///
1723+
/// # Panics
1724+
///
1725+
/// The command will panic when applied if the original entity does not exist.
1726+
///
1727+
/// # Example
1728+
///
1729+
/// ```
1730+
/// # use bevy_ecs::prelude::*;
1731+
///
1732+
/// #[derive(Component, Clone)]
1733+
/// struct ComponentA(u32);
1734+
/// #[derive(Component, Clone)]
1735+
/// struct ComponentB(u32);
1736+
///
1737+
/// fn example_system(mut commands: Commands) {
1738+
/// // Create a new entity and keep its EntityCommands.
1739+
/// let mut entity = commands.spawn((ComponentA(10), ComponentB(20)));
1740+
///
1741+
/// // Create a clone of the first entity
1742+
/// let entity_clone = entity.clone();
1743+
/// }
1744+
/// # bevy_ecs::system::assert_is_system(example_system);
1745+
pub fn clone(&mut self) -> EntityCommands<'_> {
1746+
self.clone_with(|_| {})
1747+
}
1748+
1749+
/// Clones an entity and allows configuring cloning behavior using [`EntityCloneBuilder`],
1750+
/// returning the [`EntityCommands`] of the clone.
1751+
///
1752+
/// # Panics
1753+
///
1754+
/// The command will panic when applied if the original entity does not exist.
1755+
///
1756+
/// # Example
1757+
///
1758+
/// ```
1759+
/// # use bevy_ecs::prelude::*;
1760+
///
1761+
/// #[derive(Component, Clone)]
1762+
/// struct ComponentA(u32);
1763+
/// #[derive(Component, Clone)]
1764+
/// struct ComponentB(u32);
1765+
///
1766+
/// fn example_system(mut commands: Commands) {
1767+
/// // Create a new entity and keep its EntityCommands.
1768+
/// let mut entity = commands.spawn((ComponentA(10), ComponentB(20)));
1769+
///
1770+
/// // Create a clone of the first entity, but without ComponentB
1771+
/// let entity_clone = entity.clone_with(|builder| {
1772+
/// builder.deny::<ComponentB>();
1773+
/// });
1774+
/// }
1775+
/// # bevy_ecs::system::assert_is_system(example_system);
1776+
pub fn clone_with(
1777+
&mut self,
1778+
f: impl FnOnce(&mut EntityCloneBuilder) + Send + Sync + 'static,
1779+
) -> EntityCommands<'_> {
1780+
let entity_clone = self.commands().spawn_empty().id();
1781+
self.queue(clone_entity_with(entity_clone, f));
1782+
EntityCommands {
1783+
commands: self.commands_mut().reborrow(),
1784+
entity: entity_clone,
1785+
}
1786+
}
17831787
}
17841788

17851789
/// 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>(
22542258
}
22552259
}
22562260

2261+
fn clone_entity_with(
2262+
entity_clone: Entity,
2263+
f: impl FnOnce(&mut EntityCloneBuilder) + Send + Sync + 'static,
2264+
) -> impl EntityCommand {
2265+
move |entity: Entity, world: &mut World| {
2266+
let mut builder = EntityCloneBuilder::new(world);
2267+
f(&mut builder);
2268+
builder.clone_entity(entity, entity_clone);
2269+
}
2270+
}
2271+
22572272
#[cfg(test)]
22582273
#[allow(clippy::float_cmp, clippy::approx_constant)]
22592274
mod tests {

crates/bevy_hierarchy/src/hierarchy.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,8 @@ mod tests {
443443
})
444444
.id();
445445
let e_clone = commands
446-
.clone_entity_with(e, |builder| {
446+
.entity(e)
447+
.clone_with(|builder| {
447448
builder.recursive(true);
448449
})
449450
.id();
@@ -481,7 +482,8 @@ mod tests {
481482
let parent = commands.spawn_empty().add_child(child).id();
482483

483484
let child_clone = commands
484-
.clone_entity_with(child, |builder| {
485+
.entity(child)
486+
.clone_with(|builder| {
485487
builder.as_child(true);
486488
})
487489
.id();

0 commit comments

Comments
 (0)