fixing things here and there
This commit is contained in:
203
FlexLove.lua
203
FlexLove.lua
@@ -338,6 +338,7 @@ end
|
|||||||
---@field children table<integer, Element> -- Children of this element
|
---@field children table<integer, Element> -- Children of this element
|
||||||
---@field parent Element? -- Parent element (nil if top-level)
|
---@field parent Element? -- Parent element (nil if top-level)
|
||||||
---@field border Border -- Border configuration for the element
|
---@field border Border -- Border configuration for the element
|
||||||
|
---@field opacity number
|
||||||
---@field borderColor Color -- Color of the border
|
---@field borderColor Color -- Color of the border
|
||||||
---@field background Color -- Background color of the element
|
---@field background Color -- Background color of the element
|
||||||
---@field prevGameSize {width:number, height:number} -- Previous game size for resize calculations
|
---@field prevGameSize {width:number, height:number} -- Previous game size for resize calculations
|
||||||
@@ -370,6 +371,7 @@ Element.__index = Element
|
|||||||
---@field h number? -- Height of the element (default: calculated automatically)
|
---@field h number? -- Height of the element (default: calculated automatically)
|
||||||
---@field border Border? -- Border configuration for the element
|
---@field border Border? -- Border configuration for the element
|
||||||
---@field borderColor Color? -- Color of the border (default: black)
|
---@field borderColor Color? -- Color of the border (default: black)
|
||||||
|
---@field opacity number?
|
||||||
---@field background Color? -- Background color (default: transparent)
|
---@field background Color? -- Background color (default: transparent)
|
||||||
---@field gap number? -- Space between children elements (default: 10)
|
---@field gap number? -- Space between children elements (default: 10)
|
||||||
---@field padding {top:number?, right:number?, bottom:number?, left:number?, horizontal: number?, vertical:number?}? -- Padding around children (default: {top=0, right=0, bottom=0, left=0})
|
---@field padding {top:number?, right:number?, bottom:number?, left:number?, horizontal: number?, vertical:number?}? -- Padding around children (default: {top=0, right=0, bottom=0, left=0})
|
||||||
@@ -395,9 +397,11 @@ local ElementProps = {}
|
|||||||
---@return Element
|
---@return Element
|
||||||
function Element.new(props)
|
function Element.new(props)
|
||||||
local self = setmetatable({}, Element)
|
local self = setmetatable({}, Element)
|
||||||
self.x = props.x or 0
|
self.children = {}
|
||||||
self.y = props.y or 0
|
self.callback = props.callback
|
||||||
|
|
||||||
|
------ add non-hereditary ------
|
||||||
|
--- self drawing---
|
||||||
self.border = props.border
|
self.border = props.border
|
||||||
and {
|
and {
|
||||||
top = props.border.top or false,
|
top = props.border.top or false,
|
||||||
@@ -411,19 +415,15 @@ function Element.new(props)
|
|||||||
bottom = false,
|
bottom = false,
|
||||||
left = false,
|
left = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.background = props.background or Color.new(0, 0, 0, 0)
|
|
||||||
self.borderColor = props.borderColor or Color.new(0, 0, 0, 1)
|
self.borderColor = props.borderColor or Color.new(0, 0, 0, 1)
|
||||||
|
self.background = props.background or Color.new(0, 0, 0, 0)
|
||||||
|
self.opacity = props.opacity or 1
|
||||||
|
|
||||||
if props.textColor then
|
self.text = props.text
|
||||||
self.textColor = props.textColor
|
self.textSize = props.textSize
|
||||||
elseif props.parent then
|
self.textAlign = props.textAlign or TextAlign.START
|
||||||
self.textColor = props.parent.textColor
|
|
||||||
else
|
|
||||||
self.textColor = Color.new(0, 0, 0, 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
self.gap = props.gap or 10
|
--- self positioning ---
|
||||||
self.padding = props.padding
|
self.padding = props.padding
|
||||||
and {
|
and {
|
||||||
top = props.padding.top or props.padding.vertical or 0,
|
top = props.padding.top or props.padding.vertical or 0,
|
||||||
@@ -437,6 +437,7 @@ function Element.new(props)
|
|||||||
bottom = 0,
|
bottom = 0,
|
||||||
left = 0,
|
left = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.margin = props.margin
|
self.margin = props.margin
|
||||||
and {
|
and {
|
||||||
top = props.margin.top or props.margin.vertical or 0,
|
top = props.margin.top or props.margin.vertical or 0,
|
||||||
@@ -451,26 +452,48 @@ function Element.new(props)
|
|||||||
left = 0,
|
left = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.text = props.text
|
---- Sizing ----
|
||||||
|
local gw, gh = love.window.getMode()
|
||||||
|
self.prevGameSize = { width = gw, height = gh }
|
||||||
|
self.autosizing = { width = false, height = false }
|
||||||
|
|
||||||
self.textColor = props.textColor
|
if props.w then
|
||||||
if self.textColor == nil then
|
self.width = props.w
|
||||||
if props.parent then
|
else
|
||||||
self.textColor = props.parent.textColor
|
self.autosizing.width = true
|
||||||
else
|
self.width = self:calculateAutoWidth()
|
||||||
self.textColor = Color.new(0, 0, 0, 1)
|
end
|
||||||
end
|
if props.h then
|
||||||
|
self.height = props.h
|
||||||
|
else
|
||||||
|
self.autosizing.height = true
|
||||||
|
self.height = self:calculateAutoHeight()
|
||||||
end
|
end
|
||||||
self.textAlign = props.textAlign or TextAlign.START
|
|
||||||
self.textSize = props.textSize
|
|
||||||
|
|
||||||
self.positioning = props.positioning
|
--- child positioning ---
|
||||||
if props.positioning == nil then
|
self.gap = props.gap or 10
|
||||||
if props.parent then
|
|
||||||
self.positioning = props.parent.positioning
|
------ add hereditary ------
|
||||||
else
|
if props.parent == nil then
|
||||||
self.positioning = Positioning.ABSOLUTE
|
table.insert(Gui.topElements, self)
|
||||||
end
|
|
||||||
|
self.x = props.x or 0
|
||||||
|
self.y = props.y or 0
|
||||||
|
self.z = props.z or 0
|
||||||
|
|
||||||
|
self.textColor = props.textColor or Color.new(0, 0, 0, 1)
|
||||||
|
|
||||||
|
self.positioning = props.positioning or Positioning.ABSOLUTE
|
||||||
|
else
|
||||||
|
self.parent = props.parent
|
||||||
|
self.x = self.parent.x + (props.x or 0)
|
||||||
|
self.y = self.parent.y + (props.y or 0)
|
||||||
|
self.z = props.z or self.parent.z or 0
|
||||||
|
|
||||||
|
self.textColor = props.textColor or self.parent.textColor
|
||||||
|
self.positioning = props.positioning or self.parent.positioning
|
||||||
|
|
||||||
|
props.parent:addChild(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.positioning == Positioning.FLEX then
|
if self.positioning == Positioning.FLEX then
|
||||||
@@ -482,53 +505,10 @@ function Element.new(props)
|
|||||||
self.alignSelf = props.alignSelf or AlignSelf.AUTO
|
self.alignSelf = props.alignSelf or AlignSelf.AUTO
|
||||||
end
|
end
|
||||||
|
|
||||||
self.autosizing = { width = false, height = false }
|
---animation
|
||||||
|
|
||||||
if props.w then
|
|
||||||
self.width = props.w
|
|
||||||
else
|
|
||||||
self.autosizing.width = true
|
|
||||||
self.width = self:calculateAutoWidth()
|
|
||||||
end
|
|
||||||
|
|
||||||
if props.h then
|
|
||||||
self.height = props.h
|
|
||||||
else
|
|
||||||
self.autosizing.height = true
|
|
||||||
self.height = self:calculateAutoHeight()
|
|
||||||
end
|
|
||||||
|
|
||||||
self.parent = props.parent
|
|
||||||
if self.parent then
|
|
||||||
-- Only add parent position to child coordinates if parent is not absolutely positioned
|
|
||||||
if self.parent.positioning ~= Positioning.ABSOLUTE then
|
|
||||||
self.x = self.x + self.parent.x
|
|
||||||
self.y = self.y + self.parent.y
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self.children = {}
|
|
||||||
if props.parent then
|
|
||||||
props.parent:addChild(self)
|
|
||||||
end
|
|
||||||
local gw, gh = love.window.getMode()
|
|
||||||
|
|
||||||
self.prevGameSize = { width = gw, height = gh }
|
|
||||||
|
|
||||||
self.z = props.z or 0
|
|
||||||
|
|
||||||
-- Add transform and transition properties
|
|
||||||
self.transform = props.transform or {}
|
self.transform = props.transform or {}
|
||||||
self.transition = props.transition or {}
|
self.transition = props.transition or {}
|
||||||
|
|
||||||
-- Initialize opacity for animations to work properly
|
|
||||||
self.opacity = self.background.a
|
|
||||||
|
|
||||||
-- Store callback function for click events
|
|
||||||
self.callback = props.callback or nil
|
|
||||||
|
|
||||||
if not props.parent then
|
|
||||||
table.insert(Gui.topElements, self)
|
|
||||||
end
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -543,12 +523,14 @@ end
|
|||||||
function Element:addChild(child)
|
function Element:addChild(child)
|
||||||
child.parent = self
|
child.parent = self
|
||||||
table.insert(self.children, child)
|
table.insert(self.children, child)
|
||||||
|
|
||||||
if self.autosizing.height then
|
if self.autosizing.height then
|
||||||
self.height = self:calculateAutoHeight()
|
self.height = self:calculateAutoHeight()
|
||||||
end
|
end
|
||||||
if self.autosizing.width then
|
if self.autosizing.width then
|
||||||
self.width = self:calculateAutoWidth()
|
self.width = self:calculateAutoWidth()
|
||||||
end
|
end
|
||||||
|
|
||||||
self:layoutChildren()
|
self:layoutChildren()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -607,17 +589,19 @@ function Element:layoutChildren()
|
|||||||
-- Skip positioning for absolute children as they should maintain their own coordinates
|
-- Skip positioning for absolute children as they should maintain their own coordinates
|
||||||
goto continue
|
goto continue
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.flexDirection == FlexDirection.VERTICAL then
|
if self.flexDirection == FlexDirection.VERTICAL then
|
||||||
child.x = self.margin.left or 0
|
-- Position relative to parent origin
|
||||||
child.y = currentPos + (self.margin.top or 0)
|
child.x = self.x + (self.margin.left or 0)
|
||||||
|
child.y = self.y + currentPos
|
||||||
|
|
||||||
-- Apply alignment to vertical axis (alignItems)
|
-- Apply alignment to vertical axis (alignItems)
|
||||||
if self.alignItems == AlignItems.FLEX_START then
|
if self.alignItems == AlignItems.FLEX_START then
|
||||||
--nothing, currentPos is all
|
-- nothing
|
||||||
elseif self.alignItems == AlignItems.CENTER then
|
elseif self.alignItems == AlignItems.CENTER then
|
||||||
child.x = (self.width - (child.width or 0)) / 2
|
child.x = self.x + (self.width - (child.width or 0)) / 2
|
||||||
elseif self.alignItems == AlignItems.FLEX_END then
|
elseif self.alignItems == AlignItems.FLEX_END then
|
||||||
child.x = self.width - (child.width or 0)
|
child.x = self.x + self.width - (child.width or 0)
|
||||||
elseif self.alignItems == AlignItems.STRETCH then
|
elseif self.alignItems == AlignItems.STRETCH then
|
||||||
child.width = self.width
|
child.width = self.width
|
||||||
end
|
end
|
||||||
@@ -629,20 +613,19 @@ function Element:layoutChildren()
|
|||||||
end
|
end
|
||||||
|
|
||||||
if effectiveAlignSelf == AlignSelf.FLEX_START then
|
if effectiveAlignSelf == AlignSelf.FLEX_START then
|
||||||
-- nothing, currentPos is all - position should be at the beginning of cross axis
|
-- Position at the start of cross axis relative to parent
|
||||||
-- For VERTICAL flex, this means X = 0
|
child.x = self.x + (self.margin.left or 0)
|
||||||
child.x = 0
|
|
||||||
elseif effectiveAlignSelf == AlignSelf.CENTER then
|
elseif effectiveAlignSelf == AlignSelf.CENTER then
|
||||||
if self.flexDirection == FlexDirection.VERTICAL then
|
if self.flexDirection == FlexDirection.VERTICAL then
|
||||||
child.x = (self.width - (child.width or 0)) / 2
|
child.x = self.x + (self.width - (child.width or 0)) / 2
|
||||||
else
|
else
|
||||||
child.y = self.y + (self.height - (child.height or 0)) / 2 + self.y
|
child.y = self.y + (self.height - (child.height or 0)) / 2
|
||||||
end
|
end
|
||||||
elseif effectiveAlignSelf == AlignSelf.FLEX_END then
|
elseif effectiveAlignSelf == AlignSelf.FLEX_END then
|
||||||
if self.flexDirection == FlexDirection.VERTICAL then
|
if self.flexDirection == FlexDirection.VERTICAL then
|
||||||
child.x = self.width - (child.width or 0)
|
child.x = self.x + self.width - (child.width or 0)
|
||||||
else
|
else
|
||||||
child.y = self.height - (child.height or 0)
|
child.y = self.y + self.height - (child.height or 0)
|
||||||
end
|
end
|
||||||
elseif effectiveAlignSelf == AlignSelf.STRETCH then
|
elseif effectiveAlignSelf == AlignSelf.STRETCH then
|
||||||
if self.flexDirection == FlexDirection.VERTICAL then
|
if self.flexDirection == FlexDirection.VERTICAL then
|
||||||
@@ -660,29 +643,29 @@ function Element:layoutChildren()
|
|||||||
|
|
||||||
currentPos = currentPos + (child.height or 0) + self.gap + (self.margin.top or 0) + (self.margin.bottom or 0)
|
currentPos = currentPos + (child.height or 0) + self.gap + (self.margin.top or 0) + (self.margin.bottom or 0)
|
||||||
else
|
else
|
||||||
child.x = currentPos + (self.margin.left or 0)
|
-- Horizontal layout: position relative to parent origin
|
||||||
-- Start with margin
|
child.x = self.x + currentPos + (self.margin.left or 0)
|
||||||
child.y = self.margin.top or 0
|
child.y = self.y + (self.margin.top or 0)
|
||||||
|
|
||||||
-- Determine effective alignment - alignSelf takes precedence over alignItems
|
-- Determine effective alignment - alignSelf takes precedence over alignItems
|
||||||
local effectiveAlign = child.alignSelf
|
local effectiveAlign = child.alignSelf
|
||||||
if effectiveAlign == AlignSelf.AUTO then
|
if effectiveAlign == AlignSelf.AUTO then
|
||||||
effectiveAlign = self.alignItems
|
effectiveAlign = self.alignItems
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Apply alignment
|
-- Apply alignment
|
||||||
if effectiveAlign == AlignItems.FLEX_START then
|
if effectiveAlign == AlignItems.FLEX_START then
|
||||||
-- Keep the margin.top position
|
-- Keep the margin.top position (already applied)
|
||||||
elseif effectiveAlign == AlignItems.CENTER then
|
elseif effectiveAlign == AlignItems.CENTER then
|
||||||
child.y = (self.height - (child.height or 0)) / 2
|
child.y = self.y + (self.height - (child.height or 0)) / 2
|
||||||
elseif effectiveAlign == AlignItems.FLEX_END then
|
elseif effectiveAlign == AlignItems.FLEX_END then
|
||||||
child.y = self.height - (child.height or 0)
|
child.y = self.y + self.height - (child.height or 0)
|
||||||
elseif effectiveAlign == AlignItems.STRETCH then
|
elseif effectiveAlign == AlignItems.STRETCH then
|
||||||
-- Only set height if not already stretched
|
-- Only set height if not already stretched
|
||||||
if child.height ~= self.height then
|
if child.height ~= self.height then
|
||||||
child.height = self.height
|
child.height = self.height
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
currentPos = currentPos + (child.width or 0) + self.gap + (self.margin.left or 0) + (self.margin.right or 0)
|
currentPos = currentPos + (child.width or 0) + self.gap + (self.margin.left or 0) + (self.margin.right or 0)
|
||||||
end
|
end
|
||||||
@@ -987,6 +970,14 @@ function Element:updateText(newText, autoresize)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param newOpacity number
|
||||||
|
function Element:updateOpacity(newOpacity)
|
||||||
|
self.opacity = newOpacity
|
||||||
|
for _, child in ipairs(self.children) do
|
||||||
|
child:updateOpacity(newOpacity)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
Gui.new = Element.new
|
Gui.new = Element.new
|
||||||
Gui.Element = Element
|
Gui.Element = Element
|
||||||
Gui.Animation = Animation
|
Gui.Animation = Animation
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ function TestAbsolutePositioning:testWindowWithAbsolutePositioning()
|
|||||||
})
|
})
|
||||||
|
|
||||||
-- Verify child properties
|
-- Verify child properties
|
||||||
luaunit.assertEquals(child.x, 20)
|
luaunit.assertEquals(child.x, 120)
|
||||||
luaunit.assertEquals(child.y, 30)
|
luaunit.assertEquals(child.y, 130)
|
||||||
luaunit.assertEquals(child.width, 50)
|
luaunit.assertEquals(child.width, 50)
|
||||||
luaunit.assertEquals(child.height, 30)
|
luaunit.assertEquals(child.height, 30)
|
||||||
luaunit.assertEquals(child.positioning, enums.Positioning.ABSOLUTE)
|
luaunit.assertEquals(child.positioning, enums.Positioning.ABSOLUTE)
|
||||||
@@ -185,9 +185,8 @@ function TestAbsolutePositioning:testAbsolutePositioningWithPaddingAndMargin()
|
|||||||
text = "Test Button",
|
text = "Test Button",
|
||||||
})
|
})
|
||||||
|
|
||||||
-- Verify absolute child position is independent of padding/margin
|
luaunit.assertEquals(child.x, 30)
|
||||||
luaunit.assertEquals(child.x, 20)
|
luaunit.assertEquals(child.y, 40)
|
||||||
luaunit.assertEquals(child.y, 30)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Run the tests
|
-- Run the tests
|
||||||
|
|||||||
Reference in New Issue
Block a user