Merge branch 'main' of https://github.com/Ukendio/jecs into docs

This commit is contained in:
Ukendio 2024-07-30 21:09:45 +02:00
commit c5505f095b
5 changed files with 266 additions and 228 deletions

View file

@ -170,10 +170,14 @@ return {
end,
Functions = {
Mirror = function()
for entityId, firstComponent in mcs:query(E1, E2, E3, E4) do
Matter = function()
for entityId, firstComponent in newWorld:query(A1, A2, A3, A4) do
end
end,
ECR = function()
for entityId, firstComponent in registry2:view(B1, B2, B3, B3) do
end
end,
Jecs = function()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 42 KiB

BIN
image.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

View file

@ -750,7 +750,15 @@ do
local A, B, C, D, E, F, G, H
local a, b, c, d, e, f, g, h
local init
local drain
local function query_init(query)
if init and drain then
return
end
init = true
lastArchetype = 1
archetype = compatible_archetypes[lastArchetype]
@ -767,191 +775,193 @@ do
local records = archetype.records
if not B then
a = records[A]
a = columns[records[A]]
elseif not C then
a = records[A]
b = records[B]
a = columns[records[A]]
b = columns[records[B]]
elseif not D then
a = records[A]
b = records[B]
c = records[C]
a = columns[records[A]]
b = columns[records[B]]
c = columns[records[C]]
elseif not E then
a = records[A]
b = records[B]
c = records[C]
d = records[D]
a = columns[records[A]]
b = columns[records[B]]
c = columns[records[C]]
d = columns[records[D]]
elseif not F then
a = records[A]
b = records[B]
c = records[C]
d = records[D]
e = records[E]
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 = records[A]
b = records[B]
c = records[C]
d = records[D]
e = records[E]
f = records[F]
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 = records[A]
b = records[B]
c = records[C]
d = records[D]
e = records[E]
f = records[F]
g = records[G]
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 = records[A]
b = records[B]
c = records[C]
d = records[D]
e = records[E]
f = records[F]
g = records[G]
h = records[H]
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 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
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 B then
a = columns[records[A]]
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
i-=1
if queryLength == 1 then
return entityId, a[row]
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
for j, id in ids do
queryOutput[j] = columns[field[id]][row]
end
local records = archetype.records
if not B then
a = records[A]
elseif not C then
a = records[A]
b = records[B]
elseif not D then
a = records[A]
b = records[B]
c = records[C]
elseif not E then
a = records[A]
b = records[B]
c = records[C]
d = records[D]
elseif not F then
a = records[A]
b = records[B]
c = records[C]
d = records[D]
e = records[E]
elseif not G then
a = records[A]
b = records[B]
c = records[C]
d = records[D]
e = records[E]
f = records[F]
elseif not H then
a = records[A]
b = records[B]
c = records[C]
d = records[D]
e = records[E]
f = records[F]
g = records[G]
elseif H then
a = records[A]
b = records[B]
c = records[C]
d = records[D]
e = records[E]
f = records[F]
g = records[G]
h = records[H]
end
columns = archetype.columns
entities = archetype.entities
i = #entities
entityId = entities[i]
end
local row = i
i-=1
if queryLength == 1 then
return entityId, columns[a][row]
elseif queryLength == 2 then
return entityId, columns[a][row], columns[b][row]
elseif queryLength == 3 then
return entityId, columns[a][row], columns[b][row], columns[c][row]
elseif queryLength == 4 then
return entityId, columns[a][row], columns[b][row], columns[c][row], columns[d][row]
elseif queryLength == 5 then
return entityId,
columns[a][row],
columns[b][row],
columns[c][row],
columns[d][row],
columns[e][row]
elseif queryLength == 6 then
return entityId,
columns[a][row],
columns[b][row],
columns[c][row],
columns[d][row],
columns[e][row],
columns[f][row]
elseif queryLength == 7 then
return entityId,
columns[a][row],
columns[b][row],
columns[c][row],
columns[d][row],
columns[e][row],
columns[f][row],
columns[g][row]
elseif queryLength == 8 then
return entityId,
columns[a][row],
columns[b][row],
columns[c][row],
columns[d][row],
columns[e][row],
columns[f][row],
columns[g][row],
columns[h][row]
end
local field = archetype.records
for j, id in ids do
queryOutput[j] = columns[field[id]][row]
end
return entityId, unpack(queryOutput, 1, queryLength)
return entityId, unpack(queryOutput, 1, queryLength)
end
local function world_query_without(self, ...)
local withoutComponents = { ... }
for i = #compatible_archetypes, 1, -1 do
local archetype = compatible_archetypes[i]
local records = archetype.records
local shouldRemove = false
local withoutComponents = { ... }
for i = #compatible_archetypes, 1, -1 do
local archetype = compatible_archetypes[i]
local records = archetype.records
local shouldRemove = false
for _, componentId in withoutComponents do
if records[componentId] then
shouldRemove = true
break
for _, componentId in withoutComponents do
if records[componentId] then
shouldRemove = true
break
end
end
if shouldRemove then
local last = #compatible_archetypes
if last ~= i then
compatible_archetypes[i] = compatible_archetypes[last]
end
compatible_archetypes[last] = nil
end
end
end
if shouldRemove then
local last = #compatible_archetypes
if last ~= i then
compatible_archetypes[i] = compatible_archetypes[last]
end
compatible_archetypes[last] = nil
end
end
return self
return self
end
local function world_query_replace_values(row, columns, ...)
@ -961,72 +971,74 @@ do
end
local function world_query_replace(query, fn: (...any) -> (...any))
query_init(query)
query_init(query)
for i, archetype in compatible_archetypes do
local columns = archetype.columns
local tr = archetype.records
for row in archetype.entities do
if queryLength == 1 then
local va = columns[tr[a]]
local pa = fn(va[row])
for i, archetype in compatible_archetypes do
local columns = archetype.columns
local tr = archetype.records
for row in archetype.entities do
if queryLength == 1 then
local va = columns[tr[A]]
local pa = fn(va[row])
va[row] = pa
elseif queryLength == 2 then
local va = columns[tr[a]]
local vb = columns[tr[b]]
va[row] = pa
elseif queryLength == 2 then
local va = columns[tr[A]]
local vb = columns[tr[B]]
va[row], vb[row] = fn(va[row], vb[row])
elseif queryLength == 3 then
local va = columns[tr[a]]
local vb = columns[tr[b]]
local vc = columns[tr[c]]
va[row], vb[row] = fn(va[row], vb[row])
elseif queryLength == 3 then
local va = columns[tr[A]]
local vb = columns[tr[B]]
local vc = columns[tr[C]]
va[row], vb[row], vc[row] = fn(va[row], vb[row], vc[row])
elseif queryLength == 4 then
local va = columns[tr[a]]
local vb = columns[tr[b]]
local vc = columns[tr[c]]
local vd = columns[tr[d]]
va[row], vb[row], vc[row] = fn(va[row], vb[row], vc[row])
elseif queryLength == 4 then
local va = columns[tr[A]]
local vb = columns[tr[B]]
local vc = columns[tr[C]]
local vd = columns[tr[D]]
va[row], vb[row], vc[row], vd[row] = fn(
va[row], vb[row], vc[row], vd[row])
else
local field = archetype.records
for j, id in ids do
queryOutput[j] = columns[field[id]][row]
end
world_query_replace_values(row, columns,
fn(unpack(queryOutput)))
end
va[row], vb[row], vc[row], vd[row] = fn(
va[row], vb[row], vc[row], vd[row])
else
local field = archetype.records
for j, id in ids do
queryOutput[j] = columns[field[id]][row]
end
world_query_replace_values(row, columns,
fn(unpack(queryOutput)))
end
end
end
end
end
local function world_query_with(query, ...)
local ids = { ... }
for i = #compatible_archetypes, 1, -1 do
local archetype = compatible_archetypes[i]
local records = archetype.records
local shouldRemove = false
local ids = { ... }
for i = #compatible_archetypes, 1, -1 do
local archetype = compatible_archetypes[i]
local records = archetype.records
local shouldRemove = false
for _, id in ids do
if not records[id] then
shouldRemove = true
break
end
end
for _, id in ids do
if not records[id] then
shouldRemove = true
break
end
end
if shouldRemove then
local last = #compatible_archetypes
if last ~= i then
compatible_archetypes[i] = compatible_archetypes[last]
end
compatible_archetypes[last] = nil
end
end
if shouldRemove then
local last = #compatible_archetypes
if last ~= i then
compatible_archetypes[i] = compatible_archetypes[last]
end
compatible_archetypes[last] = nil
end
end
return query
query_init(query)
return query
end
-- Meant for directly iterating over archetypes to minimize
@ -1036,8 +1048,6 @@ do
return compatible_archetypes
end
local drain
local function world_query_drain(query)
drain = true
query_init(query)
@ -1045,9 +1055,7 @@ do
end
local function world_query_iter(query)
if not drain then
query_init(query)
end
query_init(query)
return world_query_iter_next
end
@ -1058,7 +1066,6 @@ do
return world_query_iter_next()
end
local it = {
__iter = world_query_iter,
drain = world_query_drain,
@ -1121,6 +1128,7 @@ do
end
drain = false
init = false
ids = components
return it

View file

@ -282,6 +282,32 @@ TEST("world:query()", function()
CHECK(counter == 0)
end
do CASE "query more than 8 components"
local world = jecs.World.new()
local components = {}
for i = 1, 9 do
local id = world:component()
components[i] = id
end
local e = world:entity()
for i, id in components do
world:set(e, id, 13^i)
end
for entity, a, b, c, d, e, f, g, h, i in world:query(unpack(components)) do
CHECK(a == 13^1)
CHECK(b == 13^2)
CHECK(c == 13^3)
CHECK(d == 13^4)
CHECK(e == 13^5)
CHECK(f == 13^6)
CHECK(g == 13^7)
CHECK(h == 13^8)
CHECK(i == 13^9)
end
end
do CASE "should be able to get next results"
local world = jecs.World.new() :: World
world:component()