Skip to content

Commit

Permalink
impl Command for <impl FnOnce(&mut World)> (#2996)
Browse files Browse the repository at this point in the history
This is my first contribution to this exciting project! Thanks so much for your wonderful work. If there is anything that I can improve about this PR, please let me know :)

# Objective

- Fixes #2899
- If a simple one-off command is needed to be added within a System, this simplifies that process so that we can simply do `commands.add(|world: &mut World| { /* code here */ })` instead of defining a custom type implementing `Command`.

## Solution

- This is achieved by `impl Command for F where F: FnOnce(&mut World) + Send + Sync + 'static` as just calling the function.

I am not sure if the bounds can be further relaxed but needed the whole `Send`, `Sync`, and `'static` to get it to compile.
  • Loading branch information
sseemayer committed Feb 3, 2022
1 parent 69e9a47 commit 21ac4bc
Showing 1 changed file with 34 additions and 0 deletions.
34 changes: 34 additions & 0 deletions crates/bevy_ecs/src/system/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,15 @@ impl<'w, 's, 'a> EntityCommands<'w, 's, 'a> {
}
}

impl<F> Command for F
where
F: FnOnce(&mut World) + Send + Sync + 'static,
{
fn write(self, world: &mut World) {
self(world)
}
}

#[derive(Debug)]
pub struct Spawn<T> {
pub bundle: T,
Expand Down Expand Up @@ -760,6 +769,10 @@ mod tests {
#[derive(Component)]
struct W<T>(T);

fn simple_command(world: &mut World) {
world.spawn().insert_bundle((W(0u32), W(42u64)));
}

#[test]
fn commands() {
let mut world = World::default();
Expand Down Expand Up @@ -788,6 +801,27 @@ mod tests {
.map(|(a, b)| (a.0, b.0))
.collect::<Vec<_>>();
assert_eq!(results2, vec![]);

// test adding simple (FnOnce) commands
{
let mut commands = Commands::new(&mut command_queue, &world);

// set up a simple command using a closure that adds one additional entity
commands.add(|world: &mut World| {
world.spawn().insert_bundle((W(42u32), W(0u64)));
});

// set up a simple command using a function that adds one additional entity
commands.add(simple_command);
}
command_queue.apply(&mut world);
let results3 = world
.query::<(&W<u32>, &W<u64>)>()
.iter(&world)
.map(|(a, b)| (a.0, b.0))
.collect::<Vec<_>>();

assert_eq!(results3, vec![(42u32, 0u64), (0u32, 42u64)]);
}

#[test]
Expand Down

0 comments on commit 21ac4bc

Please sign in to comment.