mirror of
https://github.com/Ukendio/jecs.git
synced 2025-04-24 17:10:03 +00:00
Remove drain and next
This commit is contained in:
parent
d6932ff80e
commit
25dd6394ba
2 changed files with 57 additions and 114 deletions
|
@ -611,13 +611,7 @@ end
|
|||
local function archetype_ensure_edge(world, edges, id): GraphEdge
|
||||
local edge = edges[id]
|
||||
if not edge then
|
||||
edge = {
|
||||
from = nil :: any,
|
||||
to = nil :: any,
|
||||
id = id,
|
||||
prev = nil,
|
||||
next = nil,
|
||||
} :: GraphEdge
|
||||
edge = {} :: GraphEdge
|
||||
edges[id] = edge
|
||||
end
|
||||
|
||||
|
@ -1095,9 +1089,6 @@ local EMPTY_QUERY = {
|
|||
iter = function()
|
||||
return NOOP
|
||||
end,
|
||||
drain = ARM,
|
||||
next = NOOP,
|
||||
replace = NOOP,
|
||||
with = ARM,
|
||||
without = ARM,
|
||||
archetypes = function()
|
||||
|
@ -1107,16 +1098,9 @@ local EMPTY_QUERY = {
|
|||
|
||||
setmetatable(EMPTY_QUERY, EMPTY_QUERY)
|
||||
|
||||
local function query_iter(query)
|
||||
local function query_iter_init(query)
|
||||
local world_query_iter_next
|
||||
|
||||
if query.should_drain then
|
||||
world_query_iter_next = query.iter_next
|
||||
if world_query_iter_next then
|
||||
return world_query_iter_next
|
||||
end
|
||||
end
|
||||
|
||||
local compatible_archetypes = query.compatible_archetypes
|
||||
local lastArchetype = 1
|
||||
local archetype = compatible_archetypes[1]
|
||||
|
@ -1363,19 +1347,16 @@ local function query_iter(query)
|
|||
end
|
||||
end
|
||||
|
||||
query.iter_next = world_query_iter_next
|
||||
query.next = world_query_iter_next
|
||||
return world_query_iter_next
|
||||
end
|
||||
|
||||
local function query_drain(query)
|
||||
local query_iter_next = query_iter(query)
|
||||
query.next = query_iter_next
|
||||
query.should_drain = true
|
||||
return query
|
||||
end
|
||||
|
||||
local function query_next(query)
|
||||
error("Did you forget to call drain?")
|
||||
local function query_iter(query)
|
||||
local query_next = query.next
|
||||
if not query_next then
|
||||
query_next = query_iter_init(query)
|
||||
end
|
||||
return query_next
|
||||
end
|
||||
|
||||
local function query_without(query, ...)
|
||||
|
@ -1440,55 +1421,6 @@ local function query_with(query, ...)
|
|||
return query
|
||||
end
|
||||
|
||||
local function columns_replace_values(row, columns, ...)
|
||||
for i, column in columns do
|
||||
column[row] = select(i, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local function query_replace(query, fn: (...any) -> ...any)
|
||||
local compatible_archetypes = query.compatible_archetypes
|
||||
local ids = query.ids
|
||||
local A, B, C, D, E = unpack(ids, 1, 5)
|
||||
local queryOutput = {}
|
||||
for i, archetype in compatible_archetypes do
|
||||
local columns = archetype.columns
|
||||
local records = archetype.records
|
||||
for row in archetype.entities do
|
||||
if not B then
|
||||
local va = columns[records[A].column]
|
||||
local pa = fn(va[row])
|
||||
|
||||
va[row] = pa
|
||||
elseif not C then
|
||||
local va = columns[records[A].column]
|
||||
local vb = columns[records[B].column]
|
||||
|
||||
va[row], vb[row] = fn(va[row], vb[row])
|
||||
elseif not D then
|
||||
local va = columns[records[A].column]
|
||||
local vb = columns[records[B].column]
|
||||
local vc = columns[records[C].column]
|
||||
|
||||
va[row], vb[row], vc[row] = fn(va[row], vb[row], vc[row])
|
||||
elseif not E then
|
||||
local va = columns[records[A].column]
|
||||
local vb = columns[records[B].column]
|
||||
local vc = columns[records[C].column]
|
||||
local vd = columns[records[D].column]
|
||||
|
||||
va[row], vb[row], vc[row], vd[row] = fn(va[row], vb[row], vc[row], vd[row])
|
||||
else
|
||||
for j, id in ids do
|
||||
local tr = records[id]
|
||||
queryOutput[j] = columns[tr.column][row]
|
||||
end
|
||||
columns_replace_values(row, columns, fn(unpack(queryOutput)))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Meant for directly iterating over archetypes to minimize
|
||||
-- function call overhead. Should not be used unless iterating over
|
||||
-- hundreds of thousands of entities in bulk.
|
||||
|
@ -1499,13 +1431,10 @@ end
|
|||
local Query = {}
|
||||
Query.__index = Query
|
||||
Query.__iter = query_iter
|
||||
Query.iter = query_iter
|
||||
Query.iter = query_iter_init
|
||||
Query.without = query_without
|
||||
Query.with = query_with
|
||||
Query.archetypes = query_archetypes
|
||||
Query.drain = query_drain
|
||||
Query.next = query_next
|
||||
Query.replace = query_replace
|
||||
|
||||
local function world_query(world: World, ...)
|
||||
local compatible_archetypes = {}
|
||||
|
|
|
@ -328,7 +328,7 @@ TEST("world:query()", function()
|
|||
world:set(eAB, B, true)
|
||||
|
||||
-- Should drain the iterator
|
||||
local q = world:query(A):drain()
|
||||
local q = world:query(A)
|
||||
|
||||
local i = 0
|
||||
local j = 0
|
||||
|
@ -403,9 +403,9 @@ TEST("world:query()", function()
|
|||
world:set(eAB, A, true)
|
||||
world:set(eAB, B, true)
|
||||
|
||||
local q = world:query(A):drain()
|
||||
local it = world:query(A):iter()
|
||||
|
||||
local e, data = q.next()
|
||||
local e, data = it()
|
||||
while e do
|
||||
if e == eA then
|
||||
CHECK(data)
|
||||
|
@ -415,7 +415,7 @@ TEST("world:query()", function()
|
|||
CHECK(false)
|
||||
end
|
||||
|
||||
e, data = q.next()
|
||||
e, data = it()
|
||||
end
|
||||
CHECK(true)
|
||||
end
|
||||
|
@ -689,9 +689,10 @@ TEST("world:query()", function()
|
|||
world:add(e1, A)
|
||||
|
||||
local query = world:query(B)
|
||||
CHECK(query:next() == nil)
|
||||
CHECK(query:replace() == nil)
|
||||
CHECK(query:without() == query)
|
||||
CHECK(query:with() == query)
|
||||
-- They always return the same EMPTY_LIST
|
||||
CHECK(query:archetypes() == world:query(B):archetypes())
|
||||
end
|
||||
|
||||
do
|
||||
|
@ -711,26 +712,6 @@ TEST("world:query()", function()
|
|||
end
|
||||
end
|
||||
|
||||
do CASE "replace"
|
||||
local world = jecs.World.new()
|
||||
local A = world:component()
|
||||
local B = world:component()
|
||||
local C = world:component()
|
||||
|
||||
local e = world:entity()
|
||||
world:set(e, A, 1)
|
||||
world:set(e, B, true)
|
||||
world:set(e, C, "hello ")
|
||||
|
||||
world:query(A, B, C):replace(function(a, b, c)
|
||||
return a * 2, not b, c.."world"
|
||||
end)
|
||||
|
||||
CHECK(world:get(e, A) == 2)
|
||||
CHECK(world:get(e, B) == false)
|
||||
CHECK(world:get(e, C) == "hello world")
|
||||
end
|
||||
|
||||
do CASE "without"
|
||||
do
|
||||
-- REGRESSION TEST
|
||||
|
@ -1104,9 +1085,9 @@ local function ChangeTracker<T>(world, T: Entity<T>): Tracker<T>
|
|||
|
||||
local function changes_added()
|
||||
added = true
|
||||
local q = world:query(T):without(PreviousT):drain()
|
||||
local it = world:query(T):without(PreviousT):iter()
|
||||
return function()
|
||||
local id, data = q.next()
|
||||
local id, data = it()
|
||||
if not id then
|
||||
return nil
|
||||
end
|
||||
|
@ -1120,10 +1101,10 @@ local function ChangeTracker<T>(world, T: Entity<T>): Tracker<T>
|
|||
end
|
||||
|
||||
local function changes_changed()
|
||||
local q = world:query(T, PreviousT):drain()
|
||||
local it = world:query(T, PreviousT):iter()
|
||||
|
||||
return function()
|
||||
local id, new, old = q.next()
|
||||
local id, new, old = it()
|
||||
while true do
|
||||
if not id then
|
||||
return nil
|
||||
|
@ -1137,7 +1118,7 @@ local function ChangeTracker<T>(world, T: Entity<T>): Tracker<T>
|
|||
break
|
||||
end
|
||||
|
||||
id, new, old = q.next()
|
||||
id, new, old = it()
|
||||
end
|
||||
|
||||
add[id] = new
|
||||
|
@ -1149,9 +1130,9 @@ local function ChangeTracker<T>(world, T: Entity<T>): Tracker<T>
|
|||
local function changes_removed()
|
||||
removed = true
|
||||
|
||||
local q = world:query(PreviousT):without(T):drain()
|
||||
local it = world:query(PreviousT):without(T):iter()
|
||||
return function()
|
||||
local id = q.next()
|
||||
local id = it()
|
||||
if id then
|
||||
world:remove(id, PreviousT)
|
||||
end
|
||||
|
@ -1705,4 +1686,37 @@ TEST("scheduler", function()
|
|||
CHECK(systems[1].callback == camera)
|
||||
end
|
||||
end)
|
||||
|
||||
TEST("repro", function()
|
||||
do CASE ""
|
||||
local world = world_new()
|
||||
local reproEntity = world:component()
|
||||
local components = { Cooldown = world:component() }
|
||||
world:set(reproEntity, components.Cooldown, 2)
|
||||
|
||||
local function updateCooldowns(dt: number)
|
||||
local toRemove = {}
|
||||
|
||||
for id, cooldown in world:query(components.Cooldown):iter() do
|
||||
cooldown -= dt
|
||||
|
||||
if cooldown <= 0 then
|
||||
table.insert(toRemove, id)
|
||||
print('removing')
|
||||
-- world:remove(id, components.Cooldown)
|
||||
else
|
||||
world:set(id, components.Cooldown, cooldown)
|
||||
end
|
||||
end
|
||||
|
||||
for _, id in toRemove do
|
||||
world:remove(id, components.Cooldown)
|
||||
CHECK(not world:get(id, components.Cooldown))
|
||||
end
|
||||
end
|
||||
|
||||
updateCooldowns(1.5)
|
||||
updateCooldowns(1.5)
|
||||
end
|
||||
end)
|
||||
FINISH()
|
||||
|
|
Loading…
Reference in a new issue