broken restrained mode - will revert

This commit is contained in:
Michael Freno
2025-11-05 19:46:14 -05:00
parent c77d93fdee
commit 7783be2d4f
2 changed files with 73 additions and 19 deletions

View File

@@ -54,8 +54,10 @@ local Positioning, FlexDirection, JustifyContent, AlignContent, AlignItems, Text
local Gui = GuiState
--- Initialize FlexLove with configuration
---@param config {baseScale?: {width?:number, height?:number}, theme?: string|ThemeDefinition, immediateMode?: boolean, stateRetentionFrames?: number, maxStateEntries?: number}
---@param config {baseScale?: {width?:number, height?:number}, theme?: string|ThemeDefinition, immediateMode?: boolean, stateRetentionFrames?: number, maxStateEntries?: number, autoFrameManagement?: boolean}
function Gui.init(config)
config = config or {}
if config.baseScale then
Gui.baseScale = {
width = config.baseScale.width or 1920,
@@ -85,22 +87,18 @@ function Gui.init(config)
end
end
-- Initialize immediate mode if requested
if config.immediateMode then
Gui._immediateMode = true
Gui._immediateModeState = ImmediateModeState
local immediateMode = config.immediateMode or false
Gui.setMode(immediateMode and "immediate" or "retained")
-- Configure state management
if config.stateRetentionFrames or config.maxStateEntries then
ImmediateModeState.configure({
stateRetentionFrames = config.stateRetentionFrames,
maxStateEntries = config.maxStateEntries,
})
end
else
-- Explicitly disable immediate mode if not requested
Gui._immediateMode = false
Gui._immediateModeState = nil
-- Configure auto frame management (defaults to false for manual control)
Gui._autoFrameManagement = config.autoFrameManagement or false
-- Configure state management
if config.stateRetentionFrames or config.maxStateEntries then
ImmediateModeState.configure({
stateRetentionFrames = config.stateRetentionFrames,
maxStateEntries = config.maxStateEntries,
})
end
end
@@ -123,6 +121,34 @@ function Gui.resize()
end
end
--- Set the rendering mode (immediate or retained)
---@param mode "immediate"|"retained" The rendering mode to use
function Gui.setMode(mode)
if mode == "immediate" then
Gui._immediateMode = true
Gui._immediateModeState = ImmediateModeState
-- Reset frame state
Gui._frameStarted = false
Gui._autoBeganFrame = false
elseif mode == "retained" then
Gui._immediateMode = false
Gui._immediateModeState = nil
-- Clear immediate mode state
Gui._frameStarted = false
Gui._autoBeganFrame = false
Gui._currentFrameElements = {}
Gui._frameNumber = 0
else
error("[FlexLove] Invalid mode: " .. tostring(mode) .. ". Expected 'immediate' or 'retained'")
end
end
--- Get the current rendering mode
---@return "immediate"|"retained"
function Gui.getMode()
return Gui._immediateMode and "immediate" or "retained"
end
--- Begin a new immediate mode frame
function Gui.beginFrame()
if not Gui._immediateMode then
@@ -136,6 +162,7 @@ function Gui.beginFrame()
-- Clear current frame elements
Gui._currentFrameElements = {}
Gui._frameStarted = true
-- Clear top elements (they will be recreated this frame)
Gui.topElements = {}
@@ -147,6 +174,16 @@ function Gui.endFrame()
return
end
-- Auto-update all top-level elements (triggers layout calculation and overflow detection)
-- This must happen BEFORE saving state so that scroll positions and overflow are calculated
for _, element in ipairs(Gui._currentFrameElements) do
-- Only update top-level elements (those without parents in the current frame)
-- Element:update() will recursively update children
if not element.parent then
element:update(0) -- dt=0 since we're not doing animation updates here
end
end
-- Save state back for all elements created this frame
for _, element in ipairs(Gui._currentFrameElements) do
if element.id and element.id ~= "" then
@@ -184,6 +221,9 @@ function Gui.endFrame()
-- Force cleanup if we have too many states
ImmediateModeState.forceCleanupIfNeeded()
StateManager.forceCleanupIfNeeded()
-- Clear frame started flag
Gui._frameStarted = false
end
-- Canvas cache for game rendering
@@ -194,6 +234,12 @@ Gui._canvasDimensions = { width = 0, height = 0 }
---@param gameDrawFunc function|nil
---@param postDrawFunc function|nil
function Gui.draw(gameDrawFunc, postDrawFunc)
-- Auto-end frame if it was auto-started in immediate mode
if Gui._immediateMode and Gui._autoBeganFrame then
Gui.endFrame()
Gui._autoBeganFrame = false
end
local outerCanvas = love.graphics.getCanvas()
local gameCanvas = nil
@@ -487,6 +533,12 @@ function Gui.new(props)
return Element.new(props)
end
-- Auto-begin frame if not manually started (convenience feature)
if not Gui._frameStarted then
Gui.beginFrame()
Gui._autoBeganFrame = true
end
-- Immediate mode: generate ID if not provided
if not props.id then
props.id = ImmediateModeState.generateID(props)

View File

@@ -31,6 +31,8 @@ local GuiState = {
_frameNumber = 0,
_currentFrameElements = {},
_immediateModeState = nil, -- Will be initialized if immediate mode is enabled
_frameStarted = false,
_autoBeganFrame = false,
}
--- Get current scale factors