bevy icon indicating copy to clipboard operation
bevy copied to clipboard

Immediate Execution of `Commands` on a `&mut World`

Open Zeenobit opened this issue 3 years ago • 8 comments
trafficstars

Objective

Fixed #6184

Solution

This PR adds an Execute trait which is implemented for &mut World and &mut App. It allows the user to do this:

let mut world = World::default();
let _ = world.execute(|_world, mut commands| {
    /* ... */
});

Zeenobit avatar Oct 06 '22 17:10 Zeenobit

As you mention in your doc comment, this is a very inefficient way to execute a command when you have a world available.

If this is only to be used for test, I would rather it being not available outside of tests

mockersf avatar Oct 06 '22 22:10 mockersf

As you mention in your doc comment, this is a very inefficient way to execute a command when you have a world available.

If this is only to be used for test, I would rather it being not available outside of tests

I considered doing this initially. There is a couple of problems with this:

  1. We can't just gate it behind #[cfg(test)], as it would also be useful for examples. So ideally it should be locked behind a feature of its own, but that's just extra build complexity for questionable benefit.
  2. I've found this to be useful for debug UI code, such as with egui, where I want to have a button which executes a bunch of commands when I have &mut World access. So it's also useful for general diagnostics at runtime.

For these reasons, I decided keeping it available but with a warning in the comments is probably the best option.

Also, Execute is not imported with preludes. So that's an extra layer of "protection".

Zeenobit avatar Oct 07 '22 00:10 Zeenobit

If this is only to be used for test, I would rather it being not available outside of tests

This came up before in my other PRs for testing utilities. I think that the trait (that's not in the prelude) is a reasonable approach. I would also support the creation of a bevy_testing crate to stick this sort of thing in, which would improve discoverability.

alice-i-cecile avatar Oct 07 '22 01:10 alice-i-cecile

This came up before in my other PRs for testing utilities. I think that the trait (that's not in the prelude) is a reasonable approach. I would also support the creation of a bevy_testing crate to stick this sort of thing in, which would improve discoverability.

I like this idea, but I would suggest naming it some more generic like bevy_diagnostics. My rationale is that a lot of stuff like this that's useful for testing would also be useful for stuff like cheats, debug tools, or automation. If we name it bevy_testing, it'd imply it's only useful for testing.

Zeenobit avatar Oct 07 '22 03:10 Zeenobit

Well, we have bevy_diagnostic. @mockersf, I'd be okay with testing utilities going in there!

alice-i-cecile avatar Oct 07 '22 13:10 alice-i-cecile

Let me know if we want to move the entire implementation into a separate file execute.rs under bevy_diagnostic.

Zeenobit avatar Oct 10 '22 18:10 Zeenobit

Yes please :)

alice-i-cecile avatar Oct 10 '22 19:10 alice-i-cecile

Awesome. Can you add an example for this? Maybe in the root tests directory? I would suggest you link it from the Commands docs but we can't, because circular dependencies.

I added an example under how_to_test_commands.rs. It's hard to come up with a good use case for using a custom command without really explaining a system which might need it. I figured navigation might the best example, but let me know if you have better ideas. And for all regular commands, most of them are accessible through &mut World anyways.

Also, I'm not sure if it was just me, but an issue I discovered while testing:

world.spawn(()) seems to panic with "index out of bounds: the len is 0 but the index is 0". But commands.spawn(()) seems fine.

Zeenobit avatar Oct 10 '22 22:10 Zeenobit

Today I realized I accidentally deleted the repository for this. 😢 I'll open a new PR in future.

Zeenobit avatar Jan 20 '23 18:01 Zeenobit