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
.
- Note that this closure is always treated as a
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 forecs_find!
queries, but useful forecs_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, ...>
: SeeOneOf
.
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);
}