Commit Graph

8 Commits

Author SHA1 Message Date
Narcasung 63e179e96e Keep the scroll arrows skinned when the list refreshes
The scroll frame re-shows the button's own native art whenever it
recalculates, and one skinning pass can't hold against it: ElvUI's
HandleNextPrevButton guards on isSkinned, so a second call does nothing.

The talent frame already carried the answer -- re-hide the art by file
from OnUpdate and pin the three state textures -- so it moves into the
shared layer as Skin:ScrollArrow and the Challenges list scrolls take it
too. Routing the talent frame through it also picks up the
disabled-hover fix every other button already has.
2026-08-22 16:59:59 +02:00
Narcasung a8541fa1ee Skin the Challenges window, its tab row and the Trials tab
ChallengesFrame is a HIGH-strata window parented straight to UIParent and
mouse-enabled itself, not one of the three that hang off the Collections
container -- so it gets its own module and its own enable switch rather
than joining the collections group, and it deliberately skips
ApplyWindowScale and CollectionTabs: the first scales Collections, which
would resize the other three windows and not this one, and the second
skins the tab row those three share.

The panel is built as a backdrop instead of through SetTemplate. A
template's backdrop is drawn as regions of the frame and can only match
its rect, and the title sits above that rect -- the native art carries a
banner up there -- so a panel sized to the frame left the title floating
over the open world. A backdrop has points of its own, so its top edge is
pushed up over the title, measured live rather than hardcoded, with the
hit rect and the close button following it. The nine-slice is stripped
rather than run through HideArt for a related reason: the title is one of
its regions, and Hide() would take it down with the border.

The tab row is the first stock Blizzard flavour the plugin skins, so the
shared layer grows to cover it. TAB_TEXTURES picks up the Middle pieces
those name their body after, and the OnUpdate art re-check watches the
Disabled set as well -- that pair is how a stock tab draws its selected
state, so watching only the inactive half missed art returning on
whichever tab was open. Native panel tabs also interlock, each anchored
16px back into the one before it so the ornate end caps overlap, which
reads as one merged bar once the art is gone; the overlap is absorbed by
narrowing each tab rather than by spacing the row out, which would have
grown it 80px past a frame with 16px of slack. The row is pulled up flush
against the panel it belongs to, since the native tops that spanned that
gap went with the art.

Inside the Trials tab: the search box, the filter dropdown and the scroll
bar. The dropdown is the same widget as the vanity and wardrobe ones and
takes the existing handler unchanged. The search box needs its border
cleared by file, not stripped -- an EditBox draws its caret and selection
highlight as plain textures of its own, and a blind strip leaves a box
you can type in with no cursor in it.

The scroll bar needed a handler of its own. HandleScrollBar reaches for
the thumb through GetThumbTexture and then calls SetTexture on it, but
these bars are hand-built: the thumb is a Button with art of its own, and
the arrows are named off the scroll frame rather than off the bar, so it
finds neither. Both pieces are also arted lazily -- at skin time their
textures read back nil, which is why clearing them, noop'ing their
SetTexture and alpha'ing them all failed in turn -- so the art is
suppressed from OnUpdate, the same answer the tab art needed. Colours
follow ElvUI's own proportional scroll bars, and the track is left empty
rather than given a backdrop.
2026-08-22 16:32:37 +02:00
Narcasung 919feed322 Strip the native hover glow from every skinned button
HandleButton clears a button's own Normal/Highlight/Pushed/Disabled textures
and the named Left/Middle/Right pieces, so a native highlight drawn as a plain
region of the button survives it and lights up under the cursor against the
flat backdrop. Clearing the wardrobe Cancel button's by file fixed that one
button and nothing else: probing the HIGHLIGHT layer across everything the
plugin skins turned up Save outfit wearing the same red file, and Disable
transmog and Disable spell visuals wearing the dialog-box glow, none of which
any clear-by-file call site was ever going to reach.

The whole layer goes rather than named files. On these frames it only ever
carries native hover art -- every button probed has exactly one HIGHLIGHT
region, blank on the ones that already looked right, so there is nothing else
there to lose. ElvUI's own hover treatment is untouched: it is the backdrop
border swap HandleButton hooks, and a backdrop is drawn through SetBackdrop
plus two child border frames rather than as a region of the button.

Cleared from Skin:Button, so every call site in the plugin inherits it, and
unguarded so a region added after the first skin pass is caught too. SetTexture
is noop'd per region as StripArtByFile does, or a state change that re-arts the
button would bring the glow straight back.
2026-08-18 16:43:31 +02:00
Narcasung d2e55eb3cb Stop disabled buttons taking the hover border colour
S:HandleButton ends with an unconditional OnEnter/OnLeave pair that swaps
the border to the value colour and back, and neither handler looks at
IsEnabled. A disabled button still fires both scripts on this client, so
the greyed Activate button, Save changes with nothing pending and Purchase
with nothing selected all lit up under the cursor and read as clickable.

