mirror of
https://github.com/Reuh/ubiquitousse.git
synced 2025-10-28 09:39:31 +00:00
Button combinations, create signal registry per scene
This commit is contained in:
parent
f6fb8ad649
commit
15dfb18c65
3 changed files with 102 additions and 78 deletions
48
ecs/ecs.can
48
ecs/ecs.can
|
|
@ -1,7 +1,7 @@
|
||||||
--- ubiquitousse.ecs
|
--- ubiquitousse.ecs
|
||||||
-- Optional dependency: ubiquitousse.scene, to allow quick creation of ECS-based scenes.
|
-- Optional dependency: ubiquitousse.scene, to allow quick creation of ECS-based scenes.
|
||||||
local loaded, newScene = pcall(require, (...):match("^(.-)ecs").."scene")
|
local loaded, scene = pcall(require, (...):match("^(.-)ecs").."scene")
|
||||||
if not loaded then newScene = nil end
|
if not loaded then scene = nil end
|
||||||
|
|
||||||
--- Entity Component System library, inspired by the excellent tiny-ecs. Main differences include:
|
--- Entity Component System library, inspired by the excellent tiny-ecs. Main differences include:
|
||||||
-- * ability to nest systems;
|
-- * ability to nest systems;
|
||||||
|
|
@ -268,9 +268,12 @@ let recCallOnAddToWorld = (world, systems)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Create and returns a world system based on a list of systems.
|
--- ECS module.
|
||||||
-- The systems will be instancied for this world.
|
let ecs = {
|
||||||
let world = (...)
|
--- Create and returns a world system based on a list of systems.
|
||||||
|
-- The systems will be instancied for this world.
|
||||||
|
-- @impl ubiquitousse
|
||||||
|
world = (...)
|
||||||
let world = setmetatable({
|
let world = setmetatable({
|
||||||
filter = (e) return true end,
|
filter = (e) return true end,
|
||||||
s = {}
|
s = {}
|
||||||
|
|
@ -279,10 +282,11 @@ let world = (...)
|
||||||
world.systems = recInstanciateSystems(world, {...})
|
world.systems = recInstanciateSystems(world, {...})
|
||||||
recCallOnAddToWorld(world, world.systems)
|
recCallOnAddToWorld(world, world.systems)
|
||||||
return world
|
return world
|
||||||
end
|
end,
|
||||||
|
|
||||||
--- Returns a filter that returns true if, for every argument, a field with the same name exists in the entity.
|
--- Returns a filter that returns true if, for every argument, a field with the same name exists in the entity.
|
||||||
let all = (...)
|
-- @impl ubiquitousse
|
||||||
|
all = (...)
|
||||||
let l = {...}
|
let l = {...}
|
||||||
return function(s, e)
|
return function(s, e)
|
||||||
for _, k in ipairs(l) do
|
for _, k in ipairs(l) do
|
||||||
|
|
@ -292,10 +296,11 @@ let all = (...)
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end,
|
||||||
|
|
||||||
--- Returns a filter that returns true if one of the arguments if the name of a field in the entity.
|
--- Returns a filter that returns true if one of the arguments if the name of a field in the entity.
|
||||||
let any = (...)
|
-- @impl ubiquitousse
|
||||||
|
any = (...)
|
||||||
let l = {...}
|
let l = {...}
|
||||||
return function(s, e)
|
return function(s, e)
|
||||||
for _, k in ipairs(l) do
|
for _, k in ipairs(l) do
|
||||||
|
|
@ -305,14 +310,16 @@ let any = (...)
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end,
|
||||||
|
|
||||||
let scene = (name, systems={}, entities={})
|
--- If uqt.scene is available, returns a new scene that will consist of a ECS world with the specified systems and entities.
|
||||||
let s = newScene(name)
|
-- @impl ubiquitousse
|
||||||
|
scene = (name, systems={}, entities={})
|
||||||
|
let s = scene.new(name)
|
||||||
let w
|
let w
|
||||||
|
|
||||||
function s:enter()
|
function s:enter()
|
||||||
w = world(unpack(systems))
|
w = ecs.world(unpack(systems))
|
||||||
w:add(unpack(entities))
|
w:add(unpack(entities))
|
||||||
end
|
end
|
||||||
function s:exit()
|
function s:exit()
|
||||||
|
|
@ -326,12 +333,7 @@ let scene = (name, systems={}, entities={})
|
||||||
end
|
end
|
||||||
|
|
||||||
return s
|
return s
|
||||||
end
|
end
|
||||||
|
|
||||||
--- ECS module.
|
|
||||||
return {
|
|
||||||
world = world,
|
|
||||||
all = all,
|
|
||||||
any = any,
|
|
||||||
scene = scene
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ecs
|
||||||
|
|
|
||||||
|
|
@ -501,6 +501,7 @@ input = {
|
||||||
-- identifier, preceded by a % : for example "gamepad.axis.1.leftx%-0.5" should return true when the left-stick of the first gamepad is moved to the right
|
-- identifier, preceded by a % : for example "gamepad.axis.1.leftx%-0.5" should return true when the left-stick of the first gamepad is moved to the right
|
||||||
-- by more of 50%. The negative threshold value means that the button will be pressed only when the axis has a negative value (in the example, it won't be
|
-- by more of 50%. The negative threshold value means that the button will be pressed only when the axis has a negative value (in the example, it won't be
|
||||||
-- pressed when the axis is moved to the right).
|
-- pressed when the axis is moved to the right).
|
||||||
|
-- Buttons can also be defined by a list of buttons (string or functions), in which case the button will be considered down if all the buttons are down.
|
||||||
|
|
||||||
--- Makes a new button detector from a identifier string.
|
--- Makes a new button detector from a identifier string.
|
||||||
-- The function may error if the identifier is incorrect.
|
-- The function may error if the identifier is incorrect.
|
||||||
|
|
@ -509,7 +510,7 @@ input = {
|
||||||
-- @impl backend
|
-- @impl backend
|
||||||
basicButtonDetector = function(str) end,
|
basicButtonDetector = function(str) end,
|
||||||
|
|
||||||
--- Make a new button detector from a detector function of string.
|
--- Make a new button detector from a detector function, string, or list of buttons.
|
||||||
-- @tparam string, function button identifier
|
-- @tparam string, function button identifier
|
||||||
-- @impl ubiquitousse
|
-- @impl ubiquitousse
|
||||||
buttonDetector = function(obj)
|
buttonDetector = function(obj)
|
||||||
|
|
@ -517,6 +518,19 @@ input = {
|
||||||
return obj
|
return obj
|
||||||
elseif type(obj) == "string" then
|
elseif type(obj) == "string" then
|
||||||
return input.basicButtonDetector(obj)
|
return input.basicButtonDetector(obj)
|
||||||
|
elseif type(obj) == "table" then
|
||||||
|
local l = {}
|
||||||
|
for _, b in ipairs(obj) do
|
||||||
|
table.insert(l, input.buttonDetector(b))
|
||||||
|
end
|
||||||
|
return function()
|
||||||
|
for _, b in ipairs(l) do
|
||||||
|
if not b() then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
error(("Not a valid button detector: %s"):format(obj))
|
error(("Not a valid button detector: %s"):format(obj))
|
||||||
end,
|
end,
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ if not loaded then timer = nil end
|
||||||
-- * all scene change callbacks are called after setting scene.current to the new scene but before changing scene.stack
|
-- * all scene change callbacks are called after setting scene.current to the new scene but before changing scene.stack
|
||||||
-- * all scene exit/suspend callbacks are called before scene enter/resume callbacks
|
-- * all scene exit/suspend callbacks are called before scene enter/resume callbacks
|
||||||
local scene
|
local scene
|
||||||
scene = setmetatable({
|
scene = {
|
||||||
--- The current scene table.
|
--- The current scene table.
|
||||||
-- @impl ubiquitousse
|
-- @impl ubiquitousse
|
||||||
current = nil,
|
current = nil,
|
||||||
|
|
@ -34,6 +34,9 @@ scene = setmetatable({
|
||||||
--- Shortcut for scene.current.timer.
|
--- Shortcut for scene.current.timer.
|
||||||
-- @impl ubiquitousse
|
-- @impl ubiquitousse
|
||||||
timer = nil,
|
timer = nil,
|
||||||
|
--- Shortcut for scene.current.signal.
|
||||||
|
-- @impl ubiquitousse
|
||||||
|
signal = nil,
|
||||||
|
|
||||||
--- The scene stack: list of scene, from the farest one to the nearest.
|
--- The scene stack: list of scene, from the farest one to the nearest.
|
||||||
-- @impl ubiquitousse
|
-- @impl ubiquitousse
|
||||||
|
|
@ -77,6 +80,7 @@ scene = setmetatable({
|
||||||
name = name or "unamed", -- The scene name.
|
name = name or "unamed", -- The scene name.
|
||||||
|
|
||||||
timer = timer and timer.new(), -- Scene-specific TimerRegistry, if uqt.time is available.
|
timer = timer and timer.new(), -- Scene-specific TimerRegistry, if uqt.time is available.
|
||||||
|
signal = signal and signal.new(), -- Scene-specific SignalRegistry, if uqt.signal is available.
|
||||||
|
|
||||||
enter = function(self, ...) end, -- Called when entering a scene.
|
enter = function(self, ...) end, -- Called when entering a scene.
|
||||||
exit = function(self) end, -- Called when exiting a scene, and not expecting to come back (scene may be unloaded).
|
exit = function(self) end, -- Called when exiting a scene, and not expecting to come back (scene may be unloaded).
|
||||||
|
|
@ -101,8 +105,12 @@ scene = setmetatable({
|
||||||
local previous = scene.current
|
local previous = scene.current
|
||||||
scene.current = type(scenePath) == "string" and scene.load(scene.prefix..scenePath) or scenePath
|
scene.current = type(scenePath) == "string" and scene.load(scene.prefix..scenePath) or scenePath
|
||||||
scene.timer = scene.current.timer
|
scene.timer = scene.current.timer
|
||||||
|
scene.signal = scene.current.signal
|
||||||
scene.current.name = scene.current.name or tostring(scenePath)
|
scene.current.name = scene.current.name or tostring(scenePath)
|
||||||
if previous then previous:exit() end
|
if previous then
|
||||||
|
previous:exit()
|
||||||
|
if timer then previous.timer:clear() end
|
||||||
|
end
|
||||||
scene.current:enter(...)
|
scene.current:enter(...)
|
||||||
scene.stack[math.max(#scene.stack, 1)] = scene.current
|
scene.stack[math.max(#scene.stack, 1)] = scene.current
|
||||||
end,
|
end,
|
||||||
|
|
@ -118,6 +126,7 @@ scene = setmetatable({
|
||||||
local previous = scene.current
|
local previous = scene.current
|
||||||
scene.current = type(scenePath) == "string" and scene.load(scene.prefix..scenePath) or scenePath
|
scene.current = type(scenePath) == "string" and scene.load(scene.prefix..scenePath) or scenePath
|
||||||
scene.timer = scene.current.timer
|
scene.timer = scene.current.timer
|
||||||
|
scene.signal = scene.current.signal
|
||||||
scene.current.name = scene.current.name or tostring(scenePath)
|
scene.current.name = scene.current.name or tostring(scenePath)
|
||||||
if previous then previous:suspend() end
|
if previous then previous:suspend() end
|
||||||
scene.current:enter(...)
|
scene.current:enter(...)
|
||||||
|
|
@ -131,8 +140,12 @@ scene = setmetatable({
|
||||||
pop = function()
|
pop = function()
|
||||||
local previous = scene.current
|
local previous = scene.current
|
||||||
scene.current = scene.stack[#scene.stack-1]
|
scene.current = scene.stack[#scene.stack-1]
|
||||||
scene.timer = scene.current.timer
|
scene.timer = scene.current and scene.current.timer or nil
|
||||||
if previous then previous:exit() end
|
scene.signal = scene.current and scene.current.signal or nil
|
||||||
|
if previous then
|
||||||
|
previous:exit()
|
||||||
|
if timer then previous.timer:clear() end
|
||||||
|
end
|
||||||
if scene.current then scene.current:resume() end
|
if scene.current then scene.current:resume() end
|
||||||
table.remove(scene.stack)
|
table.remove(scene.stack)
|
||||||
end,
|
end,
|
||||||
|
|
@ -164,12 +177,7 @@ scene = setmetatable({
|
||||||
draw = function(...)
|
draw = function(...)
|
||||||
if scene.current then scene.current:draw(...) end
|
if scene.current then scene.current:draw(...) end
|
||||||
end
|
end
|
||||||
}, {
|
}
|
||||||
--- scene(...) is a shortcut for scene.new(...)
|
|
||||||
__call = function(self, ...)
|
|
||||||
return scene.new(...)
|
|
||||||
end
|
|
||||||
})
|
|
||||||
|
|
||||||
-- Bind signals
|
-- Bind signals
|
||||||
if signal then
|
if signal then
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue