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
+2
View File
@@ -13,6 +13,8 @@ This fork is based on [Dusk/ShaguTweaks-ClassicAPI](https://octowow.st/git/Dusk/
### Changed
- **Golden UI** also turns the stock bright yellow text (titles, names, labels: everything in the normal gold font) into WoW Forever's softer, browner gold (`goldmode.text`, default .84, .72, .48).
- **Golden UI** darkens the window title bars to WoW Forever's red-brown (`goldmode.bar`, default .8, .63, .62): world map, character, spellbook, quest log, merchant, friends, mail and RollFor's classic loot window. Where the title sits in the same layer as the art, the title is drawn again on top of the bar; the quest log's white title now uses the same gold as the others, and the lighter patch in the world map's stone art is evened out.
- **Darkened UI and Golden UI** give the mail inbox the same stationery page as the send page. Its parchment art turned strongly red under Golden UI.
- **Darkened UI and Golden UI** tint the round border of addon minimap buttons (the stock tracking border, as on RollFor's button), also when the addon makes its button after login.
- **Darkened UI and Golden UI** now keep these addons' borders in the palette too, even when they set their colors again later or open a window after login: ShaguDPS, Bagshui, Outfitter, SoulstoneTracker, TrinketMenu, OctoBus, RollFor and VCB. Outfitter's own window art and the lower half of Artisan's profession window (its own textures, which stayed silver) are tinted too, VCB's buff and weapon-buff buttons get a border like the Blizzard buff buttons, the loot window, and RollFor's classic loot window (its own art plus the item rows), are recolored each time they open, and Loot Quality draws common (white) items with the palette's border color. Only light grey, white and silver borders change; colored ones (item quality, hover highlights, class or theme colors) and dark ones stay as the addon draws them. No change is needed in those addons.
- **Darkened UI:** works the same, but now shares its recolor code with Golden UI. Big Health's replacement unit frame art follows whichever of the two is on.
+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