HookScript can't be undone, but handlers fire in registration order, so a
hook registered after HandleButton runs last and has the final say on the
colour. Skin:Button wraps HandleButton with that hook, and every call site
in the plugin now goes through it, so the correction is inherited rather
than repeated per module.

The Activate button carries the border from its own update as well:
activating a spec disables it under the very cursor that just clicked it,
and OnEnter has been and gone by then, so nothing else would put the border
back until the pointer moved off.

Skin:IsEnabled hoists the 0/1-to-boolean normalisation this client needs
out of UpdateActivateState, which held the only copy of it.
2026-08-18 16:30:27 +02:00
Narcasung cddfc7e7af Skin the Apply and Cancel buttons on the wardrobe model
Both only exist while a transmog change is pending, which is why every
earlier pass over the frame missed them -- it was always skinned in its idle
state -- so they still wore their native green and red pills against an
otherwise flat window.

They are the same widget as the specialization menu's Activate button: no
Normal/Pushed texture for HandleButton to clear, the pill drawn across plain
regions from an atlas. Two files, not one -- Apply takes the green variant of
128GoldRedButton, Cancel is drawn from 128RedButton, HIGHLIGHT region and all,
which is what left a red glow under the cursor once only the gold file was
being cleared. The shared "RedButton" suffix matches both. Their labels take
ElvUI's yellow rather than carrying the atlas's green/red split over: the two
sit side by side and read apart by their text.

The buttons exist from the start rather than being created on the first
pending change, so the normal skin pass reaches them, but the art is only
there to be cleared once a change is pending -- and nothing fires the frame's
OnShow at that point, since the window is already open. The buttons' own
OnShow catches it instead.

The clear-by-file loop the Activate button and the dropdown pills had a copy
of each now lives in Skinning.lua as Skin:StripArtByFile, with the atlas name
alongside it.
2026-08-18 16:29:12 +02:00
Narcasung 01f1f5c7c3 Centre wardrobe tab labels and name the skin for what it covers
The label nudge in the shared tab handler exists to clear the icon on the
talent window's tabs, where the native anchor sits tight against it and
grown text would collide. The wardrobe's category tabs carry no icon and
centre their label, so the same nudge pushed every one of them off to the
right. It's now applied only to tabs that actually have a visible icon.

The settings entry covers three windows, so it's named for all three:
Advancement/Vanity/Wardrobe. The keys behind it move with it -- the db
table is skins.collections, after Collections, the container the three
windows and the tab row all hang off, and talentScale becomes
advancementScale. Nothing here has been released, so there's no stored
setting to migrate.
2026-08-17 22:41:25 +02:00
Narcasung 964f88559d Add a Talents skin entry with an enable switch and per-window scale
The talent window, the Vanity and Wardrobe windows it switches between and
the tab row along its bottom are one feature to the player, so they get one
entry in the Skins tree and one master switch gating all three
Initialize calls together. Skinning one of them without the others reads as
a bug.

Scale is a slider per window, 0.5 to 1.5, applied as a multiplier on the
existing scale rather than an absolute -- the three don't ship at the same
size (the vanity store's frame runs about 9% larger than the others), and
that is the server's choice to keep. A setting of 1.0 leaves everything
exactly as it was.

The scale is set on Collections, not on the window itself. All three
windows and the tab row are its children, and it is the only one of them
with mouse enabled -- it is what the player drags. Scaling a window
directly left the drag target at full size, so a shrunk window had to be
grabbed by clicking outside itself, and the tab row, not being a child of
any window, kept whichever size the first-opened one gave it. Scaling the
container moves its hit area with it and the tabs follow as children.
2026-08-17 22:37:53 +02:00
Narcasung 766e561839 Share one skinning path across the three CoA frames
The talent, vanity and wardrobe frames are built from the same handful of
widget templates, but each module carried its own copy of the handling:
close buttons, panels, dropdown pills, tabs and the ADDON_LOADED loader
were all written out three times. The copies had drifted -- tab backdrop
insets of 3 against 2, tabs grown in one frame and not the other, the
wardrobe clearing only three of the six tab textures -- and that drift is
what reads in-game as the same control looking different depending on which
tab you're on.

Modules/Skinning.lua now owns each of those behaviours once, and the three
modules call into it. Where the copies disagreed the values are unified;
tab growth is gated on the tab actually having a label, since growing an
icon-only tab just pushes its icon off the layout, and the SetChecked hook
is guarded because hooksecurefunc errors outright on a missing method.

Titles are pinned to Arial Narrow at 13: the vanity store titled in Friz
Quadrata while the other two used Arial Narrow. Frame scale is left as the
server set it, so the vanity title still renders slightly larger than the
others.

Two things deliberately not shared: the vanity frame still skips
StripTextures, since its currency counters are regions of the frame itself,
and the talent frame's bottom-bar dropdowns stay on their own path -- they
are a different widget, a native dropdown plus a separate caret button.
2026-08-17 22:19:50 +02:00