From 2bb4b8e25d4f47085ebd39e4c4480ec2ad533d6f Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Tue, 17 Oct 2023 09:45:19 -0400 Subject: [PATCH 01/10] OnWheelMoved supported on a gui object --- init.lua | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/init.lua b/init.lua index a8fe4a2..a6902a0 100644 --- a/init.lua +++ b/init.lua @@ -83,7 +83,7 @@ local function Hook(funcname, func) end -- This will run the hooks after everything has loaded -updater:newTask(function() +updater:newLoop(function(loop) Hook("quit", gui.Events.OnQuit.Fire) Hook("directorydropped", gui.Events.OnDirectoryDropped.Fire) Hook("displayrotated", gui.Events.OnDisplayRotated.Fire) @@ -103,6 +103,7 @@ updater:newTask(function() Hook("touchmoved", gui.Events.OnTouchMoved.Fire) Hook("touchpressed", gui.Events.OnTouchPressed.Fire) Hook("touchreleased", gui.Events.OnTouchReleased.Fire) + loop:Destroy() end) -- Hotkeys @@ -470,6 +471,14 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual) return true end + local function defaultCheck(...) + if not c:isActive() then return end + local x, y = love.mouse.getPosition() + if c:canPress(x, y) then + return c, ... + end + end + setmetatable(c, gui) c.__variables = {clip = {false, 0, 0, 0, 0}} c.active = true @@ -496,6 +505,7 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual) c.OnExit = multi:newConnection() c.OnMoved = testHierarchy .. multi:newConnection() + c.OnWheelMoved = defaultCheck / gui.Events.OnWheelMoved local dragging = false local entered = false From ae5bea943dda92fd381dbc12e7dda2c7db3aa1ea Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Tue, 17 Oct 2023 23:30:39 -0400 Subject: [PATCH 02/10] Changed how hooks work, fixed parent on root gui object --- init.lua | 49 +++++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/init.lua b/init.lua index a6902a0..8b3aac2 100644 --- a/init.lua +++ b/init.lua @@ -82,29 +82,25 @@ local function Hook(funcname, func) end end --- This will run the hooks after everything has loaded -updater:newLoop(function(loop) - Hook("quit", gui.Events.OnQuit.Fire) - Hook("directorydropped", gui.Events.OnDirectoryDropped.Fire) - Hook("displayrotated", gui.Events.OnDisplayRotated.Fire) - Hook("filedropped", gui.Events.OnFilesDropped.Fire) - Hook("focus", gui.Events.OnFocus.Fire) - Hook("mousefocus", gui.Events.OnMouseFocus.Fire) - Hook("resize", gui.Events.OnResized.Fire) - Hook("visible", gui.Events.OnVisible.Fire) - Hook("keypressed", gui.Events.OnKeyPressed.Fire) - Hook("keyreleased", gui.Events.OnKeyReleased.Fire) - Hook("textedited", gui.Events.OnTextEdited.Fire) - Hook("textinput", gui.Events.OnTextInputed.Fire) - Hook("mousemoved", gui.Events.OnMouseMoved.Fire) - Hook("mousepressed", gui.Events.OnMousePressed.Fire) - Hook("mousereleased", gui.Events.OnMouseReleased.Fire) - Hook("wheelmoved", gui.Events.OnWheelMoved.Fire) - Hook("touchmoved", gui.Events.OnTouchMoved.Fire) - Hook("touchpressed", gui.Events.OnTouchPressed.Fire) - Hook("touchreleased", gui.Events.OnTouchReleased.Fire) - loop:Destroy() -end) +Hook("quit", gui.Events.OnQuit.Fire) +Hook("directorydropped", gui.Events.OnDirectoryDropped.Fire) +Hook("displayrotated", gui.Events.OnDisplayRotated.Fire) +Hook("filedropped", gui.Events.OnFilesDropped.Fire) +Hook("focus", gui.Events.OnFocus.Fire) +Hook("mousefocus", gui.Events.OnMouseFocus.Fire) +Hook("resize", gui.Events.OnResized.Fire) +Hook("visible", gui.Events.OnVisible.Fire) +Hook("keypressed", gui.Events.OnKeyPressed.Fire) +Hook("keyreleased", gui.Events.OnKeyReleased.Fire) +Hook("textedited", gui.Events.OnTextEdited.Fire) +Hook("textinput", gui.Events.OnTextInputed.Fire) +Hook("mousemoved", gui.Events.OnMouseMoved.Fire) +Hook("mousepressed", gui.Events.OnMousePressed.Fire) +Hook("mousereleased", gui.Events.OnMouseReleased.Fire) +Hook("wheelmoved", gui.Events.OnWheelMoved.Fire) +Hook("touchmoved", gui.Events.OnTouchMoved.Fire) +Hook("touchpressed", gui.Events.OnTouchPressed.Fire) +Hook("touchreleased", gui.Events.OnTouchReleased.Fire) -- Hotkeys @@ -264,8 +260,7 @@ function gui:getAllChildren(vis) end function gui:newThread(func) - return updater:newThread("ThreadHandler<" .. self.type .. ">", func, self, - thread) + return updater:newThread("ThreadHandler<" .. self.type .. ">", func, self, thread) end function gui:setDualDim(x, y, w, h, sx, sy, sw, sh) @@ -472,11 +467,12 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual) end local function defaultCheck(...) - if not c:isActive() then return end + if not c:isActive() then return false end local x, y = love.mouse.getPosition() if c:canPress(x, y) then return c, ... end + return false end setmetatable(c, gui) @@ -1388,6 +1384,7 @@ gui.virtual.w = w gui.virtual.h = h -- Root gui +gui.parent = gui gui.type = frame gui.children = {} gui.dualDim = gui:newDualDim() From ffd3f24d055acb50ca6ae3d31c185c7c49d69845 Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Thu, 19 Oct 2023 13:45:56 -0400 Subject: [PATCH 03/10] Gradients --- core/color.lua | 7 ++- init.lua | 153 +++++++++++++++++++++++++++++++------------------ 2 files changed, 101 insertions(+), 59 deletions(-) diff --git a/core/color.lua b/core/color.lua index 5dceb57..555a1a2 100644 --- a/core/color.lua +++ b/core/color.lua @@ -47,7 +47,7 @@ function color.hsl(h, s, l) elseif h < 4 then r,b,g = 0,x,c elseif h < 5 then r,b,g = x,0,c else r,b,g = c,0,x - end return (r+m)*255, (g+m)*255, (b+m)*255 + end return (r+m)*255, (g+m)*255, (b+m)*255, 255 end min = math.min @@ -60,7 +60,7 @@ function color.hsv(h, s, v) local r = min (max (3*abs (((h )/180)%2-1)-1, 0), 1) local g = min (max (3*abs (((h -120)/180)%2-1)-1, 0), 1) local b = min (max (3*abs (((h +120)/180)%2-1)-1, 0), 1) - return k1 + k2 * r, k1 + k2 * g, k1 + k2 * b + return k1 + k2 * r, k1 + k2 * g, k1 + k2 * b, 1 end function color.isLight(r, g, b) @@ -102,9 +102,10 @@ function color.new(r, g, b, fmt) end local temp if fmt then - temp = {r,b,g} + temp = {r, b, g, 1} else temp = {love.math.colorFromBytes(r, g, b)} + temp[4] = 1 end setmetatable(temp, mt) return temp diff --git a/init.lua b/init.lua index 8b3aac2..ee8d3a0 100644 --- a/init.lua +++ b/init.lua @@ -25,7 +25,7 @@ gui.TYPE_VIDEO = video gui.TYPE_BUTTON = button gui.TYPE_ANIM = anim --- +-- Variables gui.__index = gui gui.MOUSE_PRIMARY = 1 @@ -264,26 +264,21 @@ function gui:newThread(func) end function gui:setDualDim(x, y, w, h, sx, sy, sw, sh) - self.dualDim.offset = { - pos = { - x = x or self.dualDim.offset.pos.x, - y = y or self.dualDim.offset.pos.y - }, - size = { - x = w or self.dualDim.offset.size.x, - y = h or self.dualDim.offset.size.y - } - } - self.dualDim.scale = { - pos = { - x = sx or self.dualDim.scale.pos.x, - y = sy or self.dualDim.scale.pos.y - }, - size = { - x = sw or self.dualDim.scale.size.x, - y = sh or self.dualDim.scale.size.y - } - } + --[[ + dd.offset.pos = {x = x or 0, y = y or 0} + self.dualDim.offset.size = {x = w or 0, y = h or 0} + self.dualDim.scale.pos = {x = sx or 0, y = sy or 0} + self.dualDim.scale.size = {x = sw or 0, y = sh or 0} + ]] + self.dualDim = self:newDualDim( + x or self.dualDim.offset.pos.x, + y or self.dualDim.offset.pos.y, + w or self.dualDim.offset.size.x, + h or self.dualDim.offset.size.y, + sx or self.dualDim.scale.pos.x, + sy or self.dualDim.scale.pos.y, + sw or self.dualDim.scale.size.x, + sh or self.dualDim.scale.size.y) end local image_cache = {} @@ -487,6 +482,8 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual) c.borderColor = color.black c.rotation = 0 + c.OnLoad = multi:newConnection() + c.OnPressed = testHierarchy .. multi:newConnection() c.OnPressedOuter = multi:newConnection() c.OnReleased = testHierarchy .. multi:newConnection() @@ -623,6 +620,10 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual) centerthread() end + function c:fullFrame() + self:setDualDim(0,0,0,0,0,0,1,1) + end + -- Add to the parents children table if virtual then c.parent = gui.virtual @@ -631,6 +632,7 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual) c.parent = self table.insert(self.children, c) end + local a = 0 return c end @@ -722,7 +724,9 @@ function gui:newTextBase(typ, txt, x, y, w, h, sx, sy, sw, sh) end function c:setFont(font, size) - if type(font) == "string" then + if type(font) == "number" then + self.font = love.graphics.newFont(font) + elseif type(font) == "string" then self.fontFile = font self.font = love.graphics.newFont(font, size) else @@ -1054,6 +1058,42 @@ gui.cacheImage = thread:newFunction(function(self, path_or_paths) end end) +function gui:applyGradient(direction, ...) + local colors = {...} + if direction == "horizontal" then + direction = true + elseif direction == "vertical" then + direction = false + else + error("Invalid direction '" .. tostring(direction) .. "' for gradient. Horizontal or vertical expected.") + end + local result = love.image.newImageData(direction and 1 or #colors, direction and #colors or 1) + for i, color in ipairs(colors) do + local x, y + if direction then + x, y = 0, i - 1 + else + x, y = i - 1, 0 + end + result:setPixel(x, y, color[1], color[2], color[3], color[4] or 255) + end + + local img = love.graphics.newImage(result) + img:setFilter('linear', 'linear') + local x, y, w, h = self:getAbsolutes() + self.imageColor = color.white + self.imageVisibility = 1 + self.image = img + self.image:setWrap("repeat", "repeat") + self.imageHeigth = img:getHeight() + self.imageWidth = img:getWidth() + self.quad = love.graphics.newQuad(0, 0, self.imageWidth, self.imageHeigth, self.imageWidth, self.imageHeigth) + + if not (band(self.type, image) == image) then + self.type = self.type + image + end +end + function gui:newImageBase(typ, x, y, w, h, sx, sy, sw, sh) local c = self:newBase(image + typ, x, y, w, h, sx, sy, sw, sh) c.color = color.white @@ -1069,43 +1109,41 @@ function gui:newImageBase(typ, x, y, w, h, sx, sy, sw, sh) c.setImage = function(self, i, x, y, w, h) if i == nil then return end - local img = load_image(i) - load_image(i).OnReturn(function(img) - img = love.graphics.newImage(img) - IMAGE = i - if type(i) == "string" then i = image_cache[i] or i end + img = love.image.newImageData(i) + img = love.graphics.newImage(img) + IMAGE = i + if type(i) == "string" then i = image_cache[i] or i end - if i and x then - self.imageHeigth = h - self.imageWidth = w + if i and x then + c.imageHeigth = h + c.imageWidth = w - if type(i) == "string" then - image_cache[i] = img - i = image_cache[i] - end - - self.image = i - self.image:setWrap("repeat", "repeat") - self.imageColor = color.white - self.quad = love.graphics.newQuad(x, y, w, h, self.image:getWidth(), self.image:getHeight()) - self.imageVisibility = 1 - - return - end - - if type(i) == "userdata" and i:type() == "Image" then - img = i + if type(i) == "string" then + image_cache[i] = img + i = image_cache[i] end - local x, y, w, h = self:getAbsolutes() - self.imageColor = color.white - self.imageVisibility = 1 - self.image = img - self.image:setWrap("repeat", "repeat") - self.imageHeigth = img:getHeight() - self.imageWidth = img:getWidth() - self.quad = love.graphics.newQuad(0, 0, self.imageWidth, self.imageHeigth, self.imageWidth, self.imageHeigth) - end) + c.image = i + c.image:setWrap("repeat", "repeat") + c.imageColor = color.white + c.quad = love.graphics.newQuad(x, y, w, h, c.image:getWidth(), c.image:getHeight()) + c.imageVisibility = 1 + + return + end + + if type(i) == "userdata" and i:type() == "Image" then + img = i + end + + local x, y, w, h = c:getAbsolutes() + c.imageColor = color.white + c.imageVisibility = 1 + c.image = img + c.image:setWrap("repeat", "repeat") + c.imageHeigth = img:getHeight() + c.imageWidth = img:getWidth() + c.quad = love.graphics.newQuad(0, 0, c.imageWidth, c.imageHeigth, c.imageWidth, c.imageHeigth) end return c end @@ -1312,6 +1350,7 @@ local draw_handler = function(child) love.graphics.rectangle("line", x, y, w, h, rx, ry, segments) love.graphics.setColor(bg[1], bg[2], bg[3], vis) love.graphics.rectangle("fill", x, y, w, h, rx, ry, segments) + if roundness == "top" then love.graphics.rectangle("fill", x, y + ry / 2, w, h - ry / 2 + 1) love.graphics.setLineStyle("rough") @@ -1346,7 +1385,9 @@ local draw_handler = function(child) drawtypes[band(ctype, image)](child, x, y, w, h) drawtypes[band(ctype, text)](child, x, y, w, h) drawtypes[band(ctype, box)](child, x, y, w, h) + if child.post then child:post() end + if child.__variables.clip[1] then love.graphics.setScissor() -- Remove the scissor end @@ -1382,6 +1423,7 @@ gui.virtual.dualDim.offset.size.x = w gui.virtual.dualDim.offset.size.y = h gui.virtual.w = w gui.virtual.h = h +gui.virtual.parent = gui.virtual -- Root gui gui.parent = gui @@ -1427,7 +1469,6 @@ end gui.Events.OnResized(function(w, h) if gui.aspect_ratio then local nw, nh, xt, yt = GetSizeAdjustedToAspectRatio(w, h) - print(nw, nh, xt, yt) gui.x = xt gui.y = yt gui.dualDim.offset.size.x = nw From 869db0c347010d02915a615d768b38de6989d484 Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Tue, 19 Dec 2023 01:48:01 -0500 Subject: [PATCH 04/10] Working on advanced gui elements --- addons/init.lua | 0 addons/system.lua | 1 + core/init.lua | 0 elements/init.lua | 69 +++++++++++++++++++++ elements/transitions.lua | 56 +++++++++++++++++ init.lua | 131 +++++++++++++++++++++++++++------------ 6 files changed, 219 insertions(+), 38 deletions(-) create mode 100644 addons/init.lua create mode 100644 core/init.lua create mode 100644 elements/init.lua create mode 100644 elements/transitions.lua 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) From 65d700954850dd25995587a17728a23930283be0 Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Wed, 20 Dec 2023 00:42:04 -0500 Subject: [PATCH 05/10] Working on gui canvas --- core/canvas.lua | 98 +++++++++++++++++++++++++++++++++++++++++++++++++ core/init.lua | 0 init.lua | 86 +++++++++++++++++++++++++++++++++---------- 3 files changed, 165 insertions(+), 19 deletions(-) create mode 100644 core/canvas.lua delete mode 100644 core/init.lua diff --git a/core/canvas.lua b/core/canvas.lua new file mode 100644 index 0000000..0592e6b --- /dev/null +++ b/core/canvas.lua @@ -0,0 +1,98 @@ +local gui = require("gui") +local multi, thread = require("multi"):init() + +local canvas = {} + +-- Run the canvas logic within another processor +local proc = gui:newProcessor("Canvas Handler") +local updater = proc:newLoop().OnLoop + +local draw_handler = gui.draw_handler + +function canvas:newCanvas() + local c = {} + setmetatable(c, gui) + local active = false + c.type = gui.TYPE_FRAME + c.children = {} + c.dualDim = gui:newDualDim() + c.x = 0 + c.y = 0 + + local w, h = love.graphics.getDimensions() + c.dualDim.offset.size.x = w + c.dualDim.offset.size.y = h + c.w = w + c.h = h + c.parent = c + + table.insert(canvas, c) + + proc:newThread(function() + while true do + print("Holding...") + thread.hold(c.isActive) + local children = c: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) + + function c:isActive(b) + if b == nil then + return active + end + active = b + end + + function c:OnUpdate(func) + if type(self) == "function" then func = self end + updater(function() func(c) end) + end + + function c:newThread(func) + return proc:newThread("ThreadHandler<" .. self.type .. ">", func, self, thread) + end + + function c:swap(c1, c2) + local ch1 = c1:getChildren() + local ch2 = c2:getChildren() + for i = 1, #ch1 do + ch1[i]:setParent(c2) + end + for i = 1, #ch2 do + ch2[i]:setParent(c1) + end + end + + return c +end + +gui.Events.OnResized(proc:newFunction(function(w, h) + for i = 1, #canvas do + local c = canvas[i] + if gui.aspect_ratio then + local nw, nh, xt, yt = gui.GetSizeAdjustedToAspectRatio(w, h) + c.x = xt + c.y = yt + c.dualDim.offset.size.x = nw + c.dualDim.offset.size.y = nh + c.w = nw + c.h = nh + else + c.dualDim.offset.size.x = w + c.dualDim.offset.size.y = h + c.w = w + c.h = h + end + end +end)) + +return canvas \ No newline at end of file diff --git a/core/init.lua b/core/init.lua deleted file mode 100644 index e69de29..0000000 diff --git a/init.lua b/init.lua index 368a27f..133325d 100644 --- a/init.lua +++ b/init.lua @@ -433,6 +433,11 @@ function gui:isActive() return self.active and not (self:isDescendantOf(gui.virtual)) end +function gui:isOnScreen() + + return +end + -- Base get uniques function gui:getUniques(tab) local base = { @@ -742,10 +747,8 @@ function gui:newTextBase(typ, txt, x, y, w, h, sx, sy, sw, sh) self.OnFontUpdated:Fire(self) end - function c:fitFont(n, max) - local max = max or math.huge + function c:fitFont(min_size, max_size) local font - local isdefault = false if self.fontFile then if self.fontFile:match("ttf") then font = function(n) @@ -757,27 +760,67 @@ function gui:newTextBase(typ, txt, x, y, w, h, sx, sy, sw, sh) end end else - isdefault = true font = function(n) return love.graphics.setNewFont(n) end end - local x, y, width, height = self:getAbsolutes() - local Font, text = self.Font, self.text - local s = 3 - Font = font(s) - while height < max and Font:getHeight() < height and Font:getWidth(text) < width do - s = s + 1 - Font = font(s) + local text = self.text + local x, y, max_width, max_height = self:getAbsolutes() + local min_size = min_size or 1 + local max_size = max_size or 100 -- You can adjust the maximum font size as needed + local tolerance = 0.1 + local f + while max_size - min_size > tolerance do + local size = (min_size + max_size) / 2 + + f = font(size) + local text_width = f:getWidth(text) + local text_height = f:getHeight() + + if text_width > max_width or text_height > max_height then + max_size = size + else + min_size = size + end end - Font = font(s - (4 + (n or 0))) - Font:setFilter("linear", "nearest", 4) - self.font = Font - self.textOffsetY = 0 - local top, bottom = self:calculateFontOffset(Font, 0) - self.textOffsetY = floor(((height - bottom) - top) / 2) - self.OnFontUpdated:Fire(self) - return s - (4 + (n or 0)) + self:setFont(f) + return min_size end + -- function c:fitFont(n, max) + -- local max = max or math.huge + -- local font + -- local isdefault = false + -- if self.fontFile then + -- if self.fontFile:match("ttf") then + -- font = function(n) + -- return love.graphics.newFont(self.fontFile, n, "normal") + -- end + -- else + -- font = function(n) + -- return love.graphics.newFont(self.fontFile, n) + -- end + -- end + -- else + -- isdefault = true + -- font = function(n) return love.graphics.setNewFont(n) end + -- end + -- local x, y, width, height = self:getAbsolutes() + -- local Font, text = self.Font, self.text + -- local s = 3 + -- Font = font(s) + -- while height < max and Font:getHeight() < height and Font:getWidth(text) < width do + -- s = s + 1 + -- Font = font(s) + -- end + -- Font = font(s - (4 + (n or 0))) + -- Font:setFilter("linear", "nearest", 4) + -- self.font = Font + -- self.textOffsetY = 0 + -- local top, bottom = self:calculateFontOffset(Font, 0) + -- self.textOffsetY = floor(((height - bottom) - top) / 2) + -- self.OnFontUpdated:Fire(self) + -- return s - (4 + (n or 0)) + -- end + function c:centerFont() local x, y, width, height = self:getAbsolutes() local top, bottom = self:calculateFontOffset(self.font, 0) @@ -1406,6 +1449,8 @@ local draw_handler = function(child, no_draw) end end +gui.draw_handler = draw_handler + drawer:newLoop(function() local children = gui:getAllChildren() for i = 1, #children do @@ -1443,6 +1488,7 @@ local processors = { gui.draw = drawer.run gui.update = function() for i = 1, #processors do + print(i) processors[i]() end end @@ -1500,6 +1546,8 @@ local function GetSizeAdjustedToAspectRatio(dWidth, dHeight) return newWidth, newHeight, (dWidth-newWidth)/2, (dHeight-newHeight)/2 end +gui.GetSizeAdjustedToAspectRatio = GetSizeAdjustedToAspectRatio + function gui:setAspectSize(w, h) if w and h then g_width, g_height = w, h From 6cbd09a460e3b4cdc30436ef7db43c4e98ada62d Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Thu, 21 Dec 2023 02:14:42 -0500 Subject: [PATCH 06/10] Fixed canvas, working on simulating events --- core/canvas.lua | 97 ++++------------------------------- core/simulate.lua | 108 +++++++++++++++++++++++++++++++++++++++ elements/transitions.lua | 2 +- init.lua | 15 +++--- 4 files changed, 126 insertions(+), 96 deletions(-) create mode 100644 core/simulate.lua diff --git a/core/canvas.lua b/core/canvas.lua index 0592e6b..93b8b5d 100644 --- a/core/canvas.lua +++ b/core/canvas.lua @@ -1,98 +1,21 @@ local gui = require("gui") -local multi, thread = require("multi"):init() -local canvas = {} - --- Run the canvas logic within another processor -local proc = gui:newProcessor("Canvas Handler") -local updater = proc:newLoop().OnLoop - -local draw_handler = gui.draw_handler - -function canvas:newCanvas() - local c = {} - setmetatable(c, gui) - local active = false - c.type = gui.TYPE_FRAME - c.children = {} - c.dualDim = gui:newDualDim() - c.x = 0 - c.y = 0 - - local w, h = love.graphics.getDimensions() - c.dualDim.offset.size.x = w - c.dualDim.offset.size.y = h - c.w = w - c.h = h - c.parent = c - - table.insert(canvas, c) - - proc:newThread(function() - while true do - print("Holding...") - thread.hold(c.isActive) - local children = c: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) - - function c:isActive(b) - if b == nil then - return active - end - active = b - end - - function c:OnUpdate(func) - if type(self) == "function" then func = self end - updater(function() func(c) end) - end - - function c:newThread(func) - return proc:newThread("ThreadHandler<" .. self.type .. ">", func, self, thread) - end +function newCanvas() + local c = gui:newVirtualFrame(0,0,0,0,0,0,1,1) function c:swap(c1, c2) - local ch1 = c1:getChildren() - local ch2 = c2:getChildren() - for i = 1, #ch1 do - ch1[i]:setParent(c2) + local temp = c1.children + c1.children = c2.children + c2.children = temp + for i,v in pairs(c1.children) do + v.parent = c1 end - for i = 1, #ch2 do - ch2[i]:setParent(c1) + for i,v in pairs(c2.children) do + v.parent = c2 end end return c end -gui.Events.OnResized(proc:newFunction(function(w, h) - for i = 1, #canvas do - local c = canvas[i] - if gui.aspect_ratio then - local nw, nh, xt, yt = gui.GetSizeAdjustedToAspectRatio(w, h) - c.x = xt - c.y = yt - c.dualDim.offset.size.x = nw - c.dualDim.offset.size.y = nh - c.w = nw - c.h = nh - else - c.dualDim.offset.size.x = w - c.dualDim.offset.size.y = h - c.w = w - c.h = h - end - end -end)) - -return canvas \ No newline at end of file +return newCanvas \ No newline at end of file diff --git a/core/simulate.lua b/core/simulate.lua new file mode 100644 index 0000000..42e147b --- /dev/null +++ b/core/simulate.lua @@ -0,0 +1,108 @@ +local gui = require("gui") +local multi, thread = require("multi"):init() +local transition = require("gui.elements.transitions") + +-- Triggers press then release +local function getPosition(obj, x, y) + if not x or y then + local cx, cy, w, h = obj:getAbsolutes() + return cx + w/2, cy + h/2 + else + return x, y + end +end + +proc = gui:getProcessor() + +local simulate = {} +local cursor = false +local smooth = false + +function simulate:moveCursor(bool) + cursor = bool +end + +function simulate:smoothMovement(bool) + smooth = bool +end + +function simulate:Press(button, x, y, istouch) + if self then + x, y = getPosition(self, x, y) + elseif x == nil or y == nil then + x, y = love.mouse.getPosition() + end + if cursor then + love.mouse.setPosition(x, y) + end + gui.Events.OnMousePressed:Fire(x, y, button or gui.MOUSE_PRIMARY, istouch or false) +end + +function simulate:Release(button, x, y, istouch) + if self then + x, y = getPosition(self, x, y) + elseif x == nil or y == nil then + x, y = love.mouse.getPosition() + end + if cursor then + love.mouse.setPosition(x, y) + end + gui.Events.OnMouseReleased:Fire(x, y, button or gui.MOUSE_PRIMARY, istouch or false) +end + +simulate.Click = proc:newFunction(function(self, button, x, y, istouch) + if self then + x, y = getPosition(self, x, y) + elseif x == nil or y == nil then + x, y = love.mouse.getPosition() + end + if cursor then + love.mouse.setPosition(x, y) + end + gui.Events.OnMousePressed:Fire(x, y, button or gui.MOUSE_PRIMARY, istouch or false) + thread.skip(1) + gui.Events.OnMouseReleased:Fire(x, y, button or gui.MOUSE_PRIMARY, istouch or false) +end, true) + +simulate.Move = proc:newFunction(function(self, dx, dy, x, y, istouch) + local dx, dy = dx or 0, dy or 0 + + if self then + x, y = getPosition(self, x, y) + elseif x == nil or y == nil then + x, y = love.mouse.getPosition() + end + gui.Events.OnMouseMoved:Fire(x, y, 0, 0, istouch or false) + thread.skip(1) + if smooth then + local gx = transition.glide(0, dx, .25) + local gy = transition.glide(0, dy, .25) + local xx = gx() + xx.OnStep(function(p) + _x, _y = love.mouse.getPosition() + if cursor then + love.mouse.setPosition(x + p, _y) + else + gui.Events.OnMouseMoved:Fire(x + p, _y, 0, 0, istouch or false) + end + end) + local yy = gy() + yy.OnStep(function(p) + _x, _y = love.mouse.getPosition() + if cursor then + love.mouse.setPosition(_x, y + p) + else + gui.Events.OnMouseMoved:Fire(_x, y + p, 0, 0, istouch or false) + end + end) + thread.hold(xx.OnStop * yy.OnStop) + gui.Events.OnMouseMoved:Fire(x + dx, y + dy, 0, 0, istouch or false) + else + if cursor then + love.mouse.setPosition(x + dx, y + dy) + end + gui.Events.OnMouseMoved:Fire(x + dx, y + dy, 0, 0, istouch or false) + end +end, true) + +return simulate \ No newline at end of file diff --git a/elements/transitions.lua b/elements/transitions.lua index a036305..003ed36 100644 --- a/elements/transitions.lua +++ b/elements/transitions.lua @@ -15,7 +15,7 @@ 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 + if start == stop then multi.print("start and stop cannot be the same!") return {OnStep = function() end, OnStop = function() end} end local handle = t.func(t, start, stop, time or 1, unpack(args)) return { OnStep = handle.OnStatus, diff --git a/init.lua b/init.lua index 133325d..af98b2b 100644 --- a/init.lua +++ b/init.lua @@ -327,6 +327,11 @@ function gui:bottomStack() table.insert(siblings, 1, self) end +function gui:OnUpdate(func) -- Not crazy about this approach, will probably rework this + if type(self) == "function" then func = self end + mainupdater(function() func(c) end) +end + local mainupdater = updater:newLoop().OnLoop function gui:canPress(mx, my) -- Get the intersection of the clip area and the self then test with the clip, otherwise test as normal @@ -480,8 +485,8 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual) end return false end - - setmetatable(c, gui) + setmetatable(c, self) + c.__index = self.__index c.__variables = {clip = {false, 0, 0, 0, 0}} c.active = true c.type = typ @@ -586,11 +591,6 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual) function c:respectHierarchy(bool) hierarchy = bool end - function c:OnUpdate(func) -- Not crazy about this approach, will probably rework this - if type(self) == "function" then func = self end - mainupdater(function() func(c) end) - end - local function centerthread() local centerfunc = function() return centerX or centerY -- If the condition is true it acts like a yield @@ -1488,7 +1488,6 @@ local processors = { gui.draw = drawer.run gui.update = function() for i = 1, #processors do - print(i) processors[i]() end end From 004d5b9ca447730dadc9133631db0496edcbf67d Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Fri, 22 Dec 2023 02:29:11 -0500 Subject: [PATCH 07/10] Fixed issue in transitions and updated simulate module --- core/simulate.lua | 76 ++++++++++++++++------------------------ elements/transitions.lua | 11 +++++- 2 files changed, 40 insertions(+), 47 deletions(-) diff --git a/core/simulate.lua b/core/simulate.lua index 42e147b..02bcd22 100644 --- a/core/simulate.lua +++ b/core/simulate.lua @@ -15,16 +15,6 @@ end proc = gui:getProcessor() local simulate = {} -local cursor = false -local smooth = false - -function simulate:moveCursor(bool) - cursor = bool -end - -function simulate:smoothMovement(bool) - smooth = bool -end function simulate:Press(button, x, y, istouch) if self then @@ -32,9 +22,7 @@ function simulate:Press(button, x, y, istouch) elseif x == nil or y == nil then x, y = love.mouse.getPosition() end - if cursor then - love.mouse.setPosition(x, y) - end + love.mouse.setPosition(x, y) gui.Events.OnMousePressed:Fire(x, y, button or gui.MOUSE_PRIMARY, istouch or false) end @@ -44,9 +32,7 @@ function simulate:Release(button, x, y, istouch) elseif x == nil or y == nil then x, y = love.mouse.getPosition() end - if cursor then - love.mouse.setPosition(x, y) - end + love.mouse.setPosition(x, y) gui.Events.OnMouseReleased:Fire(x, y, button or gui.MOUSE_PRIMARY, istouch or false) end @@ -56,9 +42,7 @@ simulate.Click = proc:newFunction(function(self, button, x, y, istouch) elseif x == nil or y == nil then x, y = love.mouse.getPosition() end - if cursor then - love.mouse.setPosition(x, y) - end + love.mouse.setPosition(x, y) gui.Events.OnMousePressed:Fire(x, y, button or gui.MOUSE_PRIMARY, istouch or false) thread.skip(1) gui.Events.OnMouseReleased:Fire(x, y, button or gui.MOUSE_PRIMARY, istouch or false) @@ -72,37 +56,37 @@ simulate.Move = proc:newFunction(function(self, dx, dy, x, y, istouch) elseif x == nil or y == nil then x, y = love.mouse.getPosition() end + + if dx == 0 and dy == 0 then + _x, _y = love.mouse.getPosition() + if x == _x and y == _y then + return + end + local dx, dy = 0, 0 + dx = x - _x + dy = y - _y + return simulate.Move(nil, dx, dy) + end gui.Events.OnMouseMoved:Fire(x, y, 0, 0, istouch or false) thread.skip(1) - if smooth then - local gx = transition.glide(0, dx, .25) - local gy = transition.glide(0, dy, .25) - local xx = gx() - xx.OnStep(function(p) - _x, _y = love.mouse.getPosition() - if cursor then - love.mouse.setPosition(x + p, _y) - else - gui.Events.OnMouseMoved:Fire(x + p, _y, 0, 0, istouch or false) - end - end) - local yy = gy() - yy.OnStep(function(p) - _x, _y = love.mouse.getPosition() - if cursor then - love.mouse.setPosition(_x, y + p) - else - gui.Events.OnMouseMoved:Fire(_x, y + p, 0, 0, istouch or false) - end - end) + local gx = transition.glide(0, dx, .25) + local gy = transition.glide(0, dy, .25) + local xx = gx() + xx.OnStep(function(p) + _x, _y = love.mouse.getPosition() + love.mouse.setPosition(x + p, _y) + end) + local yy = gy() + yy.OnStep(function(p) + _x, _y = love.mouse.getPosition() + love.mouse.setPosition(_x, y + p) + end) + if not(dx==0 and dy == 0) then + print("Holding...") thread.hold(xx.OnStop * yy.OnStop) - gui.Events.OnMouseMoved:Fire(x + dx, y + dy, 0, 0, istouch or false) - else - if cursor then - love.mouse.setPosition(x + dx, y + dy) - end - gui.Events.OnMouseMoved:Fire(x + dx, y + dy, 0, 0, istouch or false) end + print("Done") + gui.Events.OnMouseMoved:Fire(x + dx, y + dy, 0, 0, istouch or false) end, true) return simulate \ No newline at end of file diff --git a/elements/transitions.lua b/elements/transitions.lua index 003ed36..8605335 100644 --- a/elements/transitions.lua +++ b/elements/transitions.lua @@ -15,7 +15,16 @@ 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 multi.print("start and stop cannot be the same!") return {OnStep = function() end, OnStop = function() end} end + if start == stop then + local temp = { + OnStep = function() end, + OnStop = multi:newConnection() + } + proc:newTask(function() + temp.OnStop:Fire() + end) + return temp + end local handle = t.func(t, start, stop, time or 1, unpack(args)) return { OnStep = handle.OnStatus, From a5415e9e719055c6c5b23f747243d3a1a6f16069 Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Fri, 22 Dec 2023 22:27:01 -0500 Subject: [PATCH 08/10] testing stuff --- core/simulate.lua | 2 -- init.lua | 90 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 65 insertions(+), 27 deletions(-) diff --git a/core/simulate.lua b/core/simulate.lua index 02bcd22..0b887d3 100644 --- a/core/simulate.lua +++ b/core/simulate.lua @@ -82,10 +82,8 @@ simulate.Move = proc:newFunction(function(self, dx, dy, x, y, istouch) love.mouse.setPosition(_x, y + p) end) if not(dx==0 and dy == 0) then - print("Holding...") thread.hold(xx.OnStop * yy.OnStop) end - print("Done") gui.Events.OnMouseMoved:Fire(x + dx, y + dy, 0, 0, istouch or false) end, true) diff --git a/init.lua b/init.lua index af98b2b..c09101a 100644 --- a/init.lua +++ b/init.lua @@ -189,6 +189,7 @@ function gui:hasType(t) return band(self.type, t) == t end function gui:move(x, y) self.dualDim.offset.pos.x = self.dualDim.offset.pos.x + x self.dualDim.offset.pos.y = self.dualDim.offset.pos.y + y + self.OnPositionChanged:Fire(self, x, y) end function gui:moveInBounds(dx, dy) @@ -285,6 +286,19 @@ function gui:setDualDim(x, y, w, h, sx, sy, sw, sh) sy or self.dualDim.scale.pos.y, sw or self.dualDim.scale.size.x, sh or self.dualDim.scale.size.y) + self.OnSizeChanged:Fire(self, x, y, w, h, sx, sy, sw, sh) +end + +function gui:rawSetDualDim(x, y, w, h, sx, sy, sw, sh) + self.dualDim = self:newDualDim( + x or self.dualDim.offset.pos.x, + y or self.dualDim.offset.pos.y, + w or self.dualDim.offset.size.x, + h or self.dualDim.offset.size.y, + sx or self.dualDim.scale.pos.x, + sy or self.dualDim.scale.pos.y, + sw or self.dualDim.scale.size.x, + sh or self.dualDim.scale.size.y) end local image_cache = {} @@ -517,6 +531,9 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual) c.OnMoved = testHierarchy .. multi:newConnection() c.OnWheelMoved = defaultCheck / gui.Events.OnWheelMoved + c.OnSizeChanged = multi:newConnection() + c.OnPositionChanged = multi:newConnection() + local dragging = false local entered = false local moved = false @@ -592,21 +609,15 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual) function c:respectHierarchy(bool) hierarchy = bool end local function centerthread() - local centerfunc = function() - return centerX or centerY -- If the condition is true it acts like a yield - end - c:newThread(function() - while true do - thread.hold(centerfunc) - local x, y, w, h = c:getAbsolutes() - if centerX then - c:setDualDim(-w / 2, nil, nil, nil, .5) - end - if centerY then - c:setDualDim(nil, -h / 2, nil, nil, nil, .5) - end + if centerX or centerY then + local x, y, w, h = c:getAbsolutes() + if centerX then + c:rawSetDualDim(-w / 2, nil, nil, nil, .5) end - end) + if centerY then + c:rawSetDualDim(nil, -h / 2, nil, nil, nil, .5) + end + end end function c:enableDragging(but) @@ -622,14 +633,18 @@ function gui:newBase(typ, x, y, w, h, sx, sy, sw, sh, virtual) centerX = bool if centering then return end centering = true - centerthread() + self.OnSizeChanged(centerthread) + self.OnPositionChanged(centerthread) + updater:newLoop(centerthread) end function c:centerY(bool) centerY = bool if centering then return end centering = true - centerthread() + self.OnSizeChanged(centerthread) + self.OnPositionChanged(centerthread) + updater:newLoop(centerthread) end function c:fullFrame() @@ -1135,9 +1150,9 @@ function gui:applyGradient(direction, ...) self.imageVisibility = 1 self.image = img self.image:setWrap("repeat", "repeat") - self.imageHeigth = img:getHeight() + self.imageHeight = img:getHeight() self.imageWidth = img:getWidth() - self.quad = love.graphics.newQuad(0, 0, self.imageWidth, self.imageHeigth, self.imageWidth, self.imageHeigth) + self.quad = love.graphics.newQuad(0, 0, self.imageWidth, self.imageHeight, self.imageWidth, self.imageHeight) if not (band(self.type, image) == image) then self.type = self.type + image @@ -1148,6 +1163,8 @@ function gui:newImageBase(typ, x, y, w, h, sx, sy, sw, sh) local c = self:newBase(image + typ, x, y, w, h, sx, sy, sw, sh) c.color = color.white c.visibility = 0 + c.scaleX = 1 + c.scaleY = 1 local IMAGE function c:getUniques() @@ -1157,6 +1174,14 @@ function gui:newImageBase(typ, x, y, w, h, sx, sy, sw, sh) }) end + function c:flip(vert) + if vert then + c.scaleY = c.scaleY * -1 + else + c.scaleX = c.scaleX * -1 + end + end + c.setImage = function(self, i, x, y, w, h) if i == nil then return end img = love.image.newImageData(i) @@ -1165,7 +1190,7 @@ function gui:newImageBase(typ, x, y, w, h, sx, sy, sw, sh) if type(i) == "string" then i = image_cache[i] or i end if i and x then - c.imageHeigth = h + c.imageHeight = h c.imageWidth = w if type(i) == "string" then @@ -1191,9 +1216,9 @@ function gui:newImageBase(typ, x, y, w, h, sx, sy, sw, sh) c.imageVisibility = 1 c.image = img c.image:setWrap("repeat", "repeat") - c.imageHeigth = img:getHeight() + c.imageHeight = img:getHeight() c.imageWidth = img:getWidth() - c.quad = love.graphics.newQuad(0, 0, c.imageWidth, c.imageHeigth, c.imageWidth, c.imageHeigth) + c.quad = love.graphics.newQuad(0, 0, c.imageWidth, c.imageHeight, c.imageWidth, c.imageHeight) end return c end @@ -1294,9 +1319,24 @@ local drawtypes = { [0] = function(child, x, y, w, h) end, [1] = function(child, x, y, w, h) if child.image then - love.graphics.setColor(child.imageColor[1], child.imageColor[2], - child.imageColor[3], child.imageVisibility) - love.graphics.draw(child.image, child.quad, x, y, rad(child.rotation), w / child.imageWidth, h / child.imageHeigth) + if child.scaleX < 0 or child.scaleY < 0 then + local sx, sy = child.scaleX, child.scaleY + local adjustX, adjustY = child.scaleX * w, child.scaleY * h + love.graphics.setColor(child.imageColor[1], child.imageColor[2], + child.imageColor[3], child.imageVisibility) + if sx < 0 and sy < 0 then + love.graphics.draw(child.image, child.quad, x - adjustX, y - adjustY, rad(child.rotation), (w / child.imageWidth) * child.scaleX, (h / child.imageHeight) * child.scaleY) + elseif sx < 0 then + love.graphics.draw(child.image, child.quad, x - adjustX, y, rad(child.rotation), (w / child.imageWidth) * child.scaleX, h / child.imageHeight) + else + love.graphics.draw(child.image, child.quad, x, y - adjustY, rad(child.rotation), w / child.imageWidth, (h / child.imageHeight) * child.scaleY) + end + else + love.graphics.setColor(child.imageColor[1], child.imageColor[2], + child.imageColor[3], child.imageVisibility) + + love.graphics.draw(child.image, child.quad, x, y, rad(child.rotation), w / child.imageWidth, h / child.imageHeight) + end end end, [2] = function(child, x, y, w, h) @@ -1345,7 +1385,7 @@ local drawtypes = { if child.video and child.playing then love.graphics.setColor(child.videoColor[1], child.videoColor[2], child.videoColor[3], child.videoVisibility) - if w ~= child.imageWidth and h ~= child.imageHeigth then + if w ~= child.imageWidth and h ~= child.imageHeight then love.graphics.draw(child.video, x, y, rad(child.rotation), w / child.videoWidth, h / child.videoHeigth) else From 95aaafea65e369cc29bee4b7b932795888fd0f07 Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Wed, 6 Mar 2024 19:23:17 -0500 Subject: [PATCH 09/10] Testing --- init.lua | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/init.lua b/init.lua index a8fe4a2..8f23f84 100644 --- a/init.lua +++ b/init.lua @@ -237,14 +237,37 @@ end function gui:getChildren() return self.children end -function gui:getAbsolutes() -- returns x, y, w, h - return (self.parent.w * self.dualDim.scale.pos.x) + +function gui:offsetToScale() + local children = self:getAllChildren() + for i = 1, #children do + local child = children[i] + local x, y = child:getAbsolutes() + local _, __, w, h = child.parent:getAbsolutes() + print(x / w, y / h) + local _, __, w, h = child:getAbsolutes() + local _, __, pw, ph = child.parent:getAbsolutes() + print(w / pw, h / ph) + end +end + +function gui:getAbsolutes(transform) -- returns x, y, w, h + if transform then + return transform((self.parent.w * self.dualDim.scale.pos.x) + + self.dualDim.offset.pos.x + self.parent.x), + transform((self.parent.h * self.dualDim.scale.pos.y) + + self.dualDim.offset.pos.y + self.parent.y), transform((self.parent.w * + self.dualDim.scale.size.x) + self.dualDim.offset.size.x), + transform((self.parent.h * self.dualDim.scale.size.y) + + self.dualDim.offset.size.y) + else + return (self.parent.w * self.dualDim.scale.pos.x) + self.dualDim.offset.pos.x + self.parent.x, (self.parent.h * self.dualDim.scale.pos.y) + self.dualDim.offset.pos.y + self.parent.y, (self.parent.w * self.dualDim.scale.size.x) + self.dualDim.offset.size.x, (self.parent.h * self.dualDim.scale.size.y) + self.dualDim.offset.size.y + end end function gui:getAllChildren(vis) @@ -1390,18 +1413,16 @@ gui.dualDim.offset.size.y = h gui.w = w gui.h = h -local g_width, g_height -local function GetSizeAdjustedToAspectRatio(dWidth, dHeight) - local isLandscape = g_width > g_height +function gui:GetSizeAdjustedToAspectRatio(dWidth, dHeight) local newHeight = 0 local newWidth = 0 - if g_width / g_height > dWidth / dHeight then - newHeight = dWidth * g_height / g_width + if self.g_width / self.g_height > dWidth / dHeight then + newHeight = dWidth * self.g_height / self.g_width newWidth = dWidth else - newWidth = dHeight * g_width / g_height + newWidth = dHeight * self.g_width / self.g_height newHeight = dHeight end @@ -1410,17 +1431,15 @@ end function gui:setAspectSize(w, h) if w and h then - g_width, g_height = w, h - gui.aspect_ratio = true + self.g_width, self.g_height = w, h else - gui.aspect_ratio = false + self.g_width, self.g_height = 0, 0 end end gui.Events.OnResized(function(w, h) - if gui.aspect_ratio then - local nw, nh, xt, yt = GetSizeAdjustedToAspectRatio(w, h) - print(nw, nh, xt, yt) + if gui.g_width then + local nw, nh, xt, yt = gui:GetSizeAdjustedToAspectRatio(w, h) gui.x = xt gui.y = yt gui.dualDim.offset.size.x = nw From 496f56d5fa6553c3a783614cbbbff588cb944876 Mon Sep 17 00:00:00 2001 From: Ryan Ward Date: Wed, 6 Mar 2024 19:28:28 -0500 Subject: [PATCH 10/10] Fixed mainupdater --- init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/init.lua b/init.lua index 4aa2099..c486f66 100644 --- a/init.lua +++ b/init.lua @@ -364,13 +364,13 @@ function gui:bottomStack() table.insert(siblings, 1, self) end +local mainupdater = updater:newLoop().OnLoop + function gui:OnUpdate(func) -- Not crazy about this approach, will probably rework this if type(self) == "function" then func = self end mainupdater(function() func(c) end) end -local mainupdater = updater:newLoop().OnLoop - function gui:canPress(mx, my) -- Get the intersection of the clip area and the self then test with the clip, otherwise test as normal local x, y, w, h if self.__variables.clip[1] then