TradeSkillMaster/LibTSM/Util/NineSlice.lua

216 lines
5.7 KiB
Lua
Raw Permalink Normal View History

2020-11-13 14:13:12 -05:00
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
--- NineSlice Functions.
-- @module NineSlice
local _, TSM = ...
local NineSlice = TSM.Init("Util.NineSlice")
local private = {
styles = {},
context = {},
}
local PART_INFO = {
topLeft = {
points = {
{ "TOPLEFT" },
},
},
bottomLeft = {
points = {
{ "BOTTOMLEFT" },
},
},
topRight = {
points = {
{ "TOPRIGHT" },
},
},
bottomRight = {
points = {
{ "BOTTOMRIGHT" },
},
},
left = {
points = {
{ "TOPLEFT", "topLeft", "BOTTOMLEFT" },
{ "BOTTOMLEFT", "bottomLeft", "TOPLEFT" },
},
},
right = {
points = {
{ "TOPRIGHT", "topRight", "BOTTOMRIGHT" },
{ "BOTTOMRIGHT", "bottomRight", "TOPRIGHT" },
},
},
top = {
points = {
{ "TOPLEFT", "topLeft", "TOPRIGHT" },
{ "TOPRIGHT", "topRight", "TOPLEFT" },
},
},
bottom = {
points = {
{ "BOTTOMLEFT", "bottomLeft", "BOTTOMRIGHT" },
{ "BOTTOMRIGHT", "bottomRight", "BOTTOMLEFT" },
},
},
center = {
points = {
{ "TOPLEFT", "topLeft", "BOTTOMRIGHT" },
{ "BOTTOMRIGHT", "bottomRight", "TOPLEFT" },
},
},
}
-- ============================================================================
-- Metatable
-- ============================================================================
local NINE_SLICE_MT = {
__index = {
Hide = function(self)
local context = private.context[self]
for _, texture in pairs(context.parts) do
texture:Hide()
end
end,
SetStyle = function(self, key, inset)
local context = private.context[self]
local style = private.styles[key]
for part, texture in pairs(context.parts) do
local partStyle = style[part]
if partStyle then
texture:Show()
else
texture:Hide()
end
end
if context.styleKey == key and context.inset == inset then
return
end
context.styleKey = key
context.inset = inset
for part, texture in pairs(context.parts) do
local partStyle = style[part]
if partStyle then
texture:ClearAllPoints()
for i, point in ipairs(PART_INFO[part].points) do
local anchor, relFrame, relAnchor, xOff, yOff = nil, nil, nil, 0, 0
if partStyle.offset then
xOff, yOff = unpack(partStyle.offset[i])
end
if #point == 1 then
anchor = unpack(point)
elseif #point == 3 then
anchor, relFrame, relAnchor = unpack(point)
relFrame = context.parts[relFrame]
assert(relFrame)
else
error("Invalid point")
end
if relFrame then
texture:SetPoint(anchor, relFrame, relAnchor, xOff, yOff)
else
if inset and xOff == 0 and strmatch(anchor, "LEFT") then
xOff = inset
elseif inset and xOff == 0 and strmatch(anchor, "RIGHT") then
xOff = -inset
end
if inset and yOff == 0 and strmatch(anchor, "TOP") then
yOff = -inset
elseif inset and yOff == 0 and strmatch(anchor, "BOTTOM") then
yOff = inset
end
texture:SetPoint(anchor, xOff, yOff)
end
end
texture:SetSize(partStyle.width, partStyle.height)
texture:SetTexture(partStyle.texture)
texture:SetTexCoord(unpack(partStyle.coord))
end
end
end,
SetVertexColor = function(self, r, g, b, a)
for part in pairs(PART_INFO) do
self:SetPartVertexColor(part, r, g, b, a)
end
end,
SetPartVertexColor = function(self, part, r, g, b, a)
local context = private.context[self]
context.parts[part]:SetVertexColor(r, g, b, a)
end,
},
__newindex = function(self, key, value) error("NineSlice cannot be modified") end,
__tostring = function(self) return "NineSlice:"..strmatch(tostring(private.context[self]), "table:[^0-9a-fA-F]*([0-9a-fA-F]+)") end,
__metatable = false,
}
-- ============================================================================
-- Module Functions
-- ============================================================================
--- Registers a nine-slice style.
-- @tparam string key The style key
-- @tparam table info The style info table
function NineSlice.RegisterStyle(key, info)
assert(not private.styles[key])
private.styles[key] = info
for part in pairs(PART_INFO) do
-- allowed to be missing the center part
if part ~= "center" or info[part] ~= nil then
assert(type(info[part].texture) == "string")
assert(#info[part].coord == 4)
assert(info[part].width > 0)
assert(info[part].height > 0)
end
end
end
--- Create an nine-slice object.
-- @tparam table frame The parent frame
-- @tparam[opt=0] number subLayer The texture subLayer
-- @treturn NineSlice The nine-slice object
function NineSlice.New(frame, subLayer)
local obj = setmetatable({}, NINE_SLICE_MT)
local context = {
frame = frame,
parts = {},
styleKey = nil,
inset = nil,
}
private.context[obj] = context
-- create all the textures
for part in pairs(PART_INFO) do
local texture = frame:CreateTexture(nil, "BACKGROUND", nil, subLayer or 0)
texture:SetBlendMode("BLEND")
context.parts[part] = texture
end
-- set the points for all the textures
for part, info in pairs(PART_INFO) do
for _, point in ipairs(info.points) do
if #point == 1 then
context.parts[part]:SetPoint(unpack(point))
elseif #point == 3 then
local anchor, relFrame, relAnchor = unpack(point)
relFrame = context.parts[relFrame]
assert(relFrame)
context.parts[part]:SetPoint(anchor, relFrame, relAnchor)
else
error("Invalid point")
end
end
end
return obj
end