Golden UI: Forever-brown window title bars; mail inbox gets the send page's stationery (3.7.3 hotfix)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019W3rwusM4i1CYaHQAYixJ7
This commit is contained in:
2026-11-03 08:14:46 +00:00
co-authored by Claude Opus 5.5
parent 767b458aa6
commit 0784e2e5bb
2 changed files with 130 additions and 0 deletions
+128
View File
@@ -28,6 +28,7 @@ local golden = ShaguTweaks:register({
["goldmode.color"] = { r = 1, g = .78, b = .4, a = 1 },
["goldmode.border"] = { r = .8, g = .62, b = .32, a = 1 },
["goldmode.text"] = { r = .84, g = .72, b = .48, a = 1 },
["goldmode.bar"] = { r = .8, g = .63, b = .62, a = 1 },
}
})
@@ -78,6 +79,9 @@ local backgrounds = {
["^QuestLogDetailScrollFrame$"] = { QuestLogDetailScrollChildFrame:GetWidth(), QuestLogDetailScrollChildFrame:GetHeight(), 0, 0 },
["^QuestFrame(.+)Panel$"] = { 300, 330, 24, -82 },
["^GossipFrameGreetingPanel$"] = { 300, 330, 24, -82 },
-- the mail inbox uses the same parchment art as ItemTextFrame; the send
-- page already has its own stationery on top
["^InboxFrame$"] = { 300, 355, 24, -74 },
}
local borders = {
@@ -371,6 +375,7 @@ end
local function RecolorOnShow(frame)
if not frame or frame.stRecolorOnShow then return end
frame.stRecolorOnShow = true
if golden.rollforLoot and frame:GetName() == "RollForLootFrameHeader" then golden.rollforLoot(frame) end
ShaguTweaks.HookScript(frame, "OnShow", function()
DarkenFrame(frame)
if _G.C_Timer and _G.C_Timer.After then
@@ -645,6 +650,125 @@ module.enable = function(self)
Apply(module.config["darkmode.color"], module.config["darkmode.color"], true)
end
-- Title bars: the dark strips the window titles sit on. Golden UI
-- multiplies them toward WoW Forever's red-brown with a MOD layer. Measured
-- from the window art: rows below the frame's top edge, and how far the strip
-- runs from the left (after the portrait) and from the right (before the
-- close button).
local STRIP_A = { 72, -16, -60, -34 } -- character, spellbook, mail, quest log art
local STRIP_B = { 72, -15, -62, -33 } -- merchant, friends art
local function Shade(parent, layer, color)
local shade = parent:CreateTexture(nil, layer)
shade:SetTexture(1, 1, 1, 1)
shade:SetVertexColor(tonumber(color.r) or .8, tonumber(color.g) or .63, tonumber(color.b) or .62, 1)
shade:SetBlendMode("MOD")
return shade
end
local function PlaceStrip(shade, frame, strip)
shade:ClearAllPoints()
shade:SetPoint("TOPLEFT", frame, "TOPLEFT", strip[1], strip[2])
shade:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT", strip[3], strip[4])
end
-- The shade has to sit above the window art, which would darken a title
-- that is drawn in the same frame. Those titles are drawn again on top and
-- the original is kept, invisible, for its position and text.
local function RedrawTitle(holder, title, gold)
if not title then return end
local copy = holder:CreateFontString(nil, "OVERLAY", "GameFontNormal")
local font = not gold and title.GetFontObject and title:GetFontObject()
if font then copy:SetFontObject(font) end
-- titles drawn in white (Turtle's quest log) get the same gold as the rest
if gold and NORMAL_FONT_COLOR then
copy:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b)
end
copy:SetAllPoints(title)
if title.GetJustifyH then copy:SetJustifyH(title:GetJustifyH()) end
copy:SetText(title:GetText())
title:SetAlpha(0)
local setText = title.SetText
title.SetText = function(self, text)
setText(self, text)
copy:SetText(text)
end
return copy
end
local function ShadeTitleBar(frame, strip, title, color, level, gold)
if not frame or frame.stTitleBar then return end
local bar = CreateFrame("Frame", nil, frame)
bar:SetAllPoints(frame)
if level then bar:SetFrameLevel(level) end
frame.stTitleBar = bar
bar.shade = Shade(bar, "BACKGROUND", color)
PlaceStrip(bar.shade, frame, strip)
bar.title = RedrawTitle(bar, title, gold)
return bar
end
-- frames whose titles live in child frames (or above the art layer): the
-- shade is a plain texture in the window itself, nothing to redraw
local function ShadeStripInFrame(frame, strip, layer, color)
if not frame or frame.stTitleShade then return end
frame.stTitleShade = Shade(frame, layer, color)
PlaceStrip(frame.stTitleShade, frame, strip)
end
local function ShadeTitleBars(color)
-- world map: its strip is 3 to 21 px below the top of its art (384 above
-- the frame center), from the left corner to the window buttons
if WorldMapFrame and WorldMapFrameTitle and not WorldMapFrame.stTitleBar then
local bar = ShadeTitleBar(WorldMapFrame, { 0, 0, 0, 0 }, WorldMapFrameTitle, color)
bar.shade:ClearAllPoints()
bar.shade:SetPoint("TOPLEFT", WorldMapFrame, "CENTER", -510, 381)
bar.shade:SetPoint("BOTTOMRIGHT", WorldMapFrame, "CENTER", 455, 363)
-- the stone art is lighter around the seam of its first two pieces
-- (measured in 8 px columns): darken those columns a bit more so the
-- bar comes out even
local even = {
{ -272, .81 }, { -264, .76 },
{ -256, .66 }, { -248, .52 }, { -240, .49 }, { -232, .47 }, { -224, .53 }, { -216, .54 },
{ -208, .52 }, { -200, .58 }, { -192, .69 }, { -184, .76 }, { -176, .68 }, { -168, .68 },
{ -160, .69 }, { -152, .71 }, { -144, .78 }, { -136, .86 },
}
for i = 1, table.getn(even) do
local x, f = even[i][1], even[i][2]
local fix = Shade(bar, "BACKGROUND", { r = f, g = f, b = f })
fix:SetPoint("TOPLEFT", WorldMapFrame, "CENTER", x, 381)
fix:SetPoint("BOTTOMRIGHT", WorldMapFrame, "CENTER", x + 8, 363)
end
end
ShadeTitleBar(MerchantFrame, STRIP_B, MerchantNameText, color)
ShadeTitleBar(SpellBookFrame, STRIP_A, SpellBookTitleText, color)
ShadeTitleBar(FriendsFrame, STRIP_B, FriendsFrameTitleText, color)
-- the quest log is wider: its strip ends before the close button
ShadeTitleBar(QuestLogFrame, { 72, -16, -121, -34 }, QuestLogTitleText, color, nil, true)
-- mail: the art is on the BORDER layer, the titles are on the page frames
ShadeStripInFrame(MailFrame, STRIP_A, "ARTWORK", color)
-- character: the art is on the tab pages (PaperDollFrame and the others),
-- the name on CharacterNameFrame. The shade goes between the two.
if CharacterFrame and PaperDollFrame and CharacterNameFrame then
local level = PaperDollFrame:GetFrameLevel() + 1
if CharacterNameFrame:GetFrameLevel() <= level then CharacterNameFrame:SetFrameLevel(level + 1) end
ShadeTitleBar(CharacterFrame, STRIP_A, nil, color, level)
end
end
-- RollFor's classic loot window: the art is on the BACKGROUND layer and the
-- "Items" title on ARTWORK, so the shade fits between them. The strip runs
-- 12 to 30 px down, from the portrait to 25 px before the right edge (the
-- window width changes with the item names).
local function ShadeRollForLoot(frame, color)
ShadeStripInFrame(frame, { 68, -12, -25, -30 }, "BORDER", color)
end
golden.enable = function(self)
-- Both recolor the same textures; Darkened UI wins when both are ticked.
if ShaguTweaks_config and ShaguTweaks_config[T["Darkened UI"]] == 1 then return end
@@ -663,4 +787,8 @@ golden.enable = function(self)
local font = _G[fonts[i]]
if font and font.SetTextColor then font:SetTextColor(r, g, b) end
end
ShadeTitleBars(golden.config["goldmode.bar"])
golden.rollforLoot = function(frame) ShadeRollForLoot(frame, golden.config["goldmode.bar"]) end
if _G.RollForLootFrameHeader then golden.rollforLoot(_G.RollForLootFrameHeader) end
end