mirror of
https://github.com/bakpakin/tiny-ecs.git
synced 2024-11-28 23:54:21 +00:00
Change implementation of require/reject API
Remove the dependency on load/loadstring for requireXXX/rejectXXX API functions
This commit is contained in:
parent
821914795d
commit
32a2e99127
68
test.lua
68
test.lua
@ -6,3 +6,71 @@ local systemB = tiny.system()
|
||||
world:addSystem(systemA)
|
||||
world:addSystem(systemB)
|
||||
world:setSystemIndex(systemA, 1)
|
||||
|
||||
|
||||
--- test requireXXX/rejectXXX functions
|
||||
|
||||
local filt1 = tiny.requireAll("prop1", "prop2")
|
||||
|
||||
assert(filt1(nil, { }) == false)
|
||||
assert(filt1(nil, { prop1 = 1 }) == false)
|
||||
assert(filt1(nil, { prop1 = 1, prop3 = 2}) == false)
|
||||
assert(filt1(nil, { prop1 = 1, prop2 = 2 }) == true)
|
||||
assert(filt1(nil, { prop2 = 1 }) == false)
|
||||
assert(filt1(nil, { prop2 = 1, prop1 = 1, prop3 = 2 }) == true)
|
||||
|
||||
|
||||
local filt2 = tiny.requireAny("prop1", "prop2")
|
||||
|
||||
assert(filt2(nil, { }) == false)
|
||||
assert(filt2(nil, { prop1 = 1 }) == true)
|
||||
assert(filt2(nil, { prop1 = 1, prop3 = 2}) == true)
|
||||
assert(filt2(nil, { prop1 = 1, prop2 = 2 }) == true)
|
||||
assert(filt2(nil, { prop2 = 1 }) == true)
|
||||
assert(filt2(nil, { prop2 = 1, prop1 = 1, prop3 = 2 }) == true)
|
||||
assert(filt2(nil, { prop4 = 1, prop5 = 1, prop6 = 2 }) == false)
|
||||
|
||||
|
||||
local filt3 = tiny.rejectAll("prop1", "prop2")
|
||||
|
||||
assert(filt3(nil, { }) == true)
|
||||
assert(filt3(nil, { prop1 = 1 }) == true)
|
||||
assert(filt3(nil, { prop1 = 1, prop3 = 2}) == true)
|
||||
assert(filt3(nil, { prop1 = 1, prop2 = 2 }) == false)
|
||||
assert(filt3(nil, { prop2 = 1 }) == true)
|
||||
assert(filt3(nil, { prop2 = 1, prop1 = 1, prop3 = 2 }) == false)
|
||||
|
||||
|
||||
local filt4 = tiny.rejectAny("prop1", "prop2")
|
||||
|
||||
assert(filt4(nil, { }) == true)
|
||||
assert(filt4(nil, { prop1 = 1 }) == false)
|
||||
assert(filt4(nil, { prop1 = 1, prop3 = 2}) == false)
|
||||
assert(filt4(nil, { prop1 = 1, prop2 = 2 }) == false)
|
||||
assert(filt4(nil, { prop2 = 1 }) == false)
|
||||
assert(filt4(nil, { prop2 = 1, prop1 = 1, prop3 = 2 }) == false)
|
||||
assert(filt4(nil, { prop4 = 1, prop5 = 1, prop6 = 2 }) == true)
|
||||
|
||||
|
||||
|
||||
local filt5 = tiny.requireAll("prop3", filt2)
|
||||
|
||||
assert(filt5(nil, {}) == false)
|
||||
assert(filt5(nil, {prop1 = 1}) == false)
|
||||
assert(filt5(nil, {prop1 = 1, prop2 = 1, prop3 = 1}) == true)
|
||||
assert(filt5(nil, {prop1 = 1, prop2 = 1, prop3 = 1, prop4 = 1}) == true)
|
||||
assert(filt5(nil, {prop1 = 1, prop2 = 1, prop4 = 1}) == false)
|
||||
|
||||
local filt6 = tiny.requireAny("prop3", filt2)
|
||||
|
||||
assert(filt6(nil, {}) == false)
|
||||
assert(filt6(nil, {prop1 = 1}) == true)
|
||||
assert(filt6(nil, {prop1 = 1, prop2 = 1, prop3 = 1}) == true)
|
||||
assert(filt6(nil, {prop1 = 1, prop2 = 1, prop3 = 1, prop4 = 1}) == true)
|
||||
assert(filt6(nil, {prop1 = 1, prop2 = 1, prop4 = 1}) == true)
|
||||
assert(filt6(nil, {prop5 = 1, prop4 = 1}) == false)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
71
tiny.lua
71
tiny.lua
@ -91,40 +91,49 @@ 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(invert, joining_op, ...)
|
||||
local _args = {...}
|
||||
|
||||
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)
|
||||
return function(system, e)
|
||||
local acc
|
||||
local args = _args
|
||||
if joining_op == 'or' then
|
||||
acc = false
|
||||
for i = 1, #args do
|
||||
local v = args[i]
|
||||
if type(v) == "string" then
|
||||
acc = acc or (e[v] ~= nil)
|
||||
elseif type(v) == "function" then
|
||||
acc = acc or v(system, e)
|
||||
else
|
||||
error 'Filter token must be a string or a filter function.'
|
||||
end
|
||||
end
|
||||
local source = ('%s\nreturn function(system, e) return %s(%s) end')
|
||||
:format(
|
||||
table.concat(build, '\n'),
|
||||
prefix,
|
||||
table.concat(accum, seperator))
|
||||
local loader, err = loadstring(source)
|
||||
if err then error(err) end
|
||||
return loader(...)
|
||||
else
|
||||
acc = true
|
||||
for i = 1, #args do
|
||||
local v = args[i]
|
||||
if type(v) == "string" then
|
||||
acc = acc and (e[v] ~= nil)
|
||||
elseif type(v) == "function" then
|
||||
acc = acc and v(system, e)
|
||||
else
|
||||
error 'Filter token must be a string or a filter function.'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- computes a simple xor
|
||||
if invert then
|
||||
return not acc
|
||||
else
|
||||
return acc
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
|
||||
function filterJoin(...)
|
||||
local state, value = pcall(filterJoinRaw, ...)
|
||||
@ -169,25 +178,25 @@ end
|
||||
--- Makes a Filter that selects Entities with all specified Components and
|
||||
-- Filters.
|
||||
function tiny.requireAll(...)
|
||||
return filterJoin('', ' and ', ...)
|
||||
return filterJoin(false, 'and', ...)
|
||||
end
|
||||
|
||||
--- Makes a Filter that selects Entities with at least one of the specified
|
||||
-- Components and Filters.
|
||||
function tiny.requireAny(...)
|
||||
return filterJoin('', ' or ', ...)
|
||||
return filterJoin(false, 'or', ...)
|
||||
end
|
||||
|
||||
--- Makes a Filter that rejects Entities with all specified Components and
|
||||
-- Filters, and selects all other Entities.
|
||||
function tiny.rejectAll(...)
|
||||
return filterJoin('not', ' and ', ...)
|
||||
return filterJoin(true, 'and', ...)
|
||||
end
|
||||
|
||||
--- Makes a Filter that rejects Entities with at least one of the specified
|
||||
-- Components and Filters, and selects all other Entities.
|
||||
function tiny.rejectAny(...)
|
||||
return filterJoin('not', ' or ', ...)
|
||||
return filterJoin(true, 'or', ...)
|
||||
end
|
||||
|
||||
--- Makes a Filter from a string. Syntax of `pattern` is as follows.
|
||||
|
Loading…
Reference in New Issue
Block a user