mirror of
https://github.com/Reuh/ubiquitousse.git
synced 2025-10-27 09:09:30 +00:00
ecs: simplify linked list implementation
This commit is contained in:
parent
fe2bac6ebd
commit
99a19b11c5
1 changed files with 51 additions and 72 deletions
123
ecs/ecs.can
123
ecs/ecs.can
|
|
@ -98,6 +98,9 @@ local sprite = {
|
||||||
}
|
}
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
|
--- Special value used as the first element of each system's linked list of entities.
|
||||||
|
let head = {}
|
||||||
|
|
||||||
--- Recursively remove subsystems from a system.
|
--- Recursively remove subsystems from a system.
|
||||||
let recDestroySystems = (system)
|
let recDestroySystems = (system)
|
||||||
for i=#system.systems, 1, -1 do
|
for i=#system.systems, 1, -1 do
|
||||||
|
|
@ -383,10 +386,11 @@ let system_mt = {
|
||||||
--- Private fields ---
|
--- Private fields ---
|
||||||
|
|
||||||
--- First element of the linked list of entities: { entity, next_element }.
|
--- First element of the linked list of entities: { entity, next_element }.
|
||||||
|
-- The default entity `head` is always added as a first element to simplify algorithms; remember to skip it.
|
||||||
-- @local
|
-- @local
|
||||||
_first = nil,
|
_first = nil,
|
||||||
--- Associative map of entities in the system and their previous linked list element (or `true` if first element).
|
--- Hash map of entities in the system and their previous linked list element. Does not contain a key for the `head` entity.
|
||||||
-- This make the list effectively a doubly linked list, but with easy access to the previous element using this map (and therefore O(1) deletion).
|
-- This make the list effectively a doubly linked list, but with fast access to the previous element using this map (and therefore O(1) deletion).
|
||||||
-- @local
|
-- @local
|
||||||
_previous = nil,
|
_previous = nil,
|
||||||
--- Amount of time waited since last update (if interval is set).
|
--- Amount of time waited since last update (if interval is set).
|
||||||
|
|
@ -419,30 +423,20 @@ let system_mt = {
|
||||||
copy({ [@component] = @default }, e)
|
copy({ [@component] = @default }, e)
|
||||||
end
|
end
|
||||||
-- add to linked list
|
-- add to linked list
|
||||||
if @_first == nil then
|
let entity = @_first
|
||||||
@_first = { e, nil }
|
while entity[2] ~= nil do -- no need to process first entity as it is the special `head` entity
|
||||||
@_previous[e] = true
|
if @compare(e, entity[2][1]) then
|
||||||
elseif @compare(e, @_first[1]) then
|
let nxt = entity[2]
|
||||||
let nxt = @_first
|
entity[2] = { e, nxt }
|
||||||
@_first = { e, nxt }
|
|
||||||
@_previous[e] = true
|
|
||||||
@_previous[nxt[1]] = @_first
|
|
||||||
else
|
|
||||||
let entity = @_first
|
|
||||||
while entity[2] ~= nil do
|
|
||||||
if @compare(e, entity[2][1]) then
|
|
||||||
let nxt = entity[2]
|
|
||||||
entity[2] = { e, nxt }
|
|
||||||
@_previous[e] = entity
|
|
||||||
@_previous[nxt[1]] = entity[2]
|
|
||||||
break
|
|
||||||
end
|
|
||||||
entity = entity[2]
|
|
||||||
end
|
|
||||||
if entity[2] == nil then
|
|
||||||
entity[2] = { e, nil }
|
|
||||||
@_previous[e] = entity
|
@_previous[e] = entity
|
||||||
|
@_previous[nxt[1]] = entity[2]
|
||||||
|
break
|
||||||
end
|
end
|
||||||
|
entity = entity[2]
|
||||||
|
end
|
||||||
|
if entity[2] == nil then
|
||||||
|
entity[2] = { e, nil }
|
||||||
|
@_previous[e] = entity
|
||||||
end
|
end
|
||||||
-- notify addition
|
-- notify addition
|
||||||
@entityCount += 1
|
@entityCount += 1
|
||||||
|
|
@ -483,16 +477,9 @@ let system_mt = {
|
||||||
if @_previous[e] then -- recheck in case it was removed already from a subsystem onRemove callback
|
if @_previous[e] then -- recheck in case it was removed already from a subsystem onRemove callback
|
||||||
-- remove from linked list
|
-- remove from linked list
|
||||||
let prev = @_previous[e]
|
let prev = @_previous[e]
|
||||||
if prev == true then
|
prev[2] = prev[2][2]
|
||||||
@_first = @_first[2]
|
if prev[2] then
|
||||||
if @_first then
|
@_previous[prev[2][1]] = prev
|
||||||
@_previous[@_first[1]] = true
|
|
||||||
end
|
|
||||||
else
|
|
||||||
prev[2] = prev[2][2]
|
|
||||||
if prev[2] then
|
|
||||||
@_previous[prev[2][1]] = prev
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
-- notify removal
|
-- notify removal
|
||||||
@_previous[e] = nil
|
@_previous[e] = nil
|
||||||
|
|
@ -545,43 +532,33 @@ let system_mt = {
|
||||||
-- @tparam Entity... ... other entities to reorder
|
-- @tparam Entity... ... other entities to reorder
|
||||||
-- @treturn Entity,... `e,...` the function arguments
|
-- @treturn Entity,... `e,...` the function arguments
|
||||||
reorder = :(e, ...)
|
reorder = :(e, ...)
|
||||||
if e ~= nil then
|
if e ~= nil and @_previous[e] then
|
||||||
if @_previous[e] then
|
let prev = @_previous[e] -- { prev, { e, next } }
|
||||||
let prev = @_previous[e] -- { prev, { e, next } }
|
let next = prev[2][2]
|
||||||
let next = prev == true and @_first[2] or prev[2][2]
|
-- remove e from linked list
|
||||||
-- remove e from linked list
|
prev[2] = next
|
||||||
if prev == true then
|
if next then
|
||||||
@_first = @_first[2]
|
@_previous[next[1]] = prev
|
||||||
else
|
end
|
||||||
prev[2] = next
|
-- find position so that prev < e <= next
|
||||||
end
|
while prev[1] ~= head and @compare(e, prev[1]) do -- ensure prev < e
|
||||||
if next then
|
next = prev
|
||||||
@_previous[next[1]] = prev
|
prev = @_previous[prev[1]]
|
||||||
end
|
end
|
||||||
-- find position so that prev < e <= next
|
while next ~= nil and not @compare(e, next[1]) do -- ensure e <= next
|
||||||
while prev ~= true and @compare(e, prev[1]) do -- ensure prev < e
|
prev = next
|
||||||
next = prev
|
next = next[2]
|
||||||
prev = @_previous[prev[1]]
|
end
|
||||||
end
|
-- reinsert e in linked list
|
||||||
while next ~= nil and not @compare(e, next[1]) do -- ensure e <= next
|
let new = { e, next }
|
||||||
prev = next
|
@_previous[e] = prev
|
||||||
next = next[2]
|
if next then
|
||||||
end
|
@_previous[next[1]] = new
|
||||||
-- reinsert e in linked list
|
end
|
||||||
let new = { e, next }
|
prev[2] = new
|
||||||
@_previous[e] = prev
|
-- Reorder in subsystems
|
||||||
if next then
|
for _, s in ipairs(@systems) do
|
||||||
@_previous[next[1]] = new
|
s:reorder(e)
|
||||||
end
|
|
||||||
if prev == true then
|
|
||||||
@_first = new
|
|
||||||
else
|
|
||||||
prev[2] = new
|
|
||||||
end
|
|
||||||
-- Reorder in subsystems
|
|
||||||
for _, s in ipairs(@systems) do
|
|
||||||
s:reorder(e)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if ... then
|
if ... then
|
||||||
|
|
@ -607,7 +584,7 @@ let system_mt = {
|
||||||
--- Returns an iterator that iterate through the entties in this system, in order.
|
--- Returns an iterator that iterate through the entties in this system, in order.
|
||||||
-- @treturn iterator iterator over the entities in this system
|
-- @treturn iterator iterator over the entities in this system
|
||||||
iter = :()
|
iter = :()
|
||||||
return nextEntity, { @_first }
|
return nextEntity, { @_first[2] }
|
||||||
end,
|
end,
|
||||||
--- Get the `i`th entity in the system.
|
--- Get the `i`th entity in the system.
|
||||||
-- This is a simple wrapper around `iter`; it _will_ iterate over all the entities in the system in order until we reach the desired one.
|
-- This is a simple wrapper around `iter`; it _will_ iterate over all the entities in the system in order until we reach the desired one.
|
||||||
|
|
@ -759,6 +736,7 @@ let recInstanciateSystems = (world, systems)
|
||||||
world = world,
|
world = world,
|
||||||
w = world,
|
w = world,
|
||||||
s = world.s,
|
s = world.s,
|
||||||
|
_first = { head },
|
||||||
_previous = {},
|
_previous = {},
|
||||||
}, {
|
}, {
|
||||||
__index = :(k)
|
__index = :(k)
|
||||||
|
|
@ -813,6 +791,7 @@ ecs = {
|
||||||
let world = setmetatable({
|
let world = setmetatable({
|
||||||
filter = ecs.all(),
|
filter = ecs.all(),
|
||||||
s = {},
|
s = {},
|
||||||
|
_first = { head },
|
||||||
_previous = {}
|
_previous = {}
|
||||||
}, { __index = system_mt })
|
}, { __index = system_mt })
|
||||||
world.world = world
|
world.world = world
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue