mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 20:23:28 +00:00
refactor: Simplify lifetimes for Commands
and related types (#11445)
# Objective It would be convenient to be able to call functions with `Commands` as a parameter without having to move your own instance of `Commands`. Since this struct is composed entirely of references, we can easily get an owned instance of `Commands` by shortening the lifetime. ## Solution Add `Commands::reborrow`, `EntiyCommands::reborrow`, and `Deferred::reborrow`, which returns an owned version of themselves with a shorter lifetime. Remove unnecessary lifetimes from `EntityCommands`. The `'w` and `'s` lifetimes only have to be separate for `Commands` because it's used as a `SystemParam` -- this is not the case for `EntityCommands`. --- ## Changelog Added `Commands::reborrow`. This is useful if you have `&mut Commands` but need `Commands`. Also added `EntityCommands::reborrow` and `Deferred:reborrow` which serve the same purpose. ## Migration Guide The lifetimes for `EntityCommands` have been simplified. ```rust // Before (Bevy 0.12) struct MyStruct<'w, 's, 'a> { commands: EntityCommands<'w, 's, 'a>, } // After (Bevy 0.13) struct MyStruct<'a> { commands: EntityCommands<'a>, } ``` The method `EntityCommands::commands` now returns `Commands` rather than `&mut Commands`. ```rust // Before (Bevy 0.12) let commands = entity_commands.commands(); commands.spawn(...); // After (Bevy 0.13) let mut commands = entity_commands.commands(); commands.spawn(...); ```
This commit is contained in:
parent
e2e4e8eb9a
commit
7d69d3195f
6 changed files with 65 additions and 23 deletions
|
@ -140,7 +140,7 @@ pub trait ReflectCommandExt {
|
|||
) -> &mut Self;
|
||||
}
|
||||
|
||||
impl<'w, 's, 'a> ReflectCommandExt for EntityCommands<'w, 's, 'a> {
|
||||
impl ReflectCommandExt for EntityCommands<'_> {
|
||||
fn insert_reflect(&mut self, component: Box<dyn Reflect>) -> &mut Self {
|
||||
self.commands.add(InsertReflect {
|
||||
entity: self.entity,
|
||||
|
|
|
@ -146,6 +146,31 @@ impl<'w, 's> Commands<'w, 's> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns a [`Commands`] with a smaller lifetime.
|
||||
/// This is useful if you have `&mut Commands` but need `Commands`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// fn my_system(mut commands: Commands) {
|
||||
/// // We do our initialization in a separate function,
|
||||
/// // which expects an owned `Commands`.
|
||||
/// do_initialization(commands.reborrow());
|
||||
///
|
||||
/// // Since we only reborrowed the commands instead of moving them, we can still use them.
|
||||
/// commands.spawn_empty();
|
||||
/// }
|
||||
/// #
|
||||
/// # fn do_initialization(_: Commands) {}
|
||||
/// ```
|
||||
pub fn reborrow(&mut self) -> Commands<'w, '_> {
|
||||
Commands {
|
||||
queue: self.queue.reborrow(),
|
||||
entities: self.entities,
|
||||
}
|
||||
}
|
||||
|
||||
/// Take all commands from `other` and append them to `self`, leaving `other` empty
|
||||
pub fn append(&mut self, other: &mut CommandQueue) {
|
||||
self.queue.append(other);
|
||||
|
@ -186,11 +211,11 @@ impl<'w, 's> Commands<'w, 's> {
|
|||
///
|
||||
/// - [`spawn`](Self::spawn) to spawn an entity with a bundle.
|
||||
/// - [`spawn_batch`](Self::spawn_batch) to spawn entities with a bundle each.
|
||||
pub fn spawn_empty<'a>(&'a mut self) -> EntityCommands<'w, 's, 'a> {
|
||||
pub fn spawn_empty(&mut self) -> EntityCommands {
|
||||
let entity = self.entities.reserve_entity();
|
||||
EntityCommands {
|
||||
entity,
|
||||
commands: self,
|
||||
commands: self.reborrow(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,13 +233,13 @@ impl<'w, 's> Commands<'w, 's> {
|
|||
/// [`Commands::spawn`]. This method should generally only be used for sharing entities across
|
||||
/// apps, and only when they have a scheme worked out to share an ID space (which doesn't happen
|
||||
/// by default).
|
||||
pub fn get_or_spawn<'a>(&'a mut self, entity: Entity) -> EntityCommands<'w, 's, 'a> {
|
||||
pub fn get_or_spawn(&mut self, entity: Entity) -> EntityCommands {
|
||||
self.add(move |world: &mut World| {
|
||||
world.get_or_spawn(entity);
|
||||
});
|
||||
EntityCommands {
|
||||
entity,
|
||||
commands: self,
|
||||
commands: self.reborrow(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,7 +293,7 @@ impl<'w, 's> Commands<'w, 's> {
|
|||
///
|
||||
/// - [`spawn_empty`](Self::spawn_empty) to spawn an entity without any components.
|
||||
/// - [`spawn_batch`](Self::spawn_batch) to spawn entities with a bundle each.
|
||||
pub fn spawn<'a, T: Bundle>(&'a mut self, bundle: T) -> EntityCommands<'w, 's, 'a> {
|
||||
pub fn spawn<T: Bundle>(&mut self, bundle: T) -> EntityCommands {
|
||||
let mut e = self.spawn_empty();
|
||||
e.insert(bundle);
|
||||
e
|
||||
|
@ -310,7 +335,7 @@ impl<'w, 's> Commands<'w, 's> {
|
|||
/// - [`get_entity`](Self::get_entity) for the fallible version.
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
pub fn entity<'a>(&'a mut self, entity: Entity) -> EntityCommands<'w, 's, 'a> {
|
||||
pub fn entity(&mut self, entity: Entity) -> EntityCommands {
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
#[track_caller]
|
||||
|
@ -359,10 +384,10 @@ impl<'w, 's> Commands<'w, 's> {
|
|||
/// - [`entity`](Self::entity) for the panicking version.
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
pub fn get_entity<'a>(&'a mut self, entity: Entity) -> Option<EntityCommands<'w, 's, 'a>> {
|
||||
pub fn get_entity(&mut self, entity: Entity) -> Option<EntityCommands> {
|
||||
self.entities.contains(entity).then_some(EntityCommands {
|
||||
entity,
|
||||
commands: self,
|
||||
commands: self.reborrow(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -674,12 +699,12 @@ where
|
|||
}
|
||||
|
||||
/// A list of commands that will be run to modify an [entity](crate::entity).
|
||||
pub struct EntityCommands<'w, 's, 'a> {
|
||||
pub struct EntityCommands<'a> {
|
||||
pub(crate) entity: Entity,
|
||||
pub(crate) commands: &'a mut Commands<'w, 's>,
|
||||
pub(crate) commands: Commands<'a, 'a>,
|
||||
}
|
||||
|
||||
impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
|
||||
impl EntityCommands<'_> {
|
||||
/// Returns the [`Entity`] id of the entity.
|
||||
///
|
||||
/// # Example
|
||||
|
@ -698,6 +723,15 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
|
|||
self.entity
|
||||
}
|
||||
|
||||
/// Returns an [`EntityCommands`] with a smaller lifetime.
|
||||
/// This is useful if you have `&mut EntityCommands` but you need `EntityCommands`.
|
||||
pub fn reborrow(&mut self) -> EntityCommands {
|
||||
EntityCommands {
|
||||
entity: self.entity,
|
||||
commands: self.commands.reborrow(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a [`Bundle`] of components to the entity.
|
||||
///
|
||||
/// This will overwrite any previous value(s) of the same component type.
|
||||
|
@ -956,8 +990,8 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
|
|||
}
|
||||
|
||||
/// Returns the underlying [`Commands`].
|
||||
pub fn commands(&mut self) -> &mut Commands<'w, 's> {
|
||||
self.commands
|
||||
pub fn commands(&mut self) -> Commands {
|
||||
self.commands.reborrow()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -919,6 +919,14 @@ impl<'a, T: SystemBuffer> DerefMut for Deferred<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: SystemBuffer> Deferred<'_, T> {
|
||||
/// Returns a [`Deferred<T>`] with a smaller lifetime.
|
||||
/// This is useful if you have `&mut Deferred<T>` but need `Deferred<T>`.
|
||||
pub fn reborrow(&mut self) -> Deferred<T> {
|
||||
Deferred(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: Only local state is accessed.
|
||||
unsafe impl<T: SystemBuffer> ReadOnlySystemParam for Deferred<'_, T> {}
|
||||
|
||||
|
|
|
@ -274,15 +274,15 @@ impl Command for RemoveParent {
|
|||
/// });
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct ChildBuilder<'w, 's, 'a> {
|
||||
commands: &'a mut Commands<'w, 's>,
|
||||
pub struct ChildBuilder<'a> {
|
||||
commands: Commands<'a, 'a>,
|
||||
push_children: PushChildren,
|
||||
}
|
||||
|
||||
impl<'w, 's, 'a> ChildBuilder<'w, 's, 'a> {
|
||||
impl ChildBuilder<'_> {
|
||||
/// 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<'w, 's, '_> {
|
||||
pub fn spawn(&mut self, bundle: impl Bundle) -> EntityCommands {
|
||||
let e = self.commands.spawn(bundle);
|
||||
self.push_children.children.push(e.id());
|
||||
e
|
||||
|
@ -290,7 +290,7 @@ impl<'w, 's, 'a> ChildBuilder<'w, 's, 'a> {
|
|||
|
||||
/// 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<'w, 's, '_> {
|
||||
pub fn spawn_empty(&mut self) -> EntityCommands {
|
||||
let e = self.commands.spawn_empty();
|
||||
self.push_children.children.push(e.id());
|
||||
e
|
||||
|
@ -302,7 +302,7 @@ impl<'w, 's, 'a> ChildBuilder<'w, 's, 'a> {
|
|||
}
|
||||
|
||||
/// Adds a command to be executed, like [`Commands::add`].
|
||||
pub fn add_command<C: Command + 'static>(&mut self, command: C) -> &mut Self {
|
||||
pub fn add_command<C: Command>(&mut self, command: C) -> &mut Self {
|
||||
self.commands.add(command);
|
||||
self
|
||||
}
|
||||
|
@ -374,7 +374,7 @@ pub trait BuildChildren {
|
|||
fn remove_parent(&mut self) -> &mut Self;
|
||||
}
|
||||
|
||||
impl<'w, 's, 'a> BuildChildren for EntityCommands<'w, 's, 'a> {
|
||||
impl BuildChildren for EntityCommands<'_> {
|
||||
fn with_children(&mut self, spawn_children: impl FnOnce(&mut ChildBuilder)) -> &mut Self {
|
||||
let parent = self.id();
|
||||
let mut builder = ChildBuilder {
|
||||
|
|
|
@ -89,7 +89,7 @@ pub trait DespawnRecursiveExt {
|
|||
fn despawn_descendants(&mut self) -> &mut Self;
|
||||
}
|
||||
|
||||
impl<'w, 's, 'a> DespawnRecursiveExt for EntityCommands<'w, 's, 'a> {
|
||||
impl DespawnRecursiveExt for EntityCommands<'_> {
|
||||
/// Despawns the provided entity and its children.
|
||||
fn despawn_recursive(mut self) {
|
||||
let entity = self.id();
|
||||
|
|
|
@ -85,7 +85,7 @@ pub trait BuildChildrenTransformExt {
|
|||
/// (during [`apply_deferred`](bevy_ecs::schedule::apply_deferred)).
|
||||
fn remove_parent_in_place(&mut self) -> &mut Self;
|
||||
}
|
||||
impl<'w, 's, 'a> BuildChildrenTransformExt for EntityCommands<'w, 's, 'a> {
|
||||
impl BuildChildrenTransformExt for EntityCommands<'_> {
|
||||
fn set_parent_in_place(&mut self, parent: Entity) -> &mut Self {
|
||||
let child = self.id();
|
||||
self.commands().add(PushChildInPlace { child, parent });
|
||||
|
|
Loading…
Reference in a new issue