diff --git a/addons/init.lua b/addons/init.lua new file mode 100644 index 0000000..e69de29 diff --git a/addons/system.lua b/addons/system.lua index d7227aa..d69b531 100644 --- a/addons/system.lua +++ b/addons/system.lua @@ -1,4 +1,5 @@ local gui = require("gui") +local theme = require("gui.core.theme") local default_theme = theme:new("64342e", "b2989e", "909b9a") function gui:newWindow(x, y, w, h, text, draggable) diff --git a/core/init.lua b/core/init.lua new file mode 100644 index 0000000..e69de29 diff --git a/elements/init.lua b/elements/init.lua new file mode 100644 index 0000000..360df59 --- /dev/null +++ b/elements/init.lua @@ -0,0 +1,69 @@ +local gui = require("gui") +local color = require("gui.core.color") +local theme = require("gui.core.theme") +local transition = require("gui.elements.transitions") + +function gui:newMenu(title, sx, position, trans) + if not title then multi.error("Argument 1 string('title') is required") end + if not sx then multi.error("Argument 2 number('sx') is required") end + + local position = position or gui.ALIGN_LEFT + local trans = trans or transition.glide + + local menu, to, tc, open + if position == gui.ALIGN_LEFT then + menu = self:newFrame(0, 0, 0, 0, -sx, 0, sx, 1) + to = trans(-sx, 0, .25) + tc = trans(0, -sx, .25) + elseif position == gui.ALIGN_CENTER then + menu = self:newFrame(0, 0, 0, 0, .5 -sx/2, 1.1, sx, 1) + to = trans(1.1, 0, .35) + tc = trans(0, 1.1, .35) + elseif position == gui.ALIGN_RIGHT then + menu = self:newFrame(0, 0, 0, 0, 1, 0, sx, 1) + to = trans(1, 1 - sx, .25) + tc = trans(1 - sx, 1, .25) + end + + function menu:isOpen() + return open + end + + function menu:Open(show) + if show then + if not menu.lock then + menu.lock = true + local t = to() + t.OnStop(function() + open = true + menu.lock = false + end) + t.OnStep(function(p) + if position == gui.ALIGN_CENTER then + menu:setDualDim(nil, nil, nil, nil, nil, p) + else + menu:setDualDim(nil, nil, nil, nil, p) + end + end) + end + else + if not menu.lock then + menu.lock = true + local t = tc() + t.OnStop(function() + open = false + menu.lock = false + end) + t.OnStep(function(p) + if position == gui.ALIGN_CENTER then + menu:setDualDim(nil, nil, nil, nil, nil, p) + else + menu:setDualDim(nil, nil, nil, nil, p) + end + end) + end + end + end + + return menu +end diff --git a/elements/transitions.lua b/elements/transitions.lua new file mode 100644 index 0000000..a036305 --- /dev/null +++ b/elements/transitions.lua @@ -0,0 +1,56 @@ +local gui = require("gui") +local multi, thread = require("multi"):init() +local processor = gui:newProcessor("Transistion Processor") +local transition = {} + +local width, height, flags = love.window.getMode() +local fps = 60 + +if flags.refreshrate > 0 then + fps = flags.refreshrate +end + +transition.__index = transition +transition.__call = function(t, start, stop, time, ...) + local args = {...} + return function() + if not start or not stop then return multi.error("start and stop must be supplied") end + if start == stop then return multi.error("start and stop cannot be the same!") end + local handle = t.func(t, start, stop, time or 1, unpack(args)) + return { + OnStep = handle.OnStatus, + OnStop = handle.OnReturn + handle.OnError + } + end +end + +function transition:newTransition(func) + local c = {} + setmetatable(c, self) + + c.fps = fps + c.func = processor:newFunction(func) + c.OnStop = multi:newConnection() + + function c:SetFPS(fps) + self.fps = fps + end + + function c:GetFPS(fps) + return self.fps + end + + return c +end + +transition.glide = transition:newTransition(function(t, start, stop, time, ...) + local steps = t.fps*time + local piece = time/steps + local split = stop-start + for i = 0, steps do + thread.sleep(piece) + thread.pushStatus(start + i*(split/steps)) + end +end) + +return transition \ No newline at end of file diff --git a/init.lua b/init.lua index ee8d3a0..368a27f 100644 --- a/init.lua +++ b/init.lua @@ -4,7 +4,9 @@ local GLOBAL, THREAD = require("multi.integration.loveManager"):init() local color = require("gui.core.color") local gui = {} local updater = multi:newProcessor("UpdateManager", true) + local drawer = multi:newProcessor("DrawManager", true) + local bit = require("bit") local band, bor = bit.band, bit.bor local cursor_hand = love.mouse.getSystemCursor("hand") @@ -176,6 +178,10 @@ gui.HotKeys.OnRedo = gui:setHotKey({"lctrl", "y"}) + -- Utils +gui.newFunction = updater.newFunction + +function gui:getProcessor() return updater end + function gui:getObjectFocus() return object_focus end function gui:hasType(t) return band(self.type, t) == t end @@ -376,8 +382,7 @@ function gui:clone(opt) connections: Do we copy connections? (true/false) } ]] - -- DO = {[[setImage]], c.image or IMAGE} - -- Connections are used greatly throughout do we copy those + local temp local u = self:getUniques() if self.type == frame then @@ -389,9 +394,9 @@ function gui:clone(opt) elseif self.type == text then temp = gui:newTextLabel(self.text, self:getDualDim()) elseif self.type == image + button then - temp = gui:newImageButton(u.DO[2], self:getDualDim()) + temp = gui:newImageButton(u.Do[2], self:getDualDim()) elseif self.type == image then - temp = gui:newImageLabel(u.DO[2], self:getDualDim()) + temp = gui:newImageLabel(u.Do[2], self:getDualDim()) else -- We are dealing with a complex object temp = processDo(u) end @@ -404,7 +409,7 @@ function gui:clone(opt) if opt.connections then conn = true for i, v in pairs(self) do - if v.Type == "connector" then + if type(v) == "table" and v.Type == "connector" then -- We want to copy the connection functions from the original object and bind them to the new one if not temp[i] then -- Incase we are dealing with a custom object, create a connection if the custom objects unique declearation didn't @@ -436,6 +441,7 @@ function gui:getUniques(tab) visibility = self.visibility, color = self.color, borderColor = self.borderColor, + drawBorder = self.drawborder, rotation = self.rotation } @@ -480,6 +486,7 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual) c.visibility = 1 c.color = {.6, .6, .6} c.borderColor = color.black + c.drawBorder = true c.rotation = 0 c.OnLoad = multi:newConnection() @@ -1170,7 +1177,7 @@ end -- Video function gui:newVideo(source, x, y, w, h, sx, sy, sw, sh) - local c = self:newImageBase(video, x, y, w, h, sx, sy, sw, sh) + local c = self:newImageBase(video, x, y, w, h, sx, sy, sw, sh) c.OnVideoFinished = multi:newConnection() c.playing = false @@ -1310,7 +1317,7 @@ local drawtypes = { end } -local draw_handler = function(child) +local draw_handler = function(child, no_draw) local bg = child.color local bbg = child.borderColor local ctype = child.type @@ -1324,6 +1331,8 @@ local draw_handler = function(child) child.w = w child.h = h + if no_draw then return end + if child.clipDescendants then local children = child:getAllChildren() for c = 1, #children do -- Tell the children to clip themselves @@ -1342,42 +1351,46 @@ local draw_handler = function(child) elseif type(roundness) == "string" then love.graphics.setScissor(x - 1, y - 2, w + 2, h + 3) end - + local drawB = child.drawBorder -- Set color love.graphics.setLineStyle("smooth") love.graphics.setLineWidth(3) - love.graphics.setColor(bbg[1], bbg[2], bbg[3], vis) - love.graphics.rectangle("line", x, y, w, h, rx, ry, segments) + if drawB then + love.graphics.setColor(bbg[1], bbg[2], bbg[3], vis) + love.graphics.rectangle("line", x, y, w, h, rx, ry, segments) + end love.graphics.setColor(bg[1], bg[2], bg[3], vis) love.graphics.rectangle("fill", x, y, w, h, rx, ry, segments) + + if drawB then + if roundness == "top" then + love.graphics.rectangle("fill", x, y + ry / 2, w, h - ry / 2 + 1) + love.graphics.setLineStyle("rough") + love.graphics.setColor(bbg[1], bbg[2], bbg[3], 1) + love.graphics.setLineWidth(1) + love.graphics.line(x, y + ry, x, y + h + 1, x + 1 + w, y + h + 1, + x + 1 + w, y + ry) + love.graphics.line(x, y + h, x + 1 + w, y + h) + + love.graphics.setScissor() + love.graphics.setColor(bbg[1], bbg[2], bbg[3], .6) + love.graphics.line(x - 1, y + ry / 2 + 2, x - 1, y + h + 2) + love.graphics.line(x + w + 2, y + ry / 2 + 2, x + w + 2, y + h + 2) + elseif roundness == "bottom" then + love.graphics.rectangle("fill", x, y, w, h - ry + 2) + love.graphics.setLineStyle("rough") + love.graphics.setColor(bbg[1], bbg[2], bbg[3], 1) + love.graphics.setLineWidth(2) + love.graphics.line(x - 1, y + ry + 1, x - 1, y - 1, x + w + 1, y - 1, + x + w + 1, y + ry + 1) + love.graphics.setScissor() + love.graphics.line(x - 1, y - 1, x + w + 1, y - 1) - if roundness == "top" then - love.graphics.rectangle("fill", x, y + ry / 2, w, h - ry / 2 + 1) - love.graphics.setLineStyle("rough") - - love.graphics.setColor(bbg[1], bbg[2], bbg[3], 1) - love.graphics.setLineWidth(1) - love.graphics.line(x, y + ry, x, y + h + 1, x + 1 + w, y + h + 1, - x + 1 + w, y + ry) - love.graphics.line(x, y + h, x + 1 + w, y + h) - love.graphics.setScissor() - love.graphics.setColor(bbg[1], bbg[2], bbg[3], .6) - love.graphics.line(x - 1, y + ry / 2 + 2, x - 1, y + h + 2) - love.graphics.line(x + w + 2, y + ry / 2 + 2, x + w + 2, y + h + 2) - elseif roundness == "bottom" then - love.graphics.rectangle("fill", x, y, w, h - ry + 2) - love.graphics.setLineStyle("rough") - love.graphics.setColor(bbg[1], bbg[2], bbg[3], 1) - love.graphics.setLineWidth(2) - love.graphics.line(x - 1, y + ry + 1, x - 1, y - 1, x + w + 1, y - 1, - x + w + 1, y + ry + 1) - love.graphics.setScissor() - love.graphics.line(x - 1, y - 1, x + w + 1, y - 1) - - love.graphics.setColor(bbg[1], bbg[2], bbg[3], .6) - love.graphics.setLineWidth(2) - love.graphics.line(x - 1, y + 2, x - 1, y + h - 4 - ry / 2) - love.graphics.line(x + w + 1, y + 2, x + w + 1, y + h - 4 - ry / 2) + love.graphics.setColor(bbg[1], bbg[2], bbg[3], .6) + love.graphics.setLineWidth(2) + love.graphics.line(x - 1, y + 2, x - 1, y + h - 4 - ry / 2) + love.graphics.line(x + w + 1, y + 2, x + w + 1, y + h - 4 - ry / 2) + end end -- Start object specific stuff @@ -1406,9 +1419,39 @@ drawer:newLoop(function() first_loop = true end) +drawer:newThread(function() + while true do + thread.sleep(.01) + local children = gui.virtual:getAllChildren() + for i = 1, #children do + local child = children[i] + if child.effect then + child.effect(function() draw_handler(child, true) end) + else + draw_handler(child, true) + end + end + first_loop = true + end +end) + +local processors = { + updater.run +} + -- Drawing and Updating gui.draw = drawer.run -gui.update = updater.run +gui.update = function() + for i = 1, #processors do + processors[i]() + end +end + +function gui:newProcessor(name) + local proc = multi:newProcessor(name or "UnNamedProcess_"..multi.randomString(8), true) + table.insert(processors, proc.run) + return proc +end -- Virtual gui gui.virtual.type = frame @@ -1475,11 +1518,23 @@ gui.Events.OnResized(function(w, h) gui.dualDim.offset.size.y = nh gui.w = nw gui.h = nh + + gui.virtual.x = xt + gui.virtual.y = yt + gui.virtual.dualDim.offset.size.x = nw + gui.virtual.dualDim.offset.size.y = nh + gui.virtual.w = nw + gui.virtual.h = nh else gui.dualDim.offset.size.x = w gui.dualDim.offset.size.y = h gui.w = w gui.h = h + + gui.virtual.dualDim.offset.size.x = w + gui.virtual.dualDim.offset.size.y = h + gui.virtual.w = w + gui.virtual.h = h end end)