Files
benilla-octo/crates/benilla-app/assets/ui/ContainerFrameAdapters.xml
T
SamandClaude Fable 5.1 eadacac998 a hundred stale claims retire, and text= was never a divergence
- a comment that justifies code by an engine difference is a claim with an expiry date, and the tree had ~96 expired ones across `assets/ui`, `ui_script/` and `benilla-ui` — a hygiene pass, no behaviour change: dangling `Benilla*` names with zero definitions (`BenillaMoney_*` at thirteen sites after 1937/1962 converged the coin cluster onto the stock `SmallMoneyFrameTemplate`; `BenillaGossipRow_Resize`, `BenillaErrorsFrame_AddMessage`, the digit feed 1285 deleted, `BenillaMerchantItem_OnClick` and three more), "the shipped `assets/ui/<X>.xml`" for thirty-odd files the directory no longer holds — it holds nine — each site now naming the chain file that actually loads, `UiPanels.xml` in the present tense after 1988 took the panel manager and the dialog engine stock, and expired self-deprecation: SimpleHTML "a widget kind we do not have" (1337 built it), "benilla has no console" (1948 bound `ConsoleExec`), `Model`'s "seven verbs not published yet" and "`ClearFog` is a guess" (all 23 are published, the carve sits 500 lines below, `UNBUILT` has been `[&str; 0]` since 2027), `frame_flag_gate`'s doc describing four groups of accepted mouse divergences over a `KNOWN` list that is empty (the empty array and its enforcement stay), five comments saying key delivery is not gated on `keyboard_enabled` where `script::keyboard`'s walk filters on exactly that field (1319), `SetRaidTarget` called a verb this house lacks beside an assert that its intent IS queued (1820), two questlog tests deferring to a screenshot for `GetPoint`/`IsVisible` the regions already answer, `benilla.toc`'s "trade still needs four engine verbs" (all four bound, 1966) and its ping `Model`s "this engine draws no pixels for" (2013 renders `MinimapPing.mdx` itself), and `rig_anim`'s `set_paused` naming a booth caller it does not have; and the code the prose was propping up goes with it: `GameMenuFrame.xml`'s six `<OnLoad>` label setters, because `text=` on a `<Button>` is a global-string lookup at the loader's attribute step (0995, built 61 seconds before the file was written) — the buttons carry `text="LOGOUT"`/`"EXIT_GAME"`/`"MACROS"`/`"RETURN_TO_GAME"`/`"MAIN_MENU"` as the reference's own do; `ScriptLogFrame`'s five authored close-button lines, now `inherits="UIPanelCloseButton"` off the chain's `UIPanelTemplates.xml` seated 757 lines above it (1846); and the editbox's 22-line "gap" doc claiming only the self-acquire `autoFocus` path is built and its `false` default unverified — path 1 is 1686's `visibility_focus`, and the default is `true`, byte-read off `flags = 1` at `0x779a29`/`0x779a2e`, so the test named `autofocus_does_not_focus_on_show…` is renamed for what it actually pins (2044)
- the `text=` divergence never existed: `resolve_text`'s doc had claimed since 0068 that falling back to the raw attribute on a GlobalStrings miss was "one deliberate divergence" from a reference that draws the empty string, and read at the byte it is the reference's own behaviour — `FrameScript_GetText 0x703bf0` does return a pre-seeded empty string (`0x882748`) when the global is not a string, but that return never reaches a label, because all three `text=` readers image-wide test it and substitute the raw attribute: `Button::LoadXML` at `0x778c07` (`0x778c31 mov eax,esi`), `CSimpleFontString::LoadXML` at `0x771006` byte-identically, and `0x7292a6`, which pushes `edi` on the empty arm; so the loader changes nothing, the two test comments that had called `PetLevelText`'s "Level level race class" placeholder and `CLOSE` our divergence now name the reference's arm (a real 1.12 client draws them too), and what IS ours is the extra warning on a key-shaped miss (0983 → 0991), a strict addition; beside it, `GetEffectiveScale`'s root factor is 1 not because "benilla has no `uiScale` CVar" — 1804 registered one, default 0.9 — but because the dial is applied at the raster seam, `768/uiScale` UI units of virtual-screen height rather than a scale on `UIParent`, so every coordinate the VM hands Lua is already in those units and the reference's `GetCursorPosition()/GetEffectiveScale()` transcriptions convert correctly with a root of 1 (2044)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-06 19:39:30 +07:00

