Change API for activating/deactivating systems. Fix bugs. Update version number.

This commit is contained in:
bakpakin
2015-03-31 19:55:12 +08:00
parent 53ef1f2d36
commit 77df6e20aa
2 changed files with 78 additions and 86 deletions
+4 -6
View File
@@ -140,13 +140,11 @@ describe('tiny-ecs:', function()
end) end)
it("Disable and Enable Systems", function() it("Disable and Enable Systems", function()
world:setSystemActive(moveSystem, false) world:deactivate(moveSystem, oneTimeSystem)
world:setSystemActive(oneTimeSystem, false)
world:update(1) world:update(1)
assert.equals(timePassed, 0) assert.equals(timePassed, 0)
assert.equals(entity1.xform.x, entityTemplate1.xform.x) assert.equals(entity1.xform.x, entityTemplate1.xform.x)
world:setSystemActive(moveSystem, true) world:activate(moveSystem, oneTimeSystem)
world:setSystemActive(oneTimeSystem, true)
world:update(1) world:update(1)
assert.equals(timePassed, 1) assert.equals(timePassed, 1)
assert.are_not.equal(entity1.xform.x, entityTemplate1.xform.x) assert.are_not.equal(entity1.xform.x, entityTemplate1.xform.x)
@@ -155,13 +153,13 @@ describe('tiny-ecs:', function()
it("Clear Entities", function() it("Clear Entities", function()
world:clearEntities() world:clearEntities()
world:update(1) world:update(1)
assert.equals(0, world.getEntityCount()) assert.equals(0, world:getEntityCount())
end) end)
it("Clear Systems", function() it("Clear Systems", function()
world:clearSystems() world:clearSystems()
world:update(1) world:update(1)
assert.equals(0, world.getSystemCount()) assert.equals(0, world:getSystemCount())
end) end)
+75 -81
View File
@@ -2,8 +2,7 @@
-- @author Calvin Rose -- @author Calvin Rose
local tiny = {} local tiny = {}
--- Tiny-ecs Version, a period-separated three number string like "1.2.3" with --- Tiny-ecs Version, a period-separated three number string like "1.2.3"
-- no leading zeros.
tiny._VERSION = "0.3.0" tiny._VERSION = "0.3.0"
local tinsert = table.insert local tinsert = table.insert
@@ -120,9 +119,14 @@ function tiny.world(...)
local ret = { local ret = {
-- Table of Entities to status -- Table of Entities to status
status = {}, -- Statuses: remove, add
entityStatus = {},
-- Set of Entities -- Table of Systems to status
-- Statuses: remove, add
systemStatus = {},
-- Set of Entities -- active are true, inactive are false
entities = {}, entities = {},
-- Number of Entities in World. -- Number of Entities in World.
@@ -141,14 +145,7 @@ function tiny.world(...)
systemIndices = {}, systemIndices = {},
-- Table of Systems to Sets of matching Entities -- Table of Systems to Sets of matching Entities
systemEntities = {}, systemEntities = {}
-- List of Systems to add next update
systemsToAdd = {},
-- List of Systems to remove next update
systemsToRemove = {}
} }
tiny.add(ret, ...) tiny.add(ret, ...)
@@ -168,15 +165,13 @@ end
-- @param ... Systems and Entities -- @param ... Systems and Entities
function tiny.add(world, ...) function tiny.add(world, ...)
local args = {...} local args = {...}
local status = world.status local entityStatus = world.entityStatus
local entities = world.entities local systemStatus = world.systemStatus
local systemsToAdd = world.systemsToAdd
for _, obj in ipairs(args) do for _, obj in ipairs(args) do
if getmetatable(obj) == systemMetaTable then if getmetatable(obj) == systemMetaTable then
tinsert(systemsToAdd, obj) systemStatus[obj] = "add"
else -- Assume obj is an Entity else -- Assume obj is an Entity
entities[obj] = true entityStatus[obj] = "add"
status[obj] = "add"
end end
end end
end end
@@ -188,14 +183,13 @@ tiny_add = tiny.add
-- @param ... Systems and Entities -- @param ... Systems and Entities
function tiny.remove(world, ...) function tiny.remove(world, ...)
local args = {...} local args = {...}
local status = world.status local entityStatus = world.entityStatus
local entities = world.entities local systemStatus = world.systemStatus
local systemsToRemove = world.systemsToRemove
for _, obj in ipairs(args) do for _, obj in ipairs(args) do
if getmetatable(obj) == systemMetaTable then if getmetatable(obj) == systemMetaTable then
tinsert(systemsToRemove, obj) systemStatus[obj] = "remove"
elseif entities[obj] then -- Assume obj is an Entity else -- Assume obj is an Entity
status[obj] = "remove" entityStatus[obj] = "remove"
end end
end end
end end
@@ -234,57 +228,42 @@ function tiny.manageSystems(world)
local systemIndices = world.systemIndices local systemIndices = world.systemIndices
local entities = world.entities local entities = world.entities
local systems = world.systems local systems = world.systems
local systemsToAdd = world.systemsToAdd local systemStatus = world.systemStatus
local systemsToRemove = world.systemsToRemove
local activeSystems = world.activeSystems local activeSystems = world.activeSystems
-- Keep track of the number of Systems in the world -- Keep track of the number of Systems in the world
local deltaSystemCount = 0 local deltaSystemCount = 0
-- Remove all Systems queued for removal for system, status in pairs(systemStatus) do
for i = 1, #systemsToRemove do
-- Pop system off the remove queue
local sys = systemsToRemove[i]
systemsToRemove[i] = nil
local sysID = systemIndices[sys] if status == "add" then
if sysID then
tremove(systems, sysID)
local onRemove = sys.onRemove
if onRemove then
for e in pairs(systemEntities[sys]) do
onRemove(e)
end
end
systemEntities[sys] = nil
activeSystems[sys] = nil
deltaSystemCount = deltaSystemCount - 1
end
end
-- Add Systems queued for addition
for i = 1, #systemsToAdd do
-- Pop system off the add queue
local sys = systemsToAdd[i]
systemsToAdd[i] = nil
-- Add system to world
local es = {} local es = {}
systemEntities[sys] = es systemEntities[system] = es
tinsert(systems, sys) tinsert(systems, system)
systemIndices[sys] = #systems systemIndices[system] = #systems
activeSystems[sys] = true activeSystems[system] = true
local filter = system.filter
local filter = sys.filter
if filter then if filter then
for e in pairs(entities) do for e in pairs(entities) do
es[e] = filter(e) and true or nil es[e] = filter(e) and true or nil
end end
end end
deltaSystemCount = deltaSystemCount + 1 deltaSystemCount = deltaSystemCount + 1
elseif status == "remove" then
local index = systemIndices[system]
tremove(systems, index)
local onRemove = system.onRemove
if onRemove then
for e in pairs(systemEntities[sys]) do
onRemove(e)
end
end
systemEntities[system] = nil
activeSystems[system] = nil
deltaSystemCount = deltaSystemCount - 1
end
systemStatus[system] = nil
end end
-- Update the number of Systems in the World -- Update the number of Systems in the World
@@ -297,7 +276,7 @@ tiny_manageSystems = tiny.manageSystems
-- @param world -- @param world
function tiny.manageEntities(world) function tiny.manageEntities(world)
local statuses = world.status local entityStatus = world.entityStatus
local systemEntities = world.systemEntities local systemEntities = world.systemEntities
local entities = world.entities local entities = world.entities
local systems = world.systems local systems = world.systems
@@ -306,8 +285,9 @@ function tiny.manageEntities(world)
local deltaEntityCount = 0 local deltaEntityCount = 0
-- Add, remove, or change Entities -- Add, remove, or change Entities
for e, s in pairs(statuses) do for e, s in pairs(entityStatus) do
if s == "add" then if s == "add" then
entities[e] = true
deltaEntityCount = deltaEntityCount + 1 deltaEntityCount = deltaEntityCount + 1
for sys, es in pairs(systemEntities) do for sys, es in pairs(systemEntities) do
local filter = sys.filter local filter = sys.filter
@@ -321,8 +301,8 @@ function tiny.manageEntities(world)
end end
end end
elseif s == "remove" then elseif s == "remove" then
deltaEntityCount = deltaEntityCount - 1
entities[e] = nil entities[e] = nil
deltaEntityCount = deltaEntityCount - 1
for sys, es in pairs(systemEntities) do for sys, es in pairs(systemEntities) do
local onRemove = sys.onRemove local onRemove = sys.onRemove
if es[e] and onRemove then if es[e] and onRemove then
@@ -331,7 +311,7 @@ function tiny.manageEntities(world)
es[e] = nil es[e] = nil
end end
end end
statuses[e] = nil entityStatus[e] = nil
end end
-- Update Entity count -- Update Entity count
@@ -363,9 +343,9 @@ end
-- all Entities will be removed. -- all Entities will be removed.
-- @param world -- @param world
function tiny.clearEntities(world) function tiny.clearEntities(world)
local status = world.status local entityStatus = world.entityStatus
for e in pairs(world.entities) do for e in pairs(world.entities) do
status[e] = "remove" entityStatus[e] = "remove"
end end
end end
@@ -374,12 +354,10 @@ end
-- all Systems will be removed. -- all Systems will be removed.
-- @param world -- @param world
function tiny.clearSystems(world) function tiny.clearSystems(world)
local newSystemsToRemove = {} local systemStatus = world.systemStatus
local systems = world.systems for _, s in ipairs(world.systems) do
for i = 1, #systems do systemStatus[s] = "remove"
newSystemsToRemove[i] = systems[i]
end end
world.systemsToRemove = newSystemsToRemove
end end
--- Gets count of Entities in World. --- Gets count of Entities in World.
@@ -390,18 +368,34 @@ end
--- Gets count of Systems in World. --- Gets count of Systems in World.
-- @param world -- @param world
function tiny.getSystemsCount(world) function tiny.getSystemCount(world)
return world.systemCount return world.systemCount
end end
--- Sets if a System is active in a world. If the system is active, it will --- Activates Systems in the World.
-- update automatically when World:update(dt) is called. Otherwise, the user -- Activated Systems will be update whenever tiny.update(world, dt) is called.
-- must call World:updateSystem(system, dt) to update the unactivated system.
-- @param world -- @param world
-- @param system A System in the World activate/deactivate -- @param ... Systems to activate. The Systems must already be added to the
-- @param active Boolean new state of the System -- World.
function tiny.setSystemActive(world, system, active) function tiny.activate(world, ...)
world.activeSystems[system] = active and true or nil local args = {...}
for _, obj in ipairs(args) do
world.activeSystems[obj] = true
end
end
--- Deactivates Systems in the World.
-- Deactivated Systems must be update manually, and will not update when the
-- rest of World updates. They will, however, process new Entities added while
-- the System is deactivated.
-- @param world
-- @param ... Systems to deactivate. The Systems must already be added to the
-- World.
function tiny.deactivate(world, ...)
local args = {...}
for _, obj in ipairs(args) do
world.activeSystems[obj] = nil
end
end end
return tiny return tiny