7 releases (breaking)
0.7.0 | Nov 15, 2022 |
---|---|
0.6.0 | Aug 1, 2022 |
0.5.0 | Jun 22, 2022 |
0.4.0 | Jun 21, 2022 |
0.1.0 | May 30, 2022 |
#2203 in Game dev
18KB
136 lines
Conditional Commands
This crate implements three extension traits that allow for conditional component, bundle and child insertion without the need for an intermediate EntityCommands
or EntityMut
binding.
ConditionalInsertBundleExt
forEntityCommands
andEntityMut
Methods:insert_if
insert_if_else
insert_some
insert_some_or
ConditionalChildBuilderExt
forEntityCommands
Methods:with_children_if
ConditionalWorldChildBuilderExt
forEntityMut
Methods:with_children_if
Supports Bevy 0.9
Usage
To add to a project either use:
cargo add conditional_commands
or manually add to your Cargo.toml:
[dependencies]
conditional_commands = "0.9.0"
A Motivating But Contrived ECS Fizz-Buzz Example
use bevy::prelude::*;
use conditional_commands::*;
#[derive(Component)]
struct FizzBuzzer;
#[derive(Component)]
struct Number(usize);
#[derive(Component)]
struct Fizz;
#[derive(Component)]
struct Buzz;
fn fizz_buzz<const N: usize>(
mut commands: Commands
) {
for n in 1 ..= N {
let mut entity_commands = commands.spawn(FizzBuzzer);
match (n % 3, n % 5) {
(0, 0) => { entity_commands.insert((Fizz, Buzz)); },
(0, _) => { entity_commands.insert(Fizz); },
(_, 0) => { entity_commands.insert(Buzz); },
_ => { entity_commands.insert(Number(n)); }
}
}
}
With Conditional Commands the intermediate EntityCommands binding in no longer required.
fn fizz_buzz<const N: usize>(
mut commands: Commands
) {
for n in 1 ..= N {
commands
.spawn(FizzBuzzer)
.insert_if(0 < n % 3 && 0 < n % 5, || Number(n))
.insert_if(n % 3 == 0, || Fizz)
.insert_if(n % 5 == 0, || Buzz);
}
}
ConditionalInsertBundleExt
is also implemented for EntityMut
:
#[derive(Component)]
struct Even;
#[derive(Component)]
struct Odd;
fn exclusive_system(world: &mut World) {
for n in 0..10 {
world.spawn_empty().insert_if_else(n % 2 == 0, || Even, || Odd);
}
}
Bundles passed to the _else
/_or
methods don't need to be the same type,
as seen in the above example with the Even
and Odd
components.
Use insert_some
to insert the inner value of an optional bundle, if present.
commands.spawn(MyBundle)
.insert_some(Some(OtherBundle::default()))
.insert_some_or(None::<MyThing>, AlternativeThing::default);
Examples
cargo run --example exclusive
cargo run --example fizz_buzz
cargo run --example insert_if
cargo run --example insert_if_2
cargo run --example with_children_if
Notes
-
I haven't done any benchmarking. For performance critical systems it should be better to spawn entire bundles at once.
-
Earlier versions of this crate have both eager and lazy versions of each insertion method. I'm not sure the eager versions had any advantages (beyond no
||
), so they are gone. -
I wasn't able to quite finesse the lifetimes to get a single generic child builder trait for both
EntityCommands
andEntityMut
.
Dependencies
~18–34MB
~565K SLoC