Skip to content

Action Palette: a hold-and-release action picker - #1239

Open
nulltyto wants to merge 3 commits into
EllesmereGaming:mainfrom
nulltyto:feat/action-palettes
Open

Action Palette: a hold-and-release action picker#1239
nulltyto wants to merge 3 commits into
EllesmereGaming:mainfrom
nulltyto:feat/action-palettes

Conversation

@nulltyto

@nulltyto nulltyto commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Supersedes #1187: same feature, rebuilt as three commits on current
main with the review feedback folded in. Notable differences from that
PR: the master switch now defaults off, the Popout grid nest style
was removed (it converged with Lane in behavior), and nested palettes
now contribute all 12 of their entries except where the nest is
bounded by its parent's own region (an arc's sector, a halo's ring of
eight), which keeps the 8-entry cap.

What does this PR do?

Adds a new optional child addon, EllesmereUI Action Palette. The player
holds a keybind to open a palette of up to 12 actions, points or
scrolls to choose, and releases the key to fire. Palettes come in
grid, arc and fan layouts, can nest one level, and work in combat:
selection and firing run inside secure snippets, so no insecure code
touches protected state during lockdown.

Slots hold spells, items, toys, mounts, pets, macros, world markers
and equipment sets. A settings page with a live preview covers slot
assignment (drag to reorder, category picker, presets), per-palette
shape and appearance, and one keybinding per palette.

Everything is opt-in: the master switch defaults off, and with the
module disabled no events are registered, no override bindings exist,
and no secure buttons are built. Even when enabled, nothing exists
until a palette key is bound.

Also included:

  • .tools/palette-nest/: an offline harness that executes the real
    WrapScript/snippet plumbing and checks the secure and insecure
    sides agree about nest arming and teardown. .pkgmeta already
    ignores .tools, so it never ships. Happy to drop it from the PR
    if you prefer no dev tooling in-tree.
  • One small widget-layer change: BuildCogPopup rows accept a
    noCapture flag (same flag DualRow already honors) so a popup
    can mix capturing and non-capturing rows.

Two known deviations, called out rather than hidden:

  • One frame (the palette live view) is created at file scope while
    the module is disabled. This is deliberate: a frame created inside
    OnEnable is billed by the CPU profiler to the loading addon, and
    the in-source comment explains it. Its handlers do nothing while
    disabled.
  • The sixteen keybinding rows appear in the Key Bindings panel even
    while disabled. Gating them on the enable switch would make it
    impossible to bind a key before enabling.

How was it tested?

  • Live retail client (12.0.x): tested in dungeon and follower dungeon w/ dev mode
  • The offline nest harness passes (ALL AGREE) across the arming,
    handoff and teardown paths, including icon-overlap sweeps of every
    layout/nest-style/scale combination.
  • luac5.1 -p clean on both module files.
  • PTR 12.1: NOT YET TESTED

Checklist

  • New settings default OFF (master switch enabled = false;
    the palette cannot open without both enabling and binding a key)
  • Zero cost while disabled: no events registered, no polling, no
    hooks doing work, no secure buttons or bindings built (one inert
    file-scope frame, explained above)
  • Cheap while enabled: event-driven; the only OnUpdate runs while
    a palette is held open and stops with it
  • No writes onto Blizzard-owned frames; the module only touches
    its own frames (secure buttons, gates, catcher are all
    addon-created; Blizzard code is never SetScript'd)
  • Tested in-game, works on live retail; no load errors on the
    12.1 PTR client [FILL IN after live pass]

Hold a keybind to open a palette of up to 12 actions; point or scroll
to choose, release to fire. Palettes come in grid, arc and fan
layouts, can nest one level through a dedicated entry, and stay fully
usable in combat: selection and firing run inside secure snippets, so
no insecure code touches protected state during lockdown.

The module costs nothing while disabled: the master switch defaults
off, no events are registered, and no override bindings or secure
buttons exist until the module is enabled and a palette key is bound.

Slots hold spells, items, toys, mounts, pets, macros, world markers
and equipment sets. World markers place in the engine order, mounts
can roll the journal's own random favorite, and entries show stack
counts, charges, cooldowns and usability tints.

The module folder keeps a vestigial RadialWheel SavedVariables name
from its development history; migration moves that data to the new
key and the second name can be dropped one release later.
A settings page with a live palette preview: drag to reorder slots, a
picker with category folders for every slot kind, per-palette shape,
position and appearance, preset palettes for a quick start, and cog
popups for the power knobs. Palettes each get a keybinding row, and
markers get their own picker category.

BuildCogPopup gains a per-row noCapture flag so a popup can mix
profile-wide rows that join the capture group with per-palette rows
that must not.
An offline harness that executes the module's real WrapScript and
snippet plumbing outside the game and checks that the secure and
insecure sides agree about arming, handoff, ownership and teardown
across the nest paths. Run from EllesmereUIActionPalette/:

    lua ../.tools/palette-nest/nest_agree.lua . 3

The .pkgmeta ignore list already excludes .tools from packaging.
@nulltyto
nulltyto force-pushed the feat/action-palettes branch from 0605be4 to c39df7e Compare August 7, 2026 04:56
@nulltyto
nulltyto marked this pull request as ready for review August 7, 2026 05:01
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