- ice block freezes the body the frame it lands, before the arm even rises - the loot message links the item, so the name wears its quality colour - a looted item drops into the bag that actually took it - effect models live their authored life, born, held, decayed, and bar fills sit under their borders Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1881 lines
118 KiB
XML
1881 lines
118 KiB
XML
<Ui>
|
||
<!--
|
||
benilla's bag windows (decision 0068 T2), RE-SKINNED to the real 1.12 ContainerFrame
|
||
(dressing arc, decision 0084; whole-space generalization, decision 0216 slice 2): the
|
||
geometry and art below are QUOTED from the real `ContainerFrame.xml`/`ContainerFrame.lua`
|
||
(scratchpad `ref-framexml/ContainerFrame.xml`, `ContainerFrame.lua`; line citations inline),
|
||
turned onto our own C_Container feed/intents. FIVE windows now — the backpack (bag id 0, 16
|
||
slots, its own hand-authored block below, unchanged in shape) plus the four equipped bags
|
||
(ids 1..4, `BenillaBagWindowTemplate`, up to 20 slots each) — the ContainerFrameTemplate
|
||
generalization this file's header always said was coming.
|
||
|
||
Every window shares the same handler functions, deriving its bag id from
|
||
`button:GetParent():GetID()`/`frame:GetID()` (the ref's own `this:GetParent():GetID()`
|
||
pattern, ContainerFrame.lua:88 &c.) rather than a hardcoded global — the XML `id=` attribute
|
||
is applied (SetID) before any child's OnLoad fires (the loader's bottom-up materialize order,
|
||
`loader/mod.rs` step 5 before step 7), so a slot button's OnLoad can already read its
|
||
parent's id. All state arrives through the container snapshot
|
||
(GetContainerNumSlots/GetContainerItemInfo) and refreshes on BAG_UPDATE/ITEM_LOCK_CHANGED.
|
||
LEFT-click drives the cursor drag (PickupContainerItem → pick up / place / swap, the app's
|
||
move drain → CMSG_SWAP_INV_ITEM/CMSG_SWAP_ITEM); RIGHT-click cancels a held cursor, else uses
|
||
the slot (UseContainerItem → CMSG_USE_ITEM / auto-equip, or a merchant sell); SHIFT+left-click
|
||
opens the stack-split spinner (the reference fork, ContainerFrame.lua:567-577).
|
||
|
||
REAL-CLIENT DIVERGENCES (noted, not bugs):
|
||
- The real client scales the whole frame to CONTAINER_SCALE=0.90 (ContainerFrame.lua l.13);
|
||
we don't do frame scale, so every window renders ~11% larger. Scaling is uniform over the
|
||
frame + its children + the background art, so the slot buttons still seat in the painted
|
||
wells — only the on-screen size differs.
|
||
- The bag portrait is the C-side SetBagPortaitTexture (ContainerFrame.lua l.422): the backpack
|
||
shows the static `Interface\Buttons\Button-Backpack-Up` art, an equipped bag its own item
|
||
icon (BenillaBagWindow_Update reads inv slot 19+bagId).
|
||
- Bags 1..4 SNUG-FIT to their real row count (BenillaBagWindow_FitBackground): the background
|
||
is stitched from the real client's `UI-Bag-Components` top/middle/bottom pieces sized to
|
||
ceil(size/4) rows (ContainerFrame.lua ContainerFrame_GenerateFrame, id~=0 branch), so a
|
||
6-slot pouch is a 2-row window, not the backpack's 5-row slab. The backpack (id 0) keeps its
|
||
own single `UI-BackpackBackground` slab (the id==0 branch), unchanged.
|
||
MONEY: reuses the shared BenillaMoney_Set/_Clear purse helpers (they live in MerchantFrame.xml
|
||
— decision 0084's reusable money display; the same reuse the loot window makes). At runtime
|
||
every FrameXML file is loaded before any event fires, so the helper is defined by the time
|
||
BenillaBagWindow_Update first runs; a unit test that loads this file in isolation must also
|
||
load MerchantFrame.xml (as the loot tests do). Money is BACKPACK ONLY (ContainerFrame.lua
|
||
l.314 shows the MoneyFrame only for id==0) — every other window hides it.
|
||
|
||
The title inherits GameFontHighlight and the counts NumberFontNormal — both live in the
|
||
shipped Fonts.xml (the font-object slice already landed), so they render in the real fonts.
|
||
-->
|
||
<Script><![CDATA[
|
||
-- The five windows' shared slot count cap: the backpack is always exactly 16
|
||
-- (C_Container.GetContainerNumSlots(0) never varies — PACK_SLOTS is a wire constant); the
|
||
-- equipped-bag windows show up to this many (5 rows × 4 columns — the reference template's
|
||
-- true max is 36, but 20 is vanilla's largest actual equippable bag, and building out to 36
|
||
-- slot buttons per window for content that can never exist would be pure waste. Hides the
|
||
-- unused tail via BenillaBagSlot_Update's physIndex-past-size branch, same as the backpack.
|
||
BENILLA_BAG_WINDOW_MAX_SLOTS = 20
|
||
|
||
-- The keyring's container id (ref MainMenuBarBagButtons.lua:1) — decision 0765. It is an
|
||
-- ordinary container in every respect the seam cares about: the app feeds it like any other
|
||
-- bag (its slots are the player descriptor's own 81.., no container object), and every
|
||
-- C_Container verb, the cursor, the pending-op lock and the wire drains take it unchanged.
|
||
-- What makes it special is only what the reference makes special: the window's art, its
|
||
-- open/close sound, and the fact that its capacity is not a wire field.
|
||
KEYRING_CONTAINER = -2
|
||
|
||
-- The keyring's usable slot count (ref GetKeyRingSize, ContainerFrame.lua:773). The
|
||
-- reference recomputes a level ladder in Lua (4 / 8 at 40 / 12 at 50 / 16 above 60) that the
|
||
-- server enforces identically (Player::GetMaxKeyringSize); benilla computes it once app-side
|
||
-- and feeds it as the container's own size, so this reads it back rather than keeping a
|
||
-- second copy of the ladder that could drift from the one the feed uses.
|
||
function GetKeyRingSize()
|
||
return C_Container.GetContainerNumSlots(KEYRING_CONTAINER)
|
||
end
|
||
|
||
-- BenillaBagSlot_OnLoad(button, physIndex): physIndex is the button's CHAIN position (1 =
|
||
-- bottom-right, growing up-and-left — the anchor order below), not the game slot. The ref's
|
||
-- own formula (index = size - j + 1, ContainerFrame.lua:426/446) maps chain position → game
|
||
-- slot dynamically in BenillaBagSlot_Update, so slot 1 always reads top-left regardless of
|
||
-- how many of the window's slots are actually occupied — recomputed every Update (the ref
|
||
-- only computes it once, at window generation; recomputing is a strict robustness win for
|
||
-- the rare live bag-swap case, not a behavior change for a size that never moves).
|
||
function BenillaBagSlot_OnLoad(button, physIndex)
|
||
button.physIndex = physIndex
|
||
button.icon = getglobal(button:GetName() .. "Icon")
|
||
button.count = getglobal(button:GetName() .. "Count")
|
||
-- Both buttons must reach OnClick (the default set is LeftButtonUp only): LEFT-click is the
|
||
-- pickup gesture (PickupContainerItem — pick up / place / swap on the cursor); RIGHT-click
|
||
-- cancels a held cursor, else uses the slot (the C side sells it when a merchant is open —
|
||
-- our container drain forks).
|
||
button:RegisterForClicks("LeftButtonUp", "RightButtonUp")
|
||
-- The drag trio (decision 0216 §3): click-carry and drag are ONE code path in the
|
||
-- reference (ContainerFrame.xml:40-55 routes OnDragStart/OnReceiveDrag to the same
|
||
-- OnClick("LeftButton", ignoreModifiers=1) the plain click uses) — see
|
||
-- BenillaBagSlot_OnClick below for the identical routing (its own `ignoreModifiers`
|
||
-- suppresses the shift-split fork, the reference's own contract for drag/receive).
|
||
button:RegisterForDrag("LeftButton")
|
||
BenillaBagSlot_Update(button)
|
||
end
|
||
|
||
function BenillaBagSlot_OnClick(button, mouseButton, ignoreModifiers)
|
||
if button.slot == nil then return end -- a hidden button (physIndex past the bag's size)
|
||
local bagId = button:GetParent():GetID()
|
||
if mouseButton == "LeftButton" then
|
||
local info = C_Container.GetContainerItemInfo(bagId, button.slot)
|
||
-- The stack-split trigger — SHIFT + left-click on an unlocked stack of ≥2, the
|
||
-- reference fork verbatim (ContainerFrame.lua:567-577; ctrl's dress-up and the
|
||
-- chat-link insert are named deferrals). `ignoreModifiers` (the drag-trio calls,
|
||
-- both true) suppresses the fork, the reference's own drag/receive contract.
|
||
if IsShiftKeyDown() and not ignoreModifiers then
|
||
if info and not info.isLocked and (info.stackCount or 1) >= 2 then
|
||
button.SplitStack = function(btn, n)
|
||
SplitContainerItem(bagId, btn.slot, n)
|
||
BenillaBagWindow_Repaint(btn:GetParent())
|
||
end
|
||
-- Ref ContainerFrameItemButton_OnLoad/_OnClick (ContainerFrame.lua:558-560,
|
||
-- 573-576): the owner's own SplitStack closure carries the bag/slot so
|
||
-- StackSplitFrameOkay_Click's generic `owner.SplitStack(owner, split)` call
|
||
-- needs no window-specific knowledge. SplitContainerItem is a TOP-LEVEL
|
||
-- global (cursor.rs — not under C_Container despite the container-verb
|
||
-- naming; GetContainerItemInfo/PickupContainerItem ARE namespaced).
|
||
OpenStackSplitFrame(info.stackCount, button, "BOTTOMRIGHT", "TOPRIGHT")
|
||
end
|
||
return
|
||
end
|
||
-- A plain click hides any open split frame (ref ContainerFrame.lua:581) before the
|
||
-- ordinary pickup/place proceeds.
|
||
local split = getglobal("BenillaStackSplitFrame")
|
||
if split then split:Hide() end
|
||
-- PickupContainerItem is the single drag entry point (real client): an empty cursor
|
||
-- picks this slot up; a held cursor places/swaps into it (same slot = cancel). Hide the
|
||
-- hover tooltip (the item just left the slot for the cursor) and repaint so the picked
|
||
-- slot dims / un-dims immediately — the swap itself settles when the server answers.
|
||
C_Container.PickupContainerItem(bagId, button.slot)
|
||
GameTooltip:Hide()
|
||
BenillaBagWindow_Repaint(button:GetParent())
|
||
elseif mouseButton == "RightButton" then
|
||
-- A held cursor cancels (client-side, nothing sent); otherwise use/equip/sell the slot.
|
||
if CursorHasItem() then
|
||
ClearCursor()
|
||
BenillaBagWindow_Repaint(button:GetParent())
|
||
else
|
||
C_Container.UseContainerItem(bagId, button.slot)
|
||
end
|
||
end
|
||
end
|
||
|
||
-- Hover: the era-true GameTooltip:SetBagItem(bag, slot) — the ENGINE renders the full
|
||
-- item tooltip from the template store and owns the sell-price money law (real instance
|
||
-- + merchant open + repair off ⇒ OnTooltipAddMoney(SellPrice × stack), or the
|
||
-- ITEM_UNSELLABLE line — wow-re ui/scratch/tooltip-money.md's byte-verified gate,
|
||
-- decision 0274 P1). The durability-adjusted damaged price is deferred until durability
|
||
-- damage reaches the feed (a pristine item reduces to SellPrice × stack, the case we
|
||
-- ship). Nothing shows while the template is in flight — the OnUpdate re-enter fills it.
|
||
function BenillaBagSlot_OnEnter(button)
|
||
if button.slot == nil then return end
|
||
local bagId = button:GetParent():GetID()
|
||
local info = C_Container.GetContainerItemInfo(bagId, button.slot)
|
||
-- An emptied slot drops its tooltip (ref ContainerFrame_Update's texture-nil branch,
|
||
-- ContainerFrame.lua:281-283) — without this the OnUpdate re-enter below would leave
|
||
-- a stale tooltip up after the item is sold or moved out from under the hover.
|
||
if not info then
|
||
if GameTooltip:IsOwned(button) then GameTooltip:Hide() end
|
||
return
|
||
end
|
||
-- Ref ContainerFrameItemButton_OnEnter (ContainerFrame.lua:602-612) verbatim: a slot
|
||
-- in the RIGHT half of the screen hangs its tooltip LEFT, so it never runs off the
|
||
-- edge (the bag lives at the bottom-right — this is the ref's own screen-edge answer,
|
||
-- a side-pick, not a clamp).
|
||
if (button:GetRight() or 0) >= (GetScreenWidth() / 2) then
|
||
GameTooltip:SetOwner(button, "ANCHOR_LEFT")
|
||
else
|
||
GameTooltip:SetOwner(button, "ANCHOR_RIGHT")
|
||
end
|
||
GameTooltip:SetBagItem(bagId, button.slot)
|
||
-- The pouch/magnifier cursor (ref ContainerFrameItemButton_OnEnter tail,
|
||
-- ContainerFrame.lua l.636-642): merchant open on the MERCHANT tab and not repair
|
||
-- mode → the sell cursor over this slot; else a readable item (a mail letter copy —
|
||
-- right-click opens the reader) → the Inspect magnifier; anything else restores the
|
||
-- base cursor. The OnUpdate re-enter keeps it current while hovering (the ref's own
|
||
-- loop). The ref's `IsControlKeyDown() and hasItem` magnifier arm (the Ctrl+click
|
||
-- dress-up preview cursor) is omitted with the dress-up feature itself.
|
||
if BenillaMerchantFrame and BenillaMerchantFrame:IsShown()
|
||
and BenillaMerchantFrame.selectedTab == 1 and not InRepairMode() then
|
||
ShowContainerSellCursor(bagId, button.slot)
|
||
elseif info.isReadable then
|
||
ShowInspectCursor()
|
||
else
|
||
ResetCursor()
|
||
end
|
||
GameTooltip:Show()
|
||
end
|
||
|
||
function BenillaBagSlot_OnLeave(button)
|
||
GameTooltip:Hide()
|
||
-- Ref ItemButton OnLeave (ContainerFrame.xml): the hover's sell cursor drops with it.
|
||
ResetCursor()
|
||
end
|
||
|
||
-- Ref ContainerFrameItemButton_OnUpdate (ContainerFrame.lua:645-660): while the tooltip
|
||
-- is ours, re-run OnEnter every frame — the ref ships this loop UNTHROTTLED (its
|
||
-- updateTooltip throttle is commented out in 1.12). It is the real client's own refresh
|
||
-- mechanism: a tooltip set while the item template was still in flight fills itself in
|
||
-- the moment the answer lands, no re-hover.
|
||
function BenillaBagSlot_OnUpdate(button)
|
||
if GameTooltip:IsOwned(button) then
|
||
BenillaBagSlot_OnEnter(button)
|
||
end
|
||
end
|
||
|
||
-- The item's use-cooldown sweep (ref ContainerFrame_UpdateCooldown,
|
||
-- ContainerFrame.lua:295-299, verbatim shape over our C_Container dialect).
|
||
function BenillaBagSlot_UpdateCooldown(button, bagId)
|
||
local cooldown = getglobal(button:GetName() .. "Cooldown")
|
||
local start, duration, enable = C_Container.GetContainerItemCooldown(bagId, button.slot)
|
||
CooldownFrame_SetTimer(cooldown, start, duration, enable)
|
||
end
|
||
|
||
-- The physIndex → game-slot resolution (the module doc above) + the paint (ref
|
||
-- ContainerFrame_Update, ContainerFrame.lua:234-293). Shared by every window's slot
|
||
-- buttons. The occupied/empty fork drives the cooldown exactly as the ref does
|
||
-- (l.248-253: occupied → UpdateCooldown, empty → Cooldown:Hide()).
|
||
function BenillaBagSlot_Update(button)
|
||
local bagId = button:GetParent():GetID()
|
||
local size = C_Container.GetContainerNumSlots(bagId)
|
||
if button.physIndex > size then
|
||
button.slot = nil
|
||
button:Hide()
|
||
return
|
||
end
|
||
button.slot = size - button.physIndex + 1
|
||
button:Show()
|
||
local info = C_Container.GetContainerItemInfo(bagId, button.slot)
|
||
if info then
|
||
BenillaBagSlot_UpdateCooldown(button, bagId)
|
||
button.icon:SetTexture(info.iconFileID or BENILLA_FALLBACK_ICON)
|
||
-- A locked slot (its item is up on the cursor, or a send is still pending
|
||
-- server-side, decision 0216 §4/0218 §3) dims, the real client's drag feedback.
|
||
if info.isLocked then
|
||
button.icon:SetVertexColor(0.4, 0.4, 0.4)
|
||
else
|
||
button.icon:SetVertexColor(1, 1, 1)
|
||
end
|
||
if (info.stackCount or 1) > 1 then
|
||
button.count:SetText(info.stackCount)
|
||
else
|
||
button.count:SetText("")
|
||
end
|
||
else
|
||
button.icon:SetTexture(nil)
|
||
button.count:SetText("")
|
||
getglobal(button:GetName() .. "Cooldown"):Hide()
|
||
end
|
||
end
|
||
|
||
-- The generic per-window repaint (decision 0216 slice 2): every slot up to this window's
|
||
-- cap, the title (C_Container.GetBagName — dynamic since a live bag swap changes it), and the money
|
||
-- purse (backpack only, ContainerFrame.lua l.314). BenillaBagFrame_Update (below) is the
|
||
-- backpack's zero-arg convenience alias, kept for existing callers (UiPanels.xml's
|
||
-- OpenBackpack/CloseBackpack, and the tests that patch it directly).
|
||
function BenillaBagWindow_Update(frame)
|
||
local bagId = frame:GetID()
|
||
local maxSlots = (bagId == 0) and 16 or BENILLA_BAG_WINDOW_MAX_SLOTS
|
||
-- The backpack predates the $parent-prefixed slot naming (BenillaBagSlot1..16, not
|
||
-- BenillaBagFrameSlot1..16 — its buttons are hand-authored, not $parent-templated) and
|
||
-- several existing tests reference that exact name directly; every other window's slots
|
||
-- DO follow frame:GetName().."Slot"..i (the virtual template's $parentSlotN).
|
||
local slotPrefix = (bagId == 0) and "BenillaBagSlot" or (frame:GetName() .. "Slot")
|
||
for i = 1, maxSlots do
|
||
local button = getglobal(slotPrefix .. i)
|
||
if button then BenillaBagSlot_Update(button) end
|
||
end
|
||
local title = getglobal(frame:GetName() .. "Name")
|
||
if title then
|
||
-- The keyring is titled from the localized KEYRING string, not GetBagName — it has
|
||
-- no bag ITEM to be named after (ref ContainerFrame.lua l.418).
|
||
if bagId == KEYRING_CONTAINER then
|
||
title:SetText(KEYRING)
|
||
else
|
||
title:SetText(C_Container.GetBagName(bagId) or "")
|
||
end
|
||
end
|
||
if bagId == 0 then
|
||
BenillaMoney_Set("BenillaBagMoney", GetMoney())
|
||
elseif bagId == KEYRING_CONTAINER then
|
||
-- Fixed art, again because there is no bag item: the keyring's own portrait
|
||
-- (ref ContainerFrame.lua l.419) and its own background variant, snug-fitted to the
|
||
-- level-gated slot count exactly like an equipped bag.
|
||
local portrait = getglobal(frame:GetName() .. "Portrait")
|
||
if portrait then
|
||
portrait:SetPortraitToTexture("Interface\\ContainerFrame\\KeyRing-Bag-Icon")
|
||
end
|
||
local size = C_Container.GetContainerNumSlots(bagId)
|
||
if size > 0 then BenillaBagWindow_FitBackground(frame, size) end
|
||
else
|
||
-- The window's portrait is the bag's OWN item icon (the real client's
|
||
-- C-side SetBagPortaitTexture), not the default backpack art. An equipped bag
|
||
-- (1..4) reads its doll slot (19+bagId, Bag0Slot..Bag3Slot); a bank bag (5..10,
|
||
-- decision 0604) reads the app-resolved bank-bag feed instead — the doll array
|
||
-- stops at the equipped bags, so GetInventoryItemTexture can't reach the vault's.
|
||
-- Falls back to the backpack icon while the item template's icon is in flight.
|
||
local portrait = getglobal(frame:GetName() .. "Portrait")
|
||
if portrait then
|
||
local icon
|
||
if bagId >= 5 then
|
||
icon = BenillaGetBankBagTexture(bagId - 4)
|
||
else
|
||
icon = GetInventoryItemTexture("player", 19 + bagId)
|
||
end
|
||
if icon then
|
||
-- The circular crop (the real SetBagPortaitTexture is C-side and masks the
|
||
-- icon to the ring's inscribed circle): a raw square icon pokes its corners
|
||
-- past the round rim — the director's bank-bag popout artifact.
|
||
portrait:SetPortraitToTexture(icon)
|
||
else
|
||
-- The backpack fallback art is authored round — no crop to apply.
|
||
portrait:SetTexture("Interface\\Buttons\\Button-Backpack-Up")
|
||
end
|
||
end
|
||
-- Equipped bags snug-fit their stitched background to the live row count.
|
||
local size = C_Container.GetContainerNumSlots(bagId)
|
||
if size > 0 then BenillaBagWindow_FitBackground(frame, size) end
|
||
end
|
||
end
|
||
|
||
-- Fit an equipped-bag window's stitched background (BgTop/BgMiddle/BgBottom, authored in the
|
||
-- template above) and its OWN height to the bag's actual row count. This is a transcription of
|
||
-- the real client's ContainerFrame_GenerateFrame (the id~=0 branch) as shipped in the 1.12.1
|
||
-- MPQ (Interface\FrameXML\ContainerFrame.lua) — every constant below is the reference's, not a
|
||
-- measured approximation. rows = ceil(size/4). The TOP piece carries the header + the first
|
||
-- well row; the MIDDLE tiles the remaining rows; the BOTTOM is the frame's bottom rim. The
|
||
-- slot buttons anchor UP from the frame's BOTTOMRIGHT (first at -12,9) and hide past `size`
|
||
-- (BenillaBagSlot_Update), so nothing here touches them — only the art + the frame height.
|
||
-- Which UI-Bag-Components variant a window is stitched from — the ref's own `bagTextureSuffix`
|
||
-- (ContainerFrame_GenerateFrame, ContainerFrame.lua l.326-334): the bank bags get the
|
||
-- tinted "-Bank" plate, the keyring the "-Keyring" one, an equipped bag the plain sheet.
|
||
-- All three atlases are 256x512 with the same band layout, so FitBackground's tex-coords
|
||
-- are shared verbatim and only the file differs. (Ours ALSO applies the "-Bank" arm, which
|
||
-- benilla had been quietly skipping — the bank popouts have been drawing ordinary bag art
|
||
-- since decision 0604.)
|
||
function BenillaBagWindow_BgTexture(bagId)
|
||
local suffix = ""
|
||
if bagId >= 5 then
|
||
suffix = "-Bank"
|
||
elseif bagId == KEYRING_CONTAINER then
|
||
suffix = "-Keyring"
|
||
end
|
||
return "Interface\\ContainerFrame\\UI-Bag-Components" .. suffix
|
||
end
|
||
|
||
function BenillaBagWindow_FitBackground(frame, size)
|
||
local name = frame:GetName()
|
||
local top = getglobal(name .. "BgTop")
|
||
local middle = getglobal(name .. "BgMiddle")
|
||
local bottom = getglobal(name .. "BgBottom")
|
||
if not (top and middle and bottom) then return end
|
||
-- Re-set every fit, as the ref does at every generate: the template authors the plain
|
||
-- sheet, and a window's kind is only known from its id.
|
||
local bg = BenillaBagWindow_BgTexture(frame:GetID())
|
||
top:SetTexture(bg)
|
||
middle:SetTexture(bg)
|
||
bottom:SetTexture(bg)
|
||
local rowH = 41 -- rowHeight
|
||
local rows = math.ceil(size / 4)
|
||
if rows < 1 then rows = 1 end
|
||
-- isPlusTwoBag: a size leaving a remainder of 2 (6/10/14/18) has a 2-well top row, and the
|
||
-- texture carries a whole separate top band for it.
|
||
local plusTwo = (size - math.floor(size / 4) * 4) == 2
|
||
local topH
|
||
if plusTwo then
|
||
topH = 72
|
||
top:SetTexCoord(0, 1, 0.189453125, 0.330078125)
|
||
elseif rows == 1 then
|
||
topH = 86 -- one row only: chop the bottom of the texture
|
||
top:SetTexCoord(0, 1, 0.00390625, 0.16796875)
|
||
else
|
||
topH = 94
|
||
top:SetTexCoord(0, 1, 0.00390625, 0.18359375)
|
||
end
|
||
top:SetHeight(topH)
|
||
-- The top piece already carries one row, so the middle tiles `rows - 1` more. Its height is
|
||
-- one row short of a clean multiple: the reference's firstRowPixelOffset = 9 accounts for
|
||
-- the 9px the BOTTOM rim itself contributes to the final row's frame. Getting this wrong
|
||
-- pushes the rim a row-fraction too low and bleeds the NEXT row's wells in above it.
|
||
local middleH = 0
|
||
bottom:ClearAllPoints()
|
||
if rows > 1 then
|
||
-- A single middle piece spans at most ROWS_IN_BG_TEXTURE (6) rows; the reference
|
||
-- cycles up to MAX_BG_TEXTURES for windows taller than that. Our largest window is a
|
||
-- 20-slot bag (4 middle rows) and the keyring caps at 16 (3), so one always suffices.
|
||
middleH = (rows - 1) * rowH - 9
|
||
middle:SetHeight(middleH)
|
||
middle:SetTexCoord(0, 1, 0.353515625, middleH / 512 + 0.353515625)
|
||
middle:Show()
|
||
bottom:SetPoint("TOPRIGHT", middle, "BOTTOMRIGHT", 0, 0)
|
||
else
|
||
-- One row: the rim seats straight under the top piece. (The reference anchors it to the
|
||
-- hidden middle's TOP, which is the same point — the middle hangs off the top's bottom.)
|
||
middle:Hide()
|
||
bottom:SetPoint("TOPRIGHT", top, "BOTTOMRIGHT", 0, 0)
|
||
end
|
||
-- The bottom rim is a FIXED 10px band at texture v 0.330078125..0.349609375 — the strip
|
||
-- immediately below the plus-two top band, and the only true outer bottom border in the
|
||
-- texture. The reference never rescales or re-coords it; it is authored once in XML.
|
||
local bottomH = 10
|
||
bottom:SetHeight(bottomH)
|
||
bottom:SetTexCoord(0, 1, 0.330078125, 0.349609375)
|
||
frame:SetHeight(topH + middleH + bottomH)
|
||
-- A live size change (a bag swap while the stack is open) shifts every window stacked above
|
||
-- this one; re-run the stack layout so they re-seat against the new height.
|
||
if frame:IsShown() then BenillaBagStack_Relayout() end
|
||
end
|
||
|
||
function BenillaBagFrame_Update()
|
||
BenillaBagWindow_Update(BenillaBagFrame)
|
||
end
|
||
|
||
-- Routes a repaint through the backpack's own zero-arg BenillaBagFrame_Update alias when
|
||
-- `frame` IS the backpack — preserving that global's observability (existing tests patch it
|
||
-- directly to count backpack repaints, e.g. delete_item_tests.rs's stuck-darkening
|
||
-- regression check) — and BenillaBagWindow_Update generically for every other window. Every
|
||
-- runtime repaint trigger (a slot click, an event, BenillaOpenAllBags' pre-show paint) goes
|
||
-- through this; BenillaBagBarSlot_OnClick calls BenillaBagWindow_Update directly (it only ever
|
||
-- targets bags 1..4).
|
||
function BenillaBagWindow_Repaint(frame)
|
||
if frame:GetID() == 0 then
|
||
BenillaBagFrame_Update()
|
||
else
|
||
BenillaBagWindow_Update(frame)
|
||
end
|
||
end
|
||
|
||
-- OnLoad/OnEvent (generic, shared by all five windows — each already receives `frame`, so
|
||
-- deriving bagId from `frame:GetID()` needs no per-window body).
|
||
function BenillaBagFrame_OnLoad(frame)
|
||
frame:RegisterEvent("BAG_UPDATE")
|
||
-- The engine fires ITEM_LOCK_CHANGED(bag, slot) on every cursor pickup/clear AND every
|
||
-- pending-op send/resolve (decisions 0216 §4/0218 §3) — including clears the bag never
|
||
-- clicked through (the delete popup's No, ESC; a server failure), which the click-time
|
||
-- repaint can't see. The reference ContainerFrame repaints on exactly this event.
|
||
frame:RegisterEvent("ITEM_LOCK_CHANGED")
|
||
-- Item cooldown starts/ends (ref ContainerFrame_OnLoad, ContainerFrame.lua:21 —
|
||
-- BAG_UPDATE_COOLDOWN carries no bag argument; every open window refreshes).
|
||
frame:RegisterEvent("BAG_UPDATE_COOLDOWN")
|
||
-- The real backpack MoneyFrame refreshes on PLAYER_MONEY (SmallMoneyFrame's own OnEvent);
|
||
-- keep the purse live while the window is open. Backpack only — the other windows never
|
||
-- show a purse, so there's nothing for them to refresh.
|
||
if frame:GetID() == 0 then
|
||
frame:RegisterEvent("PLAYER_MONEY")
|
||
end
|
||
end
|
||
|
||
function BenillaBagFrame_OnEvent(frame)
|
||
if event == "PLAYER_MONEY" then
|
||
BenillaMoney_Set("BenillaBagMoney", GetMoney())
|
||
return
|
||
end
|
||
-- The cooldown-only refresh (ref ContainerFrame_UpdateCooldowns via OnEvent,
|
||
-- ContainerFrame.lua:243-253's loop shape): no bag argument — sweep every shown
|
||
-- slot of THIS window, no full repaint.
|
||
if event == "BAG_UPDATE_COOLDOWN" then
|
||
local bagId = frame:GetID()
|
||
local maxSlots = (bagId == 0) and 16 or BENILLA_BAG_WINDOW_MAX_SLOTS
|
||
local slotPrefix = (bagId == 0) and "BenillaBagSlot" or (frame:GetName() .. "Slot")
|
||
for i = 1, maxSlots do
|
||
local button = getglobal(slotPrefix .. i)
|
||
if button and button.slot then
|
||
BenillaBagSlot_UpdateCooldown(button, bagId)
|
||
end
|
||
end
|
||
return
|
||
end
|
||
-- BAG_UPDATE / ITEM_LOCK_CHANGED name their bag in arg1; only THIS window's own bag
|
||
-- repaints (ref ContainerFrame_OnEvent, ContainerFrame.lua:26-44: `this:GetID() == arg1`).
|
||
if (event == "BAG_UPDATE" or event == "ITEM_LOCK_CHANGED") and arg1 ~= frame:GetID() then
|
||
return
|
||
end
|
||
BenillaBagWindow_Repaint(frame)
|
||
end
|
||
|
||
-- OpenAllBags / CloseAllBags / ToggleBackpack (ref ContainerFrame.lua l.152-217): the 'B'
|
||
-- binding (OPENALLBAGS) and the backpack button BOTH open or close EVERY bag at once, not
|
||
-- just the backpack — the real client's own behavior (MainMenuBarBackpackButton's OnClick and
|
||
-- the OPENALLBAGS binding both route to ToggleBackpack). "All bags" = the backpack (bag 0,
|
||
-- which always exists) plus each equipped-bag slot 1..4 that actually holds a bag
|
||
-- (GetContainerNumSlots > 0); an empty slot has no window to show. The five windows, indexed
|
||
-- by bag id (BENILLA_BAG_WINDOWS[bagId+1]) — one code path over all of them.
|
||
BENILLA_BAG_WINDOWS = { "BenillaBagFrame", "BenillaBagFrame1", "BenillaBagFrame2", "BenillaBagFrame3", "BenillaBagFrame4" }
|
||
|
||
function BenillaOpenAllBags()
|
||
for bagId = 0, 4 do
|
||
-- The backpack always exists; an equipped-bag slot only when a bag is in it.
|
||
if bagId == 0 or C_Container.GetContainerNumSlots(bagId) > 0 then
|
||
local frame = getglobal(BENILLA_BAG_WINDOWS[bagId + 1])
|
||
if frame and not frame:IsShown() then
|
||
BenillaBagWindow_Repaint(frame) -- bag 0 routes through its observable alias
|
||
frame:Show()
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
function BenillaCloseAllBags()
|
||
for _, name in ipairs(BENILLA_BAG_WINDOWS) do
|
||
local frame = getglobal(name)
|
||
if frame and frame:IsShown() then frame:Hide() end
|
||
end
|
||
end
|
||
|
||
-- The backpack button (BenillaBagToggle) and the 'B' binding: if any bag window is open,
|
||
-- close them all; otherwise open every existing bag (ref ToggleBackpack — "if numOpen > 0
|
||
-- then CloseAllBags() else OpenAllBags()").
|
||
function BenillaBagToggle_OnClick()
|
||
local anyOpen = false
|
||
for _, name in ipairs(BENILLA_BAG_WINDOWS) do
|
||
local frame = getglobal(name)
|
||
if frame and frame:IsShown() then anyOpen = true end
|
||
end
|
||
if anyOpen then BenillaCloseAllBags() else BenillaOpenAllBags() end
|
||
-- The auto-toggle is provisional (ref BackpackButton_OnClick l.58-67): the button
|
||
-- lights for the BACKPACK window specifically, whatever the all-toggle just did.
|
||
local backpack = getglobal(BENILLA_BAG_WINDOWS[1])
|
||
getglobal("BenillaBagToggle"):SetChecked(backpack and backpack:IsShown())
|
||
end
|
||
|
||
-- The window's bar button (ref ContainerFrame_OnShow/OnHide: bag 0 →
|
||
-- MainMenuBarBackpackButton, bags 1..4 → CharacterBag(N-1)Slot).
|
||
function BenillaBagWindow_BarButton(frame)
|
||
local name = frame:GetName()
|
||
if name == "BenillaKeyRingFrame" then return getglobal("BenillaKeyRingButton") end
|
||
for bagId = 0, 4 do
|
||
if name == BENILLA_BAG_WINDOWS[bagId + 1] then
|
||
if bagId == 0 then return getglobal("BenillaBagToggle") end
|
||
return getglobal("BenillaBagBarSlot" .. bagId)
|
||
end
|
||
end
|
||
end
|
||
|
||
-- Open/close sounds — the window-sound convention (decision 0090), wrapper form: a named
|
||
-- Benilla<Window>Frame_OnShow/_OnHide fn (used when the handler is more than the bare
|
||
-- PlaySound, or — as here — to carry the cite). Kits quoted from the real ContainerFrame.lua
|
||
-- ContainerFrame_OnShow/OnHide (l.124-142 / l.100-122), reused VERBATIM by every window
|
||
-- (backpack included), INCLUDING the real fn's keyring fork: the keyring has its own
|
||
-- jingling KeyRingOpen/KeyRingClose pair (both real SoundEntries kits), every other window
|
||
-- the plain igBackPackOpen/igBackPackClose. Fired on every visibility transition (a Show/Hide
|
||
-- from a toggle button, the 'B' binding, a close button, or ESC), never at load (every window
|
||
-- is authored hidden="true", so none ever transitions on startup).
|
||
--
|
||
-- The `this` legacy global (RF-0025, script/event.rs) names the window that just
|
||
-- shown/hidden — used here for the open-window STACK the layout law below reads, rather
|
||
-- than a per-window OnShow/OnHide body (which would defeat the whole point of sharing one
|
||
-- handler across five windows).
|
||
function BenillaBagFrame_OnShow()
|
||
if this:GetID() == KEYRING_CONTAINER then
|
||
PlaySound("KeyRingOpen")
|
||
else
|
||
PlaySound("igBackPackOpen")
|
||
end
|
||
-- The bar lights the open bag's button (ref ContainerFrame_OnShow l.124-131,
|
||
-- SetChecked(1)) — the window side is the source of truth, so a bag opened by any
|
||
-- path (the B key, a bar click, open-all at a vendor) lights its button.
|
||
local barButton = BenillaBagWindow_BarButton(this)
|
||
if barButton then barButton:SetChecked(1) end
|
||
BenillaBagStack_Open(this)
|
||
end
|
||
|
||
function BenillaBagFrame_OnHide()
|
||
if this:GetID() == KEYRING_CONTAINER then
|
||
PlaySound("KeyRingClose")
|
||
else
|
||
PlaySound("igBackPackClose")
|
||
end
|
||
-- ...and clears it on any close (ref ContainerFrame_OnHide l.84-95, SetChecked(0)).
|
||
local barButton = BenillaBagWindow_BarButton(this)
|
||
if barButton then barButton:SetChecked(0) end
|
||
BenillaBagStack_Close(this)
|
||
end
|
||
|
||
-- ── The open-bag stack + layout law (ref ContainerFrame1.bags +
|
||
-- updateContainerFrameAnchors, ContainerFrame.lua:472-552, transcribed shape) ─────────────
|
||
-- Open windows stack bottom-right UPWARD in show order: the first at the backpack's own
|
||
-- anchor (BOTTOMRIGHT, x=0/y=70 — CONTAINER_OFFSET_X/Y), each next one anchored above the
|
||
-- previous (TOPRIGHT → BOTTOMRIGHT, CONTAINER_SPACING=0 gap); when a stack would run off the
|
||
-- top of the screen, the NEXT window starts a fresh column one CONTAINER_WIDTH further left.
|
||
-- Out of scope (nothing here ever needs it): the ref's UI-scale/BankFrame-collision shrink
|
||
-- branch (l.505-539) — benilla has no uiScale CVar and no bank window yet.
|
||
BENILLA_BAG_STACK = {}
|
||
local BENILLA_CONTAINER_OFFSET_X = 0
|
||
local BENILLA_CONTAINER_OFFSET_Y = 70
|
||
local BENILLA_CONTAINER_WIDTH = 192
|
||
local BENILLA_CONTAINER_SPACING = 0
|
||
local BENILLA_VISIBLE_CONTAINER_SPACING = 3
|
||
|
||
function BenillaBagStack_Open(frame)
|
||
table.insert(BENILLA_BAG_STACK, frame)
|
||
BenillaBagStack_Relayout()
|
||
end
|
||
|
||
function BenillaBagStack_Close(frame)
|
||
for i = 1, table.getn(BENILLA_BAG_STACK) do
|
||
if BENILLA_BAG_STACK[i] == frame then
|
||
table.remove(BENILLA_BAG_STACK, i)
|
||
break
|
||
end
|
||
end
|
||
BenillaBagStack_Relayout()
|
||
end
|
||
|
||
function BenillaBagStack_Relayout()
|
||
local screenHeight = GetScreenHeight()
|
||
local freeHeight = screenHeight - BENILLA_CONTAINER_OFFSET_Y
|
||
local column = 0
|
||
for i = 1, table.getn(BENILLA_BAG_STACK) do
|
||
local frame = BENILLA_BAG_STACK[i]
|
||
if i == 1 then
|
||
frame:SetPoint("BOTTOMRIGHT", -BENILLA_CONTAINER_OFFSET_X, BENILLA_CONTAINER_OFFSET_Y)
|
||
elseif freeHeight < frame:GetHeight() then
|
||
column = column + 1
|
||
freeHeight = screenHeight - BENILLA_CONTAINER_OFFSET_Y
|
||
frame:SetPoint("BOTTOMRIGHT",
|
||
-(column * BENILLA_CONTAINER_WIDTH) - BENILLA_CONTAINER_OFFSET_X,
|
||
BENILLA_CONTAINER_OFFSET_Y)
|
||
else
|
||
frame:SetPoint("BOTTOMRIGHT", BENILLA_BAG_STACK[i - 1], "TOPRIGHT", 0, BENILLA_CONTAINER_SPACING)
|
||
end
|
||
freeHeight = freeHeight - frame:GetHeight() - BENILLA_VISIBLE_CONTAINER_SPACING
|
||
end
|
||
end
|
||
|
||
-- ── The bag bar (decision 0216 slice 2) — four 30×30 buttons left of BenillaBagToggle,
|
||
-- mirroring the reference main-bar bag buttons (CharacterBag0..3Slot). No exact reference
|
||
-- XML was available to transcribe (not in the session's extracted set) — size (30×30) and
|
||
-- placement (left of the backpack button) are per the brief; inter-button spacing is an
|
||
-- authored assumption (2px), FLAGGED for the director's look. Each button shows the
|
||
-- equipped bag's own icon (GetInventoryItemTexture, inv slots 20..23 — Bag0Slot..Bag3Slot,
|
||
-- PaperDollItemFrame.dbc-verified, decision 0216 slice 2's char-feed extension) or the
|
||
-- empty-slot art when no bag is equipped there. Click toggles that bag's window — NAMED
|
||
-- DEFERRAL: no drag-to-equip a bag onto the bar yet (that's the paper-doll drag arc, slice
|
||
-- 3's scope, not this one).
|
||
-- The bag bar (and the backpack toggle) are RELOCATED onto the action bar — anchored into
|
||
-- BenillaActionBarArtFrame's bottom-right — which means they need seating one frame level
|
||
-- above the bar art or it paints over their icons. That lever lives with the frame it's
|
||
-- about: BenillaActionBarArt_SeatAbove (ActionBar.xml, loaded before this file), which
|
||
-- carries the full explanation; the micro-button row is its second caller. Called
|
||
-- nil-GUARDED here: the shipped load order always has the bar first, but ~25 bag/bank/
|
||
-- escape/merchant test harnesses load THIS file alone — and with no bar loaded there is by
|
||
-- definition no bar art to seat above, so the guard's no-op is the right answer, not a
|
||
-- swallowed failure.
|
||
|
||
-- Bag0Slot..Bag3Slot = live inv ids 20..23 (char_stats.rs SLOT_INFO, DBC-verified); OUR bag
|
||
-- ids 1..4 map the same way (bagId N ⇒ inv slot 19+N), the id PickupInventoryItem/
|
||
-- GetInventoryItemTexture speak.
|
||
function BenillaBagBarSlot_InvSlot(button) return 19 + button.bagId end
|
||
|
||
function BenillaBagBarSlot_OnLoad(button, bagId)
|
||
button.bagId = bagId
|
||
button.icon = getglobal(button:GetName() .. "Icon")
|
||
if BenillaActionBarArt_SeatAbove then BenillaActionBarArt_SeatAbove(button) end
|
||
button:RegisterForClicks("LeftButtonUp")
|
||
-- Drag-to-equip (decision 0208 phase 1b's deferred bag-icon arm, now landed): the bar
|
||
-- slot is a paper-doll equipment slot for bags. LEFT drag picks the equipped bag up;
|
||
-- a drag/receive drops a carried bag in to equip it (PickupInventoryItem — the exact
|
||
-- doll-slot transition, the app maps id 20..23 onto wire bag slots 19..22).
|
||
button:RegisterForDrag("LeftButton")
|
||
button:RegisterEvent("UNIT_INVENTORY_CHANGED")
|
||
button:RegisterEvent("BAG_UPDATE")
|
||
button:RegisterEvent("ITEM_LOCK_CHANGED")
|
||
BenillaBagBarSlot_Update(button)
|
||
end
|
||
|
||
-- Placing/equipping a carried bag (or picking the equipped one up) rides PickupInventoryItem,
|
||
-- exactly like a paper-doll slot; the empty-cursor plain click just toggles the bag's window.
|
||
function BenillaBagBarSlot_Place(button)
|
||
PickupInventoryItem(BenillaBagBarSlot_InvSlot(button))
|
||
BenillaBagBarSlot_Update(button)
|
||
end
|
||
|
||
function BenillaBagBarSlot_OnClick(button)
|
||
if CursorHasItem() then
|
||
BenillaBagBarSlot_Place(button) -- drop/equip the carried bag onto this slot
|
||
else
|
||
local frame = getglobal("BenillaBagFrame" .. button.bagId)
|
||
if frame then
|
||
if frame:IsShown() then
|
||
frame:Hide()
|
||
else
|
||
BenillaBagWindow_Update(frame)
|
||
frame:Show()
|
||
end
|
||
end
|
||
end
|
||
-- The click's own CheckButton auto-toggle is provisional — re-derive from the
|
||
-- window on every branch, the ref's exact tail (BagSlotButton_OnClick l.12-20:
|
||
-- SetChecked(isVisible) whether the click toggled, placed a bag, or did nothing).
|
||
local frame = getglobal("BenillaBagFrame" .. button.bagId)
|
||
button:SetChecked(frame and frame:IsShown())
|
||
end
|
||
|
||
function BenillaBagBarSlot_OnEvent(button)
|
||
if event == "UNIT_INVENTORY_CHANGED" and arg1 ~= "player" then return end
|
||
-- ITEM_LOCK_CHANGED names its slot in arg1/arg2; the bar's slots are the EQUIPMENT_BAG
|
||
-- space, so a bag-window lock event (a real bag id in arg1) never concerns the icon —
|
||
-- repainting anyway is idempotent (the lock read below is slot-specific). BAG_UPDATE
|
||
-- fires per-bag-CONTENTS change, not per-icon change (the icon is the bag ITEM's own
|
||
-- texture) — repainting on it too covers the freshly-equipped-bag-template-in-flight frame.
|
||
BenillaBagBarSlot_Update(button)
|
||
end
|
||
|
||
-- ── The bar buttons' hovers ───────────────────────────────────────────────────────────
|
||
-- ref GlobalStrings.lua l.132 / l.1458 (enUS), fallback form: the real localized
|
||
-- GlobalStrings.lua runs before this file at runtime (ui_script/mod.rs), so these only
|
||
-- fill in for the harnesses that load no patch chain.
|
||
BACKPACK_TOOLTIP = BACKPACK_TOOLTIP or "Backpack"
|
||
EQUIP_CONTAINER = EQUIP_CONTAINER or "Equip Container"
|
||
-- ref GlobalStrings.lua l.2472 / l.2810 — the keyring's window title + button tooltip, and
|
||
-- the full-keyring refusal.
|
||
KEYRING = KEYRING or "Keyring"
|
||
NO_EMPTY_KEYRING_SLOTS_ERROR = NO_EMPTY_KEYRING_SLOTS_ERROR or "Your keyring is full."
|
||
|
||
-- Both are PLAIN tooltips — the reference calls GameTooltip:SetText here, not
|
||
-- GameTooltip_AddNewbieTip, so unlike the micro buttons next door (0661) there is no second
|
||
-- explanation line to be missing. They also anchor beside the button (ANCHOR_LEFT, so the
|
||
-- plate opens toward screen center off a bottom-right button), NOT at the default corner.
|
||
--
|
||
-- ref MainMenuBarBackpackButton OnEnter (ref-MainMenuBarBagButtons.xml l.91-99). The ref
|
||
-- appends the live TOGGLEBACKPACK key with GameTooltip:AppendText; this engine has neither
|
||
-- GetBindingKey nor AppendText, so the suffix is concatenated from the one bare-key binding
|
||
-- we actually ship (ui_script/input.rs `bare_key_binding`: KeyB) — MicroMenu.xml's own shape
|
||
-- for the same problem, and the rendered line is identical.
|
||
function BenillaBagToggle_OnEnter(button)
|
||
if not GameTooltip then return end -- engine tests load file subsets
|
||
GameTooltip:SetOwner(button, "ANCHOR_LEFT")
|
||
GameTooltip:SetText(
|
||
BACKPACK_TOOLTIP .. " " .. NORMAL_FONT_COLOR_CODE .. "(B)" .. FONT_COLOR_CODE_CLOSE,
|
||
1.0, 1.0, 1.0)
|
||
end
|
||
|
||
-- ref BagSlotButton_OnEnter (ref-MainMenuBarBagButtons.lua l.86-96): the equipped bag's own
|
||
-- item tooltip, or "Equip Container" for an empty slot. The ref's "(F1)".."(F4)" suffix
|
||
-- needs GetBindingKey AND the TOGGLEBAG1..4 bindings — benilla ships neither, so no slot
|
||
-- carries one; the day those bind, this is where the suffix goes.
|
||
function BenillaBagBarSlot_OnEnter(button)
|
||
if not GameTooltip then return end
|
||
GameTooltip:SetOwner(button, "ANCHOR_LEFT")
|
||
if not GameTooltip:SetInventoryItem("player", BenillaBagBarSlot_InvSlot(button)) then
|
||
GameTooltip:SetText(EQUIP_CONTAINER, 1.0, 1.0, 1.0)
|
||
end
|
||
end
|
||
|
||
-- ref OnLeave for both (l.100-102 / the template's own): a plain Hide, no fade — the item
|
||
-- half of the split BenillaUnitFrame_OnLeave's comment describes.
|
||
function BenillaBagBarButton_OnLeave()
|
||
if GameTooltip then GameTooltip:Hide() end
|
||
end
|
||
|
||
-- ── The keyring (decision 0765) ──────────────────────────────────────────────────────────
|
||
-- ref ToggleKeyRing (ContainerFrame.lua:757-771). The reference generates the window on
|
||
-- demand from a pool of generic ContainerFrames sized to GetKeyRingSize(); ours is a fixed
|
||
-- window like the other six, so the toggle is the bag bar's own show/hide shape and the
|
||
-- size arrives through the feed. The ref's IsOptionFrameOpen() guard has no analogue here
|
||
-- (our bag-bar buttons carry none either — the game menu greys the row instead, 0674), and
|
||
-- its SetButtonPulse stop is moot with no pulse to stop (0304).
|
||
function ToggleKeyRing()
|
||
local frame = getglobal("BenillaKeyRingFrame")
|
||
if not frame then return end
|
||
if frame:IsShown() then
|
||
frame:Hide()
|
||
else
|
||
BenillaBagWindow_Update(frame)
|
||
frame:Show()
|
||
end
|
||
end
|
||
|
||
-- ref PutKeyInKeyRing (ContainerFrame.lua:740-755) — dropping a held key onto the keyring
|
||
-- BUTTON files it in the first free slot. "Pick up" from an empty slot IS the place gesture
|
||
-- (PickupContainerItem is the one entry point: empty cursor picks up, a held cursor places),
|
||
-- which is why the reference's own line reads as a pickup.
|
||
--
|
||
-- One deliberate un-quirking: the ref passes `NO_EMPTY_KEYRING_SLOTS`, but GlobalStrings
|
||
-- only ever defined `NO_EMPTY_KEYRING_SLOTS_ERROR` — so the real client silently prints
|
||
-- nothing when your keyring is full. We print the string that exists.
|
||
function PutKeyInKeyRing()
|
||
for i = 1, GetKeyRingSize() do
|
||
if not C_Container.GetContainerItemInfo(KEYRING_CONTAINER, i) then
|
||
C_Container.PickupContainerItem(KEYRING_CONTAINER, i)
|
||
return
|
||
end
|
||
end
|
||
if BenillaErrorsFrame_AddMessage then
|
||
BenillaErrorsFrame_AddMessage(NO_EMPTY_KEYRING_SLOTS_ERROR, 1.0, 0.1, 0.1)
|
||
end
|
||
end
|
||
|
||
-- ref KeyRingButton's OnLoad/OnClick/OnReceiveDrag (MainMenuBarBagButtons.xml l.142-199).
|
||
-- The button is authored HIDDEN and only ever revealed by BenillaMainMenuBar_UpdateKeyRing
|
||
-- (ActionBar.xml), which is where the whole show/hide law and its divergence note live.
|
||
function BenillaKeyRingButton_OnLoad(button)
|
||
button:SetID(KEYRING_CONTAINER)
|
||
button:RegisterForClicks("LeftButtonUp", "RightButtonUp")
|
||
button:RegisterForDrag("LeftButton")
|
||
-- The ref watches PLAYER_ENTERING_WORLD / VARIABLES_LOADED / BAG_UPDATE on the bar's art
|
||
-- frame; with no saved variable there is nothing for VARIABLES_LOADED to restore, and
|
||
-- BAG_UPDATE is what actually carries "a key just arrived".
|
||
button:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||
button:RegisterEvent("BAG_UPDATE")
|
||
if BenillaActionBarArt_SeatAbove then BenillaActionBarArt_SeatAbove(button) end
|
||
BenillaKeyRingButton_OnEvent()
|
||
end
|
||
|
||
function BenillaKeyRingButton_OnEvent()
|
||
if BenillaMainMenuBar_UpdateKeyRing then BenillaMainMenuBar_UpdateKeyRing() end
|
||
end
|
||
|
||
function BenillaKeyRingButton_OnClick(button)
|
||
-- Holding something ⇒ file it; empty-handed ⇒ open/close the keyring (ref l.166-173).
|
||
if CursorHasItem() then
|
||
PutKeyInKeyRing()
|
||
else
|
||
ToggleKeyRing()
|
||
end
|
||
-- Re-derive the lit ring from the window, the same provisional-toggle tail every other
|
||
-- bag-bar button uses.
|
||
local frame = getglobal("BenillaKeyRingFrame")
|
||
button:SetChecked(frame and frame:IsShown())
|
||
end
|
||
|
||
-- ref l.180-184: the plain KEYRING title plus the ref's own empty AddLine (which reserves
|
||
-- the second row the binding key would print into — we ship no TOGGLEKEYRING binding, the
|
||
-- same gap the bag slots' "(F1)".."(F4)" suffixes have).
|
||
function BenillaKeyRingButton_OnEnter(button)
|
||
if not GameTooltip then return end
|
||
GameTooltip:SetOwner(button, "ANCHOR_LEFT")
|
||
GameTooltip:SetText(KEYRING, 1.0, 1.0, 1.0)
|
||
end
|
||
|
||
function BenillaBagBarSlot_Update(button)
|
||
local invSlot = BenillaBagBarSlot_InvSlot(button)
|
||
local texture = GetInventoryItemTexture("player", invSlot)
|
||
button.icon:SetTexture(texture or "Interface\\PaperDoll\\UI-PaperDoll-Slot-Bag")
|
||
-- Dim while the bag is up on the cursor or a pending equip is in flight (the doll's own
|
||
-- drag feedback, IsInventoryItemLocked — the bag-slot twin of BenillaBagSlot_Update).
|
||
if IsInventoryItemLocked(invSlot) then
|
||
button.icon:SetVertexColor(0.4, 0.4, 0.4)
|
||
elseif button:IsEnabled() then
|
||
button.icon:SetVertexColor(1, 1, 1)
|
||
else
|
||
-- Disabled by Disable_BagButtons below: keep the grey. The reference needs no such
|
||
-- arm — its desaturation is a shader flag on the texture, untouched by an Update
|
||
-- that only re-sets the image — but ours IS a vertex colour (UiPanels.xml
|
||
-- SetDesaturation), so a bag update behind the open game menu would otherwise
|
||
-- repaint the icon bright under a button that stayed dead.
|
||
button.icon:SetVertexColor(0.5, 0.5, 0.5)
|
||
end
|
||
end
|
||
|
||
-- ── The item-push drop animation (decision 0887) ─────────────────────────────────────────
|
||
-- An item lands in a bag: its icon pops in above the bag bar, hangs there, then falls into
|
||
-- the button that took it and shrinks away. ref ItemAnim (MainMenuBarBagButtons.xml l.4-16 +
|
||
-- .lua l.68-80, .lua l.92-94): each bag button owns a hidden child that, on ITEM_PUSH
|
||
-- naming its own container, swaps in the pushed item's icon, rewinds to sequence time 0 and
|
||
-- shows itself; OnAnimFinished hides it again. A second push on the same button RESTARTS it
|
||
-- (SetSequenceTime(0,0)); pushes into different bags run independently. That is exactly the
|
||
-- machine below, with the reference's ITEM_PUSH `arg1` translated from its inventory-slot
|
||
-- vocabulary (20..23) into ours (bagId 1..4) app-side — ui_loot.rs `push_container` carries
|
||
-- the byte-verified selector.
|
||
--
|
||
-- The reference's is a <Model> playing Interface\ItemAnimations\ForcedBackpackItem.mdx — a
|
||
-- single 4-vertex quad on one animated bone, i.e. a 2D icon card with keyframed scale, alpha
|
||
-- and offset. benilla has no Model widget (decision 0137's Cooldown took the same posture:
|
||
-- model the mechanism, let our own renderer draw it), so it is a Texture driven by the
|
||
-- model's OWN tracks, read out of the shipped .m2 with `benilla-extract m2anim`/`m2bones`:
|
||
--
|
||
-- sequence 0, CLAMP (plays once), duration 1.000 s
|
||
-- texture-weight (alpha) 0.000→0.0 0.133→1.0 0.267→1.0 1.000→0.0 linear
|
||
-- bone 0 scale 0.000→1.0 0.133→1.2 0.267→1.0 1.000→0.014 linear
|
||
-- bone 0 translation 0.000→(0,0) 0.500→(0,0) 1.000→(+0.010,-0.040)
|
||
-- the quad itself: 0.03 x 0.03 model units, blend Alpha, unlit, no depth write
|
||
--
|
||
-- So: fade in over the first 133 ms while swelling to 1.2x; settle back to full size by
|
||
-- 267 ms; from there dwindle and fade continuously for the remaining 733 ms — while the
|
||
-- POSITION holds until the half-second and only then falls. The three tracks deliberately
|
||
-- do not share a schedule: the card is already down to ~0.69 size and ~0.68 alpha when it
|
||
-- starts moving, so the drop reads as the icon being drawn into the bag rather than as a
|
||
-- solid tile sliding. Those numbers are the file's, not ours.
|
||
--
|
||
-- THE ONE AUTHORED NUMBER is the model-unit → pixel scale, because a <Model> frame's 3D
|
||
-- projection is not RE-recorded (the ref's ItemAnim frame has no <Size> at all, so the rect
|
||
-- cannot be it) — see decision 0887's named gap. 1200 px/unit is the sibling calibration:
|
||
-- CooldownFrameTemplate is the same kind of degenerate UI model, its four quads span 0.04
|
||
-- units, and at its scale="0.75" that sweep covers a 36px action button ⇒ 0.04·K·0.75 = 36.
|
||
-- At K = 1200 this model's own numbers land on 36 px of icon (exactly a bag-bar button),
|
||
-- a 48 px fall and a 12 px sideways drift — which is why the sizes below are stated as the
|
||
-- model's ratios times the icon, not as free pixels: correct the scale in one place and the
|
||
-- whole animation stays in proportion.
|
||
BENILLA_ITEM_PUSH_PX_PER_UNIT = 1200
|
||
BENILLA_ITEM_PUSH_DURATION = 1.0
|
||
BENILLA_ITEM_PUSH_SIZE = 0.03 * BENILLA_ITEM_PUSH_PX_PER_UNIT -- 36
|
||
BENILLA_ITEM_PUSH_FALL = 0.04 * BENILLA_ITEM_PUSH_PX_PER_UNIT -- 48
|
||
BENILLA_ITEM_PUSH_DRIFT = 0.01 * BENILLA_ITEM_PUSH_PX_PER_UNIT -- 12
|
||
-- {time, value} keyframes, linear between (M2 track interpolation 1) — the file's own keys.
|
||
BENILLA_ITEM_PUSH_ALPHA = { {0.000, 0.0}, {0.133, 1.0}, {0.267, 1.0}, {1.000, 0.0} }
|
||
BENILLA_ITEM_PUSH_SCALE = { {0.000, 1.0}, {0.133, 1.2}, {0.267, 1.0}, {1.000, 0.014} }
|
||
-- The translation track as a 0..1 fraction of the fall (both components move together, so
|
||
-- one curve drives both axes — the file keys (0,0) at 0.000 and 0.500, the full offset at
|
||
-- 1.000, i.e. it hangs for the first half second and then drops).
|
||
BENILLA_ITEM_PUSH_DROP = { {0.000, 0.0}, {0.500, 0.0}, {1.000, 1.0} }
|
||
|
||
-- Sample a {time, value} keyframe list at `t`, linear between keys, clamped at both ends
|
||
-- (the M2 sampler's own shape for a CLAMP sequence).
|
||
function BenillaItemPushAnim_Sample(track, t)
|
||
local last = table.getn(track)
|
||
if t <= track[1][1] then return track[1][2] end
|
||
for i = 2, last do
|
||
local key = track[i]
|
||
if t <= key[1] then
|
||
local prev = track[i - 1]
|
||
local span = key[1] - prev[1]
|
||
if span <= 0 then return key[2] end
|
||
return prev[2] + (key[2] - prev[2]) * (t - prev[1]) / span
|
||
end
|
||
end
|
||
return track[last][2]
|
||
end
|
||
|
||
-- Place/size/fade the card for the current clock. The card LANDS centred on its button and
|
||
-- STARTS a fall's height above it (and a drift's width to the left), so the icon reads as
|
||
-- floating clear above the bar and then dropping into the bag — the model's own relative
|
||
-- motion, anchored to the button rather than to the ref's unresolvable model origin.
|
||
function BenillaItemPushAnim_Paint(anim)
|
||
local t = anim.elapsed
|
||
local drop = BenillaItemPushAnim_Sample(BENILLA_ITEM_PUSH_DROP, t)
|
||
local size = BENILLA_ITEM_PUSH_SIZE * BenillaItemPushAnim_Sample(BENILLA_ITEM_PUSH_SCALE, t)
|
||
anim:SetWidth(size)
|
||
anim:SetHeight(size)
|
||
anim:SetPoint("CENTER", anim:GetParent(), "CENTER",
|
||
BENILLA_ITEM_PUSH_DRIFT * (drop - 1),
|
||
BENILLA_ITEM_PUSH_FALL * (1 - drop))
|
||
anim:SetAlpha(BenillaItemPushAnim_Sample(BENILLA_ITEM_PUSH_ALPHA, t))
|
||
end
|
||
|
||
-- ref ItemAnim_OnLoad (l.68-70): the card listens for ITEM_PUSH and nothing else. It is
|
||
-- authored hidden, so it costs no OnUpdate until a push shows it (events reach hidden
|
||
-- frames; OnUpdate does not — the reference's own split).
|
||
function BenillaItemPushAnim_OnLoad(anim, containerId)
|
||
anim.containerId = containerId
|
||
anim.icon = getglobal(anim:GetName() .. "Icon")
|
||
anim.elapsed = 0
|
||
anim:RegisterEvent("ITEM_PUSH")
|
||
end
|
||
|
||
-- ref ItemAnim_OnEvent (l.72-80): `if this:GetParent():GetID() == arg1`, then
|
||
-- ReplaceIconTexture(arg2) / SetSequence(0) / SetSequenceTime(0,0) / Show. A push into a bag
|
||
-- with no button (a bank bag) matches nothing and animates nowhere, there and here.
|
||
function BenillaItemPushAnim_OnEvent(anim)
|
||
if arg1 ~= anim.containerId then return end
|
||
anim.icon:SetTexture(arg2)
|
||
anim.elapsed = 0
|
||
-- Seat the card above its button rather than at load: the bag bar's own level is set in
|
||
-- the BUTTON's OnLoad (BenillaActionBarArt_SeatAbove), which the loader may run after
|
||
-- this child exists. Re-deriving it per push is one call and can never read it stale.
|
||
anim:SetFrameLevel(anim:GetParent():GetFrameLevel() + 1)
|
||
BenillaItemPushAnim_Paint(anim)
|
||
anim:Show()
|
||
end
|
||
|
||
-- The CLAMP sequence's end is the ref's OnAnimFinished → this:Hide() (l.92-94).
|
||
function BenillaItemPushAnim_OnUpdate(anim, elapsed)
|
||
anim.elapsed = anim.elapsed + (elapsed or 0)
|
||
if anim.elapsed >= BENILLA_ITEM_PUSH_DURATION then
|
||
anim:Hide()
|
||
return
|
||
end
|
||
BenillaItemPushAnim_Paint(anim)
|
||
end
|
||
|
||
-- The bag BAR's five buttons (the backpack toggle + the four equipped-bag slots) — the row
|
||
-- Disable_/Enable_BagButtons greys as a unit. Distinct from UiPanels.xml's BAG_WINDOWS,
|
||
-- which is the five bag *windows* those buttons open.
|
||
BENILLA_BAG_BUTTONS = { "BenillaBagToggle", "BenillaBagBarSlot1", "BenillaBagBarSlot2",
|
||
"BenillaBagBarSlot3", "BenillaBagBarSlot4" }
|
||
|
||
-- Disable_BagButtons / Enable_BagButtons — ref MainMenuBarBagButtons.lua l.102-128, called
|
||
-- by GameMenuFrame's OnShow/OnHide (decision 0674) and by nothing else: while the game menu
|
||
-- holds the screen, the whole bag row greys out. That is the *visible* half of a rule the
|
||
-- panel manager already enforces (ShowUIPanel's native-center gate refuses every window
|
||
-- while the menu is up — UiPanels.xml `CanOpenPanels`); without it the bags would look
|
||
-- clickable and simply do nothing.
|
||
--
|
||
-- Mapping onto benilla's row: the ref's MainMenuBarBackpackButton is BenillaBagToggle and
|
||
-- CharacterBag0..3Slot are BenillaBagBarSlot1..4 — and in BOTH cases the greying goes onto
|
||
-- the button's `$parentIcon` LAYER texture, never onto a state texture. That is the
|
||
-- reference's own structure and it is load-bearing here: a disabled button draws its
|
||
-- DisabledTexture, and with none set it draws no state texture at all
|
||
-- (`ButtonState::region_visible`), so greying a NormalTexture would grey something already
|
||
-- gone. The four slots' UI-Quickslot2 rings ARE state textures and do vanish while
|
||
-- disabled unless the slot states one explicitly — so what you should see is the
|
||
-- ring stay put and the bag icon grey — which is why each slot repeats its ring as
|
||
-- DisabledTexture (see the slot instances below).
|
||
function Disable_BagButtons()
|
||
for _, button in ipairs(BENILLA_BAG_BUTTONS) do
|
||
local b = getglobal(button)
|
||
b:Disable()
|
||
SetDesaturation(b.icon, 1)
|
||
end
|
||
end
|
||
|
||
function Enable_BagButtons()
|
||
for _, button in ipairs(BENILLA_BAG_BUTTONS) do
|
||
local b = getglobal(button)
|
||
b:Enable()
|
||
SetDesaturation(b.icon, nil)
|
||
end
|
||
-- The four slots' own paint decides their restored colour: an item locked on the cursor
|
||
-- wants 0.4 grey, not the flat white SetDesaturation(nil) just left.
|
||
for i = 1, 4 do
|
||
BenillaBagBarSlot_Update(getglobal("BenillaBagBarSlot" .. i))
|
||
end
|
||
end
|
||
]]></Script>
|
||
|
||
<!--
|
||
One bag slot (ref ItemButtonTemplate, scratchpad `ref-ItemButtonTemplate.xml` l.4-45): a 37×37
|
||
button (l.5-7); the icon fills the button (l.10, no size/anchors → owner-sized); the "xN" count
|
||
is NumberFontNormal, right-justified, at BOTTOMRIGHT (-5,2) (l.11-19); the NormalTexture is the
|
||
64×64 UI-Quickslot2 ring centered at (0,-1) (l.31-42); PushedTexture UI-Quickslot-Depress
|
||
(l.43); HighlightTexture ButtonHilight-Square ADD (l.44). Shared by every window (backpack +
|
||
the four equipped bags) — physIndex-driven, see BenillaBagSlot_OnLoad's own comment.
|
||
-->
|
||
<Button name="BenillaBagSlotTemplate" virtual="true">
|
||
<Size><AbsDimension x="37" y="37"/></Size>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="$parentIcon"/>
|
||
</Layer>
|
||
<Layer level="OVERLAY">
|
||
<FontString name="$parentCount" inherits="NumberFontNormal" justifyH="RIGHT">
|
||
<Anchors>
|
||
<Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="-5" y="2"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- The item's use-cooldown sweep (ref ContainerFrame.xml:13 — $parentCooldown
|
||
inherits CooldownFrameTemplate; ours is the native Cooldown widget, same as the
|
||
action buttons'). Driven by BenillaBagSlot_Update / BAG_UPDATE_COOLDOWN via
|
||
GetContainerItemCooldown + CooldownFrame_SetTimer (ActionBar.xml's transcription,
|
||
loaded before this file). -->
|
||
<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 file="Interface\Buttons\UI-Quickslot2">
|
||
<Size><AbsDimension x="64" y="64"/></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"/>
|
||
<Scripts>
|
||
<OnClick>BenillaBagSlot_OnClick(self, arg1)</OnClick>
|
||
<OnEnter>BenillaBagSlot_OnEnter(self)</OnEnter>
|
||
<OnLeave>BenillaBagSlot_OnLeave(self)</OnLeave>
|
||
<OnUpdate>BenillaBagSlot_OnUpdate(self)</OnUpdate>
|
||
<!-- The drag trio (decision 0216 §3): both route to the SAME left-click path the
|
||
reference uses for both gestures (ContainerFrame.xml:40-55) — "LeftButton" hardcoded,
|
||
exactly as the reference calls it, since RegisterForDrag above only ever arms Left —
|
||
`true` (ignoreModifiers) suppresses the shift-split fork, matching the ref's own
|
||
ignoreModifiers contract for a drag/receive. -->
|
||
<OnDragStart>BenillaBagSlot_OnClick(self, "LeftButton", true)</OnDragStart>
|
||
<OnReceiveDrag>BenillaBagSlot_OnClick(self, "LeftButton", true)</OnReceiveDrag>
|
||
</Scripts>
|
||
</Button>
|
||
|
||
<Frame name="BenillaBagFrame" id="0" hidden="true">
|
||
<!-- The real backpack frame: 192 wide (CONTAINER_WIDTH, ContainerFrame.lua l.8,412) × 240 tall
|
||
(l.325), anchored to UIParent BOTTOMRIGHT with CONTAINER_OFFSET_X=0 / CONTAINER_OFFSET_Y=70
|
||
(l.11-12) — the STACK's own anchor once shown (BenillaBagStack_Relayout); this static
|
||
anchor is only the pre-first-show placeholder. -->
|
||
<Size><AbsDimension x="192" y="240"/></Size>
|
||
<Anchors>
|
||
<Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMRIGHT">
|
||
<Offset><AbsDimension x="0" y="70"/></Offset>
|
||
</Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<!-- The bag portrait: 40×40 at the frame TOPLEFT (7,-5) (ref-ContainerFrame.xml l.67-78).
|
||
BACKGROUND (below the ARTWORK background art) so it shows through the background's
|
||
portrait-ring cut-out — the same layering the loot-frame skull uses. Static
|
||
Button-Backpack-Up (the backpack portrait art; the real client's C-side
|
||
SetBagPortaitTexture). -->
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="BenillaBagPortrait" file="Interface\Buttons\Button-Backpack-Up">
|
||
<Size><AbsDimension x="40" y="40"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="7" y="-5"/></Offset></Anchor>
|
||
</Anchors>
|
||
</Texture>
|
||
</Layer>
|
||
<Layer level="ARTWORK">
|
||
<!-- The single backpack background slab (ContainerFrame.lua l.316-318, the id==0
|
||
branch): UI-BackpackBackground, 256×256, full TexCoords (0,1,0,1), anchored TOPRIGHT
|
||
of the frame (ref-ContainerFrame.xml l.86). Wider/taller than the 192×240 frame — it
|
||
overhangs left and down, exactly as the real art does; the painted slot wells assume
|
||
this TOPRIGHT anchoring. The middle/bottom strips are hidden for the backpack
|
||
(l.321-324), so this one texture is the whole window art. -->
|
||
<Texture name="BenillaBagBackground" file="Interface\ContainerFrame\UI-BackpackBackground">
|
||
<Size><AbsDimension x="256" y="256"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPRIGHT" relativePoint="TOPRIGHT"><Offset><AbsDimension x="0" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<TexCoords left="0" right="1" top="0" bottom="1"/>
|
||
</Texture>
|
||
<!-- Title: the bag name, GameFontHighlight, 112×12 at the frame TOPLEFT (47,-10)
|
||
(ref-ContainerFrame.xml l.120-131). BenillaBagWindow_Update keeps it current via
|
||
C_Container.GetBagName(0), which always answers "Backpack" — the authored text is just the
|
||
pre-first-Update placeholder. -->
|
||
<FontString name="BenillaBagFrameName" inherits="GameFontHighlight" text="Backpack">
|
||
<Size><AbsDimension x="112" y="12"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="47" y="-10"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!--
|
||
The item grid (ContainerFrame.lua l.425-444). Authored verbatim from the real backpack
|
||
anchor chain: Item1 at the frame BOTTOMRIGHT (-12,30) (the id==0 first-button offset,
|
||
l.433); each new row (j-1 divisible by NUM_CONTAINER_COLUMNS=4) anchors BOTTOMRIGHT to
|
||
Item(j-4)'s TOPRIGHT (0,4) (l.440), and every other button BOTTOMRIGHT to Item(j-1)'s
|
||
BOTTOMLEFT (-5,0) (l.442). So button 1 is bottom-right and the chain fills up-and-left.
|
||
Slot1 (self, 1) is CHAIN POSITION 1 (physIndex), not the game slot — BenillaBagSlot_Update
|
||
resolves the game slot dynamically (size - physIndex + 1 = 16 - physIndex + 1 for the
|
||
backpack's fixed 16), so slot 1 renders TOP-LEFT and slot 16 BOTTOM-RIGHT, matching the
|
||
ref's own visual order.
|
||
-->
|
||
<Button name="BenillaBagSlot1" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="-12" y="30"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 1)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaBagSlot2" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="BenillaBagSlot1" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 2)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaBagSlot3" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="BenillaBagSlot2" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 3)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaBagSlot4" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="BenillaBagSlot3" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 4)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaBagSlot5" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="BenillaBagSlot1" relativePoint="TOPRIGHT"><Offset><AbsDimension x="0" y="4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 5)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaBagSlot6" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="BenillaBagSlot5" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 6)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaBagSlot7" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="BenillaBagSlot6" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 7)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaBagSlot8" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="BenillaBagSlot7" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 8)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaBagSlot9" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="BenillaBagSlot5" relativePoint="TOPRIGHT"><Offset><AbsDimension x="0" y="4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 9)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaBagSlot10" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="BenillaBagSlot9" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 10)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaBagSlot11" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="BenillaBagSlot10" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 11)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaBagSlot12" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="BenillaBagSlot11" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 12)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaBagSlot13" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="BenillaBagSlot9" relativePoint="TOPRIGHT"><Offset><AbsDimension x="0" y="4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 13)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaBagSlot14" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="BenillaBagSlot13" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 14)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaBagSlot15" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="BenillaBagSlot14" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 15)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaBagSlot16" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="BenillaBagSlot15" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 16)</OnLoad></Scripts>
|
||
</Button>
|
||
|
||
<!-- The money purse (ContainerFrame.lua l.314 shows the MoneyFrame for the backpack; ref
|
||
SmallMoneyFrame anchored TOPRIGHT (-2,-216), ref-ContainerFrame.xml l.135-143). The
|
||
template pads 13px right of the copper coin (its content chains from x=-13 inside
|
||
the frame — same pad as the merchant purse), so the COIN edge the ref frame anchor
|
||
implies is -2-13 = -15. Three position-slots chained right-to-left with the real 4px
|
||
spacing (Coin1 rightmost, copper), filled copper-first and shrunk to content by
|
||
BenillaMoney_Set("BenillaBagMoney", GetMoney()); Coin2/3 chain to its left. -->
|
||
<Frame name="BenillaBagMoneyCoin1">
|
||
<Size><AbsDimension x="13" y="13"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPRIGHT" relativePoint="TOPRIGHT"><Offset><AbsDimension x="-15" y="-216"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="OVERLAY">
|
||
<Texture name="$parentIcon" file="Interface\MoneyFrame\UI-MoneyIcons">
|
||
<Size><AbsDimension x="13" y="13"/></Size>
|
||
<Anchors><Anchor point="RIGHT" relativePoint="RIGHT"/></Anchors>
|
||
<TexCoords left="0.5" right="0.75" top="0" bottom="1"/>
|
||
</Texture>
|
||
<FontString name="$parentNum" inherits="NumberFontNormal" justifyH="RIGHT">
|
||
<Size><AbsDimension x="20" y="13"/></Size>
|
||
<Anchors><Anchor point="RIGHT" relativePoint="RIGHT"><Offset><AbsDimension x="-13" y="0"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
</Frame>
|
||
<Frame name="BenillaBagMoneyCoin2">
|
||
<Size><AbsDimension x="13" y="13"/></Size>
|
||
<Anchors>
|
||
<Anchor point="RIGHT" relativeTo="BenillaBagMoneyCoin1" relativePoint="LEFT"><Offset><AbsDimension x="-4" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="OVERLAY">
|
||
<Texture name="$parentIcon" file="Interface\MoneyFrame\UI-MoneyIcons">
|
||
<Size><AbsDimension x="13" y="13"/></Size>
|
||
<Anchors><Anchor point="RIGHT" relativePoint="RIGHT"/></Anchors>
|
||
<TexCoords left="0.25" right="0.5" top="0" bottom="1"/>
|
||
</Texture>
|
||
<FontString name="$parentNum" inherits="NumberFontNormal" justifyH="RIGHT">
|
||
<Size><AbsDimension x="20" y="13"/></Size>
|
||
<Anchors><Anchor point="RIGHT" relativePoint="RIGHT"><Offset><AbsDimension x="-13" y="0"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
</Frame>
|
||
<Frame name="BenillaBagMoneyCoin3">
|
||
<Size><AbsDimension x="13" y="13"/></Size>
|
||
<Anchors>
|
||
<Anchor point="RIGHT" relativeTo="BenillaBagMoneyCoin2" relativePoint="LEFT"><Offset><AbsDimension x="-4" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="OVERLAY">
|
||
<Texture name="$parentIcon" file="Interface\MoneyFrame\UI-MoneyIcons">
|
||
<Size><AbsDimension x="13" y="13"/></Size>
|
||
<Anchors><Anchor point="RIGHT" relativePoint="RIGHT"/></Anchors>
|
||
<TexCoords left="0" right="0.25" top="0" bottom="1"/>
|
||
</Texture>
|
||
<FontString name="$parentNum" inherits="NumberFontNormal" justifyH="RIGHT">
|
||
<Size><AbsDimension x="20" y="13"/></Size>
|
||
<Anchors><Anchor point="RIGHT" relativePoint="RIGHT"><Offset><AbsDimension x="-13" y="0"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
</Frame>
|
||
|
||
<!-- Close: the real ContainerFrame close button position, TOPRIGHT (0,-1)
|
||
(ref-ContainerFrame.xml l.217-224), on the minimize-button art UIPanelCloseButton
|
||
itself uses (ref-UIPanelTemplates.xml l.100-102 — the same art merchant/loot draw; our
|
||
engine ships no UIPanelCloseButton template, so we draw it, matching the house style).
|
||
A close hides the window (the standalone-addon equivalent of ToggleBag). -->
|
||
<Button name="BenillaBagCloseButton">
|
||
<Size><AbsDimension x="32" y="32"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPRIGHT" relativePoint="TOPRIGHT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor>
|
||
</Anchors>
|
||
<NormalTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Up"/>
|
||
<PushedTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Down"/>
|
||
<HighlightTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Highlight" alphaMode="ADD"/>
|
||
<Scripts>
|
||
<OnClick>getglobal("BenillaBagFrame"):Hide()</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
</Frames>
|
||
<Scripts>
|
||
<OnLoad>BenillaBagFrame_OnLoad(self)</OnLoad>
|
||
<OnEvent>BenillaBagFrame_OnEvent(self)</OnEvent>
|
||
<OnShow>BenillaBagFrame_OnShow()</OnShow>
|
||
<OnHide>BenillaBagFrame_OnHide()</OnHide>
|
||
</Scripts>
|
||
</Frame>
|
||
|
||
<!--
|
||
The generalized equipped-bag window (decision 0216 slice 2): the same portrait + slot template
|
||
as the backpack, but a stitched UI-Bag-Components background that SNUG-FITS the bag's row count
|
||
(BenillaBagWindow_FitBackground) rather than the backpack's fixed slab. The authored 260 height
|
||
is only a placeholder — FitBackground sets the live height on every repaint (before Show). No
|
||
money frame; first slot at the ref's non-backpack offset (-12,9 vs the backpack's -12,30 —
|
||
ContainerFrame.lua l.435 vs l.433, the id==0 fork). Carries NO <Scripts> block — each of the
|
||
four concrete windows below supplies its own (so the template/instance merge never has to
|
||
reconcile two OnLoad bodies; see `framexml.rs::merge`'s doc — a template with no Scripts child
|
||
can't collide with the instance's).
|
||
-->
|
||
<Frame name="BenillaBagWindowTemplate" virtual="true" hidden="true">
|
||
<Size><AbsDimension x="192" y="260"/></Size>
|
||
<Anchors>
|
||
<Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMRIGHT">
|
||
<Offset><AbsDimension x="0" y="70"/></Offset>
|
||
</Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="$parentPortrait" file="Interface\Buttons\Button-Backpack-Up">
|
||
<Size><AbsDimension x="40" y="40"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="7" y="-5"/></Offset></Anchor>
|
||
</Anchors>
|
||
</Texture>
|
||
</Layer>
|
||
<Layer level="ARTWORK">
|
||
<!-- The snug-fit background, STITCHED from the real client's UI-Bag-Components (256×512;
|
||
ContainerFrame.lua ContainerFrame_GenerateFrame, the id~=0 branch), so an equipped
|
||
bag's window is exactly its row count tall instead of the backpack's fixed 5-row
|
||
slab (decision 0216's flagged divergence, now closed). Three right-anchored 256-wide
|
||
pieces, all sized/tex-coorded per-bag by BenillaBagWindow_FitBackground (below): the
|
||
TOP carries the title bar + portrait ring + the top well row (a full 4-well row, or
|
||
a partial 2-well row for a size%4==2 bag — the reference's isPlusTwoBag fork); the
|
||
MIDDLE tiles the remaining full well rows (41px each, the button row stride, from
|
||
texture v 0.353515625 = the grid's top edge); the BOTTOM is the frame's bottom rim.
|
||
Authored values are a 2-row full-bag placeholder — every Show repaints through
|
||
FitBackground first, so the live geometry always wins. -->
|
||
<Texture name="$parentBgTop" file="Interface\ContainerFrame\UI-Bag-Components">
|
||
<Size><AbsDimension x="256" y="94"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPRIGHT" relativePoint="TOPRIGHT"><Offset><AbsDimension x="0" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<TexCoords left="0" right="1" top="0.00390625" bottom="0.18359375"/>
|
||
</Texture>
|
||
<Texture name="$parentBgMiddle" file="Interface\ContainerFrame\UI-Bag-Components">
|
||
<Size><AbsDimension x="256" y="32"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentBgTop" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<TexCoords left="0" right="1" top="0.353515625" bottom="0.416015625"/>
|
||
</Texture>
|
||
<Texture name="$parentBgBottom" file="Interface\ContainerFrame\UI-Bag-Components">
|
||
<Size><AbsDimension x="256" y="10"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentBgMiddle" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<TexCoords left="0" right="1" top="0.330078125" bottom="0.349609375"/>
|
||
</Texture>
|
||
<FontString name="$parentName" inherits="GameFontHighlight">
|
||
<Size><AbsDimension x="112" y="12"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="47" y="-10"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- 20 slots, 5 rows × 4 columns, chain-anchored exactly like the backpack's own 16 (see
|
||
that block's comment) but from the non-backpack first-button offset (-12,9). -->
|
||
<!-- First slot at (-12, 9) — the reference's id~=0 first-button offset (the backpack's is
|
||
-12,30). The grid then seats itself on the baked wells for free, because the background
|
||
is built bottom-up from the same 41px stride: the rim is 10px, the button's bottom edge
|
||
sits 9px up, and every row above is +41. -->
|
||
<Button name="$parentSlot1" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="-12" y="9"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 1)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot2" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot1" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 2)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot3" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot2" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 3)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot4" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot3" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 4)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot5" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot1" relativePoint="TOPRIGHT"><Offset><AbsDimension x="0" y="4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 5)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot6" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot5" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 6)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot7" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot6" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 7)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot8" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot7" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 8)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot9" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot5" relativePoint="TOPRIGHT"><Offset><AbsDimension x="0" y="4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 9)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot10" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot9" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 10)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot11" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot10" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 11)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot12" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot11" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 12)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot13" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot9" relativePoint="TOPRIGHT"><Offset><AbsDimension x="0" y="4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 13)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot14" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot13" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 14)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot15" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot14" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 15)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot16" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot15" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 16)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot17" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot13" relativePoint="TOPRIGHT"><Offset><AbsDimension x="0" y="4"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 17)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot18" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot17" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 18)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot19" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot18" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 19)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSlot20" inherits="BenillaBagSlotTemplate">
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativeTo="$parentSlot19" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaBagSlot_OnLoad(self, 20)</OnLoad></Scripts>
|
||
</Button>
|
||
|
||
<!-- Close: same art/position as the backpack's, but resolves ITS OWN parent via `this`
|
||
(the button, legacy global) rather than a hardcoded name — one body, five windows. -->
|
||
<Button name="$parentCloseButton">
|
||
<Size><AbsDimension x="32" y="32"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPRIGHT" relativePoint="TOPRIGHT"><Offset><AbsDimension x="0" y="-1"/></Offset></Anchor>
|
||
</Anchors>
|
||
<NormalTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Up"/>
|
||
<PushedTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Down"/>
|
||
<HighlightTexture file="Interface\Buttons\UI-Panel-MinimizeButton-Highlight" alphaMode="ADD"/>
|
||
<Scripts>
|
||
<OnClick>this:GetParent():Hide()</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
</Frames>
|
||
</Frame>
|
||
|
||
<!-- The four equipped-bag windows: id=1..4 (SetID applied before any child's OnLoad — the
|
||
loader's bottom-up materialize order), each supplying its OWN Scripts block (the template
|
||
above carries none, so there is nothing to merge/collide with). -->
|
||
<Frame name="BenillaBagFrame1" id="1" inherits="BenillaBagWindowTemplate">
|
||
<Scripts>
|
||
<OnLoad>BenillaBagFrame_OnLoad(self)</OnLoad>
|
||
<OnEvent>BenillaBagFrame_OnEvent(self)</OnEvent>
|
||
<OnShow>BenillaBagFrame_OnShow()</OnShow>
|
||
<OnHide>BenillaBagFrame_OnHide()</OnHide>
|
||
</Scripts>
|
||
</Frame>
|
||
<Frame name="BenillaBagFrame2" id="2" inherits="BenillaBagWindowTemplate">
|
||
<Scripts>
|
||
<OnLoad>BenillaBagFrame_OnLoad(self)</OnLoad>
|
||
<OnEvent>BenillaBagFrame_OnEvent(self)</OnEvent>
|
||
<OnShow>BenillaBagFrame_OnShow()</OnShow>
|
||
<OnHide>BenillaBagFrame_OnHide()</OnHide>
|
||
</Scripts>
|
||
</Frame>
|
||
<Frame name="BenillaBagFrame3" id="3" inherits="BenillaBagWindowTemplate">
|
||
<Scripts>
|
||
<OnLoad>BenillaBagFrame_OnLoad(self)</OnLoad>
|
||
<OnEvent>BenillaBagFrame_OnEvent(self)</OnEvent>
|
||
<OnShow>BenillaBagFrame_OnShow()</OnShow>
|
||
<OnHide>BenillaBagFrame_OnHide()</OnHide>
|
||
</Scripts>
|
||
</Frame>
|
||
<Frame name="BenillaBagFrame4" id="4" inherits="BenillaBagWindowTemplate">
|
||
<Scripts>
|
||
<OnLoad>BenillaBagFrame_OnLoad(self)</OnLoad>
|
||
<OnEvent>BenillaBagFrame_OnEvent(self)</OnEvent>
|
||
<OnShow>BenillaBagFrame_OnShow()</OnShow>
|
||
<OnHide>BenillaBagFrame_OnHide()</OnHide>
|
||
</Scripts>
|
||
</Frame>
|
||
|
||
<!--
|
||
The keyring window (decision 0765) — id = KEYRING_CONTAINER. Structurally just a seventh
|
||
container window on the SAME template as the four equipped bags and the six bank popouts;
|
||
everything that makes it a keyring (the "-Keyring" plate, the KeyRing-Bag-Icon portrait, the
|
||
KEYRING title, the jingling open/close pair) is the id-keyed fork inside the shared handlers,
|
||
exactly as ContainerFrame.lua does it. Its 20 template buttons cover the keyring's 16-slot
|
||
ceiling; the level-gated remainder hides through the ordinary physIndex-past-size branch.
|
||
|
||
It is deliberately NOT in BENILLA_BAG_WINDOWS: the keyring is not one of "your bags", so 'B'
|
||
/ the backpack toggle / a vendor's auto-open never touch it, which is the reference's own
|
||
arrangement (OpenAllBags counts it out, and CloseAllBags is id-driven over 1..4). ESC still
|
||
closes it — UiPanels.xml's CloseAllWindows hides every open container, the ref's own loop.
|
||
-->
|
||
<Frame name="BenillaKeyRingFrame" id="-2" inherits="BenillaBagWindowTemplate">
|
||
<Scripts>
|
||
<OnLoad>BenillaBagFrame_OnLoad(self)</OnLoad>
|
||
<OnEvent>BenillaBagFrame_OnEvent(self)</OnEvent>
|
||
<OnShow>BenillaBagFrame_OnShow()</OnShow>
|
||
<OnHide>BenillaBagFrame_OnHide()</OnHide>
|
||
</Scripts>
|
||
</Frame>
|
||
|
||
<!--
|
||
The backpack toggle, RELOCATED onto the main action bar's right side so the bar reads whole
|
||
(the real client's MainMenuBarBackpackButton, ref-MainMenuBarBagButtons.xml l.54-64): a 37x37
|
||
button parented/anchored to the bar art frame at BOTTOMRIGHT (-6,2). Its behavior (toggle the
|
||
backpack window) is unchanged; only its seat moved from the free-floating screen corner onto
|
||
the bar. (BenillaActionBarArtFrame is defined in ActionBar.xml, which the loader loads before
|
||
this file; the anchor resolves by name.)
|
||
-->
|
||
<CheckButton name="BenillaBagToggle">
|
||
<Size><AbsDimension x="37" y="37"/></Size>
|
||
<Anchors>
|
||
<Anchor point="BOTTOMRIGHT" relativeTo="BenillaActionBarArtFrame" relativePoint="BOTTOMRIGHT">
|
||
<Offset><AbsDimension x="-6" y="2"/></Offset>
|
||
</Anchor>
|
||
</Anchors>
|
||
<!-- The backpack art is a LAYER texture, not the NormalTexture — the reference's own
|
||
structure (MainMenuBarBackpackButton inherits ItemButtonTemplate and sets
|
||
`MainMenuBarBackpackButtonIconTexture` in its OnLoad; the state textures are the
|
||
template's ring). It matters because `Disable_BagButtons` (decision 0674) disables this
|
||
button while the game menu is up, and a *state* texture with no DisabledTexture beside
|
||
it is not drawn in the disabled state (`ButtonState::region_visible` — the byte rule at
|
||
`SetState 0x779790`), so the backpack icon vanished outright instead of greying
|
||
(director-reported). As a layer it is untouched by button state, exactly like the four
|
||
bag-bar slots' own `$parentIcon`, and the greying is the vertex tint on it. -->
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="$parentIcon" file="Interface\Buttons\Button-Backpack-Up"/>
|
||
</Layer>
|
||
</Layers>
|
||
<!-- The item-push drop card (decision 0887, BenillaItemPushAnim_* above) — the ref's
|
||
$parentItemAnim, one per bag button, container id 0 = the backpack. -->
|
||
<Frames>
|
||
<Frame name="$parentItemAnim" hidden="true">
|
||
<Size><AbsDimension x="36" y="36"/></Size>
|
||
<Anchors><Anchor point="CENTER"/></Anchors>
|
||
<Layers>
|
||
<Layer level="OVERLAY">
|
||
<Texture name="$parentIcon" setAllPoints="true"/>
|
||
</Layer>
|
||
</Layers>
|
||
<Scripts>
|
||
<OnLoad>BenillaItemPushAnim_OnLoad(self, 0)</OnLoad>
|
||
<OnEvent>BenillaItemPushAnim_OnEvent(self)</OnEvent>
|
||
<OnUpdate>BenillaItemPushAnim_OnUpdate(self, arg1)</OnUpdate>
|
||
</Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
<HighlightTexture file="Interface\Buttons\ButtonHilight-Square" alphaMode="ADD"/>
|
||
<!-- The lit ring while the backpack window is open (ref MainMenuBarBackpackButton
|
||
l.104) — a CheckButton like the ref's; OnShow/OnHide of the window drive it. -->
|
||
<CheckedTexture file="Interface\Buttons\CheckButtonHilight" alphaMode="ADD"/>
|
||
<Scripts>
|
||
<!-- Seat the backpack icon above the bar art too (same reason as the bag-bar slots —
|
||
BenillaActionBarArt_SeatAbove's comment). -->
|
||
<OnLoad>
|
||
self.icon = getglobal("BenillaBagToggleIcon")
|
||
if BenillaActionBarArt_SeatAbove then BenillaActionBarArt_SeatAbove(self) end
|
||
</OnLoad>
|
||
<OnClick>BenillaBagToggle_OnClick()</OnClick>
|
||
<OnEnter>BenillaBagToggle_OnEnter(self)</OnEnter>
|
||
<OnLeave>BenillaBagBarButton_OnLeave()</OnLeave>
|
||
</Scripts>
|
||
</CheckButton>
|
||
|
||
<!--
|
||
The bag bar (decision 0216 slice 2, BenillaBagBarSlot_* above): four 36×36 buttons to the
|
||
LEFT of BenillaBagToggle, mirroring the reference CharacterBag0..3Slot row. Bar slot N (1..4)
|
||
sits at chain position N counting away from the backpack button — BenillaBagBarSlot1 (bagId
|
||
1, Bag0Slot) is CLOSEST to the backpack, BenillaBagBarSlot4 (bagId 4, Bag3Slot) FARTHEST —
|
||
the real bar's own left-to-right order. Sized to MATCH the action buttons (36×36 icon in a
|
||
66×66 UI-Quickslot2 ring, 6px chain gap = the 42px stride), so the bag icons fill their slots
|
||
exactly like the spell icons instead of floating undersized (the earlier 30×30 guess).
|
||
-->
|
||
<CheckButton name="BenillaBagBarSlot1">
|
||
<Size><AbsDimension x="36" y="36"/></Size>
|
||
<Anchors>
|
||
<Anchor point="RIGHT" relativeTo="BenillaBagToggle" relativePoint="LEFT"><Offset><AbsDimension x="-6" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers><Layer level="BACKGROUND"><Texture name="$parentIcon"/></Layer></Layers>
|
||
<!-- The item-push drop card (decision 0887, BenillaItemPushAnim_* above) — the ref's
|
||
$parentItemAnim, one per bag button; container id 1. -->
|
||
<Frames>
|
||
<Frame name="$parentItemAnim" hidden="true">
|
||
<Size><AbsDimension x="36" y="36"/></Size>
|
||
<Anchors><Anchor point="CENTER"/></Anchors>
|
||
<Layers>
|
||
<Layer level="OVERLAY">
|
||
<Texture name="$parentIcon" setAllPoints="true"/>
|
||
</Layer>
|
||
</Layers>
|
||
<Scripts>
|
||
<OnLoad>BenillaItemPushAnim_OnLoad(self, 1)</OnLoad>
|
||
<OnEvent>BenillaItemPushAnim_OnEvent(self)</OnEvent>
|
||
<OnUpdate>BenillaItemPushAnim_OnUpdate(self, arg1)</OnUpdate>
|
||
</Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
<NormalTexture file="Interface\Buttons\UI-Quickslot2">
|
||
<Size><AbsDimension x="66" y="66"/></Size>
|
||
<Anchors><Anchor point="CENTER" relativePoint="CENTER"/></Anchors>
|
||
</NormalTexture>
|
||
<!-- The same ring again as the DISABLED art, so the slot keeps its frame while
|
||
Disable_BagButtons has the row greyed under the game menu (decision 0674). A button
|
||
with no DisabledTexture draws NO state texture when disabled
|
||
(`ButtonState::region_visible`) — the ring would blink out of the bar entirely. The
|
||
reference needs no such line because its widget keeps the previously shown texture up
|
||
when the new state's slot is empty (`SetState 0x779790`'s gated hide); ours states it
|
||
instead of relying on that. -->
|
||
<DisabledTexture file="Interface\Buttons\UI-Quickslot2">
|
||
<Size><AbsDimension x="66" y="66"/></Size>
|
||
<Anchors><Anchor point="CENTER" relativePoint="CENTER"/></Anchors>
|
||
</DisabledTexture>
|
||
<HighlightTexture file="Interface\Buttons\ButtonHilight-Square" alphaMode="ADD"/>
|
||
<!-- The lit ring while this bag's window is open (ref BagSlotButtonTemplate l.52). -->
|
||
<CheckedTexture file="Interface\Buttons\CheckButtonHilight" alphaMode="ADD"/>
|
||
<Scripts>
|
||
<OnLoad>BenillaBagBarSlot_OnLoad(self, 1)</OnLoad>
|
||
<OnClick>BenillaBagBarSlot_OnClick(self)</OnClick>
|
||
<OnEvent>BenillaBagBarSlot_OnEvent(self)</OnEvent>
|
||
<OnEnter>BenillaBagBarSlot_OnEnter(self)</OnEnter>
|
||
<OnLeave>BenillaBagBarButton_OnLeave()</OnLeave>
|
||
<!-- The drag trio: OnDragStart picks the equipped bag up, OnReceiveDrag drops a carried
|
||
bag in — both the same PickupInventoryItem transition (empty cursor picks up, a held
|
||
bag places), mirroring the paper-doll/bag-slot drag routing. -->
|
||
<OnDragStart>BenillaBagBarSlot_Place(self)</OnDragStart>
|
||
<OnReceiveDrag>BenillaBagBarSlot_Place(self)</OnReceiveDrag>
|
||
</Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="BenillaBagBarSlot2">
|
||
<Size><AbsDimension x="36" y="36"/></Size>
|
||
<Anchors>
|
||
<Anchor point="RIGHT" relativeTo="BenillaBagBarSlot1" relativePoint="LEFT"><Offset><AbsDimension x="-6" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers><Layer level="BACKGROUND"><Texture name="$parentIcon"/></Layer></Layers>
|
||
<!-- The item-push drop card (decision 0887, BenillaItemPushAnim_* above) — the ref's
|
||
$parentItemAnim, one per bag button; container id 2. -->
|
||
<Frames>
|
||
<Frame name="$parentItemAnim" hidden="true">
|
||
<Size><AbsDimension x="36" y="36"/></Size>
|
||
<Anchors><Anchor point="CENTER"/></Anchors>
|
||
<Layers>
|
||
<Layer level="OVERLAY">
|
||
<Texture name="$parentIcon" setAllPoints="true"/>
|
||
</Layer>
|
||
</Layers>
|
||
<Scripts>
|
||
<OnLoad>BenillaItemPushAnim_OnLoad(self, 2)</OnLoad>
|
||
<OnEvent>BenillaItemPushAnim_OnEvent(self)</OnEvent>
|
||
<OnUpdate>BenillaItemPushAnim_OnUpdate(self, arg1)</OnUpdate>
|
||
</Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
<NormalTexture file="Interface\Buttons\UI-Quickslot2">
|
||
<Size><AbsDimension x="66" y="66"/></Size>
|
||
<Anchors><Anchor point="CENTER" relativePoint="CENTER"/></Anchors>
|
||
</NormalTexture>
|
||
<!-- The same ring again as the DISABLED art, so the slot keeps its frame while
|
||
Disable_BagButtons has the row greyed under the game menu (decision 0674). A button
|
||
with no DisabledTexture draws NO state texture when disabled
|
||
(`ButtonState::region_visible`) — the ring would blink out of the bar entirely. The
|
||
reference needs no such line because its widget keeps the previously shown texture up
|
||
when the new state's slot is empty (`SetState 0x779790`'s gated hide); ours states it
|
||
instead of relying on that. -->
|
||
<DisabledTexture file="Interface\Buttons\UI-Quickslot2">
|
||
<Size><AbsDimension x="66" y="66"/></Size>
|
||
<Anchors><Anchor point="CENTER" relativePoint="CENTER"/></Anchors>
|
||
</DisabledTexture>
|
||
<HighlightTexture file="Interface\Buttons\ButtonHilight-Square" alphaMode="ADD"/>
|
||
<CheckedTexture file="Interface\Buttons\CheckButtonHilight" alphaMode="ADD"/>
|
||
<Scripts>
|
||
<OnLoad>BenillaBagBarSlot_OnLoad(self, 2)</OnLoad>
|
||
<OnClick>BenillaBagBarSlot_OnClick(self)</OnClick>
|
||
<OnEvent>BenillaBagBarSlot_OnEvent(self)</OnEvent>
|
||
<OnEnter>BenillaBagBarSlot_OnEnter(self)</OnEnter>
|
||
<OnLeave>BenillaBagBarButton_OnLeave()</OnLeave>
|
||
<!-- The drag trio: OnDragStart picks the equipped bag up, OnReceiveDrag drops a carried
|
||
bag in — both the same PickupInventoryItem transition (empty cursor picks up, a held
|
||
bag places), mirroring the paper-doll/bag-slot drag routing. -->
|
||
<OnDragStart>BenillaBagBarSlot_Place(self)</OnDragStart>
|
||
<OnReceiveDrag>BenillaBagBarSlot_Place(self)</OnReceiveDrag>
|
||
</Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="BenillaBagBarSlot3">
|
||
<Size><AbsDimension x="36" y="36"/></Size>
|
||
<Anchors>
|
||
<Anchor point="RIGHT" relativeTo="BenillaBagBarSlot2" relativePoint="LEFT"><Offset><AbsDimension x="-6" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers><Layer level="BACKGROUND"><Texture name="$parentIcon"/></Layer></Layers>
|
||
<!-- The item-push drop card (decision 0887, BenillaItemPushAnim_* above) — the ref's
|
||
$parentItemAnim, one per bag button; container id 3. -->
|
||
<Frames>
|
||
<Frame name="$parentItemAnim" hidden="true">
|
||
<Size><AbsDimension x="36" y="36"/></Size>
|
||
<Anchors><Anchor point="CENTER"/></Anchors>
|
||
<Layers>
|
||
<Layer level="OVERLAY">
|
||
<Texture name="$parentIcon" setAllPoints="true"/>
|
||
</Layer>
|
||
</Layers>
|
||
<Scripts>
|
||
<OnLoad>BenillaItemPushAnim_OnLoad(self, 3)</OnLoad>
|
||
<OnEvent>BenillaItemPushAnim_OnEvent(self)</OnEvent>
|
||
<OnUpdate>BenillaItemPushAnim_OnUpdate(self, arg1)</OnUpdate>
|
||
</Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
<NormalTexture file="Interface\Buttons\UI-Quickslot2">
|
||
<Size><AbsDimension x="66" y="66"/></Size>
|
||
<Anchors><Anchor point="CENTER" relativePoint="CENTER"/></Anchors>
|
||
</NormalTexture>
|
||
<!-- The same ring again as the DISABLED art, so the slot keeps its frame while
|
||
Disable_BagButtons has the row greyed under the game menu (decision 0674). A button
|
||
with no DisabledTexture draws NO state texture when disabled
|
||
(`ButtonState::region_visible`) — the ring would blink out of the bar entirely. The
|
||
reference needs no such line because its widget keeps the previously shown texture up
|
||
when the new state's slot is empty (`SetState 0x779790`'s gated hide); ours states it
|
||
instead of relying on that. -->
|
||
<DisabledTexture file="Interface\Buttons\UI-Quickslot2">
|
||
<Size><AbsDimension x="66" y="66"/></Size>
|
||
<Anchors><Anchor point="CENTER" relativePoint="CENTER"/></Anchors>
|
||
</DisabledTexture>
|
||
<HighlightTexture file="Interface\Buttons\ButtonHilight-Square" alphaMode="ADD"/>
|
||
<CheckedTexture file="Interface\Buttons\CheckButtonHilight" alphaMode="ADD"/>
|
||
<Scripts>
|
||
<OnLoad>BenillaBagBarSlot_OnLoad(self, 3)</OnLoad>
|
||
<OnClick>BenillaBagBarSlot_OnClick(self)</OnClick>
|
||
<OnEvent>BenillaBagBarSlot_OnEvent(self)</OnEvent>
|
||
<OnEnter>BenillaBagBarSlot_OnEnter(self)</OnEnter>
|
||
<OnLeave>BenillaBagBarButton_OnLeave()</OnLeave>
|
||
<!-- The drag trio: OnDragStart picks the equipped bag up, OnReceiveDrag drops a carried
|
||
bag in — both the same PickupInventoryItem transition (empty cursor picks up, a held
|
||
bag places), mirroring the paper-doll/bag-slot drag routing. -->
|
||
<OnDragStart>BenillaBagBarSlot_Place(self)</OnDragStart>
|
||
<OnReceiveDrag>BenillaBagBarSlot_Place(self)</OnReceiveDrag>
|
||
</Scripts>
|
||
</CheckButton>
|
||
<CheckButton name="BenillaBagBarSlot4">
|
||
<Size><AbsDimension x="36" y="36"/></Size>
|
||
<Anchors>
|
||
<Anchor point="RIGHT" relativeTo="BenillaBagBarSlot3" relativePoint="LEFT"><Offset><AbsDimension x="-6" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers><Layer level="BACKGROUND"><Texture name="$parentIcon"/></Layer></Layers>
|
||
<!-- The item-push drop card (decision 0887, BenillaItemPushAnim_* above) — the ref's
|
||
$parentItemAnim, one per bag button; container id 4. -->
|
||
<Frames>
|
||
<Frame name="$parentItemAnim" hidden="true">
|
||
<Size><AbsDimension x="36" y="36"/></Size>
|
||
<Anchors><Anchor point="CENTER"/></Anchors>
|
||
<Layers>
|
||
<Layer level="OVERLAY">
|
||
<Texture name="$parentIcon" setAllPoints="true"/>
|
||
</Layer>
|
||
</Layers>
|
||
<Scripts>
|
||
<OnLoad>BenillaItemPushAnim_OnLoad(self, 4)</OnLoad>
|
||
<OnEvent>BenillaItemPushAnim_OnEvent(self)</OnEvent>
|
||
<OnUpdate>BenillaItemPushAnim_OnUpdate(self, arg1)</OnUpdate>
|
||
</Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
<NormalTexture file="Interface\Buttons\UI-Quickslot2">
|
||
<Size><AbsDimension x="66" y="66"/></Size>
|
||
<Anchors><Anchor point="CENTER" relativePoint="CENTER"/></Anchors>
|
||
</NormalTexture>
|
||
<!-- The same ring again as the DISABLED art, so the slot keeps its frame while
|
||
Disable_BagButtons has the row greyed under the game menu (decision 0674). A button
|
||
with no DisabledTexture draws NO state texture when disabled
|
||
(`ButtonState::region_visible`) — the ring would blink out of the bar entirely. The
|
||
reference needs no such line because its widget keeps the previously shown texture up
|
||
when the new state's slot is empty (`SetState 0x779790`'s gated hide); ours states it
|
||
instead of relying on that. -->
|
||
<DisabledTexture file="Interface\Buttons\UI-Quickslot2">
|
||
<Size><AbsDimension x="66" y="66"/></Size>
|
||
<Anchors><Anchor point="CENTER" relativePoint="CENTER"/></Anchors>
|
||
</DisabledTexture>
|
||
<HighlightTexture file="Interface\Buttons\ButtonHilight-Square" alphaMode="ADD"/>
|
||
<CheckedTexture file="Interface\Buttons\CheckButtonHilight" alphaMode="ADD"/>
|
||
<Scripts>
|
||
<OnLoad>BenillaBagBarSlot_OnLoad(self, 4)</OnLoad>
|
||
<OnClick>BenillaBagBarSlot_OnClick(self)</OnClick>
|
||
<OnEvent>BenillaBagBarSlot_OnEvent(self)</OnEvent>
|
||
<OnEnter>BenillaBagBarSlot_OnEnter(self)</OnEnter>
|
||
<OnLeave>BenillaBagBarButton_OnLeave()</OnLeave>
|
||
<!-- The drag trio: OnDragStart picks the equipped bag up, OnReceiveDrag drops a carried
|
||
bag in — both the same PickupInventoryItem transition (empty cursor picks up, a held
|
||
bag places), mirroring the paper-doll/bag-slot drag routing. -->
|
||
<OnDragStart>BenillaBagBarSlot_Place(self)</OnDragStart>
|
||
<OnReceiveDrag>BenillaBagBarSlot_Place(self)</OnReceiveDrag>
|
||
</Scripts>
|
||
</CheckButton>
|
||
|
||
<!--
|
||
The keyring button (decision 0765) — ref KeyRingButton, MainMenuBarBagButtons.xml l.142-199.
|
||
Sits at the FAR left of the bag row, past BenillaBagBarSlot4 (the ref's CharacterBag3Slot),
|
||
and is authored HIDDEN: nothing reveals it but BenillaMainMenuBar_UpdateKeyRing, and only
|
||
while HasKey() — the point being that a character with no key has no keyring at all, and the
|
||
bar's plate has no socket for one.
|
||
|
||
18x39 and the TexCoords are the ref's exactly, and they are not arbitrary: the three state
|
||
atlases are 32x64 holding one 18x39 button, so 18/32 = 0.5625 and 39/64 = 0.609375 crop it
|
||
1:1. The chain gap is OUR row's -6 rather than the ref's -5, so the button seats evenly
|
||
against the 36px slots this bar scaled its own row to.
|
||
|
||
Unlike the five bag buttons it is NOT in BENILLA_BAG_BUTTONS: its art is a state texture, not
|
||
an $parentIcon layer, so Disable_BagButtons' SetDesaturation(b.icon) has nothing to grey —
|
||
and the ref leaves it out of its own Disable_BagButtons for the same reason.
|
||
-->
|
||
<CheckButton name="BenillaKeyRingButton" hidden="true">
|
||
<Size><AbsDimension x="18" y="39"/></Size>
|
||
<Anchors>
|
||
<Anchor point="RIGHT" relativeTo="BenillaBagBarSlot4" relativePoint="LEFT"><Offset><AbsDimension x="-6" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<!-- The item-push drop card (decision 0887, BenillaItemPushAnim_* above) — the ref's
|
||
$parentItemAnim, one per bag button; container id -2 (KEYRING_CONTAINER). The ref gives
|
||
the keyring one too (MainMenuBarBagButtons.xml l.152-160), and the byte selector really
|
||
does reach it: a push landing in player-array slots 81..112 resolves to -2, not 0. -->
|
||
<Frames>
|
||
<Frame name="$parentItemAnim" hidden="true">
|
||
<Size><AbsDimension x="36" y="36"/></Size>
|
||
<Anchors><Anchor point="CENTER"/></Anchors>
|
||
<Layers>
|
||
<Layer level="OVERLAY">
|
||
<Texture name="$parentIcon" setAllPoints="true"/>
|
||
</Layer>
|
||
</Layers>
|
||
<Scripts>
|
||
<OnLoad>BenillaItemPushAnim_OnLoad(self, -2)</OnLoad>
|
||
<OnEvent>BenillaItemPushAnim_OnEvent(self)</OnEvent>
|
||
<OnUpdate>BenillaItemPushAnim_OnUpdate(self, arg1)</OnUpdate>
|
||
</Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
<NormalTexture file="Interface\Buttons\UI-Button-KeyRing">
|
||
<TexCoords left="0" right="0.5625" top="0" bottom="0.609375"/>
|
||
</NormalTexture>
|
||
<PushedTexture file="Interface\Buttons\UI-Button-KeyRing-Down">
|
||
<TexCoords left="0" right="0.5625" top="0" bottom="0.609375"/>
|
||
</PushedTexture>
|
||
<HighlightTexture file="Interface\Buttons\UI-Button-KeyRing-Highlight" alphaMode="ADD">
|
||
<TexCoords left="0" right="0.5625" top="0" bottom="0.609375"/>
|
||
</HighlightTexture>
|
||
<!-- The lit ring while the keyring window is open — the bag row's own convention
|
||
(the ref drives the same state through UpdateMicroButtons' SetButtonState). -->
|
||
<CheckedTexture file="Interface\Buttons\CheckButtonHilight" alphaMode="ADD"/>
|
||
<Scripts>
|
||
<OnLoad>BenillaKeyRingButton_OnLoad(self)</OnLoad>
|
||
<OnEvent>BenillaKeyRingButton_OnEvent()</OnEvent>
|
||
<OnClick>BenillaKeyRingButton_OnClick(self)</OnClick>
|
||
<OnEnter>BenillaKeyRingButton_OnEnter(self)</OnEnter>
|
||
<OnLeave>BenillaBagBarButton_OnLeave()</OnLeave>
|
||
<!-- A key dragged onto the button files itself, the ref's own OnReceiveDrag (l.174-178). -->
|
||
<OnReceiveDrag>PutKeyInKeyRing()</OnReceiveDrag>
|
||
</Scripts>
|
||
</CheckButton>
|
||
</Ui>
|