166 lines
3.9 KiB
Lua
166 lines
3.9 KiB
Lua
local GUI = {}
|
|
local EMPTY = {}
|
|
local Vector2 = require("Vector2")
|
|
local templates = {}
|
|
GUI.__index = GUI
|
|
|
|
|
|
local function clone(data)
|
|
if type(data) ~= "table" then
|
|
return data
|
|
else
|
|
|
|
local new = {}
|
|
for k, v in pairs(data) do
|
|
new[k] = clone(v)
|
|
end
|
|
return setmetatable(new, getmetatable(data))
|
|
end
|
|
end
|
|
|
|
function revipairs(t)
|
|
return function(t, i) i = i - 1 if i > 0 then return i, t[i] end end, t, #t+1
|
|
end
|
|
|
|
function GUI.sortByDepth(a, b)
|
|
return a.depth < b.depth
|
|
end
|
|
|
|
function getPos(self)
|
|
if self._parent then
|
|
local x0, y0 = self._parent:getPos()
|
|
return self.pos.x + x0, self.pos.y + y0
|
|
else
|
|
return self.pos.x, self.pos.y
|
|
end
|
|
end
|
|
function getSize(self)
|
|
return self.size.x, self.size.y
|
|
end
|
|
function getBounds(self)
|
|
local x, y = getPos(self)
|
|
return x, y, self.size.x, self.size.y
|
|
end
|
|
function inBounds(self, x, y)
|
|
local Ex, Ey, width, height = getBounds(self)
|
|
return (x > Ex and x < Ex + width and y > Ey and y < Ey + height)
|
|
end
|
|
|
|
function GUI.createElement(elementType, data)
|
|
assert(templates[elementType], "Element type \""..elementType.."\" dosen't exist")
|
|
|
|
local elem = data or {}
|
|
for k, v in pairs(templates[elementType]) do
|
|
if not (type(k) == "string" and k:find("^__")) and type(elem[k]) == "nil" then
|
|
elem[k] = clone(v)
|
|
end
|
|
end
|
|
setmetatable(elem, template)
|
|
|
|
-- Ensure that the mandatory varaibles are declered
|
|
elem.depth = elem.depth or 0
|
|
elem.pos = elem.pos or Vector2()
|
|
elem.size = elem.size or Vector2()
|
|
if type(elem.visible) ~= "boolean" then
|
|
elem.visible = true
|
|
end
|
|
|
|
if elem.load then elem:load() end
|
|
return elem
|
|
end
|
|
|
|
function GUI.new(class, width, height)
|
|
assert(width and height, "Width and height are undefined")
|
|
local self = setmetatable({}, class)
|
|
self.pos = Vector2()
|
|
self.size = Vector2(width, height)
|
|
|
|
self.getPos = getPos
|
|
self.getSize = getSize
|
|
self.getBounds = getBounds
|
|
self.inBounds = inBounds
|
|
|
|
self._elements = {}
|
|
return self
|
|
end
|
|
|
|
function GUI:removeElement(element)
|
|
for i, elem in ipairs(self._elements) do
|
|
if elem == element then
|
|
table.remove(self._elements, i)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
function GUI:addElement(elementType, data)
|
|
local elem = GUI.createElement(elementType, data)
|
|
elem._parent = self
|
|
-- Add it to the list
|
|
table.insert(self._elements, elem)
|
|
table.sort(self._elements, GUI.sortByDepth)
|
|
return elem
|
|
end
|
|
|
|
function GUI.newTemplate(name)
|
|
local template = {}
|
|
template.__index = template
|
|
|
|
template.getPos = getPos
|
|
template.getSize = getSize
|
|
template.getBounds = getBounds
|
|
template.inBounds = inBounds
|
|
|
|
templates[name] = template
|
|
return template
|
|
end
|
|
|
|
function GUI:resize(...)
|
|
for _, element in ipairs(self._elements) do
|
|
if element.resize then
|
|
element:resize(...)
|
|
end
|
|
end
|
|
end
|
|
|
|
function GUI.callMethod(parent, name, ...)
|
|
local useFallback = false
|
|
for _, element in revipairs(parent._elements) do
|
|
if element.visible then
|
|
if type(element._elements) == "table" then
|
|
if GUI.callMethod(element, name, ...) then break end
|
|
end
|
|
if useFallback and element[name.."Fallback"] then
|
|
element[name.."Fallback"](element, ...)
|
|
elseif element[name] then
|
|
if element[name](element, ...) then useFallback = true end
|
|
end
|
|
end
|
|
end
|
|
return useFallback
|
|
end
|
|
|
|
function GUI:draw(...)
|
|
local useFallback = false
|
|
for _, element in ipairs(self._elements) do
|
|
if element.visible then
|
|
if useFallback and element["drawFallback"] then
|
|
element["drawFallback"](element, ...)
|
|
elseif element["draw"] then
|
|
if element["draw"](element, ...) then useFallback = true end
|
|
end
|
|
if type(element._elements) == "table" then
|
|
GUI.draw(element, "draw", ...)
|
|
end
|
|
end
|
|
end
|
|
return useFallback
|
|
end
|
|
|
|
for i, name in pairs{"keypressed", "keyreleased", "mousemoved", "mousepressed", "mousereleased", "textinput"} do
|
|
GUI[name] = function(self, ...)
|
|
GUI.callMethod(self, name, ...)
|
|
end
|
|
end
|
|
|
|
return GUI |