On this page
Query grouping
Grouping keeps matching archetypes with the same integer key together. Use it when each group needs expensive setup that should not run for every entity.
local Kind <const> = {
Textured = 1,
Shaded = 2,
Flat = 3,
}
local renderables <const> = world:newQuery({
include = {tecs.Transform2D, tecs.gfx.Renderable2D},
groupBy = function(archetype: tecs.ecs.Archetype): integer
if archetype:get(tecs.gfx.Sprite) then
return Kind.Textured
end
if archetype:get(tecs.gfx.Material) then
return Kind.Shaded
end
return Kind.Flat
end,
})Tecs computes the key when an archetype begins matching and caches it. groupBy must therefore depend only on the component signature, never on row values or mutable external state.
Group traversal
groups() yields active keys in sorted order. group(key) yields the nonempty archetypes for one key:
for kind in renderables:groups() do
beginBatch(kind)
for archetype, length in renderables:group(kind) do
local transforms <const> = archetype:get(tecs.Transform2D)
for row = 1, length do
drawRow(transforms[row])
end
end
endBatch()
endAn empty group disappears from groups() until one of its archetypes fills again.
getGroup(archetype) returns the cached key. getGroupCount(key) sums the entities in that group without visiting rows, which supports two-pass buffer layout:
local offset = 0
local offsets: {integer: integer} = {}
for key in renderables:groups() do
offsets[key] = offset
offset = offset + renderables:getGroupCount(key)
endquery:iter(). Use a separate cursor for any traversal that may stop early, and close it after the loop. Nested grouped traversals need one cursor each.