5842eb7a2b
Traduction - Identifiants en anglais dans tout le module : addon, ecrans d'accueil, outils Python, banc d'essai et patcheur C#. - Fichiers au nom francais renommes (Gabarits.lua -> Templates.lua, Textes_*.lua -> Texts_*.lua, deployer.py -> deploy.py, tools/patcheur -> tools/patcher, etc.). - Commandes /fui et options de deploy.py en anglais (--check, --server, --remove-dbc). - Cles des variables sauvegardees et de data/dbc/statistics.json traduites, sans reprise des anciennes cles. - API de la micro-barre : ForeverUI.AddMicroButton(def) avec les champs name, atlasSet, after, tooltip, onClick, ready, et ForeverUI.UpdateMicro(name, isOpen). - Commentaires reecrits en anglais, courts, sans dates ni historique ; les fonctions au nom peu parlant et leurs parametres sont expliques. Code mort - Exports, fonctions et variables jamais lus retires. - Retires a la demande des modules : ForeverUI.PvPJauge, les exports FondEntete / TuilerEntete / Polices de TradeSkill, l'art legacy-up-c60, honorfill(half)blue et inv_misc_book_09, leurs entrees d'atlas et les parties d'outils correspondantes. Verifications : liaisons des noms comparees avant et apres, banc vert, chemins de textures inchanges, generateurs reproduisant les fichiers, patcheur identique octet pour octet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
635 lines
23 KiB
Lua
635 lines
23 KiB
Lua
-- ForeverUI: drawing parts of atlas sheets.
|
|
-- A sheet stays one texture: only the rectangle read from it moves. A partial fill
|
|
-- (health bar at 40 %) crops that rectangle instead of stretching the image, which would
|
|
-- distort the art.
|
|
|
|
ForeverUI = ForeverUI or {}
|
|
|
|
-- Atlas entry { file, left, right, top, bottom, width, height }, or nil if unknown.
|
|
local function entry(name)
|
|
if not UIAtlas or not UIAtlas.data then
|
|
return nil
|
|
end
|
|
return UIAtlas.data[name]
|
|
end
|
|
|
|
ForeverUI.AtlasEntry = entry
|
|
|
|
-- Sets a texture to an atlas element. keepSize keeps the current size (when the frame
|
|
-- sets its own dimensions).
|
|
function ForeverUI.SetAtlas(texture, name, keepSize)
|
|
local e = entry(name)
|
|
if not e then
|
|
return false
|
|
end
|
|
|
|
texture:SetTexture(e[1])
|
|
texture:SetTexCoord(e[2], e[3], e[4], e[5])
|
|
|
|
if not keepSize then
|
|
texture:SetWidth(e[6])
|
|
texture:SetHeight(e[7])
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
-- Left-to-right fill: the rectangle is cropped to the fraction. fullWidth: width at 100 %.
|
|
-- The client rejects a zero width, so the texture is hidden instead.
|
|
function ForeverUI.SetAtlasFill(texture, name, fraction, fullWidth)
|
|
local e = entry(name)
|
|
if not e then
|
|
texture:Hide()
|
|
return false
|
|
end
|
|
|
|
if not fraction or fraction ~= fraction or fraction < 0 then
|
|
fraction = 0
|
|
elseif fraction > 1 then
|
|
fraction = 1
|
|
end
|
|
|
|
local width = (fullWidth or e[6]) * fraction
|
|
if width < 1 then
|
|
texture:Hide()
|
|
return true
|
|
end
|
|
|
|
texture:SetTexture(e[1])
|
|
texture:SetTexCoord(e[2], e[2] + (e[3] - e[2]) * fraction, e[4], e[5])
|
|
texture:SetWidth(width)
|
|
texture:SetHeight(e[7])
|
|
texture:Show()
|
|
return true
|
|
end
|
|
|
|
-- Nine-slice cut of one atlas element.
|
|
-- mainline/MainActionBar.xml, camelot/MainMenuBarBagButtons.xml and MainMenuBarMicroMenu.xml
|
|
-- all frame their group with UI-HUD-ActionBar-Frame (TOPLEFT -6, 6; BOTTOMRIGHT 4, -5):
|
|
-- a 55 x 55 octagon (110 x 110 on a 2x sheet) with a bronze edge. The modern client
|
|
-- nine-slices it; stretched in one piece over 560 px, its bevels would become ramps.
|
|
-- options.name: atlas element; options.layer: draw layer (BACKGROUND by default);
|
|
-- options.imageMargin: corner size in the image, px; options.imageSize: image side, px;
|
|
-- options.margin: corner size on screen, px.
|
|
function ForeverUI.SetAtlasNineSlice(parent, options)
|
|
local e = entry(options.name)
|
|
if not e then
|
|
return nil
|
|
end
|
|
|
|
local layer = options.layer or "BACKGROUND"
|
|
local margin = options.margin
|
|
local fraction = options.imageMargin / options.imageSize
|
|
local du = (e[3] - e[2]) * fraction
|
|
local dv = (e[5] - e[4]) * fraction
|
|
local u = { e[2], e[2] + du, e[3] - du, e[3] }
|
|
local v = { e[4], e[4] + dv, e[5] - dv, e[5] }
|
|
|
|
local function piece(cu1, cu2, cv1, cv2)
|
|
local t = parent:CreateTexture(nil, layer)
|
|
t:SetTexture(e[1])
|
|
t:SetTexCoord(u[cu1], u[cu2], v[cv1], v[cv2])
|
|
return t
|
|
end
|
|
|
|
local p = {}
|
|
|
|
p.topLeftCorner = piece(1, 2, 1, 2)
|
|
p.topLeftCorner:SetWidth(margin)
|
|
p.topLeftCorner:SetHeight(margin)
|
|
p.topLeftCorner:SetPoint("TOPLEFT", parent, "TOPLEFT")
|
|
|
|
p.topRightCorner = piece(3, 4, 1, 2)
|
|
p.topRightCorner:SetWidth(margin)
|
|
p.topRightCorner:SetHeight(margin)
|
|
p.topRightCorner:SetPoint("TOPRIGHT", parent, "TOPRIGHT")
|
|
|
|
p.bottomLeftCorner = piece(1, 2, 3, 4)
|
|
p.bottomLeftCorner:SetWidth(margin)
|
|
p.bottomLeftCorner:SetHeight(margin)
|
|
p.bottomLeftCorner:SetPoint("BOTTOMLEFT", parent, "BOTTOMLEFT")
|
|
|
|
p.bottomRightCorner = piece(3, 4, 3, 4)
|
|
p.bottomRightCorner:SetWidth(margin)
|
|
p.bottomRightCorner:SetHeight(margin)
|
|
p.bottomRightCorner:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT")
|
|
|
|
-- Edges and center are set by two opposite corners: no size to compute.
|
|
p.topEdge = piece(2, 3, 1, 2)
|
|
p.topEdge:SetPoint("TOPLEFT", p.topLeftCorner, "TOPRIGHT")
|
|
p.topEdge:SetPoint("BOTTOMRIGHT", p.topRightCorner, "BOTTOMLEFT")
|
|
|
|
p.bottomEdge = piece(2, 3, 3, 4)
|
|
p.bottomEdge:SetPoint("TOPLEFT", p.bottomLeftCorner, "TOPRIGHT")
|
|
p.bottomEdge:SetPoint("BOTTOMRIGHT", p.bottomRightCorner, "BOTTOMLEFT")
|
|
|
|
p.leftEdge = piece(1, 2, 2, 3)
|
|
p.leftEdge:SetPoint("TOPLEFT", p.topLeftCorner, "BOTTOMLEFT")
|
|
p.leftEdge:SetPoint("BOTTOMRIGHT", p.bottomLeftCorner, "TOPRIGHT")
|
|
|
|
p.rightEdge = piece(3, 4, 2, 3)
|
|
p.rightEdge:SetPoint("TOPLEFT", p.topRightCorner, "BOTTOMLEFT")
|
|
p.rightEdge:SetPoint("BOTTOMRIGHT", p.bottomRightCorner, "TOPRIGHT")
|
|
|
|
p.center = piece(2, 3, 2, 3)
|
|
p.center:SetPoint("TOPLEFT", p.topLeftCorner, "BOTTOMRIGHT")
|
|
p.center:SetPoint("BOTTOMRIGHT", p.bottomRightCorner, "TOPLEFT")
|
|
|
|
return p
|
|
end
|
|
|
|
-- Frame art shared by the three groups at the bottom of the screen.
|
|
-- The corner must hold the whole bevel: the image's top and left profiles only become
|
|
-- constant from pixel 19 of 110. A smaller cut stretches part of the diagonal along the
|
|
-- bar. So 20 (one pixel of margin), which is 10 px on screen on this 2x sheet.
|
|
function ForeverUI.SetBarFrameArt(frame, layer)
|
|
return ForeverUI.SetAtlasNineSlice(frame, {
|
|
name = "ui-hud-actionbar-frame",
|
|
layer = layer or "BACKGROUND",
|
|
imageMargin = 20,
|
|
imageSize = 110,
|
|
margin = 10,
|
|
})
|
|
end
|
|
|
|
-- Divider between two slots. mainline/MainActionBar.xml HorizontalDividerTemplate: 12 wide,
|
|
-- three vertical slices of ui-hud-actionbar-frame-divider. Heights 14 top, 16 center,
|
|
-- 15 bottom fit a 45 button.
|
|
function ForeverUI.CreateDivider(parent, level)
|
|
local frame = CreateFrame("Frame", nil, parent)
|
|
frame:SetWidth(12)
|
|
frame:SetFrameLevel(level or parent:GetFrameLevel())
|
|
|
|
local top = frame:CreateTexture(nil, "ARTWORK")
|
|
if not ForeverUI.SetAtlas(top, "ui-hud-actionbar-frame-divider-threeslice-edgetop", true) then
|
|
frame:Hide()
|
|
return frame
|
|
end
|
|
top:SetHeight(14)
|
|
top:SetPoint("TOPLEFT", frame, "TOPLEFT")
|
|
top:SetPoint("TOPRIGHT", frame, "TOPRIGHT")
|
|
|
|
local down = frame:CreateTexture(nil, "ARTWORK")
|
|
ForeverUI.SetAtlas(down, "ui-hud-actionbar-frame-divider-threeslice-edgebottom", true)
|
|
down:SetHeight(15)
|
|
down:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT")
|
|
down:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT")
|
|
|
|
local center = frame:CreateTexture(nil, "ARTWORK")
|
|
ForeverUI.SetAtlas(center, "!ui-hud-actionbar-frame-divider-threeslice-center", true)
|
|
center:SetPoint("TOPLEFT", top, "BOTTOMLEFT")
|
|
center:SetPoint("BOTTOMRIGHT", down, "TOPRIGHT")
|
|
|
|
frame.top, frame.center, frame.down = top, center, down
|
|
return frame
|
|
end
|
|
|
|
-- Panel art: mainline/SharedUIPanelTemplates.xml PortraitFrameFlatTemplate, two layers.
|
|
-- 1. Flat background (FlatPanelBackgroundTemplate), TOPLEFT (2, -20) to BOTTOMRIGHT (-2, 3):
|
|
-- two 16 x 16 rounded bottom corners, an edge between them, the rest flat, all tinted
|
|
-- by PANEL_BACKGROUND_COLOR.
|
|
-- 2. Metal nine-slice frame: HeldBagLayout (mainline/NineSliceLayouts.lua) with the fixes
|
|
-- of camelot/NineSliceLayoutOverrides.lua (top right corner x -2, bottom corners y -8).
|
|
-- PANEL_BACKGROUND_COLOR is not in the extracted code; measured on a real client capture
|
|
-- (docs/reference): (16, 14, 12), opaque. A translucent one turns bag slot gaps blue.
|
|
-- Edges are stretched, not tiled: a tiled atlas texture spreads the whole sheet.
|
|
local PANEL_BACKGROUND = { 16 / 255, 14 / 255, 12 / 255, 1 }
|
|
|
|
-- HeldBagLayout (blizzard_sharedxml/mainline/nineslicelayouts.lua): the eight pieces are
|
|
-- OVERLAY and each corner has its offset, copied as is. In OVERLAY the metal covers every
|
|
-- region of the frame itself. The source puts title and portrait in child frames
|
|
-- (TitleContainer at frameLevel 510, PortraitContainer), which draw above their parent's
|
|
-- regions; callers must do the same for anything that must stay visible.
|
|
local PANEL_LAYER = "OVERLAY"
|
|
|
|
local PANEL_CORNERS = {
|
|
{ key = "topLeftCorner", name = "ui-frame-portraitmetal-cornertopleftsmall",
|
|
point = "TOPLEFT", x = -13, y = 16 },
|
|
{ key = "topRightCorner", name = "ui-frame-metal-cornertopright",
|
|
point = "TOPRIGHT", x = 4, y = 16 },
|
|
{ key = "bottomLeftCorner", name = "ui-frame-metal-cornerbottomleft",
|
|
point = "BOTTOMLEFT", x = -13, y = -3 },
|
|
{ key = "bottomRightCorner", name = "ui-frame-metal-cornerbottomright",
|
|
point = "BOTTOMRIGHT", x = 4, y = -3 },
|
|
}
|
|
|
|
-- options.topLeftCorner: top left corner atlas. HeldBagLayout uses ...CornerTopLeftSmall,
|
|
-- PortraitFrameTemplate ...CornerTopLeft (a wider ring for a 62 portrait).
|
|
-- options.corners: { key = { x =, y = } } overrides a corner offset, as
|
|
-- camelot/NineSliceLayoutOverrides.lua does on every layout (its art has other sizes).
|
|
-- options.level: puts the metal in a child frame this many levels above the frame. Needed
|
|
-- when the frame has other child frames, which would draw over the metal. The background
|
|
-- stays on the frame itself, behind all its child frames.
|
|
function ForeverUI.SetPanelArt(frame, options)
|
|
if frame.foreverPanel then
|
|
return frame.foreverPanel
|
|
end
|
|
|
|
options = options or {}
|
|
-- host: where the metal goes. The background stays on the frame, at the back.
|
|
local host = frame
|
|
if options.level then
|
|
host = CreateFrame("Frame", nil, frame)
|
|
host:SetAllPoints(frame)
|
|
host:SetFrameLevel(frame:GetFrameLevel() + options.level)
|
|
frame.foreverSkinLayer = host
|
|
end
|
|
|
|
local p = {}
|
|
|
|
-- 1. Flat background
|
|
local r, v, b, a = PANEL_BACKGROUND[1], PANEL_BACKGROUND[2], PANEL_BACKGROUND[3], PANEL_BACKGROUND[4]
|
|
|
|
local bottomLeft = frame:CreateTexture(nil, "BACKGROUND")
|
|
ForeverUI.SetAtlas(bottomLeft, "uiframebackground-nineslice-cornerbottomleft")
|
|
bottomLeft:SetVertexColor(r, v, b, a)
|
|
bottomLeft:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 2, 3)
|
|
|
|
local bottomRight = frame:CreateTexture(nil, "BACKGROUND")
|
|
ForeverUI.SetAtlas(bottomRight, "uiframebackground-nineslice-cornerbottomright")
|
|
bottomRight:SetVertexColor(r, v, b, a)
|
|
bottomRight:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -2, 3)
|
|
|
|
local bottomEdge = frame:CreateTexture(nil, "BACKGROUND")
|
|
bottomEdge:SetTexture(r, v, b, a)
|
|
bottomEdge:SetPoint("TOPLEFT", bottomLeft, "TOPRIGHT")
|
|
bottomEdge:SetPoint("BOTTOMRIGHT", bottomRight, "BOTTOMLEFT")
|
|
|
|
local body = frame:CreateTexture(nil, "BACKGROUND")
|
|
body:SetTexture(r, v, b, a)
|
|
body:SetPoint("TOPLEFT", frame, "TOPLEFT", 2, -20)
|
|
body:SetPoint("BOTTOMRIGHT", bottomRight, "TOPRIGHT")
|
|
|
|
p.background = { bottomLeft, bottomRight, bottomEdge, body }
|
|
|
|
-- 2. Metal frame
|
|
for _, corner in ipairs(PANEL_CORNERS) do
|
|
local texture = host:CreateTexture(nil, PANEL_LAYER)
|
|
local atlasName = corner.name
|
|
if corner.key == "topLeftCorner" and options.topLeftCorner then
|
|
atlasName = options.topLeftCorner
|
|
end
|
|
if ForeverUI.SetAtlas(texture, atlasName) then
|
|
local x, y = corner.x, corner.y
|
|
local setting = options.corners and options.corners[corner.key]
|
|
if setting then
|
|
x = setting.x or x
|
|
y = setting.y or y
|
|
end
|
|
texture:SetPoint(corner.point, host, corner.point, x, y)
|
|
p[corner.key] = texture
|
|
p[corner.key .. "Atlas"] = atlasName
|
|
else
|
|
texture:Hide()
|
|
end
|
|
end
|
|
|
|
local function edge(name, point1, target1, relative1, point2, target2, relative2)
|
|
local texture = host:CreateTexture(nil, PANEL_LAYER)
|
|
if not ForeverUI.SetAtlas(texture, name) then
|
|
texture:Hide()
|
|
return nil
|
|
end
|
|
texture:SetPoint(point1, target1, relative1)
|
|
texture:SetPoint(point2, target2, relative2)
|
|
return texture
|
|
end
|
|
|
|
if p.topLeftCorner and p.topRightCorner then
|
|
p.topEdge = edge("_ui-frame-metal-edgetop",
|
|
"TOPLEFT", p.topLeftCorner, "TOPRIGHT",
|
|
"TOPRIGHT", p.topRightCorner, "TOPLEFT")
|
|
p.leftEdge = edge("!ui-frame-metal-edgeleft",
|
|
"TOPLEFT", p.topLeftCorner, "BOTTOMLEFT",
|
|
"BOTTOMLEFT", p.bottomLeftCorner, "TOPLEFT")
|
|
p.rightEdge = edge("!ui-frame-metal-edgeright",
|
|
"TOPRIGHT", p.topRightCorner, "BOTTOMRIGHT",
|
|
"BOTTOMRIGHT", p.bottomRightCorner, "TOPRIGHT")
|
|
p.bottomEdge = edge("_ui-frame-metal-edgebottom",
|
|
"BOTTOMLEFT", p.bottomLeftCorner, "BOTTOMRIGHT",
|
|
"BOTTOMRIGHT", p.bottomRightCorner, "BOTTOMLEFT")
|
|
end
|
|
|
|
frame.foreverPanel = p
|
|
ForeverUI.UpdatePanelCorners(frame)
|
|
return p
|
|
end
|
|
|
|
-- NineSliceUtil.UpdateCornerCropping and ClipNineSliceBottomCorner
|
|
-- (blizzard_sharedxml/nineslice.lua):
|
|
-- overhang = topCornerHeight + bottomCornerHeight - frameHeight
|
|
-- - topOffset - (-bottomOffset)
|
|
-- When a frame is shorter than its two corners stacked, the bottom corners are cropped from
|
|
-- the top by that overhang (texture coordinates and height). Otherwise the corners overlap
|
|
-- and the left edge between them is drawn upside down across the frame.
|
|
function ForeverUI.UpdatePanelCorners(frame)
|
|
local p = frame.foreverPanel
|
|
if not p then
|
|
return
|
|
end
|
|
|
|
local topLeft, bottomLeft
|
|
for _, corner in ipairs(PANEL_CORNERS) do
|
|
if corner.key == "topLeftCorner" then topLeft = corner end
|
|
if corner.key == "bottomLeftCorner" then bottomLeft = corner end
|
|
end
|
|
|
|
local topEntry = ForeverUI.AtlasEntry(p.topLeftCornerAtlas or topLeft.name)
|
|
local bottomEntry = ForeverUI.AtlasEntry(bottomLeft.name)
|
|
if not (topEntry and bottomEntry) then
|
|
return
|
|
end
|
|
|
|
local overhang = topEntry[7] + bottomEntry[7] - frame:GetHeight() - topLeft.y - (-bottomLeft.y)
|
|
|
|
for _, corner in ipairs(PANEL_CORNERS) do
|
|
if corner.point == "BOTTOMLEFT" or corner.point == "BOTTOMRIGHT" then
|
|
local texture = p[corner.key]
|
|
local e = ForeverUI.AtlasEntry(corner.name)
|
|
if texture and e then
|
|
local trim = math.max(0, math.min(overhang, e[7]))
|
|
local uvHeight = e[5] - e[4]
|
|
texture:SetTexCoord(e[2], e[3], e[4] + (trim / e[7]) * uvHeight, e[5])
|
|
texture:SetWidth(e[6])
|
|
texture:SetHeight(e[7] - trim)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
-- Vertical divider in three slices. common-framedivider (11 x 50) has a cap at each end;
|
|
-- stretched over a panel's height, the caps smear over dozens of pixels. So it is cut by
|
|
-- texture coordinates into top cap, stretched middle and bottom cap.
|
|
-- atlas: element; endCap: cap height in px (4 by default); level: frame level.
|
|
function ForeverUI.CreateVerticalDivider(parent, atlas, endCap, level)
|
|
local e = ForeverUI.AtlasEntry(atlas)
|
|
local frame = CreateFrame("Frame", nil, parent)
|
|
if not e then
|
|
frame:Hide()
|
|
return frame
|
|
end
|
|
|
|
endCap = endCap or 4
|
|
frame:SetWidth(e[6])
|
|
frame:SetFrameLevel(level or parent:GetFrameLevel())
|
|
|
|
local u1, u2, v1, v2, height = e[2], e[3], e[4], e[5], e[7]
|
|
local partV = (v2 - v1) * (endCap / height)
|
|
|
|
local top = frame:CreateTexture(nil, "OVERLAY")
|
|
top:SetTexture(e[1])
|
|
top:SetTexCoord(u1, u2, v1, v1 + partV)
|
|
top:SetHeight(endCap)
|
|
top:SetPoint("TOPLEFT", frame, "TOPLEFT")
|
|
top:SetPoint("TOPRIGHT", frame, "TOPRIGHT")
|
|
|
|
local down = frame:CreateTexture(nil, "OVERLAY")
|
|
down:SetTexture(e[1])
|
|
down:SetTexCoord(u1, u2, v2 - partV, v2)
|
|
down:SetHeight(endCap)
|
|
down:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT")
|
|
down:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT")
|
|
|
|
local middle = frame:CreateTexture(nil, "OVERLAY")
|
|
middle:SetTexture(e[1])
|
|
middle:SetTexCoord(u1, u2, v1 + partV, v2 - partV)
|
|
middle:SetPoint("TOPLEFT", top, "BOTTOMLEFT")
|
|
middle:SetPoint("BOTTOMRIGHT", down, "TOPRIGHT")
|
|
|
|
frame.top, frame.middle, frame.down = top, middle, down
|
|
return frame
|
|
end
|
|
|
|
-- Nine slices cut from one image. A panel image has a shadow and fixed-size rounded
|
|
-- corners; stretched whole, the shadow scales with it and the corners distort. Corners keep
|
|
-- their size, edges stretch one way, the center both.
|
|
-- corner: corner size in px; margins = { left, top, right, bottom }: how far the image
|
|
-- overhangs the frame (the shadow thickness measured on the image), so the image's rim
|
|
-- falls on the frame edge; level: draw layer (BACKGROUND by default).
|
|
function ForeverUI.CreateNineSlice(parent, atlas, corner, margins, level)
|
|
local e = ForeverUI.AtlasEntry(atlas)
|
|
if not e then
|
|
return nil
|
|
end
|
|
|
|
local path, u1, u2, v1, v2, width, height = e[1], e[2], e[3], e[4], e[5], e[6], e[7]
|
|
local du = (u2 - u1) * corner / width
|
|
local dv = (v2 - v1) * corner / height
|
|
local us = { u1, u1 + du, u2 - du, u2 }
|
|
local vs = { v1, v1 + dv, v2 - dv, v2 }
|
|
|
|
local slices = {}
|
|
local function slice(column, row)
|
|
local t = parent:CreateTexture(nil, level or "BACKGROUND")
|
|
t:SetTexture(path)
|
|
t:SetTexCoord(us[column], us[column + 1], vs[row], vs[row + 1])
|
|
slices[#slices + 1] = t
|
|
return t
|
|
end
|
|
|
|
local topLeft, topRight = slice(1, 1), slice(3, 1)
|
|
local bottomLeft, bottomRight = slice(1, 3), slice(3, 3)
|
|
local top, down = slice(2, 1), slice(2, 3)
|
|
local left, right = slice(1, 2), slice(3, 2)
|
|
local center = slice(2, 2)
|
|
|
|
for _, c in ipairs({ topLeft, topRight, bottomLeft, bottomRight }) do
|
|
c:SetWidth(corner)
|
|
c:SetHeight(corner)
|
|
end
|
|
top:SetHeight(corner)
|
|
down:SetHeight(corner)
|
|
left:SetWidth(corner)
|
|
right:SetWidth(corner)
|
|
|
|
local G, H, D, B = margins[1], margins[2], margins[3], margins[4]
|
|
topLeft:SetPoint("TOPLEFT", parent, "TOPLEFT", -G, H)
|
|
topRight:SetPoint("TOPRIGHT", parent, "TOPRIGHT", D, H)
|
|
bottomLeft:SetPoint("BOTTOMLEFT", parent, "BOTTOMLEFT", -G, -B)
|
|
bottomRight:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", D, -B)
|
|
|
|
top:SetPoint("TOPLEFT", topLeft, "TOPRIGHT")
|
|
top:SetPoint("TOPRIGHT", topRight, "TOPLEFT")
|
|
down:SetPoint("BOTTOMLEFT", bottomLeft, "BOTTOMRIGHT")
|
|
down:SetPoint("BOTTOMRIGHT", bottomRight, "BOTTOMLEFT")
|
|
left:SetPoint("TOPLEFT", topLeft, "BOTTOMLEFT")
|
|
left:SetPoint("BOTTOMRIGHT", bottomLeft, "TOPRIGHT")
|
|
right:SetPoint("TOPLEFT", topRight, "BOTTOMLEFT")
|
|
right:SetPoint("BOTTOMRIGHT", bottomRight, "TOPRIGHT")
|
|
center:SetPoint("TOPLEFT", topLeft, "BOTTOMRIGHT")
|
|
center:SetPoint("BOTTOMRIGHT", bottomRight, "TOPLEFT")
|
|
|
|
return slices
|
|
end
|
|
|
|
-- Tertiary button, two states: common-button-tertiary-normal / -pressed, 46 x 34 each, sheet
|
|
-- commonbuttontertiaryc60. The rounded end is 11 px (column profile constant from x = 11),
|
|
-- so the corner is 11 on both axes. Stretched instead of sliced, it squashes past 46 wide.
|
|
-- The button keeps its own textures at alpha 0: they still hold its state for the client,
|
|
-- and some functions read them.
|
|
-- auto: the pressed state follows the mouse button. Otherwise the caller drives it with
|
|
-- button.foreverPress(true or false), e.g. statistic selectors, pressed while their list
|
|
-- is open.
|
|
local TERTIARY_NORMAL = "common-button-tertiary-normal"
|
|
local TERTIARY_PRESSED = "common-button-tertiary-pressed"
|
|
local TERTIARY_CORNER = 11
|
|
local TERTIARY_MARGINS = { 0, 0, 0, 0 }
|
|
|
|
function ForeverUI.SkinTertiaryButton(button, auto)
|
|
if button.foreverPress then
|
|
return button
|
|
end
|
|
|
|
for _, method in ipairs({ "GetNormalTexture", "GetPushedTexture",
|
|
"GetHighlightTexture", "GetDisabledTexture" }) do
|
|
local texture = button[method] and button[method](button)
|
|
if texture then
|
|
texture:SetAlpha(0)
|
|
end
|
|
end
|
|
|
|
button.foreverNormal = ForeverUI.CreateNineSlice(button, TERTIARY_NORMAL,
|
|
TERTIARY_CORNER, TERTIARY_MARGINS, "BACKGROUND")
|
|
button.foreverPressed = ForeverUI.CreateNineSlice(button, TERTIARY_PRESSED,
|
|
TERTIARY_CORNER, TERTIARY_MARGINS, "BACKGROUND")
|
|
|
|
button.foreverPress = function(state)
|
|
for _, slice in ipairs(button.foreverPressed or {}) do
|
|
if state then slice:Show() else slice:Hide() end
|
|
end
|
|
for _, slice in ipairs(button.foreverNormal or {}) do
|
|
if state then slice:Hide() else slice:Show() end
|
|
end
|
|
end
|
|
button.foreverPress(false)
|
|
|
|
if auto then
|
|
button:HookScript("OnMouseDown", function() button.foreverPress(true) end)
|
|
button:HookScript("OnMouseUp", function() button.foreverPress(false) end)
|
|
end
|
|
|
|
return button
|
|
end
|
|
|
|
-- Camelot inset: InsetFrameTemplate (shareduipaneltemplates.xml, nineslicelayouts.lua).
|
|
-- Tiled UI-Background-Marble background; UI-Frame-InnerTopLeft / TopRight / BotLeftCorner /
|
|
-- BotRight corners (6 x 6, bottom ones at y = -1) joined by _UI-Frame-InnerTopTile / BotTile
|
|
-- and !UI-Frame-InnerLeftTile / RightTile (3 thick).
|
|
local MARBLE = "interface" .. string.char(92) .. "ForeverUI" .. string.char(92)
|
|
.. "framegeneral" .. string.char(92) .. "ui-background-marble"
|
|
|
|
function ForeverUI.CreateInset(parent, name)
|
|
return ForeverUI.DecorateInset(CreateFrame("Frame", name, parent))
|
|
end
|
|
|
|
-- Same art on an existing frame (e.g. the bank rights frame of the guild control window):
|
|
-- regions of its own, below its child frames.
|
|
function ForeverUI.DecorateInset(e)
|
|
local background = e:CreateTexture(nil, "BACKGROUND")
|
|
background:SetTexture(MARBLE, true)
|
|
if background.SetHorizTile then
|
|
background:SetHorizTile(true)
|
|
background:SetVertTile(true)
|
|
end
|
|
background:SetAllPoints(e)
|
|
e.background = background
|
|
|
|
local function corner(atlas, point, y)
|
|
local t = e:CreateTexture(nil, "BORDER")
|
|
ForeverUI.SetAtlas(t, atlas)
|
|
t:SetPoint(point, e, point, 0, y or 0)
|
|
return t
|
|
end
|
|
local topLeft = corner("ui-frame-innertopleft", "TOPLEFT")
|
|
local topRight = corner("ui-frame-innertopright", "TOPRIGHT")
|
|
local bottomLeft = corner("ui-frame-innerbotleftcorner", "BOTTOMLEFT", -1)
|
|
local bottomRight = corner("ui-frame-innerbotright", "BOTTOMRIGHT", -1)
|
|
-- thickness from the element (3), length from the corners
|
|
local function edge(atlas, a1, c1, r1, a2, c2, r2)
|
|
local t = e:CreateTexture(nil, "BORDER")
|
|
ForeverUI.SetAtlas(t, atlas, true)
|
|
t:SetPoint(a1, c1, r1)
|
|
t:SetPoint(a2, c2, r2)
|
|
return t
|
|
end
|
|
local top = edge("_ui-frame-innertoptile", "TOPLEFT", topLeft, "TOPRIGHT", "TOPRIGHT", topRight, "TOPLEFT")
|
|
top:SetHeight(3)
|
|
local down = edge("_ui-frame-innerbottile", "BOTTOMLEFT", bottomLeft, "BOTTOMRIGHT", "BOTTOMRIGHT", bottomRight, "BOTTOMLEFT")
|
|
down:SetHeight(3)
|
|
local left = edge("!ui-frame-innerlefttile", "TOPLEFT", topLeft, "BOTTOMLEFT", "BOTTOMLEFT", bottomLeft, "TOPLEFT")
|
|
left:SetWidth(3)
|
|
local right = edge("!ui-frame-innerrighttile", "TOPRIGHT", topRight, "BOTTOMRIGHT", "BOTTOMRIGHT", bottomRight, "TOPRIGHT")
|
|
right:SetWidth(3)
|
|
e.trim = { topLeft, topRight, bottomLeft, bottomRight, top, down, left, right }
|
|
return e
|
|
end
|
|
|
|
-- Camelot panel button, UIPanelButtonTemplate: three pieces of UI-Panel-Button-Up / -Down /
|
|
-- -Disabled (left 12, stretched middle, right 12; 0.6875 high), -Highlight in ADD.
|
|
-- b:Activate(yes): UIPanelButton_OnEnable / _OnDisable, -Disabled image and grey font.
|
|
-- font: font object name (GameFontNormalSmall by default); template: optional frame template.
|
|
local PANEL_BUTTON = "Interface" .. string.char(92) .. "Buttons" .. string.char(92) .. "UI-Panel-Button-"
|
|
|
|
function ForeverUI.CreatePanelButton(parent, buttonText, width, height, name, font, template)
|
|
local b = CreateFrame("Button", name, parent, template)
|
|
b:SetWidth(width)
|
|
b:SetHeight(height)
|
|
local function piece(u1, u2)
|
|
local t = b:CreateTexture(nil, "BACKGROUND")
|
|
t:SetTexCoord(u1, u2, 0, 0.6875)
|
|
return t
|
|
end
|
|
local g = piece(0, 0.09375)
|
|
g:SetWidth(12)
|
|
g:SetPoint("TOPLEFT", b, "TOPLEFT", 0, 0)
|
|
g:SetPoint("BOTTOMLEFT", b, "BOTTOMLEFT", 0, 0)
|
|
local d = piece(0.53125, 0.625)
|
|
d:SetWidth(12)
|
|
d:SetPoint("TOPRIGHT", b, "TOPRIGHT", 0, 0)
|
|
d:SetPoint("BOTTOMRIGHT", b, "BOTTOMRIGHT", 0, 0)
|
|
local m = piece(0.09375, 0.53125)
|
|
m:SetPoint("TOPLEFT", g, "TOPRIGHT", 0, 0)
|
|
m:SetPoint("BOTTOMRIGHT", d, "BOTTOMLEFT", 0, 0)
|
|
local pieces = { g, m, d }
|
|
local function state(suffix)
|
|
for _, t in ipairs(pieces) do
|
|
t:SetTexture(PANEL_BUTTON .. suffix)
|
|
end
|
|
end
|
|
state("Up")
|
|
local normalFont = font and _G[font .. ""] or GameFontNormalSmall
|
|
local hover = font and _G[(font == "GameFontNormal") and "GameFontHighlight" or "GameFontHighlightSmall"]
|
|
or GameFontHighlightSmall
|
|
local fs = b:CreateFontString(nil, "ARTWORK")
|
|
fs:SetFontObject(normalFont)
|
|
fs:SetPoint("CENTER", b, "CENTER", 0, 0)
|
|
b:SetFontString(fs)
|
|
b:SetNormalFontObject(normalFont)
|
|
b:SetHighlightFontObject(hover)
|
|
if b.SetDisabledFontObject then
|
|
b:SetDisabledFontObject((font == "GameFontNormal") and GameFontDisable or GameFontDisableSmall)
|
|
end
|
|
b:SetText(buttonText)
|
|
b:SetHighlightTexture(PANEL_BUTTON .. "Highlight")
|
|
local s = b:GetHighlightTexture()
|
|
if s then
|
|
s:SetTexCoord(0, 0.625, 0, 0.6875)
|
|
s:SetBlendMode("ADD")
|
|
end
|
|
b.active = true
|
|
b:SetScript("OnMouseDown", function(self) if self.active then state("Down") end end)
|
|
b:SetScript("OnMouseUp", function(self) if self.active then state("Up") end end)
|
|
function b:Activate(yes)
|
|
self.active = yes and true or false
|
|
if yes then
|
|
self:Enable()
|
|
state("Up")
|
|
else
|
|
self:Disable()
|
|
state("Disabled")
|
|
end
|
|
end
|
|
return b
|
|
end
|