10 Commits

Author SHA1 Message Date
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 1a62b4ed1f Skin the options the CoA client adds to Interface, Video and Audio
ElvUI skins the stock options windows from four hardcoded name lists, so
every widget the client added since upstream last synced stays native --
53 of them here, 39 in four panels upstream never enumerated at all
(Battlenet, RaidEffects, Stereo, Voice). Reported cases were the Auto
Accept Trades checkbox and the Spell Queue Window slider.

Sweep the three panel containers on show and skin by object type instead
of carrying a parallel name list that would go stale the same way.

Panels belonging to other addons are skipped by matching frames against
INTERFACEOPTIONS_ADDONCATEGORIES, rebuilt on every sweep so a
load-on-demand addon that registers late is still caught.

Two guards worth naming. Sliders are gated on frame.template because
HandleSliderFrame has no idempotence check of its own and HookScript
stacks, so a second pass over one ElvUI already skinned would run its
OnDisable/OnEnable handlers twice. Dropdowns are detected structurally,
by a Middle texture plus a Button, because HandleDropDownBox uses that
button unguarded and a false positive is a Lua error rather than a
cosmetic miss.

No Button branch: nothing needs one, and it would flatten other addons'
panel tabs into ElvUI pill buttons.
2026-08-22 15:57:21 +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
Narcasung dc263a2419 Skin the CoA Wardrobe tab (AppearanceWardrobeFrame)
Outer panel, close button, and the top-left portrait medallion get the
same first-pass treatment as Vanity/Talent, plus the item collection
panel: native background/border art stripped from Collection and its
InsetOverlay/ShadowOverlay decoration, the 3D model preview's vanilla
border removed, and the action buttons, search box, Filter/Order By
dropdowns, page arrows, and category tabs skinned to match.

Left native for a later pass: the icon grid contents, item slot
buttons, and character model itself.
2026-08-17 21:54:30 +02:00
Narcasung b14753491c Skin the CoA Vanity tab (StoreCollectionFrame)
Skins the outer window, close button, search box, Filter dropdown
(and its arrow and popup panel), Purchase/Deliver buttons, and the
grid pager arrows. Removes nothing else -- the portrait originally
suspected at the top-left corner turned out not to exist as a
separate element, and the card grid/preview panel are left native.
2026-08-17 20:17:25 +02:00
Narcasung 0b9b0c5afa Skin the CoA talent frame's Character Advancement tab
Flattens the custom talent window into the ElvUI look: frame chrome, close
buttons, tabs, bottom bar, dropdowns and their popups, the list scrollbars,
and the spec choice cards' action buttons. The talent tree itself is left
alone -- its node borders encode rank and availability.

Most of the work is in keeping the skin applied. The frames restore their
native art on refresh in three different ways, and none of them fire an
event to hook:

- The scroll arrows re-show a region StripTextures had hidden, so the arrow
  buttons re-hide it from their own update, matching by file so ElvUI's
  panel pieces (which are regions of the same button on this client) survive.
- The pooled menu rows put their hover and selection art back when a scroll
  refills them, without firing OnShow, so the strip runs from the row update
  behind a cheap texture compare.
- The talent frame's close button keeps its absolute frame level while
  TreeView rides along when the frame is raised, so the level bump re-applies
  on every show.

Row fills and the selection edge are textures on the row rather than an ElvUI
backdrop: the backdrop is a child frame and covered the row's icon and text at
every frame level available to it.
2026-08-17 17:15:29 +02:00
Narcasung 97c4defa51 Add Class Resources and Debuff Highlighting modules; migrate settings to AceDB profiles
Move CoA settings from E.global/E.private into a proper AceDB-3.0 database
(CoA.db, SavedVariables ElvUI_CoADB) with a Profiles options tab, since
ElvUI doesn't ship AceDBOptions-3.0 (vendored under Libraries/).

Add ClassResources.lua: hooks the custom-class resource frames (segment
bar, orb, bar, multi-cast bar) into ElvUI's Toggle Anchors, with a
per-frame hide checkbox in a new "Class Resources" options tab.

Add DispelHighlight.lua: highlights dispellable debuffs on unitframes,
with talent-aware filtering for custom classes.

Fix mover/anchor reliability for Class Resources and the Instance
(LayerPicker) button:
- Movers were only retried until the target frame existed, not until the
  mover was actually created, so frames that start at zero size (e.g. a
  resource bar before that resource is ever active) permanently lost
  their mover.
- Class resource frames re-anchor themselves on refresh, stomping the
  mover's anchor; hook SetPoint to snap back to the mover holder whenever
  something else repositions the frame.
- Native click-drag on these frames ends with the engine calling SetPoint
  directly, severing the mover anchor entirely. Permanently block drag
  (script and RegisterForDrag) instead of clearing it once.
2026-07-16 15:24:12 +02:00
Narcasung d5b67920a6 Add Extra Action Button keybind with hotkey text, resizable size slider, and recentered anchor 2026-07-13 18:11:07 +02:00
Narcasung 619c913d1e Add LayerPickerFrame skinning with Instance toggle
Strips the native tooltip-style backdrop pieces off the LayerPickerFrame button and applies the ElvUI backdrop/button style, gated by a new Instance checkbox in the Skins tab.
2026-07-13 15:22:39 +02:00
Narcasung 8beb36e57e Initial commit: ElvUI_CoA plugin
Skins/hides custom CoA-server frames not covered by stock ElvUI, starting with the ExtraActionBar.
2026-07-13 15:03:05 +02:00