-
-
tiny.lua
-
-local tiny = {}
-
-tiny._VERSION = "0.3.0"
-
-local tinsert = table.insert
-local tremove = table.remove
-local tconcat = table.concat
-local pairs = pairs
-local ipairs = ipairs
-local setmetatable = setmetatable
-local getmetatable = getmetatable
-
-local tiny_system
-local tiny_manageEntities
-local tiny_manageSystems
-local tiny_updateSystem
-local tiny_add
-local tiny_remove
-
-
-function tiny.requireAll(...)
- local components = {...}
- local len = #components
- return function(e)
- local c
- for i = 1, len do
- c = components[i]
- if e[c] == nil then
- return false
- end
- end
- return true
- end
-end
-
-function tiny.requireOne(...)
- local components = {...}
- local len = #components
- return function(e)
- local c
- for i = 1, len do
- c = components[i]
- if e[c] ~= nil then
- return true
- end
- end
- return false
- end
-end
-
-
-local systemMetaTable = {}
-
-function tiny.system(callback, filter, entityCallback, onAdd, onRemove)
- local ret = {
- callback = callback,
- filter = filter,
- entityCallback = entityCallback,
- onAdd = onAdd,
- onRemove = onRemove
- }
- setmetatable(ret, systemMetaTable)
- return ret
-end
-tiny_system = tiny.system
-
-function tiny.processingSystem(filter, entityCallback, onAdd, onRemove)
- return tiny_system(nil, filter, entityCallback, onAdd, onRemove)
-end
-
-local worldMetaTable = { __index = tiny }
-
-
-function tiny.world(...)
-
- local ret = {
-
- status = {},
-
- entities = {},
-
- entityCount = 0,
-
- systemCount = 0,
-
- systems = {},
-
- activeSystems = {},
-
- systemIndices = {},
-
- systemEntities = {},
-
- systemsToAdd = {},
-
- systemsToRemove = {}
-
- }
-
- tiny.add(ret, ...)
- tiny.manageSystems(ret)
- tiny.manageEntities(ret)
-
- setmetatable(ret, worldMetaTable)
- return ret
-
-end
-
-function tiny.add(world, ...)
- local args = {...}
- local status = world.status
- local entities = world.entities
- local systemsToAdd = world.systemsToAdd
- for _, obj in ipairs(args) do
- if getmetatable(obj) == systemMetaTable then
- tinsert(systemsToAdd, obj)
- else entities[obj] = true
- status[obj] = "add"
- end
- end
-end
-tiny_add = tiny.add
-
-function tiny.remove(world, ...)
- local args = {...}
- local status = world.status
- local entities = world.entities
- local systemsToRemove = world.systemsToRemove
- for _, obj in ipairs(args) do
- if getmetatable(obj) == systemMetaTable then
- tinsert(systemsToRemove, obj)
- elseif entities[obj] then status[obj] = "remove"
- end
- end
-end
-tiny_remove = tiny.remove
-
-function tiny.updateSystem(world, system, dt)
- local callback = system.callback
- local entityCallback = system.entityCallback
-
- if callback then
- callback(dt)
- end
-
- if entityCallback then
- local entities = world.entities
- local es = world.systemEntities[system]
- if es then
- for e in pairs(es) do
- entityCallback(e, dt)
- end
- end
- end
-end
-tiny_updateSystem = tiny.updateSystem
-
-function tiny.manageSystems(world)
-
- local systemEntities = world.systemEntities
- local systemIndices = world.systemIndices
- local entities = world.entities
- local systems = world.systems
- local systemsToAdd = world.systemsToAdd
- local systemsToRemove = world.systemsToRemove
- local activeSystems = world.activeSystems
-
- local deltaSystemCount = 0
-
- for i = 1, #systemsToRemove do
- local sys = systemsToRemove[i]
- systemsToRemove[i] = nil
-
- local sysID = systemIndices[sys]
- 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
-
- for i = 1, #systemsToAdd do
- local sys = systemsToAdd[i]
- systemsToAdd[i] = nil
-
- local es = {}
- systemEntities[sys] = es
- tinsert(systems, sys)
- systemIndices[sys] = #systems
- activeSystems[sys] = true
-
- local filter = sys.filter
- if filter then
- for e in pairs(entities) do
- es[e] = filter(e) and true or nil
- end
- end
-
- deltaSystemCount = deltaSystemCount + 1
- end
-
- world.systemCount = world.systemCount + deltaSystemCount
-end
-tiny_manageSystems = tiny.manageSystems
-
-function tiny.manageEntities(world)
-
- local statuses = world.status
- local systemEntities = world.systemEntities
- local entities = world.entities
- local systems = world.systems
-
- local deltaEntityCount = 0
-
- for e, s in pairs(statuses) do
- if s == "add" then
- deltaEntityCount = deltaEntityCount + 1
- for sys, es in pairs(systemEntities) do
- local filter = sys.filter
- if filter then
- local matches = filter(e) and true or nil
- local onAdd = sys.onAdd
- if onAdd and matches and not es[e] then
- onAdd(e)
- end
- es[e] = matches
- end
- end
- elseif s == "remove" then
- deltaEntityCount = deltaEntityCount - 1
- entities[e] = nil
- for sys, es in pairs(systemEntities) do
- local onRemove = sys.onRemove
- if es[e] and onRemove then
- onRemove(e)
- end
- es[e] = nil
- end
- end
- statuses[e] = nil
- end
-
- world.entityCount = world.entityCount + deltaEntityCount
-
-end
-tiny_manageEntities = tiny.manageEntities
-
-function tiny.update(world, dt)
-
- tiny_manageSystems(world)
- tiny_manageEntities(world)
-
- for _, s in ipairs(world.systems) do
- if world.activeSystems[s] then
- tiny_updateSystem(world, s, dt)
- end
- end
-end
-
-function tiny.clearEntities(world)
- local status = world.status
- for e in pairs(world.entities) do
- status[e] = "remove"
- end
-end
-
-function tiny.clearSystems(world)
- local newSystemsToRemove = {}
- local systems = world.systems
- for i = 1, #systems do
- newSystemsToRemove[i] = systems[i]
- end
- world.systemsToRemove = newSystemsToRemove
-end
-
-function tiny.setSystemActive(world, system, active)
- world.activeSystem[system] = active and true or nil
-end
-
-return tiny
-
-
-