local NULL = function () end ---@class BUTTON.button ---@field name string ---@field x number ---@field y number ---@field w number ---@field h number --- ---@field borderWidth? number ---@field borderJoin? "bevel"|"milter"|"none" ---@field borderStyle? "rough"|"smooth" --- ---@field font? love.Font --- ---@field codeWhenPressed? function ---@field codeWhenReleased? function ---@field drawingTextFunc? function --- ---@field _hovering? boolean --- ---@field draw? function ---@field update? function local button = { name = "NEW BUTTON", x = 0, y = 0, w = 0, h = 0, backgroundColor = {0,0,0,0}, hoverColor = {1,1,1,0.5}, borderColor = {1,1,1}, textColor = {1,1,1}, font = love.graphics.newFont(15), borderWidth = 1, borderJoin = "none", borderStyle = "smooth", drawingBackgroundFunc = function(self) love.graphics.setLineWidth(self.borderWidth) love.graphics.setLineStyle(self.borderStyle) love.graphics.setLineJoin(self.borderJoin) love.graphics.setColor(unpack(self.backgroundColor)) love.graphics.rectangle('fill', self.x, self.y, self.w, self.h) if self._hovering then love.graphics.setColor(unpack(self.hoverColor)) love.graphics.rectangle('fill', self.x, self.y, self.w, self.h) end love.graphics.setColor(unpack(self.borderColor)) love.graphics.rectangle('line', self.x, self.y, self.w, self.h) end, drawingTextFunc = function(self) love.graphics.setFont(self.font) love.graphics.printf(self.name, self.x, self.y + (self.h * 0.25), self.w, "center") end, codeWhenPressed = NULL, codeWhenReleased = NULL, _hovering = false }; button.__index = button function button:draw() self:drawingBackgroundFunc() self:drawingTextFunc() end function button:isHovering(x,y) if x >= self.x and y >= self.y and x <= self.x + self.w and y <= self.y + self.h then self._hovering = true else self._hovering = false end end ---@param touch? boolean @ If the button is touched, remember to pass true into touch param function button:press(touch) if touch or self._hovering then self.codeWhenPressed() end end ---@param touch? boolean @ If the button is touched, remember to pass true into touch param function button:release(touch) if touch or self._hovering then self.codeWhenReleased() end end local BUTTON = {} ---@param D BUTTON.newData ---Validate the provided data, will be called by ``BUTTON.new`` and ``BUTTON.setDefaultOption``
---***WARNING! THIS FUNCTION WILL RAISE EXCEPTION IF DATA IS INVALID!*** function BUTTON.checkDataValidation(D) assert(type(D.name) == "string", "[name] is missing or not valid") assert(type(D.x) == "number" and D.x > 0, "[x] must be a positive integer") assert(type(D.y) == "number" and D.y > 0, "[y] must be a positive integer") assert(type(D.w) == "number" and D.w > 0, "[w] must be a positive integer") assert(type(D.h) == "number" and D.h > 0, "[h] must be a positive integer") assert((type(D.borderWidth) == "number" and D.borderWidth > 0) or D.drawingTextFunc == nil, "[borderWidth] must be a postive integer") assert(table.contains({"bevel", "milter", "none"}, D.borderJoin) or D.borderJoin == nil, "[borderJoin] must be 'bevel', 'milter' or 'none") assert(table.contains({"rough", "smooth"}, D.borderStyle) or D.borderStyle == nil, "[borderStyle] must be 'rough' or 'smooth'") assert((D.font and D.font.typeOf and D.font:typeOf("Font")) or D.font == nil, "[font] must be love.Font") local red_flag = false if D.backgroundColor then if type(D.backgroundColor) == "table" then if #D.backgroundColor == 3 or #D.backgroundColor == 4 then for _, v in pairs(D.backgroundColor) do if type(v) ~= "number" or v<0 or v>1 then red_flag = true end end else red_flag = true end else red_flag = true end end if red_flag then error("[backgroundColor] must be a table with r, g, b (, a) values, all of them must be integers between 0 and 1") end if D.hoverColor then if type(D.hoverColor) == "table" then if #D.hoverColor == 3 or #D.hoverColor == 4 then for _, v in pairs(D.hoverColor) do if type(v) ~= "number" or v<0 or v>1 then red_flag = true end end else red_flag = true end else red_flag = true end end if red_flag then error("[hoverColor] must be a table with r, g, b (, a) values, all of them must be integers between 0 and 1") end if D.borderColor then if type(D.borderColor) == "table" then if #D.borderColor == 3 or #D.borderColor == 4 then for _, v in pairs(D.borderColor) do if type(v) ~= "number" or v<0 or v>1 then red_flag = true end end else red_flag = true end else red_flag = true end end if red_flag then error("[borderColor] must be a table with r, g, b (, a) values, all of them must be integers between 0 and 1") end if D.textColor then if type(D.textColor) == "table" then if #D.textColor == 3 or #D.textColor == 4 then for _, v in pairs(D.textColor) do if type(v) ~= "number" or v<0 or v>1 then red_flag = true end end else red_flag = true end else red_flag = true end end if red_flag then error("[textColor] must be a table with r, g, b (, a) values, all of them must be integers between 0 and 1") end assert(type(D.codeWhenPressed) == "function" or D.codeWhenPressed == nil, "[codeWhenPressed] must be a function or nil") assert(type(D.codeWhenReleased) == "function" or D.codeWhenReleased == nil, "[codeWhenReleased] must be a function or nil") assert(type(D.drawingTextFunc) == "function" or D.drawingTextFunc == nil, "[drawingTextFunc] must be a function or nil") end ---@class BUTTON.newData ---@field name string # Name of the button, will be shown ---@field x number ---@field y number ---@field w number ---@field h number --- ---@field borderWidth? number|1 # Line width will be used to draw button ---@field borderJoin? "bevel"|"milter"|"none" ---@field borderStyle? "rough"|"smooth" --- ---@field font? love.Font --- ---@field backgroundColor? table<[r,g,b,a]> ---@field hoverColor? table<[r,g,b,a]> ---@field borderColor? table<[r,g,b,a]> ---@field textColor? table<[r,g,b,a]> --- ---@field codeWhenPressed? function|nil # Code will be execute when pressed ---@field codeWhenReleased? function|nil # Code will be execute when released ---@field drawingTextFunc? function|defaultDrawingTextFunc ---@param D BUTTON.newData ---@return BUTTON.button ---Create a new button, provide you a table with 2 functions inside: draw and update
---You need to put them into intended callbacks :) function BUTTON.new(D) BUTTON.checkDataValidation(D) return setmetatable({ name = D.name, x = D.x, y = D.y, w = D.w, h = D.h, borderWidth = D.borderWidth, borderJoin = D.borderJoin, borderStyle = D.borderStyle, backgroundColor = D.backgroundColor, hoverColor = D.hoverColor, borderColor = D.borderColor, textColor = D.textColor, codeWhenPressed = D.codeWhenPressed, codeWhenReleased = D.codeWhenReleased, drawingTextFunc = D.drawingTextFunc, }, button) end --- Set the default funciton used to drawing text, will be passed name, x, y, w and h function BUTTON.setDefaultDrawingTextFunction(f) assert(type(f) == "function", "[f] must be a function!") button.drawingTextFunc = f end ---@param D BUTTON.newData function BUTTON.setDefaultOption(D) BUTTON.checkDataValidation(D) for k, v in pairs(D) do if button[k] ~= nil then button[k] = v else error("There is no "..k.." parameter in BUTTON!") end end end return BUTTON