Macro gecs::ecs_find

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

Finds a single entity in an ECS world and performs an operation on it, if found.

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

The ecs_find! macro finds a single entity in an ECS world and performs an operation on it, if that entity is found in archetype storage. It takes the following arguments:

  • world: The world (as an expression) that you want to query.
  • entity: The entity handle you want to look up. May be an Entity<A>, EntityRaw<A>, EntityAny, or EntityRawAny handle.
  • |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.

The ecs_find! macro returns an Option type of the return value of the closure (which may be Option<()> if the closure has no return). The value will be Some if the entity was found, or None otherwise.

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);
}

// If you need to use a non-mut reference, see the ecs_find_borrow! macro.
fn add_three(world: &mut EcsWorld, entity: Entity<ArchFoo>) -> bool {
    // The result will be true if the entity was found and operated on.
    ecs_find!(world, entity, |comp_a: &mut CompA| { comp_a.0 += 3; }).is_some()
}

fn add_three_any(world: &mut EcsWorld, entity: EntityAny) -> bool {
    // The query syntax is the same for both Entity<A> and EntityAny.
    ecs_find!(world, entity, |comp_a: &mut CompA| { comp_a.0 += 3; }).is_some()
}

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

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

    assert!(ecs_find!(world, entity_a, |c: &CompA| assert_eq!(c.0, 0)).is_some());
    assert!(ecs_find!(world, entity_b, |c: &CompA| assert_eq!(c.0, 0)).is_some());

    assert!(add_three(&mut world, entity_a));
    assert!(add_three_any(&mut world, entity_b.into())); // Convert to an EntityAny

    assert!(ecs_find!(world, entity_a, |c: &CompA| assert_eq!(c.0, 3)).is_some());
    assert!(ecs_find!(world, entity_b, |c: &CompA| assert_eq!(c.0, 3)).is_some());
}