Make standard commands more ergonomic (in niche cases) (#8249)

# Objective

I ran into a case where I need to create a `CommandQueue` and push
standard `Command` actions like `Insert` or `Remove` to it manually. I
saw that `Remove` looked as follows:

```rust
struct Remove<T> {
  entity: Entity,
  phantom: PhantomData<T>
}
```

so naturally, I tried to use `Remove::<Foo>::from(entity)` but it didn't
exist. We need to specify the `PhantomData` explicitly when creating
this command action. The same goes for `RemoveResource` and
`InitResource`

## Solution

This PR implements the following:

- `From<Entity>` for `Remove<T>`
- `Default` for `RemoveResource` and `InitResource`
- use these traits in the implementation of methods of `Commands`
- rename `phantom` field on the structs above to `_phantom` to have a
more uniform field naming scheme for the command actions

---

## Changelog

> This section is optional. If this was a trivial fix, or has no
externally-visible impact, you can delete this section.

- Added: implemented `From<Entity>` for `Remove<T>` and `Default` for
`RemoveResource` and `InitResource` for ergonomics

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This commit is contained in:
Robert Walter 2023-03-29 20:27:48 +02:00 committed by GitHub
parent 36ada9dd4e
commit 5f0abbfd15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -444,9 +444,7 @@ impl<'w, 's> Commands<'w, 's> {
/// # bevy_ecs::system::assert_is_system(initialise_scoreboard); /// # bevy_ecs::system::assert_is_system(initialise_scoreboard);
/// ``` /// ```
pub fn init_resource<R: Resource + FromWorld>(&mut self) { pub fn init_resource<R: Resource + FromWorld>(&mut self) {
self.queue.push(InitResource::<R> { self.queue.push(InitResource::<R>::new());
_phantom: PhantomData::<R>::default(),
});
} }
/// Pushes a [`Command`] to the queue for inserting a [`Resource`] in the [`World`] with a specific value. /// Pushes a [`Command`] to the queue for inserting a [`Resource`] in the [`World`] with a specific value.
@ -499,9 +497,7 @@ impl<'w, 's> Commands<'w, 's> {
/// # bevy_ecs::system::assert_is_system(system); /// # bevy_ecs::system::assert_is_system(system);
/// ``` /// ```
pub fn remove_resource<R: Resource>(&mut self) { pub fn remove_resource<R: Resource>(&mut self) {
self.queue.push(RemoveResource::<R> { self.queue.push(RemoveResource::<R>::new());
phantom: PhantomData,
});
} }
/// Pushes a generic [`Command`] to the command queue. /// Pushes a generic [`Command`] to the command queue.
@ -748,10 +744,7 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
where where
T: Bundle, T: Bundle,
{ {
self.commands.add(Remove::<T> { self.commands.add(Remove::<T>::new(self.entity));
entity: self.entity,
phantom: PhantomData,
});
self self
} }
@ -956,6 +949,16 @@ where
} }
} }
impl<T> Remove<T> {
/// Creates a [`Command`] which will remove the specified [`Entity`] when flushed
pub const fn new(entity: Entity) -> Self {
Self {
entity,
phantom: PhantomData::<T>,
}
}
}
pub struct InitResource<R: Resource + FromWorld> { pub struct InitResource<R: Resource + FromWorld> {
_phantom: PhantomData<R>, _phantom: PhantomData<R>,
} }
@ -966,6 +969,15 @@ impl<R: Resource + FromWorld> Command for InitResource<R> {
} }
} }
impl<R: Resource + FromWorld> InitResource<R> {
/// Creates a [`Command`] which will insert a default created [`Resource`] into the [`World`]
pub const fn new() -> Self {
Self {
_phantom: PhantomData::<R>,
}
}
}
pub struct InsertResource<R: Resource> { pub struct InsertResource<R: Resource> {
pub resource: R, pub resource: R,
} }
@ -986,6 +998,15 @@ impl<R: Resource> Command for RemoveResource<R> {
} }
} }
impl<R: Resource> RemoveResource<R> {
/// Creates a [`Command`] which will remove a [`Resource`] from the [`World`]
pub const fn new() -> Self {
Self {
phantom: PhantomData::<R>,
}
}
}
/// [`Command`] to log the components of a given entity. See [`EntityCommands::log_components`]. /// [`Command`] to log the components of a given entity. See [`EntityCommands::log_components`].
pub struct LogComponents { pub struct LogComponents {
entity: Entity, entity: Entity,