mirror of
https://github.com/bakpakin/tiny-ecs.git
synced 2026-07-22 07:56:52 -06:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08e5f13d85 | ||
|
|
cbf71d2cb2 | ||
|
|
93a19d93c8 | ||
|
|
4148855233 | ||
|
|
27f881444a | ||
|
|
3b4bd9920b | ||
|
|
206361ca38 | ||
|
|
29158282bd | ||
|
|
2403a9019c | ||
|
|
6234e4b741 | ||
|
|
b870b5a34e | ||
|
|
f3b16a40f6 | ||
|
|
5035d2c8a7 | ||
|
|
18270cd60a | ||
|
|
dba8e7c89f | ||
|
|
fccff0329e | ||
|
|
8a759edca2 | ||
|
|
d9d311d858 | ||
|
|
9834dfa9d6 | ||
|
|
a5af4b6ecd | ||
|
|
f0e6ce7880 | ||
|
|
26f8259f2b | ||
|
|
b1c7e2ba83 | ||
|
|
6b549fcbc1 | ||
|
|
b9d994ad50 | ||
|
|
ce8ca35f7e | ||
|
|
19ae03707f |
+39
@@ -0,0 +1,39 @@
|
|||||||
|
language: erlang
|
||||||
|
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- LUAROCKS_BASE=luarocks-2.2.2
|
||||||
|
matrix:
|
||||||
|
- LUA=lua5.1 LUA_DEV=liblua5.1-dev LUA_VER=5.1 LUA_SFX=5.1 LUA_INCDIR=/usr/include/lua5.1
|
||||||
|
- LUA=lua5.2 LUA_DEV=liblua5.2-dev LUA_VER=5.2 LUA_SFX=5.2 LUA_INCDIR=/usr/include/lua5.2
|
||||||
|
- LUA=luajit LUA_DEV=libluajit-5.1-dev LUA_VER=5.1 LUA_SFX=jit LUA_INCDIR=/usr/include/luajit-2.0
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- if [ $LUA = "luajit" ]; then
|
||||||
|
sudo add-apt-repository ppa:mwild1/ppa -y && sudo apt-get update -y;
|
||||||
|
sudo apt-get install lua5.1;
|
||||||
|
sudo apt-get install liblua5.1-dev;
|
||||||
|
fi
|
||||||
|
- sudo apt-get install $LUA
|
||||||
|
- sudo apt-get install $LUA_DEV
|
||||||
|
- lua$LUA_SFX -v
|
||||||
|
# Install a recent luarocks release
|
||||||
|
- wget http://luarocks.org/releases/$LUAROCKS_BASE.tar.gz
|
||||||
|
- tar zxvpf $LUAROCKS_BASE.tar.gz
|
||||||
|
- cd $LUAROCKS_BASE
|
||||||
|
- ./configure
|
||||||
|
--lua-version=$LUA_VER --lua-suffix=$LUA_SFX --with-lua-include="$LUA_INCDIR"
|
||||||
|
- sudo make
|
||||||
|
- sudo make install
|
||||||
|
- cd $TRAVIS_BUILD_DIR
|
||||||
|
|
||||||
|
install:
|
||||||
|
- sudo -E luarocks install busted
|
||||||
|
|
||||||
|
script:
|
||||||
|
- sudo -E busted -v
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
email:
|
||||||
|
on_success: change
|
||||||
|
on_failure: always
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2015 Calvin Rose
|
Copyright (c) 2016 Calvin Rose
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# tiny-ecs #
|
# tiny-ecs #
|
||||||
|
|
||||||
|
[](https://travis-ci.org/bakpakin/tiny-ecs)
|
||||||
|
|
||||||
[](LICENSE)
|
[](LICENSE)
|
||||||
|
|
||||||
Tiny-ecs is an Entity Component System for lua that's simple, flexible, and useful.
|
Tiny-ecs is an Entity Component System for lua that's simple, flexible, and useful.
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package = "tiny-ecs"
|
||||||
|
version = "1.1-6"
|
||||||
|
source = {
|
||||||
|
url = "git://github.com/bakpakin/tiny-ecs",
|
||||||
|
tag = "1.1-6"
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Entity Component System for Lua.",
|
||||||
|
detailed = [[
|
||||||
|
Pure Lua implementation of an easy to use, compact, fast, and flexible
|
||||||
|
Entity Component System. Works well with Object Orientation.
|
||||||
|
]],
|
||||||
|
homepage = "https://github.com/bakpakin/tiny-ecs",
|
||||||
|
license = "MIT"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1"
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
tiny = "tiny.lua"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package = "tiny-ecs"
|
||||||
|
version = "1.1-7"
|
||||||
|
source = {
|
||||||
|
url = "git://github.com/bakpakin/tiny-ecs",
|
||||||
|
tag = "1.1-7"
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Entity Component System for Lua.",
|
||||||
|
detailed = [[
|
||||||
|
Pure Lua implementation of an easy to use, compact, fast, and flexible
|
||||||
|
Entity Component System. Works well with Object Orientation.
|
||||||
|
]],
|
||||||
|
homepage = "https://github.com/bakpakin/tiny-ecs",
|
||||||
|
license = "MIT"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1"
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
tiny = "tiny.lua"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package = "tiny-ecs"
|
||||||
|
version = "1.2-1"
|
||||||
|
source = {
|
||||||
|
url = "git://github.com/bakpakin/tiny-ecs",
|
||||||
|
tag = "1.2-1"
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Entity Component System for Lua.",
|
||||||
|
detailed = [[
|
||||||
|
Pure Lua implementation of an easy to use, compact, fast, and flexible
|
||||||
|
Entity Component System. Works well with Object Orientation.
|
||||||
|
]],
|
||||||
|
homepage = "https://github.com/bakpakin/tiny-ecs",
|
||||||
|
license = "MIT"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1"
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
tiny = "tiny.lua"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package = "tiny-ecs"
|
||||||
|
version = "1.3-1"
|
||||||
|
source = {
|
||||||
|
url = "git://github.com/bakpakin/tiny-ecs",
|
||||||
|
tag = "1.3-1"
|
||||||
|
}
|
||||||
|
description = {
|
||||||
|
summary = "Entity Component System for Lua.",
|
||||||
|
detailed = [[
|
||||||
|
Pure Lua implementation of an easy to use, compact, fast, and flexible
|
||||||
|
Entity Component System. Works well with Object Orientation.
|
||||||
|
]],
|
||||||
|
homepage = "https://github.com/bakpakin/tiny-ecs",
|
||||||
|
license = "MIT"
|
||||||
|
}
|
||||||
|
dependencies = {
|
||||||
|
"lua >= 5.1"
|
||||||
|
}
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
tiny = "tiny.lua"
|
||||||
|
}
|
||||||
|
}
|
||||||
+65
-6
@@ -1,3 +1,8 @@
|
|||||||
|
local GLOBALS = {}
|
||||||
|
for k, v in pairs(_G) do
|
||||||
|
GLOBALS[k] = v
|
||||||
|
end
|
||||||
|
|
||||||
local tiny = require "tiny"
|
local tiny = require "tiny"
|
||||||
|
|
||||||
local function deep_copy(x)
|
local function deep_copy(x)
|
||||||
@@ -85,6 +90,49 @@ describe('tiny-ecs:', function()
|
|||||||
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it("Can use functions as subfilters", function()
|
||||||
|
|
||||||
|
local f1 = tiny.requireAny('a', 'b', 'c')
|
||||||
|
local f2 = tiny.requireAll('x', 'y', 'z')
|
||||||
|
local f = tiny.requireAll(f1, f2)
|
||||||
|
|
||||||
|
assert.truthy(f(nil, {
|
||||||
|
x = true, y = true, z = true, a = true, b = true, c = true
|
||||||
|
}))
|
||||||
|
assert.truthy(f(nil, {
|
||||||
|
x = true, y = true, z = true, a = true
|
||||||
|
}))
|
||||||
|
assert.falsy(f(nil, {
|
||||||
|
x = true, y = true, a = true
|
||||||
|
}))
|
||||||
|
assert.falsy(f(nil, {
|
||||||
|
x = true, y = true, z = true
|
||||||
|
}))
|
||||||
|
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("Can use string filters", function()
|
||||||
|
|
||||||
|
local f = tiny.filter('a|b|c')
|
||||||
|
|
||||||
|
assert.truthy(f(nil, {
|
||||||
|
a = true, b = true, c = true
|
||||||
|
}))
|
||||||
|
assert.truthy(f(nil, {
|
||||||
|
a = true
|
||||||
|
}))
|
||||||
|
assert.truthy(f(nil, {
|
||||||
|
b = true
|
||||||
|
}))
|
||||||
|
assert.truthy(f(nil, {
|
||||||
|
c = true
|
||||||
|
}))
|
||||||
|
assert.falsy(f(nil, {
|
||||||
|
x = true, y = true, z = true
|
||||||
|
}))
|
||||||
|
|
||||||
|
end)
|
||||||
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('World:', function()
|
describe('World:', function()
|
||||||
@@ -115,6 +163,11 @@ describe('tiny-ecs:', function()
|
|||||||
timePassed = 0
|
timePassed = 0
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
after_each(function()
|
||||||
|
world:clearSystems()
|
||||||
|
world:refresh()
|
||||||
|
end)
|
||||||
|
|
||||||
it("Create World", function()
|
it("Create World", function()
|
||||||
assert.equals(world:getEntityCount(), 3)
|
assert.equals(world:getEntityCount(), 3)
|
||||||
assert.equals(world:getSystemCount(), 2)
|
assert.equals(world:getSystemCount(), 2)
|
||||||
@@ -180,9 +233,11 @@ describe('tiny-ecs:', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
it("Remove Entities Multiple Times", function()
|
it("Remove Entities Multiple Times", function()
|
||||||
|
assert.equals(3, world:getEntityCount())
|
||||||
world:update(1)
|
world:update(1)
|
||||||
world:remove(entity1, entity2, entity3)
|
world:remove(entity1, entity2, entity3)
|
||||||
world:update(2)
|
world:update(2)
|
||||||
|
assert.equals(0, world:getEntityCount())
|
||||||
world:remove(entity1, entity2, entity3)
|
world:remove(entity1, entity2, entity3)
|
||||||
world:update(2)
|
world:update(2)
|
||||||
assert.equals(2, world:getSystemCount())
|
assert.equals(2, world:getSystemCount())
|
||||||
@@ -191,7 +246,7 @@ describe('tiny-ecs:', function()
|
|||||||
|
|
||||||
it("Add Systems Multiple Times", function()
|
it("Add Systems Multiple Times", function()
|
||||||
world:update(1)
|
world:update(1)
|
||||||
world:add(moveSystem, oneTimeSystem)
|
assert.has_error(function() world:add(moveSystem, oneTimeSystem) end, "System already belongs to a World.")
|
||||||
world:update(2)
|
world:update(2)
|
||||||
assert.equals(2, world:getSystemCount())
|
assert.equals(2, world:getSystemCount())
|
||||||
assert.equals(3, world:getEntityCount())
|
assert.equals(3, world:getEntityCount())
|
||||||
@@ -201,7 +256,7 @@ describe('tiny-ecs:', function()
|
|||||||
world:update(1)
|
world:update(1)
|
||||||
world:remove(moveSystem)
|
world:remove(moveSystem)
|
||||||
world:update(2)
|
world:update(2)
|
||||||
world:remove(moveSystem)
|
assert.has_error(function() world:remove(moveSystem) end, "System does not belong to this World.")
|
||||||
world:update(2)
|
world:update(2)
|
||||||
assert.equals(1, world:getSystemCount())
|
assert.equals(1, world:getSystemCount())
|
||||||
assert.equals(3, world:getEntityCount())
|
assert.equals(3, world:getEntityCount())
|
||||||
@@ -211,18 +266,18 @@ describe('tiny-ecs:', function()
|
|||||||
world:update(1)
|
world:update(1)
|
||||||
world:setSystemIndex(moveSystem, 2)
|
world:setSystemIndex(moveSystem, 2)
|
||||||
world:update(1)
|
world:update(1)
|
||||||
assert.equals(2, world:getSystemIndex(moveSystem))
|
assert.equals(2, moveSystem.index)
|
||||||
assert.equals(1, world:getSystemIndex(oneTimeSystem))
|
assert.equals(1, oneTimeSystem.index)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("Sorts Entities in Sorting Systems", function()
|
it("Sorts Entities in Sorting Systems", function()
|
||||||
local sortsys = tiny.sortedProcessingSystem()
|
local sortsys = tiny.sortedProcessingSystem()
|
||||||
sortsys.filter = tiny.requireAll("vel")
|
sortsys.filter = tiny.filter("vel|xform")
|
||||||
function sortsys:compare(e1, e2)
|
function sortsys:compare(e1, e2)
|
||||||
return e1.vel.x < e2.vel.x
|
return e1.vel.x < e2.vel.x
|
||||||
end
|
end
|
||||||
world:add(sortsys)
|
world:add(sortsys)
|
||||||
world:update(0)
|
world:refresh()
|
||||||
assert.equals(sortsys.entities[1], entity2)
|
assert.equals(sortsys.entities[1], entity2)
|
||||||
assert.equals(sortsys.entities[2], entity3)
|
assert.equals(sortsys.entities[2], entity3)
|
||||||
assert.equals(sortsys.entities[3], entity1)
|
assert.equals(sortsys.entities[3], entity1)
|
||||||
@@ -230,4 +285,8 @@ describe('tiny-ecs:', function()
|
|||||||
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it("Doesn't pollute the global namespace", function()
|
||||||
|
assert.are.same(_G, GLOBALS)
|
||||||
|
end)
|
||||||
|
|
||||||
end)
|
end)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
--[[
|
--[[
|
||||||
Copyright (c) 2015 Calvin Rose
|
Copyright (c) 2016 Calvin Rose
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
@@ -23,13 +23,12 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||||||
-- @author Calvin Rose
|
-- @author Calvin Rose
|
||||||
-- @license MIT
|
-- @license MIT
|
||||||
-- @copyright 2015
|
-- @copyright 2015
|
||||||
local tiny = { _VERSION = "1.1-5" }
|
local tiny = { _VERSION = "scm" }
|
||||||
|
|
||||||
-- Local versions of standard lua functions
|
-- Local versions of standard lua functions
|
||||||
local tinsert = table.insert
|
local tinsert = table.insert
|
||||||
local tremove = table.remove
|
local tremove = table.remove
|
||||||
local tsort = table.sort
|
local tsort = table.sort
|
||||||
local pairs = pairs
|
|
||||||
local setmetatable = setmetatable
|
local setmetatable = setmetatable
|
||||||
local type = type
|
local type = type
|
||||||
local select = select
|
local select = select
|
||||||
@@ -85,88 +84,121 @@ local tiny_remove
|
|||||||
--
|
--
|
||||||
-- @section Filter
|
-- @section Filter
|
||||||
|
|
||||||
|
-- A helper function to compile filters.
|
||||||
|
local filterJoin
|
||||||
|
|
||||||
|
-- A helper function to filters from string
|
||||||
|
local filterBuildString
|
||||||
|
|
||||||
|
do
|
||||||
|
|
||||||
|
local loadstring = loadstring or load
|
||||||
|
local function getchr(c)
|
||||||
|
return "\\" .. c:byte()
|
||||||
|
end
|
||||||
|
local function make_safe(text)
|
||||||
|
return ("%q"):format(text):gsub('\n', 'n'):gsub("[\128-\255]", getchr)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function filterJoinRaw(prefix, seperator, ...)
|
||||||
|
local accum = {}
|
||||||
|
local build = {}
|
||||||
|
for i = 1, select('#', ...) do
|
||||||
|
local item = select(i, ...)
|
||||||
|
if type(item) == 'string' then
|
||||||
|
accum[#accum + 1] = ("(e[%s] ~= nil)"):format(make_safe(item))
|
||||||
|
elseif type(item) == 'function' then
|
||||||
|
build[#build + 1] = ('local subfilter_%d_ = select(%d, ...)'):format(i, i)
|
||||||
|
accum[#accum + 1] = ('(subfilter_%d_(system, e))'):format(i)
|
||||||
|
else
|
||||||
|
error 'Filter token must be a string or a filter function.'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local source = ('do %s\n return function(system, e) return %s(%s) end end'):format(
|
||||||
|
table.concat(build, '\n'),
|
||||||
|
prefix,
|
||||||
|
table.concat(accum, seperator)
|
||||||
|
)
|
||||||
|
local loader, err = loadstring(source)
|
||||||
|
if err then error(err) end
|
||||||
|
return loader(...)
|
||||||
|
end
|
||||||
|
|
||||||
|
function filterJoin(...)
|
||||||
|
local state, value = pcall(filterJoinRaw, ...)
|
||||||
|
if state then return value else return nil, value end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function buildPart(str)
|
||||||
|
local accum = {}
|
||||||
|
local subParts = {}
|
||||||
|
str = str:gsub('%b()', function(p)
|
||||||
|
subParts[#subParts + 1] = buildPart(p:sub(2, -2))
|
||||||
|
return ('\255%d'):format(#subParts)
|
||||||
|
end)
|
||||||
|
for invert, part, sep in str:gmatch('(%!?)([^%|%&%!]+)([%|%&%!]?)') do
|
||||||
|
if part:match('^\255%d+$') then
|
||||||
|
local partIndex = tonumber(part:match(part:sub(2)))
|
||||||
|
accum[#accum + 1] = ('%s(%s)'):format(invert == '' and '' or 'not', subParts[partIndex])
|
||||||
|
else
|
||||||
|
accum[#accum + 1] = ("(e[%s] %s nil)"):format(make_safe(part), invert == '' and '~=' or '==')
|
||||||
|
end
|
||||||
|
if sep ~= '' then
|
||||||
|
accum[#accum + 1] = (sep == '|' and ' or ' or ' and ')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return table.concat(accum)
|
||||||
|
end
|
||||||
|
|
||||||
|
function filterBuildString(str)
|
||||||
|
local source = ("return function(_, e) return %s end"):format(buildPart(str))
|
||||||
|
local loader, err = loadstring(source)
|
||||||
|
if err then
|
||||||
|
error(err)
|
||||||
|
end
|
||||||
|
return loader()
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- Makes a Filter that selects Entities with all specified Components and
|
--- Makes a Filter that selects Entities with all specified Components and
|
||||||
-- Filters.
|
-- Filters.
|
||||||
function tiny.requireAll(...)
|
function tiny.requireAll(...)
|
||||||
local components = {...}
|
return filterJoin('', ' and ', ...)
|
||||||
local len = #components
|
|
||||||
return function(system, e)
|
|
||||||
local c
|
|
||||||
for i = 1, len do
|
|
||||||
c = components[i]
|
|
||||||
if type(c) == 'function' then
|
|
||||||
if not c(system, e) then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
elseif e[c] == nil then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Makes a Filter that selects Entities with at least one of the specified
|
--- Makes a Filter that selects Entities with at least one of the specified
|
||||||
-- Components and Filters.
|
-- Components and Filters.
|
||||||
function tiny.requireAny(...)
|
function tiny.requireAny(...)
|
||||||
local components = {...}
|
return filterJoin('', ' or ', ...)
|
||||||
local len = #components
|
|
||||||
return function(system, e)
|
|
||||||
local c
|
|
||||||
for i = 1, len do
|
|
||||||
c = components[i]
|
|
||||||
if type(c) == 'function' then
|
|
||||||
if c(system, e) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
elseif e[c] ~= nil then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Makes a Filter that rejects Entities with all specified Components and
|
--- Makes a Filter that rejects Entities with all specified Components and
|
||||||
-- Filters, and selects all other Entities.
|
-- Filters, and selects all other Entities.
|
||||||
function tiny.rejectAll(...)
|
function tiny.rejectAll(...)
|
||||||
local components = {...}
|
return filterJoin('not', ' and ', ...)
|
||||||
local len = #components
|
|
||||||
return function(system, e)
|
|
||||||
local c
|
|
||||||
for i = 1, len do
|
|
||||||
c = components[i]
|
|
||||||
if type(c) == 'function' then
|
|
||||||
if not c(system, e) then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
elseif e[c] == nil then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Makes a Filter that rejects Entities with at least one of the specified
|
--- Makes a Filter that rejects Entities with at least one of the specified
|
||||||
-- Components and Filters, and selects all other Entities.
|
-- Components and Filters, and selects all other Entities.
|
||||||
function tiny.rejectAny(...)
|
function tiny.rejectAny(...)
|
||||||
local components = {...}
|
return filterJoin('not', ' or ', ...)
|
||||||
local len = #components
|
end
|
||||||
return function(system, e)
|
|
||||||
local c
|
--- Makes a Filter from a string. Syntax of `pattern` is as follows.
|
||||||
for i = 1, len do
|
--
|
||||||
c = components[i]
|
-- * Tokens are alphanumeric strings including underscores.
|
||||||
if type(c) == 'function' then
|
-- * Tokens can be separated by |, &, or surrounded by parentheses.
|
||||||
if c(system, e) then
|
-- * Tokens can be prefixed with !, and are then operated on with a boolean 'not'.
|
||||||
return false
|
--
|
||||||
end
|
-- Examples are best:
|
||||||
elseif e[c] ~= nil then
|
-- 'a|b|c' - Matches entities with an 'a' component OR a 'b' component or a 'c' component.
|
||||||
return false
|
-- 'a&!b&c' - Matches entities with an 'a' component AND NOT a 'b' component AND a 'c' component.
|
||||||
end
|
-- 'a|(b&c&d)|e - Matches 'a' OR ('b' AND 'c' AND 'd') OR 'e'
|
||||||
end
|
-- @param pattern
|
||||||
return true
|
function tiny.filter(pattern)
|
||||||
end
|
local state, value = pcall(filterBuildString, pattern)
|
||||||
|
if state then return value else return nil, value end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- System functions.
|
--- System functions.
|
||||||
@@ -187,6 +219,10 @@ end
|
|||||||
-- from the System.
|
-- from the System.
|
||||||
-- * `function system:onModify(dt)` - Called when the System is modified by
|
-- * `function system:onModify(dt)` - Called when the System is modified by
|
||||||
-- adding or removing Entities from the System.
|
-- adding or removing Entities from the System.
|
||||||
|
-- * `function system:onAddToWorld(world)` - Called when the System is added
|
||||||
|
-- to the World, before any entities are added to the system.
|
||||||
|
-- * `function system:onRemoveFromWorld(world)` - Called when the System is
|
||||||
|
-- removed from the world, after all Entities are removed from the System.
|
||||||
--
|
--
|
||||||
-- For Filters, it is convenient to use `tiny.requireAll` or `tiny.requireAny`,
|
-- For Filters, it is convenient to use `tiny.requireAll` or `tiny.requireAny`,
|
||||||
-- but one can write their own filters as well. Set the Filter of a System like
|
-- but one can write their own filters as well. Set the Filter of a System like
|
||||||
@@ -206,12 +242,15 @@ end
|
|||||||
-- * The `active` flag is whether or not the System is updated automatically.
|
-- * The `active` flag is whether or not the System is updated automatically.
|
||||||
-- Inactive Systems should be updated manually or not at all via
|
-- Inactive Systems should be updated manually or not at all via
|
||||||
-- `system:update(dt)`. Defaults to true.
|
-- `system:update(dt)`. Defaults to true.
|
||||||
-- * The 'entities' field is an ordered list of Entities in the System. This
|
-- * The `entities` field is an ordered list of Entities in the System. This
|
||||||
-- list can be used to quickly iterate through all Entities in a System.
|
-- list can be used to quickly iterate through all Entities in a System.
|
||||||
-- * The `interval` field is an optional field that makes Systems update at
|
-- * The `interval` field is an optional field that makes Systems update at
|
||||||
-- certain intervals using buffered time, regardless of World update frequency.
|
-- certain intervals using buffered time, regardless of World update frequency.
|
||||||
-- For example, to make a System update once a second, set the System's interval
|
-- For example, to make a System update once a second, set the System's interval
|
||||||
-- to 1.
|
-- to 1.
|
||||||
|
-- * The `index` field is the System's index in the World. Lower indexed
|
||||||
|
-- Systems are processed before higher indices. The `index` is a read only
|
||||||
|
-- field; to set the `index`, use `tiny.setSystemIndex(world, system)`.
|
||||||
-- * The `indices` field is a table of Entity keys to their indices in the
|
-- * The `indices` field is a table of Entity keys to their indices in the
|
||||||
-- `entities` list. Most Systems can ignore this.
|
-- `entities` list. Most Systems can ignore this.
|
||||||
-- * The `modified` flag is an indicator if the System has been modified in
|
-- * The `modified` flag is an indicator if the System has been modified in
|
||||||
@@ -232,21 +271,31 @@ end
|
|||||||
|
|
||||||
-- Update function for all Processing Systems.
|
-- Update function for all Processing Systems.
|
||||||
local function processingSystemUpdate(system, dt)
|
local function processingSystemUpdate(system, dt)
|
||||||
local entities = system.entities
|
|
||||||
local preProcess = system.preProcess
|
local preProcess = system.preProcess
|
||||||
local process = system.process
|
local process = system.process
|
||||||
local postProcess = system.postProcess
|
local postProcess = system.postProcess
|
||||||
local entity
|
|
||||||
|
|
||||||
if preProcess then
|
if preProcess then
|
||||||
preProcess(system, dt)
|
preProcess(system, dt)
|
||||||
end
|
end
|
||||||
|
|
||||||
if process then
|
if process then
|
||||||
local len = #entities
|
if system.nocache then
|
||||||
for i = 1, len do
|
local entities = system.world.entityList
|
||||||
entity = entities[i]
|
local filter = system.filter
|
||||||
process(system, entity, dt)
|
if filter then
|
||||||
|
for i = 1, #entities do
|
||||||
|
local entity = entities[i]
|
||||||
|
if filter(system, entity) then
|
||||||
|
process(system, entity, dt)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local entities = system.entities
|
||||||
|
for i = 1, #entities do
|
||||||
|
process(system, entities[i], dt)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -255,7 +304,7 @@ local function processingSystemUpdate(system, dt)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Sorts Systems by a function system.sort(entity1, entity2) on modify.
|
-- Sorts Systems by a function system.sortDelegate(entity1, entity2) on modify.
|
||||||
local function sortedSystemOnModify(system, dt)
|
local function sortedSystemOnModify(system, dt)
|
||||||
local entities = system.entities
|
local entities = system.entities
|
||||||
local indices = system.indices
|
local indices = system.indices
|
||||||
@@ -269,8 +318,7 @@ local function sortedSystemOnModify(system, dt)
|
|||||||
end
|
end
|
||||||
tsort(entities, sortDelegate)
|
tsort(entities, sortDelegate)
|
||||||
for i = 1, #entities do
|
for i = 1, #entities do
|
||||||
local entity = entities[i]
|
indices[entities[i]] = i
|
||||||
indices[entity] = i
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -287,9 +335,9 @@ end
|
|||||||
-- Processing Systems have three extra callbacks besides those inheritted from
|
-- Processing Systems have three extra callbacks besides those inheritted from
|
||||||
-- vanilla Systems.
|
-- vanilla Systems.
|
||||||
--
|
--
|
||||||
-- function system:preProcess(entities, dt) -- Called before iteration.
|
-- function system:preProcess(dt) -- Called before iteration.
|
||||||
-- function system:process(entities, dt) -- Process each entity.
|
-- function system:process(entity, dt) -- Process each entity.
|
||||||
-- function system:postProcess(entity, dt) -- Called after iteration.
|
-- function system:postProcess(dt) -- Called after iteration.
|
||||||
--
|
--
|
||||||
-- Processing Systems have their own `update` method, so don't implement a
|
-- Processing Systems have their own `update` method, so don't implement a
|
||||||
-- a custom `update` callback for Processing Systems.
|
-- a custom `update` callback for Processing Systems.
|
||||||
@@ -342,9 +390,10 @@ end
|
|||||||
local worldMetaTable
|
local worldMetaTable
|
||||||
|
|
||||||
--- Creates a new World.
|
--- Creates a new World.
|
||||||
-- Can optionally add default Systems and Entities.
|
-- Can optionally add default Systems and Entities. Returns the new World along
|
||||||
|
-- with default Entities and Systems.
|
||||||
function tiny.world(...)
|
function tiny.world(...)
|
||||||
local ret = {
|
local ret = setmetatable({
|
||||||
|
|
||||||
-- List of Entities to add
|
-- List of Entities to add
|
||||||
entitiesToAdd = {},
|
entitiesToAdd = {},
|
||||||
@@ -352,6 +401,9 @@ function tiny.world(...)
|
|||||||
-- List of Entities to remove
|
-- List of Entities to remove
|
||||||
entitiesToRemove = {},
|
entitiesToRemove = {},
|
||||||
|
|
||||||
|
-- List of Entities to change
|
||||||
|
entitiesToChange = {},
|
||||||
|
|
||||||
-- List of Entities to add
|
-- List of Entities to add
|
||||||
systemsToAdd = {},
|
systemsToAdd = {},
|
||||||
|
|
||||||
@@ -361,48 +413,53 @@ function tiny.world(...)
|
|||||||
-- Set of Entities
|
-- Set of Entities
|
||||||
entities = {},
|
entities = {},
|
||||||
|
|
||||||
-- Number of Entities in World.
|
-- List of Entities
|
||||||
|
entityList = {},
|
||||||
|
|
||||||
|
-- Number of Entities in World
|
||||||
entityCount = 0,
|
entityCount = 0,
|
||||||
|
|
||||||
-- List of System Data. A data element is a table with 4
|
-- List of Systems
|
||||||
-- keys: system, indices, entities, and active.
|
systems = {}
|
||||||
systems = {},
|
}, worldMetaTable)
|
||||||
|
|
||||||
-- Table of Systems to System Indices
|
|
||||||
systemIndices = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
tiny_add(ret, ...)
|
tiny_add(ret, ...)
|
||||||
tiny_manageSystems(ret)
|
tiny_manageSystems(ret)
|
||||||
tiny_manageEntities(ret)
|
tiny_manageEntities(ret)
|
||||||
|
|
||||||
return setmetatable(ret, worldMetaTable)
|
return ret, ...
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Adds an Entity to the world.
|
--- Adds an Entity to the world.
|
||||||
-- Also call this on Entities that have changed Components such that they
|
-- Also call this on Entities that have changed Components such that they
|
||||||
-- match different Filters.
|
-- match different Filters. Returns the Entity.
|
||||||
function tiny.addEntity(world, entity)
|
function tiny.addEntity(world, entity)
|
||||||
local e2a = world.entitiesToAdd
|
|
||||||
e2a[#e2a + 1] = entity
|
|
||||||
if world.entities[entity] then
|
if world.entities[entity] then
|
||||||
tiny_removeEntity(world, entity)
|
local e2c = world.entitiesToChange
|
||||||
|
e2c[#e2c + 1] = entity
|
||||||
|
else
|
||||||
|
local e2a = world.entitiesToAdd
|
||||||
|
e2a[#e2a + 1] = entity
|
||||||
end
|
end
|
||||||
|
return entity
|
||||||
end
|
end
|
||||||
tiny_addEntity = tiny.addEntity
|
tiny_addEntity = tiny.addEntity
|
||||||
|
|
||||||
--- Adds a System to the world.
|
--- Adds a System to the world. Returns the System.
|
||||||
function tiny.addSystem(world, system)
|
function tiny.addSystem(world, system)
|
||||||
|
assert(system.world == nil, "System already belongs to a World.")
|
||||||
local s2a = world.systemsToAdd
|
local s2a = world.systemsToAdd
|
||||||
s2a[#s2a + 1] = system
|
s2a[#s2a + 1] = system
|
||||||
|
system.world = world
|
||||||
|
return system
|
||||||
end
|
end
|
||||||
tiny_addSystem = tiny.addSystem
|
tiny_addSystem = tiny.addSystem
|
||||||
|
|
||||||
--- Shortcut for adding multiple Entities and Systems to the World.
|
--- Shortcut for adding multiple Entities and Systems to the World. Returns all
|
||||||
|
-- added Entities and Systems.
|
||||||
function tiny.add(world, ...)
|
function tiny.add(world, ...)
|
||||||
local obj
|
|
||||||
for i = 1, select("#", ...) do
|
for i = 1, select("#", ...) do
|
||||||
obj = select(i, ...)
|
local obj = select(i, ...)
|
||||||
if obj then
|
if obj then
|
||||||
if isSystem(obj) then
|
if isSystem(obj) then
|
||||||
tiny_addSystem(world, obj)
|
tiny_addSystem(world, obj)
|
||||||
@@ -411,104 +468,119 @@ function tiny.add(world, ...)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return ...
|
||||||
end
|
end
|
||||||
tiny_add = tiny.add
|
tiny_add = tiny.add
|
||||||
|
|
||||||
--- Removes an Entity to the World.
|
--- Removes an Entity to the World. Returns the Entity.
|
||||||
function tiny.removeEntity(world, entity)
|
function tiny.removeEntity(world, entity)
|
||||||
local e2r = world.entitiesToRemove
|
local e2r = world.entitiesToRemove
|
||||||
e2r[#e2r + 1] = entity
|
e2r[#e2r + 1] = entity
|
||||||
|
return entity
|
||||||
end
|
end
|
||||||
tiny_removeEntity = tiny.removeEntity
|
tiny_removeEntity = tiny.removeEntity
|
||||||
|
|
||||||
--- Removes a System from the world.
|
--- Removes a System from the world. Returns the System.
|
||||||
function tiny.removeSystem(world, system)
|
function tiny.removeSystem(world, system)
|
||||||
|
assert(system.world == world, "System does not belong to this World.")
|
||||||
local s2r = world.systemsToRemove
|
local s2r = world.systemsToRemove
|
||||||
s2r[#s2r + 1] = system
|
s2r[#s2r + 1] = system
|
||||||
|
return system
|
||||||
end
|
end
|
||||||
tiny_removeSystem = tiny.removeSystem
|
tiny_removeSystem = tiny.removeSystem
|
||||||
|
|
||||||
--- Shortcut for removing multiple Entities and Systems from the World.
|
--- Shortcut for removing multiple Entities and Systems from the World. Returns
|
||||||
|
-- all removed Systems and Entities
|
||||||
function tiny.remove(world, ...)
|
function tiny.remove(world, ...)
|
||||||
local obj
|
|
||||||
for i = 1, select("#", ...) do
|
for i = 1, select("#", ...) do
|
||||||
obj = select(i, ...)
|
local obj = select(i, ...)
|
||||||
if obj then
|
if obj then
|
||||||
if isSystem(obj) then
|
if isSystem(obj) then
|
||||||
tiny_removeSystem(world, obj)
|
tiny_removeSystem(world, obj)
|
||||||
else -- Assume obj is an Entity
|
else -- Assume obj is an Entity
|
||||||
tiny_removeEntity(world, obj)
|
tiny_removeEntity(world, obj)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return ...
|
||||||
end
|
end
|
||||||
tiny_remove = tiny.remove
|
tiny_remove = tiny.remove
|
||||||
|
|
||||||
-- Adds and removes Systems that have been marked from the World.
|
-- Adds and removes Systems that have been marked from the World.
|
||||||
function tiny_manageSystems(world)
|
function tiny_manageSystems(world)
|
||||||
local s2a, s2r = world.systemsToAdd, world.systemsToRemove
|
local s2a, s2r = world.systemsToAdd, world.systemsToRemove
|
||||||
|
|
||||||
-- Early exit
|
-- Early exit
|
||||||
if #s2a == 0 and #s2r == 0 then
|
if #s2a == 0 and #s2r == 0 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local systemIndices = world.systemIndices
|
world.systemsToAdd = {}
|
||||||
local entities = world.entities
|
world.systemsToRemove = {}
|
||||||
local systems = world.systems
|
|
||||||
local system, index, filter
|
|
||||||
local entityList, entityIndices, entityIndex, onRemove, onAdd
|
|
||||||
|
|
||||||
-- Remove Systems
|
local worldEntityList = world.entityList
|
||||||
for i = 1, #s2r do
|
local systems = world.systems
|
||||||
system = s2r[i]
|
|
||||||
index = systemIndices[system]
|
-- Remove Systems
|
||||||
if index then
|
for i = 1, #s2r do
|
||||||
onRemove = system.onRemove
|
local system = s2r[i]
|
||||||
if onRemove then
|
local index = system.index
|
||||||
entityList = system.entities
|
local onRemove = system.onRemove
|
||||||
for j = 1, #entityList do
|
if onRemove and not system.nocache then
|
||||||
onRemove(system, entityList[j])
|
local entityList = system.entities
|
||||||
end
|
for j = 1, #entityList do
|
||||||
end
|
onRemove(system, entityList[j])
|
||||||
systemIndices[system] = nil
|
|
||||||
tremove(systems, index)
|
|
||||||
for j = index, #systems do
|
|
||||||
systemIndices[systems[j]] = j
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
s2r[i] = nil
|
|
||||||
|
|
||||||
-- Clean up System
|
|
||||||
system.world = nil
|
|
||||||
system.entities = nil
|
|
||||||
system.indices = nil
|
|
||||||
end
|
end
|
||||||
|
tremove(systems, index)
|
||||||
|
for j = index, #systems do
|
||||||
|
systems[j].index = j
|
||||||
|
end
|
||||||
|
local onRemoveFromWorld = system.onRemoveFromWorld
|
||||||
|
if onRemoveFromWorld then
|
||||||
|
onRemoveFromWorld(system, world)
|
||||||
|
end
|
||||||
|
s2r[i] = nil
|
||||||
|
|
||||||
-- Add Systems
|
-- Clean up System
|
||||||
for i = 1, #s2a do
|
system.world = nil
|
||||||
system = s2a[i]
|
system.entities = nil
|
||||||
if not systemIndices[system] then
|
system.indices = nil
|
||||||
entityList = {}
|
system.index = nil
|
||||||
entityIndices = {}
|
end
|
||||||
system.entities = entityList
|
|
||||||
system.indices = entityIndices
|
|
||||||
if system.active == nil then
|
|
||||||
system.active = true
|
|
||||||
end
|
|
||||||
system.modified = true
|
|
||||||
system.world = world
|
|
||||||
index = #systems + 1
|
|
||||||
systemIndices[system] = index
|
|
||||||
systems[index] = system
|
|
||||||
|
|
||||||
-- Try to add Entities
|
-- Add Systems
|
||||||
onAdd = system.onAdd
|
for i = 1, #s2a do
|
||||||
filter = system.filter
|
local system = s2a[i]
|
||||||
|
if systems[system.index or 0] ~= system then
|
||||||
|
if not system.nocache then
|
||||||
|
system.entities = {}
|
||||||
|
system.indices = {}
|
||||||
|
end
|
||||||
|
if system.active == nil then
|
||||||
|
system.active = true
|
||||||
|
end
|
||||||
|
system.modified = true
|
||||||
|
system.world = world
|
||||||
|
local index = #systems + 1
|
||||||
|
system.index = index
|
||||||
|
systems[index] = system
|
||||||
|
local onAddToWorld = system.onAddToWorld
|
||||||
|
if onAddToWorld then
|
||||||
|
onAddToWorld(system, world)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Try to add Entities
|
||||||
|
if not system.nocache then
|
||||||
|
local entityList = system.entities
|
||||||
|
local entityIndices = system.indices
|
||||||
|
local onAdd = system.onAdd
|
||||||
|
local filter = system.filter
|
||||||
if filter then
|
if filter then
|
||||||
for entity in pairs(entities) do
|
for j = 1, #worldEntityList do
|
||||||
|
local entity = worldEntityList[j]
|
||||||
if filter(system, entity) then
|
if filter(system, entity) then
|
||||||
entityIndex = #entityList + 1
|
local entityIndex = #entityList + 1
|
||||||
entityList[entityIndex] = entity
|
entityList[entityIndex] = entity
|
||||||
entityIndices[entity] = entityIndex
|
entityIndices[entity] = entityIndex
|
||||||
if onAdd then
|
if onAdd then
|
||||||
@@ -518,82 +590,135 @@ function tiny_manageSystems(world)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
s2a[i] = nil
|
|
||||||
end
|
end
|
||||||
|
s2a[i] = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Adds and removes Entities that have been marked.
|
-- Adds, removes, and changes Entities that have been marked.
|
||||||
function tiny_manageEntities(world)
|
function tiny_manageEntities(world)
|
||||||
local e2a, e2r = world.entitiesToAdd, world.entitiesToRemove
|
|
||||||
|
local e2a = world.entitiesToAdd
|
||||||
|
local e2r = world.entitiesToRemove
|
||||||
|
local e2c = world.entitiesToChange
|
||||||
|
|
||||||
-- Early exit
|
-- Early exit
|
||||||
if #e2a == 0 and #e2r == 0 then
|
if #e2a == 0 and #e2r == 0 and #e2c == 0 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
world.entitiesToChange = {}
|
||||||
|
world.entitiesToAdd = {}
|
||||||
|
world.entitiesToRemove = {}
|
||||||
|
|
||||||
local entities = world.entities
|
local entities = world.entities
|
||||||
|
local entityList = world.entityList
|
||||||
local systems = world.systems
|
local systems = world.systems
|
||||||
local entityCount = world.entityCount
|
local entityCount = world.entityCount
|
||||||
local entity, system, index
|
|
||||||
local onRemove, onAdd, ses, seis, filter, tmpEntity
|
-- Change Entities
|
||||||
|
for i = 1, #e2c do
|
||||||
|
local entity = e2c[i]
|
||||||
|
if entities[entity] then
|
||||||
|
for j = 1, #systems do
|
||||||
|
local system = systems[j]
|
||||||
|
if not system.nocache then
|
||||||
|
local ses = system.entities
|
||||||
|
local seis = system.indices
|
||||||
|
local index = seis[entity]
|
||||||
|
local filter = system.filter
|
||||||
|
if filter and filter(system, entity) then
|
||||||
|
if not index then
|
||||||
|
system.modified = true
|
||||||
|
index = #ses + 1
|
||||||
|
ses[index] = entity
|
||||||
|
seis[entity] = index
|
||||||
|
local onAdd = system.onAdd
|
||||||
|
if onAdd then
|
||||||
|
onAdd(system, entity)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif index then
|
||||||
|
system.modified = true
|
||||||
|
local tmpEntity = ses[#ses]
|
||||||
|
ses[index] = tmpEntity
|
||||||
|
seis[tmpEntity] = index
|
||||||
|
seis[entity] = nil
|
||||||
|
ses[#ses] = nil
|
||||||
|
local onRemove = system.onRemove
|
||||||
|
if onRemove then
|
||||||
|
onRemove(system, entity)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
e2c[i] = nil
|
||||||
|
end
|
||||||
|
|
||||||
-- Remove Entities
|
-- Remove Entities
|
||||||
for i = 1, #e2r do
|
for i = 1, #e2r do
|
||||||
entity = e2r[i]
|
local entity = e2r[i]
|
||||||
if entities[entity] then
|
e2r[i] = nil
|
||||||
|
local listIndex = entities[entity]
|
||||||
|
if listIndex then
|
||||||
|
-- Remove Entity from world state
|
||||||
|
local lastEntity = entityList[#entityList]
|
||||||
|
entities[lastEntity] = listIndex
|
||||||
entities[entity] = nil
|
entities[entity] = nil
|
||||||
|
entityList[listIndex] = lastEntity
|
||||||
|
entityList[#entityList] = nil
|
||||||
entityCount = entityCount - 1
|
entityCount = entityCount - 1
|
||||||
|
-- Remove from cached systems
|
||||||
for j = 1, #systems do
|
for j = 1, #systems do
|
||||||
system = systems[j]
|
local system = systems[j]
|
||||||
ses = system.entities
|
if not system.nocache then
|
||||||
seis = system.indices
|
local ses = system.entities
|
||||||
index = seis[entity]
|
local seis = system.indices
|
||||||
|
local index = seis[entity]
|
||||||
if index then
|
if index then
|
||||||
system.modified = true
|
system.modified = true
|
||||||
tmpEntity = ses[#ses]
|
local tmpEntity = ses[#ses]
|
||||||
ses[index] = tmpEntity
|
ses[index] = tmpEntity
|
||||||
seis[tmpEntity] = index
|
seis[tmpEntity] = index
|
||||||
seis[entity] = nil
|
seis[entity] = nil
|
||||||
ses[#ses] = nil
|
ses[#ses] = nil
|
||||||
onRemove = system.onRemove
|
local onRemove = system.onRemove
|
||||||
if onRemove then
|
if onRemove then
|
||||||
onRemove(system, entity)
|
onRemove(system, entity)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
e2r[i] = nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add Entities
|
-- Add Entities
|
||||||
for i = 1, #e2a do
|
for i = 1, #e2a do
|
||||||
entity = e2a[i]
|
local entity = e2a[i]
|
||||||
if not entities[entity] then
|
if not entities[entity] then
|
||||||
entities[entity] = true
|
local listIndex = #entityList + 1
|
||||||
|
entities[entity] = listIndex
|
||||||
|
entityList[listIndex] = entity
|
||||||
entityCount = entityCount + 1
|
entityCount = entityCount + 1
|
||||||
|
|
||||||
for j = 1, #systems do
|
for j = 1, #systems do
|
||||||
system = systems[j]
|
local system = systems[j]
|
||||||
ses = system.entities
|
if not system.nocache then
|
||||||
seis = system.indices
|
local ses = system.entities
|
||||||
filter = system.filter
|
local seis = system.indices
|
||||||
if filter and filter(system, entity) then
|
local filter = system.filter
|
||||||
system.modified = true
|
if filter and filter(system, entity) then
|
||||||
index = #ses + 1
|
system.modified = true
|
||||||
ses[index] = entity
|
local index = #ses + 1
|
||||||
seis[entity] = index
|
ses[index] = entity
|
||||||
onAdd = system.onAdd
|
seis[entity] = index
|
||||||
if onAdd then
|
local onAdd = system.onAdd
|
||||||
onAdd(system, entity)
|
if onAdd then
|
||||||
|
onAdd(system, entity)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
e2a[i] = nil
|
e2a[i] = nil
|
||||||
end
|
end
|
||||||
@@ -602,6 +727,25 @@ function tiny_manageEntities(world)
|
|||||||
world.entityCount = entityCount
|
world.entityCount = entityCount
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Manages Entities and Systems marked for deletion or addition. Call this
|
||||||
|
-- before modifying Systems and Entities outside of a call to `tiny.update`.
|
||||||
|
-- Do not call this within a call to `tiny.update`.
|
||||||
|
function tiny.refresh(world)
|
||||||
|
tiny_manageSystems(world)
|
||||||
|
tiny_manageEntities(world)
|
||||||
|
local systems = world.systems
|
||||||
|
for i = 1, #systems do
|
||||||
|
local system = systems[i]
|
||||||
|
if system.active then
|
||||||
|
local onModify = system.onModify
|
||||||
|
if onModify and system.modified then
|
||||||
|
onModify(system, 0)
|
||||||
|
end
|
||||||
|
system.modified = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Updates the World by dt (delta time). Takes an optional parameter, `filter`,
|
--- Updates the World by dt (delta time). Takes an optional parameter, `filter`,
|
||||||
-- which is a Filter that selects Systems from the World, and updates only those
|
-- which is a Filter that selects Systems from the World, and updates only those
|
||||||
-- Systems. If `filter` is not supplied, all Systems are updated. Put this
|
-- Systems. If `filter` is not supplied, all Systems are updated. Put this
|
||||||
@@ -612,23 +756,22 @@ function tiny.update(world, dt, filter)
|
|||||||
tiny_manageEntities(world)
|
tiny_manageEntities(world)
|
||||||
|
|
||||||
local systems = world.systems
|
local systems = world.systems
|
||||||
local system, update, interval, onModify
|
|
||||||
|
|
||||||
-- Iterate through Systems IN ORDER
|
-- Iterate through Systems IN ORDER
|
||||||
for i = 1, #systems do
|
for i = 1, #systems do
|
||||||
system = systems[i]
|
local system = systems[i]
|
||||||
if system.active and ((not filter) or filter(world, system)) then
|
if system.active and ((not filter) or filter(world, system)) then
|
||||||
|
|
||||||
-- Call the modify callback on Systems that have been modified.
|
-- Call the modify callback on Systems that have been modified.
|
||||||
onModify = system.onModify
|
local onModify = system.onModify
|
||||||
if onModify and system.modified then
|
if onModify and system.modified then
|
||||||
onModify(system, dt)
|
onModify(system, dt)
|
||||||
end
|
end
|
||||||
|
|
||||||
--Update Systems that have an update method (most Systems)
|
-- Update Systems that have an update method (most Systems)
|
||||||
update = system.update
|
local update = system.update
|
||||||
if update then
|
if update then
|
||||||
interval = system.interval
|
local interval = system.interval
|
||||||
if interval then
|
if interval then
|
||||||
local bufferedTime = (system.bufferedTime or 0) + dt
|
local bufferedTime = (system.bufferedTime or 0) + dt
|
||||||
while bufferedTime >= interval do
|
while bufferedTime >= interval do
|
||||||
@@ -650,8 +793,9 @@ end
|
|||||||
|
|
||||||
--- Removes all Entities from the World.
|
--- Removes all Entities from the World.
|
||||||
function tiny.clearEntities(world)
|
function tiny.clearEntities(world)
|
||||||
for e in pairs(world.entities) do
|
local el = world.entityList
|
||||||
tiny_removeEntity(world, e)
|
for i = 1, #el do
|
||||||
|
tiny_removeEntity(world, el[i])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -673,26 +817,28 @@ function tiny.getSystemCount(world)
|
|||||||
return #(world.systems)
|
return #(world.systems)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Gets the index of a System in the World. Lower indexed Systems are processed
|
--- Gets the index of the System in the World.
|
||||||
-- before higher indexed systems.
|
-- A simpler alternative is `system.index`.
|
||||||
function tiny.getSystemIndex(world, system)
|
function tiny.getSystemIndex(world, system)
|
||||||
return world.systemIndices[system]
|
return system.index
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sets the index of a System in the World, and returns the old index. Changes
|
--- Sets the index of a System in the World, and returns the old index. Changes
|
||||||
-- the order in which they Systems processed, because lower indexed Systems are
|
-- the order in which they Systems processed, because lower indexed Systems are
|
||||||
-- processed first.
|
-- processed first. Returns the old system.index.
|
||||||
function tiny.setSystemIndex(world, system, index)
|
function tiny.setSystemIndex(world, system, index)
|
||||||
local systemIndices = world.systemIndices
|
local oldIndex = system.index
|
||||||
local oldIndex = systemIndices[system]
|
|
||||||
local systems = world.systems
|
local systems = world.systems
|
||||||
local system = systems[oldIndex]
|
|
||||||
|
if index < 0 then
|
||||||
|
index = tiny.getSystemCount(world) + 1 + index
|
||||||
|
end
|
||||||
|
|
||||||
tremove(systems, oldIndex)
|
tremove(systems, oldIndex)
|
||||||
tinsert(systems, index, system)
|
tinsert(systems, index, system)
|
||||||
|
|
||||||
for i = oldIndex, index, index >= oldIndex and 1 or -1 do
|
for i = oldIndex, index, index >= oldIndex and 1 or -1 do
|
||||||
systemIndices[systems[i]] = i
|
systems[i].index = i
|
||||||
end
|
end
|
||||||
|
|
||||||
return oldIndex
|
return oldIndex
|
||||||
@@ -707,6 +853,7 @@ worldMetaTable = {
|
|||||||
remove = tiny.remove,
|
remove = tiny.remove,
|
||||||
removeEntity = tiny.removeEntity,
|
removeEntity = tiny.removeEntity,
|
||||||
removeSystem = tiny.removeSystem,
|
removeSystem = tiny.removeSystem,
|
||||||
|
refresh = tiny.refresh,
|
||||||
update = tiny.update,
|
update = tiny.update,
|
||||||
clearEntities = tiny.clearEntities,
|
clearEntities = tiny.clearEntities,
|
||||||
clearSystems = tiny.clearSystems,
|
clearSystems = tiny.clearSystems,
|
||||||
@@ -714,7 +861,10 @@ worldMetaTable = {
|
|||||||
getSystemCount = tiny.getSystemCount,
|
getSystemCount = tiny.getSystemCount,
|
||||||
getSystemIndex = tiny.getSystemIndex,
|
getSystemIndex = tiny.getSystemIndex,
|
||||||
setSystemIndex = tiny.setSystemIndex
|
setSystemIndex = tiny.setSystemIndex
|
||||||
}
|
},
|
||||||
|
__tostring = function(self)
|
||||||
|
return "<tiny-ecs_World>"
|
||||||
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
return tiny
|
return tiny
|
||||||
|
|||||||
Reference in New Issue
Block a user