Added time controls and nice clock face

This commit is contained in:
2024-04-11 21:42:11 -06:00
parent a8df373f93
commit f3da84db34
107 changed files with 25454 additions and 49 deletions

View File

@ -0,0 +1,150 @@
--[[------------------------------------------------
-- Love Frames - A GUI library for LOVE --
-- Copyright (c) 2012-2014 Kenny Shields --
--]]------------------------------------------------
return function(loveframes)
---------- module start ----------
loveframes.objects = {}
--[[---------------------------------------------------------
- func: Create(type, parent)
- desc: creates a new object or multiple new objects
(based on the method used) and returns said
object or objects for further manipulation
--]]---------------------------------------------------------
function loveframes.Create(data, parent)
if type(data) == "string" then
local objects = loveframes.objects
local object = objects[data]
local objectcount = loveframes.objectcount
if not object then
loveframes.Error("Error creating object: Invalid object '" ..data.. "'.")
end
-- create the object
local newobject = object:new()
-- apply template properties to the object
loveframes.ApplyTemplatesToObject(newobject)
-- if the object is a tooltip, return it and go no further
if data == "tooltip" then
return newobject
end
-- remove the object if it is an internal
if newobject.internal then
newobject:Remove()
return
end
-- parent the new object by default to the base gui object
newobject.parent = loveframes.base
table.insert(loveframes.base.children, newobject)
-- if the parent argument is not nil, make that argument the object's new parent
if parent then
newobject:SetParent(parent)
end
loveframes.objectcount = objectcount + 1
-- return the object for further manipulation
return newobject
elseif type(data) == "table" then
-- table for creation of multiple objects
local objects = {}
-- this function reads a table that contains a layout of object properties and then
-- creates objects based on those properties
local function CreateObjects(t, o, c)
local child = c or false
local validobjects = loveframes.objects
for k, v in pairs(t) do
-- current default object
local object = validobjects[v.type]:new()
-- insert the object into the table of objects being created
table.insert(objects, object)
-- parent the new object by default to the base gui object
object.parent = loveframes.base
table.insert(loveframes.base.children, object)
if o then
object:SetParent(o)
end
-- loop through the current layout table and assign the properties found
-- to the current object
for i, j in pairs(v) do
if i ~= "children" and i ~= "func" then
if child then
if i == "x" then
object["staticx"] = j
elseif i == "y" then
object["staticy"] = j
else
object[i] = j
end
else
object[i] = j
end
elseif i == "children" then
CreateObjects(j, object, true)
end
end
if v.func then
v.func(object)
end
end
end
-- create the objects
CreateObjects(data)
return objects
end
end
--[[---------------------------------------------------------
- func: NewObject(id, name, inherit_from_base)
- desc: creates a new object
--]]---------------------------------------------------------
function loveframes.NewObject(id, name, inherit_from_base)
local objects = loveframes.objects
local object = false
if inherit_from_base then
local base = objects["base"]
object = loveframes.class(name, base)
objects[id] = object
else
object = loveframes.class(name)
objects[id] = object
end
return object
end
function loveframes.LoadObjects(dir)
local objectlist = loveframes.GetDirectoryContents(dir)
-- loop through a list of all gui objects and require them
for k, v in ipairs(objectlist) do
if v.extension == "lua" then
loveframes.require(v.requirepath)
end
end
end
--return objects
---------- module end ----------
end

View File

