- benilla loads real 1.12 addons from Interface/AddOns — TOC, XML and Lua through one loader, with per-addon saved variables, Bindings.xml and the lifecycle events addons expect - both AddOns screens are in: the character-select list with per-addon enable state, and the ESC menu's in-game list - the API surface is measured, not guessed — a corpus harness runs hundreds of real 1.12 addons and ranks exactly which globals, templates and verbs they demand - the Lua dialect is the client's own, read off the binary — 5.0 semantics with the 1.12 additions, and UI source files are bytes, not UTF-8 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
319 lines
20 KiB
XML
319 lines
20 KiB
XML
<Ui>
|
||
<!--
|
||
The dressing room (decision 1060) — ref `DressUpFrame.xml` / `DressUpFrame.lua`, quoted.
|
||
CTRL-left-click an item anywhere (bags, the paper doll, a chat link, the bank) and it lands
|
||
on your own character here, over the gear you are actually wearing. The window's own
|
||
instruction line says exactly that, in Blizzard's words:
|
||
`DRESSUP_FRAME_INSTRUCTIONS` = "CTRL-Left Click additional items to display them on your
|
||
character" (ref-GlobalStrings.lua:944) — which is also where the modifier is settled: CTRL
|
||
previews, SHIFT posts the link to chat (`ContainerFrame.lua:565-571`).
|
||
|
||
THE MODEL PANE is a booth-texture stand-in, not the ref's live `<DressUpModel>` widget —
|
||
the settled doctrine (0105/0118) and exactly what the character window's own pane does
|
||
(`CharacterFrame.xml`'s header). So the ref's three model METHODS have no widget to live on
|
||
and become the engine globals `BenillaDressUpModel_Dress/TryOn/Close/SetFacing`
|
||
(`benilla-ui/src/script/dressup.rs` has the why); `DressUpItem`/`DressUpItemLink` keep their
|
||
real global names, because every ctrl-click site in the UI calls those.
|
||
|
||
Departures, each named:
|
||
- No drag (the ref is `movable` with StartMoving/StopMovingOrSizing): benilla has no
|
||
user-moved-frame affordance yet — the window sits in the left UIPanel slot, which the ref
|
||
registers it into too (`UIParent.lua:41`, transcribed in UiPanels.xml).
|
||
- `DressUpModel:SetUnit("player")` and `:Dress()` are ONE verb here
|
||
(`BenillaDressUpModel_Dress`): our model is always the player's, so "point it at the
|
||
player" and "put the player's own gear back on it" are the same effect.
|
||
- The ref's `scale="2.0"` on the model widget is a 3D-widget zoom with no meaning for a
|
||
baked pane — the booth frames the body from its own bounds (`framing::body_frame`), the
|
||
same law the paper doll is framed by. The bake is framed at THIS pane's 316×351 aspect,
|
||
not square, or the UI's stretch would leave every character 11% too tall (decision 1069).
|
||
- The pane ANIMATES, as the ref's live widget does — Stand looping (decision 1069; the look
|
||
call 0822 §5 left open, made by the director). Its booth is TRANSPARENT for the same
|
||
reason a widget is: the dark room behind the character is the `DressUpBackground-<Race>`
|
||
art below, and Reset/Close sit on that art *inside* this pane's rect (both anchor sets
|
||
transcribed byte-identically from the ref, which is why the overlap is the ref's too).
|
||
-->
|
||
<Script><![CDATA[
|
||
-- GlobalStrings this window uses (ref-GlobalStrings.lua, cited per line; the
|
||
-- `X = X or "..."` idiom is this codebase's convention — CharacterFrame.xml/InspectFrame.xml).
|
||
DRESSUP_FRAME = DRESSUP_FRAME or "Dressing Room" -- :943
|
||
DRESSUP_FRAME_INSTRUCTIONS = DRESSUP_FRAME_INSTRUCTIONS
|
||
or "CTRL-Left Click additional items to display them on your character" -- :944
|
||
RESET = RESET or "Reset" -- :3340
|
||
CLOSE = CLOSE or "Close" -- :760
|
||
|
||
-- ref DressUpFrame.lua:2-8. The `not IsVisible()` gate is the reference's own state reset:
|
||
-- opening the room fresh re-dresses the model in the player's real gear, and only then
|
||
-- tries the clicked item on. Both halves ride ONE ordered intent queue app-side, so the
|
||
-- reset can never overtake the try-on (dressup.rs's module doc).
|
||
function DressUpItem(item)
|
||
if not DressUpFrame:IsVisible() then
|
||
ShowUIPanel(DressUpFrame)
|
||
BenillaDressUpModel_Dress() -- ref: DressUpModel:SetUnit("player")
|
||
end
|
||
BenillaDressUpModel_TryOn(item) -- ref: DressUpModel:TryOn(item)
|
||
end
|
||
|
||
-- ref DressUpFrame.lua:10-16, verbatim: pull the bare item id out of the `|Hitem:<id>:…`
|
||
-- payload and hand THAT to TryOn. Every ctrl-click site in the UI calls this one function,
|
||
-- which is why it keeps the reference's global name.
|
||
function DressUpItemLink(link)
|
||
if not link then
|
||
return
|
||
end
|
||
local item = gsub(link, ".*item:(%d+).*", "%1", 1)
|
||
DressUpItem(tonumber(item))
|
||
end
|
||
|
||
-- ref DressUpFrame.lua:18-32 including its own "-- HACK!!!" comment: gnomes borrow the
|
||
-- dwarf backdrop and trolls the orc one (there is no Gnome/Troll art), and an unknown race
|
||
-- falls back to Orc. Quoted, not corrected.
|
||
function DressUpTexturePath()
|
||
local race, fileName = UnitRace("player")
|
||
if fileName == "Gnome" or fileName == "GNOME" then
|
||
fileName = "Dwarf"
|
||
elseif fileName == "Troll" or fileName == "TROLL" then
|
||
fileName = "Orc"
|
||
end
|
||
if not fileName then
|
||
fileName = "Orc"
|
||
end
|
||
return "Interface\\DressUpFrame\\DressUpBackground-" .. fileName
|
||
end
|
||
|
||
-- ref DressUpFrame.lua:34-40. Called on OnShow as well as OnLoad: at load time the app has
|
||
-- usually not pushed the player's unit snapshot yet, so `UnitRace` answers nil and the ref's
|
||
-- own fallback would freeze an Orc backdrop onto every character (the same one-tick nil the
|
||
-- character window's level line documents).
|
||
function SetDressUpBackground()
|
||
local texture = DressUpTexturePath()
|
||
DressUpBackgroundTopLeft:SetTexture(texture .. 1)
|
||
DressUpBackgroundTopRight:SetTexture(texture .. 2)
|
||
DressUpBackgroundBotLeft:SetTexture(texture .. 3)
|
||
DressUpBackgroundBotRight:SetTexture(texture .. 4)
|
||
end
|
||
|
||
-- The pane's facing — the paper doll's pair of handlers, over this room's own booth yaw
|
||
-- (ref Model_OnLoad/Model_RotateLeft/Model_RotateRight/Model_OnUpdate, UIParent.lua:1421-1462;
|
||
-- CharacterFrame.xml carries the full note on the ref's sign quirk, quoted here too).
|
||
function BenillaDressUpModel_OnLoad(frame)
|
||
frame.facing = 0.61 -- ref UIParent.lua:1422, the literal default facing
|
||
BenillaDressUpModel_SetFacing(frame.facing)
|
||
end
|
||
|
||
function BenillaDressUpModel_RotateLeft(frame)
|
||
frame.facing = frame.facing - 0.03
|
||
BenillaDressUpModel_SetFacing(frame.facing)
|
||
PlaySound("igInventoryRotateCharacter")
|
||
end
|
||
|
||
function BenillaDressUpModel_RotateRight(frame)
|
||
frame.facing = frame.facing + 0.03
|
||
BenillaDressUpModel_SetFacing(frame.facing)
|
||
PlaySound("igInventoryRotateCharacter")
|
||
end
|
||
|
||
-- The held-button spin (ref Model_OnUpdate) — half a turn per second while a rotate button
|
||
-- reads PUSHED, the ref's own opposite-sign held branches included.
|
||
function BenillaDressUpModel_OnUpdate(frame, elapsed)
|
||
local step = elapsed * 2 * PI * ROTATIONS_PER_SECOND
|
||
if getglobal(frame:GetName() .. "RotateLeftButton"):GetButtonState() == "PUSHED" then
|
||
frame.facing = frame.facing + step
|
||
if frame.facing < 0 then
|
||
frame.facing = frame.facing + (2 * PI)
|
||
end
|
||
BenillaDressUpModel_SetFacing(frame.facing)
|
||
end
|
||
if getglobal(frame:GetName() .. "RotateRightButton"):GetButtonState() == "PUSHED" then
|
||
frame.facing = frame.facing - step
|
||
if frame.facing > (2 * PI) then
|
||
frame.facing = frame.facing - (2 * PI)
|
||
end
|
||
BenillaDressUpModel_SetFacing(frame.facing)
|
||
end
|
||
end
|
||
]]></Script>
|
||
|
||
<!-- A panel action button (Reset/Close): the ref's UIPanelButtonTemplate face, locally
|
||
reconstructed — this house dialect ships no such template, and each window keeps its own
|
||
copy (CraftFrame.xml's identical note). -->
|
||
<Button name="BenillaDressUpPanelButtonTemplate" virtual="true">
|
||
<Size><AbsDimension x="80" y="22"/></Size>
|
||
<NormalFont inherits="GameFontNormal"/>
|
||
<HighlightFont inherits="GameFontHighlight"/>
|
||
<DisabledFont inherits="GameFontDisable"/>
|
||
<NormalTexture file="Interface\Buttons\UI-Panel-Button-Up"><TexCoords left="0" right="0.625" top="0" bottom="0.6875"/></NormalTexture>
|
||
<PushedTexture file="Interface\Buttons\UI-Panel-Button-Down"><TexCoords left="0" right="0.625" top="0" bottom="0.6875"/></PushedTexture>
|
||
<DisabledTexture file="Interface\Buttons\UI-Panel-Button-Disabled"><TexCoords left="0" right="0.625" top="0" bottom="0.6875"/></DisabledTexture>
|
||
<HighlightTexture file="Interface\Buttons\UI-Panel-Button-Highlight" alphaMode="ADD"><TexCoords left="0" right="0.625" top="0" bottom="0.6875"/></HighlightTexture>
|
||
</Button>
|
||
|
||
<Frame name="DressUpFrame" toplevel="true" hidden="true">
|
||
<!-- The ref's 384×512 window. No <Anchors>: ShowUIPanel seats it in the left slot, this
|
||
house's convention for every panel window (MerchantFrame.xml/CraftFrame.xml). -->
|
||
<Size><AbsDimension x="384" y="512"/></Size>
|
||
<HitRectInsets><AbsInset left="0" right="30" top="0" bottom="45"/></HitRectInsets>
|
||
<Layers>
|
||
<!-- The "player" portrait, 60×60 at TOPLEFT (7,-6) (ref l.20-33) — BACKGROUND so the
|
||
window art's ring frames it; bound in OnShow, like every other portrait here. -->
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="DressUpFramePortrait">
|
||
<Size><AbsDimension x="60" y="60"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="7" y="-6"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
</Layer>
|
||
<!-- The window art: the general-panel top pair + the skill-frame bottom pair, the ref's
|
||
own four slabs (l.34-72). -->
|
||
<Layer level="ARTWORK">
|
||
<Texture file="Interface\PaperDollInfoFrame\UI-Character-General-TopLeft">
|
||
<Size><AbsDimension x="256" y="256"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"/></Anchors>
|
||
</Texture>
|
||
<Texture file="Interface\PaperDollInfoFrame\UI-Character-General-TopRight">
|
||
<Size><AbsDimension x="128" y="256"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="256" y="0"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
<Texture file="Interface\PaperDollInfoFrame\SkillFrame-BotLeft">
|
||
<Size><AbsDimension x="256" y="256"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="0" y="-256"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
<Texture file="Interface\PaperDollInfoFrame\SkillFrame-BotRight">
|
||
<Size><AbsDimension x="128" y="256"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="256" y="-256"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
<FontString name="DressUpFrameTitleText" inherits="GameFontHighlight" text="DRESSUP_FRAME">
|
||
<Size><AbsDimension x="300" y="14"/></Size>
|
||
<Anchors><Anchor point="TOP"><Offset><AbsDimension x="0" y="-17"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
<FontString name="DressUpFrameDescriptionText" inherits="GameFontNormalSmall" text="DRESSUP_FRAME_INSTRUCTIONS">
|
||
<Size><AbsDimension x="260" y="36"/></Size>
|
||
<Anchors>
|
||
<Anchor point="CENTER" relativeTo="DressUpFrameTitleText" relativePoint="BOTTOM"><Offset><AbsDimension x="10" y="-22"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
<!-- The race backdrop behind the model, four quadrants (ref l.73-118); the files are
|
||
chosen per race by SetDressUpBackground above. -->
|
||
<Layer level="OVERLAY">
|
||
<Texture name="DressUpBackgroundTopLeft">
|
||
<Size><AbsDimension x="256" y="255"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="22" y="-76"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
<Texture name="DressUpBackgroundTopRight">
|
||
<Size><AbsDimension x="62" y="255"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="DressUpBackgroundTopLeft" relativePoint="TOPRIGHT"/></Anchors>
|
||
</Texture>
|
||
<Texture name="DressUpBackgroundBotLeft">
|
||
<Size><AbsDimension x="256" y="128"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="DressUpBackgroundTopLeft" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
</Texture>
|
||
<Texture name="DressUpBackgroundBotRight">
|
||
<Size><AbsDimension x="62" y="128"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="DressUpBackgroundTopLeft" relativePoint="BOTTOMRIGHT"/></Anchors>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- The corner close X: the ref's UIPanelCloseButton seat (CENTER of TOPRIGHT, -46,-25 —
|
||
ref l.120-127) on the minimize-button art every close button in this house uses. -->
|
||
<Button name="DressUpFrameCloseButton">
|
||
<Size><AbsDimension x="32" y="32"/></Size>
|
||
<Anchors><Anchor point="CENTER" relativePoint="TOPRIGHT"><Offset><AbsDimension x="-46" y="-25"/></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>HideUIPanel(DressUpFrame)</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
<!-- Close (ref l.128-146) and Reset (l.147-165, chained off Close's LEFT). Reset is the
|
||
ref's `DressUpModel:Dress()` + its gsTitleOptionOK click. -->
|
||
<Button name="DressUpFrameCancelButton" inherits="BenillaDressUpPanelButtonTemplate" text="CLOSE">
|
||
<Anchors><Anchor point="CENTER" relativePoint="TOPLEFT"><Offset><AbsDimension x="305" y="-422"/></Offset></Anchor></Anchors>
|
||
<Scripts>
|
||
<OnClick>HideUIPanel(DressUpFrame)</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
<Button name="DressUpFrameResetButton" inherits="BenillaDressUpPanelButtonTemplate" text="RESET">
|
||
<Anchors><Anchor point="RIGHT" relativeTo="DressUpFrameCancelButton" relativePoint="LEFT"/></Anchors>
|
||
<Scripts>
|
||
<OnClick>
|
||
BenillaDressUpModel_Dress()
|
||
PlaySound("gsTitleOptionOK")
|
||
</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
|
||
<!-- The model pane (ref the <DressUpModel> widget, l.166-207): 316×351 anchored BOTTOM
|
||
(-11,+85). A plain Frame sampling the "dressup" booth bake (header). -->
|
||
<Frame name="DressUpModelFrame">
|
||
<Size><AbsDimension x="316" y="351"/></Size>
|
||
<Anchors><Anchor point="BOTTOM"><Offset><AbsDimension x="-11" y="85"/></Offset></Anchor></Anchors>
|
||
<Layers>
|
||
<!-- BACKGROUND, not ARTWORK — the booth quad is an OPAQUE stand-in for a widget
|
||
the reference renders outside the layer batches, so it must sit as low as a
|
||
region goes or it swallows same-level siblings (decision 1070; the pet
|
||
page's diet icon is where that bit). This window is the one where the
|
||
change is visible: the CLOSE/RESET buttons are declared BEFORE the pane and
|
||
overlap its lower edge, so at ARTWORK the pane was painting over them. -->
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="$parentTexture">
|
||
<Size><AbsDimension x="316" y="351"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT"/></Anchors>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- Rotate buttons (ref l.183-206): 35×35 at the WINDOW's TOPLEFT (21,-75), left
|
||
then right chained off its TOPRIGHT. Both edges registered, so one tap fires
|
||
OnClick twice and holding hands the spin to the pane's OnUpdate — the ref's
|
||
own tap-and-hold (decision 0638 §3). -->
|
||
<Button name="DressUpModelFrameRotateLeftButton">
|
||
<Size><AbsDimension x="35" y="35"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="DressUpFrame" relativePoint="TOPLEFT"><Offset><AbsDimension x="21" y="-75"/></Offset></Anchor></Anchors>
|
||
<NormalTexture file="Interface\Buttons\UI-RotationLeft-Button-Up"/>
|
||
<PushedTexture file="Interface\Buttons\UI-RotationLeft-Button-Down"/>
|
||
<HighlightTexture file="Interface\Buttons\ButtonHilight-Round" alphaMode="ADD"/>
|
||
<Scripts>
|
||
<OnLoad>self:RegisterForClicks("LeftButtonDown", "LeftButtonUp")</OnLoad>
|
||
<OnClick>BenillaDressUpModel_RotateLeft(getglobal("DressUpModelFrame"))</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
<Button name="DressUpModelFrameRotateRightButton">
|
||
<Size><AbsDimension x="35" y="35"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="DressUpModelFrameRotateLeftButton" relativePoint="TOPRIGHT"/></Anchors>
|
||
<NormalTexture file="Interface\Buttons\UI-RotationRight-Button-Up"/>
|
||
<PushedTexture file="Interface\Buttons\UI-RotationRight-Button-Down"/>
|
||
<HighlightTexture file="Interface\Buttons\ButtonHilight-Round" alphaMode="ADD"/>
|
||
<Scripts>
|
||
<OnLoad>self:RegisterForClicks("LeftButtonDown", "LeftButtonUp")</OnLoad>
|
||
<OnClick>BenillaDressUpModel_RotateRight(getglobal("DressUpModelFrame"))</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
</Frames>
|
||
<Scripts>
|
||
<OnLoad>
|
||
BenillaDressUpModel_OnLoad(self)
|
||
BenillaSetBoothTexture(getglobal(self:GetName() .. "Texture"), "dressup")
|
||
</OnLoad>
|
||
<OnUpdate>BenillaDressUpModel_OnUpdate(self, arg1)</OnUpdate>
|
||
</Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
<Scripts>
|
||
<OnLoad>SetDressUpBackground()</OnLoad>
|
||
<OnShow>
|
||
SetDressUpBackground()
|
||
SetPortraitTexture(DressUpFramePortrait, "player")
|
||
PlaySound("igCharacterInfoOpen")
|
||
</OnShow>
|
||
<!-- Closing empties the booth (dressup.rs's `Close` intent): the ref's widget keeps its
|
||
state while hidden, but its next DressUpItem re-issues SetUnit("player") *because*
|
||
the frame wasn't visible, so that state is never observable. -->
|
||
<OnHide>
|
||
BenillaDressUpModel_Close()
|
||
PlaySound("igCharacterInfoClose")
|
||
</OnHide>
|
||
</Scripts>
|
||
</Frame>
|
||
</Ui>
|