bevy_kot_ecs

Crates.iobevy_kot_ecs
lib.rsbevy_kot_ecs
version0.11.0
sourcesrc
created_at2023-11-07 20:40:27.411376
updated_at2024-01-11 03:58:19.675812
descriptionECS utilities for bevy_kot
homepage
repositoryhttps://github.com/UkoeHB/bevy_kot
max_upload_size
id1028424
size122,473
(UkoeHB)

documentation

README

ECS

[ReactCommands] makes it easy to register and unregister ECS hooks. Reactors are most useful when you need to pass information (e.g. entity IDs) into a reaction system.

A reactor will run in the first apply_deferred after its reaction trigger is detected. If a reactor triggers other reactors, they will run immediately after the initial reactor (until the entire tree of reactions terminates). Recursive reactions are currently not supported.

Registering Reactors

Reactors are registered with [ReactCommands]. You must specify a 'reaction trigger':

fn setup(mut rcommands: ReactCommands)
{
    rcommands.on(resource_mutation::<A>(),
        |a: ReactRes<A>|
        {
            //...
        }
    );
}

The available reaction triggers are:

  • [resource_mutation<R: ReactResource>()]
  • [insertion<C: ReactComponent>()]
  • [mutation<C: ReactComponent>()]
  • [removal<C: ReactComponent>()]
  • [entity_insertion<C: ReactComponent>(entity)]
  • [entity_mutation<C: ReactComponent>(entity)]
  • [entity_removal<C: ReactComponent>(entity)]
  • [event<E>()]

A reactor can be associated with multiple reaction triggers:

fn setup(mut rcommands: ReactCommands)
{
    rcommands.on((resource_mutation::<A>(), entity_insertion<B>(entity)),
        move |a: ReactRes<A>, q: Query<&B>|
        {
            q.get(entity);
            //...etc.
        }
    );
}

Revoking Reactors

Reactors can be revoked with [RevokeToken]s obtained on registration.

let token = rcommands.on(resource_mutation::<A>(), || { todo!(); });
rcommands.revoke(token);

Trigger Type: Resource Mutation

Add a reactive resource to your app:

#[derive(ReactResource)]
struct Counter(u32);

app.add_plugins(ReactPlugin)
    .add_react_resource(Counter);

Mutate the resource:

fn increment(mut rcommands: ReactCommands, mut counter: ReactResMut<Counter>)
{
    counter.get_mut(&mut rcommands).0 += 1;
}

React to the resource mutation:

fn setup(mut rcommands: ReactCommands)
{
    rcommands.on(resource_mutation::<Counter>(),
        |counter: ReactRes<Counter>|
        {
            println!("count: {}", counter.0);
        }
    );
}

Trigger Type: Component Insertion/Mutation/Removal

#[derive(ReactComponent)]
struct Health(u16);

fn setup(mut rcommands: ReactCommands)
{
    let entity = rcommands.commands().spawn_empty().id();
    rcommands.insert(entity, Health(0u16));

    rcommands.on(entity_mutation::<Health>(entity)
        move |q: Query<&React<Health>>|
        {
            let health = q.get(entity).unwrap();
            println!("health: {}", health.0);
        }
    );
}

fn add_health(mut rcommands: ReactCommands, mut q: Query<&mut React<Health>>)
{
    for health in q.iter_mut()
    {
        health.get_mut(&mut rcommands).0 += 10;
    }
}

Entity-agnostic triggers (insertion<C>(), mutation<C>(), removal<C>()) can only be grouped with each other, since their reactor requires an In<Entity> system parameter:

#[derive(ReactComponent)]
struct A;
#[derive(ReactComponent)]
struct B;

rcommands.on((insertion::<A>(), removal::<B>()),
    |In(entity): In<Entity>, a: Query<(Option<&React<A>>, Option<&React<B>>)>|
    {
        //...
    }
);

Trigger Type: Events

Register a react event:

app.add_react_event::<u32>();

Send an event:

rcommands.send(0u32);

React to the event, using the [ReactEventReader] to access event data:

rcommands.on(event::<u32>(),
    |mut events: ReactEventReader<u32>|
    {
        for event in events.iter()
        {
            println!("react u32: {}", event);
        }
    }
);

Trigger Type: Despawns

React to despawns with the [ReactCommands::on_despawn()] method:

rcommands.on_despawn(entity, move || println!("entity despawned: {}", entity));

One-off Reactors

If you only want a reactor to run once, use [ReactCommands::once()]:

let entity = rcommands.commands().spawn(Player);
rcommands.once(event::<ResetEverything>(),
    move |world: &mut World|
    {
        world.despawn(entity);
    }
);
Commit count: 141

cargo fmt