local E, L, V, P, G = unpack(ElvUI) local S = E:GetModule("Skins") local CoA = E:GetModule("CoA") local Skin = CoA.Skin local FRAME_NAME = "AppearanceWardrobeFrame" -- Standard UIPanelButtonTemplate art, same as Vanity's action buttons -- -- S:HandleButton's own texture clearing handles these directly. local function SkinActionButtons() S:HandleButton(_G[FRAME_NAME.."PlayerModelSaveOutfitButton"]) S:HandleButton(_G[FRAME_NAME.."DisableTransmogButton"]) S:HandleButton(_G[FRAME_NAME.."DisableSpellVisualsButton"]) end local function SkinSearchBox() S:HandleEditBox(_G[FRAME_NAME.."CollectionSearchBox"]) end -- suffix is "Filter" or "Sorting" -- both are CollectionX buttons with a -- matching CollectionXMenu popout (confirmed by probe), and both are the same -- widget as the vanity frame's single dropdown, so both go through the shared -- handler. local function SkinCollectionDropdown(suffix) Skin:Dropdown(_G[FRAME_NAME.."Collection"..suffix], _G[FRAME_NAME.."Collection"..suffix.."Menu"]) end local function SkinPagerArrows() local prevButton = _G[FRAME_NAME.."CollectionPageLeftButton"] local nextButton = _G[FRAME_NAME.."CollectionPageRightButton"] if prevButton then S:HandleNextPrevButton(prevButton, "left") end if nextButton then S:HandleNextPrevButton(nextButton, "right") end end -- Same art naming as the talent frame's tabs (confirmed by probe), so they go -- through the same shared handler. No level parent is passed: these are proper -- descendants of Collection rather than separately-placed siblings, so normal -- parent/child z-order already puts them above the panel and the frame-level -- bump the talent tabs need doesn't apply. -- -- Named PoolFrameAppearanceTypeTabTemplate1 through 8 (confirmed by probe), -- not pooled/created dynamically like the talent frame's spec choices, so a -- plain indexed loop is enough -- no OnShow hook needed to catch late pool -- fills. local TAB_COUNT = 8 local function SkinCategoryTabs() for i = 1, TAB_COUNT do Skin:Tab(_G[FRAME_NAME.."CollectionPoolFrameAppearanceTypeTabTemplate"..i]) end end local function SkinContents() -- Scale is set on the shared container while this window is the open one, -- which carries the tab row along with it (see Skinning.lua). Skin:ApplyWindowScale("wardrobeScale") Skin:CollectionTabs(_G[FRAME_NAME]) Skin:Title(_G[FRAME_NAME.."TitleText"]) Skin:CloseButton(_G[FRAME_NAME.."CloseButton"]) SkinActionButtons() SkinSearchBox() SkinCollectionDropdown("Filter") SkinCollectionDropdown("Sorting") SkinPagerArrows() SkinCategoryTabs() end local function SkinFrame(frame) if not frame.CoASkinned then frame.CoASkinned = true -- The native NineSlice panel draws its own ornate border/background on -- top of the Transparent template's border, doubling up. Same fix as -- the talent frame: strip and hide it. Skin:HideArt(_G[FRAME_NAME.."NineSlice"]) -- The round medallion overhangs the top-left corner (confirmed by -- probe: 61x61, TOPLEFT -6,8 -- matches the frame's own corner, not a -- counter badge elsewhere, unlike Vanity's same-named "Portrait2" -- texture). No flat equivalent, so it goes rather than getting -- reskinned, same treatment as the talent frame's portrait. Skin:HideArt(_G[FRAME_NAME.."PortraitFrame"]) -- The frame's own regions (confirmed by probe: 4 total, all BACKGROUND/ -- BORDER/OVERLAY textures, none of them functional -- unlike Vanity's -- frame, nothing here doubles as a counter badge) are the wood-panel -- background art, so this one is safe to strip before templating. Skin:Panel(frame) -- InsetOverlay's NineSlice and the ShadowOverlay are separate decorative -- art layered over the item grid area (8-piece atlas borders/shadow -- edges, confirmed via probe), stripped outright -- no functional -- content lives on either. Skin:HideArt(_G[FRAME_NAME.."CollectionInsetOverlayNineSlice"]) -- The actual panel behind the grid: Collection itself (confirmed via -- /fstack -- InsetOverlay was the wrong target, its own rect doesn't -- match the visible panel). Collection is the grid's real parent, so -- no frame-level/strata juggling needed -- children always draw above -- their own parent. -- -- 16 of its own regions turned out to hold real art -- a background -- tile plus ~14 atlas border/corner pieces (the ornate corners -- /fstack couldn't ever pick out, since loose regions aren't frames -- and don't show up there) -- none of it functional (the "Collected -- 50/2744" counter is a separate FontString region, untouched by -- StripTextures). Painting an opaque/red template over it earlier -- just masked it; it was still there underneath, which is why -- Transparent let it bleed back through. Strip first, then template, -- same order as the outer frame -- SetTemplate's own WHITE8X8 backdrop -- pieces land as regions on this same frame too, so stripping after -- would wipe them right back off. Skin:Panel(_G[FRAME_NAME.."Collection"]) -- The 3D model preview's vanilla border is an anonymous child (first -- of PlayerModel's own, confirmed by probe: 8-piece "UIFrame" atlas -- border, sized to match the model panel). No name to key off of, same -- as Vanity's pager arrows -- picked out positionally instead. The -- race-specific scenic backdrop texture is PlayerModel's own region, -- not this child's, so it's untouched. local playerModel = _G[FRAME_NAME.."PlayerModel"] local modelBorder = playerModel and select(1, playerModel:GetChildren()) if modelBorder and modelBorder:GetObjectType() == "Frame" then Skin:HideArt(modelBorder) end Skin:HideArt(_G[FRAME_NAME.."CollectionShadowOverlay"]) frame:HookScript("OnShow", SkinContents) end SkinContents() end local function TryHook() local frame = _G[FRAME_NAME] if not frame then return false end SkinFrame(frame) return true end function CoA:InitializeWardrobeFrame() if not E.private.skins.blizzard.enable then return end Skin:OnFrameAvailable(TryHook) end