@ -0,0 +1,117 @@
--[[------------------------------------------------
-- Love Frames - A GUI library for LOVE --
-- Copyright (c) 2012-2014 Kenny Shields --
--]]------------------------------------------------
return function(loveframes)
---------- module start ----------
-- skins library
loveframes.skins = {}
--[[---------------------------------------------------------
- func: RegisterSkin(skin)
- desc: registers a skin
--]]---------------------------------------------------------
function loveframes.RegisterSkin(skin)
local skins = loveframes.skins
local name = skin.name
local author = skin.author
local version = skin.version
local basename = skin.base
local newskin = false
if name == "" or not name then
loveframes.Error("Skin registration error: Invalid or missing name data.")
end
if author == "" or not author then
loveframes.Error("Skin registration error: Invalid or missing author data.")
end
if version == "" or not version then
loveframes.Error("Skin registration error: Invalid or missing version data.")
end
local namecheck = skins[name]
if namecheck then
loveframes.Error("Skin registration error: A skin with the name '" ..name.. "' already exists.")
end
local dir = skin.directory or loveframes.config["DIRECTORY"] .. "/skins/" ..name
local dircheck = love.filesystem.getInfo(dir) ~= nil and love.filesystem.getInfo(dir)["type"] == "directory"
if not dircheck then
loveframes.Error("Skin registration error: Could not find a directory for skin '" ..name.. "'.")
end
local imagedir = skin.imagedir or dir .. "/images"
local imagedircheck = love.filesystem.getInfo(imagedir) ~= nil and love.filesystem.getInfo(imagedir)["type"] == "directory"
if not imagedircheck then
loveframes.Error("Skin registration error: Could not find an image directory for skin '" ..name.. "'.")
end
if basename then
--local basename = base
local base = skins[basename]
if not base then
loveframes.Error("Could not find base skin '" ..basename.. "' for skin '" ..name.. "'.")
end
newskin = loveframes.DeepCopy(base)
newskin.name = name
newskin.author = author
newskin.version = version
newskin.imagedir = imagedir
local skincontrols = skin.controls
local basecontrols = base.controls
if skincontrols and basecontrols then
for k, v in pairs(skincontrols) do
newskin.controls[k] = v
end
for k, v in pairs(skin) do
if type(v) == "function" then
newskin[k] = v
end
end
end
end
if not newskin then
newskin = skin
end
newskin.dir = dir
local images = {}
local indeximages = loveframes.config["INDEXSKINIMAGES"]
if indeximages then
local imagelist = loveframes.GetDirectoryContents(imagedir)
local filename, extension, image
for k, v in ipairs(imagelist) do
extension = v.extension
filename = v.name .. "." .. extension
if extension == "png" then
image = love.graphics.newImage(v.fullpath)
image:setFilter("nearest", "nearest")
images[filename] = image
end
end
end
newskin.images = images
skins[name] = newskin
end
function loveframes.LoadSkins(dir)
local skinlist = loveframes.GetDirectoryContents(dir)
-- loop through a list of all gui skins and require them
local skin
for k, v in ipairs(skinlist) do
if v.extension == "lua" then
skin = loveframes.require(v.requirepath)
--loveframes.RegisterSkin(skin)
end
end
end
--return skins
---------- module end ----------
end

View File

@ -0,0 +1,85 @@
--[[------------------------------------------------
-- Love Frames - A GUI library for LOVE --
-- Copyright (c) 2012-2014 Kenny Shields --
--]]------------------------------------------------
return function(loveframes)
---------- module start ----------
-- templates library
loveframes.templates = {}
--[[---------------------------------------------------------
- func: RegisterTemplate(template)
- desc: registers a template
--]]---------------------------------------------------------
function loveframes.RegisterTemplate(template)
-- display an error message if template is not a table
if type(template) ~= "table" then
loveframes.Error("Could not register template: Template argument must be a table.")
end
local name = template.name
local base = loveframes.objects["base"]
-- display an error message if a template name was not given
if not name then
loveframes.Error("Could not register template: No template name given.")
end
if name == "Base" then
base:include(template.properties["*"])
end
-- insert the template into the available templates table
loveframes.templates[name] = template
end
--[[---------------------------------------------------------
- func: ApplyTemplatesToObject(object)
- desc: applies the properties of registered templates
to an object
--]]---------------------------------------------------------
function loveframes.ApplyTemplatesToObject(object)
local templates = loveframes.templates
local type = object.type
-- loop through all available templates
for k, v in pairs(templates) do
-- make sure the base template doesn't get applied more than once
if k ~= "Base" then
local properties = v.properties
local hasall = loveframes.TableHasKey(properties, "*")
local hasobject = false
if not hasall then
hasobject = loveframes.TableHasKey(properties, type)
end
if hasall then
for k, v in pairs(properties["*"]) do
object[k] = v
end
elseif hasobject then
-- apply the template properties to the object
for k, v in pairs(properties[type]) do
object[k] = v
end
end
end
end
end
function loveframes.LoadTemplates(dir)
local templatelist = loveframes.GetDirectoryContents(dir)
-- loop through a list of all gui templates and require them
for k, v in ipairs(templatelist) do
if v.extension == "lua" then
local template = require(v.requirepath)
loveframes.RegisterTemplate(template)
end
end
end
--return templates
---------- module end ----------
end

View File

