mirror of
https://github.com/Ukendio/jecs.git
synced 2025-04-25 09:30:03 +00:00
Specialize iterator
This commit is contained in:
parent
c486e85d43
commit
7476952f89
2 changed files with 212 additions and 121 deletions
312
src/init.luau
312
src/init.luau
|
@ -739,7 +739,6 @@ do
|
||||||
local lastArchetype: number
|
local lastArchetype: number
|
||||||
local archetype: Archetype
|
local archetype: Archetype
|
||||||
local queryOutput: { any }
|
local queryOutput: { any }
|
||||||
local queryLength: number
|
|
||||||
local entities: { number }
|
local entities: { number }
|
||||||
local i: number
|
local i: number
|
||||||
|
|
||||||
|
@ -747,7 +746,7 @@ do
|
||||||
local ids: { number }
|
local ids: { number }
|
||||||
local columns
|
local columns
|
||||||
|
|
||||||
local A, B, C, D, E, F, G, H
|
local A, B, C, D, E, F, G, H, I
|
||||||
local a, b, c, d, e, f, g, h
|
local a, b, c, d, e, f, g, h
|
||||||
|
|
||||||
local init
|
local init
|
||||||
|
@ -820,123 +819,193 @@ do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function world_query_iter_next(): any
|
local world_query_iter_next
|
||||||
local entityId = entities[i]
|
|
||||||
while entityId == nil do
|
|
||||||
lastArchetype += 1
|
|
||||||
archetype = compatible_archetypes[lastArchetype]
|
|
||||||
if not archetype then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
entities = archetype.entities
|
local function world_query_iter_create()
|
||||||
i = #entities
|
if not B then
|
||||||
if i == 0 then
|
function world_query_iter_next(): any
|
||||||
continue
|
local entityId = entities[i]
|
||||||
end
|
while entityId == nil do
|
||||||
entityId = entities[i]
|
lastArchetype += 1
|
||||||
columns = archetype.columns
|
archetype = compatible_archetypes[lastArchetype]
|
||||||
local records = archetype.records
|
if not archetype then
|
||||||
if not B then
|
return nil
|
||||||
a = columns[records[A]]
|
end
|
||||||
elseif not C then
|
|
||||||
a = columns[records[A]]
|
|
||||||
b = columns[records[B]]
|
|
||||||
elseif not D then
|
|
||||||
a = columns[records[A]]
|
|
||||||
b = columns[records[B]]
|
|
||||||
c = columns[records[C]]
|
|
||||||
elseif not E then
|
|
||||||
a = columns[records[A]]
|
|
||||||
b = columns[records[B]]
|
|
||||||
c = columns[records[C]]
|
|
||||||
d = columns[records[D]]
|
|
||||||
elseif not F then
|
|
||||||
a = columns[records[A]]
|
|
||||||
b = columns[records[B]]
|
|
||||||
c = columns[records[C]]
|
|
||||||
d = columns[records[D]]
|
|
||||||
e = columns[records[E]]
|
|
||||||
elseif not G then
|
|
||||||
a = columns[records[A]]
|
|
||||||
b = columns[records[B]]
|
|
||||||
c = columns[records[C]]
|
|
||||||
d = columns[records[D]]
|
|
||||||
e = columns[records[E]]
|
|
||||||
f = columns[records[F]]
|
|
||||||
elseif not H then
|
|
||||||
a = columns[records[A]]
|
|
||||||
b = columns[records[B]]
|
|
||||||
c = columns[records[C]]
|
|
||||||
d = columns[records[D]]
|
|
||||||
e = columns[records[E]]
|
|
||||||
f = columns[records[F]]
|
|
||||||
g = columns[records[G]]
|
|
||||||
elseif H then
|
|
||||||
a = columns[records[A]]
|
|
||||||
b = columns[records[B]]
|
|
||||||
c = columns[records[D]]
|
|
||||||
e = columns[records[E]]
|
|
||||||
f = columns[records[F]]
|
|
||||||
g = columns[records[G]]
|
|
||||||
h = columns[records[H]]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local row = i
|
entities = archetype.entities
|
||||||
i-=1
|
i = #entities
|
||||||
|
if i == 0 then
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
entityId = entities[i]
|
||||||
|
columns = archetype.columns
|
||||||
|
local records = archetype.records
|
||||||
|
a = columns[records[A]]
|
||||||
|
end
|
||||||
|
|
||||||
if queryLength == 1 then
|
local row = i
|
||||||
return entityId, a[row]
|
i-=1
|
||||||
elseif queryLength == 2 then
|
|
||||||
return entityId, a[row], b[row]
|
|
||||||
elseif queryLength == 3 then
|
|
||||||
return entityId, a[row], b[row], c[row]
|
|
||||||
elseif queryLength == 4 then
|
|
||||||
return entityId, a[row], b[row], c[row], d[row]
|
|
||||||
elseif queryLength == 5 then
|
|
||||||
return entityId,
|
|
||||||
a[row],
|
|
||||||
b[row],
|
|
||||||
c[row],
|
|
||||||
d[row],
|
|
||||||
e[row]
|
|
||||||
elseif queryLength == 6 then
|
|
||||||
return entityId,
|
|
||||||
a[row],
|
|
||||||
b[row],
|
|
||||||
c[row],
|
|
||||||
d[row],
|
|
||||||
e[row],
|
|
||||||
f[row]
|
|
||||||
elseif queryLength == 7 then
|
|
||||||
return entityId,
|
|
||||||
a[row],
|
|
||||||
b[row],
|
|
||||||
c[row],
|
|
||||||
d[row],
|
|
||||||
e[row],
|
|
||||||
f[row],
|
|
||||||
g[row]
|
|
||||||
elseif queryLength == 8 then
|
|
||||||
return entityId,
|
|
||||||
a[row],
|
|
||||||
b[row],
|
|
||||||
c[row],
|
|
||||||
d[row],
|
|
||||||
e[row],
|
|
||||||
f[row],
|
|
||||||
g[row],
|
|
||||||
h[row]
|
|
||||||
end
|
|
||||||
|
|
||||||
local field = archetype.records
|
return entityId, a[row]
|
||||||
for j, id in ids do
|
end
|
||||||
queryOutput[j] = columns[field[id]][row]
|
elseif not C then
|
||||||
end
|
function world_query_iter_next(): any
|
||||||
|
local entityId = entities[i]
|
||||||
|
while entityId == nil do
|
||||||
|
lastArchetype += 1
|
||||||
|
archetype = compatible_archetypes[lastArchetype]
|
||||||
|
if not archetype then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
return entityId, unpack(queryOutput, 1, queryLength)
|
entities = archetype.entities
|
||||||
end
|
i = #entities
|
||||||
|
if i == 0 then
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
entityId = entities[i]
|
||||||
|
columns = archetype.columns
|
||||||
|
local records = archetype.records
|
||||||
|
a = columns[records[A]]
|
||||||
|
b = columns[records[B]]
|
||||||
|
end
|
||||||
|
|
||||||
|
local row = i
|
||||||
|
i-=1
|
||||||
|
|
||||||
|
return entityId, a[row], b[row]
|
||||||
|
end
|
||||||
|
elseif not D then
|
||||||
|
function world_query_iter_next(): any
|
||||||
|
local entityId = entities[i]
|
||||||
|
while entityId == nil do
|
||||||
|
lastArchetype += 1
|
||||||
|
archetype = compatible_archetypes[lastArchetype]
|
||||||
|
if not archetype then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
entities = archetype.entities
|
||||||
|
i = #entities
|
||||||
|
if i == 0 then
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
entityId = entities[i]
|
||||||
|
columns = archetype.columns
|
||||||
|
local records = archetype.records
|
||||||
|
a = columns[records[A]]
|
||||||
|
b = columns[records[B]]
|
||||||
|
c = columns[records[C]]
|
||||||
|
end
|
||||||
|
|
||||||
|
local row = i
|
||||||
|
i-=1
|
||||||
|
|
||||||
|
return entityId, a[row], b[row], c[row]
|
||||||
|
end
|
||||||
|
elseif not E then
|
||||||
|
function world_query_iter_next(): any
|
||||||
|
local entityId = entities[i]
|
||||||
|
while entityId == nil do
|
||||||
|
lastArchetype += 1
|
||||||
|
archetype = compatible_archetypes[lastArchetype]
|
||||||
|
if not archetype then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
entities = archetype.entities
|
||||||
|
i = #entities
|
||||||
|
if i == 0 then
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
entityId = entities[i]
|
||||||
|
columns = archetype.columns
|
||||||
|
local records = archetype.records
|
||||||
|
a = columns[records[A]]
|
||||||
|
b = columns[records[B]]
|
||||||
|
c = columns[records[C]]
|
||||||
|
d = columns[records[D]]
|
||||||
|
end
|
||||||
|
|
||||||
|
local row = i
|
||||||
|
i-=1
|
||||||
|
|
||||||
|
|
||||||
|
return entityId, a[row], b[row], c[row], d[row]
|
||||||
|
end
|
||||||
|
else
|
||||||
|
function world_query_iter_next(): any
|
||||||
|
local entityId = entities[i]
|
||||||
|
while entityId == nil do
|
||||||
|
lastArchetype += 1
|
||||||
|
archetype = compatible_archetypes[lastArchetype]
|
||||||
|
if not archetype then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
entities = archetype.entities
|
||||||
|
i = #entities
|
||||||
|
if i == 0 then
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
entityId = entities[i]
|
||||||
|
columns = archetype.columns
|
||||||
|
local records = archetype.records
|
||||||
|
|
||||||
|
if not F then
|
||||||
|
a = columns[records[A]]
|
||||||
|
b = columns[records[B]]
|
||||||
|
c = columns[records[C]]
|
||||||
|
d = columns[records[D]]
|
||||||
|
e = columns[records[E]]
|
||||||
|
elseif not G then
|
||||||
|
a = columns[records[A]]
|
||||||
|
b = columns[records[B]]
|
||||||
|
c = columns[records[C]]
|
||||||
|
d = columns[records[D]]
|
||||||
|
e = columns[records[E]]
|
||||||
|
f = columns[records[F]]
|
||||||
|
elseif not H then
|
||||||
|
a = columns[records[A]]
|
||||||
|
b = columns[records[B]]
|
||||||
|
c = columns[records[C]]
|
||||||
|
d = columns[records[D]]
|
||||||
|
e = columns[records[E]]
|
||||||
|
f = columns[records[F]]
|
||||||
|
g = columns[records[G]]
|
||||||
|
elseif H then
|
||||||
|
a = columns[records[A]]
|
||||||
|
b = columns[records[B]]
|
||||||
|
c = columns[records[D]]
|
||||||
|
e = columns[records[E]]
|
||||||
|
f = columns[records[F]]
|
||||||
|
g = columns[records[G]]
|
||||||
|
h = columns[records[H]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local row = i
|
||||||
|
i-=1
|
||||||
|
|
||||||
|
if not F then
|
||||||
|
return entityId, a[row], b[row], c[row], d[row], e[row]
|
||||||
|
elseif not G then
|
||||||
|
return entityId, a[row], b[row], c[row], d[row], e[row], f[row]
|
||||||
|
elseif not H then
|
||||||
|
return entityId, a[row], b[row], c[row], d[row], e[row], f[row], g[row]
|
||||||
|
elseif not I then
|
||||||
|
return entityId, a[row], b[row], c[row], d[row], e[row], f[row], g[row], h[row]
|
||||||
|
end
|
||||||
|
|
||||||
|
local field = archetype.records
|
||||||
|
for j, id in ids do
|
||||||
|
queryOutput[j] = columns[field[id]][row]
|
||||||
|
end
|
||||||
|
|
||||||
|
return entityId, unpack(queryOutput)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local function world_query_without(self, ...)
|
local function world_query_without(self, ...)
|
||||||
local withoutComponents = { ... }
|
local withoutComponents = { ... }
|
||||||
|
@ -977,27 +1046,27 @@ do
|
||||||
local columns = archetype.columns
|
local columns = archetype.columns
|
||||||
local tr = archetype.records
|
local tr = archetype.records
|
||||||
for row in archetype.entities do
|
for row in archetype.entities do
|
||||||
if queryLength == 1 then
|
if not B then
|
||||||
local va = columns[tr[A]]
|
local va = columns[tr[A]]
|
||||||
local pa = fn(va[row])
|
local pa = fn(va[row])
|
||||||
|
|
||||||
va[row] = pa
|
va[row] = pa
|
||||||
elseif queryLength == 2 then
|
elseif not C then
|
||||||
local va = columns[tr[A]]
|
local va = columns[tr[A]]
|
||||||
local vb = columns[tr[B]]
|
local vb = columns[tr[B]]
|
||||||
|
|
||||||
va[row], vb[row] = fn(va[row], vb[row])
|
va[row], vb[row] = fn(va[row], vb[row])
|
||||||
elseif queryLength == 3 then
|
elseif not D then
|
||||||
local va = columns[tr[A]]
|
local va = columns[tr[A]]
|
||||||
local vb = columns[tr[B]]
|
local vb = columns[tr[B]]
|
||||||
local vc = columns[tr[C]]
|
local vc = columns[tr[C]]
|
||||||
|
|
||||||
va[row], vb[row], vc[row] = fn(va[row], vb[row], vc[row])
|
va[row], vb[row], vc[row] = fn(va[row], vb[row], vc[row])
|
||||||
elseif queryLength == 4 then
|
elseif not E then
|
||||||
local va = columns[tr[A]]
|
local va = columns[tr[A]]
|
||||||
local vb = columns[tr[B]]
|
local vb = columns[tr[B]]
|
||||||
local vc = columns[tr[C]]
|
local vc = columns[tr[C]]
|
||||||
local vd = columns[tr[D]]
|
local vd = columns[tr[D]]
|
||||||
|
|
||||||
va[row], vb[row], vc[row], vd[row] = fn(
|
va[row], vb[row], vc[row], vd[row] = fn(
|
||||||
va[row], vb[row], vc[row], vd[row])
|
va[row], vb[row], vc[row], vd[row])
|
||||||
|
@ -1088,7 +1157,8 @@ do
|
||||||
local length = 0
|
local length = 0
|
||||||
|
|
||||||
local components = { ... } :: any
|
local components = { ... } :: any
|
||||||
A, B, C, D, E, F, G, H = ...
|
A, B, C, D, E, F, G, H, I = ...
|
||||||
|
|
||||||
local archetypes = world.archetypes
|
local archetypes = world.archetypes
|
||||||
|
|
||||||
local firstArchetypeMap: ArchetypeMap
|
local firstArchetypeMap: ArchetypeMap
|
||||||
|
@ -1131,6 +1201,8 @@ do
|
||||||
init = false
|
init = false
|
||||||
ids = components
|
ids = components
|
||||||
|
|
||||||
|
world_query_iter_create()
|
||||||
|
|
||||||
return it
|
return it
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -516,8 +516,27 @@ TEST("world:query()", function()
|
||||||
CHECK(count == 2)
|
CHECK(count == 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
do CASE "despawning while iterating"
|
||||||
|
local world = jecs.World.new()
|
||||||
|
local A = world:component()
|
||||||
|
local B = world:component()
|
||||||
|
|
||||||
|
local e1 = world:entity()
|
||||||
|
local e2 = world:entity()
|
||||||
|
world:add(e1, A)
|
||||||
|
world:add(e2, A)
|
||||||
|
world:add(e2, B)
|
||||||
|
|
||||||
|
local count = 0
|
||||||
|
for id in world:query(A) do
|
||||||
|
world:clear(id)
|
||||||
|
count += 1
|
||||||
|
end
|
||||||
|
CHECK(count == 2)
|
||||||
|
end
|
||||||
|
|
||||||
do CASE "iterator invalidation"
|
do CASE "iterator invalidation"
|
||||||
do CASE "adding"
|
do CASE "adding"
|
||||||
SKIP()
|
SKIP()
|
||||||
local world = jecs.World.new()
|
local world = jecs.World.new()
|
||||||
local A = world:component()
|
local A = world:component()
|
||||||
|
|
Loading…
Reference in a new issue