A from-scratch World of Warcraft 1.12.1 client in Rust + Bevy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
402 lines
26 KiB
XML
402 lines
26 KiB
XML
<Ui>
|
||
<!--
|
||
benilla's gossip dialog (decision 0081 phase 3), RE-SKINNED to the real 1.12 gossip/quest
|
||
greeting window (dressing arc, decision 0084): the geometry and art below are QUOTED from the
|
||
real `GossipFrame.xml` (scratchpad `ref-GossipFrame.xml`; line citations inline), turned onto
|
||
our own feeds/intents. The name `BenillaGossipFrame`, its panel registration
|
||
(UiPanels.xml's UIPanelWindows["BenillaGossipFrame"], area="left", pushable=0), the Era gossip
|
||
feeds (GetGossipText/GetGossipOptions/IsGossipOptionCoded/SelectGossipOption/CloseGossip/
|
||
GetNumGossipQuests/GetGossipQuestInfo/SelectGossipQuest), and the intent functions are
|
||
UNCHANGED — only the window's dressing is real now.
|
||
|
||
A hidden window that shows on GOSSIP_SHOW and hides on GOSSIP_CLOSED. It wears the real
|
||
QuestFrame parchment: four quadrant slabs (UI-QuestGreeting-{TopLeft,TopRight,BotLeft,BotRight},
|
||
ref l.13-44) at the real 384×512 (ref l.128); the greeting body and the row list quoted from
|
||
the real GossipGreetingText / GossipTitleButtonTemplate (ref l.86-125, 223-264).
|
||
|
||
QUEST ROWS (decision 0088 §3, filled in): the real `GossipFrameUpdate` (ref l.24-29) fills ONE
|
||
shared `GossipTitleButton` pool through three sequential passes over a single `buttonIndex`
|
||
counter — `GossipFrameAvailableQuestsUpdate` (ref l.63-85) first, `GossipFrameActiveQuestsUpdate`
|
||
(ref l.87-109) second, `GossipFrameOptionsUpdate` (ref l.111-128) third — so quest rows always
|
||
land ABOVE the option rows, and the two blocks share the very same row buttons/anchors (a
|
||
`titleButton.type` field picked at fill time routes the click: `SelectGossipAvailableQuest` /
|
||
`SelectGossipActiveQuest` / `SelectGossipOption`, ref l.53-61). We mirror that shape exactly but
|
||
over our OWN flatter seam (`benilla-ui` `script/gossip.rs`): the app already resolves the wire's
|
||
available/active split and delivers ONE ordered `GetNumGossipQuests()`/`GetGossipQuestInfo(i)`
|
||
list (quest rows first, in wire order), so `BenillaGossipFrame_Update` below runs a single loop
|
||
over the shared `BenillaGossipRow1..8` pool — quest rows fill from i=1, option rows fill after
|
||
them — instead of the ref's three separate counters; a row's `.kind` ("quest"/"option") plus its
|
||
`.itemIndex` (the row's 1-based position within ITS OWN list) is all `BenillaGossipRow_OnClick`
|
||
needs to call the right one of `SelectGossipQuest`/`SelectGossipOption` (ref's three intents
|
||
collapse to two on our seam — see gossip.rs's doc comment). Per-row icon: active → the real
|
||
`Interface\GossipFrame\ActiveQuestIcon` (ref l.99), available → `Interface\GossipFrame\
|
||
AvailableQuestIcon` (ref l.75) — both verified present in the MPQ list. We skip the ref's
|
||
per-row `GossipResize` auto-height (ref l.130-132, `SetHeight(GetTextHeight()+2)`) and its
|
||
"too many quests" message() (ref l.67-69/91-93/115-117): no word-wrap engine to measure against
|
||
yet (same gap the greeting text already lives with), and the shared 8-row cap below silently
|
||
drops the overflow exactly like the option rows already did before this change.
|
||
|
||
ENGINE-SLICE CAVEAT (this branch predates the dressing arc's engine slice — named `<Font>`
|
||
objects are not implemented here yet, loader.rs "named Font objects are not implemented in v1").
|
||
The real window's `inherits="QuestFont"` FontStrings are transcribed faithfully below (they are
|
||
part of the quoted geometry), but until the font-object slice + our Fonts.xml land on this line
|
||
the loader warns "unknown template 'QuestFont'" and the strings render in the default font —
|
||
no worse than before (nothing here inherited a font). They light up automatically when the
|
||
slice merges. No <TexCoords> is used: every quadrant samples its whole texture (the real gossip
|
||
window uses TexCoords only on the material/patch art we omit), so this window needs none of it.
|
||
|
||
The NPC name rides in the title banner (ref GossipFrameNpcNameText, l.157-178): a GameFontHighlight
|
||
FontString centred at the window TOP -23, mirroring the merchant's pattern — the app resolves the
|
||
gossip NPC's guid through the NameCache and delivers the name as arg1 of GOSSIP_SHOW; empty until
|
||
it lands. The GOODBYE button rides bottom-right (ref GossipFrameGreetingGoodbyeButton, l.206-222),
|
||
wired to the same close path as the close button.
|
||
|
||
Real-window features we OMIT (no feed, or no scroll/wrap engine yet):
|
||
the scroll frame itself (ref l.223-436 — our short greeting needs no scrolling),
|
||
and the BotLeftPatch material art. We keep the real geometry of everything we DO ship — including
|
||
the quest-row section now (see below).
|
||
|
||
UIPanel slot system (decision 0084 §2): carries NO hardcoded <Anchors> — ShowUIPanel/SetLeftFrame
|
||
SetPoints it to the left slot (TOPLEFT UIParent, 0, -104) on open; every show goes through
|
||
ShowUIPanel, every hide through HideUIPanel, never Show()/Hide() directly.
|
||
-->
|
||
<Script><![CDATA[
|
||
-- The shared row pool's cap (decision 0088 §3): quest rows fill from slot 1, option rows fill
|
||
-- after them, both drawing from the SAME BenillaGossipRow1..8 buttons (ref's single
|
||
-- GossipTitleButton pool, l.24-29/63-128) — mirrors the option-only cap this already was.
|
||
BENILLA_GOSSIP_MAX = 8
|
||
|
||
-- The Era icon-type string → the real Blizzard gossip-icon texture (resolves from the MPQ at
|
||
-- render). Unmapped types fall back to the chat bubble (the app already defaults unknowns to
|
||
-- "gossip", so this is belt-and-braces).
|
||
BENILLA_GOSSIP_ICONS = {
|
||
gossip = "Interface\\GossipFrame\\GossipGossipIcon",
|
||
vendor = "Interface\\GossipFrame\\VendorGossipIcon",
|
||
taxi = "Interface\\GossipFrame\\TaxiGossipIcon",
|
||
trainer = "Interface\\GossipFrame\\TrainerGossipIcon",
|
||
binder = "Interface\\GossipFrame\\BinderGossipIcon",
|
||
tabard = "Interface\\GossipFrame\\TabardGossipIcon",
|
||
battlemaster = "Interface\\GossipFrame\\BattleMasterGossipIcon",
|
||
}
|
||
|
||
-- The real per-row quest icons (ref l.75/99) — active (in-progress/turn-in) vs available
|
||
-- (not yet accepted), the same split `GossipQuestRow.active` already carries off the wire.
|
||
BENILLA_GOSSIP_QUEST_ICON_ACTIVE = "Interface\\GossipFrame\\ActiveQuestIcon"
|
||
BENILLA_GOSSIP_QUEST_ICON_AVAILABLE = "Interface\\GossipFrame\\AvailableQuestIcon"
|
||
|
||
function BenillaGossipRow_OnLoad(button)
|
||
button.icon = getglobal(button:GetName() .. "Icon")
|
||
button.label = getglobal(button:GetName() .. "Label")
|
||
end
|
||
|
||
-- One shared row serves either a quest or an option depending on what
|
||
-- BenillaGossipFrame_Update assigned it this repaint (button.kind, set there) — mirrors the
|
||
-- ref's titleButton.type dispatch (ref l.53-61), collapsed onto our seam's two intents
|
||
-- (SelectGossipQuest covers both the ref's Available/Active clicks, gossip.rs's doc comment).
|
||
function BenillaGossipRow_OnClick(button)
|
||
if button.kind == "quest" then
|
||
SelectGossipQuest(button.itemIndex)
|
||
else
|
||
SelectGossipOption(button.itemIndex)
|
||
end
|
||
end
|
||
|
||
function BenillaGossipFrame_Update()
|
||
getglobal("BenillaGossipGreetingText"):SetText(GetGossipText() or "")
|
||
local numQuests = GetNumGossipQuests()
|
||
-- GetGossipOptions() returns a flat vararg of (label, type) pairs (the Era shape).
|
||
local opts = { GetGossipOptions() }
|
||
local numOptions = #opts / 2
|
||
for i = 1, BENILLA_GOSSIP_MAX do
|
||
local button = getglobal("BenillaGossipRow" .. i)
|
||
if i <= numQuests then
|
||
-- Quest rows fill first (ref l.27-28: available then active, already ordered by
|
||
-- the app before it reaches GetGossipQuestInfo) — the row's OWN 1-based position
|
||
-- IS its quest-list index, so no separate local counter is needed.
|
||
local title, active = GetGossipQuestInfo(i)
|
||
button.kind = "quest"
|
||
button.itemIndex = i
|
||
button.label:SetText(title)
|
||
button.icon:SetTexture(active and BENILLA_GOSSIP_QUEST_ICON_ACTIVE or BENILLA_GOSSIP_QUEST_ICON_AVAILABLE)
|
||
button:Enable()
|
||
button:Show()
|
||
elseif i <= numQuests + numOptions then
|
||
-- Option rows fill after every quest row (ref l.29 runs last) — itemIndex is the
|
||
-- row's position WITHIN the options list, not the shared pool slot.
|
||
local optIndex = i - numQuests
|
||
local label = opts[(optIndex - 1) * 2 + 1]
|
||
local otype = opts[(optIndex - 1) * 2 + 2]
|
||
button.kind = "option"
|
||
button.itemIndex = optIndex
|
||
button.label:SetText(label)
|
||
button.icon:SetTexture(BENILLA_GOSSIP_ICONS[otype] or BENILLA_GOSSIP_ICONS.gossip)
|
||
-- Coded (password) options are greyed and unselectable in v1 (decision 0081).
|
||
if IsGossipOptionCoded(optIndex) then
|
||
button:Disable()
|
||
else
|
||
button:Enable()
|
||
end
|
||
button:Show()
|
||
else
|
||
button:Hide()
|
||
end
|
||
end
|
||
end
|
||
|
||
function BenillaGossipFrame_OnLoad(frame)
|
||
-- The NPC portrait: the "npc" unit token → the interaction NPC's live model bake
|
||
-- (crates/benilla/src/portrait, InteractNpc). Bound once; the app re-resolves it every
|
||
-- frame, so a revisit to a different gossip NPC shows that face.
|
||
SetPortraitTexture(getglobal(frame:GetName() .. "Portrait"), "npc")
|
||
frame:RegisterEvent("GOSSIP_SHOW")
|
||
frame:RegisterEvent("GOSSIP_CLOSED")
|
||
end
|
||
|
||
-- The gossip NPC's name arrives as arg1 of GOSSIP_SHOW (the app resolves the NPC guid through
|
||
-- the NameCache); nil/empty until it lands → a blank banner (mirrors the merchant title).
|
||
function BenillaGossipFrame_SetTitle(name)
|
||
getglobal("BenillaGossipNpcNameText"):SetText(name or "")
|
||
end
|
||
|
||
function BenillaGossipFrame_OnEvent(frame)
|
||
if event == "GOSSIP_SHOW" then
|
||
BenillaGossipFrame_SetTitle(arg1)
|
||
BenillaGossipFrame_Update()
|
||
ShowUIPanel(frame)
|
||
elseif event == "GOSSIP_CLOSED" then
|
||
HideUIPanel(frame)
|
||
end
|
||
end
|
||
|
||
function BenillaGossipCloseButton_OnClick()
|
||
-- vanilla's client-side close sends no packet; the app clears the menu on this intent
|
||
-- (which fires GOSSIP_CLOSED), and we hide immediately so there's no one-frame lag.
|
||
CloseGossip()
|
||
HideUIPanel(getglobal("BenillaGossipFrame"))
|
||
end
|
||
]]></Script>
|
||
|
||
<!--
|
||
One shared gossip row (ref GossipTitleButtonTemplate, l.86-125): the real 300×16 template, used
|
||
by the REAL client for quest rows AND option rows alike (a single pool, ref l.24-29/63-128) — we
|
||
do the same rather than carrying two near-identical templates. The type icon sits at the row's
|
||
TOPLEFT (16×16; ref $parentGossipIcon, l.92-102) — the real XML defaults it to
|
||
UI-Quest-BulletPoint, but the real client (like us) overrides it per row kind at Update time, so
|
||
we carry no default file and let BenillaGossipFrame_Update set it (quest → Active/AvailableQuestIcon,
|
||
ref l.75/99; option → the per-type GossipIcon). The label is QuestFont, LEFT, at LEFT +20 (ref
|
||
ButtonText, l.112-124). The highlight is the real UI-QuestTitleHighlight ADD glow (ref l.111).
|
||
-->
|
||
<Button name="BenillaGossipRowTemplate" virtual="true">
|
||
<Size><AbsDimension x="300" y="16"/></Size>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="$parentIcon">
|
||
<Size><AbsDimension x="16" y="16"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="0" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
</Texture>
|
||
</Layer>
|
||
<Layer level="ARTWORK">
|
||
<FontString name="$parentLabel" inherits="QuestFont" justifyH="LEFT">
|
||
<Size><AbsDimension x="275" y="0"/></Size>
|
||
<Anchors>
|
||
<Anchor point="LEFT" relativePoint="LEFT"><Offset><AbsDimension x="20" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<HighlightTexture file="Interface\QuestFrame\UI-QuestTitleHighlight" alphaMode="ADD"/>
|
||
<Scripts>
|
||
<OnClick>BenillaGossipRow_OnClick(self)</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
|
||
<Frame name="BenillaGossipFrame" hidden="true">
|
||
<!-- The real 384×512 window (ref l.128). No <Anchors> — ShowUIPanel/SetLeftFrame SetPoints this
|
||
to the left slot on open. -->
|
||
<Size><AbsDimension x="384" y="512"/></Size>
|
||
<Layers>
|
||
<!-- The four QuestGreeting quadrant slabs that ARE the parchment art (ref l.13-44): 256-wide
|
||
left halves, 128-wide right halves, each 256 tall, pinned to their corner. No <TexCoords>
|
||
— each samples its whole texture. The solid-colour fill is gone (the parchment is
|
||
opaque). -->
|
||
<Layer level="BACKGROUND">
|
||
<!-- NPC portrait 60×60 TOPLEFT (7,-6) (ref GossipFramePortrait), declared BEFORE the
|
||
parchment so it draws UNDER it and the parchment's ring frames the portrait (the empty
|
||
ring showed the scene through the hole before). Bound in OnLoad, circle-masked. -->
|
||
<Texture name="$parentPortrait">
|
||
<Size><AbsDimension x="60" y="60"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="7" y="-6"/></Offset></Anchor>
|
||
</Anchors>
|
||
</Texture>
|
||
<Texture file="Interface\QuestFrame\UI-QuestGreeting-TopLeft">
|
||
<Size><AbsDimension x="256" y="256"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"/></Anchors>
|
||
</Texture>
|
||
<Texture file="Interface\QuestFrame\UI-QuestGreeting-TopRight">
|
||
<Size><AbsDimension x="128" y="256"/></Size>
|
||
<Anchors><Anchor point="TOPRIGHT" relativePoint="TOPRIGHT"/></Anchors>
|
||
</Texture>
|
||
<Texture file="Interface\QuestFrame\UI-QuestGreeting-BotLeft">
|
||
<Size><AbsDimension x="256" y="256"/></Size>
|
||
<Anchors><Anchor point="BOTTOMLEFT" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
</Texture>
|
||
<Texture file="Interface\QuestFrame\UI-QuestGreeting-BotRight">
|
||
<Size><AbsDimension x="128" y="256"/></Size>
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMRIGHT"/></Anchors>
|
||
</Texture>
|
||
<!-- Ref GossipFrame.xml:191-202: gossip has no bottom-LEFT button, but the shared
|
||
UI-QuestGreeting-BotLeft art bakes the button recess in — the ref covers it
|
||
with this patch (the director's "bottom left hole"). -->
|
||
<Texture file="Interface\QuestFrame\UI-Quest-BotLeftPatch">
|
||
<Size><AbsDimension x="128" y="64"/></Size>
|
||
<Anchors><Anchor point="BOTTOMLEFT" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="22" y="68"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
</Layer>
|
||
<Layer level="ARTWORK">
|
||
<!-- NPC name banner (ref GossipFrameNpcNameText l.157-178): GameFontHighlight, centred
|
||
on the window at TOP -23. The app delivers the name as arg1 of GOSSIP_SHOW; blank
|
||
until it lands. CENTER + the single-point (~zero-width) rect keeps the name centred
|
||
regardless of length, exactly like the merchant's title. -->
|
||
<FontString name="BenillaGossipNpcNameText" inherits="GameFontHighlight" justifyH="CENTER">
|
||
<Anchors>
|
||
<Anchor point="TOP" relativePoint="TOP"><Offset><AbsDimension x="0" y="-23"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
<!-- Greeting body: the real GossipGreetingText (ref l.241-252) — QuestFont, LEFT, its
|
||
width pinned to the real 270 so word-wrap engages once that engine lands (line
|
||
breaks today come from the wire's $B macro → \n). Positioned at the real scroll
|
||
frame's text origin: window TOPLEFT +(23,-81) (scroll frame, ref l.230) then
|
||
+(10,-10) inside the scroll child (ref l.248) = (33,-91). -->
|
||
<FontString name="BenillaGossipGreetingText" inherits="QuestFont" justifyH="LEFT">
|
||
<Size><AbsDimension x="270" y="0"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="33" y="-91"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- The shared row pool: the real GossipTitleButtonTemplate stack (ref l.256-309), now
|
||
serving quest rows AND option rows off the SAME 8 buttons (decision 0088 §3 — the
|
||
ref's own shape, ref l.24-29/63-128: quest rows fill first, options after). Row 1
|
||
anchors to the GREETING FONTSTRING's BOTTOMLEFT +(-10,-20) — the real anchor verbatim
|
||
(ref l.258-261): the greeting's height is its measured wrapped text (the engine's
|
||
measure round-trip), so a 3-line greeting pushes the rows down exactly as the real
|
||
client does (the fixed-offset bridge used before overprinted multi-line greetings —
|
||
caught by the ui-gossip capture fixture). The rest stack on the prior row's BOTTOMLEFT
|
||
(ref l.267 — no gap; the real 16px rows touch) — since it's one static anchor chain
|
||
over one shared pool, however many quest rows BenillaGossipFrame_Update shows this
|
||
repaint, the option rows that follow land right below them with no runtime
|
||
repositioning (decision 0088 §2 flags runtime SetPoint as NOT propagating to
|
||
dependents on this engine; a static XML chain has no such issue — verified by the
|
||
layout assertions in the engine test below). -->
|
||
<Button name="BenillaGossipRow1" inherits="BenillaGossipRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaGossipGreetingText" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="-10" y="-20"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>BenillaGossipRow_OnLoad(self)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaGossipRow2" inherits="BenillaGossipRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaGossipRow1" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<Scripts><OnLoad>BenillaGossipRow_OnLoad(self)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaGossipRow3" inherits="BenillaGossipRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaGossipRow2" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<Scripts><OnLoad>BenillaGossipRow_OnLoad(self)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaGossipRow4" inherits="BenillaGossipRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaGossipRow3" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<Scripts><OnLoad>BenillaGossipRow_OnLoad(self)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaGossipRow5" inherits="BenillaGossipRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaGossipRow4" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<Scripts><OnLoad>BenillaGossipRow_OnLoad(self)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaGossipRow6" inherits="BenillaGossipRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaGossipRow5" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<Scripts><OnLoad>BenillaGossipRow_OnLoad(self)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaGossipRow7" inherits="BenillaGossipRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaGossipRow6" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<Scripts><OnLoad>BenillaGossipRow_OnLoad(self)</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="BenillaGossipRow8" inherits="BenillaGossipRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="BenillaGossipRow7" relativePoint="BOTTOMLEFT"/></Anchors>
|
||
<Scripts><OnLoad>BenillaGossipRow_OnLoad(self)</OnLoad></Scripts>
|
||
</Button>
|
||
<!-- Close: the real GossipFrameCloseButton position (CENTER on the window's TOPRIGHT,
|
||
-42,-31; ref l.179-187), on the minimize-button art our close already used (the real
|
||
UIPanelCloseButton art rides the tooltip/dialog arc). -->
|
||
<Button name="BenillaGossipCloseButton">
|
||
<Size><AbsDimension x="32" y="32"/></Size>
|
||
<Anchors>
|
||
<Anchor point="CENTER" relativePoint="TOPRIGHT"><Offset><AbsDimension x="-42" y="-31"/></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>BenillaGossipCloseButton_OnClick()</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
<!-- GOODBYE button (ref GossipFrameGreetingGoodbyeButton l.206-222): the real red
|
||
UIPanelButtonTemplate, 78×22, BOTTOMRIGHT of the window -39,73. Our engine ships no
|
||
UIPanelButtonTemplate, so the button face is built directly from the very textures that
|
||
template resolves to — UI-Panel-Button-{Up,Down,Highlight} (all verified in the MPQ),
|
||
stretched over the button as its Normal/Pushed/Highlight art. The "Goodbye" label
|
||
(GlobalStrings GOODBYE = "Goodbye") is an OVERLAY FontString centred on the button (the
|
||
real ButtonText draws in the OVERLAY layer). Wired to the same close path as the close
|
||
button (CloseGossip → HideUIPanel), mirroring the ref's OnClick HideUIPanel(GossipFrame). -->
|
||
<Button name="BenillaGossipGoodbyeButton">
|
||
<Size><AbsDimension x="78" y="22"/></Size>
|
||
<Anchors>
|
||
<Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="-39" y="73"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="OVERLAY">
|
||
<FontString name="$parentText" inherits="GameFontNormal" justifyH="CENTER" text="Goodbye">
|
||
<Anchors>
|
||
<Anchor point="CENTER" relativePoint="CENTER"/>
|
||
</Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<!-- The button face occupies only the top-left 0.625×0.6875 of each file — the real
|
||
UIPanelButton*Texture templates slice it with exactly these TexCoords
|
||
(ref-UIPanelTemplates.xml l.3-17). Drawing the whole file (transparent padding
|
||
included) squashed the face into the scuffed blob the director's A/B caught. -->
|
||
<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>
|
||
<HighlightTexture file="Interface\Buttons\UI-Panel-Button-Highlight" alphaMode="ADD">
|
||
<TexCoords left="0" right="0.625" top="0" bottom="0.6875"/>
|
||
</HighlightTexture>
|
||
<Scripts>
|
||
<OnClick>BenillaGossipCloseButton_OnClick()</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
</Frames>
|
||
<Scripts>
|
||
<OnLoad>BenillaGossipFrame_OnLoad(self)</OnLoad>
|
||
<OnEvent>BenillaGossipFrame_OnEvent(self)</OnEvent>
|
||
<!-- OnShow/OnHide, quoted from the real GossipFrame.xml frame Scripts (l.445/454): the
|
||
kits igQuestListOpen/Close, and — load-bearing — CloseGossip() on hide (the real
|
||
GossipFrame_OnHide). CloseGossip ends the gossip session whenever the frame hides,
|
||
INCLUDING when another NPC window displaces it at the UIPanel slot (SetLeftFrame →
|
||
oldFrame:Hide() → OnHide); without it the GossipState resource stayed set after a
|
||
vendor/quest window replaced the menu, and gossip would not reopen until the
|
||
range-guard reset it (decision 0095). No-packet client-side clear; idempotent with the
|
||
close button, which also calls it. Never fires at load (hidden="true"). -->
|
||
<OnShow>PlaySound("igQuestListOpen")</OnShow>
|
||
<OnHide>CloseGossip(); PlaySound("igQuestListClose")</OnHide>
|
||
</Scripts>
|
||
</Frame>
|
||
</Ui>
|