mirror of
https://github.com/Reuh/ubiquitousse.git
synced 2025-10-27 17:19:31 +00:00
uqt.signal
This commit is contained in:
parent
82bc7268e6
commit
f6fb8ad649
11 changed files with 331 additions and 80 deletions
|
|
@ -2,18 +2,30 @@ local uqt = require((...):match("^(.-ubiquitousse)%."))
|
||||||
local ctr = require("ctr")
|
local ctr = require("ctr")
|
||||||
local gfx = require("ctr.gfx")
|
local gfx = require("ctr.gfx")
|
||||||
|
|
||||||
local function checkCompat(stuffName, expectedVersion, actualVersion)
|
local madeForCtr = "v1.0"
|
||||||
if actualVersion ~= expectedVersion then
|
local madeForUqt = "0.0.1"
|
||||||
local txt = ("Ubiquitousse ctrµLua backend was made for %s %s but %s is used!\nThings may not work as expected.")
|
|
||||||
:format(stuffName, expectedVersion, actualVersion)
|
-- Check versions
|
||||||
print(txt)
|
local txt = ""
|
||||||
for _=0,300 do
|
|
||||||
gfx.start(gfx.TOP)
|
if ctr.version ~= madeForCtr then
|
||||||
gfx.wrappedText(0, 0, txt, gfx.TOP_WIDTH)
|
txt = txt .. ("Ubiquitousse ctrµLua backend was made for ctrµLua %s but %s is used!\n")
|
||||||
gfx.stop()
|
:format(madeForCtr, uqt.version)
|
||||||
gfx.render()
|
end
|
||||||
end
|
|
||||||
|
if uqt.version ~= madeForUqt then
|
||||||
|
txt = txt .. ("Ubiquitousse ctrµLua backend was made for Ubiquitousse %s but %s is used!\n")
|
||||||
|
:format(madeForUqt, uqt.version)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Show warnings
|
||||||
|
if txt ~= "" then
|
||||||
|
txt = txt .. "Things may not work as expected.\n"
|
||||||
|
print(txt)
|
||||||
|
for _=0,300 do
|
||||||
|
gfx.start(gfx.TOP)
|
||||||
|
gfx.wrappedText(0, 0, txt, gfx.TOP_WIDTH)
|
||||||
|
gfx.stop()
|
||||||
|
gfx.render()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
checkCompat("ctrµLua", "v1.0", ctr.version) -- not really a version, just get the latest build
|
|
||||||
checkCompat("Ubiquitousse", "0.0.1", uqt.version)
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,30 @@
|
||||||
local uqt = require((...):match("^(.-ubiquitousse)%."))
|
local uqt = require((...):match("^(.-ubiquitousse)%."))
|
||||||
|
|
||||||
local function checkCompat(stuffName, expectedVersion, actualVersion)
|
local madeForLove = { 11, "x", "x" }
|
||||||
if actualVersion ~= expectedVersion then
|
local madeForUqt = "0.0.1"
|
||||||
local txt = ("Ubiquitousse Löve backend was made for %s %s but %s is used!\nThings may not work as expected.")
|
|
||||||
:format(stuffName, expectedVersion, actualVersion)
|
-- Check versions
|
||||||
print(txt)
|
local txt = ""
|
||||||
|
|
||||||
|
local actualLove = { love.getVersion() }
|
||||||
|
for i, v in ipairs(madeForLove) do
|
||||||
|
if v ~= "x" then
|
||||||
|
if actualLove[i] ~= v then
|
||||||
|
txt = txt .. ("Ubiquitousse Löve backend was made for LÖVE %s.%s.%s but %s.%s.%s is used!\n")
|
||||||
|
:format(madeForLove[1], madeForLove[2], madeForLove[3], actualLove[1], actualLove[2], actualLove[3])
|
||||||
|
break
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
checkCompat("Löve", "11.3.0", ("%s.%s.%s"):format(love.getVersion()))
|
|
||||||
checkCompat("Ubiquitousse", "0.0.1", uqt.version)
|
if uqt.version ~= madeForUqt then
|
||||||
|
txt = txt .. ("Ubiquitousse Löve backend was made for Ubiquitousse %s but %s is used!\n")
|
||||||
|
:format(madeForUqt, uqt.version)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Show warnings
|
||||||
|
if txt ~= "" then
|
||||||
|
txt = txt .. "Things may not work as expected.\n"
|
||||||
|
print(txt)
|
||||||
|
love.window.showMessageBox("Compatibility warning", txt, "warning")
|
||||||
|
end
|
||||||
|
|
|
||||||
22
init.lua
22
init.lua
|
|
@ -64,33 +64,19 @@ local ubiquitousse
|
||||||
ubiquitousse = {
|
ubiquitousse = {
|
||||||
--- Ubiquitousse version.
|
--- Ubiquitousse version.
|
||||||
-- @impl ubiquitousse
|
-- @impl ubiquitousse
|
||||||
version = "0.0.1",
|
version = "0.0.1"
|
||||||
|
|
||||||
--- Should be called each time the game loop is ran; will update every loaded Ubiquitousse module that needs it.
|
|
||||||
-- @tparam number dt time since last call, in miliseconds
|
|
||||||
-- @impl mixed
|
|
||||||
update = function(dt)
|
|
||||||
if ubiquitousse.timer then ubiquitousse.timer.update(dt) end
|
|
||||||
if ubiquitousse.scene then ubiquitousse.scene.update(dt) end
|
|
||||||
if ubiquitousse.input then ubiquitousse.input.update(dt) end
|
|
||||||
end,
|
|
||||||
|
|
||||||
--- Should be called each time the game expect a new frame to be drawn; will draw every loaded Ubiquitousse module that needs it
|
|
||||||
-- The screen is expected to be cleared since last frame.
|
|
||||||
-- @impl mixed
|
|
||||||
draw = function()
|
|
||||||
if ubiquitousse.scene then ubiquitousse.scene.draw() end
|
|
||||||
end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-- We're going to require modules requiring Ubiquitousse, so to avoid stack overflows we already register the ubiquitousse package
|
-- We're going to require modules requiring Ubiquitousse, so to avoid stack overflows we already register the ubiquitousse package
|
||||||
package.loaded[p] = ubiquitousse
|
package.loaded[p] = ubiquitousse
|
||||||
|
|
||||||
-- Require external submodules
|
-- Require external submodules
|
||||||
for _, m in ipairs{"asset", "ecs", "input", "scene", "timer", "util"} do
|
for _, m in ipairs{"signal", "asset", "ecs", "input", "scene", "timer", "util"} do
|
||||||
local s, t = pcall(require, p.."."..m)
|
local s, t = pcall(require, p.."."..m)
|
||||||
if s then
|
if s then
|
||||||
ubiquitousse[m] = t
|
ubiquitousse[m] = t
|
||||||
|
elseif not t:match("^module [^n]+ not found") then
|
||||||
|
error(t)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
local input = require((...):match("^(.-%.)backend").."input")
|
local input = require((...):match("^(.-%.)backend").."input")
|
||||||
|
|
||||||
|
local loaded, signal = pcall(require, (...):match("^(.-)input").."signal")
|
||||||
|
if not loaded then signal = nil end
|
||||||
|
|
||||||
local gfx = require("ctr.gfx")
|
local gfx = require("ctr.gfx")
|
||||||
local hid = require("ctr.hid")
|
local hid = require("ctr.hid")
|
||||||
|
|
||||||
|
|
@ -266,4 +269,9 @@ input.default.pointer:bind(
|
||||||
input.default.confirm:bind("key.a")
|
input.default.confirm:bind("key.a")
|
||||||
input.default.cancel:bind("key.b")
|
input.default.cancel:bind("key.b")
|
||||||
|
|
||||||
|
--- Register signals
|
||||||
|
if signal then
|
||||||
|
signal.event:replace("update", oUpdate, input.update)
|
||||||
|
end
|
||||||
|
|
||||||
return input
|
return input
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
local input = require((...):match("^(.-%.)backend").."input")
|
local input = require((...):match("^(.-%.)backend").."input")
|
||||||
|
|
||||||
|
local loaded, signal = pcall(require, (...):match("^(.-)input").."signal")
|
||||||
|
if not loaded then signal = nil end
|
||||||
|
|
||||||
-- Config --
|
-- Config --
|
||||||
|
|
||||||
-- Use ScanCodes (layout independant input) instead of KeyConstants (layout dependant) for keyboard input
|
-- Use ScanCodes (layout independant input) instead of KeyConstants (layout dependant) for keyboard input
|
||||||
|
|
@ -13,24 +16,23 @@ local displayKeyConstant = true
|
||||||
love.mouse.setVisible(false)
|
love.mouse.setVisible(false)
|
||||||
|
|
||||||
-- Button detection
|
-- Button detection
|
||||||
-- FIXME love callbacks do something cleaner
|
|
||||||
local buttonsInUse = {}
|
local buttonsInUse = {}
|
||||||
local axesInUse = {}
|
local axesInUse = {}
|
||||||
function love.keypressed(key, scancode, isrepeat)
|
function input.keypressed(key, scancode, isrepeat)
|
||||||
if useScancodes then key = scancode end
|
if useScancodes then key = scancode end
|
||||||
buttonsInUse["keyboard."..key] = true
|
buttonsInUse["keyboard."..key] = true
|
||||||
end
|
end
|
||||||
function love.keyreleased(key, scancode)
|
function input.keyreleased(key, scancode)
|
||||||
if useScancodes then key = scancode end
|
if useScancodes then key = scancode end
|
||||||
buttonsInUse["keyboard."..key] = nil
|
buttonsInUse["keyboard."..key] = nil
|
||||||
end
|
end
|
||||||
function love.mousepressed(x, y, button, istouch)
|
function input.mousepressed(x, y, button, istouch)
|
||||||
buttonsInUse["mouse."..button] = true
|
buttonsInUse["mouse."..button] = true
|
||||||
end
|
end
|
||||||
function love.mousereleased(x, y, button, istouch)
|
function input.mousereleased(x, y, button, istouch)
|
||||||
buttonsInUse["mouse."..button] = nil
|
buttonsInUse["mouse."..button] = nil
|
||||||
end
|
end
|
||||||
function love.wheelmoved(x, y)
|
function input.wheelmoved(x, y)
|
||||||
if y > 0 then
|
if y > 0 then
|
||||||
buttonsInUse["mouse.wheel.up"] = true
|
buttonsInUse["mouse.wheel.up"] = true
|
||||||
elseif y < 0 then
|
elseif y < 0 then
|
||||||
|
|
@ -42,17 +44,17 @@ function love.wheelmoved(x, y)
|
||||||
buttonsInUse["mouse.wheel.left"] = true
|
buttonsInUse["mouse.wheel.left"] = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function love.mousemoved(x, y, dx, dy)
|
function input.mousemoved(x, y, dx, dy)
|
||||||
if dx ~= 0 then axesInUse["mouse.move.x"] = dx/love.graphics.getWidth() end
|
if dx ~= 0 then axesInUse["mouse.move.x"] = dx/love.graphics.getWidth() end
|
||||||
if dy ~= 0 then axesInUse["mouse.move.y"] = dy/love.graphics.getHeight() end
|
if dy ~= 0 then axesInUse["mouse.move.y"] = dy/love.graphics.getHeight() end
|
||||||
end
|
end
|
||||||
function love.gamepadpressed(joystick, button)
|
function input.gamepadpressed(joystick, button)
|
||||||
buttonsInUse["gamepad.button."..joystick:getID().."."..button] = true
|
buttonsInUse["gamepad.button."..joystick:getID().."."..button] = true
|
||||||
end
|
end
|
||||||
function love.gamepadreleased(joystick, button)
|
function input.gamepadreleased(joystick, button)
|
||||||
buttonsInUse["gamepad.button."..joystick:getID().."."..button] = nil
|
buttonsInUse["gamepad.button."..joystick:getID().."."..button] = nil
|
||||||
end
|
end
|
||||||
function love.gamepadaxis(joystick, axis, value)
|
function input.gamepadaxis(joystick, axis, value)
|
||||||
if value ~= 0 then
|
if value ~= 0 then
|
||||||
axesInUse["gamepad.axis."..joystick:getID().."."..axis] = value
|
axesInUse["gamepad.axis."..joystick:getID().."."..axis] = value
|
||||||
else
|
else
|
||||||
|
|
@ -61,11 +63,7 @@ function love.gamepadaxis(joystick, axis, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Windows size
|
-- Windows size
|
||||||
input.drawWidth, input.drawHeight = love.graphics.getWidth(), love.graphics.getHeight()
|
input.getDrawWidth, input.getDrawHeight = love.graphics.getWidth, love.graphics.getHeight
|
||||||
function love.resize(width, height)
|
|
||||||
input.drawWidth = width
|
|
||||||
input.drawHeight = height
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Update
|
-- Update
|
||||||
local oUpdate = input.update
|
local oUpdate = input.update
|
||||||
|
|
@ -190,7 +188,7 @@ input.basicAxisDetector = function(id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
input.buttonsInUse = function(threshold)
|
input.buttonUsed = function(threshold)
|
||||||
local r = {}
|
local r = {}
|
||||||
threshold = threshold or 0.5
|
threshold = threshold or 0.5
|
||||||
for b in pairs(buttonsInUse) do
|
for b in pairs(buttonsInUse) do
|
||||||
|
|
@ -201,10 +199,10 @@ input.buttonsInUse = function(threshold)
|
||||||
table.insert(r, b.."%"..(v < 0 and -threshold or threshold))
|
table.insert(r, b.."%"..(v < 0 and -threshold or threshold))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return r
|
return unpack(r)
|
||||||
end
|
end
|
||||||
|
|
||||||
input.axesInUse = function(threshold)
|
input.axisUsed = function(threshold)
|
||||||
local r = {}
|
local r = {}
|
||||||
threshold = threshold or 0.5
|
threshold = threshold or 0.5
|
||||||
for b,v in pairs(axesInUse) do
|
for b,v in pairs(axesInUse) do
|
||||||
|
|
@ -212,7 +210,7 @@ input.axesInUse = function(threshold)
|
||||||
table.insert(r, b.."%"..threshold)
|
table.insert(r, b.."%"..threshold)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return r
|
return unpack(r)
|
||||||
end
|
end
|
||||||
|
|
||||||
input.buttonName = function(...)
|
input.buttonName = function(...)
|
||||||
|
|
@ -316,4 +314,18 @@ input.default.cancel:bind(
|
||||||
"gamepad.button.1.b"
|
"gamepad.button.1.b"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
--- Register signals
|
||||||
|
if signal then
|
||||||
|
signal.event:bind("keypressed", input.keypressed)
|
||||||
|
signal.event:bind("keyreleased", input.keyreleased)
|
||||||
|
signal.event:bind("mousepressed", input.mousepressed)
|
||||||
|
signal.event:bind("mousereleased", input.mousereleased)
|
||||||
|
signal.event:bind("wheelmoved", input.wheelmoved)
|
||||||
|
signal.event:bind("mousemoved", input.mousemoved)
|
||||||
|
signal.event:bind("gamepadpressed", input.gamepadpressed)
|
||||||
|
signal.event:bind("gamepadreleased", input.gamepadreleased)
|
||||||
|
signal.event:bind("gamepadaxis", input.gamepadaxis)
|
||||||
|
signal.event:replace("update", oUpdate, input.update)
|
||||||
|
end
|
||||||
|
|
||||||
return input
|
return input
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
--- ubiquitousse.input
|
--- ubiquitousse.input
|
||||||
-- Depends on a backend.
|
-- Depends on a backend.
|
||||||
|
-- Optional dependencies: ubiquitousse.signal (to bind to update signal in signal.event)
|
||||||
|
local loaded, signal = pcall(require, (...):match("^(.-)input").."signal")
|
||||||
|
if not loaded then signal = nil end
|
||||||
|
|
||||||
-- TODO: some key selection helper? Will be backend-implemented, to account for all the possible input methods.
|
-- TODO: some key selection helper? Will be backend-implemented, to account for all the possible input methods.
|
||||||
-- TODO: some way to list all possible input / outputs, or make the *inUse make some separation between inputs indiscutitably in use and those who are incertain.
|
-- TODO: some way to list all possible input / outputs, or make the *inUse make some separation between inputs indiscutitably in use and those who are incertain.
|
||||||
|
|
@ -40,8 +43,8 @@ local button_mt = {
|
||||||
-- @treturn ButtonInput this ButtonInput object
|
-- @treturn ButtonInput this ButtonInput object
|
||||||
unbind = function(self, ...)
|
unbind = function(self, ...)
|
||||||
for _, d in ipairs({...}) do
|
for _, d in ipairs({...}) do
|
||||||
for i, detector in ipairs(self.detectors) do
|
for i=#self.detectors, 1, -1 do
|
||||||
if detector == d then
|
if self.detectors[i] == d then
|
||||||
table.remove(self.detectors, i)
|
table.remove(self.detectors, i)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
@ -270,7 +273,9 @@ local axis_mt = {
|
||||||
self.val, self.raw, self.max = val, raw, max
|
self.val, self.raw, self.max = val, raw, max
|
||||||
updated[self] = true
|
updated[self] = true
|
||||||
end
|
end
|
||||||
end
|
end,
|
||||||
|
|
||||||
|
--- LÖVE note: other callbacks that are defined in backend/love.lua and need to be called in the associated LÖVE callbacks.
|
||||||
}
|
}
|
||||||
axis_mt.__index = axis_mt
|
axis_mt.__index = axis_mt
|
||||||
|
|
||||||
|
|
@ -382,9 +387,9 @@ local pointer_mt = {
|
||||||
x = function(self)
|
x = function(self)
|
||||||
if self.grabbing == self then
|
if self.grabbing == self then
|
||||||
self:update()
|
self:update()
|
||||||
return self.valX + (self.offsetX or self.width or input.drawWidth/2)
|
return self.valX + (self.offsetX or self.width or input.getDrawWidth()/2)
|
||||||
else
|
else
|
||||||
return self.offsetX or self.width or input.drawWidth/2
|
return self.offsetX or self.width or input.getDrawWidth()/2
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
--- Returns the current Y value of the pointer.
|
--- Returns the current Y value of the pointer.
|
||||||
|
|
@ -392,9 +397,9 @@ local pointer_mt = {
|
||||||
y = function(self)
|
y = function(self)
|
||||||
if self.grabbing == self then
|
if self.grabbing == self then
|
||||||
self:update()
|
self:update()
|
||||||
return self.valY + (self.offsetY or self.height or input.drawHeight/2)
|
return self.valY + (self.offsetY or self.height or input.getDrawHeight()/2)
|
||||||
else
|
else
|
||||||
return self.offsetY or self.height or input.drawHeight/2
|
return self.offsetY or self.height or input.getDrawHeight()/2
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
|
@ -418,9 +423,9 @@ local pointer_mt = {
|
||||||
local magnitude = sqrt(x*x + y*y)
|
local magnitude = sqrt(x*x + y*y)
|
||||||
cx, cy = cx / magnitude * width, cy / magnitude * height
|
cx, cy = cx / magnitude * width, cy / magnitude * height
|
||||||
end
|
end
|
||||||
return cx + (self.offsetX or width or input.drawWidth/2), cy + (self.offsetY or height or input.drawHeight/2)
|
return cx + (self.offsetX or width or input.getDrawWidth()/2), cy + (self.offsetY or height or input.getDrawHeight()/2)
|
||||||
else
|
else
|
||||||
return self.offsetX or width or input.drawWidth/2, self.offsetY or height or input.drawHeight/2
|
return self.offsetX or width or input.getDrawWidth()/2, self.offsetY or height or input.getDrawHeight()/2
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
|
@ -445,7 +450,7 @@ local pointer_mt = {
|
||||||
if not updated[self] then
|
if not updated[self] then
|
||||||
local x, y = self.valX, self.valY
|
local x, y = self.valX, self.valY
|
||||||
local xSpeed, ySpeed = self.xSpeed, self.ySpeed
|
local xSpeed, ySpeed = self.xSpeed, self.ySpeed
|
||||||
local width, height = self.width or input.drawWidth/2, self.height or input.drawHeight/2
|
local width, height = self.width or input.getDrawWidth()/2, self.height or input.getDrawHeight()/2
|
||||||
local newX, newY = x, y
|
local newX, newY = x, y
|
||||||
local maxMovX, maxMovY = 0, 0 -- the maxium axis movement in a direction (used to determine which axes have the priority) (absolute value)
|
local maxMovX, maxMovY = 0, 0 -- the maxium axis movement in a direction (used to determine which axes have the priority) (absolute value)
|
||||||
for _, pointer in ipairs(self.detectors) do
|
for _, pointer in ipairs(self.detectors) do
|
||||||
|
|
@ -642,16 +647,16 @@ input = {
|
||||||
|
|
||||||
--- Returns a list of the buttons currently in use, identified by their string button identifier.
|
--- Returns a list of the buttons currently in use, identified by their string button identifier.
|
||||||
-- This may also returns "axis threshold" buttons if an axis passes the threshold.
|
-- This may also returns "axis threshold" buttons if an axis passes the threshold.
|
||||||
-- @treturn table<string> buttons identifiers list
|
-- @tparam[opt=0.5] number threshold the threshold to detect axes as button
|
||||||
-- @treturn[opt=0.5] number threshold the threshold to detect axes as button
|
-- @treturn string,... buttons identifiers list
|
||||||
-- @impl backend
|
-- @impl backend
|
||||||
buttonsInUse = function(threshold) end,
|
buttonUsed = function(threshold) end,
|
||||||
|
|
||||||
--- Returns a list of the axes currently in use, identified by their string axis identifier
|
--- Returns a list of the axes currently in use, identified by their string axis identifier
|
||||||
-- @treturn table<string> axes identifiers list
|
-- @tparam[opt=0.5] number threshold the threshold to detect axes
|
||||||
-- @treturn[opt=0.5] number threshold the threshold to detect axes
|
-- @treturn string,... axes identifiers list
|
||||||
-- @impl backend
|
-- @impl backend
|
||||||
axesInUse = function(threshold) end,
|
axisUsed = function(threshold) end,
|
||||||
|
|
||||||
--- Returns a nice name for the button identifier.
|
--- Returns a nice name for the button identifier.
|
||||||
-- Can be locale-depedant and stuff, it's only for display.
|
-- Can be locale-depedant and stuff, it's only for display.
|
||||||
|
|
@ -686,14 +691,14 @@ input = {
|
||||||
cancel = nil -- Button: used to cancel something. Example binds: Escape, B button.
|
cancel = nil -- Button: used to cancel something. Example binds: Escape, B button.
|
||||||
},
|
},
|
||||||
|
|
||||||
--- Draw area dimensions.
|
--- Get draw area dimensions.
|
||||||
-- Used for pointers.
|
-- Used for pointers.
|
||||||
-- @impl backend
|
-- @impl backend
|
||||||
drawWidth = 1,
|
getDrawWidth = function() return 1 end,
|
||||||
drawHeight = 1,
|
getDrawHeight = function() return 1 end,
|
||||||
|
|
||||||
--- Update all the Inputs.
|
--- Update all the Inputs.
|
||||||
-- Should be called at every game update; called by ubiquitousse.update.
|
-- Should be called at every game update. If ubiquitousse.signal is available, will be bound to the "update" signal in signal.event.
|
||||||
-- The backend can hook into this function to to its input-related updates.
|
-- The backend can hook into this function to to its input-related updates.
|
||||||
-- @tparam numder dt the delta-time
|
-- @tparam numder dt the delta-time
|
||||||
-- @impl ubiquitousse
|
-- @impl ubiquitousse
|
||||||
|
|
@ -701,6 +706,11 @@ input = {
|
||||||
dt = newDt
|
dt = newDt
|
||||||
updated = {}
|
updated = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- If you use LÖVE, note that in order to provide every feature (especially key detection), several callbacks functions will
|
||||||
|
-- need to be called on LÖVE events. See backend/love.lua.
|
||||||
|
-- If ubiquitousse.signal is available, these callbacks will be bound to signals in signal.event (with the same name as the LÖVE
|
||||||
|
-- callbacks, minux the "love.").
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Create default inputs
|
-- Create default inputs
|
||||||
|
|
@ -708,4 +718,9 @@ input.default.pointer = input.pointer()
|
||||||
input.default.confirm = input.button()
|
input.default.confirm = input.button()
|
||||||
input.default.cancel = input.button()
|
input.default.cancel = input.button()
|
||||||
|
|
||||||
|
-- Bind signals
|
||||||
|
if signal then
|
||||||
|
signal.event:bind("update", input.update)
|
||||||
|
end
|
||||||
|
|
||||||
return input
|
return input
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
--- ubiquitousse.scene
|
--- ubiquitousse.scene
|
||||||
-- Optional dependencies: ubiquitousse.timer (to provide each scene a timer registry)
|
-- Optional dependencies: ubiquitousse.timer (to provide each scene a timer registry)
|
||||||
|
-- Optional dependencies: ubiquitousse.signal (to bind to update and draw signal in signal.event)
|
||||||
|
local loaded, signal = pcall(require, (...):match("^(.-)scene").."signal")
|
||||||
|
if not loaded then signal = nil end
|
||||||
local loaded, timer = pcall(require, (...):match("^(.-)scene").."timer")
|
local loaded, timer = pcall(require, (...):match("^(.-)scene").."timer")
|
||||||
if not loaded then timer = nil end
|
if not loaded then timer = nil end
|
||||||
|
|
||||||
|
|
@ -134,8 +137,16 @@ scene = setmetatable({
|
||||||
table.remove(scene.stack)
|
table.remove(scene.stack)
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
--- Pop all scenes.
|
||||||
|
-- @impl ubiquitousse
|
||||||
|
popAll = function()
|
||||||
|
while scene.current do
|
||||||
|
scene.pop()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
--- Update the current scene.
|
--- Update the current scene.
|
||||||
-- Should be called at every game update; called by ubiquitousse.update.
|
-- Should be called at every game update. If ubiquitousse.signal is available, will be bound to the "update" signal in signal.event.
|
||||||
-- @tparam number dt the delta-time (milisecond)
|
-- @tparam number dt the delta-time (milisecond)
|
||||||
-- @param ... arguments to pass to the scene's update function after dt
|
-- @param ... arguments to pass to the scene's update function after dt
|
||||||
-- @impl ubiquitousse
|
-- @impl ubiquitousse
|
||||||
|
|
@ -147,7 +158,7 @@ scene = setmetatable({
|
||||||
end,
|
end,
|
||||||
|
|
||||||
--- Draw the current scene.
|
--- Draw the current scene.
|
||||||
-- Should be called every time the game is draw; called by ubiquitousse.draw.
|
-- Should be called every time the game is draw. If ubiquitousse.signal is available, will be bound to the "draw" signal in signal.event.
|
||||||
-- @param ... arguments to pass to the scene's draw function
|
-- @param ... arguments to pass to the scene's draw function
|
||||||
-- @impl ubiquitousse
|
-- @impl ubiquitousse
|
||||||
draw = function(...)
|
draw = function(...)
|
||||||
|
|
@ -160,4 +171,10 @@ scene = setmetatable({
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
|
-- Bind signals
|
||||||
|
if signal then
|
||||||
|
signal.event:bind("update", scene.update)
|
||||||
|
signal.event:bind("draw", scene.draw)
|
||||||
|
end
|
||||||
|
|
||||||
return scene
|
return scene
|
||||||
|
|
|
||||||
43
signal/backend/love.lua
Normal file
43
signal/backend/love.lua
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
local signal = require((...):match("^(.-%.)backend").."signal")
|
||||||
|
|
||||||
|
function signal.registerEvents()
|
||||||
|
local callbacks = { -- everything except run, errorhandler, threaderror
|
||||||
|
"displayrotated", "draw", "load", "lowmemory", "quit", "update",
|
||||||
|
"directorydropped", "filedropped", "focus", "mousefocus", "resize", "visible",
|
||||||
|
"keypressed", "keyreleased", "textedited", "textinput",
|
||||||
|
"mousemoved", "mousepressed", "mousereleased", "wheelmoved",
|
||||||
|
"gamepadaxis", "gamepadpressed", "gamepadreleased",
|
||||||
|
"joystickadded", "joystickaxis", "joystickhat", "joystickpressed", "joystickreleased", "joystickremoved",
|
||||||
|
"touchmoved", "touchpressed", "touchreleased"
|
||||||
|
}
|
||||||
|
local event = signal.event
|
||||||
|
for _, callback in ipairs(callbacks) do
|
||||||
|
if callback == "update" then
|
||||||
|
if love[callback] then
|
||||||
|
local old = love[callback]
|
||||||
|
love[callback] = function(dt)
|
||||||
|
old(dt)
|
||||||
|
event:emit(callback, dt*1000)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
love[callback] = function(dt)
|
||||||
|
event:emit(callback, dt*1000)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if love[callback] then
|
||||||
|
local old = love[callback]
|
||||||
|
love[callback] = function(...)
|
||||||
|
old(...)
|
||||||
|
event:emit(callback, ...)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
love[callback] = function(...)
|
||||||
|
event:emit(callback, ...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return signal
|
||||||
14
signal/init.lua
Normal file
14
signal/init.lua
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
local signal
|
||||||
|
|
||||||
|
local p = ...
|
||||||
|
if love then
|
||||||
|
signal = require(p..".backend.love")
|
||||||
|
elseif package.loaded["ctr"] then
|
||||||
|
error("NYI")
|
||||||
|
elseif package.loaded["libretro"] then
|
||||||
|
error("NYI")
|
||||||
|
else
|
||||||
|
error("no backend for ubiquitousse.signal")
|
||||||
|
end
|
||||||
|
|
||||||
|
return signal
|
||||||
116
signal/signal.can
Normal file
116
signal/signal.can
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
--- ubiquitousse.signal
|
||||||
|
|
||||||
|
let registry_mt = {
|
||||||
|
--- Map of signals to list of listeners.
|
||||||
|
-- @impl ubiquitousse
|
||||||
|
signals = {},
|
||||||
|
|
||||||
|
--- Bind one or several functions to a signal name.
|
||||||
|
-- @impl ubiquitousse
|
||||||
|
bind = :(name, fn, ...)
|
||||||
|
if not @signals[name] then
|
||||||
|
@signals[name] = {}
|
||||||
|
end
|
||||||
|
table.insert(@signals[name], fn)
|
||||||
|
if ... then
|
||||||
|
return @bind(name, ...)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Unbind one or several functions to a signal name.
|
||||||
|
-- @impl ubiquitousse
|
||||||
|
unbind = :(name, fn, ...)
|
||||||
|
if not @signals[name] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
for i=#@signals[name], 1, -1 do
|
||||||
|
if @signals[name] == fn then
|
||||||
|
table.remove(@signals[name], i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if ... then
|
||||||
|
return @unbind(name, ...)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Remove every bound function to a signal name.
|
||||||
|
-- @impl ubiquitousse
|
||||||
|
unbindAll = :(name)
|
||||||
|
@signals[name] = nil
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Replace a bound function with another function.
|
||||||
|
-- @impl ubiquitousse
|
||||||
|
replace = :(name, sourceFn, destFn)
|
||||||
|
if not @signals[name] then
|
||||||
|
@signals[name] = {}
|
||||||
|
end
|
||||||
|
for i, fn in ipairs(@signals[name]) do
|
||||||
|
if fn == sourceFn then
|
||||||
|
@signals[name][i] = destFn
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Remove every bound function to every signal.
|
||||||
|
-- @impl ubiquitousse
|
||||||
|
clear = :()
|
||||||
|
@signals = {}
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Emit a signal, i.e. call every function bound to it, with the given arguments.
|
||||||
|
-- @impl ubiquitousse
|
||||||
|
emit = :(name, ...)
|
||||||
|
if @signals[name] then
|
||||||
|
for _, fn in ipairs(@signals[name]) do
|
||||||
|
fn(...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
registry_mt.__index = registry_mt
|
||||||
|
|
||||||
|
let signal = {
|
||||||
|
--- Creates and return a new SignalRegistry.
|
||||||
|
-- A SignalRegistry is a separate ubiquitousse.signal instance: its signals will be independant from other registries.
|
||||||
|
-- @impl ubiquitousse
|
||||||
|
new = ()
|
||||||
|
return setmetatable({ signals = {} }, registry_mt)
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- Global SignalRegistry.
|
||||||
|
-- @impl ubiquitousse
|
||||||
|
signals = {},
|
||||||
|
bind = (...)
|
||||||
|
return registry_mt.bind(signal, ...)
|
||||||
|
end,
|
||||||
|
unbind = (...)
|
||||||
|
return registry_mt.unbind(signal, ...)
|
||||||
|
end,
|
||||||
|
clear = (...)
|
||||||
|
return registry_mt.clear(signal, ...)
|
||||||
|
end,
|
||||||
|
emit = (...)
|
||||||
|
return registry_mt.emit(signal, ...)
|
||||||
|
end,
|
||||||
|
|
||||||
|
--- SignalRegistry which will be used to bind signals that need to be called on game engine event.
|
||||||
|
-- For example, every ubiquitousse module with a "update" function will bind it to the "update" signal in the registry;
|
||||||
|
-- you can then call this signal on each game update to update every ubiquitousse module easily.
|
||||||
|
-- Provided signals:
|
||||||
|
-- * update, should be called on every game update
|
||||||
|
-- * draw, should be called on every game draw
|
||||||
|
-- * for LÖVE, there are callbacks for every LÖVE callback function that need to be called on their corresponding LÖVE callback
|
||||||
|
-- @impl mixed
|
||||||
|
event = nil,
|
||||||
|
|
||||||
|
--- Call this function to hook signal.event signals to the current backend.
|
||||||
|
-- For LÖVE, this means overriding every existing LÖVE callback. If a callback is already defined, the new one will call the old function along with the signal:emit.
|
||||||
|
-- @impl backend
|
||||||
|
registerEvents = () end
|
||||||
|
}
|
||||||
|
|
||||||
|
signal.event = signal.new()
|
||||||
|
|
||||||
|
return signal
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
--- ubiquitousse.timer
|
--- ubiquitousse.timer
|
||||||
-- Depends on a backend.
|
-- Depends on a backend.
|
||||||
|
-- Optional dependencies: ubiquitousse.signal (to bind to update signal in signal.event)
|
||||||
|
local loaded, signal = pcall(require, (...):match("^(.-)timer").."signal")
|
||||||
|
if not loaded then signal = nil end
|
||||||
|
|
||||||
local ease = require((...):match("^.-timer")..".easing")
|
local ease = require((...):match("^.-timer")..".easing")
|
||||||
local timer
|
local timer
|
||||||
|
|
||||||
|
|
@ -332,7 +336,7 @@ timer = {
|
||||||
-- @impl ubiquitousse
|
-- @impl ubiquitousse
|
||||||
delayed = {},
|
delayed = {},
|
||||||
lastTime = 0,
|
lastTime = 0,
|
||||||
update = function(...)
|
update = function(...) -- If ubiquitousse.signal is available, will be bound to the "update" signal in signal.event.
|
||||||
return registry_mt.update(timer, ...)
|
return registry_mt.update(timer, ...)
|
||||||
end,
|
end,
|
||||||
run = function(...)
|
run = function(...)
|
||||||
|
|
@ -346,4 +350,9 @@ timer = {
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- Bind signals
|
||||||
|
if signal then
|
||||||
|
signal.event:bind("update", timer.update)
|
||||||
|
end
|
||||||
|
|
||||||
return timer
|
return timer
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue