You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

227 lines
7.9 KiB

-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local TSM = select(2, ...) ---@type TSM
local TextureAtlas = TSM.Init("Util.TextureAtlas") ---@class Util.TextureAtlas
local Color = TSM.Include("Util.Color")
local Theme = TSM.Include("Util.Theme")
local private = {
files = {},
}
-- ============================================================================
-- Module Functions
-- ============================================================================
---Adds textures from a texture pack file.
---@param key string The key for the file
---@param info table The table describing the textures within the file
function TextureAtlas.RegisterFile(key, info)
assert(type(key) == "string" and type(info) == "table")
assert(not private.files[key])
private.files[key] = info
end
---Extracts registered file info.
---@param key string The key for the file
---@return table @The file info
function TextureAtlas.ExtractFileInfo(key)
local fileInfo, coord, colorKey, flip = private.SplitTexturePath(key)
assert(not colorKey and not flip)
return {
texture = fileInfo.path,
coord = { private.GetTexCoord(fileInfo, coord) },
}
end
---Check if a texture key is valid.
---@param key string The texture key
---@return boolean @Whether or not the key is valid
function TextureAtlas.IsValid(key)
local fileInfo, coord = private.SplitTexturePath(key)
return fileInfo and coord and true or false
end
---Gets the color key component of a texture key.
---@param key string The texture key
---@return ThemeColorKey @The color key
function TextureAtlas.GetColorKey(key)
local fileInfo, _, colorKey = private.SplitTexturePath(key)
assert(fileInfo)
return colorKey
end
---Gets the width and height of a texture.
---@param key string The texture key
---@return number @The width
---@return number @The height
function TextureAtlas.GetSize(key)
local fileInfo, coord = private.SplitTexturePath(key)
assert(fileInfo and coord)
local minX, maxX, minY, maxY = unpack(coord)
local width = (maxX - minX) / fileInfo.scale
local height = (maxY - minY) / fileInfo.scale
return width, height
end
---Gets the width of a texture.
---@param key string The texture key
---@return number @The width
function TextureAtlas.GetWidth(key)
local width = TextureAtlas.GetSize(key)
return width
end
---Gets the height of a texture.
---@param key string The texture key
---@return number @The height
function TextureAtlas.GetHeight(key)
local _, height = TextureAtlas.GetSize(key)
return height
end
---Sets the visible texture of a texture widget.
---@param texture Texture The texture widget
---@param key string The texture key
function TextureAtlas.SetTexture(texture, key)
local fileInfo, coord, colorKey, flip = private.SplitTexturePath(key)
texture:SetTexture(fileInfo.path)
texture:SetTexCoord(private.GetTexCoord(fileInfo, coord, flip))
if colorKey then
texture:SetVertexColor(Theme.GetColor(colorKey):GetFractionalRGBA())
else
texture:SetVertexColor(1, 1, 1, 1)
end
end
---Sets the size of a texture widget to match a texture key.
---@param texture Texture The texture widget
---@param key string The texture key
function TextureAtlas.SetSize(texture, key)
local width, height = TextureAtlas.GetSize(key)
texture:SetWidth(width)
texture:SetHeight(height)
end
---Sets the widget of a texture widget to match a texture key.
---@param texture Texture The texture widget
---@param key string The texture key
function TextureAtlas.SetWidth(texture, key)
texture:SetWidth(TextureAtlas.GetWidth(key))
end
---Sets the height of a texture widget to match a texture key.
---@param texture Texture The texture widget
---@param key string The texture key
function TextureAtlas.SetHeight(texture, key)
texture:SetHeight(TextureAtlas.GetHeight(key))
end
---Sets the visible texture and width of a texture widget to match a texture key.
---@param texture Texture The texture widget
---@param key string The texture key
function TextureAtlas.SetTextureAndWidth(texture, key)
TextureAtlas.SetTexture(texture, key)
TextureAtlas.SetWidth(texture, key)
end
---Sets the visible texture and height of a texture widget to match a texture key.
---@param texture Texture The texture widget
---@param key string The texture key
function TextureAtlas.SetTextureAndHeight(texture, key)
TextureAtlas.SetTexture(texture, key)
TextureAtlas.SetHeight(texture, key)
end
---Sets the visible texture and size of a texture widget to match a texture key.
---@param texture Texture The texture widget
---@param key string The texture key
function TextureAtlas.SetTextureAndSize(texture, key)
TextureAtlas.SetTexture(texture, key)
TextureAtlas.SetSize(texture, key)
end
---Gets a UI escape code sequence for a texture.
---@param key string The texture key
---@return string @The escape code sequence
function TextureAtlas.GetTextureLink(key)
local width, height = TextureAtlas.GetSize(key)
local fileInfo, coord, colorKey, flip = private.SplitTexturePath(key)
assert(fileInfo and coord)
local minX, maxX, minY, maxY = private.GetTexCoord(fileInfo, coord, flip, true)
local r, g, b, a = 255, 255, 255, 255
if colorKey then
r, g, b, a = Theme.GetColor(colorKey):GetRGBA()
end
assert(a == 255)
return "|T"..strjoin(":", fileInfo.path, width, height, 0, 0, fileInfo.width, fileInfo.height, minX, maxX, minY, maxY, r, g, b).."|t"
end
---Creates a colored texture key.
---@param key string The texture key to add the color to
---@param colorKey ThemeColorKey The theme color key
---@return string @The escape code sequence
function TextureAtlas.GetColoredKey(key, colorKey)
local fileInfo, _, existingColor = private.SplitTexturePath(key)
assert(fileInfo and not existingColor)
local color = Theme.GetColor(colorKey)
assert(color and not color:Equals(Color.GetTransparent()))
return key.."#"..colorKey
end
---Crestes a vertically flipped texture key.
---@param key string The texture key to flip
---@return string @The flipped texture key
function TextureAtlas.GetFlippedVerticallyKey(key)
local fileInfo, _, existingColor, existingMirror = private.SplitTexturePath(key)
assert(fileInfo and not existingColor and not existingMirror)
return key.."@v"
end
---Crestes a horizontally flipped texture key.
---@param key string The texture key to flip
---@return string @The flipped texture key
function TextureAtlas.GetFlippedHorizontallyKey(key)
local fileInfo, _, existingColor, existingMirror = private.SplitTexturePath(key)
assert(fileInfo and not existingColor and not existingMirror)
return key.."@h"
end
-- ============================================================================
-- Private Helper Functions
-- ============================================================================
function private.SplitTexturePath(key)
local file, entry, colorKey, flip, colorKey2 = strmatch(key, "^([^%.]+)%.([^#@]+)(#?[0-9a-fA-Z_%+%-]*)@?([hv]?)(#?[0-9a-fA-Z_%+%-]*)$")
colorKey = (colorKey ~= "" and colorKey) or (colorKey2 ~= "" and colorKey2) or nil
flip = flip ~= "" and flip or nil
local fileInfo = file and private.files[file]
-- remove the leading '#' from theme color keys
colorKey = colorKey and strsub(colorKey, 2) or nil
return fileInfo, fileInfo and fileInfo.coord[entry], colorKey, flip
end
function private.GetTexCoord(fileInfo, coord, flip, nonNormalized)
local minX, maxX, minY, maxY = unpack(coord)
if flip == "h" then
minX, maxX = maxX, minX
elseif flip == "v" then
minY, maxY = maxY, minY
elseif flip then
error("Invalid flip direction: "..tostring(flip))
end
if not nonNormalized then
minX = minX / fileInfo.width
maxX = maxX / fileInfo.width
minY = minY / fileInfo.height
maxY = maxY / fileInfo.height
end
return minX, maxX, minY, maxY
end