std/ecs/query

std/ecs/src/query.trb

fn query

fn query<Space, Component>(space: Space): Iterate<(Entity, Component)> where Space: Store<Component>

Every entity that has a Component in space, with the value, in the order of the column.

A query answers an Iterate of tuples and holds a copy of the column for as long as it is walked: the loop may spawn, attach and detach on the live group, and none of it reaches the rows being visited (ECS.md, "Structural change while a query runs").

Examples

use Column from "std/ecs"

type Health with Equals, Show {
  points: Int
}

type Vitals {
  var health: Column<Health> = Column()
}

extend Vitals with Store<Health> {
  fn column(): Column<Health> {
    health
  }

  var fn attach(entity: Entity, value: Health) {
    health.put entity, value
  }

  var fn detach(entity: Entity) {
    health.remove entity
  }
}

var vitals = Vitals()
vitals.attach Entity(0), Health(3)
vitals.attach Entity(1), Health(5)
var total = 0
for (entity, health) in query<Vitals, Health>(vitals) {
  total = total + health.points + entity.index
}
assert(total == 9)

fn pairs

fn pairs<FirstSpace, SecondSpace, First, Second>(first: FirstSpace, second: SecondSpace): Iterate<(Entity, First, Second)> where FirstSpace: Store<First>, SecondSpace: Store<Second>

Every entity that has a First in first and a Second in second, in the order of the first column; an entity missing from the second drops out. The with-filter of other engines is one more column here, and the without-filter is pairs(...).filter { !other.column().has(_.0) }.

The order is a function of the operations that built the columns: the column of the first group is walked and the second is only probed, so which group drives the query is the order the caller writes them in.

fn triples

fn triples<FirstSpace, SecondSpace, ThirdSpace, First, Second, Third>(first: FirstSpace, second: SecondSpace, third: ThirdSpace): Iterate<(Entity, First, Second, Third)> where FirstSpace: Store<First>, SecondSpace: Store<Second>, ThirdSpace: Store<Third>

Every entity that has a First, a Second and a Third, in the order of the first column. See pairs.

fn quadruples

fn quadruples<FirstSpace, SecondSpace, ThirdSpace, FourthSpace, First, Second, Third, Fourth>(first: FirstSpace, second: SecondSpace, third: ThirdSpace, fourth: FourthSpace): Iterate<(Entity, First, Second, Third, Fourth)> where FirstSpace: Store<First>, SecondSpace: Store<Second>, ThirdSpace: Store<Third>, FourthSpace: Store<Fourth>

Every entity that has a First, a Second, a Third and a Fourth, in the order of the first column. Four is where it stops: a system that reads five component types wants two queries. See pairs.