broken restrained mode - will revert
This commit is contained in:
84
FlexLove.lua
84
FlexLove.lua
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user