starting mode escape hatch

This commit is contained in:
Michael Freno
2025-12-11 11:37:20 -05:00
parent eaf7383b8f
commit 0bceade7d5
8 changed files with 1420 additions and 16 deletions

View File

@@ -0,0 +1,275 @@
-- Mode Override Demo
-- Demonstrates per-element mode override in FlexLöve
-- Shows how to mix immediate and retained mode elements in the same application
package.path = package.path .. ";../?.lua;../modules/?.lua"
local FlexLove = require("FlexLove")
local Color = require("modules.Color")
-- Global state
local frameCount = 0
local clickCount = 0
local retainedPanelCreated = false
local retainedPanel = nil
function love.load()
-- Initialize FlexLove in immediate mode globally
FlexLove.init({
immediateMode = true,
theme = "space",
})
love.window.setTitle("Mode Override Demo - FlexLöve")
love.window.setMode(1200, 800)
end
function love.update(dt)
FlexLove.update(dt)
frameCount = frameCount + 1
end
function love.draw()
love.graphics.clear(0.1, 0.1, 0.15, 1)
FlexLove.beginFrame()
-- Title - Immediate mode (default, recreated every frame)
FlexLove.new({
text = "Mode Override Demo",
textSize = 32,
textColor = Color.new(1, 1, 1, 1),
width = "100vw",
height = 60,
textAlign = "center",
backgroundColor = Color.new(0.2, 0.2, 0.3, 1),
padding = { top = 15, bottom = 15 },
})
-- Container for demo panels
local container = FlexLove.new({
positioning = "flex",
flexDirection = "horizontal",
justifyContent = "center",
alignItems = "flex-start",
gap = 20,
width = "100vw",
height = "calc(100vh - 60px)",
padding = { top = 20, left = 20, right = 20, bottom = 20 },
})
-- LEFT PANEL: Immediate Mode (Dynamic, recreated every frame)
local leftPanel = FlexLove.new({
mode = "immediate", -- Explicit immediate mode (would be default anyway)
parent = container,
width = "45vw",
height = "calc(100vh - 100px)",
backgroundColor = Color.new(0.15, 0.15, 0.2, 0.95),
cornerRadius = 8,
padding = { top = 20, left = 20, right = 20, bottom = 20 },
positioning = "flex",
flexDirection = "vertical",
gap = 15,
})
-- Panel title
FlexLove.new({
parent = leftPanel,
text = "Immediate Mode Panel",
textSize = 24,
textColor = Color.new(0.4, 0.8, 1, 1),
width = "100%",
height = 40,
})
-- Description
FlexLove.new({
parent = leftPanel,
text = "Elements in this panel are recreated every frame.\nState is preserved by StateManager.",
textSize = 14,
textColor = Color.new(0.8, 0.8, 0.8, 1),
width = "100%",
height = 60,
})
-- Live frame counter (updates automatically)
FlexLove.new({
parent = leftPanel,
text = string.format("Frame: %d", frameCount),
textSize = 18,
textColor = Color.new(1, 1, 0.5, 1),
width = "100%",
height = 30,
backgroundColor = Color.new(0.2, 0.2, 0.3, 1),
padding = { top = 5, left = 10, right = 10, bottom = 5 },
cornerRadius = 4,
})
-- Click counter (updates automatically)
FlexLove.new({
parent = leftPanel,
text = string.format("Clicks: %d", clickCount),
textSize = 18,
textColor = Color.new(0.5, 1, 0.5, 1),
width = "100%",
height = 30,
backgroundColor = Color.new(0.2, 0.2, 0.3, 1),
padding = { top = 5, left = 10, right = 10, bottom = 5 },
cornerRadius = 4,
})
-- Interactive button (state preserved across frames)
FlexLove.new({
parent = leftPanel,
text = "Click Me! (Immediate Mode)",
textSize = 16,
textColor = Color.new(1, 1, 1, 1),
width = "100%",
height = 50,
themeComponent = "button",
onEvent = function(element, event)
if event.type == "release" then
clickCount = clickCount + 1
end
end,
})
-- Info box
FlexLove.new({
parent = leftPanel,
text = "Notice how the frame counter updates\nautomatically without any manual updates.\n\nThis is the power of immediate mode:\nUI reflects application state automatically.",
textSize = 13,
textColor = Color.new(0.7, 0.7, 0.7, 1),
width = "100%",
height = "auto",
backgroundColor = Color.new(0.1, 0.1, 0.15, 1),
padding = { top = 10, left = 10, right = 10, bottom = 10 },
cornerRadius = 4,
})
-- RIGHT PANEL: Retained Mode (Static, created once)
-- Only create on first frame
if not retainedPanelCreated then
retainedPanel = FlexLove.new({
mode = "retained", -- Explicit retained mode override
parent = container,
width = "45vw",
height = "calc(100vh - 100px)",
backgroundColor = Color.new(0.2, 0.15, 0.15, 0.95),
cornerRadius = 8,
padding = { top = 20, left = 20, right = 20, bottom = 20 },
positioning = "flex",
flexDirection = "vertical",
gap = 15,
})
-- Panel title (retained)
FlexLove.new({
mode = "retained",
parent = retainedPanel,
text = "Retained Mode Panel",
textSize = 24,
textColor = Color.new(1, 0.6, 0.4, 1),
width = "100%",
height = 40,
})
-- Description (retained)
FlexLove.new({
mode = "retained",
parent = retainedPanel,
text = "Elements in this panel are created once\nand persist across frames.",
textSize = 14,
textColor = Color.new(0.8, 0.8, 0.8, 1),
width = "100%",
height = 60,
})
-- Static frame counter (won't update)
local staticCounter = FlexLove.new({
mode = "retained",
parent = retainedPanel,
text = string.format("Created at frame: %d", frameCount),
textSize = 18,
textColor = Color.new(1, 1, 0.5, 1),
width = "100%",
height = 30,
backgroundColor = Color.new(0.3, 0.2, 0.2, 1),
padding = { top = 5, left = 10, right = 10, bottom = 5 },
cornerRadius = 4,
})
-- Click counter placeholder (must be manually updated)
local retainedClickCounter = FlexLove.new({
mode = "retained",
parent = retainedPanel,
text = string.format("Clicks: %d (manual update needed)", clickCount),
textSize = 18,
textColor = Color.new(0.5, 1, 0.5, 1),
width = "100%",
height = 30,
backgroundColor = Color.new(0.3, 0.2, 0.2, 1),
padding = { top = 5, left = 10, right = 10, bottom = 5 },
cornerRadius = 4,
})
-- Interactive button with manual update
FlexLove.new({
mode = "retained",
parent = retainedPanel,
text = "Click Me! (Retained Mode)",
textSize = 16,
textColor = Color.new(1, 1, 1, 1),
width = "100%",
height = 50,
themeComponent = "button",
onEvent = function(element, event)
if event.type == "release" then
clickCount = clickCount + 1
-- In retained mode, we must manually update the UI
retainedClickCounter.text = string.format("Clicks: %d (manual update needed)", clickCount)
end
end,
})
-- Info box (retained)
FlexLove.new({
mode = "retained",
parent = retainedPanel,
text = "Notice how this panel's elements\ndon't update automatically.\n\nIn retained mode, you must manually\nupdate element properties when state changes.\n\nThis gives better performance for\nstatic UI elements.",
textSize = 13,
textColor = Color.new(0.7, 0.7, 0.7, 1),
width = "100%",
height = "auto",
backgroundColor = Color.new(0.15, 0.1, 0.1, 1),
padding = { top = 10, left = 10, right = 10, bottom = 10 },
cornerRadius = 4,
})
retainedPanelCreated = true
end
FlexLove.endFrame()
-- Bottom instructions
love.graphics.setColor(0.5, 0.5, 0.5, 1)
love.graphics.print("Global mode: Immediate | Left panel: Immediate (explicit) | Right panel: Retained (override)", 10, love.graphics.getHeight() - 30)
love.graphics.print("Press ESC to quit", 10, love.graphics.getHeight() - 15)
end
function love.keypressed(key)
if key == "escape" then
love.event.quit()
end
end
function love.mousepressed(x, y, button)
FlexLove.mousepressed(x, y, button)
end
function love.mousereleased(x, y, button)
FlexLove.mousereleased(x, y, button)
end
function love.mousemoved(x, y, dx, dy)
FlexLove.mousemoved(x, y, dx, dy)
end