Files
benilla-octo/crates/benilla-app/assets/ui/ActionBar.xml
T
SamandClaude Fable 5 d16d33dfca world books open, and anvils stop offering a cursor gear
- clicking a book in the world opens it and turns its pages: letters and world books share one reader
- the cursor's object rules are the client's own 31-row strategy table now, so decorative objects stop pretending to be usable
- trainer and tradeskill windows draw each row's icon by the reference's own law, and the trainer's filter dropdown toggles again
- water color follows the zone's light blend, so lakes stop snapping between area tints

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 16:03:35 +07:00

1339 lines
81 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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:
BenillaActionBar (1024x53, BOTTOM of screen)
├─ BenillaExpBar (StatusBar, TOP) — drawn first ⇒ lowest
│ ├─ BenillaExhaustionLevelFillBar (BORDER) — the pale rested wash up to the tick
│ └─ BenillaExpBarOverlayFrame (DIALOG) — the hover "curr / max" numerals
├─ BenillaActionBarArtFrame (fills the bar) — dwarf strips + end caps over the XP bar
│ └─ 12 buttons + page up/down — child frames ⇒ over the art
└─ BenillaExhaustionTick (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 + the page number are ART ONLY (we have no bar paging — only the bonus-bar
offset; ref-ActionBarFrame.xml l.159-217). The page number renders a static "1".
- HotKey renders the LIVE binding label, abbreviated the ref's own way since 1008
(GetBindingText(key, "KEY_", 1) — UIParent.xml carries the transcription; "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 transcribed:
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 transcribed, 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):
simplified to one bar-level BOOLEAN — the cursor is a single global payload, so no two
"shows" can ever nest, and a counter would just be a boolean with extra steps. Unlike the
ref (which HIDES an empty, non-grid slot entirely), our bar always shows all 12 wells; the
grid only swaps an EMPTY slot's ring art between the occupied and empty Quickslot textures
— the default (nothing held) look is unchanged from before this slice, no capture regression.
- 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
BenillaActionBarArtFrame 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 BenillaMainMenuBar_UpdateKeyRing below, exactly where the ref keeps it
(MainMenuBar.lua l.174-183).
-->
<Script><![CDATA[
BENILLA_FALLBACK_ICON = "Interface\\Icons\\INV_Misc_QuestionMark"
-- 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
-- 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
-- real GetBindingText transcription (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
-- Whether a placeable cursor payload is held (decision 0216 §7's ACTIONBAR_SHOWGRID/
-- _HIDEGRID pair, simplified to a boolean — see the SCOPE note above).
BENILLA_ACTIONBAR_GRID_SHOWN = false
-- 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 = {}
-- 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("BenillaActionBarArtFrame")
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 BenillaKeyRingButton'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 BenillaMainMenuBar_UpdateKeyRing()
local show = HasKey and HasKey()
-- The two right-hand strips (BenillaActionBarTexture2 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 = "BenillaActionBarTexture2",
keyring = 0.6640625, keyringBottom = 1.0,
dwarf = 0.33203125, dwarfBottom = 0.5 },
{ name = "BenillaActionBarTexture3",
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("BenillaPerformanceBarFrame")
local bar = getglobal("BenillaActionBar")
if perf and bar then
perf:SetPoint("BOTTOMRIGHT", bar, "BOTTOMRIGHT", (show and -235) or -227, -10)
end
local button = getglobal("BenillaKeyRingButton")
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 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 = GetBonusBarOffset()
local base = 0
if offset > 0 then
base = (6 + offset - 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.
function BenillaActionButton_Action(button)
if button.base then
return button.base + button.index
end
return BenillaActionBar_ActionFor(button.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 RIGHT/LEFT by bar. UberTooltips
-- registers with default "1" (byte-read: WoW.exe 0x48fdd9, default string 0x82e748;
-- sibling rows BlockTrades→"0", UnitNameRenderMode→"2" confirm the layout), and benilla
-- ships no CVar state, so the branch collapses to the stock-client one: action-bar
-- tooltips live at the screen's bottom-right, above the bags.
function BenillaActionButton_OnEnter(button)
if not GameTooltip then return end -- engine tests load file subsets
GameTooltip_SetDefaultAnchor(GameTooltip, button)
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")
-- Ref ActionButton_OnLoad:104-106: the flash/range state the OnUpdate loop drives.
button.flashing = 0
button.flashtime = 0
button.rangeTimer = nil
-- 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. LOCK_ACTIONBAR stays the vanilla
-- default (unlocked), so unlike the ref's cvar guard, drag is always live here.
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)
local action = BenillaActionButton_Action(button)
if IsShiftKeyDown() then
PickupAction(action)
else
UseAction(action, 1)
end
BenillaActionButton_Update(button)
end
function BenillaActionButton_OnDragStart(button)
PickupAction(BenillaActionButton_Action(button))
BenillaActionButton_Update(button)
end
function BenillaActionButton_OnReceiveDrag(button)
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
-- transcribed 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 and the SELFACTIONBUTTON onSelf argument are not modeled (no bonus
-- bar frame, no self-cast modifier binding).
function BenillaActionButtonDown(index)
local button = getglobal("BenillaActionButton" .. index)
if ( button:GetButtonState() == "NORMAL" ) then
button:SetButtonState("PUSHED")
end
end
function BenillaActionButtonUp(index)
local button = getglobal("BenillaActionButton" .. index)
if ( button:GetButtonState() == "PUSHED" ) then
button:SetButtonState("NORMAL")
UseAction(BenillaActionButton_Action(button))
-- 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 BenillaActionButton_OnUpdate(button, elapsed)
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
-- ref ActionButton.lua:285-292 ActionButton_UpdateCount, transcribed. 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
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)
if button.base then
-- An EMPTY multibar well is the ref's own default: hidden entirely, appearing
-- as a drop-target ring only while a payload is held (ActionButton_Update's
-- showgrid==0 Hide; MultiActionBar_ShowAllGrids). 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 BENILLA_ACTIONBAR_GRID_SHOWN then
button:SetNormalTexture("Interface\\Buttons\\UI-Quickslot")
button:Show()
else
button:Hide()
end
else
-- While a payload is held, 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 BENILLA_ACTIONBAR_GRID_SHOWN 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
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)
-- 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
if event == "ACTIONBAR_SHOWGRID" or event == "ACTIONBAR_HIDEGRID" then
BENILLA_ACTIONBAR_GRID_SHOWN = (event == "ACTIONBAR_SHOWGRID")
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 BenillaExpBar_Update(bar)
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
BenillaExpBar_Update(bar)
end
-- ref-MainMenuBar.xml l.121-126: repaint, then hand arg1/arg2 to the CVAR_UPDATE watcher.
function BenillaExpBar_OnEvent(bar)
BenillaExpBar_Update(bar)
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 BenillaExhaustionToolTipText'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
BenillaExhaustionTick.timer = 1
if not GameTooltip_AddNewbieTip then return end
GameTooltip_AddNewbieTip(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
BenillaExhaustionTick.timer = nil
end
-- ── The max-level rail (ref-ReputationFrame.lua, the max-level slice) ─────────────────
-- ref l.14: the constant lives in ReputationFrame.lua, which isn't built yet — it moves
-- there with the reputation system.
MAX_PLAYER_LEVEL = 60
function BenillaMaxLevelBar_OnLoad(bar)
bar:RegisterEvent("PLAYER_ENTERING_WORLD")
bar:RegisterEvent("PLAYER_LEVEL_UP")
end
-- ref ReputationWatchBar_Update's else arm (ref-ReputationFrame.lua l.161-166 +
-- l.236-244), the no-watched-faction branch only — the reputation branches wait for the
-- reputation system: at MAX_PLAYER_LEVEL the XP strip gives way to the rail and the
-- tick goes with it. Login seam: the ref initializes off UPDATE_FACTION (its OnEvent's
-- else arm; the faction list lands at every login), an event benilla doesn't carry yet,
-- so the rail listens to PLAYER_ENTERING_WORLD instead — same moment, same values.
function BenillaMaxLevelBar_Update(newLevel)
if not newLevel then
newLevel = UnitLevel("player")
end
if newLevel == MAX_PLAYER_LEVEL then
BenillaExpBar:Hide()
BenillaMaxLevelBar:Show()
BenillaExhaustionTick:Hide()
else
BenillaExpBar:Show()
BenillaMaxLevelBar:Hide()
end
end
-- The ref's event fan (ref-ReputationFrame.xml l.1002-1016): PLAYER_LEVEL_UP passes
-- arg1 (the new level — the level FIELD may not have landed yet), everything else
-- re-reads UnitLevel.
function BenillaMaxLevelBar_OnEvent()
if event == "PLAYER_LEVEL_UP" then
BenillaMaxLevelBar_Update(arg1)
else
BenillaMaxLevelBar_Update()
end
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. One transcription cut left, named:
-- the ref's two ReputationWatchBar guards (the max-level+rep tick hide, l.51-54, and
-- the rep-bar-replaced-the-xp-bar hide, l.69-71) reference the faction watch bar, not
-- built — its frame can't be shown, so the cut is an unreachable-code cut, not a
-- behavior cut. The MainMenuBarMaxLevelBar guard is live since 1094 (the rail below).
function BenillaExhaustionTick_OnLoad(tick)
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 BenillaExhaustionTick_Update(tick)
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", "BenillaExpBar", "RIGHT", 0, 0)
end
if not exhaustionThreshold then
tick:Hide()
BenillaExhaustionLevelFillBar:Hide()
else
local exhaustionTickSet = max(((playerCurrXP + exhaustionThreshold)
/ playerMaxXP) * BenillaExpBar:GetWidth(), 0)
tick:ClearAllPoints()
if exhaustionTickSet > BenillaExpBar:GetWidth()
or BenillaMaxLevelBar:IsShown() then
tick:Hide()
BenillaExhaustionLevelFillBar:Hide()
else
tick:Show()
tick:SetPoint("CENTER", "BenillaExpBar", "LEFT", exhaustionTickSet, 0)
BenillaExhaustionLevelFillBar:Show()
BenillaExhaustionLevelFillBar:SetPoint("TOPRIGHT", "BenillaExpBar",
"TOPLEFT", exhaustionTickSet, 0)
end
end
end
-- The rest-state paint (only these two events repaint it, the ref's own split):
-- rested = light blue bar + pale blue fill-to-tick, normal = the purple default.
if event == "PLAYER_ENTERING_WORLD" or event == "UPDATE_EXHAUSTION" then
local exhaustionStateID = GetRestState()
if exhaustionStateID == 1 then
BenillaExpBar:SetStatusBarColor(0.0, 0.39, 0.88, 1.0)
BenillaExhaustionLevelFillBar:SetVertexColor(0.0, 0.39, 0.88, 0.15)
BenillaExhaustionTickHighlight:SetVertexColor(0.0, 0.39, 0.88)
elseif exhaustionStateID == 2 then
BenillaExpBar:SetStatusBarColor(0.58, 0.0, 0.55, 1.0)
BenillaExhaustionLevelFillBar:SetVertexColor(0.58, 0.0, 0.55, 0.15)
BenillaExhaustionTickHighlight:SetVertexColor(0.58, 0.0, 0.55)
end
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 BenillaExhaustionToolTipText()
if SHOW_NEWBIE_TIPS ~= "1" then
local x, y = BenillaExhaustionTick:GetCenter()
if BenillaExhaustionTick:IsVisible() then
if x >= (GetScreenWidth() / 2) then
GameTooltip:SetOwner(BenillaExhaustionTick, "ANCHOR_LEFT")
else
GameTooltip:SetOwner(BenillaExhaustionTick, "ANCHOR_RIGHT")
end
else
GameTooltip_SetDefaultAnchor(GameTooltip, UIParent)
end
end
local exhaustionStateID, exhaustionStateName, exhaustionStateMultiplier = GetRestState()
local exhaustionThreshold = GetXPExhaustion()
exhaustionStateMultiplier = exhaustionStateMultiplier * 100
local exhaustionCountdown = nil
if GetTimeToWellRested() then
exhaustionCountdown = GetTimeToWellRested() / 60
end
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)
else
if GameTooltip.canAddRestStateLine then
GameTooltip:AddLine("\n" .. tooltipText)
GameTooltip:Show()
GameTooltip.canAddRestStateLine = nil
end
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 BenillaExhaustionTick_OnUpdate(elapsed)
if BenillaExhaustionTick.timer then
if BenillaExhaustionTick.timer < 0 then
BenillaExhaustionToolTipText()
BenillaExhaustionTick.timer = nil
else
BenillaExhaustionTick.timer = BenillaExhaustionTick.timer - elapsed
end
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
BenillaExpBar.lockShow = 0
SetTextStatusBarText(BenillaExpBar, BenillaExpBarText)
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, transcribed 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:
-- GameTooltip_AddNewbieTip(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
GameTooltip_AddNewbieTip(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()
if latency > PERFORMANCEBAR_MEDIUM_LATENCY then
BenillaPerformanceBar:SetVertexColor(1, 0, 0)
elseif latency > PERFORMANCEBAR_LOW_LATENCY then
BenillaPerformanceBar:SetVertexColor(1, 1, 0)
else
BenillaPerformanceBar:SetVertexColor(0, 1, 0)
end
-- 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)
BenillaPerformanceBarFrame.hover = 1
BenillaPerformanceBar_ShowTooltip(button)
end
function BenillaPerformanceBar_OnLeave()
BenillaPerformanceBarFrame.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). Only Name (macros) stays OUT.
-->
<CheckButton name="BenillaActionButtonTemplate" 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>
</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"/>
<Scripts>
<OnClick>BenillaActionButton_OnClick(self)</OnClick>
<OnDragStart>BenillaActionButton_OnDragStart(self)</OnDragStart>
<OnReceiveDrag>BenillaActionButton_OnReceiveDrag(self)</OnReceiveDrag>
<OnUpdate>BenillaActionButton_OnUpdate(self, arg1)</OnUpdate>
<OnEnter>BenillaActionButton_OnEnter(self)</OnEnter>
<OnLeave>if GameTooltip then GameTooltip:Hide() end</OnLeave>
</Scripts>
</CheckButton>
<!-- The bar: 1024x53 anchored BOTTOM of the screen (ref-MainMenuBar.xml l.4-10). -->
<Frame name="BenillaActionBar">
<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="BenillaExpBar" 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 BenillaExhaustionTick_Update stretches its TOPRIGHT to the tick
and tints it (SetVertexColor a=0.15 over this authored white). -->
<Texture name="BenillaExhaustionLevelFillBar">
<Size><AbsDimension x="0" y="13"/></Size>
<Anchors>
<Anchor point="TOPLEFT" relativeTo="BenillaExpBar"><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="BenillaXPBarTexture0" 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="BenillaXPBarTexture1" 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="BenillaXPBarTexture2" 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="BenillaXPBarTexture3" 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="BenillaExpBarOverlayFrame" frameStrata="DIALOG">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="BenillaActionBar" relativePoint="TOPLEFT"/>
<Anchor point="BOTTOMRIGHT" relativeTo="BenillaActionBar" relativePoint="BOTTOMRIGHT"/>
</Anchors>
<Layers>
<Layer level="ARTWORK">
<FontString name="BenillaExpBarText" inherits="TextStatusBarText">
<Anchors>
<Anchor point="CENTER" relativeTo="BenillaExpBar"><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>BenillaExhaustionTick_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 BenillaExhaustionTick_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="BenillaExhaustionTick" frameStrata="DIALOG">
<Size><AbsDimension x="32" y="32"/></Size>
<Anchors>
<Anchor point="CENTER" relativeTo="BenillaExpBar"><Offset><AbsDimension x="0" y="0"/></Offset></Anchor>
</Anchors>
<Scripts>
<OnLoad>BenillaExhaustionTick_OnLoad(self)</OnLoad>
<OnEvent>BenillaExhaustionTick_Update(self)</OnEvent>
<OnEnter>BenillaExhaustionToolTipText()</OnEnter>
<OnLeave>if GameTooltip then GameTooltip:Hide() end</OnLeave>
</Scripts>
<NormalTexture name="BenillaExhaustionTickNormal" file="Interface\MainMenuBar\UI-ExhaustionTickNormal"/>
<HighlightTexture name="BenillaExhaustionTickHighlight" 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/hidden by BenillaMaxLevelBar_Update (decision 1094). The ref's OnShow/
OnHide call UIParent_ManageFramePositions, which benilla doesn't build
(DurabilityFrame.xml's note) — a named cut.
-->
<Frame name="BenillaMaxLevelBar" 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="BenillaMaxLevelBar0" 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="BenillaMaxLevelBar1" file="Interface\MainMenuBar\UI-MainMenuBar-MaxLevel">
<Size><AbsDimension x="256" y="7"/></Size>
<Anchors>
<Anchor point="LEFT" relativeTo="BenillaMaxLevelBar0" relativePoint="RIGHT"/>
</Anchors>
<TexCoords left="0" right="1.0" top="0.25" bottom="0.46875"/>
</Texture>
<Texture name="BenillaMaxLevelBar2" file="Interface\MainMenuBar\UI-MainMenuBar-MaxLevel">
<Size><AbsDimension x="256" y="7"/></Size>
<Anchors>
<Anchor point="LEFT" relativeTo="BenillaMaxLevelBar1" relativePoint="RIGHT"/>
</Anchors>
<TexCoords left="0" right="1.0" top="0.5" bottom="0.71875"/>
</Texture>
<Texture name="BenillaMaxLevelBar3" file="Interface\MainMenuBar\UI-MainMenuBar-MaxLevel">
<Size><AbsDimension x="256" y="7"/></Size>
<Anchors>
<Anchor point="LEFT" relativeTo="BenillaMaxLevelBar2" relativePoint="RIGHT"/>
</Anchors>
<TexCoords left="0" right="1.0" top="0.75" bottom="0.96875"/>
</Texture>
</Layer>
</Layers>
<Scripts>
<OnLoad>BenillaMaxLevelBar_OnLoad(self)</OnLoad>
<OnEvent>BenillaMaxLevelBar_OnEvent()</OnEvent>
</Scripts>
</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="BenillaActionBarArtFrame">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="BenillaActionBar" relativePoint="TOPLEFT"/>
<Anchor point="BOTTOMRIGHT" relativeTo="BenillaActionBar" 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="BenillaActionBarTexture0" 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="BenillaActionBarTexture1" 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="BenillaActionBarTexture2" 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="BenillaActionBarTexture3" 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="BenillaActionBarLeftEndCap" 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="BenillaActionBarRightEndCap" 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>
<FontString name="BenillaActionBarPageNumber" 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="BenillaActionButton1" 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="BenillaActionButton2" inherits="BenillaActionButtonTemplate">
<Anchors><Anchor point="LEFT" relativeTo="BenillaActionButton1" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 2)</OnLoad></Scripts>
</CheckButton>
<CheckButton name="BenillaActionButton3" inherits="BenillaActionButtonTemplate">
<Anchors><Anchor point="LEFT" relativeTo="BenillaActionButton2" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 3)</OnLoad></Scripts>
</CheckButton>
<CheckButton name="BenillaActionButton4" inherits="BenillaActionButtonTemplate">
<Anchors><Anchor point="LEFT" relativeTo="BenillaActionButton3" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 4)</OnLoad></Scripts>
</CheckButton>
<CheckButton name="BenillaActionButton5" inherits="BenillaActionButtonTemplate">
<Anchors><Anchor point="LEFT" relativeTo="BenillaActionButton4" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 5)</OnLoad></Scripts>
</CheckButton>
<CheckButton name="BenillaActionButton6" inherits="BenillaActionButtonTemplate">
<Anchors><Anchor point="LEFT" relativeTo="BenillaActionButton5" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 6)</OnLoad></Scripts>
</CheckButton>
<CheckButton name="BenillaActionButton7" inherits="BenillaActionButtonTemplate">
<Anchors><Anchor point="LEFT" relativeTo="BenillaActionButton6" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 7)</OnLoad></Scripts>
</CheckButton>
<CheckButton name="BenillaActionButton8" inherits="BenillaActionButtonTemplate">
<Anchors><Anchor point="LEFT" relativeTo="BenillaActionButton7" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 8)</OnLoad></Scripts>
</CheckButton>
<CheckButton name="BenillaActionButton9" inherits="BenillaActionButtonTemplate">
<Anchors><Anchor point="LEFT" relativeTo="BenillaActionButton8" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 9)</OnLoad></Scripts>
</CheckButton>
<CheckButton name="BenillaActionButton10" inherits="BenillaActionButtonTemplate">
<Anchors><Anchor point="LEFT" relativeTo="BenillaActionButton9" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 10)</OnLoad></Scripts>
</CheckButton>
<CheckButton name="BenillaActionButton11" inherits="BenillaActionButtonTemplate">
<Anchors><Anchor point="LEFT" relativeTo="BenillaActionButton10" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
<Scripts><OnLoad>BenillaActionButton_OnLoad(self, 11)</OnLoad></Scripts>
</CheckButton>
<CheckButton name="BenillaActionButton12" inherits="BenillaActionButtonTemplate">
<Anchors><Anchor point="LEFT" relativeTo="BenillaActionButton11" 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). ART ONLY — we have no bar paging, so the
clicks are no-ops (no OnClick handler). -->
<Button name="BenillaActionBarUpButton">
<Size><AbsDimension x="32" y="32"/></Size>
<Anchors>
<Anchor point="CENTER" relativeTo="BenillaActionBarArtFrame" relativePoint="TOPLEFT"><Offset><AbsDimension x="522" y="-22"/></Offset></Anchor>
</Anchors>
<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"/>
</Button>
<Button name="BenillaActionBarDownButton">
<Size><AbsDimension x="32" y="32"/></Size>
<Anchors>
<Anchor point="CENTER" relativeTo="BenillaActionBarArtFrame" relativePoint="TOPLEFT"><Offset><AbsDimension x="522" y="-42"/></Offset></Anchor>
</Anchors>
<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"/>
</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; BenillaMainMenuBar_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="BenillaPerformanceBarFrame" frameStrata="LOW">
<Size><AbsDimension x="16" y="64"/></Size>
<Anchors>
<Anchor point="BOTTOMRIGHT" relativeTo="BenillaActionBar" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="-227" y="-10"/></Offset></Anchor>
</Anchors>
<Layers>
<Layer level="BACKGROUND">
<Texture name="BenillaPerformanceBar" file="Interface\MainMenuBar\UI-MainMenuBar-PerformanceBar">
<Size><AbsDimension x="20" y="66"/></Size>
<Anchors><Anchor point="TOPRIGHT"/></Anchors>
</Texture>
</Layer>
</Layers>
<Frames>
<Button name="BenillaPerformanceBarButton" 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>
</Ui>