164 lines
9.8 KiB
XML

<!--
OUR adapters over the reference's own `Interface\FrameXML\ContainerFrame.xml`/`.lua`.
**This client does not transcribe those files — it EXECUTES them, off the player's own patch
chain** (decision 1751; `ui_script::reference_ui` carries the rule, and `benilla.toc` carries
the position). The bag windows on screen ARE `ContainerFrame1..12`. What is in THIS file is
only benilla's, and only where a reference body reaches for something this client genuinely
does not have.
The rule, restated in one line so it can be applied without re-reading the module: the sourced
file's globals stand unmodified; ours, loading after, win where both define a name; and where a
reference body needs a benilla answer, it is WRAPPED here — never silently stubbed.
TWO THINGS THIS FILE USED TO DO AND NO LONGER DOES, both retired by 1751's swap:
· It declared `ContainerFrameItemButtonTemplate`, transcribed from ContainerFrame.xml, because
the Lua could be sourced and the XML could not. The XML is sourced now, so the reference's
own declaration is the live one and the copy is deleted — the whole point of the migration.
· It defined `updateContainerFrameAnchors()` as a deliberate no-op, because the reference's
body walks twelve `ContainerFrame` windows this client did not build. It builds them, so the
reference's own body is correct here and the stub is deleted. Five corpus addons (Bongos,
Bongos_ActionBar, the CT_BarMod family) hook that global and call through; they now reach the
real thing.
── The adapters, and why neither is a stub ──────────────────────────────────────────────────
`ContainerFrameItemButton_OnEnter` opens with a keyring fork (ref l.615-620):
if this:GetParent():GetID() == KEYRING_CONTAINER then
GameTooltip:SetInventoryItem("player", KeyRingButtonIDToInvSlotID(this:GetID()))
CursorUpdate()
return
end
That fork exists because the REAL client's keyring items are inventory slots, not container
slots, so it has to detour out of the container API to describe one. benilla's keyring is an
ordinary container (id -2, decision 0765): its slots come through `GetContainerItemInfo` and
`GameTooltip:SetBagItem` like every other bag's — which is exactly why the reference's keyring
WINDOW, its verbs and its sounds all take our keyring unchanged, and why this one line is the
only thing in that file the swap did not simply inherit. The detour is not merely unavailable
here (`KeyRingButtonIDToInvSlotID` is not a binding here) — it is *wrong* here, and supplying
the verb would buy an empty tooltip, because our keyring items were never fed into the
inventory-slot space it reads.
So the wrapper below answers the keyring case the way benilla answers every other bag, and
hands EVERY other slot straight to the reference's own body. The path the player is actually
on — hovering an ordinary bag slot — runs the real client's code, unedited.
── Named, not hidden: what still does not work through the sourced files ────────────────────
· `REPAIR_COST` is read by the reference's repair-mode arm. It is a `GlobalStrings.lua` key and
this client sources that file too, so it resolves at runtime — and the arm is unreachable
today regardless, since `GameTooltip:SetBagItem`'s repairCost is an INTERIM 0.
· `NO_EMPTY_KEYRING_SLOTS` is read by the reference's `PutKeyInKeyRing` when the ring is full,
and no such GlobalString exists — 1.12 ships only `NO_EMPTY_KEYRING_SLOTS_ERROR`. That is a
REFERENCE BUG, and this client used to un-quirk it. It does not any more: the reference's own
file runs, so a full keyring prints the reference's own empty error line. Faithful, and
deliberately so (1751: a divergence becomes faithful or becomes a record, never silent).
-->
<Ui xmlns="http://www.blizzard.com/wow/ui/">
<Script><![CDATA[
-- The reference's own body, captured before we shadow the name. Nil on a machine with no
-- client data (nothing was sourced) — which must be LOUD at the call, not a quiet no-op:
-- a bag hover that silently does nothing is precisely the failure mode that let Bagnon
-- ship "working" through four green survey columns.
local refItemButtonOnEnter = ContainerFrameItemButton_OnEnter
function ContainerFrameItemButton_OnEnter(button)
if not button then
button = this
end
if not button then return end
-- benilla's keyring is a CONTAINER (0765), so the reference's inventory-slot detour is
-- both unavailable and wrong here; this is the same pair of calls its general path
-- makes for every other bag, which is all a keyring slot ever needed.
if button:GetParent():GetID() == KEYRING_CONTAINER then
if (button:GetRight() or 0) >= (GetScreenWidth() / 2) then
GameTooltip:SetOwner(button, "ANCHOR_LEFT")
else
GameTooltip:SetOwner(button, "ANCHOR_RIGHT")
end
GameTooltip:SetBagItem(KEYRING_CONTAINER, button:GetID())
ResetCursor()
return
end
if not refItemButtonOnEnter then
message("benilla: Interface\\FrameXML\\ContainerFrame.lua was not sourced from the "
.. "game data, so bag-slot tooltips cannot work. Check the client data path.")
return
end
refItemButtonOnEnter(button)
end
-- ══ The three bag verbs benilla answers differently (decisions 0561 + 1751) ═════════
--
-- `CloseAllBags`, `OpenBackpack` and `CloseBackpack` all exist in the sourced
-- `ContainerFrame.lua` too, and benilla's differ for one reason, not three: **0561, the
-- director's call that a window which opens your bags opens EVERY equipped bag**, not just
-- the backpack. The vendor/bank/mail/trade windows call `OpenBackpack` from their OnShow so
-- your bags come up with them and you can sell or deposit from one; the reference's own
-- body touches bag 0 alone. `CloseBackpack` is its inverse and has to match it, and
-- `CloseAllBags` is the same family's unconditional form.
--
-- **The `Benilla*` names, and the publish under them, are load ORDER** (1751). Order
-- decides every collision and the manifest is the order: this file loads after the
-- reference's `ContainerFrame.xml`, so the three publishes at the foot are the ones that
-- stand. The bodies lived in our UIParent.lua counterpart until 1988 retired it — a
-- harness with no bag stack now meets the loader's stand-ins for the three names
-- (`test_ui::UIPARENT_STAND_INS`), not a nil.
--
-- What CHANGED with the swap is only the plumbing: these used to walk five benilla windows
-- by name and stash `wasOpen` on each frame. The windows are the reference's recycled
-- `ContainerFrame1..12` now — frame N is a different bag every time it opens — so the
-- was-open memory is keyed by BAG ID, and every open and close goes through the
-- reference's own `OpenBag`/`CloseBag`/`IsBagOpen` rather than a raw Show/Hide. That buys
-- the reference's own guards for free (OpenBag's CanOpenPanels + NotWhileDeadError,
-- ToggleBag's `size > 0`) and means an addon replacing those verbs is honoured here too.
BENILLA_BAG_WAS_OPEN = {}
-- The UNCONDITIONAL close, called by ShowUIPanel's native-center branch above: a centre
-- frame takes the whole screen, so nothing is being "restored afterwards" the way a vendor
-- window restores the bags it opened, and the was-open memory is deliberately ignored.
-- Range 0..NUM_CONTAINER_FRAMES rather than the old five names — the reference's own
-- CloseAllBags covers the bank bags too (l.702-707), and now so does this.
function BenillaCloseAllBags()
for bagId = 0, (NUM_CONTAINER_FRAMES or -1) do
CloseBag(bagId)
end
end
-- OpenBackpack — 0561's all-bags form. A bag already open is REMEMBERED and left alone, so
-- the paired CloseBackpack does not close a window the player opened themselves; that
-- memory is the reference's own `backpackWasOpen`, one entry per bag instead of one flag.
function BenillaOpenBackpack()
for bagId = 0, (NUM_BAG_FRAMES or -1) do
-- The backpack always exists; an equipped-bag window only when a bag is in the
-- slot — `OpenBag` makes the same test itself, but the memory has to agree with it.
if bagId == 0 or GetContainerNumSlots(bagId) > 0 then
if IsBagOpen(bagId) then
BENILLA_BAG_WAS_OPEN[bagId] = 1
else
BENILLA_BAG_WAS_OPEN[bagId] = nil
OpenBag(bagId)
end
end
end
end
function BenillaCloseBackpack()
for bagId = 0, (NUM_BAG_FRAMES or -1) do
if not BENILLA_BAG_WAS_OPEN[bagId] then
CloseBag(bagId)
end
end
end
-- The publish — after the reference's container file, so these are the definitions that
-- stand (the stock `ShowUIPanel` calls `CloseAllBags` and the vendor's OnShow
-- `OpenBackpack`, and they reach 0561's bodies).
OpenBackpack = BenillaOpenBackpack
CloseBackpack = BenillaCloseBackpack
CloseAllBags = BenillaCloseAllBags
]]></Script>
</Ui>