@ -0,0 +1,452 @@
--[[------------------------------------------------
-- Love Frames - A GUI library for LOVE --
-- Copyright (c) 2012-2014 Kenny Shields --
--]]------------------------------------------------
return function(loveframes)
---------- module start ----------
-- util library
--local util = {}
--[[---------------------------------------------------------
- func: SetState(name)
- desc: sets the current state
--]]---------------------------------------------------------
function loveframes.SetState(name)
loveframes.state = name
loveframes.base.state = name
end
--[[---------------------------------------------------------
- func: GetState()
- desc: gets the current state
--]]---------------------------------------------------------
function loveframes.GetState()
return loveframes.state
end
--[[---------------------------------------------------------
- func: SetActiveSkin(name)
- desc: sets the active skin
--]]---------------------------------------------------------
function loveframes.SetActiveSkin(name)
local skin = name and loveframes.skins[name]
if not skin then print("SetActiveSkin: no such skin") return end
loveframes.config["ACTIVESKIN"] = name
local object = loveframes.base
object:SetSkin(name)
end
--[[---------------------------------------------------------
- func: GetActiveSkin()
- desc: gets the active skin
--]]---------------------------------------------------------
function loveframes.GetActiveSkin()
local index = loveframes.config["ACTIVESKIN"]
return loveframes.skins[index]
end
--[[---------------------------------------------------------
- func: BoundingBox(x1, x2, y1, y2, w1, w2, h1, h2)
- desc: checks for a collision between two boxes
- note: I take no credit for this function
--]]---------------------------------------------------------
function loveframes.BoundingBox(x1, x2, y1, y2, w1, w2, h1, h2)
if x1 > x2 + w2 - 1 or y1 > y2 + h2 - 1 or x2 > x1 + w1 - 1 or y2 > y1 + h1 - 1 then
return false
else
return true
end
end
--[[---------------------------------------------------------
- func: GetCollisions(object, table)
- desc: gets all objects colliding with the mouse
--]]---------------------------------------------------------
function loveframes.GetCollisions(object, t)
local x, y = love.mouse.getPosition()
local curstate = loveframes.state
local object = object or loveframes.base
local visible = object.visible
local children = object.children
local internals = object.internals
local objectstate = object.state
local t = t or {}
if objectstate == curstate and visible then
local objectx = object.x
local objecty = object.y
local objectwidth = object.width
local objectheight = object.height
local col = loveframes.BoundingBox(x, objectx, y, objecty, 1, objectwidth, 1, objectheight)
local collide = object.collide
if col and collide then
local clickbounds = object.clickbounds
if clickbounds then
local cx = clickbounds.x
local cy = clickbounds.y
local cwidth = clickbounds.width
local cheight = clickbounds.height
local clickcol = loveframes.BoundingBox(x, cx, y, cy, 1, cwidth, 1, cheight)
if clickcol then
table.insert(t, object)
end
else
table.insert(t, object)
end
end
if children then
for k, v in ipairs(children) do
loveframes.GetCollisions(v, t)
end
end
if internals then
for k, v in ipairs(internals) do
local type = v.type
if type ~= "tooltip" then
loveframes.GetCollisions(v, t)
end
end
end
end
return t
end
--[[---------------------------------------------------------
- func: GetAllObjects(object, table)
- desc: gets all active objects
--]]---------------------------------------------------------
function loveframes.GetAllObjects(object, t)
local object = object or loveframes.base
local internals = object.internals
local children = object.children
local t = t or {}
table.insert(t, object)
if internals then
for k, v in ipairs(internals) do
loveframes.GetAllObjects(v, t)
end
end
if children then
for k, v in ipairs(children) do
loveframes.GetAllObjects(v, t)
end
end
return t
end
--[[---------------------------------------------------------
- func: GetDirectoryContents(directory, table)
- desc: gets the contents of a directory and all of
its subdirectories
--]]---------------------------------------------------------
function loveframes.GetDirectoryContents(dir, t)
local dir = dir
local t = t or {}
local dirs = {}
local files = love.filesystem.getDirectoryItems(dir)
for k, v in ipairs(files) do
local isdir = love.filesystem.getInfo(dir.. "/" ..v) ~= nil and love.filesystem.getInfo(dir.. "/" ..v)["type"] == "directory" --love.filesystem.isDirectory(dir.. "/" ..v)
if isdir == true then
table.insert(dirs, dir.. "/" ..v)
else
local parts = loveframes.SplitString(v, "([.])")
local extension = #parts > 1 and parts[#parts]
if #parts > 1 then
parts[#parts] = nil
end
local name = table.concat(parts, ".")
table.insert(t, {
path = dir,
fullpath = dir.. "/" ..v,
requirepath = loveframes.utf8.gsub(dir, "/", ".") .. "." ..name,
name = name,
extension = extension
})
end
end
for k, v in ipairs(dirs) do
t = loveframes.GetDirectoryContents(v, t)
end
return t
end
--[[---------------------------------------------------------
- func: Round(num, idp)
- desc: rounds a number based on the decimal limit
- note: I take no credit for this function
--]]---------------------------------------------------------
function loveframes.Round(num, idp)
local mult = 10^(idp or 0)
if num >= 0 then
return math.floor(num * mult + 0.5) / mult
else
return math.ceil(num * mult - 0.5) / mult
end
end
--[[---------------------------------------------------------
- func: SplitString(string, pattern)
- desc: splits a string into a table based on a given pattern
- note: I take no credit for this function
--]]---------------------------------------------------------
function loveframes.SplitString(str, pat)
local t = {} -- NOTE: use {n = 0} in Lua-5.0
if pat == " " then
local fpat = "(.-)" .. pat
local last_end = 1
local s, e, cap = loveframes.utf8.find(str, fpat, 1)
while s do
if s ~= #str then
cap = cap .. " "
end
if s ~= 1 or cap ~= "" then
table.insert(t,cap)
end
last_end = e+1
s, e, cap = loveframes.utf8.find(str, fpat, last_end)
end
if last_end <= #str then
cap = loveframes.utf8.sub(str, last_end)
table.insert(t, cap)
end
else
local fpat = "(.-)" .. pat
local last_end = 1
local s, e, cap = loveframes.utf8.find(str, fpat, 1)
while s do
if s ~= 1 or cap ~= "" then
table.insert(t,cap)
end
last_end = e+1
s, e, cap = loveframes.utf8.find(str, fpat, last_end)
end
if last_end <= #str then
cap = loveframes.utf8.sub(str, last_end)
table.insert(t, cap)
end
end
return t
end
--[[---------------------------------------------------------
- func: RemoveAll()
- desc: removes all gui elements
--]]---------------------------------------------------------
function loveframes.RemoveAll()
loveframes.base.children = {}
loveframes.base.internals = {}
loveframes.hoverobject = false
loveframes.downobject = false
loveframes.modalobject = false
loveframes.inputobject = false
loveframes.hover = false
end
--[[---------------------------------------------------------
- func: TableHasValue(table, value)
- desc: checks to see if a table has a specific value
--]]---------------------------------------------------------
function loveframes.TableHasValue(table, value)
for k, v in pairs(table) do
if v == value then
return true
end
end
return false
end
--[[---------------------------------------------------------
- func: TableHasKey(table, key)
- desc: checks to see if a table has a specific key
--]]---------------------------------------------------------
function loveframes.TableHasKey(table, key)
return table[key] ~= nil
end
--[[---------------------------------------------------------
- func: Error(message)
- desc: displays a formatted error message
--]]---------------------------------------------------------
function loveframes.Error(message)
error("[Love Frames] " ..message)
end
--[[---------------------------------------------------------
- func: GetCollisionCount()
- desc: gets the total number of objects colliding with
the mouse
--]]---------------------------------------------------------
function loveframes.GetCollisionCount()
return loveframes.collisioncount
end
--[[---------------------------------------------------------
- func: GetHover()
- desc: returns loveframes.hover, can be used to check
if the mouse is colliding with a visible
Love Frames object
--]]---------------------------------------------------------
function loveframes.GetHover()
return loveframes.hover
end
--[[---------------------------------------------------------
- func: RectangleCollisionCheck(rect1, rect2)
- desc: checks for a collision between two rectangles
based on two tables containing rectangle sizes
and positions
--]]---------------------------------------------------------
function loveframes.RectangleCollisionCheck(rect1, rect2)
return loveframes.BoundingBox(rect1.x, rect2.x, rect1.y, rect2.y, rect1.width, rect2.width, rect1.height, rect2.height)
end
--[[---------------------------------------------------------
- func: DeepCopy(orig)
- desc: copies a table
- note: I take not credit for this function
--]]---------------------------------------------------------
function loveframes.DeepCopy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[loveframes.DeepCopy(orig_key)] = loveframes.DeepCopy(orig_value)
end
setmetatable(copy, loveframes.DeepCopy(getmetatable(orig)))
else -- number, string, boolean, etc
copy = orig
end
return copy
end
--[[---------------------------------------------------------
- func: GetHoverObject()
- desc: returns loveframes.hoverobject
--]]---------------------------------------------------------
function loveframes.GetHoverObject()
return loveframes.hoverobject
end
--[[---------------------------------------------------------
- func: IsCtrlDown()
- desc: checks for ctrl, for use with multiselect, copy,
paste, and such. On OS X it actually looks for cmd.
--]]---------------------------------------------------------
function loveframes.IsCtrlDown()
if love._os == "OS X" then
return love.keyboard.isDown("lgui") or love.keyboard.isDown("rgui")
end
return love.keyboard.isDown("lctrl") or love.keyboard.isDown("rctrl")
end
function loveframes.Color(s, a)
local r, g, b = string.match(s, '#?(%x%x)(%x%x)(%x%x)')
if r == nil then return end
return tonumber(r, 16) / 0xFF, tonumber(g, 16) / 0xFF, tonumber(b, 16) / 0xFF, a or 1
end
--[[---------------------------------------------------------
- func: draw()
- desc: draws debug information
--]]---------------------------------------------------------
function loveframes.DebugDraw()
local infox = 5
local infoy = 40
local topcol = {type = "None", children = {}, x = 0, y = 0, width = 0, height = 0}
local hoverobject = loveframes.hoverobject
--local objects = loveframes.GetAllObjects()
local version = loveframes.version
local stage = loveframes.stage
local basedir = loveframes.config["DIRECTORY"]
local loveversion = love._version
local fps = love.timer.getFPS()
local deltatime = love.timer.getDelta()
local font = loveframes.basicfontsmall
if hoverobject then
topcol = hoverobject
end
-- show frame docking zones
if topcol.type == "frame" then
for k, v in pairs(topcol.dockzones) do
love.graphics.setLineWidth(1)
love.graphics.setColor(255/255, 0, 0, 100/255)
love.graphics.rectangle("fill", v.x, v.y, v.width, v.height)
love.graphics.setColor(255/255, 0, 0, 255/255)
love.graphics.rectangle("line", v.x, v.y, v.width, v.height)
end
end
-- outline the object that the mouse is hovering over
love.graphics.setColor(255/255, 204/255, 51/255, 255/255)
love.graphics.setLineWidth(2)
love.graphics.rectangle("line", topcol.x - 1, topcol.y - 1, topcol.width + 2, topcol.height + 2)
-- draw main debug box
love.graphics.setFont(font)
love.graphics.setColor(0, 0, 0, 200/255)
love.graphics.rectangle("fill", infox, infoy, 200, 70)
love.graphics.setColor(255/255, 0, 0, 255/255)
love.graphics.print("Love Frames - Debug (" ..version.. " - " ..stage.. ")", infox + 5, infoy + 5)
love.graphics.setColor(255/255, 255/255, 255/255, 255/255)
love.graphics.print("LOVE Version: " ..loveversion, infox + 10, infoy + 20)
love.graphics.print("FPS: " ..fps, infox + 10, infoy + 30)
love.graphics.print("Delta Time: " ..deltatime, infox + 10, infoy + 40)
love.graphics.print("Total Objects: " ..loveframes.objectcount, infox + 10, infoy + 50)
-- draw object information if needed
if topcol.type ~= "base" then
love.graphics.setColor(0, 0, 0, 200/255)
love.graphics.rectangle("fill", infox, infoy + 75, 200, 100)
love.graphics.setColor(255/255, 0, 0, 255/255)
love.graphics.print("Object Information", infox + 5, infoy + 80)
love.graphics.setColor(255/255, 255/255, 255/255, 255/255)
love.graphics.print("Type: " ..topcol.type, infox + 10, infoy + 95)
if topcol.children then
love.graphics.print("# of children: " .. #topcol.children, infox + 10, infoy + 105)
else
love.graphics.print("# of children: 0", infox + 10, infoy + 105)
end
if topcol.internals then
love.graphics.print("# of internals: " .. #topcol.internals, infox + 10, infoy + 115)
else
love.graphics.print("# of internals: 0", infox + 10, infoy + 115)
end
love.graphics.print("X: " ..topcol.x, infox + 10, infoy + 125)
love.graphics.print("Y: " ..topcol.y, infox + 10, infoy + 135)
love.graphics.print("Width: " ..topcol.width, infox + 10, infoy + 145)
love.graphics.print("Height: " ..topcol.height, infox + 10, infoy + 155)
end
end
--return util
---------- module end ----------
end