mirror of
https://github.com/Ukendio/jecs.git
synced 2025-09-23 08:39:16 +00:00
Fix without terms for ob::observer and also add bunch of tests
Some checks failed
Some checks failed
This commit is contained in:
parent
690e9ec4d7
commit
7e1f43aff5
2 changed files with 205 additions and 73 deletions
|
@ -12,6 +12,10 @@ export type Iter<T...> = (Observer<T...>) -> () -> (jecs.Entity, T...)
|
||||||
|
|
||||||
export type Observer<T...> = {
|
export type Observer<T...> = {
|
||||||
disconnect: (Observer<T...>) -> (),
|
disconnect: (Observer<T...>) -> (),
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Monitor<T...> = {
|
||||||
|
disconnect: (Observer<T...>) -> (),
|
||||||
added: ((jecs.Entity) -> ()) -> (),
|
added: ((jecs.Entity) -> ()) -> (),
|
||||||
removed: ((jecs.Entity) -> ()) -> ()
|
removed: ((jecs.Entity) -> ()) -> ()
|
||||||
}
|
}
|
||||||
|
@ -77,11 +81,11 @@ local function observers_new<T...>(
|
||||||
if without then
|
if without then
|
||||||
for _, term in without do
|
for _, term in without do
|
||||||
if jecs.IS_PAIR(term) then
|
if jecs.IS_PAIR(term) then
|
||||||
local rel = jecs.ECS_PAIR_SECOND(term)
|
local rel = jecs.ECS_PAIR_FIRST(term)
|
||||||
local tgt = jecs.ECS_PAIR_SECOND(term)
|
local tgt = jecs.ECS_PAIR_SECOND(term)
|
||||||
local wc = tgt == jecs.w
|
local wc = tgt == jecs.w
|
||||||
local onremoved = world:removed(rel, function(entity, id)
|
local onremoved = world:removed(rel, function(entity, id)
|
||||||
if not wc and term ~= tgt then
|
if not wc and id ~= term then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local r = jecs.record(world, entity)
|
local r = jecs.record(world, entity)
|
||||||
|
@ -137,7 +141,7 @@ local function observers_new<T...>(
|
||||||
return (observer :: any) :: Observer<T...>
|
return (observer :: any) :: Observer<T...>
|
||||||
end
|
end
|
||||||
|
|
||||||
local function monitors_new<T...>(query: Query<T...>): Observer<T...>
|
local function monitors_new<T...>(query: Query<T...>): Monitor<T...>
|
||||||
query:cached()
|
query:cached()
|
||||||
|
|
||||||
local world = (query :: Query<T...> & { world: World }).world
|
local world = (query :: Query<T...> & { world: World }).world
|
||||||
|
@ -313,7 +317,7 @@ local function monitors_new<T...>(query: Query<T...>): Observer<T...>
|
||||||
removed = monitor_removed
|
removed = monitor_removed
|
||||||
}
|
}
|
||||||
|
|
||||||
return (observer :: any) :: Observer<T...>
|
return (observer :: any) :: Monitor<T...>
|
||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -5,7 +5,203 @@ local CASE, TEST, FINISH, CHECK = test.CASE, test.TEST, test.FINISH, test.CHECK
|
||||||
local FOCUS = test.FOCUS
|
local FOCUS = test.FOCUS
|
||||||
local ob = require("@addons/ob")
|
local ob = require("@addons/ob")
|
||||||
|
|
||||||
TEST("addons/ob", function()
|
TEST("addons/ob::observer", function()
|
||||||
|
local world = jecs.world()
|
||||||
|
do CASE "should match against archetypes that were already created"
|
||||||
|
local A = world:component()
|
||||||
|
|
||||||
|
local e1 = world:entity()
|
||||||
|
world:add(e1, A)
|
||||||
|
|
||||||
|
local c = 1
|
||||||
|
ob.observer(world:query(A), function()
|
||||||
|
c+=1
|
||||||
|
end)
|
||||||
|
|
||||||
|
world:remove(e1, A)
|
||||||
|
world:add(e1, A)
|
||||||
|
CHECK(c==2)
|
||||||
|
end
|
||||||
|
|
||||||
|
do CASE "Should enter observer at query:without(pair(R, t1)) when adding pair(R, t2)"
|
||||||
|
local A = world:component()
|
||||||
|
local B = world:component()
|
||||||
|
local C = world:component()
|
||||||
|
local D = world:component()
|
||||||
|
|
||||||
|
local e = world:entity()
|
||||||
|
world:add(e, A)
|
||||||
|
world:add(e, jecs.pair(B, D))
|
||||||
|
|
||||||
|
local c = 1
|
||||||
|
|
||||||
|
ob.observer(world:query(A):without(jecs.pair(B, C)), function()
|
||||||
|
c += 1
|
||||||
|
end)
|
||||||
|
|
||||||
|
local child = world:entity()
|
||||||
|
world:add(child, A)
|
||||||
|
CHECK(c==2)
|
||||||
|
world:add(child, jecs.pair(B, D))
|
||||||
|
CHECK(c==2)
|
||||||
|
world:add(child, jecs.pair(B, C))
|
||||||
|
CHECK(c==2)
|
||||||
|
end
|
||||||
|
|
||||||
|
do CASE "Should enter observer at query:without(pair(R, t1)) when removing pair(R, t1)"
|
||||||
|
local A = world:component()
|
||||||
|
local B = world:component()
|
||||||
|
local C = world:component()
|
||||||
|
local D = world:component()
|
||||||
|
|
||||||
|
local e = world:entity()
|
||||||
|
world:add(e, A)
|
||||||
|
world:add(e, jecs.pair(B, D))
|
||||||
|
|
||||||
|
local c = 1
|
||||||
|
ob.observer(world:query(A):without(jecs.pair(B, D)), function()
|
||||||
|
c += 1
|
||||||
|
end)
|
||||||
|
|
||||||
|
local child = world:entity()
|
||||||
|
world:add(child, jecs.pair(B, C))
|
||||||
|
world:add(child, jecs.pair(B, D))
|
||||||
|
CHECK(c==1)
|
||||||
|
world:add(child, A)
|
||||||
|
CHECK(c==1)
|
||||||
|
world:remove(child, jecs.pair(B, C))
|
||||||
|
CHECK(c==1)
|
||||||
|
world:add(child, jecs.pair(B, C))
|
||||||
|
CHECK(c==1)
|
||||||
|
world:remove(child, jecs.pair(B, D))
|
||||||
|
CHECK(c==2)
|
||||||
|
world:add(child, jecs.pair(B, D))
|
||||||
|
CHECK(c==2)
|
||||||
|
world:remove(child, jecs.pair(B, C))
|
||||||
|
CHECK(c==2)
|
||||||
|
world:remove(child, jecs.pair(B, D))
|
||||||
|
CHECK(c==3)
|
||||||
|
end
|
||||||
|
|
||||||
|
do CASE "Should enter observer at query:without(pair(R, *)) when adding pair(R, t1)"
|
||||||
|
local A = world:component()
|
||||||
|
local B = world:component()
|
||||||
|
local C = world:component()
|
||||||
|
local D = world:component()
|
||||||
|
|
||||||
|
local c = 1
|
||||||
|
ob.observer(world:query(A):without(jecs.pair(B, jecs.w)), function() c+= 1 end)
|
||||||
|
|
||||||
|
local child = world:entity()
|
||||||
|
world:add(child, A)
|
||||||
|
CHECK(c==2)
|
||||||
|
world:add(child, jecs.pair(B, D))
|
||||||
|
CHECK(c==2)
|
||||||
|
world:add(child, jecs.pair(B, C))
|
||||||
|
CHECK(c==2)
|
||||||
|
end
|
||||||
|
|
||||||
|
do CASE "Should enter observer at query:without(t1) when removing t1"
|
||||||
|
local A = world:component()
|
||||||
|
local B = world:component()
|
||||||
|
|
||||||
|
local c = 1
|
||||||
|
ob.observer(world:query(A):without(B), function() c+= 1 end)
|
||||||
|
|
||||||
|
local child = world:entity()
|
||||||
|
world:add(child, B)
|
||||||
|
CHECK(c==1)
|
||||||
|
world:add(child, A)
|
||||||
|
CHECK(c==1)
|
||||||
|
world:remove(child, B)
|
||||||
|
CHECK(c==2)
|
||||||
|
world:remove(child, A)
|
||||||
|
CHECK(c==2)
|
||||||
|
end
|
||||||
|
|
||||||
|
do CASE "observers should accept pairs"
|
||||||
|
local A = world:component()
|
||||||
|
local B = world:component()
|
||||||
|
|
||||||
|
local c = 1
|
||||||
|
ob.observer(world:query(jecs.pair(A, B)), function() c+= 1 end)
|
||||||
|
|
||||||
|
local child = world:entity()
|
||||||
|
world:add(child, jecs.pair(A, B))
|
||||||
|
CHECK(c == 2)
|
||||||
|
|
||||||
|
world:remove(child, jecs.pair(A, B))
|
||||||
|
CHECK(c == 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
do CASE "Ensure ordering between signals and observers"
|
||||||
|
local A = world:component()
|
||||||
|
local B = world:component()
|
||||||
|
|
||||||
|
local count = 1
|
||||||
|
local function counter()
|
||||||
|
count += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
ob.observer(world:query(A, B), counter)
|
||||||
|
|
||||||
|
world:added(A, counter)
|
||||||
|
world:added(A, counter)
|
||||||
|
|
||||||
|
for _ in world:query(A) do
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local e = world:entity()
|
||||||
|
world:add(e, A)
|
||||||
|
CHECK(count == 3)
|
||||||
|
|
||||||
|
world:add(e, B)
|
||||||
|
CHECK(count == 4)
|
||||||
|
end
|
||||||
|
|
||||||
|
do CASE "Rematch entities in observers"
|
||||||
|
local A = world:component()
|
||||||
|
|
||||||
|
local count = 1
|
||||||
|
local function counter()
|
||||||
|
count += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
ob.observer(world:query(A), counter)
|
||||||
|
|
||||||
|
local e = world:entity()
|
||||||
|
world:set(e, A, false)
|
||||||
|
CHECK(count == 2)
|
||||||
|
world:remove(e, A)
|
||||||
|
CHECK(count == 2)
|
||||||
|
world:set(e, A, false)
|
||||||
|
CHECK(count == 3)
|
||||||
|
world:set(e, A, false)
|
||||||
|
CHECK(count == 4)
|
||||||
|
end
|
||||||
|
|
||||||
|
do CASE "Call off pairs"
|
||||||
|
local A = world:component()
|
||||||
|
|
||||||
|
local callcount = 1
|
||||||
|
world:added(A, function(entity)
|
||||||
|
callcount += 1
|
||||||
|
end)
|
||||||
|
world:added(A, function(entity)
|
||||||
|
callcount += 1
|
||||||
|
end)
|
||||||
|
|
||||||
|
local e = world:entity()
|
||||||
|
local e2 = world:entity()
|
||||||
|
|
||||||
|
world:add(e2, jecs.pair(A, e))
|
||||||
|
world:add(e, jecs.pair(A, e2))
|
||||||
|
CHECK(callcount == 1 + 2 * 2)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
TEST("addons/ob::monitor", function()
|
||||||
local world = jecs.world()
|
local world = jecs.world()
|
||||||
do CASE "should match against archetypes that were already created"
|
do CASE "should match against archetypes that were already created"
|
||||||
local A = world:component()
|
local A = world:component()
|
||||||
|
@ -61,8 +257,6 @@ TEST("addons/ob", function()
|
||||||
local C = world:component()
|
local C = world:component()
|
||||||
local D = world:component()
|
local D = world:component()
|
||||||
|
|
||||||
print("B", B)
|
|
||||||
|
|
||||||
local e = world:entity()
|
local e = world:entity()
|
||||||
world:add(e, A)
|
world:add(e, A)
|
||||||
world:add(e, jecs.pair(B, D))
|
world:add(e, jecs.pair(B, D))
|
||||||
|
@ -172,53 +366,6 @@ TEST("addons/ob", function()
|
||||||
CHECK(c == 3)
|
CHECK(c == 3)
|
||||||
end
|
end
|
||||||
|
|
||||||
do CASE "Ensure ordering between signals and observers"
|
|
||||||
local A = world:component()
|
|
||||||
local B = world:component()
|
|
||||||
|
|
||||||
local count = 1
|
|
||||||
local function counter()
|
|
||||||
count += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
ob.observer(world:query(A, B), counter)
|
|
||||||
|
|
||||||
world:added(A, counter)
|
|
||||||
world:added(A, counter)
|
|
||||||
|
|
||||||
for _ in world:query(A) do
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
local e = world:entity()
|
|
||||||
world:add(e, A)
|
|
||||||
CHECK(count == 3)
|
|
||||||
|
|
||||||
world:add(e, B)
|
|
||||||
CHECK(count == 4)
|
|
||||||
end
|
|
||||||
|
|
||||||
do CASE "Rematch entities in observers"
|
|
||||||
local A = world:component()
|
|
||||||
|
|
||||||
local count = 1
|
|
||||||
local function counter()
|
|
||||||
count += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
ob.observer(world:query(A), counter)
|
|
||||||
|
|
||||||
local e = world:entity()
|
|
||||||
world:set(e, A, false)
|
|
||||||
CHECK(count == 2)
|
|
||||||
world:remove(e, A)
|
|
||||||
CHECK(count == 2)
|
|
||||||
world:set(e, A, false)
|
|
||||||
CHECK(count == 3)
|
|
||||||
world:set(e, A, false)
|
|
||||||
CHECK(count == 4)
|
|
||||||
end
|
|
||||||
|
|
||||||
do CASE "Don't report changed components in monitor"
|
do CASE "Don't report changed components in monitor"
|
||||||
local A = world:component()
|
local A = world:component()
|
||||||
local count = 1
|
local count = 1
|
||||||
|
@ -240,25 +387,6 @@ TEST("addons/ob", function()
|
||||||
world:set(e, A, false)
|
world:set(e, A, false)
|
||||||
CHECK(count == 4)
|
CHECK(count == 4)
|
||||||
end
|
end
|
||||||
|
|
||||||
do CASE "Call off pairs"
|
|
||||||
local A = world:component()
|
|
||||||
|
|
||||||
local callcount = 1
|
|
||||||
world:added(A, function(entity)
|
|
||||||
callcount += 1
|
|
||||||
end)
|
|
||||||
world:added(A, function(entity)
|
|
||||||
callcount += 1
|
|
||||||
end)
|
|
||||||
|
|
||||||
local e = world:entity()
|
|
||||||
local e2 = world:entity()
|
|
||||||
|
|
||||||
world:add(e2, jecs.pair(A, e))
|
|
||||||
world:add(e, jecs.pair(A, e2))
|
|
||||||
CHECK(callcount == 1 + 2 * 2)
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
return FINISH()
|
return FINISH()
|
||||||
|
|
Loading…
Reference in a new issue