Attribute Macro legion_codegen::system

source · []
#[system]
Expand description

Wraps a function in a system, and generates a new function which constructs that system.

There are three types of systems: simple (default), for_each and par_for_each. By default, the system macro will create a new function named <attributed_fn_name>_system which can be called to construct the system.

Examples

By default, the wrapped function is called once each time the system runs.

#[system]
fn hello_world() {
   println!("hello world");
}

Schedule::builder()
    .add_system(hello_world_system())
    .build();

The function can request resources with reference parameters marked with the #[resource] attribute.

#[system]
fn hello_world(#[resource] person: &Person) {
   println!("hello, {}", person.name);
}

Systems can also request a world or command buffer.

#[system]
fn create_entity(cmd: &mut CommandBuffer) {
   cmd.push((1usize, false, Person { name: "Jane Doe" }));
}

Systems can declare access to component types with the #[read_component] and #[write_component] attributes.

#[system]
#[read_component(usize)]
#[write_component(bool)]
fn run_query(world: &mut SubWorld) {
    let mut query = <(&usize, &mut bool)>::query();
    for (a, b) in query.iter_mut(world) {
        println!("{} {}", a, b);
    }
}

Systems can declare queries. The above can also be written as:

#[system]
fn run_query(world: &mut SubWorld, query: &mut Query<(&usize, &mut bool)>) {
    for (a, b) in query.iter_mut(world) {
        println!("{} {}", a, b);
    }
}

for_each and par_for_each system types can be used to implement the query for you. References will be interpreted as Read<T> and Write<T>, while options of references (e.g. Option<&Position>) will be interpreted as TryRead<T> and TryWrite<T>. You can request the entity ID via a &Entity parameter.

#[system(for_each)]
fn update_positions(pos: &mut Position, vel: &Velocity, #[resource] time: &Time) {
    pos.x += vel.x * time.seconds;
}

for_each and par_for_each systems can request attitional filters for their query via the #[filter] attribute.

#[system(for_each)]
#[filter(maybe_changed::<Position>())]
fn update_positions(pos: &mut Position, vel: &Velocity, #[resource] time: &Time) {
    pos.x += vel.x * time.seconds;
}

Systems can contain their own state. Add a reference marked with the #[state] parameter to your function. This state will be initialized when you construct the system.

#[system]
fn stateful(#[state] counter: &mut usize) {
    *counter += 1;
    println!("state: {}", counter);
}

Schedule::builder()
     // initialize state when you construct the system
    .add_system(stateful_system(5_usize))
    .build();

Systems can contain generic parameters.

#[system(for_each)]
fn print_component<T: Component + Debug>(component: &T) {
    println!("{:?}", component);
}

Schedule::builder()
     // supply generic parameters when constructing the system
    .add_system(print_component_system::<Position>())
    .build();