renamed module directory
This commit is contained in:
180
modules/Units.lua
Normal file
180
modules/Units.lua
Normal file
@@ -0,0 +1,180 @@
|
||||
-- ====================
|
||||
-- Units System
|
||||
-- ====================
|
||||
|
||||
--- Unit parsing and viewport calculations
|
||||
local Units = {}
|
||||
|
||||
--- Parse a unit value (string or number) into value and unit type
|
||||
---@param value string|number
|
||||
---@return number, string -- Returns numeric value and unit type ("px", "%", "vw", "vh")
|
||||
function Units.parse(value)
|
||||
if type(value) == "number" then
|
||||
return value, "px"
|
||||
end
|
||||
|
||||
if type(value) ~= "string" then
|
||||
-- Fallback to 0px for invalid types
|
||||
return 0, "px"
|
||||
end
|
||||
|
||||
-- Match number followed by optional unit
|
||||
local numStr, unit = value:match("^([%-]?[%d%.]+)(.*)$")
|
||||
if not numStr then
|
||||
-- Fallback to 0px for invalid format
|
||||
return 0, "px"
|
||||
end
|
||||
|
||||
local num = tonumber(numStr)
|
||||
if not num then
|
||||
-- Fallback to 0px for invalid numeric value
|
||||
return 0, "px"
|
||||
end
|
||||
|
||||
-- Default to pixels if no unit specified
|
||||
if unit == "" then
|
||||
unit = "px"
|
||||
end
|
||||
|
||||
local validUnits = { px = true, ["%"] = true, vw = true, vh = true, ew = true, eh = true }
|
||||
if not validUnits[unit] then
|
||||
return num, "px"
|
||||
end
|
||||
|
||||
return num, unit
|
||||
end
|
||||
|
||||
--- Convert relative units to pixels based on viewport and parent dimensions
|
||||
---@param value number -- Numeric value to convert
|
||||
---@param unit string -- Unit type ("px", "%", "vw", "vh", "ew", "eh")
|
||||
---@param viewportWidth number -- Current viewport width in pixels
|
||||
---@param viewportHeight number -- Current viewport height in pixels
|
||||
---@param parentSize number? -- Required for percentage units (parent dimension)
|
||||
---@return number -- Resolved pixel value
|
||||
---@throws Error if unit type is unknown or percentage used without parent size
|
||||
function Units.resolve(value, unit, viewportWidth, viewportHeight, parentSize)
|
||||
if unit == "px" then
|
||||
return value
|
||||
elseif unit == "%" then
|
||||
if not parentSize then
|
||||
error(formatError("Units", "Percentage units require parent dimension"))
|
||||
end
|
||||
return (value / 100) * parentSize
|
||||
elseif unit == "vw" then
|
||||
return (value / 100) * viewportWidth
|
||||
elseif unit == "vh" then
|
||||
return (value / 100) * viewportHeight
|
||||
else
|
||||
error(formatError("Units", string.format("Unknown unit type: '%s'. Valid units: px, %%, vw, vh, ew, eh", unit)))
|
||||
end
|
||||
end
|
||||
|
||||
---@return number, number -- width, height
|
||||
function Units.getViewport()
|
||||
-- Return cached viewport if available (only during resize operations)
|
||||
if Gui and Gui._cachedViewport and Gui._cachedViewport.width > 0 then
|
||||
return Gui._cachedViewport.width, Gui._cachedViewport.height
|
||||
end
|
||||
|
||||
-- Query viewport dimensions normally
|
||||
if love.graphics and love.graphics.getDimensions then
|
||||
return love.graphics.getDimensions()
|
||||
else
|
||||
local w, h = love.window.getMode()
|
||||
return w, h
|
||||
end
|
||||
end
|
||||
|
||||
--- Apply base scaling to a value
|
||||
---@param value number
|
||||
---@param axis "x"|"y" -- Which axis to scale on
|
||||
---@param scaleFactors {x:number, y:number}
|
||||
---@return number
|
||||
function Units.applyBaseScale(value, axis, scaleFactors)
|
||||
if axis == "x" then
|
||||
return value * scaleFactors.x
|
||||
else
|
||||
return value * scaleFactors.y
|
||||
end
|
||||
end
|
||||
|
||||
--- Resolve units for spacing properties (padding, margin)
|
||||
---@param spacingProps table?
|
||||
---@param parentWidth number
|
||||
---@param parentHeight number
|
||||
---@return table -- Resolved spacing with top, right, bottom, left in pixels
|
||||
function Units.resolveSpacing(spacingProps, parentWidth, parentHeight)
|
||||
if not spacingProps then
|
||||
return { top = 0, right = 0, bottom = 0, left = 0 }
|
||||
end
|
||||
|
||||
local viewportWidth, viewportHeight = Units.getViewport()
|
||||
local result = {}
|
||||
|
||||
-- Handle shorthand properties first
|
||||
local vertical = spacingProps.vertical
|
||||
local horizontal = spacingProps.horizontal
|
||||
|
||||
if vertical then
|
||||
if type(vertical) == "string" then
|
||||
local value, unit = Units.parse(vertical)
|
||||
vertical = Units.resolve(value, unit, viewportWidth, viewportHeight, parentHeight)
|
||||
end
|
||||
end
|
||||
|
||||
if horizontal then
|
||||
if type(horizontal) == "string" then
|
||||
local value, unit = Units.parse(horizontal)
|
||||
horizontal = Units.resolve(value, unit, viewportWidth, viewportHeight, parentWidth)
|
||||
end
|
||||
end
|
||||
|
||||
-- Handle individual sides
|
||||
for _, side in ipairs({ "top", "right", "bottom", "left" }) do
|
||||
local value = spacingProps[side]
|
||||
if value then
|
||||
if type(value) == "string" then
|
||||
local numValue, unit = Units.parse(value)
|
||||
local parentSize = (side == "top" or side == "bottom") and parentHeight or parentWidth
|
||||
result[side] = Units.resolve(numValue, unit, viewportWidth, viewportHeight, parentSize)
|
||||
else
|
||||
result[side] = value
|
||||
end
|
||||
else
|
||||
-- Use fallbacks
|
||||
if side == "top" or side == "bottom" then
|
||||
result[side] = vertical or 0
|
||||
else
|
||||
result[side] = horizontal or 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
--- Check if a unit string is valid
|
||||
---@param unitStr string -- Unit string to validate (e.g., "10px", "50%", "20vw")
|
||||
---@return boolean -- Returns true if unit string is valid
|
||||
function Units.isValid(unitStr)
|
||||
if type(unitStr) ~= "string" then
|
||||
return false
|
||||
end
|
||||
|
||||
local _, unit = Units.parse(unitStr)
|
||||
local validUnits = { px = true, ["%"] = true, vw = true, vh = true, ew = true, eh = true }
|
||||
return validUnits[unit] == true
|
||||
end
|
||||
|
||||
--- Parse and resolve a unit value in one call
|
||||
---@param value string|number -- Value to parse and resolve
|
||||
---@param viewportWidth number -- Current viewport width
|
||||
---@param viewportHeight number -- Current viewport height
|
||||
---@param parentSize number? -- Parent dimension for percentage units
|
||||
---@return number -- Resolved pixel value
|
||||
function Units.parseAndResolve(value, viewportWidth, viewportHeight, parentSize)
|
||||
local numValue, unit = Units.parse(value)
|
||||
return Units.resolve(numValue, unit, viewportWidth, viewportHeight, parentSize)
|
||||
end
|
||||
|
||||
return Units
|
||||
Reference in New Issue
Block a user