Skip to content

fix(cdm): apply Custom Icon to aura-tracked custom buffs - #2082

Open
wanghws wants to merge 1 commit into
EllesmereGaming:mainfrom
wanghws:fix/cdm-aura-custom-icon
Open

fix(cdm): apply Custom Icon to aura-tracked custom buffs#2082
wanghws wants to merge 1 commit into
EllesmereGaming:mainfrom
wanghws:fix/cdm-aura-custom-icon

Conversation

@wanghws

@wanghws wanghws commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

A Custom Spell ID on a Buffs bar offers Add Custom Icon in its right-click menu, but
the icon never changed: the buff kept showing its own art (screenshots below).

Cause. A custom spell ID on a buffs-family bar has no stored duration, so it is not a CDM
frame at all -- it renders in the engine aura container hung off the bar's end (_AC in
EllesmereUICdmHooks.lua). ApplyCustomIcon only stamps claimed CDM frames and our own injected
frames, so it never reaches these buttons. #1425 recorded the underlying limit: one engine group
renders every custom aura on the bar, and while auras are secret Lua cannot tell its buttons
apart, so per-spell settings have nowhere to land.

Fix. A spell that has a Custom Icon gets a single-spell group of its own in the same
container. Every button in that group is then known to hold that spell without reading the
aura, so the group's style can carry the art:

  • The style hides the engine-stamped icon (the same SetShown + alpha pair Only Show Numbers
    already uses) and shows a texture of our own in its place. The texture is created in the
    button's creation window (_AC.InitExtra, the only place a region may be parented to an engine
    aura button) and anchored to the icon, so shape masks, zoom crop, Cropped and Only Show Numbers
    all follow it.
  • Which spells carry a Custom Icon is part of the container's structural signature; the fileID
    is not. Re-picking an icon restyles that group in place (_AC.SyncFixedIcons) instead of
    rebuilding, because a rebuild abandons the old container and its engine-created group buttons
    can never be freed (AK.ReleaseContainer). Styles of groups a rebuild drops are removed from
    AK.styles.
  • The Custom Icon popup's confirm now also runs UpdateCustomBuffAuraTracking: the reanchor it
    already queued never reaches the container.

Notes:

  • Nothing changes for a bar with no Custom Icon on an aura-tracked custom: it keeps the single
    shared group and the exact signature it had, and the per-spell resolve is gated on
    ns._cdmAnyCustomIcon.
  • A split-out spell flows after the bar's other custom auras (the engine lays groups out in
    order).
  • A split does not grow the per-build button count: AuraKit notes group pools are sized at 10x
    their visible count, and the split moves one visible slot from the shared group to the new one.
  • The other per-spell rows in this menu (Buff Glow, Border, Reverse Swipe, ...) still do not
    reach these icons and are out of scope here; the audio cues are covered separately by CDM: play buff gain/loss audio cues for aura-tracked custom buffs #1712.

How was it tested?

Tested in-game on live against this checklist:

  • Custom Spell ID on a Buffs bar, Add Custom Icon 461860: the aura renders with the custom art
    while active.
  • In combat and in M+ (auras secret): the custom art holds through aura refreshes and stack
    changes.
  • Bar icon shape, Cropped and Only Show Numbers: the custom art follows each.
  • Re-picking a different icon two or three times in a row: each applies immediately.
  • Clearing the Custom Icon: the aura reverts to its own art.

Screenshots

Before -- Custom Icon 461860 saved for the spell, the buff still shows its own art:

before: Custom Icon popup

before: buff keeps its own art

After -- the buff shows the custom art:

after: buff shows the custom icon

Checklist

  • New settings default OFF -- N/A: no new setting; an existing per-spell setting now takes
    effect where it was silently ignored
  • Zero cost while disabled: the per-spell resolve runs only once ns._cdmAnyCustomIcon is
    set, and bars without a Custom Icon on an aura-tracked custom keep the exact container and
    signature
  • Cheap while enabled: no events, polling or timers added; allocation only when the container
    is (re)built or restyled, never per aura event or per frame
  • No writes onto Blizzard-owned frames: only regions on AuraKit engine buttons we build, in
    their creation window; no hooks added
  • Tested in-game on live; no version gates or pre-Midnight APIs added

https://claude.ai/code/session_01NYsCUA5DSWPU1wHWFZv2p7

A Custom Spell ID added to a Buffs bar has no stored duration, so it renders
through the engine aura container (_AC) rather than a CDM frame, and
ApplyCustomIcon never reaches it. The right-click menu still offered Add
Custom Icon for these entries, so the setting saved and nothing changed.

EllesmereGaming#1425 noted that per-spell settings cannot reach these icons: one engine
group renders every custom aura on the bar, and while auras are secret Lua
cannot tell its buttons apart. A spell with a Custom Icon now gets a
single-spell group of its own in the same container, so every button in
that group is known to hold that spell without reading the aura. Its style
hides the engine-stamped art (the same SetShown + alpha pair Only Show
Numbers uses) and shows a texture of our own, created in the button's
creation window and anchored to the icon so shape masks, zoom crop and Only
Show Numbers follow it.

Which spells carry a Custom Icon is part of the structural signature; the
fileID is not. Re-picking an icon restyles that group in place, because a
rebuild abandons the old container and its engine-created group buttons can
never be freed. Styles of groups a rebuild drops are cleared from AK.styles.

Bars with no Custom Icon on an aura-tracked custom keep the single shared
group and the exact signature they had: the per-spell resolve is gated on
ns._cdmAnyCustomIcon. The options callback also runs the aura-tracking sync
now, since the reanchor it already queued never reaches the container.

Claude-Session: https://claude.ai/code/session_01NYsCUA5DSWPU1wHWFZv2p7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant