mirror of
https://github.com/Ukendio/jecs.git
synced 2025-04-25 09:30:03 +00:00
Self contained changetracker
This commit is contained in:
parent
18ead3ed19
commit
d5de1ad425
2 changed files with 136 additions and 106 deletions
|
@ -935,7 +935,7 @@ do
|
||||||
setmetatable(it, it)
|
setmetatable(it, it)
|
||||||
|
|
||||||
function world_query(world: World, ...: any): Query
|
function world_query(world: World, ...: any): Query
|
||||||
-- breaking?
|
-- breaking
|
||||||
if (...) == nil then
|
if (...) == nil then
|
||||||
error("Missing components")
|
error("Missing components")
|
||||||
end
|
end
|
||||||
|
@ -1179,8 +1179,10 @@ function World.new()
|
||||||
|
|
||||||
self.ROOT_ARCHETYPE = archetype_of(self, {})
|
self.ROOT_ARCHETYPE = archetype_of(self, {})
|
||||||
|
|
||||||
|
for i = HI_COMPONENT_ID + 1, EcsRest do
|
||||||
-- Initialize built-in components
|
-- Initialize built-in components
|
||||||
entity_index_new_id(self.entityIndex, EcsChildOf)
|
entity_index_new_id(self.entityIndex, i)
|
||||||
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
106
test/tests.luau
106
test/tests.luau
|
@ -564,34 +564,30 @@ TEST("world", function()
|
||||||
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
type Tracker<T> = { track: (world: World, fn: (changes: {
|
||||||
|
added: () -> () -> (number, T),
|
||||||
|
removed: () -> () -> number,
|
||||||
|
changed: () -> () -> (number, T, T)
|
||||||
|
}) -> ()) -> ()
|
||||||
|
}
|
||||||
|
|
||||||
TEST("changetracker", function()
|
type Entity<T = any> = number & { __nominal_type_dont_use: T }
|
||||||
local world = jecs.World.new()
|
|
||||||
local Previous = world:component()
|
|
||||||
|
|
||||||
local function shallowEq(a, b)
|
local ChangeTracker: <T>(component: Entity<T>) -> Tracker<T>
|
||||||
for k, v in a do
|
|
||||||
if b[k] ~= v then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
local function ChangeTracker(world, component)
|
do
|
||||||
local addedComponents = {}
|
local world: World
|
||||||
local removedComponents = {}
|
local T
|
||||||
local previous = jecs.pair(Previous, component)
|
local PreviousT
|
||||||
local isTrivial = nil
|
local addedComponents
|
||||||
|
local removedComponents
|
||||||
|
local isTrivial
|
||||||
|
local added
|
||||||
|
local removed
|
||||||
|
|
||||||
local function track(fn)
|
local function changes_added()
|
||||||
local added = false
|
|
||||||
local removed = false
|
|
||||||
|
|
||||||
local changes = {}
|
|
||||||
function changes.added()
|
|
||||||
added = true
|
added = true
|
||||||
local q = world:query(component):without(previous)
|
local q = world:query(T):without(PreviousT)
|
||||||
return function()
|
return function()
|
||||||
local id, data = q:next()
|
local id, data = q:next()
|
||||||
if not id then
|
if not id then
|
||||||
|
@ -611,8 +607,17 @@ TEST("changetracker", function()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function changes.changed()
|
local function shallowEq(a, b)
|
||||||
local q = world:query(component, previous)
|
for k, v in a do
|
||||||
|
if b[k] ~= v then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function changes_changed()
|
||||||
|
local q = world:query(T, PreviousT)
|
||||||
|
|
||||||
return function()
|
return function()
|
||||||
local id, new, old = q:next()
|
local id, new, old = q:next()
|
||||||
|
@ -638,10 +643,10 @@ TEST("changetracker", function()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function changes.removed()
|
local function changes_removed()
|
||||||
removed = true
|
removed = true
|
||||||
|
|
||||||
local q = world:query(previous):without(component)
|
local q = world:query(PreviousT):without(T)
|
||||||
return function()
|
return function()
|
||||||
local id = q:next()
|
local id = q:next()
|
||||||
if id then
|
if id then
|
||||||
|
@ -651,39 +656,62 @@ TEST("changetracker", function()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local changes = {
|
||||||
|
added = changes_added,
|
||||||
|
changed = changes_changed,
|
||||||
|
removed = changes_removed,
|
||||||
|
}
|
||||||
|
|
||||||
|
local function track(worldToTrack, fn)
|
||||||
|
world = worldToTrack
|
||||||
|
added = true
|
||||||
|
removed = true
|
||||||
|
|
||||||
fn(changes)
|
fn(changes)
|
||||||
|
|
||||||
if not added then
|
if not added then
|
||||||
for _ in changes.added() do
|
for _ in changes_added() do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if not removed then
|
if not removed then
|
||||||
for _ in changes.removed() do
|
for _ in changes_removed() do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for e, data in addedComponents do
|
for e, data in addedComponents do
|
||||||
world:set(e, previous, if isTrivial then data else table.clone(data))
|
world:set(e, PreviousT, if isTrivial then data else table.clone(data))
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, e in removedComponents do
|
for _, e in removedComponents do
|
||||||
world:remove(e, previous)
|
world:remove(e, PreviousT)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return {
|
local tracker = { track = track }
|
||||||
track = track
|
|
||||||
}
|
function ChangeTracker<T>(component: Entity<T>): Tracker<T>
|
||||||
|
T = component
|
||||||
|
-- We just use jecs.Rest because people will probably not use it anyways
|
||||||
|
PreviousT = jecs.pair(jecs.Rest, T)
|
||||||
|
addedComponents = {}
|
||||||
|
removedComponents = {}
|
||||||
|
|
||||||
|
return tracker
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
TEST("changetracker", function()
|
||||||
|
local world = jecs.World.new()
|
||||||
|
|
||||||
do CASE "should allow change tracking"
|
do CASE "should allow change tracking"
|
||||||
local Test = world:component()
|
local Test = world:component() :: Entity<{ foo: number }>
|
||||||
local TestTracker = ChangeTracker(world, Test)
|
local TestTracker = ChangeTracker(Test)
|
||||||
|
|
||||||
local e = world:entity()
|
local e = world:entity()
|
||||||
world:set(e, Test, { foo = 11 })
|
world:set(e, Test, { foo = 11 })
|
||||||
|
|
||||||
TestTracker.track(function(changes)
|
TestTracker.track(world, function(changes)
|
||||||
local added = 0
|
local added = 0
|
||||||
local changed = 0
|
local changed = 0
|
||||||
local removed = 0
|
local removed = 0
|
||||||
|
@ -705,7 +733,7 @@ TEST("changetracker", function()
|
||||||
test.foo = test.foo + 1
|
test.foo = test.foo + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
TestTracker.track(function(changes)
|
TestTracker.track(world, function(changes)
|
||||||
local added = 0
|
local added = 0
|
||||||
local changed = 0
|
local changed = 0
|
||||||
local removed = 0
|
local removed = 0
|
||||||
|
@ -727,7 +755,7 @@ TEST("changetracker", function()
|
||||||
|
|
||||||
world:remove(e, Test)
|
world:remove(e, Test)
|
||||||
|
|
||||||
TestTracker.track(function(changes)
|
TestTracker.track(world, function(changes)
|
||||||
local added = 0
|
local added = 0
|
||||||
local changed = 0
|
local changed = 0
|
||||||
local removed = 0
|
local removed = 0
|
||||||
|
|
Loading…
Reference in a new issue