- a dying body lands with a sound: the `$DTH` marker makes three calls in the reference (`0x624a94`) and benilla had built only the middle one, so the screen shook and nothing landed; the thud is a two-axis join — size class against terrain sound, through `DeathThudLookups.dbc` to a land or water kit — behind exactly three gates: more than 2.0 yd of liquid over the feet is complete silence, a size class outside 0..=4, and no terrain, no row or a kit of 0; it plays on bus 0, uncapped, so a battlefield's worth of bodies all land — the shake is the rare thing (49 of 430 models name a preset), the thud the universal one (329 key a `$DTH`, players included); the size axis had sat in our `CreatureDisplayInfo` schema labelled a string column 5875 does not have, and `StringLookups` stays unparsed on purpose — 9 rows benilla already resolves (1866) - twelve faux-scroll lists showed their bar, moved their thumb and never moved their list: the reference's kit writes `frame.offset` from one handler the OWNER declares, and ours were wired to a `frame.updateFunc` field the reference does not have — Skill, Craft, TradeSkill, ScriptLog, the auction and the social panes are rewired, and a gate fails any faux frame without a handler of its own, because a list only scrolls when something drives it (1868); and the macro window's "Change Name/Icon" raised on a nil offset: `MacroPopupScrollFrame` inherits a template the manifest never loaded, and a missing template is a warning, so the frame was built BARE — no scroll bar, no scripts, no `offset = 0` — and the reference's offset read has no `or 0` cushion; the line is in the manifest, and a static gate fails any `inherits=` the manifest declares nowhere (1862) - the character geoset selector's missing eighth branch is the tabard designer: B6 of `0x477520` is gated on "the guild registrar's tabard designer is open", not an ItemDisplayInfo column, and wears the tabard flap with an EMPTY tabard slot; dormant until `TabardFrame` migrates, but reading the whole function turned up three branches wrong since their first pass: B4-short never disabled [501,599], so the bare foot — a real submesh on 11 of the 18 character models — rendered inside every boot; B3 asked "is a chest equipped?" where the reference asks whether anything but the shirt paints the ArmLower tile, wrong more often than right (533 of 637 chest displays leave it empty, 566 of 570 wrist displays fill it); and B7 had no tabard guard, an ungated doublet arm, and a leg arm read off chest-or-legs where the reference reads the chest's bit alone (1864) - a GameObject's display sounds have one trigger and two lanes: `GameObjectDisplayInfo.Sound[0..9]` has one reader (`0x5f4010`), reached only from the anim-event dispatcher, so benilla's state-transition arm — 19 Open and 4 Close rows the reference leaves silent, 80 Open and 38 Close doubled against the clip's own `$GO1`/`$GO3` — is deleted; and the kit's `0x200` flag is a LANE SELECT, not a loop flag: set means the ambient pool, which every campfire, brazier, torch and fountain names (37 live slots), and which had been starting untracked forever-channels (1867); and `WOW_PROBE_SERVICE=1` reads the NPC-service ladder back off a live server — four real NPCs, reporting the arm taken, the opcode sent and the window opened — with every hop inside the reference's own service reach, after a first run parked ~29 yd from Deputy Willem and blamed the client for a dropped packet (1865) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
875 lines
63 KiB
XML
875 lines
63 KiB
XML
<Ui>
|
||
<!--
|
||
benilla's Skills tab (decision 0437 phase 4): the 1.12 `SkillFrame`, re-expressed from the
|
||
reference FrameXML `SkillFrame.{xml,lua}` (session scratchpad `ref-ui/`, decision 0246
|
||
discipline — never committed) onto our own engine/feeds. Geometry/art-paths below are QUOTED
|
||
from the ref (line citations inline, into that same `SkillFrame.xml`/`.lua`); the Lua is
|
||
the ref's logic turned onto benilla's Era API (`GetNumSkillLines`/`GetSkillLineInfo`/
|
||
`Expand`/`CollapseSkillHeader`/`SetSelectedSkill`/`GetSelectedSkill`, decision 0437's skills
|
||
seam, `crates/benilla-ui/src/script/skills.rs`, built alongside this file).
|
||
|
||
A CHILD PAGE of `CharacterFrame` (ref: `parent="CharacterFrame"`, `id="4"` — ours too, since
|
||
the Reputation page landed and took slot 3 back), shown/
|
||
hidden by `CharacterFrame_ShowSubFrame` exactly like `PaperDollFrame` — but NOT a
|
||
physically nested `<Frame>` the way PaperDollFrame is: PaperDollFrame is declared INSIDE
|
||
CharacterFrame.xml's own `<Frames>` tree (a real engine parent/child), while this page is a
|
||
SEPARATE file's top-level `<Frame>` (CharacterFrame.xml is shared-tree with another session
|
||
this pass, so only its tab machinery is touched here — not its frame tree). `parent=` really attaches
|
||
(decision 1734; the loader resolves the name globally at load and it wins over the enclosing
|
||
element — `shipped_xml_tests::every_declared_parent_really_attaches` asserts it on the loaded
|
||
tree). The line above used to say the attribute was read nowhere, which was true once and had
|
||
outlived itself. Position still rides `<Anchors relativeTo="CharacterFrame">` — a NAMED
|
||
lookup that works regardless of tree position, the same mechanism every sibling-anchor in
|
||
this codebase uses, kept because it is the geometry this page ships with — loaded right after
|
||
`CharacterFrame.xml` in the load list so it
|
||
paints ON TOP of it (later file = higher z, the established house convention every top-level
|
||
window already relies on implicitly). Because a true engine Hide-cascade doesn't reach a
|
||
non-child, `CharacterFrame.xml`'s own `CharacterFrame_OnHide` was extended (its own
|
||
header comment) to loop-hide every `CHARACTERFRAME_SUBFRAMES` entry — the fix this
|
||
page's non-nested shape requires, done once so later non-nested tabs (Pet/Reputation/Honor)
|
||
inherit it for free.
|
||
|
||
NO OWN PORTRAIT (matches the ref: `ref-ui/SkillFrame.xml` l.130-213 draws no portrait Texture
|
||
at all): the shared quadrant background art below (`UI-Character-General-TopLeft/TopRight`,
|
||
the SAME "General" variant the ref uses, l.136-159) carries the SAME baked-in portrait-ring
|
||
cutout every PaperDollInfoFrame quadrant variant shares, so `CharacterFrame`'s own
|
||
portrait/name/level (drawn at a lower z, underneath) shows through unchanged — exactly the
|
||
ref's own real-client compositing (SkillFrame is a nested child there too, relying on the
|
||
same cutout rather than redrawing the portrait itself).
|
||
|
||
THE DETAIL PANE NESTS, as the ref's does. This file used to carry the FLAT-layout claim —
|
||
"only a plain child `<Frame>` loses [its Layers]" — quoted from TrainerFrame.xml. That claim
|
||
is FALSE and was retracted in decision 1517, which corrected TrainerFrame/TradeSkillFrame/
|
||
CraftFrame and missed this file: a fourth restatement, still asserting the constraint five
|
||
weeks after it was disproved. A runtime-shown child `<Frame>` renders its own `<Layers>`
|
||
FontStrings in this engine, and the ref's `SkillDetailScrollFrame` +
|
||
`SkillDetailScrollChildFrame` are therefore built here verbatim (below).
|
||
1517 §2 says a retracted reason is not by itself cause to move approved geometry — so the
|
||
mover here is not the retraction, it is DEMAND: pfUI's `skins/blizzard/character.lua` l.299-320
|
||
indexes `SkillDetailScrollFrameScrollBar`, `SkillDetailScrollChildFrame`, `SkillDetailCostText`
|
||
and `SkillDetailStatusBarUnlearnButton` by name, and its own skin then hides the scroll child
|
||
and reparents the three detail regions onto the scroll frame — i.e. it flattens the pane
|
||
ITSELF, which it can only do if the pane is nested to begin with. The pane also could not
|
||
keep its old size inside the ref's 296-wide viewport: the old detail bar reused the 271-wide
|
||
LIST-ROW template, whose 281-wide Border put the abandon button at x 312..344 against a
|
||
viewport ending at 318 — 26 of its 32 px clipped. So the detail bar is now the ref's OWN
|
||
declaration (211×15, Border 220×32, centred under the list) rather than a borrowed list row,
|
||
which is both what fits and what the real client draws. LOOK CHANGE, called out for the
|
||
director: the detail bar narrows and centres, and the ref's two `UI-ClassTrainer-ScrollBar`
|
||
trough textures now flank the pane's right edge (the ref draws them unconditionally, bar or
|
||
no bar). Reverting is one anchor + one Size.
|
||
|
||
v1 DEVIATIONS (each re-cited at its own site below):
|
||
1. THE DETAIL PANE OMITS THE TRAINING-POINT SPEND ROW, and nothing else. Its structure
|
||
(`SkillDetailScrollFrame` → `SkillDetailScrollChildFrame` → `SkillDetailCostText` +
|
||
`SkillDetailDescriptionText` + `SkillDetailStatusBar` → `$parentUnlearnButton`) is the
|
||
ref's, verbatim. What stays OUT is the ref's `$parentLeftArrow`/`$parentRightArrow`/
|
||
`$parentLearnSkillButton` trio and the `AddSkillUp`/`RemoveSkillUp`/`BuySkillTier`
|
||
calls behind them — driven by `stepCost`/`rankCost`/`numTempPoints`, which
|
||
`GetSkillLineInfo` always reports nil/0 (0437's own named out-of-scope: 1.12 training
|
||
points are dead data).
|
||
`SkillDetailCostText` IS built, because the ref's own no-cost path is a real path, not
|
||
a stub: ref `SkillFrame.lua` l.361 `SkillDetailCostText:Hide()` is the branch a live
|
||
1.12 server always lands on, and `BenillaSkillFrame_UpdateDetail` takes exactly that
|
||
branch every time. An empty hidden FontString here is the reference's own behaviour,
|
||
not a name published to satisfy a lookup (1189/1203).
|
||
The ABANDON BUTTON is real: `SkillDetailStatusBarUnlearnButton` (the ref's
|
||
`$parentUnlearnButton`) → the `UNLEARN_SKILL` confirm → `AbandonSkill` →
|
||
`CMSG_UNLEARN_SKILL`; the isAbandonable predicate is `SkillRaceClassInfo.flags & 0x20`
|
||
— the server's own gate, real 5875 data: primary professions only. It used to be
|
||
published as `SkillDetailUnlearnButton`, a name the reference does not have, while the
|
||
comment directly above it cited `$parentUnlearnButton` correctly — the fifth instance
|
||
this session of right-behaviour-under-a-private-name (1189).
|
||
2. NO SORT CHECKBOX (ref l.215-241's own XML-commented-out "Replace once code is ready..."
|
||
`SkillSortButton`): the ref itself ships this dead/commented, so there is nothing to
|
||
transcribe (TradeSkillFrame.xml's own "ref's own dead code is dropped" precedent).
|
||
3. NO ACCEPT BUTTON (ref l.318-337's `SkillFrameAcceptButton`) — it is XML-commented dead
|
||
in the ref, and it backs the training-point economy this pane doesn't ship (deviation 1),
|
||
so there is nothing to transcribe. Its neighbour `SkillFrameCancelButton` (l.339-357) is
|
||
NOT dead and IS built: the ref's comment closes at l.337, one line above it, and the real
|
||
client draws a CLOSE button in the page's bottom-right seat. This list used to claim both
|
||
were commented out, and that misread is exactly why that seat rendered empty — decision
|
||
1496. Only its `CancelSkillUps()` call drops (deviation 1's dead economy again); the two
|
||
hides are transcribed.
|
||
4. THE RANK TEXT FORMAT IS THE REF'S BYTE-EXACT ONE, not the task brief's own paraphrase:
|
||
`ref-ui/SkillFrame.lua` l.178-186 builds `rank .. " (" .. color .. modifier .. close ..
|
||
")/" .. max` (e.g. "57 (|cff20ff20+3|r)/75") — transcribed verbatim (the
|
||
reference file is the authority on the tuple/format, the brief's prose is a summary).
|
||
5. NO FILLBAR (ref's `$parentFillBar`, driven by `numTempPoints`): [`GetSkillLineInfo`]
|
||
always reports `numTempPoints = 0` (skills.rs's own module doc — 1.12 training points are
|
||
dead data), so the fill bar could never show — dropped outright, `TradeSkillFrame.xml`'s
|
||
OWN `BenillaTradeSkillRankFrame` (the identical StatusBar shape) already sets this local
|
||
precedent for the same reason.
|
||
6. NO HOVER TOOLTIP on a row: the ref's own `SkillFrame.lua` calls `GameTooltip` NOWHERE
|
||
(grepped the full reference file) — a skill line is pure descriptor state, nothing to
|
||
preview. Unlike Trainer/TradeSkill, this window needs no `GameTooltip:Set*Item` channel.
|
||
7. `LockHighlight`/`UnlockHighlight` ENGINE GAP (TalentFrame.xml/TradeSkillFrame.xml's own
|
||
"no engine equivalent" posture, grepped `benilla-ui/src/script/button.rs` — ships
|
||
texture-pairs/SetText/Enable/Disable/RegisterForClicks/SetButtonState/Click only): the
|
||
persistent selection glow is `SkillHighlight`, the separate overlay Frame
|
||
Trainer/TradeSkillFrame already use, moved onto the selected row's StatusBar.
|
||
8. GlobalStrings this window itself needs: NONE beyond the tab label `SKILLS` (already
|
||
declared in CharacterFrame.xml, quoted there byte-exact with its GlobalStrings.lua line
|
||
cite) — the ref's own `SkillFrame.lua` reads no other GlobalString.
|
||
|
||
Rows repaint on `SKILL_LINES_CHANGED` (registered here; `crates/benilla/src/ui_char.rs`'s
|
||
`watch_skill_ups`/`feed_skills` already fire it) and on `OnShow` (ref `SkillFrame_OnShow`,
|
||
l.4-6). The list is the house faux-scroll kit (ScrollTemplates.xml, the TrainerFrame/
|
||
TradeSkillFrame precedent) over 12 fixed row slots (ref `SKILLS_TO_DISPLAY = 12`,
|
||
`SkillFrame.lua:1` — the ref's own row count, and this page shares the ref's own 384×512
|
||
coordinate space since it fills the identical CharacterFrame page area).
|
||
-->
|
||
<Script><![CDATA[
|
||
-- ── Constants (ref SkillFrame.lua:1-2) ──────────────────────────────────────────────────────
|
||
-- SKILLS_TO_DISPLAY is the reference's own GLOBAL and is published as one. It was a chunk
|
||
-- local named SKILLS_TO_DISPLAY with the real name in a trailing comment — the
|
||
-- value transcribed, the NAME kept private, which is the same shape that cost us
|
||
-- BlackoutWorld and the five SkillFrame* children. Addons read it: pfUI's character skin
|
||
-- loops `for i = 1, SKILLS_TO_DISPLAY` over the row labels
|
||
-- (skins/blizzard/character.lua:277) and died on "'for' limit must be a number".
|
||
-- 12 is honest here rather than copied — this file declares exactly 12 SkillTypeLabel rows.
|
||
SKILLS_TO_DISPLAY = 12
|
||
local SKILLFRAME_SKILL_HEIGHT = 15 -- SKILLFRAME_SKILL_HEIGHT
|
||
|
||
-- GlobalStrings (ref GlobalStrings.lua:3478), chunk-local per the codebase idiom — safe
|
||
-- because only THIS chunk's functions read it; the nil-"All" trap (TradeSkillFrame.xml's
|
||
-- deviation notes) is the inline-XML-handler case, and no inline handler references it.
|
||
-- Its earlier ABSENCE here made format() throw in UpdateDetail on every row selection —
|
||
-- half of the 2026-07-17 "tabs are flaky" report (the silent-error half).
|
||
local SKILL_DESCRIPTION = "|cffffffff%s|r %s"
|
||
local UNLEARN_SKILL = "Do you want to unlearn %s?" -- GlobalStrings.lua:4446
|
||
local UNLEARN = "Unlearn" -- GlobalStrings.lua:4445
|
||
local UNLEARN_SKILL_TOOLTIP = "Unlearn this profession" -- GlobalStrings.lua:4447
|
||
|
||
-- Paint the rank StatusBar `bar` + its `SkillName`/`SkillRank` FontStrings for one skill-line
|
||
-- ENTRY row (never a header — callers guard that): the ref's own bar-fill + rank-text half of
|
||
-- `SkillFrame_SetStatusBar` (l.76-187) and the detail's twin `SkillDetailFrame_SetStatusBar`
|
||
-- (l.161-187, l.370-399) — the SAME formatting either pane uses, factored once here since our
|
||
-- minimal detail pane (deviation 1) needs nothing else from that function.
|
||
function BenillaSkillFrame_PaintBar(bar, skillName, skillRank, skillModifier, skillMaxRank)
|
||
local nameText = getglobal(bar:GetName() .. "SkillName")
|
||
local rankText = getglobal(bar:GetName() .. "SkillRank")
|
||
-- The trough behind the fill (ref `$parentBackground`), recoloured per branch alongside
|
||
-- the fill itself — ref SkillFrame.lua:158 (normal) and :167 (proficiency), and the
|
||
-- detail pane's identical pair at :356/:376. The ref sets the normal-skill pair BEFORE
|
||
-- its `skillMaxRank` gate and lets the proficiency arm overwrite it; setting each arm's
|
||
-- own pair here is the same result with no dead write. The ref's THIRD writer of this
|
||
-- texture — the `skillCostType == 1/2/3` green/yellow/red block at :96-111, and the
|
||
-- `stepCost` "Learn <skill>" gray at :126 — is unreachable for us and would be
|
||
-- overwritten here even if it weren't: `stepCost`/`rankCost` are always nil and
|
||
-- `numTempPoints` always 0 (skills.rs's module doc — dead 1.12 data, deviation 1/5), so
|
||
-- every entry row takes the ref's own `else -- Normal skill` arm.
|
||
local bgTexture = getglobal(bar:GetName() .. "Background")
|
||
nameText:SetText(skillName)
|
||
nameText:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b)
|
||
rankText:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
|
||
if skillMaxRank == 1 then
|
||
-- ref SkillFrame.lua:161-167 verbatim: "If max rank in a skill is 1 assume that
|
||
-- its a proficiency" — a FULL gray bar and NO rank text. Two kinds of line land
|
||
-- here, and the ref can't tell them apart because it doesn't need to: the armor
|
||
-- proficiencies, which the server really does report as 1/1, and the single-rank
|
||
-- lines (class skills, Dual Wield, racials, the per-mount riding lines) whose
|
||
-- `skillMaxRank` the engine already overrode to 1 off
|
||
-- `SkillRaceClassInfo.flags & 0x400` (skills.rs's `SkillEntry::mono`) — which is
|
||
-- why a hunter's `Beast Mastery 300/300` draws gray and numberless here, exactly
|
||
-- as it does in the real client.
|
||
bar:SetMinMaxValues(0, 1)
|
||
bar:SetValue(1)
|
||
bar:SetStatusBarColor(0.5, 0.5, 0.5)
|
||
rankText:SetText("")
|
||
bgTexture:SetVertexColor(1.0, 1.0, 1.0, 0.5)
|
||
elseif skillMaxRank == 0 then
|
||
-- Not reachable off a live server (a line the player HAS always carries a max ≥ 1)
|
||
-- and the ref leaves this case to fall through its own if/elseif untouched —
|
||
-- which, on a recycled row, would leave the PREVIOUS skill's bar and rank text
|
||
-- sitting there. We blank instead: a stale-state hole is a quirk, not behaviour.
|
||
bar:SetMinMaxValues(0, 1)
|
||
bar:SetValue(0)
|
||
bar:SetStatusBarColor(0, 0, 0, 0)
|
||
rankText:SetText("")
|
||
-- back to the template's own declared base, so a recycled row shows a neutral empty
|
||
-- trough rather than the previous skill's blue or white. The base lives in the
|
||
-- TEXEL (the template's `<Color 1,1,1,0.2>`), so restoring it means an IDENTITY
|
||
-- vertex colour — writing 0.2 here would multiply it to 0.04 (decision 1101).
|
||
bgTexture:SetVertexColor(1.0, 1.0, 1.0, 1.0)
|
||
else
|
||
bar:SetStatusBarColor(0.0, 0.0, 1.0, 0.5)
|
||
bgTexture:SetVertexColor(0.0, 0.0, 0.75, 0.5)
|
||
bar:SetMinMaxValues(0, skillMaxRank)
|
||
bar:SetValue(skillRank)
|
||
-- the ref's rank-text law (SkillFrame.lua:178-186), re-expressed here (this file's
|
||
-- header comment, deviation 4).
|
||
if skillModifier == 0 then
|
||
rankText:SetText(skillRank .. "/" .. skillMaxRank)
|
||
else
|
||
local color = RED_FONT_COLOR_CODE
|
||
if skillModifier > 0 then
|
||
color = GREEN_FONT_COLOR_CODE .. "+"
|
||
end
|
||
rankText:SetText(skillRank .. " (" .. color .. skillModifier .. FONT_COLOR_CODE_CLOSE .. ")/" .. skillMaxRank)
|
||
end
|
||
end
|
||
end
|
||
|
||
-- Fill the detail pane (deviation 1) for the current `GetSelectedSkill()`, or blank it
|
||
-- when nothing is selected / the selection isn't a visible entry. The description body is
|
||
-- the ref's own (ref SkillFrame.lua l.211-217 hide/show alongside the bar; l.262 the
|
||
-- SKILL_DESCRIPTION format): `skillType` stays "" in EVERY reachable 1.12 branch — the
|
||
-- ref's single assignment ("Tertiary Skill:") is commented out in the reference itself —
|
||
-- so the format's first slot renders empty, byte-faithful. The unlearn button rides the
|
||
-- same fill (ref l.220-226): shown only for an abandonable line, carrying the name the
|
||
-- confirm popup formats and the index its accept abandons.
|
||
function BenillaSkillFrame_UpdateDetail()
|
||
local bar = getglobal("SkillDetailStatusBar")
|
||
local desc = getglobal("SkillDetailDescriptionText")
|
||
local unlearn = getglobal("SkillDetailStatusBarUnlearnButton")
|
||
-- The ref's own no-cost branch (ref SkillFrame.lua l.361), taken unconditionally:
|
||
-- stepCost/rankCost are always nil on a 1.12 server (deviation 1). Hidden here rather
|
||
-- than left `hidden="true"` from XML so the branch is visible as a branch — the ref
|
||
-- shows this string on the paths we don't have, and this is where it would be re-shown.
|
||
getglobal("SkillDetailCostText"):Hide()
|
||
local index = GetSelectedSkill()
|
||
if index == 0 then
|
||
bar:Hide()
|
||
desc:Hide()
|
||
unlearn:Hide()
|
||
return
|
||
end
|
||
local skillName, isHeader, _, skillRank, _, skillModifier, skillMaxRank, isAbandonable = GetSkillLineInfo(index)
|
||
if not skillName or isHeader then
|
||
bar:Hide()
|
||
desc:Hide()
|
||
unlearn:Hide()
|
||
return
|
||
end
|
||
bar:Show()
|
||
BenillaSkillFrame_PaintBar(bar, skillName, skillRank, skillModifier, skillMaxRank)
|
||
if isAbandonable then
|
||
unlearn.skillName = skillName
|
||
unlearn.index = index
|
||
unlearn:Show()
|
||
else
|
||
unlearn:Hide()
|
||
end
|
||
local skillType = ""
|
||
local skillDescription = select(13, GetSkillLineInfo(index)) or ""
|
||
desc:SetText(format(SKILL_DESCRIPTION, skillType, skillDescription))
|
||
desc:Show()
|
||
end
|
||
|
||
-- ── The abandon confirm + the unlearn button's handlers ──────────────────────────────────
|
||
-- The dialog is ref StaticPopup.lua:1121-1133 verbatim (minus the vestigial TEXT()
|
||
-- wrapper); its OnAccept receives dialog.data — the visible index the button stashed.
|
||
-- CANCEL stays the bare GlobalStrings global (DeathFrame.xml's own convention — the app
|
||
-- loads the real GlobalStrings.lua before any window file). The handlers are chunk
|
||
-- functions, NOT inline bodies, so the chunk-local strings above are visible to them
|
||
-- (the nil-"All" chunk-boundary rule, TradeSkillFrame.xml's deviation notes).
|
||
StaticPopupDialogs["UNLEARN_SKILL"] = {
|
||
text = UNLEARN_SKILL,
|
||
button1 = UNLEARN,
|
||
button2 = CANCEL,
|
||
OnAccept = function(index)
|
||
AbandonSkill(index)
|
||
end,
|
||
timeout = 60,
|
||
exclusive = 1,
|
||
whileDead = 1,
|
||
showAlert = 1,
|
||
hideOnEscape = 1
|
||
}
|
||
|
||
function BenillaSkillUnlearnButton_OnClick(btn)
|
||
local dialog = StaticPopup_Show("UNLEARN_SKILL", btn.skillName)
|
||
if dialog then
|
||
dialog.data = btn.index
|
||
end
|
||
end
|
||
|
||
function BenillaSkillUnlearnButton_OnEnter(btn)
|
||
GameTooltip:SetOwner(btn, "ANCHOR_RIGHT")
|
||
GameTooltip:SetText(UNLEARN_SKILL_TOOLTIP)
|
||
end
|
||
|
||
-- Paint list slot `i` (1..12) from the visible row at `index` (ref SkillFrame_SetStatusBar,
|
||
-- l.24-188 — the header branch, l.55-69, and the entry branch, l.76-187, collapsed: the
|
||
-- skillCostType coloring + stepCost/rankCost training-up arrows never apply here, since
|
||
-- GetSkillLineInfo always reports them nil/0, this file's header comment deviation 1).
|
||
function BenillaSkillFrame_SetRow(i, index, numRows)
|
||
local bar = getglobal("SkillRankFrame" .. i)
|
||
local label = getglobal("SkillTypeLabel" .. i)
|
||
|
||
if index > numRows then
|
||
bar:Hide()
|
||
bar.skillIndex = nil
|
||
label:Hide()
|
||
label.skillIndex = nil
|
||
return
|
||
end
|
||
|
||
local skillName, isHeader, isExpanded, skillRank, _, skillModifier, skillMaxRank = GetSkillLineInfo(index)
|
||
|
||
if isHeader then
|
||
bar:Hide()
|
||
bar.skillIndex = nil
|
||
label:Show()
|
||
label.skillIndex = index
|
||
label:SetText(skillName)
|
||
if isExpanded then
|
||
label:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-Up")
|
||
else
|
||
label:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-Up")
|
||
end
|
||
return
|
||
end
|
||
|
||
label:Hide()
|
||
label.skillIndex = nil
|
||
bar:Show()
|
||
bar.skillIndex = index
|
||
BenillaSkillFrame_PaintBar(bar, skillName, skillRank, skillModifier, skillMaxRank)
|
||
end
|
||
|
||
-- The list page (ref SkillFrame_UpdateSkills, l.402-448 — the dead
|
||
-- `UnitCharacterPoints("player")`/`SkillFrame.UpdatedSkillPoints` read, l.437-440, whose
|
||
-- result nothing downstream ever consumes even in the ref itself, is dropped — the
|
||
-- TradeSkillFrame.xml "ref's own dead code is dropped" precedent).
|
||
-- The scroll frame's `<OnVerticalScroll>` is its own chunk and cannot see this file's
|
||
-- `local SKILLFRAME_SKILL_HEIGHT`, so the pitch is handed over here rather than written as
|
||
-- a literal in the XML (1868; the trainer paid for this lesson first, in 1860).
|
||
function BenillaSkillList_OnVerticalScroll()
|
||
FauxScrollFrame_OnVerticalScroll(SKILLFRAME_SKILL_HEIGHT, BenillaSkillFrame_Update)
|
||
end
|
||
|
||
function BenillaSkillFrame_Update()
|
||
local numRows = GetNumSkillLines()
|
||
local scrollFrame = getglobal("SkillListScrollFrame")
|
||
FauxScrollFrame_Update(scrollFrame, numRows, SKILLS_TO_DISPLAY, SKILLFRAME_SKILL_HEIGHT)
|
||
-- Our trough follows the bar the reference's `_Update` just decided about; nothing in
|
||
-- its kit shows one, because the reference has no trough at all (1860).
|
||
BenillaScrollTrough_Follow("SkillListScrollFrame")
|
||
local offset = FauxScrollFrame_GetOffset(scrollFrame)
|
||
|
||
local highlight = getglobal("SkillHighlight")
|
||
highlight:Hide()
|
||
local selected = GetSelectedSkill()
|
||
|
||
for i = 1, SKILLS_TO_DISPLAY do
|
||
local index = i + offset
|
||
BenillaSkillFrame_SetRow(i, index, numRows)
|
||
if selected == index and index <= numRows then
|
||
highlight:SetPoint("TOPLEFT", getglobal("SkillRankFrame" .. i), "TOPLEFT", -5, 0)
|
||
highlight:Show()
|
||
end
|
||
end
|
||
|
||
-- The collapse-all tab's +/- icon (ref l.417-429's own numHeaders/notExpanded scan).
|
||
local allExpanded = true
|
||
for i = 1, numRows do
|
||
local _, isHeader, isExpanded = GetSkillLineInfo(i)
|
||
if isHeader and not isExpanded then
|
||
allExpanded = false
|
||
end
|
||
end
|
||
local collapseAll = getglobal("SkillFrameCollapseAllButton")
|
||
if numRows == 0 then
|
||
collapseAll:Disable()
|
||
else
|
||
collapseAll:Enable()
|
||
end
|
||
if allExpanded then
|
||
collapseAll.collapsed = nil
|
||
collapseAll:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-Up")
|
||
else
|
||
collapseAll.collapsed = 1
|
||
collapseAll:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-Up")
|
||
end
|
||
|
||
BenillaSkillFrame_UpdateDetail()
|
||
BenillaSkillFrameExpandButtonFrame_Fit()
|
||
end
|
||
|
||
-- A rank-bar click selects it (ref SkillBar_OnClick, l.450-455).
|
||
function BenillaSkillRankFrame_OnClick(bar)
|
||
local index = bar.skillIndex
|
||
if not index then
|
||
return
|
||
end
|
||
SetSelectedSkill(index)
|
||
BenillaSkillFrame_Update()
|
||
end
|
||
|
||
-- A header click folds/unfolds its group (ref SkillLabelTemplate's own OnClick, l.72-80).
|
||
function BenillaSkillTypeLabel_OnClick(label)
|
||
local index = label.skillIndex
|
||
if not index then
|
||
return
|
||
end
|
||
local _, _, isExpanded = GetSkillLineInfo(index)
|
||
if isExpanded then
|
||
CollapseSkillHeader(index)
|
||
-- A fold reshuffles visible indices — an UNLEARN_SKILL confirm armed for a row
|
||
-- that no longer holds the selection must not fire against the wrong line (ref
|
||
-- SkillLabelTemplate's own OnClick, ref SkillFrame.xml l.72-78).
|
||
local dialog = StaticPopup_FindVisible("UNLEARN_SKILL")
|
||
if dialog and dialog.data ~= GetSelectedSkill() then
|
||
StaticPopup_Hide("UNLEARN_SKILL")
|
||
end
|
||
else
|
||
ExpandSkillHeader(index)
|
||
end
|
||
BenillaSkillFrame_Update()
|
||
end
|
||
|
||
-- The collapse-all tab (ref SkillFrameCollapseAllButton's own isExpanded flag, l.303-309,
|
||
-- driven the TrainerFrame.xml BenillaTrainerCollapseAllButton way since this engine's
|
||
-- CollapseSkillHeader(0)/ExpandSkillHeader(0) already fold/unfold every group at once).
|
||
function BenillaSkillFrameCollapseAllButton_OnClick()
|
||
local b = getglobal("SkillFrameCollapseAllButton")
|
||
if b.collapsed then
|
||
ExpandSkillHeader(0)
|
||
else
|
||
CollapseSkillHeader(0)
|
||
FauxScrollFrame_SetOffset(getglobal("SkillListScrollFrame"), 0)
|
||
end
|
||
BenillaSkillFrame_Update()
|
||
end
|
||
|
||
-- The tab is as wide as its own label (ref SkillFrameExpandButtonFrame's OnLoad, l.312-316:
|
||
-- SetWidth(SkillFrameCollapseAllButton:GetTextWidth()+45)) — the 45 is the two 8px caps plus
|
||
-- the label's 25px seat plus the margin the ref leaves before the right cap, and the middle
|
||
-- slab stretches into whatever that leaves off its own two anchors.
|
||
--
|
||
-- Run from BOTH the ref's own OnLoad and every Update, because a measure here is not the
|
||
-- ref's synchronous one: benilla seats the VM's font engine at the frame boundary
|
||
-- (`ui_script::extract`, ahead of the tick), and XML load happens BEFORE any frame — so the
|
||
-- OnLoad call reads 0 and the tab would keep a 45px stump forever. The zero guard is what
|
||
-- makes the pair safe: an unmeasured call leaves the width alone rather than squashing the
|
||
-- tab, and the first Update after the atlas exists fits it. (The house's own preference is
|
||
-- two opposing anchors and no Lua width — UiPanels.xml's tab-highlight note — but a span
|
||
-- can only be resolved from two anchors when both edges are frames; a text width has to be
|
||
-- asked for.)
|
||
function BenillaSkillFrameExpandButtonFrame_Fit()
|
||
local label = getglobal("SkillFrameCollapseAllButton")
|
||
local w = label:GetTextWidth()
|
||
if w and w > 0 then
|
||
getglobal("SkillFrameExpandButtonFrame"):SetWidth(w + 45)
|
||
end
|
||
end
|
||
|
||
-- The page's own CLOSE (ref SkillFrameCancelButton's OnClick, l.350-356). The ref's
|
||
-- CancelSkillUps() drops out with the training-point economy this pane doesn't ship (this
|
||
-- file's header comment deviation 1); the two hides are the ref's own, in its own order —
|
||
-- the page first, then the window (CharacterFrame_OnHide's subframe loop would reach this
|
||
-- page anyway, but the ref hides it explicitly and so do we).
|
||
function BenillaSkillFrameCancelButton_OnClick()
|
||
getglobal("SkillFrame"):Hide()
|
||
HideUIPanel(getglobal("CharacterFrame"))
|
||
end
|
||
|
||
-- The window's wheel handler (bubbled up the parent chain from a row) → one row via the faux
|
||
-- kit (TrainerFrame.xml's own note: the engine bubbles a spin up the parent chain).
|
||
function BenillaSkillFrame_OnMouseWheel(delta)
|
||
BenillaFauxScrollFrame_OnMouseWheel(getglobal("SkillListScrollFrame"), delta)
|
||
end
|
||
|
||
-- ── Lifecycle (ref SkillFrame_OnLoad/_OnShow/_OnEvent, l.4-22, collapsed to the events this
|
||
-- page's feed actually fires: CHARACTER_POINTS_CHANGED backs the training-point economy this
|
||
-- pane doesn't ship, this file's header comment deviation 1). ─────────────────────────────────
|
||
function SkillFrame_OnLoad()
|
||
local frame = this
|
||
frame:RegisterEvent("SKILL_LINES_CHANGED")
|
||
end
|
||
|
||
function SkillFrame_OnShow()
|
||
BenillaSkillFrame_Update()
|
||
end
|
||
|
||
function SkillFrame_OnEvent(event)
|
||
local frame = this
|
||
if event == "SKILL_LINES_CHANGED" and frame:IsVisible() then
|
||
BenillaSkillFrame_Update()
|
||
end
|
||
end
|
||
]]></Script>
|
||
|
||
<!--
|
||
The rank StatusBar row (ref SkillStatusBarTemplate, l.4-65 — the FillBar dropped, this file's
|
||
header comment deviation 5): 271×15, name+rank overlaid, the Border child Button for OnClick
|
||
+ hover highlight (TradeSkillFrame.xml's own BenillaTradeSkillRankFrame shape, verbatim).
|
||
-->
|
||
<StatusBar name="BenillaSkillRankTemplate" virtual="true" hidden="true" drawLayer="BACKGROUND" minValue="0" maxValue="1" defaultValue="0">
|
||
<Size><AbsDimension x="271" y="15"/></Size>
|
||
<Layers>
|
||
<Layer level="ARTWORK">
|
||
<FontString name="$parentSkillName" inherits="GameFontNormalSmall">
|
||
<Anchors><Anchor point="LEFT" relativePoint="LEFT"><Offset><AbsDimension x="6" y="1"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
<FontString name="$parentSkillRank" inherits="GameFontHighlightSmall" justifyH="LEFT">
|
||
<Size><AbsDimension x="128" y="0"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativeTo="$parentSkillName" relativePoint="RIGHT"><Offset><AbsDimension x="13" y="0"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="$parentBackground"><Color r="1.0" g="1.0" b="1.0" a="0.2"/></Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<Button name="$parentBorder">
|
||
<Size><AbsDimension x="281" y="32"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativePoint="LEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<NormalTexture file="Interface\PaperDollInfoFrame\UI-Character-Skills-BarBorder"/>
|
||
<HighlightTexture file="Interface\PaperDollInfoFrame\UI-Character-Skills-BarBorderHighlight"/>
|
||
<Scripts><OnClick>BenillaSkillRankFrame_OnClick(self:GetParent())</OnClick></Scripts>
|
||
</Button>
|
||
</Frames>
|
||
<BarTexture name="$parentBar" file="Interface\PaperDollInfoFrame\UI-Character-Skills-Bar"/>
|
||
<BarColor r="0.25" g="0.25" b="0.75"/>
|
||
</StatusBar>
|
||
|
||
<!--
|
||
The category header row (ref SkillLabelTemplate, l.66-129, minus the DisabledTexture — this
|
||
window never Disable()s a header): 285×14, the +/- fold icon + name text.
|
||
-->
|
||
<Button name="BenillaSkillHeaderTemplate" virtual="true" hidden="true">
|
||
<Size><AbsDimension x="285" y="14"/></Size>
|
||
<Scripts><OnClick>BenillaSkillTypeLabel_OnClick(self)</OnClick></Scripts>
|
||
<NormalTexture file="Interface\Buttons\UI-MinusButton-UP">
|
||
<Size><AbsDimension x="16" y="16"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativePoint="LEFT"><Offset><AbsDimension x="3" y="0"/></Offset></Anchor></Anchors>
|
||
</NormalTexture>
|
||
<HighlightTexture file="Interface\Buttons\UI-PlusButton-Hilight" alphaMode="ADD">
|
||
<Size><AbsDimension x="16" y="16"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativePoint="LEFT"><Offset><AbsDimension x="3" y="0"/></Offset></Anchor></Anchors>
|
||
</HighlightTexture>
|
||
<ButtonText>
|
||
<Anchors><Anchor point="LEFT" relativePoint="LEFT"><Offset><AbsDimension x="25" y="0"/></Offset></Anchor></Anchors>
|
||
</ButtonText>
|
||
<NormalFont inherits="GameFontHighlight" justifyH="LEFT"/>
|
||
</Button>
|
||
|
||
<!-- id=4, the ref's own: a page's id is the slot it occupies in the WINDOW'S OWN tab row, and
|
||
ToggleCharacter selects the tab from it (ref CharacterFrame.lua:11). This was 3 while
|
||
Reputation (the ref's 3) was not built; ReputationFrame.xml landed and took that slot, so
|
||
Skills is back on the reference's number. `character_tests.rs` pins every page's id against
|
||
its slot in CHARACTERFRAME_SUBFRAMES, which is what made the renumber loud rather
|
||
than silent — exactly as this comment predicted. -->
|
||
<Frame name="SkillFrame" enableMouse="true" parent="CharacterFrame" hidden="true" id="4">
|
||
<!-- The real 384×512 page. No <Anchors relativeTo> substitute for true parenting exists
|
||
(this file's header comment) — pinned to CharacterFrame's own TOPLEFT by name. -->
|
||
<Size><AbsDimension x="384" y="512"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="CharacterFrame" relativePoint="TOPLEFT"/></Anchors>
|
||
<!-- Transcribed for fidelity (ref l.131-133); no loader wiring exists yet for the hit-rect
|
||
shrink (TradeSkillFrame.xml's own "transcribe the hook even if nothing drives it yet"
|
||
posture, TalentFrame.xml's precedent). -->
|
||
<HitRectInsets><AbsInset left="0" right="30" top="0" bottom="75"/></HitRectInsets>
|
||
<Layers>
|
||
<!-- The shared quadrant background (ref l.136-183): NO portrait redraw here (this file's
|
||
header comment) — "General" TopLeft/TopRight (the same variant every PaperDollInfoFrame
|
||
page shares, carrying the portrait-ring cutout) + SkillFrame's own BotLeft/BotRight. -->
|
||
<Layer level="BACKGROUND">
|
||
<Texture file="Interface\PaperDollInfoFrame\UI-Character-General-TopLeft">
|
||
<Size><AbsDimension x="256" y="256"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="2" y="-1"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
<Texture file="Interface\PaperDollInfoFrame\UI-Character-General-TopRight">
|
||
<Size><AbsDimension x="128" y="256"/></Size>
|
||
<Anchors><Anchor point="TOPRIGHT" relativePoint="TOPRIGHT"><Offset><AbsDimension x="2" y="-1"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
<Texture file="Interface\PaperDollInfoFrame\SkillFrame-BotLeft">
|
||
<Size><AbsDimension x="256" y="256"/></Size>
|
||
<Anchors><Anchor point="BOTTOMLEFT" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="2" y="-1"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
<Texture file="Interface\PaperDollInfoFrame\SkillFrame-BotRight">
|
||
<Size><AbsDimension x="128" y="256"/></Size>
|
||
<Anchors><Anchor point="BOTTOMRIGHT" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="2" y="-1"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
</Layer>
|
||
<!-- The divider bar below the list, above the detail pane (ref l.186-211's own
|
||
TOPLEFT(15,-290); nudged to -305 here to clear this file's own 12-row chain, whose
|
||
last row sits slightly lower than the ref's fixed-slot geometry — a pixel-fit
|
||
adjustment, not a structural deviation). -->
|
||
<Layer level="ARTWORK">
|
||
<Texture name="SkillHorizontalBarLeft" file="Interface\ClassTrainerFrame\UI-ClassTrainer-HorizontalBar">
|
||
<Size><AbsDimension x="256" y="16"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="15" y="-305"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="0" right="1.0" top="0" bottom="0.25"/>
|
||
</Texture>
|
||
<Texture file="Interface\ClassTrainerFrame\UI-ClassTrainer-HorizontalBar">
|
||
<Size><AbsDimension x="75" y="16"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativeTo="SkillHorizontalBarLeft" relativePoint="RIGHT"/></Anchors>
|
||
<TexCoords left="0" right="0.29296875" top="0.25" bottom="0.5"/>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- The expand/collapse-all tab (ref SkillFrameExpandButtonFrame, l.242-317 — the SAME
|
||
QuestLogSortTab art TrainerFrame.xml's own BenillaTrainerExpandButtonFrame uses).
|
||
The tab is SIZED BY ITS LABEL, the ref's own OnLoad law (l.312-316:
|
||
SetWidth(GetTextWidth()+45)) — the middle slab stretches between the two 8px caps
|
||
off its OWN two anchors (ref l.279-287), so the 45 is exactly the two caps plus the
|
||
label's seat. Was a fixed 54 with a fixed 38 middle, copied off
|
||
TrainerFrame.xml rather than read off THIS ref; the label's own font fix below
|
||
(12px, not 10) would have run under the right cap at that width. -->
|
||
<Frame name="SkillFrameExpandButtonFrame">
|
||
<Size><AbsDimension x="54" y="32"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="70" y="-49"/></Offset></Anchor></Anchors>
|
||
<Layers><Layer level="BACKGROUND">
|
||
<Texture name="SkillFrameExpandTabLeft" file="Interface\QuestFrame\UI-QuestLogSortTab-Left"><Size><AbsDimension x="8" y="32"/></Size><Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="0" y="6"/></Offset></Anchor></Anchors></Texture>
|
||
<Texture name="SkillFrameExpandTabRight" file="Interface\QuestFrame\UI-QuestLogSortTab-Right"><Size><AbsDimension x="8" y="32"/></Size><Anchors><Anchor point="TOPRIGHT" relativePoint="TOPRIGHT"><Offset><AbsDimension x="0" y="6"/></Offset></Anchor></Anchors></Texture>
|
||
<Texture name="SkillFrameExpandTabMiddle" file="Interface\QuestFrame\UI-QuestLogSortTab-Middle"><Size><AbsDimension x="0" y="32"/></Size><Anchors><Anchor point="LEFT" relativeTo="SkillFrameExpandTabLeft" relativePoint="RIGHT"/><Anchor point="RIGHT" relativeTo="SkillFrameExpandTabRight" relativePoint="LEFT"/></Anchors></Texture>
|
||
</Layer></Layers>
|
||
<Frames>
|
||
<!-- The ALL fold (ref SkillFrameCollapseAllButton, l.292-310). Its face is the
|
||
ref's SkillLabelTemplate one — the SAME face every SkillTypeLabel row wears
|
||
(BenillaSkillHeaderTemplate above, l.83-128 of the ref): the +/- glyph at
|
||
LEFT+3, the label at LEFT+25, and GameFontHighlight — WHITE at 12px, not
|
||
GameFontNormalSmall's yellow 10. Spelled out here rather than inherited
|
||
because this button keeps its own OnClick (this engine's
|
||
CollapseSkillHeader(0)/ExpandSkillHeader(0) fold everything at once, so it
|
||
needs no skillIndex/isExpanded bookkeeping) and this loader CONCATENATES an
|
||
instance's children onto its template's rather than replacing them, so an
|
||
inherited <Scripts> would stand alongside ours. Its seat is the ref's own
|
||
(-3,-3) off the left cap: the tab art's visible lip sits BELOW the
|
||
texture's geometric middle, so the label rides 3px low, not 3px high — the
|
||
+3 copied from TrainerFrame.xml put the whole "- All" 6px above where the
|
||
reference seats it. -->
|
||
<Button name="SkillFrameCollapseAllButton" text="ALL">
|
||
<Size><AbsDimension x="40" y="22"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativeTo="SkillFrameExpandTabLeft" relativePoint="RIGHT"><Offset><AbsDimension x="-3" y="-3"/></Offset></Anchor></Anchors>
|
||
<NormalTexture file="Interface\Buttons\UI-MinusButton-Up"><Size><AbsDimension x="16" y="16"/></Size><Anchors><Anchor point="LEFT" relativePoint="LEFT"><Offset><AbsDimension x="3" y="0"/></Offset></Anchor></Anchors></NormalTexture>
|
||
<HighlightTexture file="Interface\Buttons\UI-PlusButton-Hilight" alphaMode="ADD"><Size><AbsDimension x="16" y="16"/></Size><Anchors><Anchor point="LEFT" relativePoint="LEFT"><Offset><AbsDimension x="3" y="0"/></Offset></Anchor></Anchors></HighlightTexture>
|
||
<ButtonText><Anchors><Anchor point="LEFT" relativePoint="LEFT"><Offset><AbsDimension x="25" y="0"/></Offset></Anchor></Anchors></ButtonText>
|
||
<NormalFont inherits="GameFontHighlight" justifyH="LEFT"/>
|
||
<Scripts><OnClick>BenillaSkillFrameCollapseAllButton_OnClick()</OnClick></Scripts>
|
||
</Button>
|
||
</Frames>
|
||
<Scripts><OnLoad>BenillaSkillFrameExpandButtonFrame_Fit()</OnLoad></Scripts>
|
||
</Frame>
|
||
|
||
<!-- The page's own CLOSE button (ref SkillFrameCancelButton, l.339-357: 80x22,
|
||
UIPanelButtonTemplate, CENTER of TOPLEFT (305,-422), text CLOSE). LIVE in the
|
||
reference, not dead: the ref's XML comment that swallows SkillFrameAcceptButton
|
||
CLOSES at l.337, one line ABOVE this button — this file's own header comment
|
||
deviation 3 read that boundary wrong and dropped a button the real client draws,
|
||
which is why the page's bottom-right seat sat empty (decision 1496). The
|
||
UIPanelButtonTemplate face is reconstructed locally, the house convention every
|
||
window here follows (CraftFrame.xml's BenillaCraftPanelButtonTemplate note) — one
|
||
site, so inline rather than a virtual template (GroupLootFrame.xml's own precedent
|
||
for a single ref-template button). -->
|
||
<Button name="SkillFrameCancelButton" text="CLOSE">
|
||
<Size><AbsDimension x="80" y="22"/></Size>
|
||
<Anchors><Anchor point="CENTER" relativePoint="TOPLEFT"><Offset><AbsDimension x="305" y="-422"/></Offset></Anchor></Anchors>
|
||
<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>
|
||
<Scripts><OnClick>BenillaSkillFrameCancelButton_OnClick()</OnClick></Scripts>
|
||
</Button>
|
||
|
||
<!-- The persistent selection highlight (Trainer/TradeSkillFrame's own precedent, this
|
||
file's header comment deviation 7): 281×15, ARTWORK-layer UI-Listbox-Highlight2.
|
||
Declared BEFORE the rows so the row text paints OVER the glow (same z-tiebreak). -->
|
||
<Frame name="SkillHighlightFrame" hidden="true">
|
||
<Size><AbsDimension x="281" y="15"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"/></Anchors>
|
||
<Layers><Layer level="ARTWORK">
|
||
<Texture name="SkillHighlight" file="Interface\Buttons\UI-Listbox-Highlight2">
|
||
<Anchors><Anchor point="TOPLEFT"/><Anchor point="BOTTOMRIGHT"/></Anchors>
|
||
</Texture>
|
||
</Layer></Layers>
|
||
</Frame>
|
||
|
||
<!-- 12 header-row slots (ref SkillTypeLabel1..12, l.358-465): 285×14, row1 LEFT of
|
||
TOPLEFT(22,-86); rows 2-12 chain by (0,-18). -->
|
||
<Button name="SkillTypeLabel1" inherits="BenillaSkillHeaderTemplate">
|
||
<Anchors><Anchor point="LEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="22" y="-86"/></Offset></Anchor></Anchors>
|
||
</Button>
|
||
<Button name="SkillTypeLabel2" inherits="BenillaSkillHeaderTemplate"><Anchors><Anchor point="LEFT" relativeTo="SkillTypeLabel1"><Offset><AbsDimension x="0" y="-18"/></Offset></Anchor></Anchors></Button>
|
||
<Button name="SkillTypeLabel3" inherits="BenillaSkillHeaderTemplate"><Anchors><Anchor point="LEFT" relativeTo="SkillTypeLabel2"><Offset><AbsDimension x="0" y="-18"/></Offset></Anchor></Anchors></Button>
|
||
<Button name="SkillTypeLabel4" inherits="BenillaSkillHeaderTemplate"><Anchors><Anchor point="LEFT" relativeTo="SkillTypeLabel3"><Offset><AbsDimension x="0" y="-18"/></Offset></Anchor></Anchors></Button>
|
||
<Button name="SkillTypeLabel5" inherits="BenillaSkillHeaderTemplate"><Anchors><Anchor point="LEFT" relativeTo="SkillTypeLabel4"><Offset><AbsDimension x="0" y="-18"/></Offset></Anchor></Anchors></Button>
|
||
<Button name="SkillTypeLabel6" inherits="BenillaSkillHeaderTemplate"><Anchors><Anchor point="LEFT" relativeTo="SkillTypeLabel5"><Offset><AbsDimension x="0" y="-18"/></Offset></Anchor></Anchors></Button>
|
||
<Button name="SkillTypeLabel7" inherits="BenillaSkillHeaderTemplate"><Anchors><Anchor point="LEFT" relativeTo="SkillTypeLabel6"><Offset><AbsDimension x="0" y="-18"/></Offset></Anchor></Anchors></Button>
|
||
<Button name="SkillTypeLabel8" inherits="BenillaSkillHeaderTemplate"><Anchors><Anchor point="LEFT" relativeTo="SkillTypeLabel7"><Offset><AbsDimension x="0" y="-18"/></Offset></Anchor></Anchors></Button>
|
||
<Button name="SkillTypeLabel9" inherits="BenillaSkillHeaderTemplate"><Anchors><Anchor point="LEFT" relativeTo="SkillTypeLabel8"><Offset><AbsDimension x="0" y="-18"/></Offset></Anchor></Anchors></Button>
|
||
<Button name="SkillTypeLabel10" inherits="BenillaSkillHeaderTemplate"><Anchors><Anchor point="LEFT" relativeTo="SkillTypeLabel9"><Offset><AbsDimension x="0" y="-18"/></Offset></Anchor></Anchors></Button>
|
||
<Button name="SkillTypeLabel11" inherits="BenillaSkillHeaderTemplate"><Anchors><Anchor point="LEFT" relativeTo="SkillTypeLabel10"><Offset><AbsDimension x="0" y="-18"/></Offset></Anchor></Anchors></Button>
|
||
<Button name="SkillTypeLabel12" inherits="BenillaSkillHeaderTemplate"><Anchors><Anchor point="LEFT" relativeTo="SkillTypeLabel11"><Offset><AbsDimension x="0" y="-18"/></Offset></Anchor></Anchors></Button>
|
||
|
||
<!-- 12 rank-bar slots (ref SkillRankFrame1..12, l.746-853): 271×15, row1 TOPLEFT(38,-79);
|
||
rows 2-12 chain BOTTOMLEFT→TOPLEFT by (0,-3) — the SAME 18px pitch as the label chain
|
||
(15 bar height + 3 gap). -->
|
||
<StatusBar name="SkillRankFrame1" inherits="BenillaSkillRankTemplate" id="1">
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="38" y="-79"/></Offset></Anchor></Anchors>
|
||
</StatusBar>
|
||
<StatusBar name="SkillRankFrame2" inherits="BenillaSkillRankTemplate" id="2"><Anchors><Anchor point="TOPLEFT" relativeTo="SkillRankFrame1" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-3"/></Offset></Anchor></Anchors></StatusBar>
|
||
<StatusBar name="SkillRankFrame3" inherits="BenillaSkillRankTemplate" id="3"><Anchors><Anchor point="TOPLEFT" relativeTo="SkillRankFrame2" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-3"/></Offset></Anchor></Anchors></StatusBar>
|
||
<StatusBar name="SkillRankFrame4" inherits="BenillaSkillRankTemplate" id="4"><Anchors><Anchor point="TOPLEFT" relativeTo="SkillRankFrame3" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-3"/></Offset></Anchor></Anchors></StatusBar>
|
||
<StatusBar name="SkillRankFrame5" inherits="BenillaSkillRankTemplate" id="5"><Anchors><Anchor point="TOPLEFT" relativeTo="SkillRankFrame4" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-3"/></Offset></Anchor></Anchors></StatusBar>
|
||
<StatusBar name="SkillRankFrame6" inherits="BenillaSkillRankTemplate" id="6"><Anchors><Anchor point="TOPLEFT" relativeTo="SkillRankFrame5" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-3"/></Offset></Anchor></Anchors></StatusBar>
|
||
<StatusBar name="SkillRankFrame7" inherits="BenillaSkillRankTemplate" id="7"><Anchors><Anchor point="TOPLEFT" relativeTo="SkillRankFrame6" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-3"/></Offset></Anchor></Anchors></StatusBar>
|
||
<StatusBar name="SkillRankFrame8" inherits="BenillaSkillRankTemplate" id="8"><Anchors><Anchor point="TOPLEFT" relativeTo="SkillRankFrame7" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-3"/></Offset></Anchor></Anchors></StatusBar>
|
||
<StatusBar name="SkillRankFrame9" inherits="BenillaSkillRankTemplate" id="9"><Anchors><Anchor point="TOPLEFT" relativeTo="SkillRankFrame8" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-3"/></Offset></Anchor></Anchors></StatusBar>
|
||
<StatusBar name="SkillRankFrame10" inherits="BenillaSkillRankTemplate" id="10"><Anchors><Anchor point="TOPLEFT" relativeTo="SkillRankFrame9" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-3"/></Offset></Anchor></Anchors></StatusBar>
|
||
<StatusBar name="SkillRankFrame11" inherits="BenillaSkillRankTemplate" id="11"><Anchors><Anchor point="TOPLEFT" relativeTo="SkillRankFrame10" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-3"/></Offset></Anchor></Anchors></StatusBar>
|
||
<StatusBar name="SkillRankFrame12" inherits="BenillaSkillRankTemplate" id="12"><Anchors><Anchor point="TOPLEFT" relativeTo="SkillRankFrame11" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-3"/></Offset></Anchor></Anchors></StatusBar>
|
||
|
||
<!-- The faux-scroll frame (FauxScrollFrameTemplate, ScrollTemplates.xml): invisible
|
||
container over the 12 rows; only its right-hand Slider scroll bar renders. Sized to the
|
||
12-row span (SKILLS_TO_DISPLAY × 18px pitch), TrainerFrame.xml's own
|
||
same-TOPLEFT-as-row1 convention. Its `<OnVerticalScroll>` re-binds the rows (1868). -->
|
||
<ScrollFrame name="SkillListScrollFrame" inherits="FauxScrollFrameTemplate">
|
||
<Size><AbsDimension x="296" y="216"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPLEFT"><Offset><AbsDimension x="22" y="-79"/></Offset></Anchor></Anchors>
|
||
<Scripts>
|
||
<!-- The reference's kit writes `frame.offset` ONLY from here: the bar's
|
||
OnValueChanged calls `SetVerticalScroll`, which lands in this handler.
|
||
Our transcription used a `frame.updateFunc` field instead, which the
|
||
reference does not have — without this the bar moves and the list does
|
||
not follow (1860). -->
|
||
<OnVerticalScroll>BenillaSkillList_OnVerticalScroll()</OnVerticalScroll>
|
||
</Scripts>
|
||
</ScrollFrame>
|
||
|
||
<!-- ═══ THE DETAIL PANE ═══ ref SkillFrame.xml l.513-747, transcribed as the ref
|
||
declares it (header: the FLAT-layout claim this file used to carry is retracted,
|
||
decision 1517). A real ScrollFrame over a real scroll child; `scrollBarHideable`
|
||
keeps the bar off, which for a one-paragraph description is every time. The two
|
||
flanking textures are the ref's own trough art on the SCROLL FRAME's own Layers
|
||
(ItemTextFrame.xml's ItemTextScrollFrame is this file's precedent for both) — the
|
||
ref draws them unconditionally, so they stand whether or not the bar does.
|
||
The scroll range is the child's whole SUBTREE box (decision 1338), which is why
|
||
the ref's 320x50 child is not the undersized thing it looks like. -->
|
||
<ScrollFrame name="SkillDetailScrollFrame" inherits="UIPanelScrollFrameTemplate">
|
||
<Size><AbsDimension x="296" y="107"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="SkillListScrollFrame" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-8"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="ARTWORK">
|
||
<Texture file="Interface\ClassTrainerFrame\UI-ClassTrainer-ScrollBar">
|
||
<Size><AbsDimension x="30" y="100"/></Size>
|
||
<Anchors><Anchor point="TOPLEFT" relativePoint="TOPRIGHT"><Offset><AbsDimension x="-3" y="5"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="0" right="0.46875" top="0" bottom="0.78125"/>
|
||
</Texture>
|
||
<Texture file="Interface\ClassTrainerFrame\UI-ClassTrainer-ScrollBar">
|
||
<Size><AbsDimension x="30" y="100"/></Size>
|
||
<Anchors><Anchor point="BOTTOMLEFT" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="-3" y="-2"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="0.53125" right="1.0" top="0.21875" bottom="1.0"/>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<Scripts>
|
||
<!-- A handler declared on an instance REPLACES the template's, it does not
|
||
chain (ItemTextFrame.xml's own note), so the template's OnLoad is re-called
|
||
by hand before this instance's own line. -->
|
||
<OnLoad>
|
||
ScrollFrame_OnLoad()
|
||
self.scrollBarHideable = 1
|
||
</OnLoad>
|
||
</Scripts>
|
||
<ScrollChild>
|
||
<Frame name="SkillDetailScrollChildFrame">
|
||
<Size><AbsDimension x="320" y="50"/></Size>
|
||
<Layers>
|
||
<Layer level="ARTWORK">
|
||
<!-- The training-point price tag (ref l.567-577). Built, never
|
||
filled: `GetSkillLineInfo` reports no stepCost/rankCost on a
|
||
1.12 server, so BenillaSkillFrame_UpdateDetail takes the ref's
|
||
OWN no-cost branch (ref SkillFrame.lua l.361) and hides it —
|
||
deviation 1. It still earns its place as the DESCRIPTION's
|
||
anchor target, which is the ref's own arrangement. -->
|
||
<FontString name="SkillDetailCostText" inherits="GameFontNormalSmall" justifyH="CENTER" hidden="true">
|
||
<Size><AbsDimension x="200" y="0"/></Size>
|
||
<Anchors><Anchor point="CENTER" relativeTo="$parent" relativePoint="TOP"><Offset><AbsDimension x="-10" y="-40"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
<!-- The description body (ref l.579-591). Its anchor is XML now:
|
||
the flat layout had to set it in SkillFrame_OnLoad because the
|
||
bar was a forward reference on the page, and inside the child
|
||
the ref's own static TOP anchor resolves. -->
|
||
<FontString name="SkillDetailDescriptionText" inherits="GameFontHighlightSmall" justifyH="LEFT" justifyV="TOP" hidden="true">
|
||
<Size><AbsDimension x="275" y="0"/></Size>
|
||
<Anchors><Anchor point="TOP" relativeTo="$parent" relativePoint="TOP"><Offset><AbsDimension x="-5" y="-35"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- The selected skill's rank bar (ref l.594-747), the ref's OWN
|
||
declaration rather than the borrowed 271-wide list row it used to
|
||
be: 211x15 under a 220x32 Border, centred on the child's TOP. The
|
||
Border is a TEXTURE here, as the ref has it — the list row's
|
||
Border is a Button because a row is clickable, and the detail bar
|
||
is not, so the old "its Border click is harmless here" hedge is
|
||
gone with the borrowing. Names match the list template's
|
||
($parentSkillName/$parentSkillRank/$parentBackground), so
|
||
BenillaSkillFrame_PaintBar drives both unchanged. -->
|
||
<StatusBar name="SkillDetailStatusBar" drawLayer="BACKGROUND" minValue="0" maxValue="1" defaultValue="0" hidden="true">
|
||
<Size><AbsDimension x="211" y="15"/></Size>
|
||
<Anchors>
|
||
<Anchor point="CENTER" relativeTo="SkillDetailScrollChildFrame" relativePoint="TOP"><Offset><AbsDimension x="-10" y="-20"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="ARTWORK">
|
||
<Texture name="$parentBorder" file="Interface\PaperDollInfoFrame\UI-Character-Skills-BarBorder">
|
||
<Size><AbsDimension x="220" y="32"/></Size>
|
||
<Anchors><Anchor point="LEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
<FontString name="$parentSkillName" inherits="GameFontNormalSmall">
|
||
<Anchors><Anchor point="LEFT"><Offset><AbsDimension x="6" y="1"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
<FontString name="$parentSkillRank" inherits="GameFontHighlightSmall">
|
||
<Size><AbsDimension x="128" y="0"/></Size>
|
||
</FontString>
|
||
</Layer>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="$parentBackground">
|
||
<Color r="1.0" g="1.0" b="1.0" a="0.2"/>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- The abandon button (ref $parentUnlearnButton, l.705-737,
|
||
verbatim art/geometry): the red circle-slash right of the
|
||
Border, shown by UpdateDetail only for an abandonable line.
|
||
HitRectInsets transcribed-inert (no loader wiring —
|
||
CharacterFrame.xml's engine-gap note). Handlers are chunk
|
||
functions (the chunk-boundary rule — OnEnter reads the
|
||
chunk-local UNLEARN_SKILL_TOOLTIP). -->
|
||
<Button name="$parentUnlearnButton" hidden="true">
|
||
<Size><AbsDimension x="32" y="32"/></Size>
|
||
<Anchors>
|
||
<Anchor point="LEFT" relativeTo="$parentBorder" relativePoint="RIGHT">
|
||
<Offset><AbsDimension x="-2" y="-1"/></Offset>
|
||
</Anchor>
|
||
</Anchors>
|
||
<HitRectInsets><AbsInset left="9" right="7" top="-7" bottom="10"/></HitRectInsets>
|
||
<Scripts>
|
||
<OnClick>BenillaSkillUnlearnButton_OnClick(self)</OnClick>
|
||
<OnEnter>BenillaSkillUnlearnButton_OnEnter(self)</OnEnter>
|
||
<OnLeave>GameTooltip:Hide()</OnLeave>
|
||
</Scripts>
|
||
<NormalTexture file="Interface\Buttons\CancelButton-Up"/>
|
||
<PushedTexture file="Interface\Buttons\CancelButton-Down"/>
|
||
<HighlightTexture file="Interface\Buttons\CancelButton-Highlight" alphaMode="ADD"/>
|
||
</Button>
|
||
</Frames>
|
||
<BarTexture name="$parentBar" file="Interface\PaperDollInfoFrame\UI-Character-Skills-Bar"/>
|
||
<BarColor r="0.25" g="0.25" b="0.75"/>
|
||
</StatusBar>
|
||
</Frames>
|
||
</Frame>
|
||
</ScrollChild>
|
||
</ScrollFrame>
|
||
</Frames>
|
||
<Scripts>
|
||
<OnLoad>SkillFrame_OnLoad()</OnLoad>
|
||
<OnShow>SkillFrame_OnShow()</OnShow>
|
||
<OnEvent>SkillFrame_OnEvent(event)</OnEvent>
|
||
<OnMouseWheel>BenillaSkillFrame_OnMouseWheel(arg1)</OnMouseWheel>
|
||
</Scripts>
|
||
</Frame>
|
||
</Ui>
|