- forty files that carried the reference's literal Lua are rewritten as our own expression of the behaviour — worst identical run 61 lines down to 7 — and the README now says exactly that - the overlap gate measures the code itself across all four reference corpora, and ratchets: the number may only go down - a lost session ends at the login screen instead of silently re-authenticating and stealing the account back - a building's skybox is a real model: Caverns of Time's white ceiling becomes its painted nebula and additive stars Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
444 lines
24 KiB
XML
444 lines
24 KiB
XML
<Ui>
|
|
<!--
|
|
The party member frames + the group-invite popup (decision 0434 phase 3). Geometry, art
|
|
paths and behavior laws are MEASURED against the reference client's own FrameXML, extracted
|
|
through the full MPQ patch chain (decision 0246; survey 2026-07-17):
|
|
PartyFrame.xml, PartyFrameTemplates.xml, PartyMemberFrame.lua, StaticPopup.lua ("PARTY_INVITE"),
|
|
UIParent.lua (the PARTY_INVITE_REQUEST wiring) — the code below is our own. Data flow is
|
|
ours too: the app feeds
|
|
party1..party4 unit snapshots + the PartyState roster (crates/benilla/src/ui_party.rs) and
|
|
fires the PARTY_* events; the popup's Accept/Decline queue PartyRequests the app drains.
|
|
|
|
THE CASCADE. The ref anchors frames 2-4 to the PREVIOUS frame's PetFrame bottom-left at
|
|
(-23,-10) — spacing rides the pet frame, which sits at (23,-27) when hidden (26 tall), so
|
|
the no-pet stride is TOPLEFT->BOTTOMLEFT (0,-10). Pet frames land in phase 4; until then
|
|
the cascade uses that no-pet stride directly, which is byte-identical to the ref's layout
|
|
for petless parties (the only kind phase 3 renders).
|
|
|
|
DEVIATIONS / DEFERRED (phase 4+, decision 0434):
|
|
- Pet frames, the 4 debuff buttons (48,-32 +2px chain), the 16/8 buff hover panel, and the
|
|
dispellable-debuff Status ring: they need the party aura/pet feed (phase 4).
|
|
(The PVP icon landed with decision 0646 — UnitFactionGroup exists now.)
|
|
- HIDE_PARTY_INTERFACE (hide-in-raid uvar): waits for the raid UI slice.
|
|
- Portrait: our high-res model bake (decision 0105), same as every unit frame.
|
|
- The ref's low-health portrait pulse flips alpha 127/255<->255/255 on 0.5 s half-cycles
|
|
(PartyMemberFrame.lua's sign-flip counter); transcribed as the same triangle wave.
|
|
|
|
DOUBLE-DECLINE, KEPT: the ref's popup calls DeclineGroup() in OnCancel AND again in OnHide
|
|
(only OnAccept sets the inviteAccepted guard), so a clicked Decline sends two
|
|
CMSG_GROUP_DECLINE. vmangos silently ignores the second (no pending invite -> early
|
|
return). Matched rather than "fixed" - the wire tolerates it and the guard's
|
|
real job is the timeout/override/escape paths.
|
|
-->
|
|
<Script><![CDATA[
|
|
-- ── MAX_RAID_MEMBERS (ref RaidFrame.lua l.2) ─────────────────────────────────────────
|
|
-- A fact about the protocol, not about our implementation: a 1.12 raid is 40, and the
|
|
-- `raid1`..`raid40` token space is 40 wide whether or not we build a raid UI. Declared
|
|
-- here rather than in a RaidFrame.xml because we ship none; party and raid are the same
|
|
-- subsystem family, and this is the file that already owns the group surface.
|
|
--
|
|
-- **The loop it feeds already works.** `for i = 1, MAX_RAID_MEMBERS do UnitName("raid"..i)`
|
|
-- answers nil for every absent token, which is exactly right for a player not in a raid —
|
|
-- so the constant is not a promise of a raid UI, it is the bound the token space has.
|
|
--
|
|
-- Reached by following a `'for' limit must be a number` five addons shared:
|
|
-- `CT_RaidAssist.lua:3283` is `for i = 1, MAX_RAID_MEMBERS, 1 do`. Read with `grep -a`,
|
|
-- because this corpus's Ace files are ISO-8859 and plain grep silently skips them.
|
|
MAX_RAID_MEMBERS = 40
|
|
-- Its two siblings, each reached one line further along the same chain
|
|
-- (`CT_RAOptions.lua:75`, then `:231`). The reference declares all three together at
|
|
-- RaidFrame.lua l.2-4, and they agree: 40 = 8 x 5. Adding them one at a time as an addon
|
|
-- asked was the wrong shape — they are one fact about the raid token space, so they land
|
|
-- as one.
|
|
NUM_RAID_GROUPS = 8
|
|
MEMBERS_PER_RAID_GROUP = 5
|
|
|
|
-- ── The group-invite popup ────────────────────────────────────────────────────────────
|
|
-- The strings and the three flags are the reference's own (INVITATION = "%s invites you to
|
|
-- a group.", GlobalStrings:2586-area; a 60 s silent timeout, answerable while dead,
|
|
-- closable with ESC).
|
|
--
|
|
-- The whole of its behaviour turns on ONE latch, `inviteAccepted`, and the four hooks below
|
|
-- are just the four moments that read or write it. It lives on the registry entry rather
|
|
-- than in an upvalue here because that is where the reference keeps it and an addon
|
|
-- inspecting the dialog expects to find it there — which is why each hook goes back through
|
|
-- `StaticPopupDialogs["PARTY_INVITE"]` instead of closing over a local.
|
|
--
|
|
-- They are named rather than inlined so the entry below reads as the manifest it is: four
|
|
-- strings, three flags, four hooks.
|
|
|
|
-- Every showing starts unanswered — including a re-show of the same entry, which is what a
|
|
-- second invite arriving while the first is up does.
|
|
local function PartyInvite_OnShow()
|
|
StaticPopupDialogs["PARTY_INVITE"].inviteAccepted = nil
|
|
end
|
|
|
|
-- The only path that answers the server affirmatively, and the only one that latches.
|
|
local function PartyInvite_OnAccept()
|
|
AcceptGroup()
|
|
StaticPopupDialogs["PARTY_INVITE"].inviteAccepted = 1
|
|
end
|
|
|
|
local function PartyInvite_OnCancel()
|
|
DeclineGroup()
|
|
end
|
|
|
|
-- The catch-all. EVERY way this dialog leaves the screen lands here — Decline, the 60 s
|
|
-- timeout, ESC, and another dialog overriding it — and the latch is what tells the one
|
|
-- that already said yes from the four that never answered at all. A clicked Decline
|
|
-- therefore declines twice (OnCancel, then here); see DOUBLE-DECLINE in the header, which
|
|
-- is the reference's behaviour and the wire tolerates it.
|
|
local function PartyInvite_OnHide()
|
|
if not StaticPopupDialogs["PARTY_INVITE"].inviteAccepted then
|
|
DeclineGroup()
|
|
end
|
|
end
|
|
|
|
StaticPopupDialogs["PARTY_INVITE"] = {
|
|
text = INVITATION,
|
|
button1 = ACCEPT,
|
|
button2 = DECLINE,
|
|
sound = "igPlayerInvite",
|
|
timeout = 60,
|
|
whileDead = 1,
|
|
hideOnEscape = 1,
|
|
OnShow = PartyInvite_OnShow,
|
|
OnAccept = PartyInvite_OnAccept,
|
|
OnCancel = PartyInvite_OnCancel,
|
|
OnHide = PartyInvite_OnHide,
|
|
}
|
|
|
|
-- ref PartyMemberFrame.lua's OnLoad: cache children, register, first paint.
|
|
function BenillaPartyFrame_OnLoad(frame)
|
|
local id = frame:GetID()
|
|
local name = frame:GetName()
|
|
local tf = name .. "TextureFrame"
|
|
frame.unit = "party" .. id
|
|
frame.portrait = getglobal(name .. "Portrait")
|
|
frame.healthBar = getglobal(name .. "HealthBar")
|
|
frame.manaBar = getglobal(name .. "ManaBar")
|
|
-- The recessed-bar look, the reference's own mechanism (ref-TargetFrame.lua l.32-34):
|
|
-- push the bars one frame level BELOW the art's TextureFrame. Frame level is the only
|
|
-- key term above the draw layer (decision 0884), so this is the only thing that can hold
|
|
-- the BACKGROUND party art over the ARTWORK bar fills. See the LAYERING note below.
|
|
local textureFrameLevel = getglobal(tf):GetFrameLevel()
|
|
frame.healthBar:SetFrameLevel(textureFrameLevel - 1)
|
|
frame.manaBar:SetFrameLevel(textureFrameLevel - 1)
|
|
frame.nameText = getglobal(tf .. "Name")
|
|
frame.leaderIcon = getglobal(tf .. "LeaderIcon")
|
|
frame.masterIcon = getglobal(tf .. "MasterIcon")
|
|
frame.disconnect = getglobal(tf .. "Disconnect")
|
|
frame.pvpIcon = getglobal(tf .. "PVPIcon")
|
|
frame.flashTimer = 0
|
|
SetPortraitTexture(frame.portrait, frame.unit)
|
|
frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
|
frame:RegisterEvent("PARTY_MEMBERS_CHANGED")
|
|
frame:RegisterEvent("PARTY_LEADER_CHANGED")
|
|
frame:RegisterEvent("PARTY_LOOT_METHOD_CHANGED")
|
|
frame:RegisterEvent("UNIT_HEALTH")
|
|
frame:RegisterEvent("UNIT_MAXHEALTH")
|
|
frame:RegisterEvent("UNIT_POWER_UPDATE")
|
|
frame:RegisterEvent("UNIT_MAXPOWER")
|
|
frame:RegisterEvent("UNIT_DISPLAYPOWER")
|
|
frame:RegisterEvent("UNIT_NAME_UPDATE")
|
|
frame:RegisterEvent("UNIT_FACTION")
|
|
frame:EnableMouse(true)
|
|
BenillaPartyFrame_Update(frame)
|
|
end
|
|
|
|
function BenillaPartyFrame_OnEvent(frame)
|
|
-- UNIT_* events name their unit in arg1; other units' updates are not ours.
|
|
if string.sub(event, 1, 5) == "UNIT_" and arg1 ~= frame.unit then
|
|
return
|
|
end
|
|
BenillaPartyFrame_Update(frame)
|
|
end
|
|
|
|
-- ref PartyMemberHealthCheck: the portrait recolor law + the disconnect override.
|
|
function BenillaPartyFrame_HealthCheck(frame)
|
|
local unit = frame.unit
|
|
if not UnitIsConnected(unit) then
|
|
-- Disconnected: bar forced full and grey, portrait desaturated, icon on.
|
|
frame.healthBar:SetMinMaxValues(0, 1)
|
|
frame.healthBar:SetValue(1)
|
|
frame.healthBar:SetStatusBarColor(0.5, 0.5, 0.5)
|
|
SetDesaturation(frame.portrait, 1)
|
|
frame.disconnect:Show()
|
|
return
|
|
end
|
|
SetDesaturation(frame.portrait, nil)
|
|
frame.disconnect:Hide()
|
|
frame.healthBar:SetStatusBarColor(0.0, 1.0, 0.0)
|
|
local hp, hpMax = UnitHealth(unit), UnitHealthMax(unit)
|
|
if UnitIsDead(unit) then
|
|
frame.portrait:SetVertexColor(0.35, 0.35, 0.35, 1.0)
|
|
elseif UnitIsGhost(unit) then
|
|
frame.portrait:SetVertexColor(0.2, 0.2, 0.75, 1.0)
|
|
elseif hpMax > 0 and hp / hpMax <= 0.2 then
|
|
frame.portrait:SetVertexColor(1.0, 0.0, 0.0, 1.0)
|
|
else
|
|
frame.portrait:SetVertexColor(1.0, 1.0, 1.0, 1.0)
|
|
end
|
|
end
|
|
|
|
function BenillaPartyFrame_Update(frame)
|
|
local unit = frame.unit
|
|
if not UnitExists(unit) then
|
|
frame:Hide()
|
|
return
|
|
end
|
|
frame:Show()
|
|
|
|
frame.nameText:SetText(UnitName(unit) or "Unknown")
|
|
|
|
frame.healthBar:SetMinMaxValues(0, UnitHealthMax(unit))
|
|
frame.healthBar:SetValue(UnitHealth(unit))
|
|
|
|
local maxPower = UnitManaMax(unit)
|
|
if maxPower > 0 then
|
|
frame.manaBar:Show()
|
|
local _, token = UnitPowerType(unit)
|
|
local c = BENILLA_POWER_COLORS[token] or BENILLA_POWER_COLORS.MANA
|
|
frame.manaBar:SetStatusBarColor(c.r, c.g, c.b)
|
|
frame.manaBar:SetMinMaxValues(0, maxPower)
|
|
frame.manaBar:SetValue(UnitMana(unit))
|
|
else
|
|
frame.manaBar:Hide()
|
|
end
|
|
|
|
-- Leader + master-looter icons (ref: GetPartyLeaderIndex / GetLootMethod vs own id).
|
|
local id = frame:GetID()
|
|
if GetPartyLeaderIndex() == id then
|
|
frame.leaderIcon:Show()
|
|
else
|
|
frame.leaderIcon:Hide()
|
|
end
|
|
local lootMethod, masterId = GetLootMethod()
|
|
if lootMethod == "master" and masterId == id then
|
|
frame.masterIcon:Show()
|
|
else
|
|
frame.masterIcon:Hide()
|
|
end
|
|
|
|
BenillaPartyFrame_HealthCheck(frame)
|
|
BenillaPartyFrame_UpdatePvP(frame)
|
|
end
|
|
|
|
-- ref PartyMemberFrame_UpdatePvPStatus (PartyMemberFrame.lua l.116-130), verbatim: the
|
|
-- same three branches the unit frames run, but the faction leg draws the GroupFrame art
|
|
-- (UI-Group-PVP-<group>) — only the FFA skull is shared with the big frames, because no
|
|
-- UI-Group-PVP-FFA ships. Decision 0646 §4; closes 0434's named deferral (the icon waited
|
|
-- on UnitFactionGroup, which the app now feeds).
|
|
function BenillaPartyFrame_UpdatePvP(frame)
|
|
local unit = frame.unit
|
|
local factionGroup = UnitFactionGroup(unit)
|
|
if UnitIsPVPFreeForAll(unit) then
|
|
frame.pvpIcon:SetTexture("Interface\\TargetingFrame\\UI-PVP-FFA")
|
|
frame.pvpIcon:Show()
|
|
elseif factionGroup and UnitIsPVP(unit) then
|
|
frame.pvpIcon:SetTexture("Interface\\GroupFrame\\UI-Group-PVP-" .. factionGroup)
|
|
frame.pvpIcon:Show()
|
|
else
|
|
frame.pvpIcon:Hide()
|
|
end
|
|
end
|
|
|
|
-- The ref's <=20% portrait alpha pulse: a 0.5 s-per-leg triangle between 127/255 and 1.
|
|
function BenillaPartyFrame_OnUpdate(frame, elapsed)
|
|
local unit = frame.unit
|
|
if not UnitExists(unit) or not UnitIsConnected(unit) then
|
|
return
|
|
end
|
|
local hp, hpMax = UnitHealth(unit), UnitHealthMax(unit)
|
|
if hpMax > 0 and hp > 0 and hp / hpMax <= 0.2 then
|
|
local t = mod(frame.flashTimer + elapsed, 1.0)
|
|
frame.flashTimer = t
|
|
local a
|
|
if t < 0.5 then
|
|
a = 1.0 - t * (1.0 - 127 / 255) * 2
|
|
else
|
|
a = 127 / 255 + (t - 0.5) * (1.0 - 127 / 255) * 2
|
|
end
|
|
frame.portrait:SetAlpha(a)
|
|
elseif frame.flashTimer ~= 0 then
|
|
frame.flashTimer = 0
|
|
frame.portrait:SetAlpha(1.0)
|
|
end
|
|
end
|
|
|
|
-- The hover tooltip: same law as the unit frames (default corner anchor + SetUnit).
|
|
function BenillaPartyFrame_OnEnter(frame)
|
|
if not UnitExists(frame.unit) then return end
|
|
GameTooltip_SetDefaultAnchor(GameTooltip, frame)
|
|
if GameTooltip:SetUnit(frame.unit) then
|
|
getglobal("GameTooltipTextLeft1"):SetTextColor(GameTooltip_UnitColor(frame.unit))
|
|
end
|
|
end
|
|
|
|
-- The invite driver (ref UIParent.lua): PARTY_INVITE_REQUEST shows the popup with the
|
|
-- inviter's name; PARTY_INVITE_CANCEL hides it.
|
|
function BenillaPartyInviteDriver_OnEvent()
|
|
if event == "PARTY_INVITE_REQUEST" then
|
|
StaticPopup_Show("PARTY_INVITE", arg1)
|
|
elseif event == "PARTY_INVITE_CANCEL" then
|
|
StaticPopup_Hide("PARTY_INVITE")
|
|
end
|
|
end
|
|
|
|
-- The right-click dropdown (decision 0434 phase 5; ref PartyMemberFrame.lua l.369-381)
|
|
-- + the ref's click law (l.226-237): left targets the member, right opens the PARTY
|
|
-- menu seated at the frame's (47, 15).
|
|
function PartyFrameDropDown_OnLoad()
|
|
UIDropDownMenu_Initialize(this, PartyFrameDropDown_Initialize, "MENU")
|
|
end
|
|
|
|
function PartyFrameDropDown_Initialize()
|
|
local dropdown
|
|
if UIDROPDOWNMENU_OPEN_MENU then
|
|
dropdown = getglobal(UIDROPDOWNMENU_OPEN_MENU)
|
|
else
|
|
dropdown = this
|
|
end
|
|
UnitPopup_ShowMenu(dropdown, "PARTY", "party" .. dropdown:GetParent():GetID())
|
|
end
|
|
|
|
function BenillaPartyFrame_OnClick(frame, button)
|
|
if button == "LeftButton" then
|
|
TargetUnit(frame.unit)
|
|
elseif button == "RightButton" then
|
|
ToggleDropDownMenu(1, nil, getglobal(frame:GetName() .. "DropDown"), frame:GetName(), 47, 15)
|
|
end
|
|
end
|
|
]]></Script>
|
|
|
|
<!-- The shared member-frame template — ref PartyFrameTemplates.xml, 128x53 over the 128x64
|
|
UI-PartyFrame art at (0,-2) (the art hangs 13 px below the frame rect, as authored).
|
|
|
|
LAYERING (the ref's law): the ref nests the frame art two anonymous child frames deep so it
|
|
draws OVER the status bars — the bars show through the art's semi-transparent tube windows,
|
|
inset, their ends clipped by the rails. Ours is the UnitFrames.xml idiom, which reaches the
|
|
same place by the ref's OTHER route (its TargetFrame's): a $parentTextureFrame child, with
|
|
OnLoad pushing the bars one frame level BELOW it. Both spend a frame LEVEL, which is the
|
|
point — level is the one key term above the draw layer (decision 0884). Until then this file
|
|
instead leaned on declaring the TextureFrame after the bars, and the old draw key's
|
|
insertion-order tie-break; 0884 pinned the layer as bucket-wide and above the frame, which
|
|
put the bars' ARTWORK fills straight over the BACKGROUND art. Do not go back to declaration
|
|
order. The name and the leader/master/disconnect icons ride in the TextureFrame too (the ref
|
|
keeps them in that nested frame; left below the art, the ring would swallow the leader
|
|
crown). -->
|
|
<!-- frameStrata LOW is the ref's own (`PartyFrameTemplates.xml` l.194) and it is load-bearing,
|
|
not decoration. The panel windows (loot, character, merchant, quest log, …) are MEDIUM, and
|
|
the party frames share the top-left corner with the left-slot panel. Left in the default
|
|
MEDIUM, a party frame's nested HealthBar/ManaBar/TextureFrame children land one frame LEVEL
|
|
above a panel's background region — and level outranks insertion order in the draw key, so
|
|
the party frame draws straight *through* the loot window no matter which was shown last.
|
|
Nothing about raising could have saved it: a raise only reorders within one stratum (wow-re
|
|
`system/ui/scratch/toplevel-raise.md`, dispatched for exactly this). Decision 0597. -->
|
|
<Frame name="BenillaPartyMemberTemplate" virtual="true" hidden="true" frameStrata="LOW">
|
|
<Size><AbsDimension x="128" y="53"/></Size>
|
|
<Layers>
|
|
<Layer level="BACKGROUND">
|
|
<!-- Portrait at the bottom of the stack; the art's round window shows it through. -->
|
|
<Texture name="$parentPortrait">
|
|
<Size><AbsDimension x="37" y="37"/></Size>
|
|
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="7" y="-6"/></Offset></Anchor></Anchors>
|
|
</Texture>
|
|
</Layer>
|
|
</Layers>
|
|
<Frames>
|
|
<StatusBar name="$parentHealthBar">
|
|
<Size><AbsDimension x="70" y="8"/></Size>
|
|
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="47" y="-12"/></Offset></Anchor></Anchors>
|
|
<BarTexture file="Interface\TargetingFrame\UI-StatusBar"/>
|
|
<BarColor r="0" g="1.0" b="0"/>
|
|
</StatusBar>
|
|
<StatusBar name="$parentManaBar">
|
|
<Size><AbsDimension x="70" y="8"/></Size>
|
|
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="47" y="-21"/></Offset></Anchor></Anchors>
|
|
<BarTexture file="Interface\TargetingFrame\UI-StatusBar"/>
|
|
<BarColor r="0" g="0" b="1.0"/>
|
|
</StatusBar>
|
|
<!-- The PARTY-menu dropdown host (ref $parentDropDown): hidden state-holder only —
|
|
the list anchors to the member frame by name. -->
|
|
<Frame name="$parentDropDown" inherits="UIDropDownMenuTemplate" hidden="true">
|
|
<Size><AbsDimension x="10" y="10"/></Size>
|
|
<Anchors><Anchor point="TOP"><Offset><AbsDimension x="-20" y="-10"/></Offset></Anchor></Anchors>
|
|
<Scripts>
|
|
<OnLoad>PartyFrameDropDown_OnLoad()</OnLoad>
|
|
</Scripts>
|
|
</Frame>
|
|
<Frame name="$parentTextureFrame">
|
|
<Size><AbsDimension x="128" y="53"/></Size>
|
|
<Anchors><Anchor point="TOPLEFT"/></Anchors>
|
|
<Layers>
|
|
<Layer level="BACKGROUND">
|
|
<Texture name="$parentTexture" file="Interface\TargetingFrame\UI-PartyFrame">
|
|
<Size><AbsDimension x="128" y="64"/></Size>
|
|
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors>
|
|
</Texture>
|
|
</Layer>
|
|
<Layer level="OVERLAY">
|
|
<FontString name="$parentName" inherits="GameFontNormalSmall" justifyH="LEFT">
|
|
<Anchors><Anchor point="BOTTOMLEFT"><Offset><AbsDimension x="50" y="43"/></Offset></Anchor></Anchors>
|
|
</FontString>
|
|
<Texture name="$parentLeaderIcon" file="Interface\GroupFrame\UI-Group-LeaderIcon" hidden="true">
|
|
<Size><AbsDimension x="16" y="16"/></Size>
|
|
<Anchors><Anchor point="TOPLEFT"/></Anchors>
|
|
</Texture>
|
|
<Texture name="$parentMasterIcon" file="Interface\GroupFrame\UI-Group-MasterLooter" hidden="true">
|
|
<Size><AbsDimension x="16" y="16"/></Size>
|
|
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="32" y="0"/></Offset></Anchor></Anchors>
|
|
</Texture>
|
|
<!-- The group PvP icon, 32x32 TOPLEFT (-9,-15) (ref PartyFrameTemplates.xml
|
|
l.298-309). Texture chosen at runtime — decision 0646 §4. -->
|
|
<Texture name="$parentPVPIcon" hidden="true">
|
|
<Size><AbsDimension x="32" y="32"/></Size>
|
|
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="-9" y="-15"/></Offset></Anchor></Anchors>
|
|
</Texture>
|
|
<Texture name="$parentDisconnect" file="Interface\CharacterFrame\Disconnect-Icon" hidden="true">
|
|
<Size><AbsDimension x="64" y="64"/></Size>
|
|
<Anchors><Anchor point="LEFT"><Offset><AbsDimension x="-7" y="-1"/></Offset></Anchor></Anchors>
|
|
</Texture>
|
|
</Layer>
|
|
</Layers>
|
|
</Frame>
|
|
</Frames>
|
|
<Scripts>
|
|
<OnLoad>BenillaPartyFrame_OnLoad(this)</OnLoad>
|
|
<OnEvent>BenillaPartyFrame_OnEvent(this)</OnEvent>
|
|
<OnUpdate>BenillaPartyFrame_OnUpdate(this, arg1)</OnUpdate>
|
|
<OnEnter>BenillaPartyFrame_OnEnter(this)</OnEnter>
|
|
<OnLeave>GameTooltip:FadeOut()</OnLeave>
|
|
<OnClick>BenillaPartyFrame_OnClick(this, arg1)</OnClick>
|
|
</Scripts>
|
|
</Frame>
|
|
|
|
<!-- The four instances — frame 1 at the ref's (10,-128); 2-4 cascade at the no-pet stride
|
|
(see the header note; the pet-frame anchor law returns with phase 4). -->
|
|
<Frame name="PartyMemberFrame1" inherits="BenillaPartyMemberTemplate" parent="UIParent" id="1">
|
|
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="10" y="-128"/></Offset></Anchor></Anchors>
|
|
</Frame>
|
|
<Frame name="PartyMemberFrame2" inherits="BenillaPartyMemberTemplate" parent="UIParent" id="2">
|
|
<Anchors><Anchor point="TOPLEFT" relativeTo="PartyMemberFrame1" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-10"/></Offset></Anchor></Anchors>
|
|
</Frame>
|
|
<Frame name="PartyMemberFrame3" inherits="BenillaPartyMemberTemplate" parent="UIParent" id="3">
|
|
<Anchors><Anchor point="TOPLEFT" relativeTo="PartyMemberFrame2" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-10"/></Offset></Anchor></Anchors>
|
|
</Frame>
|
|
<Frame name="PartyMemberFrame4" inherits="BenillaPartyMemberTemplate" parent="UIParent" id="4">
|
|
<Anchors><Anchor point="TOPLEFT" relativeTo="PartyMemberFrame3" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-10"/></Offset></Anchor></Anchors>
|
|
</Frame>
|
|
|
|
<!-- The invite event driver (hidden; the DeathFrame driver pattern). -->
|
|
<Frame name="BenillaPartyInviteDriver" parent="UIParent" hidden="true">
|
|
<Size><AbsDimension x="1" y="1"/></Size>
|
|
<Anchors><Anchor point="TOPLEFT"/></Anchors>
|
|
<Scripts>
|
|
<OnLoad>
|
|
this:RegisterEvent("PARTY_INVITE_REQUEST")
|
|
this:RegisterEvent("PARTY_INVITE_CANCEL")
|
|
</OnLoad>
|
|
<OnEvent>BenillaPartyInviteDriver_OnEvent()</OnEvent>
|
|
</Scripts>
|
|
</Frame>
|
|
</Ui>
|