- a tooltip change costs ~1.3 ms — five whole-interface recomputes, each working as designed: the quad re-convert at 474 µs, the Lua tick at 287, the layout resolve at 200, bevy's `Assets<Mesh>` tax at ~270 and the mesh rebuild at 146 — pinned with new hover probes (a jitter dial, a `WOW_PROBE_HOVER_DUTY` duty cycle so run drift cancels, an `AssetChanged` tax meter), and the layout preamble's two whole-roster scans become lists maintained at the writer (52–83 µs → 1–11) - the splice compared this frame's entries against last frame's by index, so one inserted highlight shifted the 160 entries behind it and read as "everything changed"; it now aligns on `z` — an identity, not a position — and a `Text` entry that writes only quads became spliceable, so a tooltip change re-converts 22 entries instead of 520 (`convert` +439 µs → +107), with `WOW_UI_SPLICE_VERIFY` running the full conversion behind every spliced frame: 0 mismatches over 1,078 - a spell-less macro is a usable action button, not the 0.4 grey — the reference's usable compute has a dedicated leg answering usable for the bound-spell zero, cross-checked at the bytes in the reference's disassembly — and the button's Name line is written unconditionally from `GetActionText` as the reference does, so the macro's name sits under its icon and a `/cast` of a spell the character does not know now greys, which is also 1.12's behaviour (B340) - a capture bounds its run in wall-clock seconds, because a frame cap is no cap at the ~1 fps a starved `nextDrawable` leaves — 1800 frames is thirty minutes there — and the teardown backstop runs on every run as a liveness guarantee, carrying the exit code the run asked for; the Multisampling row reads Off / 2x / 4x, since "1x" contradicts the no-multisampling byte both of the reference's enumerators normalise to and the bit-depth prefix was identical on every row Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2316 lines
146 KiB
XML
2316 lines
146 KiB
XML
<Ui>
|
||
<!--
|
||
benilla's main action bar, RE-SKINNED to the real 1.12 MainMenuBar (decision 0068 slice-1;
|
||
dressing arc, decision 0084). The geometry + art below are QUOTED from the real FrameXML
|
||
(scratchpad refs, line citations inline): ref-MainMenuBar.xml (the bar art, end caps, XP bar),
|
||
ref-ActionBarFrame.xml (the 12-button anchor chain + page buttons), ref-ActionButtonTemplate.xml
|
||
(the button template). The Lua data flow is UNCHANGED — the vanilla page formula, the
|
||
ACTIONBAR_SLOT_CHANGED repaint, HasAction/GetActionTexture in, UseAction out.
|
||
|
||
Structure mirrors the real hierarchy so the draw order falls out of the frame tree:
|
||
MainMenuBar (1024x53, BOTTOM of screen)
|
||
├─ MainMenuExpBar (StatusBar, TOP) — drawn first ⇒ lowest
|
||
│ ├─ ExhaustionLevelFillBar (BORDER) — the pale rested wash up to the tick
|
||
│ └─ MainMenuBarOverlayFrame (DIALOG) — the hover "curr / max" numerals
|
||
├─ MainMenuBarArtFrame (fills the bar) — dwarf strips + end caps over the XP bar
|
||
│ └─ 12 buttons + page up/down — child frames ⇒ over the art
|
||
└─ ExhaustionTick (DIALOG) — the rested-boundary marker on the strip
|
||
(The real client gets the same order via RaiseFrameLevel(MainMenuBarArtFrame); our loader's
|
||
later-sibling-is-higher + child-over-parent rules reproduce it without the explicit raise.)
|
||
|
||
SCOPE / real-client divergences (noted, not bugs):
|
||
- No frame scale: the real bar is UIParent-scaled; we render 1:1. Geometry is otherwise exact.
|
||
- Page up/down page the bar for real (`CURRENT_ACTIONBAR_PAGE`, below) and the numeral
|
||
follows through `ChangeActionBarPage`, not through the ref's ACTIONBAR_PAGE_CHANGED —
|
||
which we never fire, so an addon LISTENING for the page change hears nothing (it is a
|
||
Rust-side event with no Lua producer). Addons that drive paging call the verb.
|
||
- HotKey renders the LIVE binding label, abbreviated the ref's own way since 1008
|
||
(GetBindingText(key, "KEY_", 1) — UIParent.xml carries our own version; "s-2" for
|
||
SHIFT-2, "·" for a 2+-modifier chord). A slot with NO binding wears the ref's
|
||
RANGE_INDICATOR dot path instead (red dot only while out of range); a bound slot's
|
||
out-of-range read is the label's red tint (the OnUpdate range timer below).
|
||
- The state/feedback layer (decision 0137 phase 4) is the ref ActionButton.lua re-expressed:
|
||
UpdateState (checked on IsCurrentAction/IsAutoRepeatAction), UpdateUsable (the 1/1/1 ·
|
||
0.5/0.5/1 · 0.4/0.4/0.4 vertex-color trio), UpdateCooldown (CooldownFrame_SetTimer),
|
||
the Border's equipped green, and the 0.4 s Flash blink — with ONE structural deviation:
|
||
the event set registers on the BAR frame and fans to all 12 buttons, instead of the
|
||
ref's per-button Register/Unregister churn on HasAction (12 fixed buttons make the
|
||
skip-empties optimization noise; the handlers themselves are the ref's).
|
||
- Count: ActionButton_UpdateCount re-expressed, gated on IsConsumableAction exactly as the
|
||
ref does (0216 §7's "count > 0" simplification is retired — it put a stack number under
|
||
a mount, which has no stack; the engine-side law is ItemInfo::is_consumable, byte-cited
|
||
from 0x4e5250).
|
||
- Empty-slot grid (ref ActionButton.lua:241-259's ShowGrid/HideGrid, a per-button COUNTER):
|
||
the counter is BACK, and the argument that retired it is exactly why. 0216 §7 collapsed it
|
||
to one global boolean because "the cursor is a single global payload, so no two shows can
|
||
ever nest" — true while the payload was the only thing that could ask for a grid. Decision
|
||
1500 gives it a second asker (ALWAYS_SHOW_MULTIBARS, which holds the four extra bars'
|
||
empty wells open with no payload in hand), and with two independent askers the boolean is
|
||
wrong by its own reasoning: dropping a payload would close wells the option is still
|
||
asking for. So `button.showgrid` COUNTS, exactly as the reference's does, and
|
||
ActionButton_ShowGrid/_HideGrid below are its two verbs.
|
||
The count — rather than a flag — is also what the addon corpus already assumes: zBar
|
||
REPLACES both verbs and writes `button.showgrid = 1/0`, CT_BarMod writes 0/1/2 and
|
||
increments it on OUR ActionButton1-12, and Bartender2 HOOKS ActionButton_ShowGrid at
|
||
load — which died on a nil global here until now, the same session-start crash class
|
||
1218/1219 fixed for MultiBarLeft.
|
||
Unlike the ref (which HIDES an empty, non-grid slot entirely), our MAIN bar always shows
|
||
all 12 wells; the grid only swaps an EMPTY slot's ring art between the occupied and empty
|
||
Quickslot textures. The ref's extra SetVertexColor(1,1,1,0.5) dim on a grid ring is NOT
|
||
ours — that look is unchanged since 0216 and is the director's to move.
|
||
- Exhaustion tick + rest fill, XP text (hover/cvar-gated), MaxLevelBar: OUT. The bar's
|
||
right-hand cluster is otherwise complete — the backpack toggle + four bag slots live in
|
||
BagFrame.xml and the eight micro buttons in MicroMenu.xml (both anchored into
|
||
MainMenuBarArtFrame and seated over the art by BenillaActionBarArt_SeatAbove below),
|
||
and the performance meter is at the foot of this file. The KEYRING landed with decision
|
||
0765: its button and container live in BagFrame.xml (the ref's own split —
|
||
MainMenuBarBagButtons.xml / ContainerFrame.lua), and the bar's half of it — swapping the
|
||
two right-hand strips to the keyring art and sliding the performance meter over to make
|
||
room — is MainMenuBar_UpdateKeyRing below, exactly where the ref keeps it
|
||
(MainMenuBar.lua l.174-183).
|
||
-->
|
||
<Script><![CDATA[
|
||
BENILLA_FALLBACK_ICON = "Interface\\Icons\\INV_Misc_QuestionMark"
|
||
|
||
-- **The reference's action-bar constant block (ActionButton.lua:1-9).** Every one of these
|
||
-- was cited in comments across this file and MultiBars.xml and DEFINED nowhere, so an addon
|
||
-- reading them got nil. `zBar.lua:40` is the shape:
|
||
--
|
||
-- to = to or value.max or NUM_ACTIONBAR_BUTTONS
|
||
-- for i = from, to do -- 'for' limit must be a number
|
||
--
|
||
-- Found by the use-probe, which is the only column that touches anything.
|
||
--
|
||
-- `CURRENT_ACTIONBAR_PAGE` used to be withheld from this list on the grounds that it is the
|
||
-- reference's MUTABLE page cursor and we did not page the main bar — "defining it as a
|
||
-- frozen 1 would hand every addon a number that is silently wrong forever". That reasoning
|
||
-- was right and is now discharged rather than overruled: the bar pages, the global is live
|
||
-- state the paged-id formula reads, and it is declared with the paging verbs below rather
|
||
-- than here among the true constants. A frozen 1 would still be a lie; this one moves.
|
||
NUM_ACTIONBAR_PAGES = 6
|
||
NUM_ACTIONBAR_BUTTONS = 12
|
||
RIGHT_ACTIONBAR_PAGE = 3
|
||
LEFT_ACTIONBAR_PAGE = 4
|
||
BOTTOMRIGHT_ACTIONBAR_PAGE = 5
|
||
BOTTOMLEFT_ACTIONBAR_PAGE = 6
|
||
|
||
-- Ref ActionButton.lua:4 / UIParent.lua: the flash blink period and the range-check cadence.
|
||
ATTACK_BUTTON_FLASH_TIME = 0.4
|
||
TOOLTIP_UPDATE_TIME = 0.2
|
||
|
||
-- "Lock ActionBars" (ref UIOptionsFrame.lua:102-103 — uvar LOCK_ACTIONBAR, default "0").
|
||
-- The reference declares it in its options window; ours lives with the bar it locks, which
|
||
-- is this codebase's rule for every stock global (1128/1134): the assignment sits beside its
|
||
-- consumers, and the options row CAPTURES it rather than restating a default of its own.
|
||
-- Read by the drag guards below and by the pet bar's (PetActionBar.xml, the ref's own second
|
||
-- consumer at PetActionBarFrame.lua:270/278); driven by the Action Bars page and by the
|
||
-- TOGGLEACTIONBARLOCK binding the option's tooltip promises (decision 1136).
|
||
LOCK_ACTIONBAR = "0"
|
||
RegisterForSave("LOCK_ACTIONBAR")
|
||
|
||
-- CooldownFrame_SetTimer moved to Cooldown.xml (the ref's own file split) — the bag
|
||
-- slots share it, so it loads before both consumers.
|
||
|
||
-- One button's HotKey corner — the ref's ActionButton_UpdateHotkeys law in FULL since
|
||
-- 1008 (closing 0997's raw-token residue): the ABBREVIATED binding text through the
|
||
-- GetBindingText the ref specifies (ours, in UIParent.xml — one modifier abbreviates, "s-2";
|
||
-- two or more collapse to the ref's "·"), and with NO binding the ref's no-binding
|
||
-- leg — an empty label the OnUpdate range timer fills with the RANGE_INDICATOR dot
|
||
-- while out of range (until 1008 that leg was multibar-only; now any unbound slot,
|
||
-- main bar included, wears it). A harness with no registered bindings paints nothing.
|
||
function BenillaActionButton_PaintHotkey(button)
|
||
local key = GetBindingKey(button.bindingCommand)
|
||
local text
|
||
if GetBindingText then
|
||
text = GetBindingText(key, "KEY_", 1)
|
||
else
|
||
-- lone-file harness (the shipped manifest always has UIParent.xml first):
|
||
-- the raw token, the MicroMenu.xml fallback idiom.
|
||
text = key or ""
|
||
end
|
||
button.noBindingLabel = (text == "")
|
||
button.hotkey:SetText(text)
|
||
end
|
||
|
||
-- Every button's label, repainted on UPDATE_BINDINGS (a rebind, a set switch, the seed).
|
||
function BenillaActionBar_UpdateHotkeys()
|
||
for i = 1, table.getn(BENILLA_ACTION_BUTTONS) do
|
||
BenillaActionButton_PaintHotkey(BENILLA_ACTION_BUTTONS[i])
|
||
end
|
||
end
|
||
|
||
-- Every live action button — the main bar's 12 plus the multibars' (MultiBars.xml joins
|
||
-- at OnLoad). The fan-out roster for the bar-level events below: the ref registers the
|
||
-- feedback events per-button; our bar-level fan needs the full set in one place.
|
||
BENILLA_ACTION_BUTTONS = {}
|
||
|
||
-- ── Main-bar paging (ref ActionButton.lua l.1-12 and l.63-101) ───────────────────────
|
||
-- The main bar has six pages, and we already hold every slot they address: the app owns
|
||
-- the authoritative 1..120 action table, so the DATA for pages 2-6 was always there and
|
||
-- only the page SELECTOR was missing. Its absence was on screen, not just in the API —
|
||
-- the page arrows below shipped as art with no OnClick, which this file's own comment
|
||
-- admitted ("ART ONLY - we have no bar paging, so the clicks are no-ops").
|
||
--
|
||
-- `Bartender2.lua:686` is the corpus tell: three bare `ChangeActionBarPage()` calls, and
|
||
-- the addon died on the nil global at session start.
|
||
CURRENT_ACTIONBAR_PAGE = 1
|
||
-- "Table of actionbar pages and whether they're viewable or not" (the reference's own
|
||
-- comment). The page walk below honours it rather than counting, which is what makes the
|
||
-- whole thing work: a page an extra bar already displays must not ALSO be reachable on the
|
||
-- main bar, or paging up shows you the twelve actions already on screen beside it.
|
||
--
|
||
-- **This is the shipped START state, not a constant: it FOLLOWS the four bar toggles.**
|
||
-- All six pages are viewable here because all four extra bars now ship hidden (decision
|
||
-- 1500 — they are player options, off by default), and `MultiActionBar_Update`
|
||
-- (MultiBars.xml) does the arithmetic from then on: a bar that comes up takes its page out
|
||
-- of the cycle, a bar that goes down puts it back. Blanking two rows at declaration was
|
||
-- only ever right because visibility was static (0270's always-on bottom pair), and the
|
||
-- moment the player can move it a declaration cannot be the answer.
|
||
VIEWABLE_ACTION_BAR_PAGES = {1, 1, 1, 1, 1, 1}
|
||
|
||
-- `ChangeActionBarPage()` takes NO arguments — every reference caller sets
|
||
-- CURRENT_ACTIONBAR_PAGE first and then calls this to apply it (l.79, l.100), and
|
||
-- Bartender2 calls it bare.
|
||
--
|
||
-- Upstream it is a client binding; here it is FrameXML, deliberately. Our paged action id
|
||
-- is computed in Lua by `BenillaActionBar_ActionFor`, so the page IS this global and the
|
||
-- only work left for the verb is the work the reference gets by firing
|
||
-- ACTIONBAR_PAGE_CHANGED: repaint the twelve buttons, and restamp the page numeral (the
|
||
-- ref's own listener for that event is the up arrow's OnEvent, l.176-181 — the numeral is
|
||
-- the ONLY thing it does there). Addons CALL this, they never replace it, so the
|
||
-- divergence is unobservable from Lua — unlike a name we shadow, which is 1222's class.
|
||
function ChangeActionBarPage()
|
||
MainMenuBarPageNumber:SetText(CURRENT_ACTIONBAR_PAGE)
|
||
for i = 1, table.getn(BENILLA_ACTION_BUTTONS) do
|
||
BenillaActionButton_Update(BENILLA_ACTION_BUTTONS[i])
|
||
end
|
||
end
|
||
|
||
function ActionBar_PageUp()
|
||
local page = CURRENT_ACTIONBAR_PAGE + 1
|
||
local nextPage
|
||
for i = page, NUM_ACTIONBAR_PAGES do
|
||
if VIEWABLE_ACTION_BAR_PAGES[i] then nextPage = i break end
|
||
end
|
||
-- Past the last viewable page, wrap to 1 — the reference wraps to the LITERAL 1 here
|
||
-- rather than to the first viewable page, which is its own asymmetry with PageDown
|
||
-- (which rescans). Kept, because it is observable: with page 1 blanked, paging up off
|
||
-- the end lands on a page the down-walk would have skipped.
|
||
CURRENT_ACTIONBAR_PAGE = nextPage or 1
|
||
ChangeActionBarPage()
|
||
end
|
||
|
||
function ActionBar_PageDown()
|
||
local page = CURRENT_ACTIONBAR_PAGE - 1
|
||
local prevPage
|
||
for i = page, 1, -1 do
|
||
if VIEWABLE_ACTION_BAR_PAGES[i] then prevPage = i break end
|
||
end
|
||
if not prevPage then
|
||
for i = NUM_ACTIONBAR_PAGES, 1, -1 do
|
||
if VIEWABLE_ACTION_BAR_PAGES[i] then prevPage = i break end
|
||
end
|
||
end
|
||
CURRENT_ACTIONBAR_PAGE = prevPage; ChangeActionBarPage()
|
||
end
|
||
|
||
-- Seat a TOP-LEVEL frame that anchors INTO the bar art (the bag bar + backpack toggle,
|
||
-- BagFrame.xml; the micro-button row, MicroMenu.xml) one frame level above the art, so its
|
||
-- icons draw over the bar plate instead of under it.
|
||
--
|
||
-- Why it's needed: those frames are top-level, so they default to a LOWER frame level than
|
||
-- the bar's own art (a child hierarchy — the ExpBar's dwarf notches + the metal/well art sit
|
||
-- at the bar's child level). Frame level dominates the flat painter's order, so the bar art
|
||
-- would paint OVER them — the ring shows but the centered icon is fully covered (the "empty
|
||
-- rings, no bag icons" bug). The bar's OWN 12 buttons avoid this by being CHILDREN of the art
|
||
-- frame (child-over-parent). (SetParent onto the art frame would be the structural twin, but
|
||
-- the engine keys draw order at creation and does not re-key on a runtime reparent, so the
|
||
-- explicit level is the reliable lever.) Lives here, with the frame it's about, because two
|
||
-- files now need it — it began as BagFrame.xml's private BenillaBagBar_SeatAboveActionBar.
|
||
function BenillaActionBarArt_SeatAbove(frame)
|
||
local art = getglobal("MainMenuBarArtFrame")
|
||
if art then frame:SetFrameLevel(art:GetFrameLevel() + 1) end
|
||
end
|
||
|
||
-- ── The keyring's half of the bar (ref MainMenuBar_UpdateKeyRing, MainMenuBar.lua
|
||
-- l.174-183; decision 0765) ──────────────────────────────────────────────────────────────
|
||
-- The keyring is not just a button bolted onto the bar: the bar's two RIGHT-hand strips are
|
||
-- re-textured to a variant plate that has a socket for it, and the performance meter slides
|
||
-- 8px further left out of the way. Both atlases are 256-wide 43px strips at the same on-
|
||
-- screen size and anchors, so only the file + TexCoords change (UI-MainMenuBar-KeyRing is
|
||
-- 256x128 and holds exactly the two bands the ref names: 0.3359375 * 128 = 43px each).
|
||
--
|
||
-- Called by KeyRingButton's own OnEvent (BagFrame.xml). Everything is nil-guarded:
|
||
-- this file loads without BagFrame.xml in several harnesses, and BagFrame.xml loads without
|
||
-- this one in ~25 bag/bank/escape/merchant tests — either way the missing half no-ops.
|
||
--
|
||
-- DIVERGENCE (decision 0765): the ref latches this ON forever the first time HasKey() is
|
||
-- true, via the saved variable SHOW_KEYRING (and pulses the button for 60s to announce it).
|
||
-- This engine has no saved variables, and a session-scoped latch would leak across a
|
||
-- character switch — showing a keyring on a character with no key — so the state is derived
|
||
-- from HasKey() on every BAG_UPDATE instead, in BOTH directions. Observably identical
|
||
-- unless you destroy your last key, which then un-shows the keyring rather than leaving an
|
||
-- empty one behind. The 60s pulse is out, consistently with decision 0304's "no button
|
||
-- pulse" for the micro buttons.
|
||
function MainMenuBar_UpdateKeyRing()
|
||
local show = HasKey and HasKey()
|
||
-- The two right-hand strips (MainMenuBarTexture2 at x=+128, Texture3 at x=+384),
|
||
-- keyring plate or the ordinary dwarf plate. The dwarf coords are this file's own
|
||
-- authored ones (see the strips below) — restated here because this is the only code
|
||
-- that ever changes them back.
|
||
local strips = {
|
||
{ name = "MainMenuBarTexture2",
|
||
keyring = 0.6640625, keyringBottom = 1.0,
|
||
dwarf = 0.33203125, dwarfBottom = 0.5 },
|
||
{ name = "MainMenuBarTexture3",
|
||
keyring = 0.1640625, keyringBottom = 0.5,
|
||
dwarf = 0.08203125, dwarfBottom = 0.25 },
|
||
}
|
||
for _, strip in ipairs(strips) do
|
||
local tex = getglobal(strip.name)
|
||
if tex then
|
||
if show then
|
||
tex:SetTexture("Interface\\MainMenuBar\\UI-MainMenuBar-KeyRing")
|
||
tex:SetTexCoord(0, 1, strip.keyring, strip.keyringBottom)
|
||
else
|
||
tex:SetTexture("Interface\\MainMenuBar\\UI-MainMenuBar-Dwarf")
|
||
tex:SetTexCoord(0, 1, strip.dwarf, strip.dwarfBottom)
|
||
end
|
||
end
|
||
end
|
||
-- The performance meter's recess moves with the plate: -227 without the keyring,
|
||
-- -235 with it (ref l.180). Its own comment at the foot of this file has the geometry.
|
||
local perf = getglobal("MainMenuBarPerformanceBarFrame")
|
||
local bar = getglobal("MainMenuBar")
|
||
if perf and bar then
|
||
perf:SetPoint("BOTTOMRIGHT", bar, "BOTTOMRIGHT", (show and -235) or -227, -10)
|
||
end
|
||
local button = getglobal("KeyRingButton")
|
||
if button then
|
||
if show then button:Show() else button:Hide() end
|
||
end
|
||
-- Losing the last key with the keyring open would strand an orphan window; the ref
|
||
-- can't reach this state (its latch is one-way), so this is ours to decide.
|
||
local frame = getglobal("BenillaKeyRingFrame")
|
||
if frame and not show and frame:IsShown() then frame:Hide() end
|
||
end
|
||
|
||
-- ── The bonus-bar slide (decision 1524; ref BonusActionBarFrame.lua:1-98) ──────────────
|
||
--
|
||
-- The reference never re-pages its main bar: entering a form slides a 505x43 REPLICA of
|
||
-- the bar (own art, own 12 buttons on the bonus page) up out of the screen-bottom edge
|
||
-- over 0.15s, plays igBonusBarOpen when it lands, and leaves it covering the button strip
|
||
-- for as long as the form is up; leaving the form slides it back down carrying the OLD
|
||
-- form's icons (lastBonusBar) and hides it — no sound on the way down. benilla re-pages
|
||
-- the main bar (1223) — so here the overlay is the TRANSITION VEHICLE and the faithful
|
||
-- addon-visible state (`BonusActionBarFrame:IsShown()` is true exactly while a form is
|
||
-- up, as on the real client): the main bar keeps painting the OLD page under the rising
|
||
-- overlay (BenillaActionBar_DisplayedOffset) and adopts the bonus page when it lands.
|
||
--
|
||
-- Ref timing/geometry, quoted: SLIDETIME 0.15, YPOS 43 (= the frame's own height, so it
|
||
-- rises exactly out of the screen edge), XPOS 4 (the ref Lua re-anchors every tick at 4,
|
||
-- overriding its own XML's 40; the art's left TexCoord is trimmed 4px to line back up).
|
||
-- Ours slides a PROGRESS fraction rather than the ref's mode+timer pair: flipping form
|
||
-- mid-slide turns the bar around from where it is, where the ref's timer arithmetic
|
||
-- mirror-jumps the position (a quirk, not the mechanism).
|
||
BONUSACTIONBAR_SLIDETIME = 0.15
|
||
BONUSACTIONBAR_YPOS = 43
|
||
BONUSACTIONBAR_XPOS = 4
|
||
|
||
-- Ref-named verb (BonusActionBarFrame.lua:74): addons call it. Begin (or continue toward)
|
||
-- the up-slide; a bar already landed is a no-op — a direct form→form swap (warrior stance
|
||
-- dance, cat→bear powershift) repaints without re-sliding or re-sounding, ref-verbatim.
|
||
function ShowBonusActionBar()
|
||
local frame = BonusActionBarFrame
|
||
if not frame:IsShown() then
|
||
frame.slideProgress = 0
|
||
frame:Show()
|
||
end
|
||
if (frame.slideProgress or 0) < 1 then
|
||
frame.mode = "show"
|
||
end
|
||
end
|
||
|
||
-- Ref-named verb (l.87): begin the down-slide. Nothing to do when already hidden; a
|
||
-- mid-show flip turns around from the current position.
|
||
function HideBonusActionBar()
|
||
local frame = BonusActionBarFrame
|
||
if frame:IsShown() and frame.mode ~= "hide" then
|
||
frame.mode = "hide"
|
||
end
|
||
end
|
||
|
||
function BenillaBonusBar_OnLoad(frame)
|
||
frame.mode = "none"
|
||
frame.slideProgress = 0
|
||
-- Ref field (l.17/23, read by ActionButton_GetPagedID:449-451): the last NONZERO
|
||
-- offset, so the down-slide keeps painting the form's icons after the offset is 0.
|
||
frame.lastBonusBar = 1
|
||
end
|
||
|
||
function BonusActionBar_OnUpdate(elapsed)
|
||
local frame = BonusActionBarFrame
|
||
if frame.mode == "show" then
|
||
frame.slideProgress = frame.slideProgress + elapsed / BONUSACTIONBAR_SLIDETIME
|
||
if frame.slideProgress >= 1 then
|
||
frame.slideProgress = 1
|
||
frame.mode = "none"
|
||
frame:SetPoint("TOPLEFT", MainMenuBar, "BOTTOMLEFT",
|
||
BONUSACTIONBAR_XPOS, BONUSACTIONBAR_YPOS)
|
||
-- The landing edge IS the sound (ref l.61-64: played on slide-up completion,
|
||
-- never on the way down), and the moment the main bar under the overlay
|
||
-- adopts the bonus page (DisplayedOffset stops suppressing).
|
||
PlaySound("igBonusBarOpen")
|
||
for i = 1, table.getn(BENILLA_ACTION_BUTTONS) do
|
||
BenillaActionButton_Update(BENILLA_ACTION_BUTTONS[i])
|
||
end
|
||
else
|
||
frame:SetPoint("TOPLEFT", MainMenuBar, "BOTTOMLEFT",
|
||
BONUSACTIONBAR_XPOS, frame.slideProgress * BONUSACTIONBAR_YPOS)
|
||
end
|
||
elseif frame.mode == "hide" then
|
||
frame.slideProgress = frame.slideProgress - elapsed / BONUSACTIONBAR_SLIDETIME
|
||
if frame.slideProgress <= 0 then
|
||
frame.slideProgress = 0
|
||
frame.mode = "none"
|
||
frame:SetPoint("TOPLEFT", MainMenuBar, "BOTTOMLEFT", BONUSACTIONBAR_XPOS, 0)
|
||
frame:Hide()
|
||
else
|
||
frame:SetPoint("TOPLEFT", MainMenuBar, "BOTTOMLEFT",
|
||
BONUSACTIONBAR_XPOS, frame.slideProgress * BONUSACTIONBAR_YPOS)
|
||
end
|
||
end
|
||
end
|
||
|
||
-- The offset the MAIN bar paints. Live, except during the up-slide: the old page keeps
|
||
-- painting under the rising overlay and the bonus page arrives when it lands (the ref's
|
||
-- main bar shows page 1 the whole time a form is up — ours adopts the bonus page at
|
||
-- landing instead, 1223's re-paging model; 1524). The getglobal guard: buttons paint
|
||
-- during load, before BonusActionBarFrame (declared after the bar) exists.
|
||
function BenillaActionBar_DisplayedOffset()
|
||
local frame = getglobal("BonusActionBarFrame")
|
||
if frame and frame.mode == "show" then
|
||
return 0
|
||
end
|
||
return GetBonusBarOffset()
|
||
end
|
||
|
||
-- The wire/API action id the MAIN bar's button i displays (the vanilla page formula).
|
||
-- INTERNAL to BenillaActionButton_Action below — the ONLY caller. A button path that
|
||
-- reaches past it computes a MAIN-bar id for a multibar button (base ignored), which
|
||
-- reads as "the slot below": the tooltip hover did exactly that until 2026-07-21.
|
||
function BenillaActionBar_ActionFor(index)
|
||
local offset = BenillaActionBar_DisplayedOffset()
|
||
local base = 0
|
||
if offset > 0 then
|
||
base = (6 + offset - 1) * 12
|
||
else
|
||
-- The paged main bar. A bonus page (stance/form/stealth) OUTRANKS it, which is
|
||
-- why this is the else arm and not an addition: the reference's own
|
||
-- `ActionButton_GetPagedID` takes the bonus branch first.
|
||
base = (CURRENT_ACTIONBAR_PAGE - 1) * 12
|
||
end
|
||
return base + index
|
||
end
|
||
|
||
-- The action id a specific BUTTON displays: the ref forks on the parent frame's NAME
|
||
-- (ActionButton_GetPagedID:446-467 — MultiBarBottomLeft ⇒ page 6, MultiBarBottomRight ⇒
|
||
-- page 5, else the paged/bonus formula); we carry the fork as data — a fixed per-button
|
||
-- page base set at OnLoad (MultiBars.xml), nil for the bonus-paged main bar.
|
||
-- **Adopt a button that never ran our OnLoad.**
|
||
--
|
||
-- Our handlers read a region cache (`button.icon`, `.count`, `.cooldown`, …) that
|
||
-- `BenillaActionButton_OnLoad` fills. An addon inheriting `ActionBarButtonTemplate` gets
|
||
-- those handlers and supplies its OWN `<OnLoad>`, which REPLACES the template's rather
|
||
-- than chaining — so ours never runs and every one of those reads was nil. zBar.xml:7 is
|
||
-- the corpus shape; it died in OUR file at `ActionBar.xml:529` on `button.icon`.
|
||
--
|
||
-- Resolving from the derived names is not a fallback bolted on: it is exactly what our
|
||
-- OnLoad does, and what the REFERENCE does on every access (`ActionButton_Update` reads
|
||
-- `getglobal(this:GetName().."Icon")` each time rather than caching). We cache because it
|
||
-- is cheaper; this is the same lookup for the buttons that never got cached.
|
||
--
|
||
-- It deliberately does NOT join `BENILLA_ACTION_BUTTONS`. That roster is the event fan-out
|
||
-- for OUR bars, and a foreign button's owner drives its own updates — adding it would have
|
||
-- us repainting somebody else's button behind their back.
|
||
function BenillaActionButton_Adopt(button)
|
||
if not button or button.icon then return end
|
||
local n = button:GetName()
|
||
if not n then return end
|
||
button.icon = getglobal(n .. "Icon")
|
||
button.hotkey = getglobal(n .. "HotKey")
|
||
button.count = getglobal(n .. "Count")
|
||
button.flash = getglobal(n .. "Flash")
|
||
button.border = getglobal(n .. "Border")
|
||
button.cooldown = getglobal(n .. "Cooldown")
|
||
button.name = getglobal(n .. "Name")
|
||
button.flashing = button.flashing or 0
|
||
button.flashtime = button.flashtime or 0
|
||
-- The grid count, same posture: a foreign button reaching ActionButton_HideGrid with
|
||
-- no count would raise on the arithmetic, which is 1199's class of silent-wrong-shape.
|
||
button.showgrid = button.showgrid or 0
|
||
end
|
||
|
||
function BenillaActionButton_Action(button)
|
||
-- `index` falls back to the button's ID, which is where the REFERENCE reads it from:
|
||
-- `ActionButton_GetPagedID` uses `this:GetID()`, and our `.index` is only that value
|
||
-- cached at OnLoad. A button that inherits `ActionBarButtonTemplate` and wires its own
|
||
-- OnLoad — zBar.xml:7 does exactly this — never runs ours, so `.index` is nil while
|
||
-- `GetID()` is set from the XML `id=`. Before the fallback, our own handler raised
|
||
-- `ActionBar.xml:228: arithmetic on local 'index'` on somebody else's button.
|
||
--
|
||
-- Still nothing? Action 0, which is not a real slot: every reader answers nil for it
|
||
-- and the button draws empty. Deliberately not an early `return nil` — the callers are
|
||
-- arithmetic all the way down, and a nil would move the raise rather than remove it.
|
||
local index = button.index or button:GetID() or 0
|
||
if button.base then
|
||
return button.base + index
|
||
end
|
||
-- The overlay's own buttons (ref ActionButton_GetPagedID:447-452): the LIVE bonus
|
||
-- page — with lastBonusBar standing in once the offset has dropped, so the
|
||
-- down-slide keeps painting (and a click mid-descent keeps using) the old form's
|
||
-- slots, ref-verbatim. Distinct from the main bar's DisplayedOffset suppression:
|
||
-- these buttons show the NEW page from the first slide frame.
|
||
if button.isBonus then
|
||
local offset = GetBonusBarOffset()
|
||
if offset == 0 then
|
||
local frame = getglobal("BonusActionBarFrame")
|
||
offset = (frame and frame.lastBonusBar) or 1
|
||
end
|
||
return (6 + offset - 1) * 12 + index
|
||
end
|
||
return BenillaActionBar_ActionFor(index)
|
||
end
|
||
|
||
-- Hover: SetAction's pure delegation (decision 0276 — a SPELL slot renders the spell
|
||
-- tooltip with its rank column, an ITEM slot the shared item renderer; ref
|
||
-- ActionButton_SetTooltip). The re-enter keeps it live across page flips.
|
||
-- Anchor: ref ActionButton_SetTooltip (ActionButton.lua l.366-372) branches on the
|
||
-- UberTooltips CVar — "1" → the default corner, else beside the button, LEFT for the bars
|
||
-- that sit at the screen edge and RIGHT for the rest. This branch was collapsed to the "1"
|
||
-- leg until B230, on the reason that benilla shipped no CVar state for anything to move
|
||
-- it; 0954 ended that and cvars.rs now registers the key (default "1", byte-read — the
|
||
-- evidence lives on that row), so the fork is live and the stock look is unchanged.
|
||
--
|
||
-- The ref's LEFT set is {MultiBarBottomRight, MultiBarRight, MultiBarLeft} — the three bars
|
||
-- that sit at (or against) the right edge, so their plates have to open toward the centre.
|
||
-- All three exist here now: the two VERTICAL bars landed with 1219 and became player
|
||
-- options with 1500, and this comment said "only the first exists" for as long as that was
|
||
-- true. Membership is by FRAME, not by visibility — a hidden bar is never hovered anyway.
|
||
function BenillaActionButton_OnEnter(button)
|
||
BenillaActionButton_Adopt(button)
|
||
if not GameTooltip then return end -- engine tests load file subsets
|
||
if GetCVar("UberTooltips") == "0" then
|
||
-- `parent and` first: an orphan button's nil parent would otherwise match a nil
|
||
-- MultiBarRight in a harness that loaded no multibars, and anchor the wrong way.
|
||
local parent = button:GetParent()
|
||
local edgeBar = parent and (parent == MultiBarBottomRight
|
||
or parent == MultiBarRight or parent == MultiBarLeft)
|
||
if edgeBar then GameTooltip:SetOwner(button, "ANCHOR_LEFT") else GameTooltip:SetOwner(button, "ANCHOR_RIGHT") end
|
||
else
|
||
GameTooltip_SetDefaultAnchor(GameTooltip, button)
|
||
end
|
||
GameTooltip:SetAction(BenillaActionButton_Action(button))
|
||
end
|
||
|
||
function BenillaActionButton_OnLoad(button, index, base, commandPrefix)
|
||
button.index = index
|
||
button.base = base
|
||
button.icon = getglobal(button:GetName() .. "Icon")
|
||
button.hotkey = getglobal(button:GetName() .. "HotKey")
|
||
button.count = getglobal(button:GetName() .. "Count")
|
||
button.flash = getglobal(button:GetName() .. "Flash")
|
||
button.border = getglobal(button:GetName() .. "Border")
|
||
button.cooldown = getglobal(button:GetName() .. "Cooldown")
|
||
button.name = getglobal(button:GetName() .. "Name")
|
||
-- Ref ActionButton_OnLoad:104-106: the flash/range state the OnUpdate loop drives.
|
||
button.flashing = 0
|
||
button.flashtime = 0
|
||
button.rangeTimer = nil
|
||
-- ref ActionButton_OnLoad l.104: the empty-well grid count starts at zero.
|
||
button.showgrid = 0
|
||
-- Every bar button carries its binding COMMAND (0997 main bar, 1008 multibars):
|
||
-- the caller names the command family (MultiBars.xml passes MULTIACTIONBAR1/2BUTTON
|
||
-- — the ref's own bar↔page mapping quoted there); nothing passed = the main bar's
|
||
-- ACTIONBUTTON. The label paints from it here and repaints on UPDATE_BINDINGS.
|
||
button.bindingCommand = (commandPrefix or "ACTIONBUTTON") .. index
|
||
BenillaActionButton_PaintHotkey(button)
|
||
table.insert(BENILLA_ACTION_BUTTONS, button)
|
||
-- BOTH mouse buttons, ref-verbatim (ActionButton_OnLoad, ActionButton.lua:108-109):
|
||
-- an action button is a two-button button. The OnClick body reads no `arg1` — in the
|
||
-- ref either button runs the same PickupAction/UseAction fork — so right-click USES
|
||
-- the action, which is how food and spells are used off the bar. Without this the
|
||
-- widget default ({"LeftButtonUp"}, `benilla_ui::script::button`) silently swallowed
|
||
-- every right-click on the bar (director's report B200).
|
||
button:RegisterForClicks("LeftButtonUp", "RightButtonUp")
|
||
-- The drag trio (decision 0216 §3/§7): click-carry and drag share one downstream path
|
||
-- by construction (OnClick/OnDragStart both call PickupAction; OnReceiveDrag calls
|
||
-- PlaceAction — ref ActionBarFrame.xml:12-38). Both buttons drag, ref-verbatim too
|
||
-- (l.108) — a started drag suppresses the click, so right-press-and-move relocates the
|
||
-- action while right-click-in-place still uses it. Both drag ends honour LOCK_ACTIONBAR
|
||
-- since 1136 — see the guards themselves for what the lock does and does not stop.
|
||
button:RegisterForDrag("LeftButton", "RightButton")
|
||
BenillaActionButton_Update(button)
|
||
end
|
||
|
||
-- Ref ActionBarFrame.xml:12-22's fork verbatim: shift picks up, else uses (checkCursor=1 —
|
||
-- the engine routes a click-with-payload to PlaceAction instead, decision 0216 §7).
|
||
function BenillaActionButton_OnClick(button)
|
||
BenillaActionButton_Adopt(button)
|
||
local action = BenillaActionButton_Action(button)
|
||
if IsShiftKeyDown() then
|
||
PickupAction(action)
|
||
else
|
||
UseAction(action, 1)
|
||
end
|
||
BenillaActionButton_Update(button)
|
||
end
|
||
|
||
-- The lock (ref ActionBarFrame.xml:23-38, both handlers wrapped in `if LOCK_ACTIONBAR ~= "1"
|
||
-- then … end`). Note what the reference does NOT guard, and neither do we: the shift-click
|
||
-- pick-up in OnClick above (its l.12-22 fork runs PickupAction unconditionally). So the lock
|
||
-- stops the *drag*, and shift-click stays the deliberate way to move an action with the bar
|
||
-- locked — which is what makes the setting usable rather than a wall.
|
||
function BenillaActionButton_OnDragStart(button)
|
||
BenillaActionButton_Adopt(button)
|
||
if LOCK_ACTIONBAR == "1" then return end
|
||
PickupAction(BenillaActionButton_Action(button))
|
||
BenillaActionButton_Update(button)
|
||
end
|
||
|
||
function BenillaActionButton_OnReceiveDrag(button)
|
||
BenillaActionButton_Adopt(button)
|
||
if LOCK_ACTIONBAR == "1" then return end
|
||
PlaceAction(BenillaActionButton_Action(button))
|
||
BenillaActionButton_Update(button)
|
||
end
|
||
|
||
-- The default ACTIONBUTTON1..12 key bindings (ref Bindings.xml:121-127: keys 1..9,0,-,=
|
||
-- run ActionButtonDown on keystate "down" and ActionButtonUp on "up" via runOnUp), both
|
||
-- re-expressed from ActionButton.lua:15-28/30-45 and routed here from the app's key feed.
|
||
-- DOWN pushes the button only from NORMAL; UP fires the action only from PUSHED — the
|
||
-- state pair is both the pushed visual and the debounce (a key-repeat DOWN or a stray UP
|
||
-- is a no-op). Calls UseAction DIRECTLY with NO checkCursor argument — unlike the
|
||
-- mouse-click fork above, a keybind never places (decision 0216 §7: the ref itself never
|
||
-- routes ActionButtonUp through OnClick, so this no longer goes through Click() either —
|
||
-- the two entry points share the id formula, not the click path). The ref's
|
||
-- BonusActionBar fork is not modeled (no bonus bar frame).
|
||
--
|
||
-- SIGNATURES ARE THE 1.12 ONES (decision 1199): `ActionButtonDown(id)` /
|
||
-- `ActionButtonUp(id, onSelf)`, the shapes an addon calls. These two never took a frame —
|
||
-- they take the bar INDEX in both clients — so nothing here changes but the names and the
|
||
-- restored `onSelf`, which rides through to UseAction's third argument exactly as the ref's
|
||
-- l.56 does (our binding accepts and ignores it — `script/action.rs`).
|
||
-- Both route to the overlay's buttons while it is up — ref ActionButton.lua:15-61's own
|
||
-- fork, and the half of the swap that must NOT wait for the slide: the overlay is shown
|
||
-- from the first slide frame, so a key pressed the instant you enter stealth already
|
||
-- drives the stealth page (and, during the down-slide, still drives the old form's page —
|
||
-- lastBonusBar — exactly as the reference does).
|
||
function ActionButtonDown(id)
|
||
if BonusActionBarFrame:IsShown() then
|
||
local button = getglobal("BonusActionButton" .. id)
|
||
if ( button:GetButtonState() == "NORMAL" ) then button:SetButtonState("PUSHED") end
|
||
return
|
||
end
|
||
local button = getglobal("ActionButton" .. id)
|
||
if ( button:GetButtonState() == "NORMAL" ) then button:SetButtonState("PUSHED") end
|
||
end
|
||
|
||
function ActionButtonUp(id, onSelf)
|
||
local button
|
||
if BonusActionBarFrame:IsShown() then
|
||
button = getglobal("BonusActionButton" .. id)
|
||
else
|
||
button = getglobal("ActionButton" .. id)
|
||
end
|
||
if ( button:GetButtonState() == "PUSHED" ) then
|
||
button:SetButtonState("NORMAL")
|
||
UseAction(BenillaActionButton_Action(button), 0, onSelf)
|
||
-- Ref ActionButtonUp:55-59: the checked ring reflects the use immediately.
|
||
BenillaActionButton_UpdateState(button)
|
||
end
|
||
end
|
||
|
||
-- Ref ActionButton_UpdateState:261-267 — the checked ring: the current action (Attack
|
||
-- while auto-attacking, the in-flight cast) or the live auto-repeat spell.
|
||
function BenillaActionButton_UpdateState(button)
|
||
local action = BenillaActionButton_Action(button)
|
||
if ( IsCurrentAction(action) or IsAutoRepeatAction(action) ) then button:SetChecked(1) else button:SetChecked(0) end
|
||
end
|
||
|
||
-- Ref ActionButton_UpdateUsable:269-283, verbatim colors: usable white; out of power the
|
||
-- blue-grey 0.5/0.5/1.0 on icon AND ring; otherwise-unusable the 0.4 grey icon only.
|
||
function BenillaActionButton_UpdateUsable(button)
|
||
local action = BenillaActionButton_Action(button)
|
||
local normalTexture = getglobal(button:GetName() .. "NormalTexture")
|
||
local isUsable, notEnoughMana = IsUsableAction(action)
|
||
if ( isUsable ) then
|
||
button.icon:SetVertexColor(1.0, 1.0, 1.0)
|
||
normalTexture:SetVertexColor(1.0, 1.0, 1.0)
|
||
elseif ( notEnoughMana ) then
|
||
button.icon:SetVertexColor(0.5, 0.5, 1.0)
|
||
normalTexture:SetVertexColor(0.5, 0.5, 1.0)
|
||
else
|
||
button.icon:SetVertexColor(0.4, 0.4, 0.4)
|
||
normalTexture:SetVertexColor(1.0, 1.0, 1.0)
|
||
end
|
||
end
|
||
|
||
-- Ref ActionButton_UpdateCooldown:294-298.
|
||
function BenillaActionButton_UpdateCooldown(button)
|
||
local start, duration, enable = GetActionCooldown(BenillaActionButton_Action(button))
|
||
CooldownFrame_SetTimer(button.cooldown, start, duration, enable)
|
||
end
|
||
|
||
-- Ref ActionButton_UpdateFlash/StartFlash/StopFlash/IsFlashing:469-496: the red blink on
|
||
-- an engaged Attack button / a live auto-repeat, toggled by the OnUpdate loop below.
|
||
function BenillaActionButton_UpdateFlash(button)
|
||
local action = BenillaActionButton_Action(button)
|
||
if ( (IsAttackAction(action) and IsCurrentAction(action)) or IsAutoRepeatAction(action) ) then
|
||
BenillaActionButton_StartFlash(button)
|
||
else
|
||
BenillaActionButton_StopFlash(button)
|
||
end
|
||
end
|
||
|
||
function BenillaActionButton_StartFlash(button)
|
||
button.flashing = 1
|
||
button.flashtime = 0
|
||
BenillaActionButton_UpdateState(button)
|
||
end
|
||
|
||
function BenillaActionButton_StopFlash(button)
|
||
button.flashing = 0
|
||
button.flash:Hide()
|
||
BenillaActionButton_UpdateState(button)
|
||
end
|
||
|
||
-- Ref ActionButton_OnUpdate:384-428, minus the tooltip refresh (no per-button tooltip
|
||
-- yet): the 0.4 s flash toggle, and the 0.2 s range recheck — a bound slot's label
|
||
-- tints red/grey, an unbound one wears the RANGE_INDICATOR dot (both legs the ref's,
|
||
-- unified in 1008 — the SCOPE note).
|
||
function ActionButton_OnUpdate(elapsed)
|
||
BenillaActionButton_Adopt(this)
|
||
local button = this
|
||
if ( button.flashing == 1 ) then
|
||
button.flashtime = button.flashtime - elapsed
|
||
if ( button.flashtime <= 0 ) then
|
||
local overtime = -button.flashtime
|
||
if ( overtime >= ATTACK_BUTTON_FLASH_TIME ) then
|
||
overtime = 0
|
||
end
|
||
button.flashtime = ATTACK_BUTTON_FLASH_TIME - overtime
|
||
if ( button.flash:IsVisible() ) then
|
||
button.flash:Hide()
|
||
else
|
||
button.flash:Show()
|
||
end
|
||
end
|
||
end
|
||
if ( button.rangeTimer ) then
|
||
button.rangeTimer = button.rangeTimer - elapsed
|
||
if ( button.rangeTimer <= 0 ) then
|
||
if ( IsActionInRange(BenillaActionButton_Action(button)) == 0 ) then
|
||
-- An UNBOUND button has no label to tint: paint the ref's
|
||
-- RANGE_INDICATOR dot instead (net ref behavior — red dot iff out of
|
||
-- range). Since 1008 the fork is the binding text itself (any bar's
|
||
-- slot can be bound or bare now), not which bar owns the button.
|
||
if button.noBindingLabel then
|
||
button.hotkey:SetText("●")
|
||
end
|
||
button.hotkey:SetVertexColor(1.0, 0.1, 0.1)
|
||
else
|
||
if button.noBindingLabel then
|
||
button.hotkey:SetText("")
|
||
end
|
||
button.hotkey:SetVertexColor(0.6, 0.6, 0.6)
|
||
end
|
||
button.rangeTimer = TOOLTIP_UPDATE_TIME
|
||
end
|
||
end
|
||
end
|
||
|
||
-- the ref's count law (ActionButton.lua:285-292), re-expressed here. The gate is
|
||
-- IsConsumableAction, NOT "count > 0": a consumable you have run out of shows a literal
|
||
-- "0", and an item that is not consumable (a mount, a trinket, a bag) shows nothing at
|
||
-- all, however many copies you hold.
|
||
function BenillaActionButton_UpdateCount(button)
|
||
local action = BenillaActionButton_Action(button)
|
||
if IsConsumableAction(action) then
|
||
button.count:SetText(GetActionCount(action))
|
||
else
|
||
button.count:SetText("")
|
||
end
|
||
end
|
||
|
||
-- ── The reference's names, so an addon that hooks them is reached ──────────────────────
|
||
--
|
||
-- The 1.12 customisation model is "replace a global and the client calls your replacement"
|
||
-- (Bagnon does it to `ToggleBackpack`; `zBar`/`zBarEx` do
|
||
-- `SetScript("OnShow", ActionButton_Update)`; `CT_BarMod` calls `ActionButton_Update()`
|
||
-- outright). Wherever our UI calls a `Benilla`-named function and never the reference's
|
||
-- name, every one of those addons is SILENTLY INERT — the override is installed and never
|
||
-- invoked. A survey cannot see it; it loads addons and fires events but never clicks.
|
||
--
|
||
-- These are ADAPTERS, not renames, and the distinction is the whole point: the reference's
|
||
-- contract is `this`-shaped and no-argument, ours takes the button explicitly. Renaming
|
||
-- would let `TipBuddy`'s `originalUnitFrame_OnEnter()` reach us with a nil frame — reachable
|
||
-- but broken, which is worse than inert. The adapter publishes the reference's SHAPE and
|
||
-- delegates.
|
||
--
|
||
-- NOT adapted, and named so nobody assumes it was missed: `ActionButton_OnLoad`. Ours is
|
||
-- `(button, index, base, commandPrefix)` and the reference's takes nothing — the extra
|
||
-- arguments are real state our per-container registration needs, so no adapter can supply
|
||
-- them. That is the per-button event registration change already at the top of the arc
|
||
-- queue, not a naming fix.
|
||
-- **`ActionButton_OnLoad()` — the reference's own, taking nothing and reading `this`.**
|
||
--
|
||
-- This sat at the top of the arc queue for the whole wave, recorded as unadaptable: ours
|
||
-- takes `(button, index, base, commandPrefix)` and the reference's takes none, so "no
|
||
-- adapter can supply them". Reading ref ActionButton.lua:103-119 shows that was wrong —
|
||
-- the reference derives all three from `this` and it is our own signature that caches
|
||
-- them:
|
||
--
|
||
-- index -> `this:GetID()` (what ActionButton_GetPagedID reads)
|
||
-- commandPrefix -> `this.buttonType`, a field the BAR sets, "ACTIONBUTTON" by default
|
||
-- (ref l.118 `ActionButton_UpdateHotkeys(this.buttonType)`)
|
||
-- base -> not an OnLoad concept at all; the reference forks on the PARENT's
|
||
-- NAME at read time. A foreign bar ("zBar1") matches no multibar, so
|
||
-- the paged/bonus formula applies — which is what leaving `base` nil
|
||
-- already does here.
|
||
--
|
||
-- The events are registered on the BUTTON, as the reference does, and reach it through the
|
||
-- `<OnEvent>` this change adds to `ActionBarButtonTemplate`. Our own bars do NOT call this
|
||
-- and never register, so they keep being driven by the BENILLA_ACTION_BUTTONS fan-out and
|
||
-- cannot be double-driven.
|
||
function ActionButton_OnLoad()
|
||
local button = this
|
||
if not button then return end
|
||
BenillaActionButton_Adopt(button)
|
||
button.index = button.index or button:GetID()
|
||
button.bindingCommand = (button.buttonType or "ACTIONBUTTON") .. (button.index or 1)
|
||
button.showgrid = 0
|
||
button.flashing = 0
|
||
button.flashtime = 0
|
||
button:RegisterForDrag("LeftButton", "RightButton")
|
||
button:RegisterForClicks("LeftButtonUp", "RightButtonUp")
|
||
button:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||
button:RegisterEvent("UPDATE_BONUS_ACTIONBAR")
|
||
button:RegisterEvent("ACTIONBAR_SHOWGRID")
|
||
button:RegisterEvent("ACTIONBAR_HIDEGRID")
|
||
button:RegisterEvent("ACTIONBAR_PAGE_CHANGED")
|
||
button:RegisterEvent("ACTIONBAR_SLOT_CHANGED")
|
||
button:RegisterEvent("UPDATE_BINDINGS")
|
||
BenillaActionButton_PaintHotkey(button)
|
||
BenillaActionButton_Update(button)
|
||
end
|
||
|
||
-- The per-button event arm the reference's own template carries. Only buttons that ran
|
||
-- `ActionButton_OnLoad` ever registered, so this is a no-op for ours.
|
||
function ActionButton_OnEvent()
|
||
local button = this
|
||
if not button then return end
|
||
BenillaActionButton_Adopt(button)
|
||
-- Through the two verbs, ref-verbatim in shape (ActionButton_OnEvent l.317-324) and
|
||
-- no longer the 1/0 assignment this arm shipped with: `showgrid` is a COUNT now, and a
|
||
-- foreign button handed a bare 0 while the option still wanted its wells open would
|
||
-- close them. Each verb repaints, so these arms return rather than fall through.
|
||
if event == "ACTIONBAR_SHOWGRID" then
|
||
ActionButton_ShowGrid(button)
|
||
return
|
||
elseif event == "ACTIONBAR_HIDEGRID" then
|
||
ActionButton_HideGrid(button)
|
||
return
|
||
elseif event == "UPDATE_BINDINGS" then
|
||
BenillaActionButton_PaintHotkey(button)
|
||
end
|
||
BenillaActionButton_Update(button)
|
||
end
|
||
|
||
-- ref ActionButton.lua:446 — the action id a button displays, forked on its parent bar.
|
||
-- `BenillaActionButton_Action` IS this function; only the name was ours. CT_BarMod calls it
|
||
-- the moment there is an action to page, which is why an EMPTY-world survey never saw it:
|
||
-- it surfaced only when the fixture started seating a populated session.
|
||
function ActionButton_GetPagedID(button)
|
||
return BenillaActionButton_Action(button or this)
|
||
end
|
||
|
||
function ActionButton_Update()
|
||
-- Adopt here too: this adapter carries the REFERENCE's name, so `this` is very often a
|
||
-- button somebody else built (zBar's, CT_BarMod's) that never ran our OnLoad and so has
|
||
-- no region cache. The handler-boundary adopts do not cover it — an addon calls this
|
||
-- global directly, without any of our scripts in the stack.
|
||
BenillaActionButton_Adopt(this)
|
||
BenillaActionButton_Update(this)
|
||
end
|
||
|
||
function ActionButton_UpdateUsable()
|
||
BenillaActionButton_UpdateUsable(this)
|
||
end
|
||
|
||
-- ── The empty-slot grid (ref ActionButton.lua l.243-260) ────────────────────────────────
|
||
-- `button.showgrid` is a COUNT of how many things currently want this button's empty well
|
||
-- visible, and it is the reference's own field under its own name — see the SCOPE note for
|
||
-- why a count and not a flag, and for the three corpus addons that already write it.
|
||
--
|
||
-- Today there are exactly two askers and they are independent: the cursor's placeable
|
||
-- payload (the ACTIONBAR_SHOWGRID/_HIDEGRID pair, fanned over the whole roster in
|
||
-- BenillaActionBar_OnEvent) and ALWAYS_SHOW_MULTIBARS (MultiBars.xml's
|
||
-- MultiActionBar_UpdateGridVisibility, over the four extra bars only). Either alone holds
|
||
-- the wells open; the count is what lets one let go without closing what the other holds.
|
||
--
|
||
-- Divergence from the ref, deliberate: ours re-derive the whole button through
|
||
-- BenillaActionButton_Update rather than doing their own Show/Hide + vertex tint. There is
|
||
-- one paint path in this file and the grid is one of its inputs, so a verb that painted
|
||
-- directly would be a second, slightly different answer to "what does an empty well look
|
||
-- like" — which is how the two got out of step in the ref (its ShowGrid dims the ring, its
|
||
-- Update never restores the dim).
|
||
function BenillaActionButton_GridShown(button)
|
||
return button.showgrid ~= nil and button.showgrid > 0
|
||
end
|
||
|
||
function ActionButton_ShowGrid(button)
|
||
button = button or this
|
||
BenillaActionButton_Adopt(button)
|
||
button.showgrid = (button.showgrid or 0) + 1
|
||
BenillaActionButton_Update(button)
|
||
end
|
||
|
||
function ActionButton_HideGrid(button)
|
||
button = button or this
|
||
BenillaActionButton_Adopt(button)
|
||
-- Clamped at zero. The ref subtracts unconditionally and can go negative — a button
|
||
-- that joined the roster mid-payload takes one HIDEGRID it never took a SHOWGRID for,
|
||
-- and from then on its wells need TWO shows to open. Ours simply cannot owe.
|
||
local count = (button.showgrid or 0) - 1
|
||
if count < 0 then count = 0 end
|
||
button.showgrid = count
|
||
BenillaActionButton_Update(button)
|
||
end
|
||
|
||
function BenillaActionButton_Update(button)
|
||
local action = BenillaActionButton_Action(button)
|
||
if HasAction(action) then
|
||
button.icon:SetTexture(GetActionTexture(action) or BENILLA_FALLBACK_ICON)
|
||
button.icon:Show()
|
||
button:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
|
||
button:Show()
|
||
button.rangeTimer = -1
|
||
BenillaActionButton_UpdateCount(button)
|
||
BenillaActionButton_UpdateState(button)
|
||
BenillaActionButton_UpdateUsable(button)
|
||
BenillaActionButton_UpdateCooldown(button)
|
||
BenillaActionButton_UpdateFlash(button)
|
||
else
|
||
-- ref l.168: the empty arm HIDES the icon region — it does not clear the path. The
|
||
-- distinction is load-bearing here: UpdateUsable's SetVertexColor tint survives a
|
||
-- SetTexture(nil) ("a tint outlives the art"), and an occupied slot going empty on
|
||
-- a character switch left that white tint on a pathless region — the solid white
|
||
-- buttons of the 2026-08-07 report (decision 1108, with the engine-side draw gate).
|
||
button.icon:Hide()
|
||
button.count:SetText("")
|
||
button.cooldown:Hide()
|
||
button.rangeTimer = nil
|
||
button.hotkey:SetVertexColor(0.6, 0.6, 0.6)
|
||
button:SetChecked(0)
|
||
BenillaActionButton_StopFlash(button)
|
||
local grid = BenillaActionButton_GridShown(button)
|
||
if button.base then
|
||
-- An EMPTY multibar well is the ref's own default: hidden entirely, appearing
|
||
-- as a drop-target ring only while the grid is asked for (a held payload, or
|
||
-- ALWAYS_SHOW_MULTIBARS). Only the MAIN bar keeps our always-visible wells
|
||
-- divergence (the SCOPE note) — its art has sockets; floating rings over bare
|
||
-- world would not read as a bar.
|
||
button.hotkey:SetText("")
|
||
if not grid then
|
||
button:Hide()
|
||
else
|
||
button:SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
|
||
button:Show()
|
||
end
|
||
else
|
||
-- While the grid is up, an empty slot shows the ref's own "no action" ring
|
||
-- (Interface\Buttons\UI-Quickslot) so it reads as a drop target; otherwise the
|
||
-- plain occupied-style ring, unchanged from before this slice (SCOPE note).
|
||
if grid then
|
||
button:SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
|
||
else
|
||
button:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2")
|
||
end
|
||
end
|
||
end
|
||
-- Ref ActionButton_Update:221-228: the equipped-item green border.
|
||
if ( IsEquippedAction(action) ) then
|
||
button.border:SetVertexColor(0, 1.0, 0, 0.35)
|
||
button.border:Show()
|
||
else
|
||
button.border:Hide()
|
||
end
|
||
-- Ref ActionButton_Update:236-238, "Update Macro Text": the Name line under the icon,
|
||
-- written on EVERY update, occupied or not — `GetActionText` answers a MACRO slot's
|
||
-- macro name and nil for anything else, and a nil clears the line, so an emptied or
|
||
-- re-filled slot loses the old name through this same write. Guarded only because an
|
||
-- adopted foreign button may inherit a template that declares no `$parentName`.
|
||
-- (B340: the line was declared in the template and never set — decision 1636.)
|
||
if button.name then
|
||
button.name:SetText(GetActionText(action))
|
||
end
|
||
end
|
||
|
||
function BenillaActionBar_OnLoad(frame)
|
||
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||
frame:RegisterEvent("ACTIONBAR_SLOT_CHANGED")
|
||
frame:RegisterEvent("UPDATE_BONUS_ACTIONBAR")
|
||
frame:RegisterEvent("ACTIONBAR_SHOWGRID")
|
||
frame:RegisterEvent("ACTIONBAR_HIDEGRID")
|
||
-- The state/feedback events (ref ActionButton_OnLoad's per-button set, registered
|
||
-- bar-level here — the SCOPE note): the app fires each on the byte-mapped client
|
||
-- edge (wow-re action-button-state-api.md).
|
||
frame:RegisterEvent("ACTIONBAR_UPDATE_STATE")
|
||
frame:RegisterEvent("ACTIONBAR_UPDATE_USABLE")
|
||
frame:RegisterEvent("ACTIONBAR_UPDATE_COOLDOWN")
|
||
frame:RegisterEvent("PLAYER_TARGET_CHANGED")
|
||
frame:RegisterEvent("PLAYER_AURAS_CHANGED")
|
||
frame:RegisterEvent("PLAYER_ENTER_COMBAT")
|
||
frame:RegisterEvent("PLAYER_LEAVE_COMBAT")
|
||
frame:RegisterEvent("START_AUTOREPEAT_SPELL")
|
||
frame:RegisterEvent("STOP_AUTOREPEAT_SPELL")
|
||
-- The binding table moved (a rebind, a set switch, the seed) — repaint the HotKey
|
||
-- corners (0997; the ref's own UPDATE_BINDINGS consumer is UpdateHotkeys too).
|
||
frame:RegisterEvent("UPDATE_BINDINGS")
|
||
end
|
||
|
||
-- Run one ref per-button handler over the OCCUPIED buttons (the bar-level fan — SCOPE
|
||
-- note). The HasAction gate is the ref's own semantics, load-bearing, not an optimization:
|
||
-- ActionButton.lua registers these handlers only while the button has an action ("All
|
||
-- event handlers below this line are only set when the button has an action"), so an
|
||
-- empty button never runs them — UpdateUsable on an empty would land its 0.4 grey
|
||
-- SetVertexColor on the texture-less icon region, which draws as a solid grey plate
|
||
-- (the director's empty-wells report, 2026-07-10).
|
||
function BenillaActionBar_ForEach(fn)
|
||
for i = 1, table.getn(BENILLA_ACTION_BUTTONS) do
|
||
local button = BENILLA_ACTION_BUTTONS[i]
|
||
if HasAction(BenillaActionButton_Action(button)) then
|
||
fn(button)
|
||
end
|
||
end
|
||
end
|
||
|
||
function BenillaActionBar_OnEvent(frame)
|
||
-- The form/stance/stealth edge (ref BonusActionBar_OnEvent:20-35): start the overlay
|
||
-- slide, then FALL THROUGH to the tail — the roster repaint under the new state is
|
||
-- the same statement for this event as for any other. Deliberately in the handler
|
||
-- that repaints, not a second OnEvent on the overlay frame: one handler means the
|
||
-- slide state is set before any button paints, so there is no one-frame flash of the
|
||
-- new page before the suppression lands.
|
||
if event == "UPDATE_BONUS_ACTIONBAR" then
|
||
if GetBonusBarOffset() <= 0 then
|
||
HideBonusActionBar()
|
||
else
|
||
BonusActionBarFrame.lastBonusBar = GetBonusBarOffset()
|
||
ShowBonusActionBar()
|
||
end
|
||
end
|
||
-- ACTIONBAR_SLOT_CHANGED names its action in arg1; repaint just the button showing it.
|
||
if event == "ACTIONBAR_SLOT_CHANGED" and arg1 then
|
||
for i = 1, table.getn(BENILLA_ACTION_BUTTONS) do
|
||
local button = BENILLA_ACTION_BUTTONS[i]
|
||
if BenillaActionButton_Action(button) == arg1 then
|
||
BenillaActionButton_Update(button)
|
||
end
|
||
end
|
||
return
|
||
end
|
||
if event == "UPDATE_BINDINGS" then
|
||
BenillaActionBar_UpdateHotkeys()
|
||
return
|
||
end
|
||
-- The ref ActionButton_OnEvent dispatch (l.332-362), fanned bar-level:
|
||
if event == "ACTIONBAR_UPDATE_STATE" then
|
||
BenillaActionBar_ForEach(BenillaActionButton_UpdateState)
|
||
return
|
||
end
|
||
if event == "ACTIONBAR_UPDATE_USABLE" or event == "ACTIONBAR_UPDATE_COOLDOWN" then
|
||
BenillaActionBar_ForEach(BenillaActionButton_UpdateUsable)
|
||
BenillaActionBar_ForEach(BenillaActionButton_UpdateCooldown)
|
||
return
|
||
end
|
||
if event == "PLAYER_TARGET_CHANGED" or event == "PLAYER_AURAS_CHANGED" then
|
||
BenillaActionBar_ForEach(BenillaActionButton_UpdateUsable)
|
||
return
|
||
end
|
||
if event == "PLAYER_ENTER_COMBAT" then
|
||
BenillaActionBar_ForEach(function(b)
|
||
if IsAttackAction(BenillaActionButton_Action(b)) then
|
||
BenillaActionButton_StartFlash(b)
|
||
end
|
||
end)
|
||
return
|
||
end
|
||
if event == "PLAYER_LEAVE_COMBAT" then
|
||
BenillaActionBar_ForEach(function(b)
|
||
if IsAttackAction(BenillaActionButton_Action(b)) then
|
||
BenillaActionButton_StopFlash(b)
|
||
end
|
||
end)
|
||
return
|
||
end
|
||
if event == "START_AUTOREPEAT_SPELL" then
|
||
BenillaActionBar_ForEach(function(b)
|
||
if IsAutoRepeatAction(BenillaActionButton_Action(b)) then
|
||
BenillaActionButton_StartFlash(b)
|
||
end
|
||
end)
|
||
return
|
||
end
|
||
if event == "STOP_AUTOREPEAT_SPELL" then
|
||
BenillaActionBar_ForEach(function(b)
|
||
if b.flashing == 1 and not IsAttackAction(BenillaActionButton_Action(b)) then
|
||
BenillaActionButton_StopFlash(b)
|
||
end
|
||
end)
|
||
return
|
||
end
|
||
-- The payload edge, routed through the two PUBLISHED verbs rather than a private flag
|
||
-- — which is what makes Bartender2's `self:Hook("ActionButton_ShowGrid")` see a cursor
|
||
-- pick-up at all. The engine fires this pair strictly on the cursor's None↔Some edges
|
||
-- (`script/model.rs`), so the count it drives is balanced by construction.
|
||
if event == "ACTIONBAR_SHOWGRID" or event == "ACTIONBAR_HIDEGRID" then
|
||
local show = (event == "ACTIONBAR_SHOWGRID")
|
||
for i = 1, table.getn(BENILLA_ACTION_BUTTONS) do
|
||
if show then
|
||
ActionButton_ShowGrid(BENILLA_ACTION_BUTTONS[i])
|
||
else
|
||
ActionButton_HideGrid(BENILLA_ACTION_BUTTONS[i])
|
||
end
|
||
end
|
||
return -- each verb already repainted its own button
|
||
end
|
||
for i = 1, table.getn(BENILLA_ACTION_BUTTONS) do
|
||
BenillaActionButton_Update(BENILLA_ACTION_BUTTONS[i])
|
||
end
|
||
end
|
||
|
||
-- The XP bar (ref-MainMenuBar.lua MainMenuExpBar_Update): value = current XP within the
|
||
-- level, max = XP-to-level. Both from the player-global UnitXP feed (PLAYER_XP /
|
||
-- PLAYER_NEXT_LEVEL_XP). currXP >= 0 so min(0,currXP) is just 0.
|
||
function MainMenuExpBar_Update()
|
||
local bar = this
|
||
local currXP = UnitXP("player")
|
||
local nextXP = UnitXPMax("player")
|
||
bar:SetMinMaxValues(0, nextXP)
|
||
bar:SetValue(currXP)
|
||
end
|
||
|
||
function BenillaExpBar_OnLoad(bar)
|
||
bar:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||
bar:RegisterEvent("PLAYER_XP_UPDATE")
|
||
-- The numerals seam (ref-MainMenuBar.xml l.117-120: TextStatusBar_Initialize() +
|
||
-- textLockable in the bar's own OnLoad; TextStatusBar.xml). textLockable is what lets
|
||
-- the statusBarText cvar pin the numerals on permanently.
|
||
if TextStatusBar_Initialize then -- engine tests load file subsets
|
||
TextStatusBar_Initialize()
|
||
bar.textLockable = 1
|
||
end
|
||
MainMenuExpBar_Update()
|
||
end
|
||
|
||
-- ref-MainMenuBar.xml l.121-126: repaint, then hand arg1/arg2 to the CVAR_UPDATE watcher.
|
||
function BenillaExpBar_OnEvent(bar)
|
||
MainMenuExpBar_Update()
|
||
if TextStatusBar_OnEvent then TextStatusBar_OnEvent(arg1, arg2) end
|
||
end
|
||
|
||
-- The XP bar's hover (ref-MainMenuBar.xml l.136-147, MainMenuExpBar's own OnEnter/OnLeave).
|
||
-- ref GlobalStrings.lua l.5461 / l.2789 / l.1929-1932 (enUS), in the `X = X or` FALLBACK
|
||
-- form: the app runs the real localized GlobalStrings.lua off the patch chain BEFORE this
|
||
-- file (ui_script/mod.rs load_global_strings), so the installed locale wins and these
|
||
-- copies only fill in for the test harnesses, which load no patch chain.
|
||
-- CombatText.xml's shape.
|
||
XPBAR_LABEL = XPBAR_LABEL or "XP Bar"
|
||
NEWBIE_TOOLTIP_XPBAR = NEWBIE_TOOLTIP_XPBAR or "The amount of experience (XP) you have earned. The color of the XP bar indicates your rest state: light blue for Rested, and purple for Normal. Rested players earn twice the experience they would normally gain from slaying a monster. Characters become less rested when they kill monsters, and more rested by spending time at or logging out at an inn or city."
|
||
EXHAUST_TOOLTIP1 = EXHAUST_TOOLTIP1 or "|cffffd200%s|r\n|cffffffff%d%% of normal experience\ngained from monsters.|r"
|
||
EXHAUST_TOOLTIP2 = EXHAUST_TOOLTIP2 or "\n|cffff0000You should rest at an Inn.|r"
|
||
EXHAUST_TOOLTIP4 = EXHAUST_TOOLTIP4 or "\n\n|cffffd200Resting|r\n|cffffffffYou must rest for %d additional\nminutes to become|r |cffffd200Fully Rested|r|cffffffff.|r"
|
||
|
||
-- The ref OnEnter's full body (ref-MainMenuBar.xml l.136-141), now that its machinery
|
||
-- exists (decision 1082): the on-bar numerals (TextStatusBar.xml), the 1 s armed timer
|
||
-- that appends the rest-state line to the held-open tooltip, and canAddRestStateLine —
|
||
-- the handshake ExhaustionToolTipText's newbie-tips branch reads. The trailing 1
|
||
-- is the ref's noNormalText: with detailed tips OFF this hover shows NOTHING rather than
|
||
-- a bare "XP Bar". Transcribed, though 1.12's default (0661) never takes it.
|
||
function BenillaExpBar_OnEnter(bar)
|
||
if TextStatusBar_UpdateTextString then -- engine tests load file subsets
|
||
TextStatusBar_UpdateTextString(bar)
|
||
ShowTextStatusBarText(bar)
|
||
end
|
||
ExhaustionTick.timer = 1
|
||
if not GameTooltip_AddNewbieTip then return end
|
||
BenillaTooltip_AddNewbieTipFor(bar, XPBAR_LABEL, 1.0, 1.0, 1.0, NEWBIE_TOOLTIP_XPBAR, 1)
|
||
GameTooltip.canAddRestStateLine = 1
|
||
end
|
||
|
||
function BenillaExpBar_OnLeave(bar)
|
||
if HideTextStatusBarText then HideTextStatusBarText(bar) end
|
||
if GameTooltip then GameTooltip:Hide() end
|
||
ExhaustionTick.timer = nil
|
||
end
|
||
|
||
-- ══ The reputation WATCH BAR (ref-ReputationFrame.xml l.869-1036 + ref-ReputationFrame.lua
|
||
-- l.3-14 and l.161-270) ═══════════════════════════════════════════════════════════════
|
||
--
|
||
-- **THE PLACEMENT IS A DELIBERATE CALL, and this is its justification.** The reference
|
||
-- declares `ReputationWatchBar` and defines its update, its two text verbs, MAX_PLAYER_LEVEL
|
||
-- and FACTION_BAR_COLORS in `ReputationFrame.{xml,lua}`, because FrameXML loads MainMenuBar
|
||
-- and ReputationFrame in one breath and neither can exist without the other. benilla's
|
||
-- manifest is not one breath: this file is entry 94, `ReputationFrame.xml` is 213, and the
|
||
-- engine's per-window test harnesses deliberately load FILE SUBSETS — the XP bar's harness
|
||
-- loads no character window, the character window's loads no action bar.
|
||
--
|
||
-- Every frame `ReputationWatchBar_Update` touches except the watch bar itself is declared
|
||
-- in THIS file: MainMenuExpBar, MainMenuBarMaxLevelBar, ExhaustionTick, MainMenuBarArtFrame
|
||
-- and MainMenuBar. So does every frame that reads the bar back: `ExhaustionTick_Update`
|
||
-- below consults `ReputationWatchBar:IsShown()` twice, which is the reference's own pair of
|
||
-- guards. Splitting the bar's FRAME from the bar's UPDATE across a 120-entry manifest gap
|
||
-- would leave each subset holding half a mechanism and would put a nil-guard on every one
|
||
-- of those sites — the exact "special case to dodge a problem" shape the contract forbids.
|
||
-- The bar therefore stays whole, in the file that owns its collaborators, and
|
||
-- `ReputationFrame.xml` — which owns the PANE — reaches `ReputationWatchBar_Update()` by
|
||
-- name at click time, the direction that always resolves.
|
||
--
|
||
-- What DID move is the half-mechanism. `BenillaMaxLevelBar_Update` covered "the
|
||
-- no-watched-faction branch only" of the reference's function, parked on the rail frame
|
||
-- because the watch bar was driven by nothing; it is gone, replaced in place by the whole
|
||
-- `ReputationWatchBar_Update(newLevel)`. `MainMenuBarMaxLevelBar` accordingly carries NO
|
||
-- scripts any more — the reference's rail carries none either, because this function is its
|
||
-- only driver — and the event fan that sat on it is now the watch bar's own OnLoad/OnEvent,
|
||
-- which is where the reference puts it.
|
||
MAX_PLAYER_LEVEL = 60 -- ref-ReputationFrame.lua l.14 (with the ref's own "Hard coded =(")
|
||
|
||
-- The eight rank colours, quoted from ref-ReputationFrame.lua l.3-12 — a table of the
|
||
-- client's own rgb facts, which have no other value they could take. Indexed by the 1-based
|
||
-- standingID both `GetFactionInfo` and `GetWatchedFactionInfo` report (benilla-ui
|
||
-- `script::reputation`), so the pane's 15 bars and this one bar can never disagree about a
|
||
-- colour. Declared HERE rather than in ReputationFrame.xml (its reference home) for the
|
||
-- placement reason above: this file must be able to index it with no reputation file
|
||
-- loaded, and ReputationFrame.xml cannot be loaded without this one.
|
||
FACTION_BAR_COLORS = {
|
||
[1] = { r = 0.8, g = 0.3, b = 0.22 },
|
||
[2] = { r = 0.8, g = 0.3, b = 0.22 },
|
||
[3] = { r = 0.75, g = 0.27, b = 0 },
|
||
[4] = { r = 0.9, g = 0.7, b = 0 },
|
||
[5] = { r = 0, g = 0.6, b = 0.1 },
|
||
[6] = { r = 0, g = 0.6, b = 0.1 },
|
||
[7] = { r = 0, g = 0.6, b = 0.1 },
|
||
[8] = { r = 0, g = 0.6, b = 0.1 },
|
||
}
|
||
|
||
-- THE TWO POSTURES the watched strip can take, as data. `ref-ReputationFrame.lua`
|
||
-- l.184-230 is the specification and every number below is quoted from it; the shape is
|
||
-- ours, because the reference's two arms differ in exactly four numbers and which of the
|
||
-- two end-art sets is up, and that is a table and one application rather than two
|
||
-- hand-written branches that have to be diffed to be read.
|
||
--
|
||
-- STACKED is the below-max-level posture: an 8px strip sitting 3 above MainMenuBar, wearing
|
||
-- the UI-ReputationWatchBar end art, with the XP bar still underneath it. REPLACING is the
|
||
-- max-level one: 13px on MainMenuBar's own TOP, wearing the dwarf XP-bar art instead so the
|
||
-- strip reads as the bar it took over from.
|
||
BENILLA_WATCHBAR_POSTURE = {
|
||
stacked = { height = 8, seat = "BOTTOM", seatY = -3, textY = 3, art = "ReputationWatchBarTexture" },
|
||
replacing = { height = 13, seat = "TOP", seatY = 0, textY = 1, art = "ReputationXPBarTexture" },
|
||
}
|
||
|
||
-- Seat the strip in one posture and take the other's art down with it. Both end-art sets
|
||
-- are four 256-wide slices of the 1024 strip, named `<set>0` .. `<set>3`.
|
||
function BenillaWatchBar_SetPosture(stacked)
|
||
local wear, drop = BENILLA_WATCHBAR_POSTURE.replacing, BENILLA_WATCHBAR_POSTURE.stacked
|
||
if stacked then
|
||
wear, drop = drop, wear
|
||
end
|
||
ReputationWatchStatusBar:SetHeight(wear.height)
|
||
ReputationWatchBar:ClearAllPoints()
|
||
ReputationWatchBar:SetPoint(wear.seat, MainMenuBar, "TOP", 0, wear.seatY)
|
||
ReputationWatchStatusBarText:SetPoint("CENTER", ReputationWatchBarOverlayFrame, "CENTER", 0, wear.textY)
|
||
for slice = 0, 3 do
|
||
getglobal(wear.art .. slice):Show()
|
||
getglobal(drop.art .. slice):Hide()
|
||
end
|
||
end
|
||
|
||
-- The XP strip and the rested tick that rides it go up and down together: with no strip
|
||
-- there is nothing for the tick to sit on. Every site the reference hides the strip from it
|
||
-- also hides the tick, and `ExhaustionTick_Update` enforces the same rule from the other
|
||
-- side on every event (its own last statement) — so it is one verb, not a pairing three
|
||
-- call sites have to remember.
|
||
function BenillaExpStrip_SetShown(shown)
|
||
if shown then
|
||
MainMenuExpBar:Show()
|
||
else
|
||
MainMenuExpBar:Hide()
|
||
ExhaustionTick:Hide()
|
||
end
|
||
end
|
||
|
||
-- The watched faction's strip on the main bar — `ref-ReputationFrame.lua`
|
||
-- `ReputationWatchBar_Update` (l.161-250) is the specification. THREE states: a watched
|
||
-- faction takes one of the two postures above (the level picks), and no watched faction
|
||
-- leaves the XP bar — or, at max level, the brass rail — holding that space instead.
|
||
--
|
||
-- `newLevel` is the reference's own parameter: PLAYER_LEVEL_UP carries the new level as
|
||
-- arg1 because the level FIELD may not have landed yet, and every other caller re-reads
|
||
-- UnitLevel. Note the two level tests are deliberately NOT the same test: watched forks on
|
||
-- `< MAX_PLAYER_LEVEL`, unwatched on `== MAX_PLAYER_LEVEL`, which is the reference's own
|
||
-- asymmetry and only differs above the cap, where nothing can go.
|
||
--
|
||
-- ONE GUARD ADDED, at the tail: `updateContainerFrameAnchors` is defined by
|
||
-- ContainerFrameAdapters.xml (manifest 206, below this file), and a harness that shows this
|
||
-- bar without it would take a nil call on a line that only ever runs on a visibility flip.
|
||
-- The `if <global> then` shape is this codebase's own subset-load idiom (CharacterFrame.xml's
|
||
-- `if UpdateMicroButtons then`). `UIParent_ManageFramePositions` needs no such guard:
|
||
-- UIParent.xml is manifest 42, above every consumer.
|
||
function ReputationWatchBar_Update(newLevel)
|
||
newLevel = newLevel or UnitLevel("player")
|
||
local name, reaction, rankMin, rankMax, standing = GetWatchedFactionInfo()
|
||
-- Whether the strip's visibility FLIPS is all the tail below needs, so read it once
|
||
-- here and compare once at the end rather than threading a flag through both arms.
|
||
local wasShown = ReputationWatchBar:IsShown()
|
||
if name then
|
||
-- The engine reports the rank window ABSOLUTE for exactly this reason (benilla-ui
|
||
-- `script::reputation`'s module doc): the strip's range is the window's WIDTH, and
|
||
-- its value the distance into it.
|
||
local width = rankMax - rankMin
|
||
local progress = standing - rankMin
|
||
ReputationWatchStatusBar:SetMinMaxValues(0, width)
|
||
ReputationWatchStatusBar:SetValue(progress)
|
||
ReputationWatchStatusBarText:SetText(name .. " " .. progress .. " / " .. width)
|
||
local color = FACTION_BAR_COLORS[reaction]
|
||
ReputationWatchStatusBar:SetStatusBarColor(color.r, color.g, color.b)
|
||
ReputationWatchBar:Show()
|
||
ReputationWatchStatusBar:SetFrameLevel(MainMenuBarArtFrame:GetFrameLevel() - 1)
|
||
|
||
-- Stacked, the XP bar is still the bar underneath; replacing, it goes away with its
|
||
-- tick. Either way the brass rail is not wanted — the strip fills that space.
|
||
local stacked = newLevel < MAX_PLAYER_LEVEL
|
||
BenillaWatchBar_SetPosture(stacked)
|
||
BenillaExpStrip_SetShown(stacked)
|
||
MainMenuBarMaxLevelBar:Hide()
|
||
else
|
||
-- Nothing watched (the arm decision 1094 shipped alone): the strip goes down, and
|
||
-- at the cap the brass rail is what takes the XP bar's place.
|
||
ReputationWatchBar:Hide()
|
||
local capped = newLevel == MAX_PLAYER_LEVEL
|
||
BenillaExpStrip_SetShown(not capped)
|
||
if capped then
|
||
MainMenuBarMaxLevelBar:Show()
|
||
else
|
||
MainMenuBarMaxLevelBar:Hide()
|
||
end
|
||
end
|
||
if wasShown ~= ReputationWatchBar:IsShown() then
|
||
UIParent_ManageFramePositions()
|
||
if updateContainerFrameAnchors then updateContainerFrameAnchors() end
|
||
end
|
||
end
|
||
|
||
-- The numerals lock, to ref-ReputationFrame.lua l.252-270. A two-key lock: `cvarLocked`
|
||
-- records that the statusBarText cvar (not a hover) asked for the text, and `textLocked`
|
||
-- that the text is currently pinned on — which is what the bar's own OnLeave reads before
|
||
-- hiding it again. Note the Show verb only ever shows the text AT MAX LEVEL, where the
|
||
-- strip has replaced the XP bar and is tall enough to hold numerals; below that it falls
|
||
-- through to the Hide one. Both function names, both field names and the FontString are
|
||
-- the addon-visible contract; the shapes below (early exits where the ref nests) are ours.
|
||
function ShowWatchedReputationBarText(lock)
|
||
if lock then ReputationWatchBar.cvarLocked = lock end
|
||
if UnitLevel("player") ~= MAX_PLAYER_LEVEL or not ReputationWatchBar:IsVisible() then
|
||
HideWatchedReputationBarText()
|
||
return
|
||
end
|
||
ReputationWatchBar.textLocked = 1
|
||
ReputationWatchStatusBarText:Show()
|
||
end
|
||
|
||
function HideWatchedReputationBarText(unlock)
|
||
-- Same gate as the ref's `unlock or not cvarLocked`, spun as the early exit.
|
||
if not unlock and ReputationWatchBar.cvarLocked then return end
|
||
ReputationWatchStatusBarText:Hide()
|
||
ReputationWatchBar.cvarLocked = nil
|
||
ReputationWatchBar.textLocked = nil
|
||
end
|
||
|
||
-- ── The watch bar's own handlers ────────────────────────────────────────────────────────
|
||
-- Chunk functions rather than the reference's inline bodies, so the departures below have
|
||
-- somewhere to be explained (ReputationFrame.xml's chunk-boundary rule).
|
||
-- `ref-ReputationFrame.xml` l.996-1035 is the specification.
|
||
--
|
||
-- PLAYER_ENTERING_WORLD is benilla's ADDITION (decision 1094's own): our faction feed only
|
||
-- fires once the catalog and the player's race/class are up, which can be a tick or two
|
||
-- after world entry, and the max-level rail must be right from the first frame. The arm it
|
||
-- lands in is idempotent, so the extra registration only ever costs a no-op. The event fan
|
||
-- is here rather than on `MainMenuBarMaxLevelBar`, where it sat while the watch bar was
|
||
-- driven by nothing — the rail is this function's output, not its own driver.
|
||
function BenillaWatchBar_OnLoad(bar)
|
||
bar:RegisterEvent("UPDATE_FACTION")
|
||
bar:RegisterEvent("PLAYER_LEVEL_UP")
|
||
bar:RegisterEvent("CVAR_UPDATE")
|
||
bar:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||
end
|
||
|
||
-- Every event but one ends in a repaint of the bar, so the odd one out — the cvar that
|
||
-- pins the numerals on and off — is answered first and leaves.
|
||
--
|
||
-- TWO ARMS read as odd and are the reference's own:
|
||
-- · a faction push repaints the PANE, from the BAR's handler. The pane registers
|
||
-- UPDATE_FACTION itself (ReputationFrame.xml), so this is the reference double-driving
|
||
-- it; kept rather than "fixed", and harmless because the pane's repaint is idempotent.
|
||
-- Guarded on existence because this file loads WITHOUT ReputationFrame.xml in the
|
||
-- engine's per-window subset harnesses.
|
||
-- · the `statusBarText` token is DEAD CODE in shipped 1.12 and stays: the CVAR_UPDATE
|
||
-- token is the caller's third SetCVar argument, and 1.12's own options panels pass the
|
||
-- uppercase display name ("STATUS_BAR_TEXT"), never the cvar's own name (benilla-ui
|
||
-- `script::cvars`, decision 1140, which carves exactly this).
|
||
function BenillaWatchBar_OnEvent(bar, event)
|
||
if event == "CVAR_UPDATE" and arg1 == "statusBarText" then
|
||
if arg2 == "1" then ShowWatchedReputationBarText("lock") else HideWatchedReputationBarText("unlock") end
|
||
return
|
||
end
|
||
if event == "UPDATE_FACTION" and bar:IsVisible() and ReputationFrame_Update then
|
||
ReputationFrame_Update()
|
||
end
|
||
-- PLAYER_LEVEL_UP is the one event that knows the level; every other asks for nil and
|
||
-- lets the update re-read UnitLevel.
|
||
if event == "PLAYER_LEVEL_UP" then
|
||
ReputationWatchBar_Update(arg1)
|
||
else
|
||
ReputationWatchBar_Update()
|
||
end
|
||
end
|
||
|
||
-- Coming up with the cvar set means the numerals were meant to be pinned on all along.
|
||
function BenillaWatchBar_OnShow()
|
||
if GetCVar("statusBarText") == "1" then ShowWatchedReputationBarText("lock") end
|
||
UIParent_ManageFramePositions()
|
||
end
|
||
|
||
-- ── The exhaustion tick (ref-MainMenuBar.lua ExhaustionTick_*) ────────────────────────
|
||
-- The round marker riding the XP bar at the point where rested XP runs out, plus the
|
||
-- pale fill between the bar's value and that point. NOTHING of the specification is cut
|
||
-- here any more: the two ReputationWatchBar guards that used to be missing (the
|
||
-- max-level-plus-rep tick hide, ref-MainMenuBar.lua l.51-54, and the
|
||
-- rep-bar-replaced-the-xp-bar hide, l.69-71) were dropped as UNREACHABLE — the watch bar
|
||
-- could never show — and it shows now, so both are live in ExhaustionTick_Update below.
|
||
-- The MainMenuBarMaxLevelBar guard is live since 1094.
|
||
--
|
||
-- The rest-state palette, keyed by GetRestState's own state id (ref-MainMenuBar.lua
|
||
-- l.56-66 is the specification; the two rgb triples are its). Rested is the light blue,
|
||
-- normal the purple; the ids above 2 are the beta-era tiers the live server never sends and
|
||
-- the reference paints nothing for either.
|
||
BENILLA_REST_STATE_COLOR = {
|
||
[1] = { r = 0.0, g = 0.39, b = 0.88 },
|
||
[2] = { r = 0.58, g = 0.0, b = 0.55 },
|
||
}
|
||
|
||
function ExhaustionTick_OnLoad()
|
||
local tick = this
|
||
tick:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||
tick:RegisterEvent("PLAYER_XP_UPDATE")
|
||
tick:RegisterEvent("UPDATE_EXHAUSTION")
|
||
tick:RegisterEvent("PLAYER_LEVEL_UP")
|
||
tick:RegisterEvent("PLAYER_UPDATE_RESTING")
|
||
end
|
||
|
||
function ExhaustionTick_Update()
|
||
local tick = this
|
||
if event == "PLAYER_ENTERING_WORLD" or event == "PLAYER_XP_UPDATE"
|
||
or event == "UPDATE_EXHAUSTION" or event == "PLAYER_LEVEL_UP" then
|
||
local playerCurrXP = UnitXP("player")
|
||
local playerMaxXP = UnitXPMax("player")
|
||
local exhaustionThreshold = GetXPExhaustion()
|
||
local exhaustionStateID = GetRestState()
|
||
-- The ref's beta-eras leftover: the tired/exhausted tiers (id >= 3) park the tick
|
||
-- at the bar's RIGHT end. The live server never produces them (GetRestState's
|
||
-- binding note) — kept because the ref keeps it.
|
||
if exhaustionStateID >= 3 then
|
||
tick:SetPoint("CENTER", "MainMenuExpBar", "RIGHT", 0, 0)
|
||
end
|
||
if not exhaustionThreshold then
|
||
tick:Hide()
|
||
ExhaustionLevelFillBar:Hide()
|
||
else
|
||
local exhaustionTickSet = max(((playerCurrXP + exhaustionThreshold)
|
||
/ playerMaxXP) * MainMenuExpBar:GetWidth(), 0)
|
||
tick:ClearAllPoints()
|
||
if exhaustionTickSet > MainMenuExpBar:GetWidth()
|
||
or MainMenuBarMaxLevelBar:IsShown() then
|
||
tick:Hide()
|
||
ExhaustionLevelFillBar:Hide()
|
||
else
|
||
tick:Show()
|
||
tick:SetPoint("CENTER", "MainMenuExpBar", "LEFT", exhaustionTickSet, 0)
|
||
ExhaustionLevelFillBar:Show()
|
||
ExhaustionLevelFillBar:SetPoint("TOPRIGHT", "MainMenuExpBar",
|
||
"TOPLEFT", exhaustionTickSet, 0)
|
||
end
|
||
end
|
||
-- ref-MainMenuBar.lua l.51-54: at max level with a watched faction the strip the
|
||
-- tick rides is the REPUTATION bar, which has no rested pool — hide the tick.
|
||
if UnitLevel("player") == MAX_PLAYER_LEVEL and ReputationWatchBar:IsShown() then ExhaustionTick:Hide() end
|
||
end
|
||
-- The rest-state paint (only these two events repaint it, the ref's own split): one
|
||
-- rest state, one hue, worn by all three pieces at once — the strip's fill, the pale
|
||
-- wash up to the tick at a sixth alpha, and the tick's own ADD highlight. A state with
|
||
-- no row paints nothing, which is what the reference's if/elseif does for every id but
|
||
-- these two (and GetRestState answers nil off a wire that has not spoken yet, which
|
||
-- indexes to the same nothing).
|
||
if event == "PLAYER_ENTERING_WORLD" or event == "UPDATE_EXHAUSTION" then
|
||
local rest = BENILLA_REST_STATE_COLOR[GetRestState()]
|
||
if rest then
|
||
MainMenuExpBar:SetStatusBarColor(rest.r, rest.g, rest.b, 1.0)
|
||
ExhaustionLevelFillBar:SetVertexColor(rest.r, rest.g, rest.b, 0.15)
|
||
ExhaustionTickHighlight:SetVertexColor(rest.r, rest.g, rest.b)
|
||
end
|
||
end
|
||
-- ref-MainMenuBar.lua l.69-71, the function's own last statement: the watch bar has
|
||
-- REPLACED the XP bar (max level), so there is no XP strip left for the tick to sit on
|
||
-- whatever the event was. Distinct from the guard above, which only runs on the four
|
||
-- position events; this one runs on every one.
|
||
if ReputationWatchBar:IsShown() and not MainMenuExpBar:IsShown() then ExhaustionTick:Hide() end
|
||
end
|
||
|
||
-- The tick's tooltip (ref-MainMenuBar.lua ExhaustionToolTipText, the live branches only —
|
||
-- its own dead commented-out code is not carried). Two callers, two postures: hovering
|
||
-- the TICK anchors the plate beside it (flipped to whichever side has room); the armed
|
||
-- 1 s timer from the BAR hover instead APPENDS the line to the already-open newbie tip,
|
||
-- gated on canAddRestStateLine. EXHAUST_TOOLTIP4 (time to fully rested) needs
|
||
-- GetTimeToWellRested, which is nil on this wire — the line simply never renders,
|
||
-- faithfully (the binding's note).
|
||
function ExhaustionToolTipText()
|
||
if SHOW_NEWBIE_TIPS ~= "1" then
|
||
local x, y = ExhaustionTick:GetCenter()
|
||
if not ExhaustionTick:IsVisible() then
|
||
GameTooltip_SetDefaultAnchor(GameTooltip, UIParent)
|
||
elseif x >= (GetScreenWidth() / 2) then
|
||
GameTooltip:SetOwner(ExhaustionTick, "ANCHOR_LEFT")
|
||
else
|
||
GameTooltip:SetOwner(ExhaustionTick, "ANCHOR_RIGHT")
|
||
end
|
||
end
|
||
local exhaustionThreshold = GetXPExhaustion()
|
||
local exhaustionStateID, exhaustionStateName, exhaustionStateMultiplier = GetRestState()
|
||
exhaustionStateMultiplier = exhaustionStateMultiplier * 100
|
||
-- nil while the wire has not answered; a number (minutes) once it has.
|
||
local exhaustionCountdown = GetTimeToWellRested() and GetTimeToWellRested() / 60
|
||
local tooltipText = format(EXHAUST_TOOLTIP1, exhaustionStateName,
|
||
exhaustionStateMultiplier)
|
||
local append = nil
|
||
if IsResting() then
|
||
if exhaustionThreshold and exhaustionCountdown then append = format(EXHAUST_TOOLTIP4, exhaustionCountdown) end
|
||
elseif exhaustionStateID == 4 or exhaustionStateID == 5 then
|
||
append = EXHAUST_TOOLTIP2
|
||
end
|
||
if append then
|
||
tooltipText = tooltipText .. append
|
||
end
|
||
if SHOW_NEWBIE_TIPS ~= "1" then
|
||
GameTooltip:SetText(tooltipText)
|
||
elseif GameTooltip.canAddRestStateLine then
|
||
GameTooltip:AddLine("\n" .. tooltipText)
|
||
GameTooltip.canAddRestStateLine = nil
|
||
GameTooltip:Show()
|
||
end
|
||
end
|
||
|
||
-- Driven from the XP BAR's OnUpdate (the ref wires it there, not on the tick — the timer
|
||
-- only ever counts while the mouse is on the bar, which is what arms it).
|
||
function ExhaustionTick_OnUpdate(elapsed)
|
||
if not ExhaustionTick.timer then return end
|
||
if ExhaustionTick.timer >= 0 then
|
||
ExhaustionTick.timer = ExhaustionTick.timer - elapsed
|
||
else
|
||
ExhaustionTick.timer = nil
|
||
ExhaustionToolTipText()
|
||
end
|
||
end
|
||
|
||
-- ref-MainMenuBar.xml l.104-110 (the overlay child's OnLoad): the numerals wiring lives
|
||
-- in the OVERLAY frame's own OnLoad because there its FontString is guaranteed
|
||
-- materialized; the bar's lockShow starts at the not-hovered refcount.
|
||
function BenillaExpBarOverlay_OnLoad()
|
||
if SetTextStatusBarText then -- engine tests load file subsets
|
||
MainMenuExpBar.lockShow = 0
|
||
SetTextStatusBarText(MainMenuExpBar, MainMenuBarExpText)
|
||
end
|
||
end
|
||
|
||
-- ── The performance ("ping") meter ────────────────────────────────────────────────────
|
||
-- ref-MainMenuBar.xml l.344-407: a 16x64 frame in the bar's own right-hand recess whose
|
||
-- 20x66 bar texture is TINTED green/yellow/red by the connection's latency, plus an
|
||
-- all-points button on top for the hover tooltip. The thresholds, the 10 s poll and the
|
||
-- inline handlers below are the ref's, re-expressed out of its XML into named functions.
|
||
-- The meter shows LATENCY ONLY: 1.12 never scales the bar's height, only its color.
|
||
PERFORMANCEBAR_LOW_LATENCY = 300
|
||
PERFORMANCEBAR_MEDIUM_LATENCY = 600
|
||
PERFORMANCEBAR_UPDATE_INTERVAL = 10
|
||
|
||
-- ref-GlobalStrings.lua l.2659 / l.2689 / l.2746 (enUS), fallback form — see the XP bar's
|
||
-- note above for why these never override a real localized install.
|
||
MAINMENUBAR_LATENCY_LABEL = MAINMENUBAR_LATENCY_LABEL or "Latency:"
|
||
MILLISECONDS_ABBR = MILLISECONDS_ABBR or "ms"
|
||
NEWBIE_TOOLTIP_LATENCY = NEWBIE_TOOLTIP_LATENCY or "The average time it takes to talk with the game server. A low latency will display as a green bar, higher latencies will be yellow or even red. Consistently high latencies may indicate a problem with your Internet connection."
|
||
|
||
function BenillaPerformanceBar_OnLoad(frame)
|
||
frame.hover = nil
|
||
-- 0, not the interval: the ref's first OnUpdate tick runs the poll immediately, so the
|
||
-- bar is never briefly untinted (its texture is grey until the first SetVertexColor).
|
||
frame.updateInterval = 0
|
||
end
|
||
|
||
function BenillaPerformanceBar_TooltipText()
|
||
local _, _, latency = GetNetStats()
|
||
return MAINMENUBAR_LATENCY_LABEL .. " " .. latency .. MILLISECONDS_ABBR
|
||
end
|
||
|
||
-- ref l.389 (the held-open refresh) and l.400 (OnEnter), both the same call:
|
||
-- BenillaTooltip_AddNewbieTipFor(MAINMENUBAR_LATENCY_LABEL.." "..latency..MILLISECONDS_ABBR,
|
||
-- 1.0, 1.0, 1.0, NEWBIE_TOOLTIP_LATENCY)
|
||
-- So the reference hover is TWO lines — the number, then the wrapped explanation — seated
|
||
-- at the default screen corner, not beside the meter (GameTooltip.xml, decision 0661).
|
||
function BenillaPerformanceBar_ShowTooltip(owner)
|
||
if not GameTooltip_AddNewbieTip then return end -- engine tests load file subsets
|
||
BenillaTooltip_AddNewbieTipFor(owner, BenillaPerformanceBar_TooltipText(), 1.0, 1.0, 1.0,
|
||
NEWBIE_TOOLTIP_LATENCY)
|
||
end
|
||
|
||
function BenillaPerformanceBar_OnUpdate(frame, elapsed)
|
||
if frame.updateInterval > 0 then
|
||
frame.updateInterval = frame.updateInterval - elapsed
|
||
return
|
||
end
|
||
frame.updateInterval = PERFORMANCEBAR_UPDATE_INTERVAL
|
||
local _, _, latency = GetNetStats()
|
||
local r, g, b = 0, 1, 0
|
||
if latency > PERFORMANCEBAR_MEDIUM_LATENCY then
|
||
r, g, b = 1, 0, 0
|
||
elseif latency > PERFORMANCEBAR_LOW_LATENCY then
|
||
r, g, b = 1, 1, 0
|
||
end
|
||
MainMenuBarPerformanceBar:SetVertexColor(r, g, b)
|
||
-- Held-open tooltips re-read the number on the same 10 s beat (the ref's own refresh).
|
||
if frame.hover then
|
||
BenillaPerformanceBar_ShowTooltip(frame)
|
||
end
|
||
end
|
||
|
||
function BenillaPerformanceBar_OnEnter(button)
|
||
MainMenuBarPerformanceBarFrame.hover = 1
|
||
BenillaPerformanceBar_ShowTooltip(button)
|
||
end
|
||
|
||
function BenillaPerformanceBar_OnLeave()
|
||
MainMenuBarPerformanceBarFrame.hover = nil
|
||
if GameTooltip then GameTooltip:Hide() end
|
||
end
|
||
]]></Script>
|
||
|
||
<!--
|
||
One action button (ref-ActionButtonTemplate.xml, now the FULL template — decision 0137
|
||
phase 4): a CheckButton, 36x36 (l.3-6); icon fills the button (BACKGROUND, owner-sized,
|
||
l.8-10); Flash (UI-QuickslotRed, hidden — the auto-attack/auto-repeat blink) + HotKey
|
||
(l.11-24) + Count (l.25-33) on ARTWORK; Border (UI-ActionButton-Border 62x62 CENTER, ADD,
|
||
hidden — the equipped-item green ring, l.48-59) on OVERLAY; the Cooldown child (the ref's
|
||
CooldownFrameTemplate Model at 36x36 CENTER (0,-1), l.62-73 — ours is the native Cooldown
|
||
widget playing the same machine); NormalTexture = the 66x66 UI-Quickslot2 ring centered at
|
||
(0,-1) (l.74-85); PushedTexture UI-Quickslot-Depress (l.86); HighlightTexture
|
||
ButtonHilight-Square ADD (l.87); CheckedTexture CheckButtonHilight ADD (l.88 — the
|
||
IsCurrentAction/IsAutoRepeatAction ring); Name (the macro-name line, l.34-46) on ARTWORK,
|
||
set from `GetActionText` at the tail of every update as the ref's `ActionButton_Update`
|
||
does (decision 1636).
|
||
-->
|
||
<!-- **The reference's own two-level split, which ours used to conflate into one template.**
|
||
`ActionButtonTemplate` (ref ActionButtonTemplate.xml:3) is REGIONS ONLY and carries no
|
||
scripts at all; `ActionBarButtonTemplate` (ref ActionBarFrame.xml:4) inherits it and adds
|
||
the handler set. Addons rely on both halves being separately inheritable: `zBar.xml:7` is
|
||
`<CheckButton name="zBarButtonTemplate" inherits="ActionBarButtonTemplate">` and then
|
||
wires its OWN OnLoad, and its per-button code reads
|
||
`getglobal(button:GetName().."NormalTexture")` — a derived name it only gets by inheriting
|
||
a template that declares `$parentNormalTexture`.
|
||
2 corpus addons name `ActionBarButtonTemplate` in an XML `inherits=`; with neither name
|
||
published they got a bare frame, no art, no regions, and no error (1203's silent shape).
|
||
`BenillaActionButtonTemplate` survives below as a pure alias so every one of our own
|
||
`inherits=` sites is untouched. -->
|
||
<CheckButton name="ActionButtonTemplate" virtual="true">
|
||
<Size><AbsDimension x="36" y="36"/></Size>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="$parentIcon"/>
|
||
</Layer>
|
||
<Layer level="ARTWORK">
|
||
<Texture name="$parentFlash" file="Interface\Buttons\UI-QuickslotRed" hidden="true"/>
|
||
<FontString name="$parentHotKey" inherits="NumberFontNormalSmallGray" justifyH="RIGHT">
|
||
<Size><AbsDimension x="36" y="10"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="-2" y="-2"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
<FontString name="$parentCount" inherits="NumberFontNormal" justifyH="RIGHT">
|
||
<Anchors>
|
||
<Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="-2" y="2"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
<!-- ref ActionButtonTemplate.xml's `$parentName` — the macro-name line along the
|
||
button's bottom edge. `BenillaActionButton_Update` writes it from
|
||
`GetActionText` on every update (a MACRO slot's macro name, nil — cleared —
|
||
for any other kind); it is also part of the template's published contract, so
|
||
an addon indexing `<button>Name` gets the region. -->
|
||
<FontString name="$parentName" inherits="GameFontHighlightSmallOutline">
|
||
<Size><AbsDimension x="36" y="10"/></Size>
|
||
<Anchors>
|
||
<Anchor point="BOTTOM"><Offset><AbsDimension x="0" y="2"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
<Layer level="OVERLAY">
|
||
<Texture name="$parentBorder" file="Interface\Buttons\UI-ActionButton-Border" hidden="true" alphaMode="ADD">
|
||
<Size><AbsDimension x="62" y="62"/></Size>
|
||
<Anchors>
|
||
<Anchor point="CENTER" relativePoint="CENTER"><Offset><AbsDimension x="0" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<Cooldown name="$parentCooldown" hidden="true">
|
||
<Size><AbsDimension x="36" y="36"/></Size>
|
||
<Anchors>
|
||
<Anchor point="CENTER" relativePoint="CENTER"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor>
|
||
</Anchors>
|
||
</Cooldown>
|
||
</Frames>
|
||
<NormalTexture name="$parentNormalTexture" file="Interface\Buttons\UI-Quickslot2">
|
||
<Size><AbsDimension x="66" y="66"/></Size>
|
||
<Anchors>
|
||
<Anchor point="CENTER" relativePoint="CENTER"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor>
|
||
</Anchors>
|
||
</NormalTexture>
|
||
<PushedTexture file="Interface\Buttons\UI-Quickslot-Depress"/>
|
||
<HighlightTexture file="Interface\Buttons\ButtonHilight-Square" alphaMode="ADD"/>
|
||
<CheckedTexture file="Interface\Buttons\CheckButtonHilight" alphaMode="ADD"/>
|
||
</CheckButton>
|
||
|
||
<!-- The bar half: the reference's `ActionBarButtonTemplate`, regions inherited, handlers added. -->
|
||
<CheckButton name="ActionBarButtonTemplate" inherits="ActionButtonTemplate" virtual="true">
|
||
<Scripts>
|
||
<OnEvent>ActionButton_OnEvent()</OnEvent>
|
||
<OnClick>BenillaActionButton_OnClick(self)</OnClick>
|
||
<OnDragStart>BenillaActionButton_OnDragStart(self)</OnDragStart>
|
||
<OnReceiveDrag>BenillaActionButton_OnReceiveDrag(self)</OnReceiveDrag>
|
||
<OnUpdate>ActionButton_OnUpdate(arg1)</OnUpdate>
|
||
<OnEnter>BenillaActionButton_OnEnter(self)</OnEnter>
|
||
<OnLeave>if GameTooltip then GameTooltip:Hide() end</OnLeave>
|
||
</Scripts>
|
||
</CheckButton>
|
||
|
||
<!-- Pure alias, so every existing `inherits="BenillaActionButtonTemplate"` in this file,
|
||
MultiBars.xml, StanceBar.xml and PetActionBar.xml keeps resolving to exactly what it did
|
||
before the split. -->
|
||
<CheckButton name="BenillaActionButtonTemplate" inherits="ActionBarButtonTemplate" virtual="true"/>
|
||
|
||
<!-- The bar: 1024x53 anchored BOTTOM of the screen (ref-MainMenuBar.xml l.4-10). -->
|
||
<Frame name="MainMenuBar">
|
||
<Size><AbsDimension x="1024" y="53"/></Size>
|
||
<Anchors>
|
||
<Anchor point="BOTTOM" relativePoint="BOTTOM"><Offset><AbsDimension x="0" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Frames>
|
||
<!--
|
||
The XP StatusBar: 1024x13 anchored TOP of the bar (ref-MainMenuBar.xml l.12-18).
|
||
BarTexture UI-StatusBar, BarColor purple (0.58,0,0.55) (l.158-159); a solid black
|
||
a=0.5 BACKGROUND (l.89-93); and the 4 dwarf-notch OVERLAY strips (256x10, BOTTOM
|
||
x=-384/-128/128/384 y=3, the tick TexCoord bands l.36-87) that frame the fill.
|
||
Drawn first among the bar's children ⇒ lowest, so the dwarf art overlaps it (the
|
||
real RaiseFrameLevel(art) order).
|
||
-->
|
||
<!-- enableMouse: the ref's MainMenuExpBar takes the mouse for its own hover (l.136-147).
|
||
The strip is the bar's top 13 px, clear of every button on it. -->
|
||
<StatusBar name="MainMenuExpBar" enableMouse="true">
|
||
<Size><AbsDimension x="1024" y="13"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOP" relativePoint="TOP"><Offset><AbsDimension x="0" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture>
|
||
<Color r="0.0" g="0.0" b="0.0" a="0.5"/>
|
||
</Texture>
|
||
</Layer>
|
||
<Layer level="BORDER">
|
||
<!-- The rested fill (ref-MainMenuBar.xml l.20-33 ExhaustionLevelFillBar):
|
||
the pale wash from the bar's LEFT edge to the exhaustion tick. 0-wide
|
||
until ExhaustionTick_Update stretches its TOPRIGHT to the tick
|
||
and tints it (SetVertexColor a=0.15 over this authored white). -->
|
||
<Texture name="ExhaustionLevelFillBar">
|
||
<Size><AbsDimension x="0" y="13"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="MainMenuExpBar"><Offset><AbsDimension x="0" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Color r="1.0" g="1.0" b="1.0" a="1.0"/>
|
||
</Texture>
|
||
</Layer>
|
||
<Layer level="OVERLAY">
|
||
<Texture name="MainMenuXPBarTexture0" file="Interface\MainMenuBar\UI-MainMenuBar-Dwarf">
|
||
<Size><AbsDimension x="256" y="10"/></Size>
|
||
<Anchors><Anchor point="BOTTOM" relativePoint="BOTTOM"><Offset><AbsDimension x="-384" y="3"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="0" right="1.0" top="0.79296875" bottom="0.83203125"/>
|
||
</Texture>
|
||
<Texture name="MainMenuXPBarTexture1" file="Interface\MainMenuBar\UI-MainMenuBar-Dwarf">
|
||
<Size><AbsDimension x="256" y="10"/></Size>
|
||
<Anchors><Anchor point="BOTTOM" relativePoint="BOTTOM"><Offset><AbsDimension x="-128" y="3"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="0" right="1.0" top="0.54296875" bottom="0.58203125"/>
|
||
</Texture>
|
||
<Texture name="MainMenuXPBarTexture2" file="Interface\MainMenuBar\UI-MainMenuBar-Dwarf">
|
||
<Size><AbsDimension x="256" y="10"/></Size>
|
||
<Anchors><Anchor point="BOTTOM" relativePoint="BOTTOM"><Offset><AbsDimension x="128" y="3"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="0" right="1.0" top="0.29296875" bottom="0.33203125"/>
|
||
</Texture>
|
||
<Texture name="MainMenuXPBarTexture3" file="Interface\MainMenuBar\UI-MainMenuBar-Dwarf">
|
||
<Size><AbsDimension x="256" y="10"/></Size>
|
||
<Anchors><Anchor point="BOTTOM" relativePoint="BOTTOM"><Offset><AbsDimension x="384" y="3"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="0" right="1.0" top="0.04296875" bottom="0.08203125"/>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- The numerals overlay (ref-MainMenuBar.xml l.96-113 MainMenuBarOverlayFrame):
|
||
a DIALOG-strata child so the "1234 / 5678" text draws over the dwarf-notch
|
||
art and the buttons; its own OnLoad wires the FontString to the bar
|
||
(BenillaExpBarOverlay_OnLoad's note). -->
|
||
<Frame name="MainMenuBarOverlayFrame" frameStrata="DIALOG">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="MainMenuBar" relativePoint="TOPLEFT"/>
|
||
<Anchor point="BOTTOMRIGHT" relativeTo="MainMenuBar" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="ARTWORK">
|
||
<FontString name="MainMenuBarExpText" inherits="TextStatusBarText">
|
||
<Anchors>
|
||
<Anchor point="CENTER" relativeTo="MainMenuExpBar"><Offset><AbsDimension x="0" y="1"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Scripts>
|
||
<OnLoad>BenillaExpBarOverlay_OnLoad()</OnLoad>
|
||
</Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
<BarTexture file="Interface\TargetingFrame\UI-StatusBar"/>
|
||
<BarColor r="0.58" g="0.0" b="0.55"/>
|
||
<Scripts>
|
||
<OnLoad>BenillaExpBar_OnLoad(self)</OnLoad>
|
||
<OnEvent>BenillaExpBar_OnEvent(self)</OnEvent>
|
||
<OnEnter>BenillaExpBar_OnEnter(self)</OnEnter>
|
||
<OnLeave>BenillaExpBar_OnLeave(self)</OnLeave>
|
||
<OnUpdate>ExhaustionTick_OnUpdate(arg1)</OnUpdate>
|
||
<OnValueChanged>
|
||
if this:IsShown() and TextStatusBar_OnValueChanged then
|
||
TextStatusBar_OnValueChanged()
|
||
end
|
||
</OnValueChanged>
|
||
</Scripts>
|
||
</StatusBar>
|
||
|
||
<!--
|
||
The exhaustion tick (ref-MainMenuBar.xml l.415-442): a 32×32 button riding the XP
|
||
bar at the rested boundary, DIALOG strata so it draws over the bar art. Normal =
|
||
the brass marker, Highlight = the ADD glow ExhaustionTick_Update tints to
|
||
the rest state. Starts at the bar's CENTER exactly like the ref (its own first
|
||
Update re-seats or hides it before anything is seen).
|
||
-->
|
||
<Button name="ExhaustionTick" frameStrata="DIALOG">
|
||
<Size><AbsDimension x="32" y="32"/></Size>
|
||
<Anchors>
|
||
<Anchor point="CENTER" relativeTo="MainMenuExpBar"><Offset><AbsDimension x="0" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts>
|
||
<OnLoad>ExhaustionTick_OnLoad()</OnLoad>
|
||
<OnEvent>ExhaustionTick_Update()</OnEvent>
|
||
<OnEnter>ExhaustionToolTipText()</OnEnter>
|
||
<OnLeave>if GameTooltip then GameTooltip:Hide() end</OnLeave>
|
||
</Scripts>
|
||
<NormalTexture name="ExhaustionTickNormal" file="Interface\MainMenuBar\UI-ExhaustionTickNormal"/>
|
||
<HighlightTexture name="ExhaustionTickHighlight" file="Interface\MainMenuBar\UI-ExhaustionTickHighlight" alphaMode="ADD"/>
|
||
</Button>
|
||
|
||
<!--
|
||
The max-level rail (ref-MainMenuBar.xml l.161-225 MainMenuBarMaxLevelBar): the
|
||
flat brass rail that replaces the XP strip at MAX_PLAYER_LEVEL — four 256×7
|
||
quarters of UI-MainMenuBar-MaxLevel, riding just above the frame's own 7 px rect
|
||
(each quarter's BOTTOM sits on the frame's TOP, the ref's own geometry).
|
||
Shown and hidden by ReputationWatchBar_Update (above) and by nothing else — which
|
||
is the reference's own arrangement, and why this frame carries NO Scripts. It held
|
||
a benilla OnLoad/OnEvent pair while the watch bar was driven by nothing (decision
|
||
1094); those were a transcription of the WATCH BAR's own handlers parked here, and
|
||
they have gone back to it. The ref's OnShow/OnHide call
|
||
UIParent_ManageFramePositions, which benilla doesn't build
|
||
(DurabilityFrame.xml's note) — a named cut.
|
||
-->
|
||
<Frame name="MainMenuBarMaxLevelBar" enableMouse="true" hidden="true">
|
||
<Size><AbsDimension x="1024" y="7"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOP" relativePoint="TOP"><Offset><AbsDimension x="0" y="-11"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="MainMenuMaxLevelBar0" file="Interface\MainMenuBar\UI-MainMenuBar-MaxLevel">
|
||
<Size><AbsDimension x="256" y="7"/></Size>
|
||
<Anchors>
|
||
<Anchor point="BOTTOM" relativePoint="TOP"><Offset><AbsDimension x="-384" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<TexCoords left="0" right="1.0" top="0" bottom="0.21875"/>
|
||
</Texture>
|
||
<Texture name="MainMenuMaxLevelBar1" file="Interface\MainMenuBar\UI-MainMenuBar-MaxLevel">
|
||
<Size><AbsDimension x="256" y="7"/></Size>
|
||
<Anchors>
|
||
<Anchor point="LEFT" relativeTo="MainMenuMaxLevelBar0" relativePoint="RIGHT"/>
|
||
</Anchors>
|
||
<TexCoords left="0" right="1.0" top="0.25" bottom="0.46875"/>
|
||
</Texture>
|
||
<Texture name="MainMenuMaxLevelBar2" file="Interface\MainMenuBar\UI-MainMenuBar-MaxLevel">
|
||
<Size><AbsDimension x="256" y="7"/></Size>
|
||
<Anchors>
|
||
<Anchor point="LEFT" relativeTo="MainMenuMaxLevelBar1" relativePoint="RIGHT"/>
|
||
</Anchors>
|
||
<TexCoords left="0" right="1.0" top="0.5" bottom="0.71875"/>
|
||
</Texture>
|
||
<Texture name="MainMenuMaxLevelBar3" file="Interface\MainMenuBar\UI-MainMenuBar-MaxLevel">
|
||
<Size><AbsDimension x="256" y="7"/></Size>
|
||
<Anchors>
|
||
<Anchor point="LEFT" relativeTo="MainMenuMaxLevelBar2" relativePoint="RIGHT"/>
|
||
</Anchors>
|
||
<TexCoords left="0" right="1.0" top="0.75" bottom="0.96875"/>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
</Frame>
|
||
|
||
<!--
|
||
The art frame: fills the bar (ref-MainMenuBar.xml l.225-229). Carries the 4 dwarf
|
||
strips (ARTWORK) + the 2 end caps and page number (OVERLAY); the buttons are its
|
||
children so they draw over the art.
|
||
-->
|
||
<Frame name="MainMenuBarArtFrame">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="MainMenuBar" relativePoint="TOPLEFT"/>
|
||
<Anchor point="BOTTOMRIGHT" relativeTo="MainMenuBar" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
<Layers>
|
||
<!-- 4 dwarf strips: 256x43, BOTTOM x=-384/-128/128/384 y=0, TexCoord bands
|
||
(ref-MainMenuBar.xml l.232-283). Adjacent atlas rows ⇒ the joins are seamless. -->
|
||
<Layer level="ARTWORK">
|
||
<Texture name="MainMenuBarTexture0" file="Interface\MainMenuBar\UI-MainMenuBar-Dwarf">
|
||
<Size><AbsDimension x="256" y="43"/></Size>
|
||
<Anchors><Anchor point="BOTTOM" relativePoint="BOTTOM"><Offset><AbsDimension x="-384" y="0"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="0" right="1.0" top="0.83203125" bottom="1.0"/>
|
||
</Texture>
|
||
<Texture name="MainMenuBarTexture1" file="Interface\MainMenuBar\UI-MainMenuBar-Dwarf">
|
||
<Size><AbsDimension x="256" y="43"/></Size>
|
||
<Anchors><Anchor point="BOTTOM" relativePoint="BOTTOM"><Offset><AbsDimension x="-128" y="0"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="0" right="1.0" top="0.58203125" bottom="0.75"/>
|
||
</Texture>
|
||
<Texture name="MainMenuBarTexture2" file="Interface\MainMenuBar\UI-MainMenuBar-Dwarf">
|
||
<Size><AbsDimension x="256" y="43"/></Size>
|
||
<Anchors><Anchor point="BOTTOM" relativePoint="BOTTOM"><Offset><AbsDimension x="128" y="0"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="0" right="1.0" top="0.33203125" bottom="0.5"/>
|
||
</Texture>
|
||
<Texture name="MainMenuBarTexture3" file="Interface\MainMenuBar\UI-MainMenuBar-Dwarf">
|
||
<Size><AbsDimension x="256" y="43"/></Size>
|
||
<Anchors><Anchor point="BOTTOM" relativePoint="BOTTOM"><Offset><AbsDimension x="384" y="0"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="0" right="1.0" top="0.08203125" bottom="0.25"/>
|
||
</Texture>
|
||
</Layer>
|
||
<!-- End caps: UI-MainMenuBar-EndCap-Dwarf 128x128, BOTTOM x=-544 / +544; the RIGHT
|
||
cap mirrors its art with TexCoords (1.0, 0.0, 0.0, 1.0) so the lion faces
|
||
outward on both sides (ref-MainMenuBar.xml l.286-310; the mirrored-UV engine
|
||
fix landed in 87c97d7). Page number: GameFontNormalSmall CENTER (30,-5),
|
||
static "1" (l.311-319). -->
|
||
<Layer level="OVERLAY">
|
||
<Texture name="MainMenuBarLeftEndCap" file="Interface\MainMenuBar\UI-MainMenuBar-EndCap-Dwarf">
|
||
<Size><AbsDimension x="128" y="128"/></Size>
|
||
<Anchors><Anchor point="BOTTOM" relativePoint="BOTTOM"><Offset><AbsDimension x="-544" y="0"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
<Texture name="MainMenuBarRightEndCap" file="Interface\MainMenuBar\UI-MainMenuBar-EndCap-Dwarf">
|
||
<Size><AbsDimension x="128" y="128"/></Size>
|
||
<Anchors><Anchor point="BOTTOM" relativePoint="BOTTOM"><Offset><AbsDimension x="544" y="0"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="1.0" right="0.0" top="0.0" bottom="1.0"/>
|
||
</Texture>
|
||
<!-- The page numeral. `text="1"` is the LOAD SEED the ref gets from the up
|
||
arrow's OnLoad (`SetText(CURRENT_ACTIONBAR_PAGE)`, which is 1 there
|
||
too); every change after that comes through `ChangeActionBarPage`. -->
|
||
<FontString name="MainMenuBarPageNumber" inherits="GameFontNormalSmall" text="1">
|
||
<Anchors>
|
||
<Anchor point="CENTER" relativePoint="CENTER"><Offset><AbsDimension x="30" y="-5"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- The 12 buttons: Button1 at the art frame BOTTOMLEFT (8,4); 2..12 chain LEFT of
|
||
the previous's RIGHT +6,0 (ref-ActionBarFrame.xml l.51-158). Replaces our old
|
||
fixed 38px stride with the real 42px chain (36 wide + 6 gap). -->
|
||
<CheckButton name="ActionButton1" inherits="BenillaActionButtonTemplate">
|
||
<Anchors><Anchor point="BOTTOMLEFT" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="8" y="4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 1)</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="ActionButton2" inherits="BenillaActionButtonTemplate">
|
||
<Anchors><Anchor point="LEFT" relativeTo="ActionButton1" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 2)</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="ActionButton3" inherits="BenillaActionButtonTemplate">
|
||
<Anchors><Anchor point="LEFT" relativeTo="ActionButton2" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 3)</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="ActionButton4" inherits="BenillaActionButtonTemplate">
|
||
<Anchors><Anchor point="LEFT" relativeTo="ActionButton3" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 4)</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="ActionButton5" inherits="BenillaActionButtonTemplate">
|
||
<Anchors><Anchor point="LEFT" relativeTo="ActionButton4" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 5)</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="ActionButton6" inherits="BenillaActionButtonTemplate">
|
||
<Anchors><Anchor point="LEFT" relativeTo="ActionButton5" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 6)</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="ActionButton7" inherits="BenillaActionButtonTemplate">
|
||
<Anchors><Anchor point="LEFT" relativeTo="ActionButton6" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 7)</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="ActionButton8" inherits="BenillaActionButtonTemplate">
|
||
<Anchors><Anchor point="LEFT" relativeTo="ActionButton7" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 8)</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="ActionButton9" inherits="BenillaActionButtonTemplate">
|
||
<Anchors><Anchor point="LEFT" relativeTo="ActionButton8" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 9)</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="ActionButton10" inherits="BenillaActionButtonTemplate">
|
||
<Anchors><Anchor point="LEFT" relativeTo="ActionButton9" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 10)</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="ActionButton11" inherits="BenillaActionButtonTemplate">
|
||
<Anchors><Anchor point="LEFT" relativeTo="ActionButton10" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 11)</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="ActionButton12" inherits="BenillaActionButtonTemplate">
|
||
<Anchors><Anchor point="LEFT" relativeTo="ActionButton11" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 12)</OnLoad></Scripts>
|
||
</CheckButton>
|
||
|
||
<!-- Page up/down: 32x32 at CENTER of the art frame's TOPLEFT +(522,-22)/(522,-42)
|
||
(ref-ActionBarFrame.xml l.159-217). Live now that the bar pages — they were
|
||
art with no OnClick for as long as `CURRENT_ACTIONBAR_PAGE` did not exist.
|
||
|
||
The HitRectInsets are LOAD-BEARING, not decoration: the two 32x32 squares
|
||
are stacked only 20px apart, so their raw rects OVERLAP by 12px and the
|
||
hit-test (later sibling wins) would give that band — the bottom third of
|
||
the visible up arrow — to the DOWN button. The ref's ±6/±7 insets shrink
|
||
each to the 20x18 arrow it actually draws, which separates them and stops
|
||
the down arrow's rect hanging below the screen edge and over the XP bar. -->
|
||
<Button name="ActionBarUpButton">
|
||
<Size><AbsDimension x="32" y="32"/></Size>
|
||
<Anchors>
|
||
<Anchor point="CENTER" relativeTo="MainMenuBarArtFrame" relativePoint="TOPLEFT"><Offset><AbsDimension x="522" y="-22"/></Offset></Anchor>
|
||
</Anchors>
|
||
<HitRectInsets><AbsInset left="6" right="6" top="7" bottom="7"/></HitRectInsets>
|
||
<NormalTexture file="Interface\MainMenuBar\UI-MainMenu-ScrollUpButton-Up"/>
|
||
<PushedTexture file="Interface\MainMenuBar\UI-MainMenu-ScrollUpButton-Down"/>
|
||
<HighlightTexture file="Interface\MainMenuBar\UI-MainMenu-ScrollUpButton-Highlight" alphaMode="ADD"/>
|
||
<Scripts><OnClick>ActionBar_PageUp() PlaySound("UChatScrollButton")</OnClick></Scripts>
|
||
</Button>
|
||
<Button name="ActionBarDownButton">
|
||
<Size><AbsDimension x="32" y="32"/></Size>
|
||
<Anchors>
|
||
<Anchor point="CENTER" relativeTo="MainMenuBarArtFrame" relativePoint="TOPLEFT"><Offset><AbsDimension x="522" y="-42"/></Offset></Anchor>
|
||
</Anchors>
|
||
<HitRectInsets><AbsInset left="6" right="6" top="7" bottom="7"/></HitRectInsets>
|
||
<NormalTexture file="Interface\MainMenuBar\UI-MainMenu-ScrollDownButton-Up"/>
|
||
<PushedTexture file="Interface\MainMenuBar\UI-MainMenu-ScrollDownButton-Down"/>
|
||
<HighlightTexture file="Interface\MainMenuBar\UI-MainMenu-ScrollDownButton-Highlight" alphaMode="ADD"/>
|
||
<Scripts><OnClick>ActionBar_PageDown() PlaySound("UChatScrollButton")</OnClick></Scripts>
|
||
</Button>
|
||
</Frames>
|
||
</Frame>
|
||
|
||
<!-- The performance ("ping") meter (ref-MainMenuBar.xml l.344-407). 16x64 pinned to the
|
||
bar's BOTTOMRIGHT +(-227,-10) — the empty recess between the last micro button and
|
||
the bag slots, which the bar art leaves TRANSPARENT for exactly this. The 20x66
|
||
texture hangs off the frame's TOPRIGHT (so it overspills 4 left and 2 below), and
|
||
the frame itself hangs 10 below the bar, putting the bar's grey column in the slot.
|
||
|
||
frameStrata="LOW" is load-bearing, not decoration: the meter draws UNDER the bar art
|
||
and shows through its transparent window. At the default MEDIUM it would paint over
|
||
the metal surround, since the texture is wider than the slot. (The ref gets the same
|
||
order via strata too — MainMenuBar's OnLoad RaiseFrameLevel can't reach across it.)
|
||
|
||
The hover button is the ref's own split: a HIGH-strata all-points button, because the
|
||
LOW frame beneath the art can't take the mouse itself. The ref declares it as a
|
||
sibling with parent="MainMenuBarPerformanceBarFrame"; nesting it is the same frame
|
||
tree, and its explicit strata survives the parent's LOW subtree-force (attributes
|
||
apply before nested <Frames> are built).
|
||
|
||
The -227 authored here is the NO-keyring position; MainMenuBar_UpdateKeyRing
|
||
(top of this file) re-points it to -235 while the keyring is shown, the ref's own
|
||
shift (MainMenuBar.lua l.180). Both offsets live in that one function. -->
|
||
<Frame name="MainMenuBarPerformanceBarFrame" frameStrata="LOW">
|
||
<Size><AbsDimension x="16" y="64"/></Size>
|
||
<Anchors>
|
||
<Anchor point="BOTTOMRIGHT" relativeTo="MainMenuBar" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="-227" y="-10"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="MainMenuBarPerformanceBar" file="Interface\MainMenuBar\UI-MainMenuBar-PerformanceBar">
|
||
<Size><AbsDimension x="20" y="66"/></Size>
|
||
<Anchors><Anchor point="TOPRIGHT"/></Anchors>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<Button name="MainMenuBarPerformanceBarFrameButton" setAllPoints="true" frameStrata="HIGH">
|
||
<Scripts>
|
||
<OnEnter>BenillaPerformanceBar_OnEnter(self)</OnEnter>
|
||
<OnLeave>BenillaPerformanceBar_OnLeave()</OnLeave>
|
||
</Scripts>
|
||
</Button>
|
||
</Frames>
|
||
<Scripts>
|
||
<OnLoad>BenillaPerformanceBar_OnLoad(self)</OnLoad>
|
||
<OnUpdate>BenillaPerformanceBar_OnUpdate(self, arg1)</OnUpdate>
|
||
</Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
<Scripts>
|
||
<OnLoad>BenillaActionBar_OnLoad(self)</OnLoad>
|
||
<OnEvent>BenillaActionBar_OnEvent(self)</OnEvent>
|
||
</Scripts>
|
||
</Frame>
|
||
|
||
<!-- **The bonus action bar** — declared with 1223 (addons reach for it by name: the largest
|
||
single session-start row in the corpus was `CT_BarMod\CT_BarModOptions.lua:154`'s
|
||
`getglobal("BonusActionButton" .. i):ClearAllPoints()`; five more addons index the frame,
|
||
1218's corrected ranking), and DRIVEN since 1524: it is the form/stance/stealth swap's
|
||
transition vehicle — the 505x43 replica of the button strip that slides up out of the
|
||
screen edge over 0.15s when a form comes up (igBonusBarOpen on landing), stays covering
|
||
the strip while the form holds (so `BonusActionBarFrame:IsShown()` reads
|
||
reference-faithfully), and slides back down carrying the old form's icons when it drops.
|
||
The machinery lives in this file's script block (ShowBonusActionBar / HideBonusActionBar /
|
||
BonusActionBar_OnUpdate, all ref names) and in BenillaActionBar_OnEvent's
|
||
UPDATE_BONUS_ACTIONBAR arm; benilla still models the bonus page by RE-PAGING THE MAIN BAR
|
||
(1223) — the overlay never replaces that, it covers the swap.
|
||
|
||
The buttons wire to the bonus page — `BenillaActionButton_OnLoad(self, i)` plus the ref's
|
||
own `isBonus` mark, which forks BenillaActionButton_Action to the live bonus page (with
|
||
lastBonusBar standing in during the down-slide). They share the ACTIONBUTTON command
|
||
prefix, the reference's binding story: vanilla's ACTIONBUTTON1-12 drive the bonus bar
|
||
while a form is up (ActionButtonDown/Up's IsShown fork above).
|
||
|
||
Geometry quoted from the reference: a 505x43 frame anchored TOPLEFT to MainMenuBar's
|
||
BOTTOMLEFT +(40,0) as declared — every shown appearance re-anchors at x=4 (the ref Lua's
|
||
own BONUSACTIONBAR_XPOS, whose art trims 4px of left TexCoord to line back up); button 1
|
||
at BOTTOMLEFT +(5,4), each next LEFT-of-previous-RIGHT +6; the two OVERLAY art strips are
|
||
the dwarf sheet rows the main bar itself draws (ref l.55-105). -->
|
||
<Frame name="BonusActionBarFrame" frameStrata="HIGH" parent="MainMenuBar" enableMouse="true" toplevel="true" hidden="true">
|
||
<Size><AbsDimension x="505" y="43"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="MainMenuBar" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="40" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="OVERLAY">
|
||
<Texture name="BonusActionBarTexture0" file="Interface\MainMenuBar\UI-MainMenuBar-Dwarf">
|
||
<Size><AbsDimension x="252" y="43"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"/></Anchors>
|
||
<TexCoords left="0.015625" right="1.0" top="0.83203125" bottom="1.0"/>
|
||
</Texture>
|
||
<Texture name="BonusActionBarTexture1" file="Interface\MainMenuBar\UI-MainMenuBar-Dwarf">
|
||
<Size><AbsDimension x="253" y="43"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativeTo="BonusActionBarTexture0" relativePoint="RIGHT"/></Anchors>
|
||
<TexCoords left="0" right="0.98828125" top="0.58203125" bottom="0.75"/>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<CheckButton name="BonusActionButton1" inherits="BenillaActionButtonTemplate" id="1">
|
||
<Anchors><Anchor point="BOTTOMLEFT" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="5" y="4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 1) self.isBonus = 1</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="BonusActionButton2" inherits="BenillaActionButtonTemplate" id="2">
|
||
<Anchors><Anchor point="LEFT" relativeTo="BonusActionButton1" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 2) self.isBonus = 1</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="BonusActionButton3" inherits="BenillaActionButtonTemplate" id="3">
|
||
<Anchors><Anchor point="LEFT" relativeTo="BonusActionButton2" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 3) self.isBonus = 1</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="BonusActionButton4" inherits="BenillaActionButtonTemplate" id="4">
|
||
<Anchors><Anchor point="LEFT" relativeTo="BonusActionButton3" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 4) self.isBonus = 1</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="BonusActionButton5" inherits="BenillaActionButtonTemplate" id="5">
|
||
<Anchors><Anchor point="LEFT" relativeTo="BonusActionButton4" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 5) self.isBonus = 1</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="BonusActionButton6" inherits="BenillaActionButtonTemplate" id="6">
|
||
<Anchors><Anchor point="LEFT" relativeTo="BonusActionButton5" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 6) self.isBonus = 1</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="BonusActionButton7" inherits="BenillaActionButtonTemplate" id="7">
|
||
<Anchors><Anchor point="LEFT" relativeTo="BonusActionButton6" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 7) self.isBonus = 1</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="BonusActionButton8" inherits="BenillaActionButtonTemplate" id="8">
|
||
<Anchors><Anchor point="LEFT" relativeTo="BonusActionButton7" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 8) self.isBonus = 1</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="BonusActionButton9" inherits="BenillaActionButtonTemplate" id="9">
|
||
<Anchors><Anchor point="LEFT" relativeTo="BonusActionButton8" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 9) self.isBonus = 1</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="BonusActionButton10" inherits="BenillaActionButtonTemplate" id="10">
|
||
<Anchors><Anchor point="LEFT" relativeTo="BonusActionButton9" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 10) self.isBonus = 1</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="BonusActionButton11" inherits="BenillaActionButtonTemplate" id="11">
|
||
<Anchors><Anchor point="LEFT" relativeTo="BonusActionButton10" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 11) self.isBonus = 1</OnLoad></Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="BonusActionButton12" inherits="BenillaActionButtonTemplate" id="12">
|
||
<Anchors><Anchor point="LEFT" relativeTo="BonusActionButton11" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 12) self.isBonus = 1</OnLoad></Scripts>
|
||
</CheckButton>
|
||
</Frames>
|
||
<Scripts>
|
||
<OnLoad>BenillaBonusBar_OnLoad(self)</OnLoad>
|
||
<OnUpdate>BonusActionBar_OnUpdate(arg1)</OnUpdate>
|
||
</Scripts>
|
||
</Frame>
|
||
|
||
<!-- **The reputation watch bar** — built to `ref-ReputationFrame.xml:869-1036`, whose geometry
|
||
and art it quotes (those are the client's own facts) and whose handlers it implements in
|
||
this file's script block. It
|
||
shipped built-and-hidden with 1223 (three corpus addons index it by name — `FuBar_FuXPFu`,
|
||
`CT_BottomBar`, `zBarEx` — and FuXPFu dies at `FuBar_FuXPFu.lua:227` on the nil); it is
|
||
DRIVEN now, by `ReputationWatchBar_Update` in this file's script block, whose own comment
|
||
carries the reason the reputation watch-bar slice lives here rather than in
|
||
ReputationFrame.xml where the reference declares it.
|
||
|
||
Geometry quoted from the reference: a 1024x11 frame whose BOTTOM sits on MainMenuBar's TOP
|
||
at (0,-3), holding a 1024x8 `ReputationWatchStatusBar` at TOP. TWO sets of end art ride the
|
||
status bar and the update swaps between them: the four `ReputationWatchBarTexture*` slices
|
||
of `UI-ReputationWatchBar` for the stacked-above-the-XP-bar posture, and the four
|
||
`ReputationXPBarTexture*` slices of the dwarf `UI-MainMenuBar-Dwarf` sheet for the
|
||
replaces-the-XP-bar posture at max level, where the strip has to look like the bar it took
|
||
over from. The numerals live on their own DIALOG-strata overlay child so they draw over
|
||
both. -->
|
||
<Frame name="ReputationWatchBar" enableMouse="true" parent="MainMenuBar" hidden="true">
|
||
<Size><AbsDimension x="1024" y="11"/></Size>
|
||
<Anchors>
|
||
<Anchor point="BOTTOM" relativeTo="MainMenuBar" relativePoint="TOP"><Offset><AbsDimension x="0" y="-3"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Frames>
|
||
<StatusBar name="ReputationWatchStatusBar" drawLayer="ARTWORK">
|
||
<Size><AbsDimension x="1024" y="8"/></Size>
|
||
<Anchors><Anchor point="TOP"/></Anchors>
|
||
<Layers>
|
||
<Layer level="OVERLAY">
|
||
<!-- ref l.890-929: four 256-wide quarters of the 1024 strip, each its own
|
||
band of the sheet. The TexCoords were MISSING while the frame was a
|
||
stub that could not show; without them every quarter draws the whole
|
||
sheet. -->
|
||
<Texture name="ReputationWatchBarTexture0" file="Interface\PaperDollInfoFrame\UI-ReputationWatchBar">
|
||
<Size><AbsDimension x="256" y="11"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="0" y="2"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="0" right="1.0" top="0" bottom="0.171875"/>
|
||
</Texture>
|
||
<Texture name="ReputationWatchBarTexture1" file="Interface\PaperDollInfoFrame\UI-ReputationWatchBar">
|
||
<Size><AbsDimension x="256" y="11"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativeTo="ReputationWatchBarTexture0" relativePoint="RIGHT"/></Anchors>
|
||
<TexCoords left="0" right="1.0" top="0.171875" bottom="0.34375"/>
|
||
</Texture>
|
||
<Texture name="ReputationWatchBarTexture2" file="Interface\PaperDollInfoFrame\UI-ReputationWatchBar">
|
||
<Size><AbsDimension x="256" y="11"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativeTo="ReputationWatchBarTexture1" relativePoint="RIGHT"/></Anchors>
|
||
<TexCoords left="0" right="1.0" top="0.34375" bottom="0.515625"/>
|
||
</Texture>
|
||
<Texture name="ReputationWatchBarTexture3" file="Interface\PaperDollInfoFrame\UI-ReputationWatchBar">
|
||
<Size><AbsDimension x="256" y="11"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativeTo="ReputationWatchBarTexture2" relativePoint="RIGHT"/></Anchors>
|
||
<TexCoords left="0" right="1.0" top="0.515625" bottom="0.6875"/>
|
||
</Texture>
|
||
<!-- ref l.930-969: the max-level alternate, four bands of the SAME dwarf
|
||
sheet the XP bar's own notch art comes from, so the replaced bar reads
|
||
as the bar it replaced. Hidden until the max-level arm shows them. -->
|
||
<Texture name="ReputationXPBarTexture0" file="Interface\MainMenuBar\UI-MainMenuBar-Dwarf" hidden="true">
|
||
<Size><AbsDimension x="256" y="10"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"/></Anchors>
|
||
<TexCoords left="0" right="1.0" top="0.79296875" bottom="0.83203125"/>
|
||
</Texture>
|
||
<Texture name="ReputationXPBarTexture1" file="Interface\MainMenuBar\UI-MainMenuBar-Dwarf" hidden="true">
|
||
<Size><AbsDimension x="256" y="10"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativeTo="ReputationXPBarTexture0" relativePoint="RIGHT"/></Anchors>
|
||
<TexCoords left="0" right="1.0" top="0.54296875" bottom="0.58203125"/>
|
||
</Texture>
|
||
<Texture name="ReputationXPBarTexture2" file="Interface\MainMenuBar\UI-MainMenuBar-Dwarf" hidden="true">
|
||
<Size><AbsDimension x="256" y="10"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativeTo="ReputationXPBarTexture1" relativePoint="RIGHT"/></Anchors>
|
||
<TexCoords left="0" right="1.0" top="0.29296875" bottom="0.33203125"/>
|
||
</Texture>
|
||
<Texture name="ReputationXPBarTexture3" file="Interface\MainMenuBar\UI-MainMenuBar-Dwarf" hidden="true">
|
||
<Size><AbsDimension x="256" y="10"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativeTo="ReputationXPBarTexture2" relativePoint="RIGHT"/></Anchors>
|
||
<TexCoords left="0" right="1.0" top="0.04296875" bottom="0.08203125"/>
|
||
</Texture>
|
||
</Layer>
|
||
<!-- ref l.971-975: the half-alpha black backing the fill rides over. -->
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="ReputationWatchStatusBarBackground">
|
||
<Color r="0.0" g="0.0" b="0.0" a="0.5"/>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<!-- ref l.977-978. The purple is only the load-time default: every painted state
|
||
takes FACTION_BAR_COLORS[reaction] instead. -->
|
||
<BarTexture file="Interface\TargetingFrame\UI-StatusBar"/>
|
||
<BarColor r="0.58" g="0.0" b="0.55"/>
|
||
</StatusBar>
|
||
<!-- ref l.980-994: the numerals sit on a DIALOG-strata child of their own so they clear
|
||
both sets of end art. Hidden by default; the hover shows them, and at max level the
|
||
statusBarText cvar can pin them (ShowWatchedReputationBarText). -->
|
||
<Frame name="ReputationWatchBarOverlayFrame" frameStrata="DIALOG" setAllPoints="true">
|
||
<Layers>
|
||
<Layer level="ARTWORK">
|
||
<FontString name="ReputationWatchStatusBarText" inherits="NumberFontNormal" hidden="true">
|
||
<Anchors><Anchor point="CENTER"><Offset><AbsDimension x="0" y="3"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
</Frame>
|
||
</Frames>
|
||
<!-- ref l.996-1035. The three that carry any thought are chunk functions in this file's
|
||
script block, where their departures are documented (`BenillaWatchBar_OnLoad` /
|
||
`_OnEvent` / `_OnShow`); the three below are one statement each and stay where the
|
||
reference has them. The numerals hover is the pair: coming onto the bar shows them
|
||
unconditionally, leaving takes them down UNLESS the statusBarText cvar has pinned them
|
||
on — `textLocked` is the pin, and the two text verbs above are what set it. -->
|
||
<Scripts>
|
||
<OnLoad>BenillaWatchBar_OnLoad(self)</OnLoad>
|
||
<OnEvent>BenillaWatchBar_OnEvent(self, event)</OnEvent>
|
||
<OnShow>BenillaWatchBar_OnShow()</OnShow>
|
||
<OnHide>UIParent_ManageFramePositions()</OnHide>
|
||
<OnEnter>ReputationWatchStatusBarText:Show()</OnEnter>
|
||
<OnLeave>
|
||
if not ReputationWatchBar.textLocked then
|
||
ReputationWatchStatusBarText:Hide()
|
||
end
|
||
</OnLeave>
|
||
</Scripts>
|
||
</Frame>
|
||
</Ui>
|