Skip to content

Conditional component, bundle, and child insertion without the need for an intermediate EntityCommands binding

License

MIT, Unknown licenses found

Licenses found

MIT
LICENSE
Unknown
LICENSE-APACHE
Notifications You must be signed in to change notification settings

ickshonpe/Conditional_Commands

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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 for EntityCommands and EntityMut
    Methods:
    • insert_if
    • insert_if_else
    • insert_some
    • insert_some_or
  • ConditionalChildBuilderExt for EntityCommands
    Methods:
    • with_children_if
  • ConditionalWorldChildBuilderExt for EntityMut
    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 and EntityMut.

About

Conditional component, bundle, and child insertion without the need for an intermediate EntityCommands binding

Topics

Resources

License

MIT, Unknown licenses found

Licenses found

MIT
LICENSE
Unknown
LICENSE-APACHE

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages