Skip to main content

Crate bevy_ergo_plugin

Crate bevy_ergo_plugin 

Source
Expand description

Macros to make building bevy plugins more ergonomic (in my opinion).

Bevy’s API puts adding a system separate from its implementation. Separatng the system’s run conditions and other system parameters from its definition adds an extra layer of indirection, harming readability and adding boilerplate (.add_system)
This crate’s purpose is to replace that API with a more ergonomic one, using attribute macros as markers for system parameters.
Not only does this allow for more readable system run conditions, but it also gives us fallible systems with logging much more cleanly, while still using bevy’s built-ins.

Putting the bevy_plugin attribute on the impl block of a struct will turn that struct into a Bevy Plugin, which registers its associated functions as systems.
If you want to add extra functionality to your plugin’s Plugin::build (like adding an asset or registering a component), the contents of any associated function named build in a bevy_plugin attributed impl block will be inserted into the generated Plugin::build implementation.

The other macros are the aforementioned parameter markers to be put on your system definitions.
For any params not included by a specific marker, you can use the sysparam marker to define custom behavior.

Multiple parameter markers on a system do stack onto a single add_system call, so you can add multiple run conditions and have it work as expected.

This crate is basically just doing code generation, so it doesn’t depend on bevy itself. It should work with any bevy version that has the functions you’re generating.

This crate has not been thoroughly tested, so there will probably be weird bugs I don’t know about.

§Example

adapted from https://github.com/bevyengine/bevy/blob/latest/examples/ecs/run_conditions.rs\

use bevy::prelude::*;
use bevy_ergo_plugin::*;

fn main() {
    println!();
    println!("For the first 2 seconds you will not be able to increment the counter");
    println!("Once that time has passed you can press space, enter, left mouse, right mouse or touch the screen to increment the counter");
    println!();

    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugin(Game)
        .run();
}
#[derive(Resource, Default)]
pub struct InputCounter(usize);

pub struct Game;
#[bevy_plugin]
impl Game {
    #[resource_exists(InputCounter)]
    #[run_if(Game::has_user_input)]
    pub fn increment_input_counter(mut counter: ResMut<InputCounter>) {
        counter.0 += 1;
    }

    #[run_if(resource_exists::<InputCounter>().and_then(
        |counter: Res<InputCounter>| counter.is_changed() && !counter.is_added()
    ))]
    pub fn print_input_counter(counter: Res<InputCounter>) {
        println!("Input counter: {}", counter.0);
    }

    #[run_if(Game::time_passed(2.0))]
    #[run_if(not(Game::time_passed(2.5)))]
    pub fn print_time_message() {
        println!(
            "It has been more than 2 seconds since the program started and less than 2.5 seconds"
        );
    }

    #[do_not_add]
    pub fn has_user_input(
        keyboard_input: Res<Input<KeyCode>>,
        mouse_button_input: Res<Input<MouseButton>>,
        touch_input: Res<Touches>,
    ) -> bool {
        keyboard_input.just_pressed(KeyCode::Space)
            || keyboard_input.just_pressed(KeyCode::Return)
            || mouse_button_input.just_pressed(MouseButton::Left)
            || mouse_button_input.just_pressed(MouseButton::Right)
            || touch_input.any_just_pressed()
    }

    #[do_not_add]
    pub fn time_passed(t: f32) -> impl FnMut(Local<f32>, Res<Time>) -> bool {
        move |mut timer: Local<f32>, time: Res<Time>| {
            *timer += time.delta_seconds();
            *timer >= t
        }
    }

    pub fn build(&self, app: &mut App) {
        app.init_resource::<InputCounter>();
    }
}

Attribute Macros§

after
system parameter marker attribute that generates
.add_system( system_name.after(arg) )
any_with_component
system parameter marker attribute that generates
.add_system( system_name.run_if(any_with_component::<arg>()) )
before
system parameter marker attribute that generates
.add_system( system_name.before(arg) )
bevy_plugin
Put this attribute on an impl block of a struct to turn the struct into a plugin where the functions in the impl block are systems. Use the marker attributes on your systems to add parameters. A function named build can be used to add custom functionality to the Plugin::build in the generated Plugin implementation.
dbg
system parameter marker attribute that generates
.add_system( system_name.pipe(system_adapter::dbg) )
do_not_add
a marker attribute to exclude a function from being added
error
system parameter marker attribute that generates
.add_system( system_name.pipe(system_adapter::error) )
ignore
system parameter marker attribute that generates
.add_system( system_name.pipe(system_adapter::ignore) )
in_base_set
system parameter marker attribute that generates
.add_system( system_name.in_base_set(arg) )
in_schedule
system parameter marker attribute that generates
.add_system( system_name.in_schedule(arg) )
in_set
system parameter marker attribute that generates
.add_system( system_name.in_set(arg) )
in_state
system parameter marker attribute that generates
.add_system( system_name.run_if(in_state(arg)) )
info
system parameter marker attribute that generates
.add_system( system_name.pipe(system_adapter::info) )
not
system parameter marker attribute that generates
.add_system( system_name.run_if(not(arg)) )
on_enter
system parameter marker attribute that generates
.add_system( system_name.in_schedule(OnEnter(arg)) )
on_event
system parameter marker attribute that generates
.add_system( system_name.run_if(on_event::<arg>()) )
on_exit
system parameter marker attribute that generates
.add_system( system_name.in_schedule(OnExit(arg)) )
on_update
system parameter marker attribute that generates
.add_system( system_name.in_set(OnUpdate(arg)) )
pipe
system parameter marker attribute that generates
.add_system( system_name.pipe(arg) )
resource_added
system parameter marker attribute that generates
.add_system( system_name.run_if(resource_added::<arg>()) )
resource_changed
system parameter marker attribute that generates
.add_system( system_name.run_if(resource_changed::<arg>()) )
resource_changed_or_removed
system parameter marker attribute that generates
.add_system( system_name.run_if(resource_changed_or_removed::<arg>()) )
resource_equals
system parameter marker attribute that generates
.add_system( system_name.run_if(resource_equals(arg)) )
resource_exists
system parameter marker attribute that generates
.add_system( system_name.run_if(resource_exists::<arg>()) )
resource_exists_and_changed
system parameter marker attribute that generates
.add_system( system_name.run_if(resource_exists_and_changed::<arg>()) )
resource_exists_and_equals
system parameter marker attribute that generates
.add_system( system_name.run_if(resource_exists_and_equals(arg)) )
resource_removed
system parameter marker attribute that generates
.add_system( system_name.run_if(resource_removed::<arg>()) )
run_if
system parameter marker attribute that generates
.add_system( system_name.run_if(arg) )
run_once
system parameter marker attribute that generates
.add_system( system_name.run_if(run_once()) )
startup
system parameter marker attribute that generates
.add_system( system_name.on_startup() )
state_changed
system parameter marker attribute that generates
.add_system( system_name.run_if(state_changed::<arg>()) )
state_exists
system parameter marker attribute that generates
.add_system( system_name.run_if(state_exists::<arg>()) )
state_exists_and_equals
system parameter marker attribute that generates
.add_system( system_name.run_if(state_exists_and_equals(arg)) )
sysparam
system parameter marker attribute that generates
.add_system( system_name.arg )
unwrap
system parameter marker attribute that generates
.add_system( system_name.pipe(system_adapter::unwrap) )
warn
system parameter marker attribute that generates
.add_system( system_name.pipe(system_adapter::warn) )