feat: add customDraw callback support to Element
- Add customDraw property to Element.new() for custom rendering callbacks - Add getComputedBox() method to access element's content area position/size - Call customDraw in Element:draw() between text and children (Layer 4.5) - Graphics state isolated with push/pop and color reset - Enables rendering custom content (e.g. game objects) within UI elements
This commit is contained in:
@@ -355,6 +355,8 @@ function Element.new(props)
|
|||||||
self.onEnter = props.onEnter
|
self.onEnter = props.onEnter
|
||||||
self.onEnterDeferred = props.onEnterDeferred or false
|
self.onEnterDeferred = props.onEnterDeferred or false
|
||||||
|
|
||||||
|
self.customDraw = props.customDraw -- Custom rendering callback
|
||||||
|
|
||||||
-- Initialize state manager ID for immediate mode (use self.id which may be auto-generated)
|
-- Initialize state manager ID for immediate mode (use self.id which may be auto-generated)
|
||||||
self._stateId = self.id
|
self._stateId = self.id
|
||||||
|
|
||||||
@@ -1313,10 +1315,18 @@ function Element.new(props)
|
|||||||
-- Warn if CSS positioning properties are used without absolute positioning
|
-- Warn if CSS positioning properties are used without absolute positioning
|
||||||
if (props.top or props.bottom or props.left or props.right) and not self._explicitlyAbsolute then
|
if (props.top or props.bottom or props.left or props.right) and not self._explicitlyAbsolute then
|
||||||
local properties = {}
|
local properties = {}
|
||||||
if props.top then table.insert(properties, "top") end
|
if props.top then
|
||||||
if props.bottom then table.insert(properties, "bottom") end
|
table.insert(properties, "top")
|
||||||
if props.left then table.insert(properties, "left") end
|
end
|
||||||
if props.right then table.insert(properties, "right") end
|
if props.bottom then
|
||||||
|
table.insert(properties, "bottom")
|
||||||
|
end
|
||||||
|
if props.left then
|
||||||
|
table.insert(properties, "left")
|
||||||
|
end
|
||||||
|
if props.right then
|
||||||
|
table.insert(properties, "right")
|
||||||
|
end
|
||||||
Element._ErrorHandler:warn("Element", "LAY_011", {
|
Element._ErrorHandler:warn("Element", "LAY_011", {
|
||||||
element = self.id or "unnamed",
|
element = self.id or "unnamed",
|
||||||
positioning = self._originalPositioning or "relative",
|
positioning = self._originalPositioning or "relative",
|
||||||
@@ -1500,7 +1510,7 @@ function Element.new(props)
|
|||||||
|
|
||||||
-- Warn if explicit x/y is set on a child that will be positioned by flex layout
|
-- Warn if explicit x/y is set on a child that will be positioned by flex layout
|
||||||
-- This position will be overridden unless the child has positioning="absolute"
|
-- This position will be overridden unless the child has positioning="absolute"
|
||||||
local parentWillUseFlex = self.parent.positioning ~= "grid"
|
local parentWillUseFlex = self.parent.positioning ~= "grid"
|
||||||
local childIsRelative = self.positioning ~= "absolute" or not self._explicitlyAbsolute
|
local childIsRelative = self.positioning ~= "absolute" or not self._explicitlyAbsolute
|
||||||
if parentWillUseFlex and childIsRelative and (props.x or props.y) then
|
if parentWillUseFlex and childIsRelative and (props.x or props.y) then
|
||||||
Element._ErrorHandler:warn("Element", "LAY_008", {
|
Element._ErrorHandler:warn("Element", "LAY_008", {
|
||||||
@@ -1583,10 +1593,18 @@ function Element.new(props)
|
|||||||
-- Warn if CSS positioning properties are used without absolute positioning
|
-- Warn if CSS positioning properties are used without absolute positioning
|
||||||
if (props.top or props.bottom or props.left or props.right) and not self._explicitlyAbsolute then
|
if (props.top or props.bottom or props.left or props.right) and not self._explicitlyAbsolute then
|
||||||
local properties = {}
|
local properties = {}
|
||||||
if props.top then table.insert(properties, "top") end
|
if props.top then
|
||||||
if props.bottom then table.insert(properties, "bottom") end
|
table.insert(properties, "top")
|
||||||
if props.left then table.insert(properties, "left") end
|
end
|
||||||
if props.right then table.insert(properties, "right") end
|
if props.bottom then
|
||||||
|
table.insert(properties, "bottom")
|
||||||
|
end
|
||||||
|
if props.left then
|
||||||
|
table.insert(properties, "left")
|
||||||
|
end
|
||||||
|
if props.right then
|
||||||
|
table.insert(properties, "right")
|
||||||
|
end
|
||||||
Element._ErrorHandler:warn("Element", "LAY_011", {
|
Element._ErrorHandler:warn("Element", "LAY_011", {
|
||||||
element = self.id or "unnamed",
|
element = self.id or "unnamed",
|
||||||
positioning = self._originalPositioning or "relative",
|
positioning = self._originalPositioning or "relative",
|
||||||
@@ -1937,6 +1955,18 @@ function Element:getBorderBoxHeight()
|
|||||||
return self._borderBoxHeight or (self.height + self.padding.top + self.padding.bottom)
|
return self._borderBoxHeight or (self.height + self.padding.top + self.padding.bottom)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get computed box dimensions (content area position and size)
|
||||||
|
--- Returns the position and size of the content area (inside padding)
|
||||||
|
---@return {x: number, y: number, width: number, height: number}
|
||||||
|
function Element:getComputedBox()
|
||||||
|
return {
|
||||||
|
x = self.x + self.padding.left,
|
||||||
|
y = self.y + self.padding.top,
|
||||||
|
width = self.width,
|
||||||
|
height = self.height,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
--- Mark this element and its ancestors as dirty, requiring layout recalculation
|
--- Mark this element and its ancestors as dirty, requiring layout recalculation
|
||||||
--- Call this when element properties change that affect layout
|
--- Call this when element properties change that affect layout
|
||||||
function Element:invalidateLayout()
|
function Element:invalidateLayout()
|
||||||
@@ -2477,6 +2507,14 @@ function Element:draw(backdropCanvas)
|
|||||||
-- LAYER 4: Delegate text rendering (text, cursor, selection, placeholder, password masking) to Renderer module
|
-- LAYER 4: Delegate text rendering (text, cursor, selection, placeholder, password masking) to Renderer module
|
||||||
self._renderer:drawText(self)
|
self._renderer:drawText(self)
|
||||||
|
|
||||||
|
-- LAYER 4.5: Custom draw callback (if provided)
|
||||||
|
if self.customDraw then
|
||||||
|
love.graphics.push()
|
||||||
|
love.graphics.setColor(1, 1, 1, 1) -- Reset color to white
|
||||||
|
self.customDraw(self)
|
||||||
|
love.graphics.pop()
|
||||||
|
end
|
||||||
|
|
||||||
-- Draw visual feedback when element is pressed (if it has an onEvent handler and highlight is not disabled)
|
-- Draw visual feedback when element is pressed (if it has an onEvent handler and highlight is not disabled)
|
||||||
if self.onEvent and not self.disableHighlight and self._eventHandler then
|
if self.onEvent and not self.disableHighlight and self._eventHandler then
|
||||||
-- Check if any button is pressed
|
-- Check if any button is pressed
|
||||||
|
|||||||
Reference in New Issue
Block a user