diff --git a/CHANGELOG.md b/CHANGELOG.md index 6881b03..a3d45ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ Changes in OEVG/ShaguTweaks-ClassicAPI, newest first. Entries summarize released Based on [Dusk/ShaguTweaks-ClassicAPI](https://octowow.st/git/Dusk/ShaguTweaks-ClassicAPI) at `4391564` (2026-09-08). Earlier history is available upstream. +## 3.8.7 — 2026-11-08 — Unit frames and minimap buttons + +- Add optional owner class colors for pet health bars, including targeted pets with identifiable owners. +- Add an option to remove the class-colored background behind your player name, including on the detached name frame. +- Apply Darkened and Golden UI tints to the Outfitter, TrinketMenu and Atlas-CFM minimap buttons. +- Preserve the Spellbook's original parchment and torn edges in Darkened and Golden UI. + ## 3.8.6 — 2026-11-06 — Module fixes and native timers - Prevent recursive merchant-click hooks when Buy Em All runs alongside another merchant addon. diff --git a/README.md b/README.md index c151b00..efb0c57 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ English-only fork of [Dusk/ShaguTweaks-ClassicAPI](https://octowow.st/git/Dusk/S Focused on **stability, compatibility, customization, and performance** while keeping the original ShaguTweaks experience. -**Version 3.8.6.** What changed in each update: see the [changelog](CHANGELOG.md). +**Version 3.8.7.** What changed in each update: see the [changelog](CHANGELOG.md). > **Upgrading to 3.7:** the modules of the separate *ShaguTweaks Extras ClassicAPI* addon are now built into ShaguTweaks. **Disable or delete `ShaguTweaks-extras`** after updating, otherwise its older copies replace the built-in ones. Your on/off settings carry over. Raid Frames, Bag Item Click, Bag Search Bar and Auction Alt-Buy were not merged. See [Docs/EXTRAS_MERGE.md](Docs/EXTRAS_MERGE.md) for where each module went and why some were left out. See the [migration guide](Docs/EXTRAS_MERGE.md#removed-later) for removed modules. diff --git a/ShaguTweaks.toc b/ShaguTweaks.toc index 109188a..fbd48d7 100644 --- a/ShaguTweaks.toc +++ b/ShaguTweaks.toc @@ -2,7 +2,7 @@ ## Title: |cffffcc00Shagu|cffffffffTweaks |cffcccccc[ClassicAPI] ## Author: Shagu ## Notes: A collection of tweaks and enhancements to the Default UI -## Version: 3.8.6 +## Version: 3.8.7 ## Dependencies: !!!ClassicAPI ## SavedVariables: ShaguTweaks_player_cache, ShaguTweaks_social_cache ## SavedVariablesPerCharacter: ShaguTweaks_config, ShaguTweaks_cache diff --git a/mods/dark-ui-elements.lua b/mods/dark-ui-elements.lua index c6ab64a..d702297 100644 --- a/mods/dark-ui-elements.lua +++ b/mods/dark-ui-elements.lua @@ -73,7 +73,6 @@ local regionskips = { } local backgrounds = { - ["^SpellBookFrame$"] = { 325, 355, 17, -74 }, ["^ItemTextFrame$"] = { 300, 355, 24, -74 }, } @@ -276,6 +275,40 @@ local function IsExcludedFrame(frame) return name and string.find(name, "TrinketMenu", 1, true) == 1 end +-- The Spellbook's metal frame and torn paper share four 256px-high tiles. +local spellbookPaper = { + topleft = {22, 74, 256, 256, 256}, + topright = {0, 74, 85, 256, 128}, + botleft = {22, 0, 256, 175, 256}, + botright = {0, 0, 85, 175, 128}, +} + +local function RestoreSpellbookParchment(frame, source) + if source.stSpellbookPaper then return end + local path = source:GetTexture() + if type(path) ~= "string" then return end + local _, _, side = string.find(string.lower(path), "^interface\\spellbook\\ui%-spellbookpanel%-(%a+)$") + local crop = spellbookPaper[side] + if not crop then return end + local width, height = source:GetWidth(), source:GetHeight() + if not width or width <= 0 or not height or height <= 0 then return end + + -- Keep the art below the paper and the page number above it. + source:SetDrawLayer("BORDER") + if _G.SpellBookPageText then _G.SpellBookPageText:SetDrawLayer("OVERLAY") end + local paper = frame:CreateTexture(nil, "ARTWORK") + paper.stOriginalQuestPaper = true + paper:SetTexture(path) + paper:SetVertexColor(1, 1, 1, 1) + local x1, y1, x2, y2, tileWidth = unpack(crop) + local sx, sy = width / tileWidth, height / 256 + paper:SetTexCoord(x1 / tileWidth, x2 / tileWidth, y1 / 256, y2 / 256) + paper:SetWidth((x2 - x1) * sx) + paper:SetHeight((y2 - y1) * sy) + paper:SetPoint("TOPLEFT", source, "TOPLEFT", x1 * sx, -y1 * sy) + source.stSpellbookPaper = paper +end + local function RestoreQuestParchment(frame) local name = frame.GetName and frame:GetName() if not name or not (string.find(name, "^QuestFrame.*Panel$") @@ -435,6 +468,7 @@ local function DarkenFrame(frame, r, g, b, a, scan) else if capture then capture.textureWrites = capture.textureWrites + 1 end region:SetVertexColor(r,g,b,a) + if name == "SpellBookFrame" then RestoreSpellbookParchment(frame, region) end end end end @@ -577,10 +611,24 @@ local function FindAddonFrames(frame) end end --- The round border of addon minimap buttons (most use the stock tracking --- border texture). Those buttons are often made after login. +-- These buttons need explicit discovery when created by XML or nested below +-- a minimap child frame. Outfitter and TrinketMenu bake the rim into their art. +local addonMinimapButtons = { + OutfitterMinimapButton = true, + TrinketMenu_IconFrame = true, + AtlasCFMMinimapButton = true, +} + local function TintMinimapButton(frame) - if not frame or not frame.GetRegions then return end + if not tint or not frame or not frame.GetRegions then return end + local name = frame.GetName and frame:GetName() + if name == "OutfitterMinimapButton" or name == "TrinketMenu_IconFrame" then + local normal = frame:GetNormalTexture() + local pushed = frame:GetPushedTexture() + if normal then normal:SetVertexColor(tint.r, tint.g, tint.b, 1) end + if pushed then pushed:SetVertexColor(tint.r, tint.g, tint.b, 1) end + return + end if IsExcludedFrame(frame) then return end local regions = { frame:GetRegions() } for i = 1, table.getn(regions) do @@ -592,6 +640,10 @@ local function TintMinimapButton(frame) end end +local function TintLoadedMinimapButton(name) + HookAddonOrVariable(name, function() TintMinimapButton(_G[name]) end) +end + local function RecolorOnShow(frame) if not frame or frame.stRecolorOnShow then return end frame.stRecolorOnShow = true @@ -620,6 +672,14 @@ local function LockAddonFrames() local buttons = { Minimap:GetChildren() } for i = 1, table.getn(buttons) do TintMinimapButton(buttons[i]) end end + for name in pairs(addonMinimapButtons) do + local button = _G[name] + if not button then + TintLoadedMinimapButton(name) + elseif button:GetParent() ~= Minimap then + TintMinimapButton(button) + end + end -- frames those addons create later: named after the addon, or created -- inside one of their frames (templates bring their children along) @@ -637,7 +697,7 @@ local function LockAddonFrames() end end -- minimap buttons get their border texture right after they are made - if frame and a3 and a3 == Minimap then + if frame and ((a3 and a3 == Minimap) or addonMinimapButtons[a2]) then if _G.C_Timer and _G.C_Timer.After then _G.C_Timer.After(0, function() TintMinimapButton(frame) end) end diff --git a/mods/unitframes-classcolor.lua b/mods/unitframes-classcolor.lua index 67c2add..20f9d24 100644 --- a/mods/unitframes-classcolor.lua +++ b/mods/unitframes-classcolor.lua @@ -19,6 +19,95 @@ local function GetUnitClassColor(unit) return palette[class] or FALLBACK_CLASS_COLOR end +local playerNameOption = ShaguTweaks:register({ + title = T["Player's Name No Class Color"], + description = T["Removes the class-colored strip behind your player name, including the separate name frame."], + expansions = { ["vanilla"] = true }, + category = T["Unit Frames"], + enable = function() end, -- Read by both player name layouts at startup. +}) + +local petColors = ShaguTweaks:register({ + title = T["Pets Use Owner Class Color"], + description = T["Colors pet health bars by their owners' classes, including targeted pets whose owners can be identified."], + expansions = { ["vanilla"] = true }, + category = T["Unit Frames"], +}) + +petColors.enable = function() + local refresh = {} + local function AddPetBar(bar, pet, owner) + if not bar then return end + local setColor = bar.SetStatusBarColor + local function Apply() + if not UnitExists(pet) or not UnitExists(owner) then return end + local color = GetUnitClassColor(owner) + setColor(bar, color.r, color.g, color.b, 1) + end + refresh[owner] = Apply + ShaguTweaks.hooksecurefunc(bar, "SetStatusBarColor", Apply) + Apply() + end + AddPetBar(PetFrameHealthBar, "pet", "player") + for id = 1, MAX_PARTY_MEMBERS do + AddPetBar(_G["PartyMemberFrame" .. id .. "PetFrameHealthBar"], "partypet" .. id, "party" .. id) + end + + local function GetTargetOwner() + if not UnitExists("target") then return end + if UnitIsUnit("target", "pet") then return "player" end + for id = 1, MAX_PARTY_MEMBERS do + if UnitIsUnit("target", "partypet" .. id) then return "party" .. id end + end + local api = ShaguTweaks.API + if api and api.UnitTokenFromGUID and _G.UnitIsPet and _G.UnitOwnerGUID and _G.UnitIsPet("target") then + local guid = _G.UnitOwnerGUID("target") + local owner = guid and api.UnitTokenFromGUID(guid) + if owner and UnitIsPlayer(owner) then return owner end + end + end + + local function RefreshTarget() end + if TargetFrameHealthBar then + local bar = TargetFrameHealthBar + local setColor = bar.SetStatusBarColor + local r, g, b, a = bar:GetStatusBarColor() + local targetColor + RefreshTarget = function() + local owner = GetTargetOwner() + local previous = targetColor + targetColor = owner and GetUnitClassColor(owner) + if targetColor then + setColor(bar, targetColor.r, targetColor.g, targetColor.b, 1) + elseif previous then + setColor(bar, r, g, b, a or 1) + end + end + -- Big Health installs its setter hook later. Calls through the captured + -- setter still reach this hook, so the owner color wins over reaction blue. + ShaguTweaks.hooksecurefunc(bar, "SetStatusBarColor", function(_, red, green, blue, alpha) + r, g, b, a = red, green, blue, alpha + if targetColor then setColor(bar, targetColor.r, targetColor.g, targetColor.b, 1) end + end) + ShaguTweaks.hooksecurefunc("TargetFrame_CheckFaction", RefreshTarget) + RefreshTarget() + end + + local events = CreateFrame("Frame") + events:RegisterEvent("UNIT_PET") + events:RegisterEvent("PARTY_MEMBERS_CHANGED") + events:RegisterEvent("PLAYER_ENTERING_WORLD") + events:SetScript("OnEvent", function() + if event == "UNIT_PET" then + local apply = refresh[arg1] + if apply then apply() end + else + for _, apply in pairs(refresh) do apply() end + end + RefreshTarget() + end) +end + local function SetTextColorIfChanged(fontString, r, g, b, a) local cr, cg, cb, ca = fontString:GetTextColor() if cr ~= r or cg ~= g or cb ~= b or ca ~= a then @@ -74,6 +163,10 @@ module.enable = function(self) PlayerFrameNameBackground:SetHeight(19) PlayerFrameNameBackground:SetPoint("TOPLEFT", 106, -22) PlayerFrameNameBackground:SetVertexColor(playerColor.r, playerColor.g, playerColor.b, 1) + -- Big Health still reads this texture's class tint when its artwork is hidden. + if ShaguTweaks_config and ShaguTweaks_config[playerNameOption.title] == 1 then + PlayerFrameNameBackground:Hide() + end local wait = CreateFrame("Frame") wait:RegisterEvent("PLAYER_ENTERING_WORLD") diff --git a/mods/unitframes-hide-player-resources.lua b/mods/unitframes-hide-player-resources.lua index 88eee03..d30e654 100644 --- a/mods/unitframes-hide-player-resources.lua +++ b/mods/unitframes-hide-player-resources.lua @@ -202,20 +202,22 @@ module.enable = function(self) playerName:ClearAllPoints() playerName:SetPoint("CENTER", name, "CENTER", 0, 0) end - -- Big Health deliberately hides the stock name background. Keep its - -- color source for that module, but draw a separate class strip here. - name.classBackground = name:CreateTexture(nil, "BACKGROUND") - name.classBackground:SetPoint("TOPLEFT", name, "TOPLEFT", 4, -3) - name.classBackground:SetPoint("BOTTOMRIGHT", name, "BOTTOMRIGHT", -4, 3) - local healthTexture = PlayerFrameHealthBar:GetStatusBarTexture() - name.classBackground:SetTexture(healthTexture and healthTexture:GetTexture() - or "Interface\\TargetingFrame\\UI-StatusBar") - local _, class = UnitClass("player") - local palette = ShaguTweaks.ModernClassColors or RAID_CLASS_COLORS - local classColor = palette and palette[class] - local cr, cg, cb = PlayerFrameHealthBar:GetStatusBarColor() - name.classBackground:SetVertexColor(classColor and classColor.r or cr, - classColor and classColor.g or cg, classColor and classColor.b or cb, 1) + if ShaguTweaks_config[T["Player's Name No Class Color"]] ~= 1 then + -- Big Health deliberately hides the stock name background. Keep its + -- color source for that module, but draw a separate class strip here. + name.classBackground = name:CreateTexture(nil, "BACKGROUND") + name.classBackground:SetPoint("TOPLEFT", name, "TOPLEFT", 4, -3) + name.classBackground:SetPoint("BOTTOMRIGHT", name, "BOTTOMRIGHT", -4, 3) + local healthTexture = PlayerFrameHealthBar:GetStatusBarTexture() + name.classBackground:SetTexture(healthTexture and healthTexture:GetTexture() + or "Interface\\TargetingFrame\\UI-StatusBar") + local _, class = UnitClass("player") + local palette = ShaguTweaks.ModernClassColors or RAID_CLASS_COLORS + local classColor = palette and palette[class] + local cr, cg, cb = PlayerFrameHealthBar:GetStatusBarColor() + name.classBackground:SetVertexColor(classColor and classColor.r or cr, + classColor and classColor.g or cg, classColor and classColor.b or cb, 1) + end if ShaguTweaks_config[T["Hide Player Name"]] == 1 then name:Hide() end -- Keep native bar objects and events alive. Copies may still mirror them. diff --git a/tests/test_personal_resource_display.lua b/tests/test_personal_resource_display.lua index 581f965..50927fe 100644 --- a/tests/test_personal_resource_display.lua +++ b/tests/test_personal_resource_display.lua @@ -1,5 +1,5 @@ local root=(arg[1] or '.') .. '/' -local function Check(big,timer,hideResources,druid) +local function Check(big,timer,hideResources,druid,noNameColor) local modules,frames,pending={},{},{} local methods={} local function noop() end @@ -112,6 +112,7 @@ local function Check(big,timer,hideResources,druid) function methods:StartSizing(direction) self.sizing=direction end ShaguTweaks.Abbreviate=function(v) return tostring(v) end ShaguTweaks_config={['Hide Player Frame Resources']=hideResources and 1 or 0, + ["Player's Name No Class Color"]=noNameColor and 1 or 0, ['Unit Frame Big Health for Player']=big and 1 or 0, PersonalResourceDisplay={Health={x=420,y=520,width=180,height=40}}} local nativeHeight=PlayerFrameHealthBar:GetHeight() @@ -121,6 +122,9 @@ local function Check(big,timer,hideResources,druid) local ready=frames[table.getn(frames)] fire(ready,'OnEvent');fire(ready,'OnUpdate') if timer then pending[1]();pending={} else fire(ready,'OnUpdate') end + local name=ShaguTweaks.PlayerFrameResourcesLayout.name + assert((name.classBackground~=nil)==not noNameColor) + assert(PlayerFrame.name:GetParent()==name) end local parent=PlayerFrameHealthBar:GetParent() local alpha=PlayerFrameHealthBar.alpha @@ -198,6 +202,7 @@ end Check(false,true,false);Check(true,true,false);Check(false,true,true);Check(true,true,true) Check(false,false,false);Check(true,false,true) Check(false,true,false,true);Check(true,true,true,true) +Check(true,true,true,true,true) -- Migration preserves explicit new choices and old health/power positions. local f=assert(io.open(root..'main.lua'));local s=f:read('*a');f:close() local a=assert(string.find(s,' -- Replace detached native bars',1,true)) diff --git a/tests/test_player_frame_options.lua b/tests/test_player_frame_options.lua index c2d4e71..ae29bba 100644 --- a/tests/test_player_frame_options.lua +++ b/tests/test_player_frame_options.lua @@ -5,7 +5,11 @@ ShaguTweaks={T=setmetatable({},{__index=function(t,k) return k end})} function ShaguTweaks.GetGlobalEnv() return _G end function ShaguTweaks:register(module) modules[module.title]=module; return module end function ShaguTweaks.hooksecurefunc(object,name,callback) - if type(object)~='table' then return end + if type(object)=='string' then + local original=_G[object] + _G[object]=function(...) original(unpack(arg));name(unpack(arg)) end + return + end local original=object[name]; object[name]=function(self,a,b,c,d) original(self,a,b,c,d); callback(self,a,b,c,d) end end MAX_PARTY_MEMBERS=0 @@ -24,6 +28,72 @@ this=deferred.frame; deferred.callback(); this=nil local expected='Interface\\AddOns\\ShaguTweaks\\img\\BlizzardRetailBar' assert(PlayerFrameNameBackground.path==expected and TargetFrameNameBackground.path==expected and PlayerFrameHealthBar.path==expected) print('Lua 5.0: matching modern name/health artwork passed') + +local function healthBar() + return { SetStatusBarColor=function(self,r,g,b) self.color={r,g,b} end } +end +local units={player='WARLOCK', pet='WARRIOR', party1='HUNTER', partypet1='WARRIOR'} +function UnitClass(unit) return units[unit],units[unit] end +local targetUnit +function UnitExists(unit) return units[unit=='target' and targetUnit or unit]~=nil end +function UnitIsUnit(first,second) return first=='target' and targetUnit==second end +function UnitIsPlayer(unit) return unit=='party1' end +function UnitIsPet(unit) return unit=='target' and targetUnit=='remotePet' end +function UnitOwnerGUID() return 'owner-guid' end +ShaguTweaks.API={UnitTokenFromGUID=function(guid) if guid=='owner-guid' then return 'party1' end end} +PetFrameHealthBar=healthBar() +PartyMemberFrame1PetFrameHealthBar=healthBar() +TargetFrameHealthBar=healthBar() +TargetFrameHealthBar:SetStatusBarColor(0,1,0) +function TargetFrameHealthBar:GetStatusBarColor() return unpack(self.color) end +MAX_PARTY_MEMBERS=1 +local scripts={} +function CreateFrame() return {RegisterEvent=function() end, SetScript=function(_,k,v) scripts[k]=v end} end +modules['Pets Use Owner Class Color']:enable() +assert(PetFrameHealthBar.color[3]==.93 and PartyMemberFrame1PetFrameHealthBar.color[1]==.67) +PetFrameHealthBar:SetStatusBarColor(0,1,0) +assert(PetFrameHealthBar.color[3]==.93) +targetUnit='pet';TargetFrame_CheckFaction() +assert(TargetFrameHealthBar.color[3]==.93) +-- Big Health captures the setter and applies the faction tint through it. +local bigHealthSetter=TargetFrameHealthBar.SetStatusBarColor +bigHealthSetter(TargetFrameHealthBar,0,0,1,1) +assert(TargetFrameHealthBar.color[3]==.93) +targetUnit='partypet1';TargetFrame_CheckFaction() +assert(TargetFrameHealthBar.color[1]==.67) +units.remotePet='WARRIOR' +targetUnit='remotePet';TargetFrame_CheckFaction() +assert(TargetFrameHealthBar.color[1]==.67) +TargetFrameHealthBar:SetStatusBarColor(0,1,0) +units.npc='WARRIOR' +targetUnit='npc';TargetFrame_CheckFaction() +assert(TargetFrameHealthBar.color[2]==1 and TargetFrameHealthBar.color[3]==0) +units.party1='WARLOCK' +event,arg1='UNIT_PET','party1';scripts.OnEvent() +assert(PartyMemberFrame1PetFrameHealthBar.color[3]==.93) +units.partypet1=nil +PartyMemberFrame1PetFrameHealthBar:SetStatusBarColor(0,1,0) +assert(PartyMemberFrame1PetFrameHealthBar.color[2]==1) + +function UnitReaction() return 5 end +function UnitIsPlayer() return false end +local name={GetFont=function() return 'font',12 end, SetFont=function() end} +PlayerFrame={name=name,CreateTexture=function() + local strip=texture() + strip.SetWidth=function() end;strip.SetHeight=function() end;strip.SetPoint=function() end + strip.Hide=function(self) self.hidden=true end + return strip +end} +TargetFrame={name=name} +TargetFrameNameBackground.Hide=function() end +for _,hide in ipairs({0,1}) do + ShaguTweaks_config={["Player's Name No Class Color"]=hide} + modules['Unit Frame Class Colors']:enable() + assert((PlayerFrameNameBackground.hidden or false)==(hide==1)) + assert(PlayerFrameNameBackground.r==.53) +end +print('Player name and pet options: hidden name strip keeps its class tint for Big Health, pet bars follow their owners') + -- Hiding the player name never affects the grouped player frame. dofile(root..'mods/unitframes-hide-player-name.lua') local nameHidden=false diff --git a/tests/test_quest_parchment.lua b/tests/test_quest_parchment.lua index 4eee592..0b0ce9e 100644 --- a/tests/test_quest_parchment.lua +++ b/tests/test_quest_parchment.lua @@ -14,7 +14,33 @@ function methods:SetHeight(v) self.height=v end function methods:SetPoint(...) self.point=arg end function methods:SetTexCoord(...) self.uv=arg end function methods:SetVertexColor(...) self.color=arg end +function methods:SetDrawLayer(layer) self.layer=layer end local function texture(path,w,h) return setmetatable({path=path,width=w,height=h},{__index=methods}) end + +local spellbookStart=assert(string.find(source,'local spellbookPaper =',1,true)) +local restoreSpellbook=assert(loadstring(string.sub(source,spellbookStart,a-1)..'return RestoreSpellbookParchment'))() +SpellBookPageText=texture() +local spellbook={copies=0} +function spellbook:CreateTexture(_,layer) + self.copies=self.copies+1 + local paper=texture();paper:SetDrawLayer(layer);return paper +end +for _,suffix in ipairs({'TopLeft','TopRight','BotLeft','BotRight'}) do + local left=string.find(suffix,'Left',1,true) + local top=string.find(suffix,'Top',1,true) + local tile=texture('Interface\\Spellbook\\UI-SpellbookPanel-'..suffix,left and 256 or 128,256) + restoreSpellbook(spellbook,tile) + restoreSpellbook(spellbook,tile) + local paper=assert(tile.stSpellbookPaper) + assert(paper.path==tile.path and paper.color[1]==1 and paper.color[4]==1) + assert(paper.width==(left and 234 or 85) and paper.height==(top and 182 or 175)) + assert(paper.point[2]==tile and paper.point[4]==(left and 22 or 0) and paper.point[5]==(top and -74 or 0)) + assert(tile.layer=='BORDER' and paper.layer=='ARTWORK' and SpellBookPageText.layer=='OVERLAY') +end +restoreSpellbook(spellbook,texture('Interface\\Spellbook\\Spellbook-Icon',58,58)) +assert(spellbook.copies==4) +assert(not string.find(source,'["^SpellBookFrame$"]',1,true)) + for _,name in ipairs({'GossipFrameGreetingPanel','QuestFrameGreetingPanel','QuestFrameDetailPanel','QuestFrameProgressPanel','QuestFrameRewardPanel'}) do local regions={} for _,suffix in ipairs({'TopLeft','TopRight','BotLeft','BotRight'}) do diff --git a/tests/test_ui_palette.lua b/tests/test_ui_palette.lua index ed5248d..12c452c 100644 --- a/tests/test_ui_palette.lua +++ b/tests/test_ui_palette.lua @@ -61,3 +61,23 @@ helpers[3](parent) helpers[4](probe) assert(not matches('TrinketMenu_MainFrame')) print('Active palettes: TrinketMenu recursive, persistent-hook and minimap recoloring paths are excluded') + +local function texture(path) + return { GetTexture = function() return path end, + SetVertexColor = function(self, r, g, b) self.color = {r, g, b} end } +end +for _, name in ipairs({"TrinketMenu_IconFrame", "OutfitterMinimapButton"}) do + local normal, pressed = texture(), texture() + helpers[4]({ + GetName = function() return name end, + GetNormalTexture = function() return normal end, + GetPushedTexture = function() return pressed end, + GetRegions = function() error("Only the baked button artwork should be tinted") end, + }) + assert(normal.color[2] == .78 and pressed.color[3] == .4) +end +local atlasIcon = texture("Interface\\WorldMap\\WorldMap-Icon") +local atlasRim = texture("Interface\\Minimap\\MiniMap-TrackingBorder") +helpers[4]({GetName = function() return "AtlasCFMMinimapButton" end, + GetRegions = function() return atlasIcon, atlasRim end}) +assert(not atlasIcon.color and atlasRim.color[2] == .78)