From a17e524730020a69735d9c8fcbc189bf70403f81 Mon Sep 17 00:00:00 2001 From: Michael Freno Date: Tue, 24 Feb 2026 21:50:12 -0500 Subject: [PATCH] debug mode --- FlexLove.lua | 69 ++++++++++++++++++++++++++++++++++++++++++++- modules/Context.lua | 6 +++- modules/Element.lua | 20 +++++++++++++ modules/types.lua | 2 ++ 4 files changed, 95 insertions(+), 2 deletions(-) diff --git a/FlexLove.lua b/FlexLove.lua index dcca43a..2c5987c 100644 --- a/FlexLove.lua +++ b/FlexLove.lua @@ -294,6 +294,10 @@ function flexlove.init(config) flexlove.initialized = true flexlove._initState = "ready" + -- Configure debug draw overlay + flexlove._debugDraw = config.debugDraw or false + flexlove._debugDrawKey = config.debugDrawKey or nil + -- Process all queued element creations local queue = flexlove._initQueue flexlove._initQueue = {} -- Clear queue before processing to prevent re-entry issues @@ -557,6 +561,49 @@ flexlove._backdropCanvas = nil ---@type {width: number, height: number} flexlove._canvasDimensions = { width = 0, height = 0 } +--- Recursively draw debug boundaries for an element and all its children +--- Draws regardless of visibility/opacity to reveal hidden or transparent elements +---@param element Element +local function drawDebugElement(element) + local color = element._debugColor + if color then + local bw = element._borderBoxWidth or (element.width + element.padding.left + element.padding.right) + local bh = element._borderBoxHeight or (element.height + element.padding.top + element.padding.bottom) + + -- Fill with 0.5 opacity + love.graphics.setColor(color[1], color[2], color[3], 0.5) + love.graphics.rectangle("fill", element.x, element.y, bw, bh) + + -- Border with full opacity, 1px line + love.graphics.setColor(color[1], color[2], color[3], 1) + love.graphics.setLineWidth(1) + love.graphics.rectangle("line", element.x, element.y, bw, bh) + end + + for _, child in ipairs(element.children) do + drawDebugElement(child) + end +end + +--- Render the debug draw overlay for all elements in the tree +--- Traverses every element regardless of visibility or opacity +function flexlove._renderDebugOverlay() + -- Save current graphics state + local prevR, prevG, prevB, prevA = love.graphics.getColor() + local prevLineWidth = love.graphics.getLineWidth() + + -- Clear any active scissor so debug draws are always visible + love.graphics.setScissor() + + for _, win in ipairs(flexlove.topElements) do + drawDebugElement(win) + end + + -- Restore graphics state + love.graphics.setColor(prevR, prevG, prevB, prevA) + love.graphics.setLineWidth(prevLineWidth) +end + --- Render all UI elements with optional backdrop blur support for glassmorphic effects --- Place your game scene in gameDrawFunc to enable backdrop blur on UI elements; use postDrawFunc for overlays ---@param gameDrawFunc function|nil pass component draws that should be affected by a backdrop blur @@ -667,6 +714,11 @@ function flexlove.draw(gameDrawFunc, postDrawFunc) -- Render performance HUD if enabled flexlove._Performance:renderHUD() + -- Render debug draw overlay if enabled + if flexlove._debugDraw then + flexlove._renderDebugOverlay() + end + love.graphics.setCanvas(outerCanvas) -- NOTE: Deferred callbacks are NOT executed here because the calling code @@ -918,8 +970,10 @@ end ---@param scancode string ---@param isrepeat boolean function flexlove.keypressed(key, scancode, isrepeat) - -- Handle performance HUD toggle flexlove._Performance:keypressed(key) + if flexlove._debugDrawKey and key == flexlove._debugDrawKey then + flexlove._debugDraw = not flexlove._debugDraw + end local focusedElement = Context.getFocused() if focusedElement then focusedElement:keypressed(key, scancode, isrepeat) @@ -1248,6 +1302,19 @@ function flexlove.clearFocus() Context.setFocused(nil) end +--- Enable or disable the debug draw overlay that renders element boundaries with random colors +--- Each element gets a unique color: full opacity border and 0.5 opacity fill to identify collisions and overlaps +---@param enabled boolean True to enable debug draw overlay, false to disable +function flexlove.setDebugDraw(enabled) + flexlove._debugDraw = enabled +end + +--- Check if the debug draw overlay is currently active +---@return boolean enabled True if debug draw overlay is enabled +function flexlove.getDebugDraw() + return flexlove._debugDraw +end + flexlove.Animation = Animation flexlove.Color = Color flexlove.Theme = Theme diff --git a/modules/Context.lua b/modules/Context.lua index 7d69e2a..97cd068 100644 --- a/modules/Context.lua +++ b/modules/Context.lua @@ -22,7 +22,11 @@ local Context = { _settingFocus = false, initialized = false, - + + -- Debug draw overlay + _debugDraw = false, + _debugDrawKey = nil, + -- Initialization state tracking ---@type "uninitialized"|"initializing"|"ready" _initState = "uninitialized", diff --git a/modules/Element.lua b/modules/Element.lua index 88549a3..d378e61 100644 --- a/modules/Element.lua +++ b/modules/Element.lua @@ -2018,6 +2018,26 @@ function Element.new(props) self._dirty = false -- Element properties have changed, needs layout self._childrenDirty = false -- Children have changed, needs layout + -- Debug draw: assign a stable random color for element boundary visualization + -- Uses a vibrant HSL-based color to ensure good visibility against any background + local hue = math.random() * 360 + local function hslToRgb(h) + local s, l = 0.9, 0.55 + local c = (1 - math.abs(2 * l - 1)) * s + local x = c * (1 - math.abs((h / 60) % 2 - 1)) + local m = l - c / 2 + local r, g, b + if h < 60 then r, g, b = c, x, 0 + elseif h < 120 then r, g, b = x, c, 0 + elseif h < 180 then r, g, b = 0, c, x + elseif h < 240 then r, g, b = 0, x, c + elseif h < 300 then r, g, b = x, 0, c + else r, g, b = c, 0, x end + return r + m, g + m, b + m + end + local dr, dg, db = hslToRgb(hue) + self._debugColor = { dr, dg, db } + return self end diff --git a/modules/types.lua b/modules/types.lua index f0ac85b..e7e7b69 100644 --- a/modules/types.lua +++ b/modules/types.lua @@ -198,6 +198,8 @@ local TransformProps ---@field gcInterval number? -- Frames between GC steps in periodic mode (default: 60) ---@field gcStepSize number? -- Work units per GC step, higher = more aggressive (default: 200) ---@field immediateModeBlurOptimizations boolean? -- Cache blur canvases in immediate mode to avoid re-rendering each frame (default: true) +---@field debugDraw boolean? -- Enable debug draw overlay showing element boundaries with random colors (default: false) +---@field debugDrawKey string? -- Key to toggle debug draw overlay at runtime (default: nil, no toggle key) local FlexLoveConfig = {} --=====================================--