Skip to content

Commit

Permalink
Use an opaque type for EntityCommand::with_entity (bevyengine#11210)
Browse files Browse the repository at this point in the history
# Objective

The trait method `with_entity` is used to add an `EntityCommand` to the
command queue. Currently this method returns `WithEntity<C>` which pairs
a command with an `Entity`. By replacing this explicit type with an
opaque type, implementors can override this default implementation by
returning a custom command or closure that does the same thing with a
lower memory footprint.

# Solution

Return an opaque type from the method. As a bonus this file is now
cleaner without the `WithEntity` boilerplate
  • Loading branch information
JoJoJet authored Jun 26, 2024
1 parent f0bdce7 commit a4c621a
Showing 1 changed file with 9 additions and 25 deletions.
34 changes: 9 additions & 25 deletions crates/bevy_ecs/src/system/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use crate::{
};
use bevy_utils::tracing::{error, info};
pub use parallel_scope::*;
use std::marker::PhantomData;

/// A [`Command`] queue to perform structural changes to the [`World`].
///
Expand Down Expand Up @@ -825,34 +824,19 @@ impl<'w, 's> Commands<'w, 's> {
/// ```
pub trait EntityCommand<Marker = ()>: Send + 'static {
/// Executes this command for the given [`Entity`].
fn apply(self, id: Entity, world: &mut World);
fn apply(self, entity: Entity, world: &mut World);

/// Returns a [`Command`] which executes this [`EntityCommand`] for the given [`Entity`].
fn with_entity(self, id: Entity) -> WithEntity<Marker, Self>
///
/// This method is called when adding an [`EntityCommand`] to a command queue via [`Commands`].
/// You can override the provided implementation if you can return a `Command` with a smaller memory
/// footprint than `(Entity, Self)`.
/// In most cases the provided implementation is sufficient.
fn with_entity(self, entity: Entity) -> impl Command
where
Self: Sized,
{
WithEntity {
cmd: self,
id,
marker: PhantomData,
}
}
}

/// Turns an [`EntityCommand`] type into a [`Command`] type.
pub struct WithEntity<Marker, C: EntityCommand<Marker>> {
cmd: C,
id: Entity,
marker: PhantomData<fn() -> Marker>,
}

impl<M, C: EntityCommand<M>> Command for WithEntity<M, C>
where
M: 'static,
{
#[inline]
fn apply(self, world: &mut World) {
self.cmd.apply(self.id, world);
move |world: &mut World| self.apply(entity, world)
}
}

Expand Down

0 comments on commit a4c621a

Please sign in to comment.