Expand description
Queries: picking entities by the components they carry.
A query is a type, not a value. The components to hand out are written in the turbofish, so the compiler checks them, and the iterator resolves them once per archetype instead of once per row.
| Item | Yields |
|---|---|
&T | the component, shared; only archetypes carrying it match |
&mut T | the component, exclusive; only archetypes carrying it match |
Option<&T> | Some when the archetype carries the component |
Option<&mut T> | Some when it carries it, exclusive |
Entity | the entity itself |
Has<T> | whether the archetype carries T, narrowing nothing |
A tuple of items asks for all of them at once and yields a tuple of their
items, and tuples nest: (&a, (&b, &c)) asks for the same three components
as (&a, &b, &c) and yields (&A, (&B, &C)). An item written &(a, b) is
one component whose type is that tuple, not two, and an item outside the
forms above fails to compile.
A query is held rather than borrowed one row at a time: crate::QueryBorrow
is what a scope hands out, it claims the components it will reach when it is
built, and the claims are released when it is dropped. Iterating it is
crate::QueryBorrow::iter.
let mut world = World::new();
world.root_scope_mut().spawn(bundle![1u32, 10.0f32]);
world.root_scope_mut().spawn(bundle![2u32, true]);
let mut query = world.root_scope().query::<&u32>();
let sum: u32 = query.iter().map(|value| *value).sum();
assert_eq!(sum, 3);
// The entity, its component, and whether it also carries a `bool`. The
// `Has<bool>` reports the answer without narrowing anything, so both spawns
// above are visited and the one without a `bool` prints `false`.
for (entity, value, has_bool) in world.root_scope().query::<(Entity, &u32, Has<bool>)>().iter() {
println!("{entity:?} has {value}, and a bool: {has_bool}");
}
// Tuples nest, so this asks for the same components and yields
// `(&u32, (&f32,))` instead of `(&u32, &f32)`.
for (value, (height,)) in world.root_scope().query::<(&u32, (&f32,))>().iter() {
let _ = (value, height);
}A query visits archetypes in creation order and rows in storage order, so iteration is deterministic. It skips the rows the scope cannot see and the treeβs two scaffolding entities.
Narrowing which archetypes a query visits, including by a component set only
known at run time, is crate::QueryBorrow::by.
Β§Queries of your own
A row that carries more than a tuple impl covers, or one whose components are
worth naming, is declared with the crate::query! macro:
pub struct Health(pub i32);
pub struct Armor(pub i32);
pub struct Mana(pub i32);
query! {
/// Everything one combatant is made of.
pub struct Combatant<'a> {
pub entity: Entity,
pub health: &'a mut Health,
pub armor: &'a Armor,
/// `None` for a row that carries no mana.
pub mana: Option<&'a Mana>,
pub has_armor: Has<Armor>,
}
}
let mut world = World::new();
world.root_scope_mut().spawn(bundle![Health(10), Armor(2)]);
for row in world.root_scope().query::<Combatant>().iter() {
row.health.0 -= row.armor.0;
assert!(row.has_armor);
assert!(row.mana.is_none());
}The declaration is one row: the macro derives the item struct and the
Query impl from it. No unsafe is involved on the callerβs side, and
the claims the query makes are exactly the fields it declares: a component is
claimed by asking the PlanBuilder for it, so there is no second list
that could disagree with what the query actually reaches.
Re-exportsΒ§
use core::any::TypeId;πuse core::cell::UnsafeCell;πuse core::marker::PhantomData;πuse crate::archetype::Archetype;πuse crate::borrow::Claims;πuse crate::entity::Entity;πuse crate::world::World;πpub use iter::QueryIter;
ModulesΒ§
MacrosΒ§
- impl_
tuple π
StructsΒ§
- Col
- A claimed column, shared.
- ColMut
- A claimed column, exclusive.
- Has
- Yields whether the archetype carries
T. - Plan
Builder - What one archetype offers, and what a query asks of it while resolving its plan.
- Query
Borrow - What a scope hands out for a query: the claims, and the way to iterate them.
- Query
One - What a scope hands out for a query over one entity.
EnumsΒ§
- Mode
- Whether a component is reached shared or exclusive.
TraitsΒ§
- Archetype
Filter - Narrows the archetypes a query visits.
- Query
- What to fetch from every entity a query matches.
Type AliasesΒ§
- Ask π
- One component a query reaches, and how.