Macro gecs::ecs_iter

source ·
macro_rules! ecs_iter {
    (...) => { ... };
}
Expand description

Iterates over all entities across all archetypes that match the given component bounds.

ecs_iter!(world, |comp_a: &CompA, comp_b: &mut CompB, ...| { ... });

The ecs_iter! macro iterates over all entities matching the conditions of its closure and executes that closure on those entities’ data. It takes the following arguments:

  • world: The world (as an expression) that you want to query.
  • |comp_a: &CompA, comp_b: &mut CompB, ...| { ... }: A closure containing the operation to perform on the current entity’s data. The parameters of the closure determine what components for the entity that this query will access and how. Any component can be accessed as &Component or &mut Component. The query will only check archetypes that are known at compile-time to have all components requested in the query closure.
    • Note that this closure is always treated as a &mut FnMut.

Special Arguments

Query closure arguments can have the following special types:

  • &Entity<A>/&EntityAny: Returns the current entity being accessed by the closure. This is somewhat redundant for ecs_find! queries, but useful for ecs_iter! loops. Note that this is always read-only – the entity can never be accessed mutably.
  • &EntityRaw<A>/EntityRawAny: As above, but using raw handles to the direct position of the entity in its archetype. This can accelerate lookup, but may be invalidated if the archetype changes. See [EntityRawAny] for more information.
  • &Entity<_>/&EntityRaw<_>: When used with the special _ wildcard, each execution of this query will return a typed (raw) entity handle for the exact archetype matched for this specific execution. This can be used to optimize switched behavior by type.
  • &OneOf<A, B, ...> or &mut OneOf<A, B, ...>: See OneOf.

In query closures, a special MatchedArchetype type alias is set to the currently matched archetype being accessed during this execution of the closure. This can be used for generic operations.

Example

use gecs::prelude::*;

pub struct CompA(pub u32);
pub struct CompB(pub u32);
pub struct CompC(pub u32);

ecs_world! {
    ecs_archetype!(ArchFoo, 100, CompA, CompB);
    ecs_archetype!(ArchBar, 100, CompA, CompC);
}

fn main() {
    let mut world = EcsWorld::default();

    let mut vec_a = Vec::<EntityAny>::new();
    let mut vec_b = Vec::<EntityAny>::new();
    let mut vec_c = Vec::<EntityAny>::new();

    let entity_a = world.create::<ArchFoo>((CompA(0), CompB(0)));
    let entity_b = world.create::<ArchBar>((CompA(0), CompC(0)));

    // This iterates both ArchFoo and ArchBar since both have a CompA.
    ecs_iter!(world, |entity: &EntityAny, a: &mut CompA| {
        vec_a.push(*entity);
        a.0 += 3; // Add 3 to both entities
    });
    assert!(vec_a == vec![entity_a.into(), entity_b.into()]);

    // Even though both ArchFoo and ArchBar have a CompA, only ArchFoo can
    // provide Entity<ArchFoo> handles, so this will only iterate that one.
    ecs_iter!(world, |entity: &Entity<ArchFoo>, a: &mut CompA| {
        vec_b.push((*entity).into());
        a.0 += 3; // Add 3 to entity_a
    });
    assert!(vec_b == vec![entity_a.into()]);

    // This iterates only ArchBar since ArchFoo does not have a CompC.
    ecs_iter!(world, |entity: &EntityAny, a: &mut CompA, _: &CompC| {
        vec_c.push(*entity);
        a.0 += 3; // Add 3 to entity_b
    });
    assert!(vec_c == vec![entity_b.into()]);

    let mut sum = 0;
    ecs_iter!(world, |a: &CompA| {
        sum += a.0;
    });
    assert_eq!(sum, 12);
}