Skip to content

Instantly share code, notes, and snippets.

@EngineerSmith
Created July 8, 2022 12:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EngineerSmith/71cb3f8790914b26126190ec05c7c095 to your computer and use it in GitHub Desktop.
Save EngineerSmith/71cb3f8790914b26126190ec05c7c095 to your computer and use it in GitHub Desktop.
Modules for android buttons - doesn't handle scaling for you; you can add that
local input = require("input")
local button = { }
button.__index = button
button.new = function(x, y, w, h)
return setmetatable({ x = x, y = y, w = w, h = h}, button)
end
button.setTapCallback = function(self, callback, ...)
if not self.heldID then
if self.tapID then input.removeTapArea(self.tapID) end -- todo see input.regTapArea
self.callback = callback
self.tapID = input.regTapArea(self.x, self.y, self.w, self.h, callback, ...)
else
error("This is a held button already") -- could be dueled but for this example it's not
end
return self
end
button.setHeldCallback = function(self, startCallback, endCallback)
if not self.tapID then
if self.heldID then input.removeHeldArea(self.heldID) end -- todo see input.regHeldArea
self.startCallback, self.endCallback = startCallback, endCallback
self.heldID = input.regHeldArea(self.x, self.y, self.w, self.h, startCallback, endCallback)
else
error("This is a tap button already") -- could be dueled but for this example it's not
end
return self
end
button.draw = function(self)
love.graphics.setColor(.4,.4,.4)
love.graphics.rectangle("fill", self.x, self.y, self.w, self.h)
love.graphics.setColor(1,1,1)
if self.text then love.graphics.printf(self.text, self.x, self.y, self.w, "center") end
end
return button
-- Handle input; singleton but could easily be tweaked so you can have multiple controllers per scene if you wanted to manage different scene inputs and pause others (e.g. a menu vs game)
local input = {
touches = { },
tapDelay = 0.2,
tapAreas = { }, -- see input.regTapArea
heldAreas = { } -- see input.regHeldArea
}
local insert, remove = table.insert, table.remove
-- util func
local pointAABB = function(x1, y1, x2, y2, w, h)
return x1 > x2 and x1 < x2 + w and
y1 > y2 and y1 < y2 + h
end
--
input.getTouch = function(id)
for k, v in ipairs(input.touches) do
if v.id == id then return k, v end
end
return nil
end
input.touchpressed = function(id, x, y)
insert(input.touches, {
id = id,
x = x, y = y,
update = { },
time = love.timer.getTime(),
-- useful variables not internally used
startX = x, startY = y,
})
for _, area in ipairs(input.heldAreas) do
if pointAABB(x, y, area.x, area.y, area.w, area.h) then
local id = #input.touches
input.touches[id].held = area
area.startCallback()
end
end
end
input.touchmoved = function(id, x, y)
local key, touch = input.getTouch(id)
if key then
table.insert(touch.update, { x = x, y = y})
end
end
input.touchreleased = function(id, x, y)
local key, touch = input.getTouch(id)
if key then
local time = love.timer.getTime() - touch.time
if touch.held then
touch.held.endCallback()
elseif time < input.tapDelay then -- if not touch.held
input.tap(x, y)
end
remove(input.touches, key)
end
end
input.tap = function(x, y)
for _, area in ipairs(input.tapAreas) do
if pointAABB(x, y, area.x, area.y, area.w, area.h) then
if area.args then
area.callback(unpack(area.args))
else area.callback() end
end
end
end
input.regTapArea = function(x, y, w, h, callback, ...)
insert(input.tapAreas, {
x = x, y = y, w = w, h = h, callback = callback,
})
local id = #input.tapAreas
if select('#', ...) ~= 0 then
input.tapAreas[id].args = {...}
end
return id -- todo add remove function using returned id
end
input.regHeldArea = function(x, y, w, h, startCallback, endCallback)
insert(input.heldAreas, {
x = x, y = y, w = w, h = h, startCallback = startCallback, endCallback = endCallback,
})
return #input.heldAreas -- todo add remove function using returned id
end
input.update = function() -- this function is like this cause I ripped it out of my old code where more things are done here (e.g. pinch zoom and drag movement)
for _, touch in ipairs(input.touches) do
for _, update in ipairs(touch.update) do
touch.x, touch.y = update.x, update.y
end
end
end
return input
local input = require("input")
local button = require("button")
local w, h = love.graphics.getDimensions()
local b1 = button.new(w/2-50, h/2-50 - 150, 100, 100)
b1:setTapCallback(function(button) button.text = "I've been tapped" end, b1) -- showing off args
local b2 = button.new(w/2-50, h/2-50 + 0, 100, 100)
b2:setHeldCallback(function() b2.text = "I'm being held" end, function() b2.text = nil end)
local b3 = button.new(w/2-50, h/2-50 + 150, 100, 100)
b3.text = "Reset"
b3:setTapCallback(function() b1.text = nil end)
love.update = function()
input.update()
end
love.touchpressed = input.touchpressed -- lazy than writing a wrapper
love.touchmoved = input.touchmoved
love.touchreleased = input.touchrelease
-- debug on PC
love.mousepressed = function(x, y, _, _, isTouch)
if ifTouch then return end
input.touchpressed("mouse", x, y)
end
love.mousemoved = function(x, y, _, _, isTouch)
if ifTouch then return end
input.touchmoved("mouse", x, y)
end
love.mousereleased = function(x, y, _, _, isTouch)
if ifTouch then return end
input.touchreleased("mouse", x, y)
end
love.draw = function()
b1:draw()
b2:draw()
b3:draw()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment