require 'point' -- Clickable UI button ---@class Button ---@field position Point ---@field size Point ---@field prevPressed boolean ---@field lastPressed boolean Button = { position = Point:new( 1, 1 ), size = Point:new( 1, 1 ), prevPressed = false, lastPressed = false } -- Factory function ---@param position Point | nil ---@param size Point | nil ---@param pressed function | nil ---@param held function | nil ---@param released function | nil ---@return Button function Button:new( position, size, pressed, held, released ) local button = { position = position or Button.position, size = size or Button.size, prevPressed = false, lastPressed = false, pressed = pressed or Button.pressed, held = held or Button.held, released = released or Button.released } setmetatable( button, { __index = self } ) return button end -- Called when button just clicked function Button:pressed() end -- Called when button is held ---@param dt number function Button:held( dt ) dt = dt end -- Called when button is just unclicked function Button:released() end -- Drawing function function Button:draw() local x, y = self.position:coords() local w, h = self.size:coords() love.graphics.rectangle( 'line', x, y, w, h ) end -- Check if given point is in bounds of button ---@param point Point ---@return boolean function Button:checkPoint( point ) local px, py = point:coords() local sx, sy = self.position:coords() local ex, ey = self.position:coords() ex = ex + sx ey = ey + sy return px >= sx and px <= ex and py >= sy and py <= ey end -- Changing states and calls appropriate functions ---@param dt number ---@param point Point function Button:update( dt, point, pressed ) self.prevPressed = self.lastPressed self.lastPressed = pressed if self.lastPressed and not self.prevPressed then local inBounds = self:checkPoint( point ) if inBounds then self:pressed() end elseif self.lastPressed and self.prevPressed then self:held( dt ) elseif not self.lastPressed and self.prevPressed then self:released() end end