- the Brightness slider in the options window changes the picture and keeps its value; it was writing to no setting at all, so every reopen read 50% again (2186) - the login, realm and character screens share one letterboxed frame, so clicking down the character roster no longer slides the backdrop and every panel over it; at 4:3 nothing changes (2187) - Questie's world-map notes show their tooltip on hover: the note hands the tooltip a frame where an anchor name goes, which benilla refused with a script error and the reference reads as the default anchor (2176) - with OmniCC installed, a warrior in a stance sees the countdown on action bar 1 again: raising that bar's buttons by script carried their cooldown sweep up over the count (2189) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
4618 lines
350 KiB
XML
4618 lines
350 KiB
XML
<Ui>
|
||
<!--
|
||
The OPTIONS window (decision 0950) — the shell (slice A) and the real PAGES: Audio
|
||
(0957), Graphics (0959), Controls (0961), Nameplates (0992, with the dropdown row
|
||
shape). Opened from the game menu's Options button.
|
||
Setting rows ride the CVar store (0954): rows read GetCVar on show, write SetCVar on
|
||
interaction, and Defaults resets the visible page's CVars to their registered defaults.
|
||
Pages without rows are still empty and keep Defaults disabled. One row defers — uiScale
|
||
stages a pending value and commits through the era Apply button (0961), because a live
|
||
write would rescale the very slider being dragged.
|
||
|
||
PROVENANCE (0985 — the three-source split, stated the same way in every era-shaped
|
||
window; GameMenuFrame.xml carries the sibling block):
|
||
· STRUCTURE & BEHAVIOR — the 1.15 era client (wow-ui-source-era @ 1.15.9.68940):
|
||
layout, geometry grammar, interaction, functionality — the single all-in-one
|
||
window, the category tree, the search, the Apply flow. If 1.15 has the mechanism,
|
||
it STAYS, even where the older clients had none — except a DIRECTED CUT the
|
||
director makes on look, each recorded (0989: the slider steppers and the corner
|
||
close X; the split bends to taste only by record, never silently).
|
||
· CHROME MECHANISM — the 1.13/1.14 clients' own UI source (wow-ui-source @ 1.14.4,
|
||
their System window family; 0981/0984): HOW surfaces are textured — the dialog
|
||
backdrop, the outline boxes, the title plate, the select/hover washes and their
|
||
tints, the hairlines. Geometry may bend where 1.15 furniture needs a seat (the
|
||
-52 band below); the mechanism holds.
|
||
· ART BYTES — the 1.12 MPQ chain only, or a plain color fill (0978 retired every
|
||
era-atlas extraction and the `era:` scheme; one install, nothing later-client at
|
||
runtime).
|
||
So: the 1.12 OptionsFrame family (four separate panels) collapses into the era's
|
||
single window — a category list, one page area — every texture 1.12-native. The era
|
||
art names in the bullets below stay as GEOMETRY CITATIONS, not drawn art:
|
||
· **Root** — Blizzard_SettingsPanel.xml `SettingsPanel`: 920x724, CENTER, strata HIGH,
|
||
hidden. Skin per `SettingsFrameTemplate` (Classic/Blizzard_SettingsPanelTemplates.xml):
|
||
FlatPanelBackgroundTemplate at TOPLEFT (7,-18) → BOTTOMRIGHT (-3,3), the
|
||
`ButtonFrameTemplateNoPortrait` nine-slice (Classic/NineSliceLayouts.lua l.132 — right
|
||
edge x=-8/x1=8), the `_UI-Frame-TitleTileBg` title band (256x17, TexCoords
|
||
.2890625/.421875, TOPLEFT (8,-3) → TOPRIGHT (0,-3)), title GameFontNormal TOP (0,-5).
|
||
· **Category list** — Blizzard_CategoryList.xml + .lua: rows/headers STRETCH to the
|
||
scroll target's width (199, no scroll bar); header 30 tall (label 14px white at
|
||
LEFT (20,-1), Options_CategoryHeader_<n> wash at TOPLEFT at atlas size, n cycling
|
||
per header); row 20 tall (label GameFontNormal TOPLEFT (36,+1); bg CENTER —
|
||
options_list_active selected / options_list_hover hover, at atlas size); 2 between
|
||
elements, 18-tall spacer between groups (so 22 row-to-header).
|
||
· **Page area** — Blizzard_SettingsList.xml: title 20px white TOPLEFT (7,-22), the
|
||
options_horizontaldivider at TOP (0,-50), Defaults 96x22 at TOPRIGHT (-36,-16).
|
||
· **Tabs** — SharedXML Shared/Tabs/MinimalTab.{xml,lua}: a bottom-anchored three-slice
|
||
of Options_Tab[_Active]_{Left,Middle,Right}, GameTab TOPLEFT (32,-27) h37, AddOnsTab
|
||
5 right of it; width text+40; selected = white small text at BOTTOM+6, unselected =
|
||
gold small at BOTTOM+4.
|
||
· **Search box** — SharedXML SearchBoxTemplate → InputBoxVisualTemplate
|
||
(SecureUIPanelTemplates.xml l.42-67): the common-search-border three-slice (8x20 caps,
|
||
left hung 5 outside, middle stretched, all centered on the 22 box), 10x10 magnifier at
|
||
LEFT (1,-1), 17x17 clear button at RIGHT (-3), TextInsets 16/20, instructions label
|
||
GameFontDisableSmall tinted 0.35 at TOPLEFT (16,0) → BOTTOMRIGHT (-20,0).
|
||
THE 1.12 ART MAPPING (0978 base set, 0981 chrome — every file verified present in the
|
||
5875 MPQ chain; the CHROME recipe is the 1.14 System window's own, read verbatim from
|
||
wow-ui-source @1.14.4 OptionsFrameTemplates.xml + InterfaceOptionsFrame.xml, whose
|
||
every piece is 1.12-native or a color):
|
||
· window chrome — BACKDROP_DIALOG_32_32, the 1.14 options frames' backdrop: tiled
|
||
UI-DialogBox-Background ground (uniform black at 60% alpha — the world reads
|
||
through, the reference screenshot's actual mechanism; 0978 misread that ground as
|
||
parchment) + UI-DialogBox-Border rope edge 32, insets 11/12/12/11. Title plate
|
||
UI-DialogBox-Header at the options frames' 300x68 TOP (0,+12) seat, title on it.
|
||
ON TOP of that tile, inside the rope, a plain black 0.7 fill (1476) takes the
|
||
composite ground to 0.88: at the bare tile the world reached the option labels
|
||
hard enough to break them over bright terrain. The read-through stays, dimmed.
|
||
· the era's one dark Options_InnerFrame panel → TWO 1.14 OptionsFrameListTemplate
|
||
boxes: tooltip-border backdrops with the FILL AT ALPHA 0 (outlines — the ground
|
||
shows through) and the border tinted LIGHTGRAY_FONT_COLOR 0.6, tops at -52 (1.14's
|
||
own -40 band deepened 12 to hold the era search seat — 0984), tabs seated on the
|
||
category box's top edge (BOTTOMLEFT → box TOPLEFT (6,-3), the file-folder tuck).
|
||
· category rows — the 1.14 list-button wash, verbatim mechanism (0984,
|
||
OptionsFrameTemplates.{xml l.216-229, lua l.107-131}): ONE UI-QuestLogTitleHighlight
|
||
quad in ADD blend at the era plate seat (187x21 centered), steel-blue (.196,.388,.8)
|
||
as the hover and locked GOLD (1,1,0) as the selection, white hover/selected text.
|
||
The Options_CategoryHeader_<n> washes have no 1.12 counterpart and are DROPPED —
|
||
headers are their label alone.
|
||
· checkboxes: the UI-CheckBox four-state set at the era 30x29 seat (no HighlightTexture
|
||
— hover feedback stays the era row-wide wash, unchanged behavior).
|
||
· sliders: the 1.12 OptionsSliderTemplate groove — UI-SliderBar-Background/-Border
|
||
backdrop, its exact edge 8 / tile 8 / insets 3/3/6/6 — on a 17-tall Groove frame at
|
||
the era track seat, and the 32x32 UI-SliderBar-Button-Horizontal thumb. NO steppers
|
||
(0989, a directed cut of era structure): the bar is the whole control, 1.12's own
|
||
look — and the whole bar is live (thumb drag, or press anywhere on the track to
|
||
seat the thumb there and keep dragging; the engine's 0989 track-press law).
|
||
· tabs: UI-Character-ActiveTab / -InActiveTab flipped vertically via TexCoords (1.12
|
||
ships only bottom-tab plates; the flip turns them top-tab), one stretched piece per
|
||
plate instead of the era three-slice, at the era plate heights (26 active / 23 not).
|
||
(1.14's own UI-OptionsFrame-{Active,InActive}Tab three-slice is a 2.x file — not in
|
||
the 1.12 chain, verified absent.)
|
||
· search box: the classic Common-Input-Border three-slice (the file IS in 1.12
|
||
interface.MPQ — 0950's pull list mislabeled it era-only), the InputBoxTemplate UVs.
|
||
The era magnifier has no 1.12 counterpart and is DROPPED (the "Search" placeholder
|
||
carries the affordance) — and with it the era's 16-left TextInsets seat, which
|
||
exists to clear that magnifier: text and caret sit at 5, snug to the border ink
|
||
(0989). The clear-X wears the UI-Panel-MinimizeButton ball at its 17x17 seat,
|
||
half-lit, full-lit on hover (the era ClearButtonMixin's alpha law).
|
||
· divider: a 1-unit white hairline at 0.3 alpha, a color fill — what the era's
|
||
options_horizontaldivider atlas member actually is (decoded: a 630x1 pure-white row,
|
||
alpha peaking ~0.4, mean ~0.26). 0978's stretched UI-DialogBox-Divider is retired.
|
||
|
||
SCOPE / divergences (noted, not bugs):
|
||
- **No corner close X (0989, a directed cut)** — the era HAS one
|
||
(UIPanelCloseButtonNoScripts: the UI-Panel-MinimizeButton family at TOPRIGHT (+4,+4),
|
||
Classic SharedUIPanelTemplates.xml l.172-180), and 0981/0984 wore it; the director
|
||
cut it. The red Close button and ESC close the window, and the freed corner returns
|
||
the search box to the era's full-width TOPRIGHT seat.
|
||
- **Tabs are STATIC MinimalTab plates** (slice B): Game wears the selected state
|
||
permanently, AddOns the unselected gold — the era swaps these in code
|
||
(MinimalTabMixin), and with nothing behind AddOns the selection can never change, so
|
||
the two states are authored rather than driven. The mixin port comes with the addon
|
||
list. Width is era's text+40 law, fitted once from each tab's own `<OnShow>` (2028 —
|
||
the engine's measurer answers in the call that asks); the era's
|
||
measure-at-the-medium-font quirk is deliberately dropped (~6 units of padding).
|
||
- **Search WORKS (0984)** — the era SettingsPanel mechanism re-expressed (the Script
|
||
block's search section): label-tag substring match scored by matched length,
|
||
results grouped under clickable category heads ordered by best score, a matched
|
||
child pulls its parent row in, "Search Results" title with Defaults hidden while
|
||
the search holds the page, the no-results line, and the search ends on a category
|
||
click or hide (the era's own ClearSearchBox law). The result rows are the LIVE
|
||
rows, reflowed — values, writes and dependencies all work mid-search. The two
|
||
strings ("Search Results", "No results found.") are ours: the era's
|
||
SETTINGS_SEARCH_* globals live in the client binary, not the dump.
|
||
- **The PAGE AREA scrolls; the category tree does not.** The static tree (9 rows, 2
|
||
headers) fits its 199px column outright, and every CVar page fits its area, so nothing
|
||
on a settled page has a bar. The page area is a real ScrollFrame all the same (B217 —
|
||
the era's SettingsList is a ScrollBox with a MinimalScrollBar, and results and pages
|
||
ride the same one): a SEARCH chains group heads and matched rows from every category
|
||
into one column, which for a broad query outran the page and drew out through the
|
||
window onto the world. The body is the scroll child, sized to the visible rect until
|
||
the content outgrows it (OptionsScroll_Fit). The KEYBINDINGS page (decision 1008 — the
|
||
1.15 Settings panel's own Keybindings category, module + provenance in
|
||
KeyBindingsPage.xml) keeps its OWN faux-scroll list inside that body — it fills the
|
||
body exactly, so the outer scroll's range on it is 0 and the two bars are never live
|
||
together; its search results reflow live binding rows under a Keybindings group head
|
||
whose click jumps to the page (the era redirect law), capped at the static pool's size.
|
||
Both bars wear the shared kit's trough (the recessed channel — 1.12 authors that art
|
||
per window, so it is opt-in there and declared beside each bar here).
|
||
- **Row tooltips are 1.12's own strings on the era's seat (B223, decision 1054)**: every
|
||
row whose setting exists in a 1.12 panel raises that panel's `OPTION_TOOLTIP_*` text —
|
||
the description ALONE, wrapped, in the engine's default gold (the 1.12/1.14 option-row
|
||
plate, and this window's own since 1008's Character Specific row), seated the era way
|
||
(ANCHOR_RIGHT off the label half, x -10). The era's name-line-then-description pair
|
||
(`Settings.InitTooltip` → `GameTooltip_AddHighlightLine(name)`) is cut: its title would
|
||
repeat the label the cursor is already on. **Auto Loot** is the one row with no 1.12
|
||
string — no 1.12 row exists for it (its label is era's too) — and raises no plate.
|
||
- **Setting-page cuts (0957 Audio, 0959 Graphics)**: Defaults resets the VISIBLE page only (the
|
||
era confirm dialog is not modeled); era rows with no 1.12 CVar +
|
||
benilla knob behind them (output device, Dialog volume, loop music, channels, cache;
|
||
the whole era Graphics dropdown zoo) don't ship. A slider shows the 1.12 panel's
|
||
range even where the benilla knob's clamp is wider (uiScale's env clamp is 0.5..1.5):
|
||
a config value outside the page range displays clamped — thumb and readout agree on
|
||
the nearest expressible value, the engine keeps running the config's truth, and
|
||
nothing writes back until the player actually moves the row.
|
||
- **Apply-flow cuts (0961)**: the era's close-with-pending 3-button confirm dialog
|
||
(GAME_SETTINGS_CONFIRM_DISCARD) is not modeled — hiding the window silently discards
|
||
pending edits (the era's own hide path wipes without committing too); the 8-second
|
||
"keep these settings?" revert timer (CommitFlag.Revertable) is not modeled either —
|
||
Apply commits outright.
|
||
- Era rows this slice does not ship: the Accessibility group, and Languages/Network under
|
||
System — pages with no benilla knobs behind them yet (0950's "only rows backed by real
|
||
knobs" rule). Nameplates joined the tree in slice B on the promise of its knobs; the
|
||
page went LIVE in 0992 (the three UnitName* checkbox rows).
|
||
- **The window rides a scale knob** (slice B): fonts ride frame scale engine-wide now
|
||
(the 0219 §2 divergence closed), so ERA_WINDOW_SCALE × the era checkFit shrink
|
||
(UIPanelUpdateScaleForFit, re-expressed in this file) sizes the whole window; 0.78 is
|
||
the director's-eye starting point, live-tunable. The knob is SHARED: it stands in for
|
||
the era client's UIParent scale (smaller than our 1.12 768-canvas on modern screens),
|
||
so every era-shaped window wears it — GameMenuFrame.xml reads it in its OnShow.
|
||
-->
|
||
|
||
<!-- The two era fonts this window needs beyond Fonts.xml's 1.12 set (the era
|
||
GameFontHighlightMedium / GameFontHighlightHuge — Blizzard_Fonts_Shared: FRIZQT 14 and
|
||
20, white). Named Options* rather than the era names on purpose: Fonts.xml is the
|
||
COMPLETE 1.12 set and stays that way; these are this window's own, defined with
|
||
MasterFont's exact shadow inlined (its only content — Fonts.xml l.62). -->
|
||
<Font name="OptionsFontHighlightMedium" font="Fonts\FRIZQT__.TTF" virtual="true">
|
||
<Shadow>
|
||
<Offset><AbsDimension x="1" y="-1"/></Offset>
|
||
<Color r="0" g="0" b="0"/>
|
||
</Shadow>
|
||
<FontHeight><AbsValue val="14"/></FontHeight>
|
||
<Color r="1.0" g="1.0" b="1.0"/>
|
||
</Font>
|
||
<Font name="OptionsFontHighlightHuge" font="Fonts\FRIZQT__.TTF" virtual="true">
|
||
<Shadow>
|
||
<Offset><AbsDimension x="1" y="-1"/></Offset>
|
||
<Color r="0" g="0" b="0"/>
|
||
</Shadow>
|
||
<FontHeight><AbsValue val="20"/></FontHeight>
|
||
<Color r="1.0" g="1.0" b="1.0"/>
|
||
</Font>
|
||
|
||
<Script><![CDATA[
|
||
-- ══ WHAT THIS FILE NO LONGER DECLARES, AND WHERE IT COMES FROM NOW (decision 2115) ══════
|
||
--
|
||
-- benilla's options window is THIS file and it is the one the player opens. But the
|
||
-- reference's own `UIOptionsFrame.xml` is now loaded too — hidden, off the player's chain,
|
||
-- at the manifest's l.21 seat above this row — so that a third-party addon reaching for
|
||
-- `UIOptionsFrame`, `UIOptionsFrameCheckButton42` or `UIOptionsFrame_Load()` finds the real
|
||
-- thing instead of an alias onto us. Three things this file used to carry are the stock
|
||
-- file's, and are gone from here rather than duplicated:
|
||
--
|
||
-- · **The 30 options uvars.** `UIOptionsFrame_Init` (stock UIOptionsFrame.lua l.93-185)
|
||
-- assigns every one its factory value and `RegisterForSave`s it — SIMPLE_CHAT,
|
||
-- CHAT_LOCKED, REMOVE_CHAT_DELAY, SHOW_NEWBIE_TIPS, LOCK_ACTIONBAR,
|
||
-- SHOW_BUFF_DURATIONS, ALWAYS_SHOW_MULTIBARS, SHOW_PARTY_PETS, QUEST_FADING_DISABLE,
|
||
-- SHOW_PARTY_BACKGROUND, HIDE_PARTY_INTERFACE, SHOW_TARGET_OF_TARGET(+_STATE),
|
||
-- HIDE_OUTDOOR_WORLD_STATE, AUTO_QUEST_WATCH, the fourteen COMBAT_TEXT_* rows and
|
||
-- COMBAT_TEXT_FLOAT_MODE, plus NAMEPLATES_ON/FRIENDNAMEPLATES_ON. Every value we used
|
||
-- to write here was already the reference's (1804 made them so), so this is a pure
|
||
-- de-duplication and the DEFAULT IS NOW THE REFERENCE'S BY CONSTRUCTION: our rows read
|
||
-- the global at their OnLoad (`OptionsGlobalRow_OnLoad`'s `udefault`), and the stock
|
||
-- file has assigned it long before, so Defaults still walks back to the shipped value.
|
||
-- Five it declares that we never did come free: SIMPLE_CHAT, SHOW_PARTY_PETS,
|
||
-- SHOW_PARTY_BACKGROUND, HIDE_PARTY_INTERFACE, and the nameplate pair's save rows.
|
||
--
|
||
-- · **`UIOptionsFrameCheckButtons`.** The reference's option table, whose home is that
|
||
-- file. Stock `MultiActionBars.lua:10` writes five rows into it at ITS load ("Hack to
|
||
-- get around load order dependencies"), which is why the stock window's row must sit
|
||
-- above MultiActionBars.xml in benilla.toc — it does, at l.21 exactly as the
|
||
-- reference's toc has it. Our rows never read this table; they keep their own store
|
||
-- (`OptionsRow_Get`'s three kinds).
|
||
--
|
||
-- · **`UpdateNameplates`.** `UIOptionsFrame.lua` l.768-780 — the reference's own home
|
||
-- for it, and the four verbs it calls (Show/HideNameplates, Show/HideFriendNameplates)
|
||
-- are ours in `script/cvars.rs`, unchanged. **One line of that body came back here**
|
||
-- (decision 2132) — see the re-declaration below; the de-duplication otherwise stands.
|
||
--
|
||
-- ── THE ONE ASSIGNMENT THAT STAYS, AND WHY IT IS AN OVERRIDE ────────────────────────────
|
||
-- `AUTO_QUEST_WATCH` is the string `"1"` ON PURPOSE (decision 1136): the reference assigns
|
||
-- the NUMBER 1 (`UIOptionsFrame.lua` l.122) while every consumer — stock
|
||
-- `QuestLogFrame.lua:64/68` and the checkbox's own load — compares against the STRING, and
|
||
-- in Lua 5.0 `1 ~= "1"`. So on a fresh 1.12 install the box paints unchecked and the
|
||
-- advertised auto-watch is dead until the player clicks it. We ship the string so the
|
||
-- advertised default is the real one — a recorded deviation under 1804's rule, not a quiet
|
||
-- one.
|
||
--
|
||
-- **This file loads AFTER the stock one** (manifest l.21 vs this window's seat before
|
||
-- GameMenuFrame), so this line runs after `UIOptionsFrame_Init` and wins. It is a
|
||
-- re-assignment, not a declaration: the `RegisterForSave` is the stock file's, and a second
|
||
-- one would be redundant — but it is kept, because `RegisterForSave` is idempotent and a
|
||
-- reader of this line should not have to know the stock file registered it to know the
|
||
-- global is persisted.
|
||
AUTO_QUEST_WATCH = "1"
|
||
RegisterForSave("AUTO_QUEST_WATCH")
|
||
|
||
-- The family's apply, ref UIOptionsFrame_Save l.371-376 verbatim: the addon is
|
||
-- LoadOnDemand, so turning the master on loads it, and the update runs only once it is
|
||
-- there. Every combat-text row's `applyFunc` is this (1964).
|
||
function CombatText_UpdateOrLoad()
|
||
if ( SHOW_COMBAT_TEXT == "1" ) then
|
||
UIParentLoadAddOn("Blizzard_CombatText")
|
||
end
|
||
if ( CombatText_UpdateDisplayedMessages ) then
|
||
CombatText_UpdateDisplayedMessages()
|
||
end
|
||
end
|
||
-- The Remove Chat Hover Delay row's applyFunc: the reference's own line
|
||
-- (UIOptionsFrame.lua l.216, `SetChatMouseOverDelay(REMOVE_CHAT_DELAY)`) under the name the
|
||
-- row resolves at apply time. `SetChatMouseOverDelay` is FloatingChatFrame.lua's.
|
||
function ChatFrame_ApplyMouseOverDelay()
|
||
if SetChatMouseOverDelay then -- a VM that loaded this file without the chat files — a test's
|
||
SetChatMouseOverDelay(REMOVE_CHAT_DELAY)
|
||
end
|
||
end
|
||
|
||
-- ── Show Tutorials' SETTER: the reference's own Save arm (decision 2077) ────────────
|
||
-- UIOptionsFrame.lua l.318-327, verbatim in behaviour. Its CheckButtons row is a bare
|
||
-- `{ index = 28 }` with no cvar and no uvar, which is why decision 1140's census filed it
|
||
-- as an "index-only entry with no store at all" and left it out; that reading is wrong.
|
||
-- The store is not in the TABLE, it is in the three special-case arms `UIOptionsFrame_Load`
|
||
-- (l.239), `_Save` (l.318) and `_SetDefaults` (l.645) keep for this key — the getter is
|
||
-- `TutorialsEnabled()` and the setter is the Reset/Clear pair, because "disable tutorials"
|
||
-- in 1.12 literally means "mark every bit of the acknowledged bank", not a CVar (1976;
|
||
-- wow-re censused all 210 `CVar::Register` sites and there is no tutorial CVar).
|
||
--
|
||
-- The `~=` guard is the reference's and it matters: `TutorialsEnabled()` returns the NUMBER
|
||
-- 1 or nil, so re-ticking an already-on row does not re-`ResetTutorials()` — which would
|
||
-- re-arm every tutorial the player has already dismissed.
|
||
function BenillaOptionsFrame_SetTutorialsEnabled(value)
|
||
if ( tonumber(value) ~= TutorialsEnabled() ) then
|
||
if ( value == "1" ) then
|
||
ResetTutorials()
|
||
TutorialFrameCheckButton:SetChecked(1)
|
||
else
|
||
ClearTutorials()
|
||
end
|
||
TutorialFrame_HideAllAlerts()
|
||
end
|
||
end
|
||
|
||
-- ── `UpdateNameplates` — OURS AGAIN, and the deviation is ONE LINE (decision 2132) ──────
|
||
-- The stock body is `UIOptionsFrame.lua` l.768-780, running off the chain since 2115.
|
||
-- This file loads after it (manifest l.21 vs this window's seat), so this re-declaration
|
||
-- wins. It is transcribed verbatim except that l.776 is dropped, and both halves of the
|
||
-- reason are benilla facts, not taste:
|
||
--
|
||
-- · **l.774-776 is a stock typo.** `if ( FRIENDNAMEPLATES_ON ) then
|
||
-- ShowFriendNameplates(); HideFriendNameplates();` — show, then hide, so BOTH branches
|
||
-- end hidden. On 1.12 that only clears volatile engine bits, and the friendly global is
|
||
-- not even saved (its l.182 registers `NAMEPLATES_ON` a second time where
|
||
-- `FRIENDNAMEPLATES_ON` was meant). On benilla the four verbs write the CVar pair, and
|
||
-- the CVar pair IS the store (`vplates.rs`, `script/cvars.rs`) — so those two lines
|
||
-- erase a persisted setting at every world entry and untick this window's own
|
||
-- Friendly Name Plates row.
|
||
-- · **There is no volatile level here to replay into.** The reference clears
|
||
-- `[0xc4da34]` on every EnterWorld and this function restores it; `VPlateMode` is never
|
||
-- cleared, so the replay has nothing to restore. What it still owes is the other
|
||
-- direction — an addon that sets `NAMEPLATES_ON` and calls this expects plates to move
|
||
-- — which is why the body stays rather than becoming a no-op (1203's posture).
|
||
--
|
||
-- The globals it reads are kept true by the host (`vplates::push_plate_globals`), seeded
|
||
-- ahead of `VARIABLES_LOADED` on the load edge, so in the steady state every branch here
|
||
-- writes a value the CVar already holds and queues nothing at all.
|
||
function UpdateNameplates()
|
||
if ( NAMEPLATES_ON ) then
|
||
ShowNameplates()
|
||
else
|
||
HideNameplates()
|
||
end
|
||
if ( FRIENDNAMEPLATES_ON ) then
|
||
ShowFriendNameplates()
|
||
else
|
||
HideFriendNameplates()
|
||
end
|
||
end
|
||
|
||
|
||
-- The static category tree (era Game tab, Classic tocs), in list order. Keys are the row
|
||
-- name suffixes; the visible label doubles as the page title (the era does the same —
|
||
-- Settings.RegisterCategory names both from one string).
|
||
OPTIONS_CATEGORY_KEYS = {
|
||
"Controls", "Interface", "ActionBars", "Combat", "Chat", "Keybindings", "Nameplates",
|
||
"Graphics", "Audio",
|
||
}
|
||
|
||
-- The era-window scale (shared, director-owned — the 0219 WORLDMAP_WINDOWED_SCALE
|
||
-- pattern): the era client's UIParent draws smaller against the screen than our 1.12
|
||
-- 768-canvas does on modern displays, and this knob is that mapping — every era-shaped
|
||
-- window wears it (this window here; GameMenuFrame in its OnShow — in the era both draw
|
||
-- at the SAME UIParent px-per-unit, the parity the director's eye checked). At 1.0 the
|
||
-- 724-tall window fills ~85% of the screen's height in our 768-virtual space, where the
|
||
-- reference at typical resolutions reads nearer two-thirds.
|
||
ERA_WINDOW_SCALE = 0.78
|
||
|
||
function BenillaOptionsFrame_UpdateScale()
|
||
-- The era panel is registered `checkFit = 1`: the panel manager also shrinks it to
|
||
-- fit a small screen (UIPanelUpdateScaleForFit: min over width/height ratios
|
||
-- against the panel + 20 units of air each way, capped at 1) — re-expressed here.
|
||
local k = ERA_WINDOW_SCALE
|
||
local wFit = GetScreenWidth() / 940
|
||
local hFit = GetScreenHeight() / 744
|
||
if wFit < k then k = wFit end
|
||
if hFit < k then k = hFit end
|
||
BenillaOptionsFrame:SetScale(k)
|
||
end
|
||
|
||
-- The era tab width law (MinimalTab.lua l.7): label width + 40, measured ONCE per show —
|
||
-- the 1.12 CharacterFrameTabButtonTemplate's own seat (its <OnShow> calls
|
||
-- PanelTemplates_TabResize; decision 1993), and it has to be a show rather than the era's
|
||
-- OnLoad for a reason that outlives the measure: GetStringWidth answers in the REGION'S
|
||
-- OWN units, so its number depends on the owner's effective scale (glyph advances snap to
|
||
-- whole physical pixels, so the same label is not proportionally the same width at two
|
||
-- scales) — and this window's scale is set by BenillaOptionsFrame_UpdateScale in its own <OnShow>,
|
||
-- after every OnLoad has already run. Fired from the tabs' <OnShow>, which the engine
|
||
-- runs pre-order behind the window's own, the scale is the drawn one. No poll and no latch:
|
||
-- the engine's font measurer answers inside the Lua call that asked (benilla-ui
|
||
-- script/measure.rs), and a re-show re-fits at whatever scale the window then wears.
|
||
-- Deliberate divergence: the era measures with the MEDIUM font it is about to swap away
|
||
-- (an accident of its code order, ~6 units of extra padding); we measure the small font
|
||
-- the label actually wears.
|
||
function OptionsTab_FitWidth(tab)
|
||
tab:SetWidth(getglobal(tab:GetName() .. "Text"):GetStringWidth() + 40)
|
||
end
|
||
|
||
-- Each row's OnLoad: remember the key + title, paint the label, size the wash plate —
|
||
-- the era sized it via SetAtlas(name, true) at atlas size (187x21, centered: 6 units
|
||
-- in from either edge of the 199 row); with plain SetTexture the size is authored
|
||
-- here once — and set the 1.14 base tint: OptionsListButton_OnLoad's own
|
||
-- SetVertexColor(.196, .388, .8), the steel-blue every unselected row's hover wears
|
||
-- (OptionsFrameTemplates.lua l.130-131). The whole row identity lives here so adding
|
||
-- a category is one XML row + one key in the table above.
|
||
function OptionsCategoryRow_OnLoad(row, key, label)
|
||
row.categoryKey = key
|
||
row.pageTitle = label
|
||
row:SetText(label)
|
||
local bg = getglobal(row:GetName() .. "Bg")
|
||
bg:SetWidth(187)
|
||
bg:SetHeight(21)
|
||
bg:SetVertexColor(0.196, 0.388, 0.8)
|
||
end
|
||
|
||
-- The selection — 1.14's OptionsList_SelectButton/_ClearSelection pair, re-expressed
|
||
-- (OptionsFrameTemplates.lua l.107-121): the selected row's wash goes GOLD (1,1,0)
|
||
-- and locks on; every other row drops back to the blue hover tint, wash off. The
|
||
-- white selected label is LockHighlight's own text state, carried by the font swap.
|
||
-- Also the era law on top (SettingsPanelMixin:SelectCategory clears the search box —
|
||
-- Blizzard_SettingsPanel.lua l.793): picking a category ENDS a live search; the
|
||
-- SetText("") round-trips through OnTextChanged -> restore -> back here, so this call
|
||
-- returns early and lets the re-entry do the work once.
|
||
-- Then the page swap: a category with rows (OPTIONS_PAGE_ROWS) shows its body
|
||
-- refreshed from the CVars and Defaults goes live with it; every other page is still
|
||
-- empty, Defaults disabled.
|
||
function BenillaOptionsFrame_SelectCategory(key)
|
||
BenillaOptionsFrame.selectedCategory = key
|
||
if BenillaOptionsFrameSearchBox:GetText() ~= "" then
|
||
BenillaOptionsFrameSearchBox:SetText("")
|
||
return -- the OnTextChanged restore re-entered with this same key and finished
|
||
end
|
||
for _, k in ipairs(OPTIONS_CATEGORY_KEYS) do
|
||
local row = getglobal("BenillaOptionsFrameCategoryListRow" .. k)
|
||
local bg = getglobal("BenillaOptionsFrameCategoryListRow" .. k .. "Bg")
|
||
if k == key then
|
||
bg:SetVertexColor(1, 1, 0)
|
||
bg:Show()
|
||
row:SetTextFontObject("GameFontHighlight")
|
||
BenillaOptionsFrameContainerTitle:SetText(row.pageTitle)
|
||
else
|
||
bg:SetVertexColor(0.196, 0.388, 0.8)
|
||
bg:Hide()
|
||
row:SetTextFontObject("GameFontNormal")
|
||
end
|
||
end
|
||
for k in pairs(OPTIONS_PAGE_ROWS) do
|
||
local body = getglobal("BenillaOptionsFrameContainerBody" .. k)
|
||
if k == key then body:Show() else body:Hide() end
|
||
end
|
||
-- A category switch starts at the TOP (2180), which is what entering and leaving a
|
||
-- search have always done two functions down and what the era's own ScrollBox does
|
||
-- per category. It was invisible until this record, because no PAGE outran its area
|
||
-- — only the search results did, and both of their edges reset. Now that Controls
|
||
-- carries sixteen rows, leaving it scrolled and clicking Interface would land the
|
||
-- player halfway down a page they have not seen the top of.
|
||
BenillaOptionsFrameContainerScroll:SetVerticalScroll(0)
|
||
-- The Keybindings page (KeyBindingsPage.xml, decision 1008) body-swaps like the
|
||
-- CVar pages but runs its own machinery: entering rebuilds the section tree;
|
||
-- leaving disarms a straggling capture (the host seam must never outlive the page)
|
||
-- and clears its message line. Its Defaults is the confirmed Reset To Default (the
|
||
-- button's OnClick forks), and the Unbind Key button exists only here.
|
||
local kb = getglobal("BenillaOptionsFrameContainerBodyKeybindings")
|
||
if key == "Keybindings" then
|
||
kb:Show()
|
||
KeyBindingsPage_Refresh()
|
||
BenillaOptionsFrameContainerUnbind:Show()
|
||
BenillaOptionsFrameContainerDefaults:Enable()
|
||
else
|
||
kb:Hide()
|
||
KeyBindings_SetSelected(nil)
|
||
KeyBindings_Output("")
|
||
BenillaOptionsFrameContainerUnbind:Hide()
|
||
if OPTIONS_PAGE_ROWS[key] then
|
||
OptionsPage_Refresh(key)
|
||
BenillaOptionsFrameContainerDefaults:Enable()
|
||
else
|
||
BenillaOptionsFrameContainerDefaults:Disable()
|
||
end
|
||
end
|
||
end
|
||
|
||
-- ── Search (0984): the era SettingsPanel mechanism, re-expressed ────────────────────
|
||
-- Blizzard_SettingsPanel.lua l.566-692 + Blizzard_Settings.lua l.65-77, cut to our
|
||
-- static rows: a setting's search tag is its LABEL uppercased (the era's default tag
|
||
-- is exactly the setting name — SettingControls.lua l.773); a query matches by plain
|
||
-- substring, scored by matched-word length; matches group under their category, the
|
||
-- groups ordered by their best score; each group opens with a clickable category
|
||
-- header (SettingsListSearchCategoryTemplate — click = jump to the category, which
|
||
-- ends the search); no match shows the section-header "no results" line. The results
|
||
-- ARE the live rows — the era reflows the real initializers into a fresh vertical
|
||
-- layout, so ours re-anchor the real row frames (values, writes, dependencies all
|
||
-- work in place) and the restore path lays every page back down by the one layout
|
||
-- law below.
|
||
|
||
-- The era's word list (l.569-572): the WHOLE query first — a phrase match outranks
|
||
-- its own words — then every comma/space-separated token.
|
||
function OptionsSearch_Words(text)
|
||
local up = string.upper(text)
|
||
local words = { up }
|
||
for w in string.gfind(up, "([^, ]+)") do
|
||
table.insert(words, w)
|
||
end
|
||
return words
|
||
end
|
||
|
||
-- The era score (Blizzard_Settings.lua l.65-77 MatchesSearchTags): first word that
|
||
-- hits the tag scores last-first (matched length - 1); no hit is no match. Plain
|
||
-- find — the era passes plain=true, no pattern magic.
|
||
function OptionsSearch_Score(tag, words)
|
||
for _, w in ipairs(words) do
|
||
local first, last = string.find(tag, w, 1, true)
|
||
if first then return last - first end
|
||
end
|
||
return nil
|
||
end
|
||
|
||
-- The era gather+group (l.575-636): rows bucketed by score, scores walked high to
|
||
-- low; a category's group is born the first time one of its rows surfaces — so the
|
||
-- group ORDER is best-score order — and collects that category's matches as the walk
|
||
-- descends. Returns the ordered group list { key, rkeys } .. .
|
||
function OptionsSearch_FindMatches(text)
|
||
local words = OptionsSearch_Words(text)
|
||
local buckets, scores = {}, {}
|
||
for _, key in ipairs(OPTIONS_CATEGORY_KEYS) do
|
||
if OPTIONS_PAGE_ROWS[key] then
|
||
for _, rkey in ipairs(OPTIONS_PAGE_ROWS[key]) do
|
||
local row = getglobal("BenillaOptionsFrameContainerBody" .. key .. rkey)
|
||
local s = OptionsSearch_Score(row.searchTag, words)
|
||
if s then
|
||
if not buckets[s] then
|
||
buckets[s] = {}
|
||
table.insert(scores, s)
|
||
end
|
||
table.insert(buckets[s], { key = key, rkey = rkey })
|
||
end
|
||
end
|
||
end
|
||
end
|
||
-- The keybinding entries join the same buckets (the era's searchable fake category
|
||
-- whose results REDIRECT to the Keybindings page — KeyBindingsPage.xml's search
|
||
-- note). Their rkey is the BINDING INDEX; the display fork below tells them apart
|
||
-- by the group key.
|
||
for _, m in ipairs(KeyBindings_SearchMatches(words)) do
|
||
if not buckets[m.score] then
|
||
buckets[m.score] = {}
|
||
table.insert(scores, m.score)
|
||
end
|
||
table.insert(buckets[m.score], { key = "Keybindings", rkey = m.index })
|
||
end
|
||
table.sort(scores, function(a, b) return a > b end)
|
||
local groups, order = {}, {}
|
||
for _, s in ipairs(scores) do
|
||
for _, m in ipairs(buckets[s]) do
|
||
if not groups[m.key] then
|
||
groups[m.key] = {}
|
||
table.insert(order, m.key)
|
||
end
|
||
table.insert(groups[m.key], m.rkey)
|
||
end
|
||
end
|
||
return order, groups
|
||
end
|
||
|
||
-- ── The page scroll (B217) ──────────────────────────────────────────────────────────
|
||
-- The body is the scroll child (the ScrollFrame above it), so what these two do is
|
||
-- decide how TALL it is: the content's own extent, or the visible page rect, whichever
|
||
-- is larger. Below the rect nothing changes at all — range 0, no bar, every page seated
|
||
-- exactly where its XML puts it — and above it the overflow becomes a scroll instead of
|
||
-- a spill.
|
||
--
|
||
-- The measured set is every element that takes a seat in the ONE layout law's chain:
|
||
-- each page's rows, the search group heads, and the keybinding result pool. All of them
|
||
-- hang off the body's TOP, so their extent is independent of the height being computed —
|
||
-- which is what makes this converge. Nothing anchored to the body's BOTTOM may join them
|
||
-- (the Keybindings page's output line is the live example): growing the body would move
|
||
-- it down, which would grow the body. IsVisible, not IsShown: a hidden page's rows keep
|
||
-- their own shown flag, and only what the player can actually see may set the height.
|
||
function OptionsScroll_ContentBottom()
|
||
local bottom = nil
|
||
local function take(name)
|
||
local f = getglobal(name)
|
||
if f and f:IsVisible() then
|
||
local b = f:GetBottom()
|
||
if b and (not bottom or b < bottom) then bottom = b end
|
||
end
|
||
end
|
||
for _, key in ipairs(OPTIONS_CATEGORY_KEYS) do
|
||
if OPTIONS_PAGE_ROWS[key] then
|
||
take("BenillaOptionsFrameContainerBodySearchHead" .. key)
|
||
for _, rkey in ipairs(OPTIONS_PAGE_ROWS[key]) do
|
||
take("BenillaOptionsFrameContainerBody" .. key .. rkey)
|
||
end
|
||
end
|
||
end
|
||
take("BenillaOptionsFrameContainerBodySearchHeadKeybindings")
|
||
for i = 1, KEYBINDINGS_SEARCH_ROWS do
|
||
take("BenillaOptionsFrameContainerBodyKeybindSearch" .. i)
|
||
end
|
||
return bottom
|
||
end
|
||
|
||
-- Size the body to that, from the scroll frame's OnUpdate. Frame-late by nature, and for
|
||
-- a reason that has nothing to do with the text measure: RECTS resolve after Lua runs, so
|
||
-- a pass that reads GetHeight() to reflow answers off the previous resolve however it is
|
||
-- driven. Write-gated: SetWidth/SetHeight invalidate layout, so an every-frame write
|
||
-- would fight the resolver. UpdateScrollChildRect re-drives the bar through
|
||
-- OnScrollRangeChanged, which is what shows and hides it (and its trough).
|
||
function OptionsScroll_Fit()
|
||
local sf = BenillaOptionsFrameContainerScroll
|
||
local body = BenillaOptionsFrameContainerBody
|
||
local fw, fh = sf:GetWidth(), sf:GetHeight()
|
||
if not fw or fw <= 0 or not fh or fh <= 0 then return end
|
||
if math.abs(body:GetWidth() - fw) >= 0.5 then body:SetWidth(fw) end
|
||
local h = fh
|
||
local top, bottom = body:GetTop(), OptionsScroll_ContentBottom()
|
||
if top and bottom then
|
||
local content = (top - bottom) + BENILLA_SCROLL_PAD
|
||
if content > h then h = content end
|
||
end
|
||
if math.abs(body:GetHeight() - h) >= 0.5 then
|
||
body:SetHeight(h)
|
||
sf:UpdateScrollChildRect()
|
||
end
|
||
end
|
||
|
||
-- THE one layout law (era SettingsList: verticalPad 10, padLeft 25/padRight 0 →
|
||
-- first element at (10,-12) off the body, spacing 9 → chain at (0,-9)). The rows'
|
||
-- authored XML anchors state exactly this chain as the initial layout; search
|
||
-- reflows steal rows out of it, and this function is how ANY element — row or search
|
||
-- head — takes a seat in it. prev is a global frame NAME (nil = the chain head).
|
||
function OptionsSearch_Place(name, prev)
|
||
local f = getglobal(name)
|
||
f:ClearAllPoints()
|
||
if prev then
|
||
f:SetPoint("TOPLEFT", prev, "BOTTOMLEFT", 0, -9)
|
||
f:SetPoint("TOPRIGHT", prev, "BOTTOMRIGHT", 0, -9)
|
||
else
|
||
f:SetPoint("TOPLEFT", "BenillaOptionsFrameContainerBody", "TOPLEFT", 10, -12)
|
||
f:SetPoint("TOPRIGHT", "BenillaOptionsFrameContainerBody", "TOPRIGHT", -20, -12)
|
||
end
|
||
end
|
||
|
||
-- Lay a page's rows back down on their authored chain (the XML anchors' law,
|
||
-- re-stated after a search reflow; the pin test holds the two equal).
|
||
function OptionsPage_Layout(key)
|
||
local prev = nil
|
||
for _, rkey in ipairs(OPTIONS_PAGE_ROWS[key]) do
|
||
local name = "BenillaOptionsFrameContainerBody" .. key .. rkey
|
||
OptionsSearch_Place(name, prev)
|
||
getglobal(name):Show()
|
||
prev = name
|
||
end
|
||
end
|
||
|
||
-- The results view (era OnSearchTextChanged's hasText arm, l.659-691): every page
|
||
-- body SHOWS (they are bare row hosts sharing one rect) with every row hidden, then
|
||
-- the groups chain down — category head, then its matches; a matched CHILD row pulls
|
||
-- its parent row in first (l.665-670, the era parentInitializer rule — our Audio
|
||
-- volumes ride under Master). Title reads "Search Results", Defaults hides while the
|
||
-- search holds the page (l.684-688), and an empty result shows the no-results line
|
||
-- (l.680-682).
|
||
function OptionsSearch_Display(text)
|
||
-- A new result set starts at the top (the era's own ScrollBox reset on a search).
|
||
BenillaOptionsFrameContainerScroll:SetVerticalScroll(0)
|
||
for k in pairs(OPTIONS_PAGE_ROWS) do
|
||
getglobal("BenillaOptionsFrameContainerBody" .. k):Show()
|
||
for _, rkey in ipairs(OPTIONS_PAGE_ROWS[k]) do
|
||
getglobal("BenillaOptionsFrameContainerBody" .. k .. rkey):Hide()
|
||
end
|
||
getglobal("BenillaOptionsFrameContainerBodySearchHead" .. k):Hide()
|
||
end
|
||
-- The Keybindings furniture leaves the stage with the rest: its body hides (the
|
||
-- search paints matched bindings on the shared pool below, not the page list), a
|
||
-- straggling capture disarms, and the pool starts blank.
|
||
getglobal("BenillaOptionsFrameContainerBodyKeybindings"):Hide()
|
||
getglobal("BenillaOptionsFrameContainerBodySearchHeadKeybindings"):Hide()
|
||
for i = 1, KEYBINDINGS_SEARCH_ROWS do
|
||
getglobal("BenillaOptionsFrameContainerBodyKeybindSearch" .. i):Hide()
|
||
end
|
||
KeyBindingsPage.searchPainted = nil
|
||
KeyBindings_SetSelected(nil)
|
||
BenillaOptionsFrameContainerUnbind:Hide()
|
||
BenillaOptionsFrameContainerTitle:SetText("Search Results")
|
||
BenillaOptionsFrameContainerDefaults:Hide()
|
||
|
||
local order, groups = OptionsSearch_FindMatches(text)
|
||
if table.getn(order) == 0 then
|
||
BenillaOptionsFrameContainerBodyNoResults:Show()
|
||
return
|
||
end
|
||
BenillaOptionsFrameContainerBodyNoResults:Hide()
|
||
local prev = nil
|
||
for _, key in ipairs(order) do
|
||
local head = "BenillaOptionsFrameContainerBodySearchHead" .. key
|
||
OptionsSearch_Place(head, prev)
|
||
getglobal(head):Show()
|
||
prev = head
|
||
if key == "Keybindings" then
|
||
-- Matched bindings painted LIVE onto the static pool (the era reflows its
|
||
-- real rows the same way; the pool caps the count — the SCOPE note in
|
||
-- KeyBindingsPage.xml — and the head above jumps to the full page).
|
||
KeyBindingsPage.searchPainted = {}
|
||
local shown = 0
|
||
for _, index in ipairs(groups[key]) do
|
||
if shown < KEYBINDINGS_SEARCH_ROWS then
|
||
shown = shown + 1
|
||
local name = "BenillaOptionsFrameContainerBodyKeybindSearch" .. shown
|
||
KeyBindings_PaintBindRow(name, index)
|
||
OptionsSearch_Place(name, prev)
|
||
getglobal(name):Show()
|
||
KeyBindingsPage.searchPainted[name] = index
|
||
prev = name
|
||
end
|
||
end
|
||
else
|
||
local placed = {}
|
||
for _, rkey in ipairs(groups[key]) do
|
||
local row = getglobal("BenillaOptionsFrameContainerBody" .. key .. rkey)
|
||
if row.parentRow and not placed[row.parentRow] then
|
||
placed[row.parentRow] = 1
|
||
local pname = "BenillaOptionsFrameContainerBody" .. key .. row.parentRow
|
||
OptionsSearch_Place(pname, prev)
|
||
getglobal(pname):Show()
|
||
prev = pname
|
||
end
|
||
if not placed[rkey] then
|
||
placed[rkey] = 1
|
||
local name = "BenillaOptionsFrameContainerBody" .. key .. rkey
|
||
OptionsSearch_Place(name, prev)
|
||
row:Show()
|
||
prev = name
|
||
end
|
||
end
|
||
OptionsPage_Refresh(key)
|
||
end
|
||
end
|
||
end
|
||
|
||
-- Ending a search: every page back on its authored chain, heads away, and the
|
||
-- selection re-applied — SelectCategory re-shows the one body, retitles, and brings
|
||
-- Defaults back (the era's no-text arm, l.655-658).
|
||
function OptionsSearch_Restore()
|
||
BenillaOptionsFrameContainerScroll:SetVerticalScroll(0)
|
||
for k in pairs(OPTIONS_PAGE_ROWS) do
|
||
OptionsPage_Layout(k)
|
||
getglobal("BenillaOptionsFrameContainerBodySearchHead" .. k):Hide()
|
||
end
|
||
for i = 1, KEYBINDINGS_SEARCH_ROWS do
|
||
getglobal("BenillaOptionsFrameContainerBodyKeybindSearch" .. i):Hide()
|
||
end
|
||
getglobal("BenillaOptionsFrameContainerBodySearchHeadKeybindings"):Hide()
|
||
KeyBindingsPage.searchPainted = nil
|
||
BenillaOptionsFrameContainerBodyNoResults:Hide()
|
||
BenillaOptionsFrameContainerDefaults:Show()
|
||
BenillaOptionsFrame_SelectCategory(BenillaOptionsFrame.selectedCategory or "Controls")
|
||
end
|
||
|
||
-- The text gate (era OnSearchTextChanged l.640-652): a repeat of the same text is a
|
||
-- no-op, and the FIRST change (searchText still nil — load-time initialization)
|
||
-- arms without acting; text clearing restores only if a search was actually live.
|
||
function OptionsSearch_OnTextChanged(text)
|
||
if text == BenillaOptionsFrame.searchText then return end
|
||
local had = BenillaOptionsFrame.searchText and BenillaOptionsFrame.searchText ~= ""
|
||
BenillaOptionsFrame.searchText = text
|
||
if text == "" then
|
||
if had then OptionsSearch_Restore() end
|
||
else
|
||
OptionsSearch_Display(text)
|
||
end
|
||
end
|
||
|
||
-- ── The setting pages: 1.12 rows in the era Settings grammar ────────────────────────
|
||
-- One machinery, every page (Audio 0957, the first). Semantics (rows, CVars, labels,
|
||
-- dependencies, the click-sound quirk) are the 1.12 client's own panels, quoted
|
||
-- verbatim (SoundOptionsFrame.lua / OptionsFrame.lua + GlobalStrings.lua); geometry is
|
||
-- the era settings list (Blizzard_SettingControls.xml/.lua + Blizzard_SettingsList.lua
|
||
-- @1.15.9 — 26-tall rows on a 9 spacing, label LEFT+37 → CENTER-85, control at
|
||
-- CENTER-80, child rows +15 indent in the small font). Era rows with no 1.12 CVar +
|
||
-- benilla knob behind them (Enable Sound=Sound_EnableAllSound, Dialog, output device,
|
||
-- channels…) do not ship — the 0950 honest-tree rule applied to settings.
|
||
-- The options strings that are NOT the reference's (1639, 1650). Every other
|
||
-- tooltip on this window resolves an OPTION_TOOLTIP_* out of 1.12's GlobalStrings, and a
|
||
-- benilla row with no counterpart there has so far simply gone mute (the nameplate pair).
|
||
-- Render Scale cannot afford to: the director's own reaction to the dial was "not really
|
||
-- sure what this does". So it gets a description, under a BENILLA_ prefix rather than an
|
||
-- invented OPTION_TOOLTIP_ -- the reference's namespace stays the reference's, and an
|
||
-- addon reading GlobalStrings still finds exactly what 1.12 defined.
|
||
BENILLA_TOOLTIP_RENDER_SCALE =
|
||
"Draws the 3D world at a fraction of the window's resolution, or larger than it. "
|
||
.. "The interface is unaffected at any setting.\n\n"
|
||
.. "Below 100% trades sharpness for frame rate; above 100% is supersampling, which "
|
||
.. "smooths edges at the cost of frame rate. Applies when you click Apply."
|
||
|
||
-- Enable Sound in Background (1847). An era row: 1.12 hardcodes the behaviour and has no
|
||
-- checkbox, so there is no OPTION_TOOLTIP_* to resolve and the BENILLA_ prefix applies
|
||
-- for the same reason Render Scale's does -- the reference's namespace stays the
|
||
-- reference's. The last line is not padding: mute is not pause on either client, and a
|
||
-- player who expects a paused fight to resume where it stopped is owed the difference.
|
||
BENILLA_TOOLTIP_BACKGROUND_SOUND =
|
||
"Keeps the game's sound playing while you are working in another window.\n\n"
|
||
.. "With this off, switching away silences the game and switching back restores it. "
|
||
.. "Sounds keep running while they are silenced, so a long one may have finished by "
|
||
.. "the time you return."
|
||
|
||
-- Display Mode (1650). 1.12's own OPTION_TOOLTIP_WINDOWED_MODE cannot ride this row: it
|
||
-- is written for the checkbox it belonged to ("Check to play in a non-fullscreen
|
||
-- window..."), and its second half describes a desktop-gamma consequence of an exclusive
|
||
-- mode-set we do not do. The row also has to answer the question a player arrives with —
|
||
-- "where is Fullscreen?" — which no reference string was ever written to answer.
|
||
BENILLA_TOOLTIP_DISPLAY_MODE =
|
||
"Windowed (Fullscreen) fills the screen with a borderless window; Windowed runs in "
|
||
.. "an ordinary one.\n\n"
|
||
.. "There is no exclusive fullscreen mode. WoW itself removed one in 8.0.1, and "
|
||
.. "modern Classic offers these same two."
|
||
|
||
-- Brightness (2182). 1.12's own OPTION_TOOLTIP_GAMMA cannot ride this row: its whole
|
||
-- second sentence is "Increase brightness until you can clearly see all 21 levels of gray
|
||
-- bars to the right", and those bars are the stock video window's own calibration art,
|
||
-- which this page does not have (2182 §7 names it as a follow-up). The row also has to answer the
|
||
-- question the reference never had to — why a brightness control works here at all, when
|
||
-- 1.12's did nothing outside exclusive fullscreen.
|
||
BENILLA_TOOLTIP_BRIGHTNESS =
|
||
"Lightens or darkens the whole picture — nights, caves and interiors are what it is "
|
||
.. "for.\n\n"
|
||
.. "This is the same correction 1.12 applied through the display's own gamma ramp, "
|
||
.. "which it could only do in exclusive fullscreen. benilla applies it to the "
|
||
.. "finished image instead, so it works in both display modes."
|
||
|
||
OPTIONS_PAGE_ROWS = {
|
||
-- Seven rows became sixteen at 2180, and the nine that arrived were not new
|
||
-- settings: every one names a CVar this client already registered AND read, with no
|
||
-- control anywhere a player could reach. The four camera toggles are why the record
|
||
-- exists — 2149 built their mechanisms and 2179 rebuilt water collision, and none of
|
||
-- the four could be turned off from inside the game.
|
||
--
|
||
-- SEATS: every row that was already here keeps the era-derived seat it had; each new
|
||
-- row takes the seat its own 1.12 box gives it, that box's COLUMNS read left to
|
||
-- right and flattened into this single one (the rule this page's Block Trades
|
||
-- comment already states). BasicOptionsGeneral runs 45 -> 3 -> 16 down its middle
|
||
-- column and 14 -> 61 down its right, so Attack on assist and Auto Clear AFK follow
|
||
-- Sticky Targeting and Auto Self Cast follows Block Trades. BasicOptionsCamera runs
|
||
-- the following-style dropdown -> 24 -> 26, then Slider2 -> 27 -> 15, then Slider3
|
||
-- -> Slider4 — which is the block below verbatim, and which leaves Max Camera
|
||
-- Distance exactly where it already sat, last.
|
||
Controls = {
|
||
"RowStickyTarget", "RowAssistAttack", "RowClearAFK",
|
||
"RowBlockTrades", "RowAutoSelfCast",
|
||
"RowAutoLoot", "RowInvertMouse", "RowMouseSpeed",
|
||
"RowCameraFollowStyle", "RowFollowTerrain", "RowHeadBob",
|
||
"RowAutoFollowSpeed", "RowWaterCollision", "RowSmartPivot",
|
||
"RowMouseLookSpeed", "RowMaxCameraDistance",
|
||
},
|
||
Audio = {
|
||
"RowEnableAll", "RowMaster", "RowSound", "RowMusic", "RowAmbience",
|
||
"RowEnableMusic", "RowEnableAmbience", "RowEnableErrorSpeech",
|
||
"RowBackgroundSound",
|
||
},
|
||
Graphics = {
|
||
"RowUiScale", "RowFarclip", "RowWorldDetail", "RowBrightness",
|
||
"RowWeatherDensity",
|
||
"RowDisplayMode", "RowVerticalSync", "RowRenderScale",
|
||
},
|
||
-- Player Guild Names (2180) rides as a CHILD of Player Names, which is the
|
||
-- reference's own relationship twice over: its CheckButton22 hangs off 21 with a +26
|
||
-- x indent, and UIOptionsFrame_UpdateDependencies l.702-708 greys 22 (and 23) from
|
||
-- 21's own tick. Its knob is `UnitNamePlayerGuild`, built by 2149's §6.
|
||
Nameplates = {
|
||
"RowEnemyPlates", "RowFriendlyPlates",
|
||
"RowPlayerNames", "RowGuildNames", "RowNpcNames", "RowOwnName",
|
||
},
|
||
-- The stock globals that were already defined AND consumed when 1134 opened the store
|
||
-- (1136; Buff Durations 1139), plus the two equipment-display toggles (1472), in the
|
||
-- reference's own on-screen order. Its Basic Options Display box is three COLUMNS read
|
||
-- left to right: A gives Enhanced Tooltips (CheckButton12, added 2180) then Status
|
||
-- Text (2), B gives Show Cloak → Show Helm
|
||
-- (31 → 20, sitting under the name toggles that live on our Nameplates page), C gives
|
||
-- the 42 → 39 → 66 chain. The **Help** box closes the page, and since 2077 it is
|
||
-- the box's own order rather than its one shippable row: 28 (Show Tutorials), 44
|
||
-- (Show Loading Screen Tips, anchored under 28 there) then 29 (Show Detailed
|
||
-- Tooltips). 28 was left out by 1140's census as an "index-only entry
|
||
-- with no store at all"; that reading missed the three special-case arms
|
||
-- `UIOptionsFrame_Load`/`_Save`/`_SetDefaults` keep for the key, which are its store.
|
||
-- The target-of-target pair (decision 1576) breaks that left-to-right reading, and
|
||
-- it has to: 1.12 keeps it in a box this window has no page for — Advanced Options'
|
||
-- "Raid & Party" — so there is no column order to preserve, only a neighbour to pick.
|
||
-- It sits under Status Text because that is the other unit-frame readout on the page.
|
||
Interface = {
|
||
"RowEnhancedTooltips", "RowStatusText", "RowTargetOfTarget", "RowTargetOfTargetMode",
|
||
"RowShowCloak", "RowShowHelm",
|
||
"RowInstantQuestText", "RowBuffDurations", "RowAutoQuestWatch",
|
||
"RowProfanityFilter",
|
||
"RowShowTutorials", "RowTipOfTheDay", "RowNewbieTips",
|
||
},
|
||
-- 1.12's Advanced Options **Chat** box (decision 1589, B246 — "no chat section in
|
||
-- options"). The page was called `Social` and held exactly the two chat-bubble
|
||
-- switches 1139 put on it; it is the reference's own `CHAT_LABEL` box now, and grew
|
||
-- into it. Order is the reference's own anchor chain (UIOptionsFrame.xml l.751-840:
|
||
-- CheckButton 7 → 8 → 13 → 18 → 37 → 46 → 38 → 51 → 68), with the rows we have no
|
||
-- mechanism for skipped rather than stubbed:
|
||
-- · 7 Simple Chat — needs FCF_Set_SimpleChat's re-layout (0288 §2)
|
||
-- · 8 Lock Chat Settings — the ONE row here whose machinery now exists: 1594
|
||
-- built the move, the resize and the blanket `CHAT_LOCKED` switch this
|
||
-- checkbox drives (`FCF_Set_ChatLocked`/`FCF_Get_ChatLocked`, gating both
|
||
-- verbs). It is unbuilt because nobody has asked for it, not because it
|
||
-- would be inert — and the per-window lock the tab menu carries is the one
|
||
-- a player actually reaches for. Ships when it is wanted
|
||
-- · 51 Auto-join Guild Recruitment Channel — **this note used to say the row is
|
||
-- inert in the reference too, and that was wrong** (corrected by 2115; it is
|
||
-- exactly the mistake 2077 corrected for SHOW_TUTORIALS). The table entry is a
|
||
-- bare `{ index = 51 }`, but the store is not in the TABLE — it is in the three
|
||
-- special-case arms `UIOptionsFrame_Load` (l.243-248, `GetGuildRecruitmentMode`),
|
||
-- `_Save` (l.326-331, `SetGuildRecruitmentMode`) and `_SetDefaults` (l.649) keep
|
||
-- for the key. Both verbs are ours now (2115), over the chat cache's
|
||
-- `OPTION_GUILD_RECRUITMENT_CHANNEL` latch. The row is unshipped here because
|
||
-- nobody has asked for it, not because it would be inert
|
||
-- Row 68, Disable Spam Filter, **shipped by 2077** — and the note it replaces was
|
||
-- wrong twice over, both corrected at the bytes by wow-re's `text-filter-law.md`.
|
||
-- The filter is not a word list, it is 28 compiled PCRE patterns from
|
||
-- `SpamMessages.dbc`; and it does not drop `CHAT_MSG_FILTERED` lines, it is armed for
|
||
-- every type EXCEPT that one (`0x49aad2`'s `jne` skips the disarm, which the older
|
||
-- note read backwards). It drops a matching line silently, with nothing in its place.
|
||
-- 1139's note about the 37 → 46 → 38 gap is closed by this record: 46 is Loot Spam,
|
||
-- and it has a knob now.
|
||
Chat = {
|
||
"RowGuildMemberAlert", "RowRemoveChatDelay", "RowChatBubbles", "RowLootSpam",
|
||
"RowPartyChatBubbles", "RowSpamFilter",
|
||
},
|
||
-- 1.12's Advanced Options "Action Bars" group, whole (decision 1500 completing 1136).
|
||
-- Its six rows, the four bar toggles then the grid switch then the lock. That is the
|
||
-- DIRECTOR's order, not the reference's: 1.12's box is two columns and leads with the
|
||
-- lock (CheckButton32 at its TOPLEFT, then 33/40/34 down the left, 35/36 down the
|
||
-- right), which does not survive being flattened into one column — the five switches
|
||
-- that decide what is on screen belong above the one that decides whether it can be
|
||
-- dragged. 1136 could ship only the lock, because the other five had
|
||
-- nothing behind them: the two bottom bars were unconditionally on and the two vertical
|
||
-- ones unconditionally hidden (0270/1219). 1500 made all four bars options, which is
|
||
-- what gave the five rows a store to read.
|
||
--
|
||
-- Two DIFFERENT stores on one page, and the split is verified rather than chosen: the
|
||
-- four bar rows are `func` rows over the server's own PLAYER_FIELD_BYTES byte 2 (no
|
||
-- local store exists to save), while Always Show ActionBars is a `uvar` row — the
|
||
-- engine binding takes exactly four arguments and silently drops the fifth the
|
||
-- reference passes it, so that switch has no server side at all. Decision 1500 and
|
||
-- wow-re action-bar-toggles.md carry the byte-level evidence.
|
||
ActionBars = {
|
||
"RowMultiBar1", "RowMultiBar2", "RowMultiBar3", "RowMultiBar4",
|
||
"RowAlwaysShowMultibars", "RowLockActionBar",
|
||
},
|
||
-- The floating-combat-text family (decision 1134), in the reference's own on-screen
|
||
-- order — its AdvancedOptionsCombatText box's anchor chain, master → scroll mode →
|
||
-- the twelve, NOT its check-button index order (which jumps 58→60→63…59→69).
|
||
Combat = {
|
||
"RowCombatText", "RowFloatMode", "RowLowHealthMana", "RowAuras", "RowAuraFade",
|
||
"RowCombatState", "RowDodgeParryMiss", "RowResistances", "RowReputation",
|
||
"RowReactives", "RowFriendlyNames", "RowComboPoints", "RowEnergyGains",
|
||
"RowHonorGained",
|
||
-- The damage-NUMBER trio (2180) shares the reference's box and NOT its master:
|
||
-- 19 -> 11 -> 9 close the AdvancedOptionsCombatText anchor chain, and the
|
||
-- "Additional combat text dependancies" block that greys 53…69 never names them
|
||
-- — 19 runs its own pair instead (UIOptionsFrame.lua l.709-714). So Show Target
|
||
-- Damage is a second, independent master on this page, and the two under it are
|
||
-- its children.
|
||
"RowShowDamage", "RowPeriodicDamage", "RowPetDamage",
|
||
},
|
||
}
|
||
|
||
-- `tip` is the GlobalStrings KEY of the row's description (B223, decision 1054) — the key,
|
||
-- not the text: it resolves at HOVER, the way the 1.12 Interface panel resolves its own
|
||
-- (UIOptionsFrame.lua l.265, `getglobal("OPTION_TOOLTIP_"..key)`), so the row is wired
|
||
-- before GlobalStrings has to exist. nil = no 1.12 string for this setting (Auto Loot).
|
||
function OptionsRow_OnLoad(row, cvar, label, tip, child)
|
||
row.cvar = cvar
|
||
row.tip = tip
|
||
-- The search tag: the era's default is exactly the setting's display name
|
||
-- (SettingControls.lua l.773 AddSearchTags(name)), uppercased at registration
|
||
-- (Blizzard_Settings.lua l.60).
|
||
row.searchTag = string.upper(label)
|
||
-- Kept, not just applied: the disabled-state font (OptionsRow_SetEnabled) has to pick
|
||
-- the SAME size the indent chose, or greying a child row also promotes it.
|
||
row.child = child
|
||
local l = getglobal(row:GetName() .. "Label")
|
||
l:SetText(label)
|
||
if child then
|
||
-- era child rows: +15 label indent and the small font
|
||
-- (SettingControls.lua l.319-322); the control itself does not indent.
|
||
l:SetFontObject("GameFontNormalSmall")
|
||
l:ClearAllPoints()
|
||
l:SetPoint("LEFT", row:GetName(), "LEFT", 52, 0)
|
||
l:SetPoint("RIGHT", row:GetName(), "CENTER", -85, 0)
|
||
end
|
||
end
|
||
|
||
-- ── The row's STORE: a CVar, a saved-variable global, or an API pair (1134, 1472) ──
|
||
-- 1.12's own Interface panel has THREE stores, not one: each UIOptionsFrameCheckButtons
|
||
-- entry carries `cvar = "name"` (an engine knob), `uvar = "GLOBAL"` (a RegisterForSave'd
|
||
-- Lua global), or a `func`/`setFunc` pair (an engine getter/setter with no client-side
|
||
-- store at all) — and UIOptionsFrame_Load/_Save fork on exactly that field
|
||
-- (UIOptionsFrame.lua l.230-377; the func fork at l.237-238 and l.296-297). Values are
|
||
-- strings in all three — "1"/"0" for a toggle — so only the accessor differs, and every row
|
||
-- in this file reads and writes through this trio instead of calling Get/SetCVar directly.
|
||
--
|
||
-- The third kind is what Show Helm / Show Cloak are: the preference is a bit of the
|
||
-- character's own server-side PLAYER_FLAGS, so there is nothing local to save and nothing
|
||
-- to restore at load — the getter IS the state (decision 1472).
|
||
-- **Does this row have somewhere to put a value?** The three stores of 1134, asked in the
|
||
-- order `OptionsRow_Set` tries them. A row with none is display-only and must not be
|
||
-- written.
|
||
--
|
||
-- It exists because the slider's OnValueChanged guarded on `row.cvar or row.uvar` — two of
|
||
-- the three — and so wrote nothing for a row whose store is an engine pair. The readout
|
||
-- still moved, which is the worst shape that bug can take: the control looks alive, the
|
||
-- setting never leaves the window, and nothing anywhere errors. Asking one predicate keeps
|
||
-- every caller in step with the setter by construction instead of by memory.
|
||
function OptionsRow_HasStore(row)
|
||
return row.uvar or row.setFunc or row.cvar
|
||
end
|
||
|
||
function OptionsRow_Get(row)
|
||
if row.uvar then return getglobal(row.uvar) end
|
||
if row.getFunc then
|
||
-- A NUMERIC api row (2182): the store is an engine getter whose answer is a
|
||
-- number, not a flag. 1.12's own video panel is where this shape comes from --
|
||
-- its slider table's `func` fork calls `getglobal("Get"..func)` and feeds the
|
||
-- result straight to `slider:SetValue` (OptionsFrame.lua l.110/135) -- and the
|
||
-- Brightness row is the one benilla ships. Normalised through the SAME two-decimal
|
||
-- strip the slider writes with, so a value sitting on the default compares equal
|
||
-- to it as a string and the pending/committed test below still works.
|
||
if row.numeric then
|
||
return (string.gsub(string.format("%.2f", row.getFunc()), "%.?0+$", ""))
|
||
end
|
||
if row.getFunc() then return "1" else return "0" end
|
||
end
|
||
return GetCVar(row.cvar)
|
||
end
|
||
|
||
-- The write. A global's consumers are Lua and do not poll, so a uvar row also runs its
|
||
-- `applyFunc` — the reference's own per-uvar side effects (SIMPLE_CHAT → FCF_Set_*,
|
||
-- HIDE_PARTY_INTERFACE → RaidOptionsFrame_UpdatePartyFrames, the combat-text family →
|
||
-- CombatText_UpdateDisplayedMessages), moved from its batched Okay to our live write
|
||
-- because this window commits on the click (0961's grammar), not on a Save button.
|
||
-- `cvarEvent` is a CVar row's counterpart to a global row's `applyFunc`, and it is the
|
||
-- reference's own third SetCVar argument (decision 1140): the token the engine hands back
|
||
-- as `CVAR_UPDATE`'s arg1. 1.12 passes its CheckButtons table KEY there
|
||
-- (`SetCVar(value.cvar, value.value, index)`), so a consumer that wants to react the
|
||
-- INSTANT the switch moves — rather than on its next repaint — has something to listen
|
||
-- for. nil on a row nobody listens to, which is most of them: the host polls its knob.
|
||
function OptionsRow_Set(row, value)
|
||
if row.uvar then
|
||
setglobal(row.uvar, value)
|
||
-- `applyFunc` is a global's NAME: the rows are read at this file's load, which since
|
||
-- 1938 sits at the reference's slot — before every file an apply lives in — so the
|
||
-- function is looked up when the row is applied, not when it is declared. A name
|
||
-- with no global behind it (a page harness without that definer) applies nothing,
|
||
-- which is what a nil capture always did.
|
||
local apply = row.applyFunc
|
||
if type(apply) == "string" then apply = getglobal(apply) end
|
||
if apply then apply() end
|
||
return
|
||
end
|
||
-- An API row hands the setter the row's own "1"/"0" STRING, which is what 1.12 does
|
||
-- (UIOptionsFrame_Save l.290-297 builds value.value as a string and passes it
|
||
-- straight through) — so the engine binding reads its argument numerically and "0"
|
||
-- means off. No applyFunc: the setter IS the side effect.
|
||
if row.setFunc then
|
||
-- A numeric api row hands the setter a NUMBER, which is what 1.12 does for the
|
||
-- shape it borrows from: `OptionsFrame_Save` passes `slider:GetValue()`
|
||
-- (OptionsFrame.lua l.206-226), not a string.
|
||
if row.numeric then
|
||
row.setFunc(tonumber(value))
|
||
else
|
||
row.setFunc(value)
|
||
end
|
||
return
|
||
end
|
||
SetCVar(row.cvar, value, row.cvarEvent)
|
||
OptionsRow_WritePartner(row, value)
|
||
end
|
||
|
||
-- **The PARTNER write (2180).** Three of 1.12's own rows drive a SECOND CVar that
|
||
-- appears in neither option table, from the special-case arms of `UIOptionsFrame_Save`:
|
||
-- Show Pet Melee Damage writes `PetSpellDamage` beside `PetMeleeDamage` (l.334-336), and
|
||
-- the two camera-speed sliders each write their pitch twin at a fixed ratio (l.351-356,
|
||
-- yaw/4 for the follow speed and yaw/2 for the look speed). Without this a row is a HALF
|
||
-- write — the box reads "pet damage off" while pet SPELL damage keeps floating — and it
|
||
-- is silent, because `SetCVar` on a name nobody wrote is not an error, it is a value
|
||
-- that stayed where it was.
|
||
--
|
||
-- `scale` nil means a flag: the same "1"/"0" string goes to both. A number scales, and
|
||
-- the result is formatted the way the slider path formats its own write (two decimals,
|
||
-- trailing zeros stripped) so a partner sitting at its registered default compares equal
|
||
-- to it as a STRING and stays out of the config file.
|
||
function OptionsRow_WritePartner(row, value)
|
||
if not row.partner then return end
|
||
local v = value
|
||
if row.partner.scale then
|
||
v = string.gsub(
|
||
string.format("%.2f", tonumber(value) * row.partner.scale), "%.?0+$", "")
|
||
end
|
||
SetCVar(row.partner.cvar, v)
|
||
end
|
||
|
||
-- The registered default — GetCVarDefault's counterpart for a global. `udefault` is the
|
||
-- value the defining XML assigned at FILE SCOPE, captured at this row's OnLoad: the whole
|
||
-- UI's XML loads before the saved-variables chunk executes over it (decision 1128's load
|
||
-- order), so at OnLoad the global still holds its shipped default. That makes the
|
||
-- assignment the single source of the default — the panel restates nothing and so cannot
|
||
-- drift from it, where the reference's table carries a second hand-written copy.
|
||
function OptionsRow_Default(row)
|
||
if row.uvar then return row.udefault end
|
||
if row.getFunc then return row.fdefault end
|
||
return GetCVarDefault(row.cvar)
|
||
end
|
||
|
||
-- A row whose store is a saved-variable global rather than a CVar. Same signature as
|
||
-- OptionsRow_OnLoad with the global's name in the cvar seat; the caller adds `applyFunc`
|
||
-- afterwards when the setting needs one.
|
||
function OptionsGlobalRow_OnLoad(row, uvar, label, tip, child)
|
||
OptionsRow_OnLoad(row, nil, label, tip, child)
|
||
row.uvar = uvar
|
||
row.udefault = getglobal(uvar)
|
||
end
|
||
|
||
-- A row with no store: an engine getter/setter pair, 1.12's own `func`/`setFunc` shape
|
||
-- (decision 1472). `default` has to be stated because there is no registered default to
|
||
-- ask for — the reference states it the same way, as a hand-written arm of
|
||
-- UIOptionsFrame_SetDefaults (l.631-634, SHOW_CLOAK and SHOW_HELM both SetChecked(1)).
|
||
function OptionsFuncRow_OnLoad(row, getFunc, setFunc, default, label, tip, child)
|
||
OptionsRow_OnLoad(row, nil, label, tip, child)
|
||
row.getFunc = getFunc
|
||
row.setFunc = setFunc
|
||
row.fdefault = default
|
||
end
|
||
|
||
-- The same, for a pair whose value is a NUMBER rather than a flag (2182) -- 1.12's video
|
||
-- panel's own `func` fork. `default` is still a string, because every store in this kit
|
||
-- answers in strings and the row compares them; the Brightness row computes it from
|
||
-- GetCVarDefault so the CVar table stays the one source.
|
||
function OptionsNumFuncRow_OnLoad(row, getFunc, setFunc, default, label, tip, child)
|
||
OptionsFuncRow_OnLoad(row, getFunc, setFunc, default, label, tip, child)
|
||
row.numeric = 1
|
||
end
|
||
|
||
-- ── THE LOAD-TIME LADDER IS THE REFERENCE'S OWN AGAIN (decision 2115) ──────────────
|
||
--
|
||
-- The problem it solves is real and unchanged (decision 1139): the whole UI's XML runs
|
||
-- BEFORE the saved chunk executes over it (1128's load order), so every file-scope
|
||
-- consumer of a `RegisterForSave`'d global already ran against the SHIPPED default, and
|
||
-- the saved value landing afterwards changes the variable while leaving the world it
|
||
-- configured alone. A CVar row needs nothing — the host reads its own table at boot.
|
||
--
|
||
-- 1.12 closes it with a hand-written ladder in `UIOptionsFrame_OnEvent`'s VARIABLES_LOADED
|
||
-- arm (UIOptionsFrame.lua l.193-227): `BuffButtons_UpdatePositions`, the SIMPLE_CHAT and
|
||
-- CHAT_LOCKED arms, `SetChatMouseOverDelay(REMOVE_CHAT_DELAY)`,
|
||
-- `MultiActionBar_ShowAllGrids`, `RaidOptionsFrame_UpdatePartyFrames`, and
|
||
-- `UIParentLoadAddOn("Blizzard_CombatText")`. **That arm runs here now**, off the player's
|
||
-- chain, because the stock file is loaded (hidden) at the manifest's l.21 seat — so this
|
||
-- window used to re-express a ladder that did not exist and now would be a SECOND copy of
|
||
-- one that does.
|
||
--
|
||
-- So the walk is gone, and with it `OptionsFrame_ApplySavedSettings`, this window's
|
||
-- VARIABLES_LOADED registration, and the multibar grid row's `loadFunc`. What the walk did
|
||
-- that the stock arm does not, checked one by one rather than assumed:
|
||
--
|
||
-- · `BuffButtons_UpdatePositions`, `SetChatMouseOverDelay`, `MultiActionBar_ShowAllGrids`
|
||
-- and `UIParentLoadAddOn("Blizzard_CombatText")` — the stock arm does all four, and it
|
||
-- runs FIRST (its frame registers at the l.21 seat, ours would register 30 rows later).
|
||
-- · `CombatText_UpdateDisplayedMessages` — the stock arm does not call it, and does not
|
||
-- need to: `Blizzard_CombatText`'s own `CombatText_OnLoad` calls it as its first act
|
||
-- (Blizzard_CombatText.lua l.81-84), and the addon loads INSIDE the stock arm, by
|
||
-- which time the saved uvars are already in place.
|
||
-- · `TargetofTarget_Update` — the stock arm does not call it either, and at
|
||
-- VARIABLES_LOADED there is no target, so `TargetFrame.lua:504`'s guard takes the else
|
||
-- branch and hides a frame that is already hidden. The row keeps it as its `applyFunc`,
|
||
-- which is the click behaviour and the only thing it was ever needed for.
|
||
--
|
||
-- The property the walk carried that still matters is `OptionsRow_Set`'s, and it stays
|
||
-- there: an `applyFunc` is a NAME, resolved when the row is applied, so a row whose
|
||
-- defining file a test harness never loaded applies nothing instead of raising.
|
||
|
||
-- A slider row's own range and readout, when the template's 0..1 / 5% / percent (the
|
||
-- volume shape) isn't it — called after OptionsRow_OnLoad in the row's OnLoad. The
|
||
-- refreshing guard: SetMinMaxValues re-clamps the held value and fires OnValueChanged,
|
||
-- and that clamp is wiring, not a player gesture — without the guard every load would
|
||
-- SetCVar the template's 0 clamped into the new range.
|
||
-- ── OptionsFrameSliders — THE REFERENCE'S TABLE, NOT OURS ANY MORE (2177) ───────────
|
||
-- `OptionsFrameSliders` is the video options window's own slider table (ref
|
||
-- `OptionsFrame.lua` l.24-34): one row per graphics slider, carrying the bounds the slider
|
||
-- is built with, PUBLISHED so addons can read and write it — pfUI's `hdgraphic` opens with
|
||
-- `_G.OptionsFrameSliders[3].maxValue = 15` (modules/hdgraphic.lua l.3).
|
||
--
|
||
-- **This file used to declare it, and no longer does.** Until 2177 the video window was not
|
||
-- loaded, so the name was free and our Graphics page published its own three rows into it
|
||
-- to keep that addon write landing on something. The stock window is on the manifest now
|
||
-- and brings the reference's own nine rows — and this file loads AFTER it, so a declaration
|
||
-- here would not sit beside them, it would REPLACE them, and `OptionsFrame_Load`'s
|
||
-- `getglobal("OptionsFrameSlider"..index)` walk would silently stop at three of nine.
|
||
--
|
||
-- **Nothing is lost, because our three rows WERE its rows 1-3.** Same order, same `func`
|
||
-- strings, same bounds: `uiscale` 0.64-1.0 step 0.01, `farclip` 177-777 step
|
||
-- (777-177)/10 = 60, `WorldDetail` 0-2 step 1. The Graphics page below still reads
|
||
-- `OptionsFrameSliders[1..3]` for its bounds — now off the reference's own table rather
|
||
-- than a transcription of it, which is the whole point of 1751 — and pfUI's index 3 still
|
||
-- lands on Environment Detail.
|
||
--
|
||
-- What WAS ours in those rows is the `benillaRow` field, and it moves here.
|
||
-- `BENILLA_GRAPHICS_SLIDER_ROWS` is index → the child of our Graphics page that the
|
||
-- reference's row drives; the reference addresses its own sliders as
|
||
-- `OptionsFrameSlider1..9`, a numbering our page does not use. An index with no entry is a
|
||
-- reference row we ship no knob for (rows 4, 5, 7 and 8: TerrainMip, BaseMip,
|
||
-- anisotropic, spellEffectLevel), and the OnShow re-apply loop skips it. Rows 6 and 9 are
|
||
-- Brightness (2182) and Weather Intensity (2181), which is why this table now has HOLES
|
||
-- rather than a run: the loop below is `for i, name in` — Lua 5.0's old-style `pairs` —
|
||
-- so it walks the keys that exist and an `ipairs` would have stopped at 3.
|
||
BENILLA_GRAPHICS_SLIDER_ROWS = {
|
||
"RowUiScale", "RowFarclip", "RowWorldDetail",
|
||
[6] = "RowBrightness", [9] = "RowWeatherDensity",
|
||
}
|
||
--
|
||
-- **Both WorldDetail verbs are bound** (2163), which is what makes pfUI's module RUN
|
||
-- rather than merely load: it hooks `SetWorldDetail`/`GetWorldDetail`, and hooking a nil
|
||
-- took its extended arm down at the first call. `SetWorldDetail` is `0x488dd0`'s carve —
|
||
-- truncate toward zero, `[0, 2]` or raise `"value must be in the range 0, 2"`, write the
|
||
-- `0x804518` stops {16, 32, 48} — and `GetWorldDetail` is `0x488d70` answering the stop.
|
||
-- They live in `benilla_ui::script::cvars`, not here; this page still drives the CVar
|
||
-- directly, so nothing on it calls either. The STOCK file does, now that it is loaded:
|
||
-- `OptionsFrame_Save`/`_Load` prefer `getglobal("Set"..func)` / `("Get"..func)` over
|
||
-- `SetCVar`/`GetCVar` (`OptionsFrame.lua` l.110/135/206-226) — but nothing of ours calls
|
||
-- those functions, because nothing of ours shows that window.
|
||
--
|
||
-- **The nine CVars pfUI's `hdgraphic` drives through `ConsoleExec`, each pinned** (2163;
|
||
-- `ConsoleExec` itself is bound since 1948 — it writes a registered CVar or pushes a
|
||
-- console command the app dispatches). Registered here, so the write lands:
|
||
-- `frillDensity` (2151, the clutter knob) and `nearClip` (2163, the camera near plane —
|
||
-- `0x511bd4` re-stamps `[cam+0x38]` from its record every frame, so it was never the dead
|
||
-- knob our own const claimed). Registered in the REFERENCE but with no benilla reader, so
|
||
-- they reach nothing here and registering them would be 1203's silent pretence:
|
||
-- `lodDist` (`0x688524`, "100.0" — its `[0x867960]` IS read at `0x6afb1d`, the doodad LOD
|
||
-- swap we do not have), `footstepBias` (`0x6888b4`, "0.125" — alive at `0x68fcb6`, but a
|
||
-- derived constant here with nothing to honour a write), `mapObjLightLOD` (`0x6886ec`,
|
||
-- "0") and `SkyCloudLOD` (`0x6d1d33`, "0"). Registered there and DEAD there — one writer,
|
||
-- no reader image-wide, so the reference renders identically whatever they say (wow-re
|
||
-- `cvar/scratch/graphics-cost-cvar-census.md` §8): `DistCull` (`0x688570`) and
|
||
-- `texLodBias` (`0x6885e2`, whose sink `0x672640` is literally `ret 4`). And `maxLOD` is
|
||
-- **not a CVar at all** — zero of the 214 `CVar::Register 0x63db90` sites name it — so
|
||
-- pfUI's `ConsoleExec("maxLOD " .. arg)` reaches nothing in the real client either.
|
||
|
||
function OptionsSliderRow_Setup(row, min, max, step, fmt, stops)
|
||
local slider = getglobal(row:GetName() .. "ControlSlider")
|
||
row.fmt = fmt
|
||
-- Kept for the "travel" readout, which is a share of this row's own range.
|
||
row.minv, row.maxv = min, max
|
||
-- A grid that IS a short named ladder passes its names here (Environment Detail's
|
||
-- Low/Medium/High over 0/1/2): the groove is still the reference's slider, and the
|
||
-- readout says the stop rather than its index. 1.12's own slider printed no value at
|
||
-- all — it labelled the two ENDS — but every slider row in this kit carries a readout,
|
||
-- and "1" is the one thing that seat could say that means nothing to a player.
|
||
row.stops = stops
|
||
row.refreshing = 1
|
||
slider:SetMinMaxValues(min, max)
|
||
slider:SetValueStep(step)
|
||
row.refreshing = nil
|
||
end
|
||
|
||
-- ── The dropdown rows (0992): the 1.12 kit under the era row grammar ────────────────
|
||
-- A dropdown row's choices: entries = { {text=..., value=...}, ... }, values the CVar's
|
||
-- own strings. The kit does the rest: every open re-runs the init through the stored
|
||
-- initialize (Toggle's own law), and AddButton auto-checks the entry matching the
|
||
-- capsule's selectedValue — which OptionsDropdown_ShowValue keeps equal to the CVar.
|
||
function OptionsDropdownRow_Setup(row, entries)
|
||
row.entries = entries
|
||
local dd = getglobal(row:GetName() .. "Dropdown")
|
||
UIDropDownMenu_SetWidth(180, dd)
|
||
UIDropDownMenu_Initialize(dd, OptionsDropdownRow_InitMenu)
|
||
-- The capsule's toggle button is a mouse-enabled child — it steals hover from the
|
||
-- row, so it carries the row wash like the checkbox rows' box does. Hooked here
|
||
-- (SetScript) because the capsule template is the shared kit's, not this file's.
|
||
local btn = getglobal(dd:GetName() .. "Button")
|
||
btn:SetScript("OnEnter", function() OptionsRow_Hover(this:GetParent():GetParent(), 1) end)
|
||
btn:SetScript("OnLeave", function() OptionsRow_Hover(this:GetParent():GetParent(), nil) end)
|
||
end
|
||
|
||
function OptionsDropdownRow_InitMenu()
|
||
local dd = getglobal(UIDROPDOWNMENU_INIT_MENU)
|
||
local row = dd:GetParent()
|
||
for _, e in ipairs(row.entries) do
|
||
local info = {}
|
||
info.text = e.text
|
||
info.value = e.value
|
||
info.func = OptionsDropdownEntry_OnClick
|
||
UIDropDownMenu_AddButton(info)
|
||
end
|
||
end
|
||
|
||
-- The entry click (`this` = the list row, the kit's own calling law): the write, then
|
||
-- the capsule redisplay. The kit closes the list and plays its own click sound.
|
||
function OptionsDropdownEntry_OnClick()
|
||
local dd = UIDropDownMenu_GetCurrentDropDown()
|
||
local row = dd:GetParent()
|
||
OptionsRow_Set(row, this.value)
|
||
OptionsDropdown_ShowValue(row)
|
||
end
|
||
|
||
-- Paint the capsule from the CVar. selectedValue is written as a FIELD, not through
|
||
-- SetSelectedValue: that helper's Refresh walks the SHARED DropDownList1 buttons, which
|
||
-- may still hold another dropdown's rows on this refresh path (the list is closed) —
|
||
-- a foreign row matching by value would repaint our capsule with its text. An off-grid
|
||
-- CVar value (an env A/B, a hand edit) displays the NEAREST stop — 0959's out-of-range
|
||
-- law, dropdown-flavored: control and check agree on the nearest expressible value,
|
||
-- the engine keeps running the config's truth, nothing writes back until the player
|
||
-- actually picks an entry. (A non-numeric stray shows raw and checks nothing.)
|
||
function OptionsDropdown_ShowValue(row)
|
||
local dd = getglobal(row:GetName() .. "Dropdown")
|
||
local v = OptionsRow_Get(row)
|
||
local match
|
||
for _, e in ipairs(row.entries) do
|
||
-- `alt` is a second value the same entry ANSWERS to (1502): 1.12's own Camera
|
||
-- Following Style dropdown writes "3" for Never where the engine's tables are
|
||
-- indexed 0/1/2, so a config or addon carrying that value means Never — and the
|
||
-- nearest-stop fallback below, which assumes the values are ordinal, would show
|
||
-- "Always" for it. A categorical dropdown says which strays are its own.
|
||
-- `e.alt ~= nil` guards the nil-eats-everything case: a row whose store is not
|
||
-- there yet reads nil, and every entry without an `alt` would otherwise ANSWER to
|
||
-- it (nil == nil), leaving the capsule showing the last entry and the row wearing
|
||
-- its description. An entry answers to a second value only if it has one.
|
||
if e.value == v or (e.alt ~= nil and e.alt == v) then match = e end
|
||
end
|
||
if not match and tonumber(v) then
|
||
local best
|
||
for _, e in ipairs(row.entries) do
|
||
local d = tonumber(e.value) and math.abs(tonumber(e.value) - tonumber(v))
|
||
if d and (not best or d < best) then
|
||
best = d
|
||
match = e
|
||
end
|
||
end
|
||
end
|
||
if match then
|
||
dd.selectedValue = match.value
|
||
UIDropDownMenu_SetText(match.text, dd)
|
||
-- A dropdown whose ENTRIES each carry their own description repaints the row's
|
||
-- plate as the selection moves — the reference's own shape for exactly this row
|
||
-- (UIOptionsFrameCameraDropDown_OnClick: `tooltip = getglobal("OPTION_TOOLTIP_
|
||
-- CAMERA"..GetSelectedID())`). Rows whose entries carry no `tip` keep the single
|
||
-- key OptionsRow_OnLoad gave them.
|
||
if match.tip then row.tip = match.tip end
|
||
else
|
||
dd.selectedValue = v
|
||
UIDropDownMenu_SetText(v, dd)
|
||
end
|
||
end
|
||
|
||
-- The right-hand readout text (era MinimalSlider's RIGHT label seat): rounded percent
|
||
-- (era FormatPercentage, Audio.lua l.406-411) unless the row asked for the raw number.
|
||
function OptionsRow_FormatValue(row, value)
|
||
if row.fmt == "raw" then
|
||
return string.format("%d", math.floor(value + 0.5))
|
||
end
|
||
-- A named ladder reads out its stop's name (see OptionsSliderRow_Setup). The index is
|
||
-- clamped, not wrapped: the slider itself has already clamped a config value from
|
||
-- outside the range, so this only ever guards a stops table shorter than the grid.
|
||
if row.stops then
|
||
local i = math.floor(value + 0.5) + 1
|
||
if i < 1 then i = 1 end
|
||
if i > table.getn(row.stops) then i = table.getn(row.stops) end
|
||
return row.stops[i]
|
||
end
|
||
-- A row whose stored value is a CENTRED OFFSET: show where the thumb is, as a share
|
||
-- of the groove (2182). Brightness is the case -- its stored unit is the reference's
|
||
-- own `1 - gamma`, which runs -0.5 .. +0.5 with the default at 0, and a readout of
|
||
-- "0%" on a brightness control that is doing nothing wrong is exactly backwards. As
|
||
-- travel it reads 0 .. 100 with the default at 50, the way a brightness control reads
|
||
-- everywhere else, while the value the store keeps stays the reference's.
|
||
if row.fmt == "travel" and row.minv and row.maxv and row.maxv > row.minv then
|
||
return string.format("%d%%",
|
||
math.floor((value - row.minv) / (row.maxv - row.minv) * 100 + 0.5))
|
||
end
|
||
-- A row whose stored value is a FACTOR but whose meaning is a distance: show the
|
||
-- distance (decision 1140 — cameraDistanceMaxFactor over the 15 yd base). The number
|
||
-- the player is choosing is "how far out the wheel stops", not "times 1.4".
|
||
if row.fmt == "yards" then
|
||
return string.format("%d yd", math.floor(value * 15 + 0.5))
|
||
end
|
||
return string.format("%d%%", math.floor(value * 100 + 0.5))
|
||
end
|
||
|
||
-- The era row-wide hover wash (HoverBackgroundTemplate, white a=0.1): the row and every
|
||
-- control on it show the SAME texture, so crossing from label to slider doesn't blink.
|
||
-- ONE seam carries the wash AND the plate (B223): every surface that lights the row also
|
||
-- raises its tooltip, so the two can never disagree — and the crossing is still seamless,
|
||
-- since the engine fires OnLeave before OnEnter within a move (pointer.rs), leaving the
|
||
-- hide/re-show inside a single frame.
|
||
function OptionsRow_Hover(row, on)
|
||
local hover = getglobal(row:GetName() .. "Hover")
|
||
if on then
|
||
hover:Show()
|
||
OptionsRow_ShowTooltip(row)
|
||
else
|
||
hover:Hide()
|
||
GameTooltip:Hide()
|
||
end
|
||
end
|
||
|
||
-- The row's descriptive plate (B223, decision 1054).
|
||
-- STRING: 1.12's own per-option text, by GlobalStrings key (see OptionsRow_OnLoad). A row
|
||
-- with no 1.12 string raises NOTHING — a plate whose only line echoes the label the cursor
|
||
-- is on is noise, and inventing a description would be inventing fidelity.
|
||
-- SHAPE: the 1.12/1.14 option-row plate — the description alone, wrapped, in the tooltip's
|
||
-- default gold (OptionsFrameTemplates.xml l.52-64: SetOwner + SetText(text, …, 1)); this
|
||
-- window already wears it on the Keybindings page's Character Specific row (1008). The era
|
||
-- pair (a white name line over the description) is cut — see the SCOPE note.
|
||
-- SEAT: the era's (DefaultTooltipMixin.OnEnter — ANCHOR_RIGHT, x -10, off the row's LABEL
|
||
-- half), carried by the $parentTip region, so the plate opens at the same column on every
|
||
-- row whichever surface the cursor crossed.
|
||
function OptionsRow_ShowTooltip(row)
|
||
local text = row.tip and getglobal(row.tip)
|
||
if text then
|
||
GameTooltip:SetOwner(getglobal(row:GetName() .. "Tip"), "ANCHOR_RIGHT", -10, 0)
|
||
GameTooltip:SetText(text, nil, nil, nil, nil, 1)
|
||
else
|
||
-- A mute row PUTS AWAY whatever the last row raised. Entering a row asserts "this
|
||
-- row's plate is what shows", so an early return isn't enough: the ordinary cursor
|
||
-- path is saved by the outgoing row's own OnLeave, but any caller that enters
|
||
-- without one (a driven hover, a re-layout under the cursor) would leave the
|
||
-- neighbour's description standing over a row it doesn't describe — a plate saying
|
||
-- the wrong thing is worse than a row saying nothing. 1.12's own handler has the
|
||
-- bare early-out; this is deliberate, and it is why the mute case has a test.
|
||
GameTooltip:Hide()
|
||
end
|
||
end
|
||
|
||
function OptionsCheckbox_OnClick(box)
|
||
local row = box:GetParent()
|
||
local checked = box:GetChecked()
|
||
-- Click kits: the 1.12 panels disagree with EACH OTHER — the interface panel's
|
||
-- PlayClickSound maps checked→CheckBoxOn (OptionsFrame.lua l.509), while the sound
|
||
-- panel's own OnClick maps checked→CheckBoxOff (SoundOptionsFrame.lua, the 0957
|
||
-- quirk) — so each page keeps its own panel's mapping (soundQuirk on Audio rows).
|
||
local kitOn = checked
|
||
if row.soundQuirk then kitOn = not kitOn end
|
||
if kitOn then
|
||
PlaySound("igMainMenuOptionCheckBoxOn")
|
||
else
|
||
PlaySound("igMainMenuOptionCheckBoxOff")
|
||
end
|
||
-- The write: checked = 1 — unless the row is value-INVERTED (Sticky Targeting:
|
||
-- 1.12 checks it when deselectOnClick is "0", era wraps the same CVar in
|
||
-- NegateBoolean; both references agree).
|
||
local on = checked
|
||
if row.invert then on = not on end
|
||
if on then
|
||
OptionsRow_Set(row, "1")
|
||
else
|
||
OptionsRow_Set(row, "0")
|
||
end
|
||
OptionsPage_UpdateDependencies(BenillaOptionsFrame.selectedCategory)
|
||
end
|
||
|
||
function OptionsSlider_OnValueChanged(slider, value)
|
||
local control = slider:GetParent()
|
||
local row = control:GetParent()
|
||
if not row.refreshing then
|
||
-- era obeyStepOnDrag (MinimalSlider.xml l.5-7): user moves snap to the step
|
||
-- grid — anchored at the range MINIMUM, the reference slider's own anchor
|
||
-- (farclip's 1.12 grid is 177+n*60, not the multiples of 60). A refresh
|
||
-- writes the stored value raw (era SetValue does not snap), so an off-grid
|
||
-- config value still lands where it said.
|
||
local step = slider:GetValueStep()
|
||
if step and step > 0 then
|
||
local minv = slider:GetMinMaxValues()
|
||
local snapped = minv + math.floor((value - minv) / step + 0.5) * step
|
||
if math.abs(snapped - value) > 0.00001 then
|
||
slider:SetValue(snapped) -- re-enters once with the snapped value
|
||
return
|
||
end
|
||
value = snapped -- the clean grid number, not the f32-rounded echo
|
||
end
|
||
end
|
||
getglobal(control:GetName() .. "Value"):SetText(OptionsRow_FormatValue(row, value))
|
||
if OptionsRow_HasStore(row) and not row.refreshing then
|
||
-- Two decimals cover every page's grid (the 5% volumes, uiScale's 0.01, whole
|
||
-- yards); trailing zeros stripped so a value at the registered default
|
||
-- compares equal to it as a STRING and stays out of the config file ("0.40"
|
||
-- would read as moved-off-"0.4").
|
||
local str = string.gsub(string.format("%.2f", value), "%.?0+$", "")
|
||
if row.deferred then
|
||
-- era CommitFlag.Apply, re-expressed (Blizzard_Setting.lua's staged
|
||
-- SetValue half): the control shows the new value, the ENGINE keeps the
|
||
-- old one, and the CVar moves only when Apply commits — dragging a
|
||
-- slider that rescales itself mid-drag is exactly what this flag
|
||
-- exists to prevent. Dragging back onto the committed value clears the
|
||
-- pending (era's IsModified: a pending EQUAL to current isn't one).
|
||
if str == OptionsRow_Get(row) then
|
||
row.pending = nil
|
||
else
|
||
row.pending = str
|
||
end
|
||
OptionsApply_Update()
|
||
else
|
||
OptionsRow_Set(row, str)
|
||
end
|
||
end
|
||
end
|
||
|
||
function OptionsPage_Refresh(key)
|
||
local base = "BenillaOptionsFrameContainerBody" .. key
|
||
for _, rkey in ipairs(OPTIONS_PAGE_ROWS[key]) do
|
||
local row = getglobal(base .. rkey)
|
||
local box = getglobal(base .. rkey .. "Check")
|
||
if box then
|
||
-- SetChecked takes the CVar string exactly like the 1.12 panel: the numeric
|
||
-- read means "0" unchecks (button-check-and-state-texture.md). A
|
||
-- value-inverted row checks on "0" instead — UIOptionsFrame.lua's own
|
||
-- GAMEFIELD_DESELECT arm (`checked = 1` when the CVar reads "0").
|
||
if row.invert then
|
||
local checked
|
||
if OptionsRow_Get(row) == "0" then checked = 1 end
|
||
box:SetChecked(checked)
|
||
else
|
||
box:SetChecked(OptionsRow_Get(row))
|
||
end
|
||
elseif row.entries then
|
||
OptionsDropdown_ShowValue(row)
|
||
else
|
||
local slider = getglobal(base .. rkey .. "ControlSlider")
|
||
row.refreshing = 1
|
||
-- Pending first (era GetValue returns the pendingValue while one is
|
||
-- staged): coming back to a page with an un-applied edit shows the edit.
|
||
slider:SetValue(tonumber(row.pending or OptionsRow_Get(row) or "0") or 0)
|
||
row.refreshing = nil
|
||
-- SetValue fires only on a CHANGE — write the readout unconditionally,
|
||
-- from the slider's OWN value: in range that IS the CVar (SetValue stores
|
||
-- raw), out of range the thumb and the number at least agree on the
|
||
-- nearest expressible value.
|
||
getglobal(base .. rkey .. "ControlValue"):SetText(
|
||
OptionsRow_FormatValue(row, slider:GetValue()))
|
||
end
|
||
end
|
||
OptionsPage_UpdateDependencies(key)
|
||
OptionsApply_Update()
|
||
end
|
||
|
||
-- Per-page dependency rules. Audio's is the 1.12 rule, verbatim: Enable All Sound off
|
||
-- greys Enable Ambience — and only it, of our rows
|
||
-- (SoundOptionsFrame_UpdateDependencies disables buttons 2 and 4, Ambience and Error
|
||
-- Speech; Enable Music stays live, the panel's own quirk).
|
||
function OptionsPage_UpdateDependencies(key)
|
||
if key == "Combat" then
|
||
-- The 1.12 rule, verbatim (UIOptionsFrame_UpdateDependencies' "Additional combat
|
||
-- text dependancies" block): the master off greys every FLOATING-TEXT sub-toggle
|
||
-- and the scroll dropdown. Combo Points carries the reference's second gate too —
|
||
-- it is disabled for anyone who is not a rogue or a druid, since nobody else has
|
||
-- combo points.
|
||
local on = SHOW_COMBAT_TEXT ~= "0"
|
||
local _, class = UnitClass("player")
|
||
class = class and string.upper(class)
|
||
local combo = class == "ROGUE" or class == "DRUID"
|
||
-- The damage-number trio is NOT under this master (2180). The reference's own
|
||
-- "Additional combat text dependancies" block names 53…69 and stops; 19/11/9 are
|
||
-- governed by the separate test at l.709-714. Greying them here would be a rule
|
||
-- the reference does not have, and it would read as "floating combat text off
|
||
-- means no damage numbers", which is the opposite of what CombatDamage does.
|
||
local damage = {
|
||
RowShowDamage = 1, RowPeriodicDamage = 1, RowPetDamage = 1,
|
||
}
|
||
for _, rkey in ipairs(OPTIONS_PAGE_ROWS.Combat) do
|
||
if rkey ~= "RowCombatText" and not damage[rkey] then
|
||
local live = on
|
||
if rkey == "RowComboPoints" and not combo then live = nil end
|
||
OptionsRow_SetEnabled(
|
||
getglobal("BenillaOptionsFrameContainerBodyCombat" .. rkey), live)
|
||
end
|
||
end
|
||
-- 1.12's second gate on this page, verbatim (l.709-714): Show Target Damage off
|
||
-- greys Periodic Damage and Pet Damage. The CVars keep their values — this is a
|
||
-- UI dependency, not a write — and the engine agrees with the shape: at
|
||
-- `CombatDamage` "0" both of `0x607140`/`0x6128b0`'s branch targets are
|
||
-- epilogues, so nothing floats from any source and the two sub-gates below have
|
||
-- nothing left to gate.
|
||
local dmg = GetCVar("CombatDamage") ~= "0"
|
||
OptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyCombatRowPeriodicDamage, dmg)
|
||
OptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyCombatRowPetDamage, dmg)
|
||
return
|
||
end
|
||
if key == "Controls" then
|
||
-- 1.12's own rule (l.715-719): the Auto-Follow Speed slider is dead while the
|
||
-- following style is Never, because there is no follow to set a speed for. The
|
||
-- reference tests its dropdown's selected ID against 3; ours stores the ENGINE's
|
||
-- values, where Never is "0" — and answers to "3" as well, since that is what
|
||
-- the reference's own dropdown writes and what a config or addon carrying it
|
||
-- means (the row's `alt`, decision 1502).
|
||
local style = GetCVar("cameraSmoothStyle")
|
||
OptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyControlsRowAutoFollowSpeed,
|
||
style ~= "0" and style ~= "3")
|
||
return
|
||
end
|
||
if key == "Nameplates" then
|
||
-- 1.12's own rule (l.702-708): Player Names off greys Player Guild Names. The
|
||
-- reference greys its PvP-title twin (CheckButton23) from the same test; that
|
||
-- row is still on the unbacked census, so there is one child here, not two.
|
||
OptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyNameplatesRowGuildNames,
|
||
GetCVar("UnitNamePlayer") ~= "0")
|
||
return
|
||
end
|
||
if key == "Interface" then
|
||
-- 1.12's own rule for this pair (UIOptionsFrame_UpdateDependencies l.694-700):
|
||
-- the mode picker is dead while the switch is unticked. It is the only
|
||
-- cross-row dependency on this page.
|
||
OptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyInterfaceRowTargetOfTargetMode,
|
||
SHOW_TARGET_OF_TARGET ~= "0")
|
||
return
|
||
end
|
||
if key == "ActionBars" then
|
||
-- 1.12's own rule for this pair, verbatim in effect (UIOptionsFrame.lua l.722-726):
|
||
-- Show Right ActionBar 2 is dead while Show Right ActionBar is unticked, because
|
||
-- MultiBarLeft does not appear without MultiBarRight under it (stock
|
||
-- MultiActionBar_Update's conjunction). It is the only cross-row dependency on this page — the two bottom
|
||
-- bars, the grid switch and the lock are all independent.
|
||
OptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyActionBarsRowMultiBar4,
|
||
SHOW_MULTI_ACTIONBAR_3)
|
||
return
|
||
end
|
||
if key ~= "Audio" then return end
|
||
-- 1.12's own rule, both halves: SoundOptionsFrame_UpdateDependencies greys check
|
||
-- button 2 (Enable Ambience) AND button 4 (Enable Error Speech) while the master
|
||
-- enable is unticked. Enable Music is deliberately left alive — the quirk the
|
||
-- reference's own file has.
|
||
local on = GetCVar("MasterSoundEffects") ~= "0"
|
||
for _, row in {"RowEnableAmbience", "RowEnableErrorSpeech"} do
|
||
local box = getglobal("BenillaOptionsFrameContainerBodyAudio"..row.."Check")
|
||
local label = getglobal("BenillaOptionsFrameContainerBodyAudio"..row.."Label")
|
||
if on then
|
||
box:Enable()
|
||
label:SetFontObject("GameFontNormal")
|
||
else
|
||
box:Disable()
|
||
label:SetFontObject("GameFontDisable")
|
||
end
|
||
end
|
||
end
|
||
|
||
-- Grey or wake one row, whichever control it wears (the Audio rule above predates this and
|
||
-- reaches its one checkbox by name). A dropdown row greys the way 1.12's own
|
||
-- OptionsFrame_DisableDropDown does — the capsule's toggle BUTTON disabled so the list
|
||
-- cannot open, and its text in GRAY_FONT_COLOR — since the chain's own
|
||
-- UIDropDownMenu_DisableButton addresses a LIST row (level, id), not the capsule, and
|
||
-- 1.12 has no `UIDropDownMenu_DisableDropDown` at all.
|
||
function OptionsRow_SetEnabled(row, on)
|
||
local name = row:GetName()
|
||
local box = getglobal(name .. "Check")
|
||
local dd = getglobal(name .. "Dropdown")
|
||
-- A SLIDER row greys the way 1.12's own OptionsFrame_DisableSlider does (l.481-486):
|
||
-- the THUMB is hidden — which is what says "this groove is dead" at a glance — and
|
||
-- the readout goes gray. Its Low/High end captions have no counterpart here; this kit
|
||
-- carries one readout instead of the reference's two.
|
||
--
|
||
-- **And the mouse bit, which the reference does not need and we do.** There is no
|
||
-- `Slider:Disable()` to call — 1.12 gives a Slider no enabled state at all, which is
|
||
-- why this kit's Slider has no such method (script/slider.rs's `begin_drag`) — and a
|
||
-- thumbless 1.12 slider is already undraggable. Ours is not: a press anywhere on the
|
||
-- track seats the value (0250 §5's jump), so a greyed groove would still answer a
|
||
-- click. `EnableMouse(false)` is how the reference keeps anything off the press, and
|
||
-- it takes the frame out of the hit test, so the row underneath keeps its hover wash
|
||
-- instead of losing it with the control.
|
||
local sl = getglobal(name .. "ControlSlider")
|
||
if box then
|
||
if on then box:Enable() else box:Disable() end
|
||
elseif sl then
|
||
local thumb = getglobal(name .. "ControlSliderThumb")
|
||
local value = getglobal(name .. "ControlValue")
|
||
if on then
|
||
sl:EnableMouse(true)
|
||
thumb:Show()
|
||
value:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g,
|
||
NORMAL_FONT_COLOR.b)
|
||
else
|
||
sl:EnableMouse(false)
|
||
thumb:Hide()
|
||
value:SetTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b)
|
||
end
|
||
elseif dd then
|
||
local text = getglobal(dd:GetName() .. "Text")
|
||
if on then
|
||
getglobal(dd:GetName() .. "Button"):Enable()
|
||
text:SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g,
|
||
HIGHLIGHT_FONT_COLOR.b)
|
||
else
|
||
getglobal(dd:GetName() .. "Button"):Disable()
|
||
text:SetTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b)
|
||
end
|
||
end
|
||
local label = getglobal(name .. "Label")
|
||
if on then
|
||
label:SetFontObject(row.child and "GameFontNormalSmall" or "GameFontNormal")
|
||
else
|
||
label:SetFontObject(row.child and "GameFontDisableSmall" or "GameFontDisable")
|
||
end
|
||
end
|
||
|
||
-- Defaults, live on any page with rows: every row's CVar back to its registered
|
||
-- default (era resets per-setting the same way; the era all-pages confirm dialog is
|
||
-- not modeled — Defaults resets the VISIBLE page). A pending edit dies with it — the
|
||
-- default write supersedes what Apply would have committed.
|
||
function OptionsPage_Defaults(key)
|
||
local base = "BenillaOptionsFrameContainerBody" .. key
|
||
for _, rkey in ipairs(OPTIONS_PAGE_ROWS[key]) do
|
||
local row = getglobal(base .. rkey)
|
||
row.pending = nil
|
||
OptionsRow_Set(row, OptionsRow_Default(row))
|
||
end
|
||
OptionsPage_Refresh(key)
|
||
end
|
||
|
||
-- ── The Apply flow (0961): era CommitFlag.Apply, cut to our rows ────────────────────
|
||
-- Pending edits are PANEL-wide like era's modified table: they survive a category
|
||
-- switch (the row redisplays its pending on return) and commit together; only hiding
|
||
-- the window discards them (era wipes on hide too — its close-time 3-button confirm
|
||
-- dialog and the 8-second revert timer are not modeled, SCOPE note).
|
||
|
||
-- The era Apply gate (HasUnappliedSettings + SetApplyButtonEnabled): the button is
|
||
-- enabled AND shown together — it EXISTS only while something is pending.
|
||
function OptionsApply_Update()
|
||
local pending
|
||
for key, rows in pairs(OPTIONS_PAGE_ROWS) do
|
||
local base = "BenillaOptionsFrameContainerBody" .. key
|
||
for _, rkey in ipairs(rows) do
|
||
if getglobal(base .. rkey).pending then pending = 1 end
|
||
end
|
||
end
|
||
if pending then
|
||
BenillaOptionsFrameApplyButton:Enable()
|
||
BenillaOptionsFrameApplyButton:Show()
|
||
else
|
||
BenillaOptionsFrameApplyButton:Disable()
|
||
BenillaOptionsFrameApplyButton:Hide()
|
||
end
|
||
end
|
||
|
||
-- Commit (era SettingsPanelMixin:CommitSettings, cut to our rows): every pending
|
||
-- value everywhere becomes a real SetCVar, and the button goes away.
|
||
function OptionsPage_Apply()
|
||
for key, rows in pairs(OPTIONS_PAGE_ROWS) do
|
||
local base = "BenillaOptionsFrameContainerBody" .. key
|
||
for _, rkey in ipairs(rows) do
|
||
local row = getglobal(base .. rkey)
|
||
if row.pending then
|
||
OptionsRow_Set(row, row.pending)
|
||
row.pending = nil
|
||
end
|
||
end
|
||
end
|
||
OptionsApply_Update()
|
||
end
|
||
|
||
-- Hide = discard (era's WipeModifiedTable-on-hide; the confirm dialog is cut): the
|
||
-- next open re-reads the committed CVars, so the sliders land back on the truth.
|
||
function OptionsPage_DiscardPending()
|
||
for key, rows in pairs(OPTIONS_PAGE_ROWS) do
|
||
local base = "BenillaOptionsFrameContainerBody" .. key
|
||
for _, rkey in ipairs(rows) do
|
||
getglobal(base .. rkey).pending = nil
|
||
end
|
||
end
|
||
OptionsApply_Update()
|
||
end
|
||
]]></Script>
|
||
|
||
<!-- The red panel button (era UIPanelButtonTemplate seat, 96x22): GameMenuButtonTemplate's
|
||
four-state UI-Panel-Button art + white/white/grey label trio, copied at this window's
|
||
size (GameMenuFrame.xml l.145 is the shared original; templates don't cross files). -->
|
||
<Button name="OptionsRedButtonTemplate" virtual="true">
|
||
<Size><AbsDimension x="96" y="22"/></Size>
|
||
<ButtonText name="$parentText"/>
|
||
<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>
|
||
<NormalFont inherits="GameFontHighlight"/>
|
||
<HighlightFont inherits="GameFontHighlight"/>
|
||
<DisabledFont inherits="GameFontDisable"/>
|
||
</Button>
|
||
|
||
<!-- One category row (era Blizzard_CategoryList.xml's category button): the template's
|
||
175 width is never rendered in the era either — the ScrollBox stretches every row to
|
||
the scroll target's width, 199 with no scroll bar (CategoryList.lua l.176-197 +
|
||
ScrollBoxViewUtil), and ours is the no-bar case. Gold label centered in the row (the
|
||
full-row box below).
|
||
The select/hover wash is the 1.14 OptionsListButtonTemplate mechanism VERBATIM (0984;
|
||
wow-ui-source @1.14.4 OptionsFrameTemplates.xml l.216-229 + .lua l.107-131 — 0978's
|
||
two-texture BLEND washes drew as opaque bars, the director's report): ONE
|
||
UI-QuestLogTitleHighlight quad in ADD blend, tinted steel-blue (.196,.388,.8) as the
|
||
hover and locked GOLD (1,1,0) on the selected row — 1.14's SetVertexColor pair around
|
||
LockHighlight/UnlockHighlight, carried here as Show/Hide on the Bg (our selection is
|
||
Lua-driven, not button-state-driven). Geometry stays the era plate seat (187x21
|
||
centered, 6 units in from either edge of the 199 row — sized once in
|
||
OptionsCategoryRow_OnLoad); hover text goes white via HighlightFont, 1.14's own trio. -->
|
||
<Button name="OptionsCategoryRowTemplate" virtual="true">
|
||
<Size><AbsDimension x="199" y="20"/></Size>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="$parentBg" file="Interface\QuestFrame\UI-QuestLogTitleHighlight" alphaMode="ADD" hidden="true">
|
||
<Anchors><Anchor point="CENTER"/></Anchors>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<!-- The era label is a box spanning the WHOLE row — TOPLEFT (36,+1) AND BOTTOMRIGHT
|
||
(0,+1), era CategoryList.xml l.72-77 — so the default MIDDLE vertical justify
|
||
CENTERS the text in the 20-tall row (1 unit high of true center, the era's own
|
||
nudge). The first cut had only the TOPLEFT corner: the auto-sized label hung from
|
||
the row TOP, ~4 units high of center ("text not vertically centered" — director,
|
||
2026-08-04). justifyH LEFT is the era's own attribute; a full-row box without it
|
||
would center horizontally. -->
|
||
<ButtonText name="$parentText" justifyH="LEFT">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="36" y="1"/></Offset></Anchor>
|
||
<Anchor point="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="1"/></Offset></Anchor>
|
||
</Anchors>
|
||
</ButtonText>
|
||
<NormalFont inherits="GameFontNormal"/>
|
||
<HighlightFont inherits="GameFontHighlight"/>
|
||
<DisabledFont inherits="GameFontDisable"/>
|
||
<Scripts>
|
||
<OnClick>BenillaOptionsFrame_SelectCategory(this.categoryKey)</OnClick>
|
||
<!-- 1.14's highlight shows on hover with the blue tint standing (the selected row
|
||
holds its locked gold — the guard is UnlockHighlight's job here). -->
|
||
<OnEnter>
|
||
if BenillaOptionsFrame.selectedCategory ~= this.categoryKey then
|
||
getglobal(this:GetName() .. "Bg"):Show()
|
||
end
|
||
</OnEnter>
|
||
<OnLeave>
|
||
if BenillaOptionsFrame.selectedCategory ~= this.categoryKey then
|
||
getglobal(this:GetName() .. "Bg"):Hide()
|
||
end
|
||
</OnLeave>
|
||
</Scripts>
|
||
</Button>
|
||
|
||
<!-- A category group header (era SettingsCategoryListHeaderTemplate geometry: 30 tall,
|
||
stretched to the 199 row width like the rows, 14px white label at LEFT (20,-1)). The
|
||
era's Options_CategoryHeader_<n> background wash has no 1.12 counterpart and is
|
||
dropped (header mapping note) — the header is its label alone. -->
|
||
<Frame name="OptionsCategoryHeaderTemplate" virtual="true">
|
||
<Size><AbsDimension x="199" y="30"/></Size>
|
||
<Layers>
|
||
<Layer level="OVERLAY">
|
||
<FontString name="$parentLabel" inherits="OptionsFontHighlightMedium">
|
||
<Anchors><Anchor point="LEFT"><Offset><AbsDimension x="20" y="-1"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
</Frame>
|
||
|
||
<!-- A search-results group header (era SettingsListSearchCategoryTemplate —
|
||
Blizzard_SettingsList.xml l.65-87 + .lua l.14-33): 45 tall, the category's name in
|
||
GameFontNormalLarge at TOPLEFT (16,-16), clickable — the click selects its category,
|
||
which ends the search (the era's own jump; SelectCategory clears the box). Unanchored
|
||
until a search chains it in (OptionsSearch_Place). The era's mouseover is a 0.1-gray
|
||
ADD overlay; this wears the setting rows' white-0.1 wash instead — the same read, the
|
||
file's one hover idiom (0984 notes the divergence). -->
|
||
<Button name="OptionsSearchHeadTemplate" virtual="true" hidden="true">
|
||
<Size><AbsDimension y="45"/></Size>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="$parentHover" hidden="true">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"/>
|
||
<Anchor point="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
<Color r="1" g="1" b="1" a="0.1"/>
|
||
</Texture>
|
||
</Layer>
|
||
<Layer level="ARTWORK">
|
||
<FontString name="$parentLabel" inherits="GameFontNormalLarge" justifyH="LEFT">
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="16" y="-16"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Scripts>
|
||
<OnClick>BenillaOptionsFrame_SelectCategory(this.categoryKey)</OnClick>
|
||
<OnEnter>getglobal(this:GetName() .. "Hover"):Show()</OnEnter>
|
||
<OnLeave>getglobal(this:GetName() .. "Hover"):Hide()</OnLeave>
|
||
</Scripts>
|
||
</Button>
|
||
|
||
<!-- One SETTING row, checkbox flavor (era SettingsCheckboxControlTemplate over
|
||
SettingsListElementTemplate, Blizzard_SettingControls.xml l.50-112): 26 tall, stretched
|
||
to the page width by its instance anchors; label GameFontNormal in a LEFT(37) →
|
||
CENTER(-85) box (the era mixin's runtime anchors, SettingControls.lua l.322-323); the
|
||
30x29 box at LEFT = row CENTER-80 (l.473). The checkbox art is the 1.12 UI-CheckBox
|
||
set at the era state seats (0978 mapping; the era used its minimal set): Up normal,
|
||
Down pushed, Check checked, Check-Disabled disabled+checked; no HighlightTexture —
|
||
hover feedback stays the era row-wide Hover wash (HoverBackgroundTemplate: white
|
||
a=0.1, hung 10 left / 5 right of the row), so the box doesn't double-light. -->
|
||
<Frame name="OptionsCheckboxRowTemplate" virtual="true" enableMouse="true">
|
||
<Size><AbsDimension y="26"/></Size>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="$parentHover" hidden="true">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="-10" y="0"/></Offset></Anchor>
|
||
<Anchor point="BOTTOMRIGHT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Color r="1" g="1" b="1" a="0.1"/>
|
||
</Texture>
|
||
</Layer>
|
||
<Layer level="OVERLAY">
|
||
<FontString name="$parentLabel" inherits="GameFontNormal" justifyH="LEFT">
|
||
<Anchors>
|
||
<Anchor point="LEFT"><Offset><AbsDimension x="37" y="0"/></Offset></Anchor>
|
||
<Anchor point="RIGHT" relativePoint="CENTER"><Offset><AbsDimension x="-85" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- The tooltip's SEAT (B223): the era's own anchor region, verbatim geometry — the
|
||
row's LABEL half, TOPLEFT out to (BOTTOM, -80), i.e. the control column
|
||
(SettingsListElementTemplate's $parentTooltip, Blizzard_SettingControls.xml
|
||
l.57-61). The era hangs its hover wash AND its mouse scripts here; ours borrows
|
||
the RECT only — the row lights and raises as one surface (OptionsRow_Hover) — so
|
||
this frame stays mouse-less and can never steal the row's own hover. -->
|
||
<Frame name="$parentTip">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"/>
|
||
<Anchor point="BOTTOMRIGHT" relativePoint="BOTTOM"><Offset><AbsDimension x="-80" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
</Frame>
|
||
<CheckButton name="$parentCheck">
|
||
<Size><AbsDimension x="30" y="29"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativePoint="CENTER"><Offset><AbsDimension x="-80" y="0"/></Offset></Anchor></Anchors>
|
||
<NormalTexture file="Interface\Buttons\UI-CheckBox-Up"/>
|
||
<PushedTexture file="Interface\Buttons\UI-CheckBox-Down"/>
|
||
<CheckedTexture file="Interface\Buttons\UI-CheckBox-Check"/>
|
||
<DisabledCheckedTexture file="Interface\Buttons\UI-CheckBox-Check-Disabled"/>
|
||
<Scripts>
|
||
<OnClick>OptionsCheckbox_OnClick(this)</OnClick>
|
||
<OnEnter>OptionsRow_Hover(this:GetParent(), 1)</OnEnter>
|
||
<OnLeave>OptionsRow_Hover(this:GetParent(), nil)</OnLeave>
|
||
</Scripts>
|
||
</CheckButton>
|
||
</Frames>
|
||
<Scripts>
|
||
<OnEnter>OptionsRow_Hover(this, 1)</OnEnter>
|
||
<OnLeave>OptionsRow_Hover(this, nil)</OnLeave>
|
||
</Scripts>
|
||
</Frame>
|
||
|
||
<!-- One SETTING row, slider flavor (era SettingsSliderControlTemplate →
|
||
MinimalSliderWithSteppersTemplate, SettingControls.lua l.550-552 + MinimalSlider.xml):
|
||
the same 26-tall row and label box; the 250x40 control at LEFT = row CENTER(-80,+3)
|
||
(its 40 height overrides the row symmetrically). Inside: the Slider inset 19 each
|
||
side — spanning the groove exactly — hit area the full height, the way era's is
|
||
(mouse-enabled by the widget's own construction, 0250's law — no attr needed). The
|
||
TRACK is the 0978 mapping — the 1.12 OptionsSliderTemplate groove verbatim
|
||
(extracted OptionsFrameTemplates.xml l.74: UI-SliderBar-Background/-Border backdrop,
|
||
edge 8, tile 8, insets 3/3/6/6) on a 17-tall Groove frame at the era track seat (the
|
||
era's own three-slice was 17 tall, centered), with the 1.12 32x32
|
||
UI-SliderBar-Button-Horizontal thumb. NO steppers — 0984 wore them at 26x26 as kept
|
||
era structure; 0989 cut them by the director's call (a recorded exception to 0985's
|
||
keep): the bar alone is the control, and the whole bar is live — thumb drag always
|
||
worked but the visible knob is a small target, so 0989's engine track-press law
|
||
seats the thumb under a press anywhere on the bar and drags on from there. The
|
||
readout is era's RIGHT label seat — 6 right of the control (MinimalSlider.xml
|
||
l.73-77), rounded-percent formatted.
|
||
THE +3 LIVES ON THE ART, NOT ON THE CONTROL (B232, decision 1641). It seats the
|
||
17-tall groove and the 32 px thumb inside the 26-tall row, so it belongs to the two
|
||
frames that draw them — $parentGroove and $parentSlider. It used to sit on
|
||
$parentControl itself, where the readout inherited it: every slider row drew its number
|
||
3 units above its own label, one line asked to read as two. The art's seat is unchanged
|
||
to the pixel; the text is what moved. -->
|
||
<Frame name="OptionsSliderRowTemplate" virtual="true" enableMouse="true">
|
||
<Size><AbsDimension y="26"/></Size>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="$parentHover" hidden="true">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="-10" y="0"/></Offset></Anchor>
|
||
<Anchor point="BOTTOMRIGHT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Color r="1" g="1" b="1" a="0.1"/>
|
||
</Texture>
|
||
</Layer>
|
||
<Layer level="OVERLAY">
|
||
<FontString name="$parentLabel" inherits="GameFontNormal" justifyH="LEFT">
|
||
<Anchors>
|
||
<Anchor point="LEFT"><Offset><AbsDimension x="37" y="0"/></Offset></Anchor>
|
||
<Anchor point="RIGHT" relativePoint="CENTER"><Offset><AbsDimension x="-85" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- The tooltip's seat — the era label-half region (the checkbox template's comment is
|
||
the recipe). The era anchors a SLIDER row's plate off the slider itself instead
|
||
(SettingControls.lua l.556, ANCHOR_RIGHT +20); ours keeps the one column, so a
|
||
walk down a page doesn't make the plate hop 250 units per row. -->
|
||
<Frame name="$parentTip">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"/>
|
||
<Anchor point="BOTTOMRIGHT" relativePoint="BOTTOM"><Offset><AbsDimension x="-80" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentControl">
|
||
<Size><AbsDimension x="250" y="40"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativePoint="CENTER"><Offset><AbsDimension x="-80" y="0"/></Offset></Anchor></Anchors>
|
||
<Layers>
|
||
<Layer level="OVERLAY">
|
||
<FontString name="$parentValue" inherits="GameFontNormal">
|
||
<Anchors><Anchor point="LEFT" relativePoint="RIGHT"><Offset><AbsDimension x="6" y="0"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- The groove: the 1.12 slider's own backdrop on a frame at the era track
|
||
seat (17 tall, vertically centered, spanning the slider's run).
|
||
Declared before the Slider so the thumb draws above it. -->
|
||
<Frame name="$parentGroove">
|
||
<Size><AbsDimension y="17"/></Size>
|
||
<Anchors>
|
||
<Anchor point="LEFT"><Offset><AbsDimension x="19" y="3"/></Offset></Anchor>
|
||
<Anchor point="RIGHT"><Offset><AbsDimension x="-19" y="3"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Backdrop bgFile="Interface\Buttons\UI-SliderBar-Background" edgeFile="Interface\Buttons\UI-SliderBar-Border" tile="true">
|
||
<EdgeSize><AbsValue val="8"/></EdgeSize>
|
||
<TileSize><AbsValue val="8"/></TileSize>
|
||
<BackgroundInsets><AbsInset left="3" right="3" top="6" bottom="6"/></BackgroundInsets>
|
||
</Backdrop>
|
||
</Frame>
|
||
<Slider name="$parentSlider" orientation="HORIZONTAL" minValue="0" maxValue="1" valueStep="0.05">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="19" y="3"/></Offset></Anchor>
|
||
<Anchor point="BOTTOMRIGHT"><Offset><AbsDimension x="-19" y="3"/></Offset></Anchor>
|
||
</Anchors>
|
||
<ThumbTexture name="$parentThumb" file="Interface\Buttons\UI-SliderBar-Button-Horizontal">
|
||
<Size><AbsDimension x="32" y="32"/></Size>
|
||
</ThumbTexture>
|
||
<Scripts>
|
||
<OnValueChanged>OptionsSlider_OnValueChanged(this, arg1)</OnValueChanged>
|
||
<OnEnter>OptionsRow_Hover(this:GetParent():GetParent(), 1)</OnEnter>
|
||
<OnLeave>OptionsRow_Hover(this:GetParent():GetParent(), nil)</OnLeave>
|
||
</Scripts>
|
||
</Slider>
|
||
</Frames>
|
||
</Frame>
|
||
</Frames>
|
||
<Scripts>
|
||
<OnEnter>OptionsRow_Hover(this, 1)</OnEnter>
|
||
<OnLeave>OptionsRow_Hover(this, nil)</OnLeave>
|
||
</Scripts>
|
||
</Frame>
|
||
|
||
<!-- One SETTING row, dropdown flavor (0992 — the first): the same era 26-tall row and
|
||
label box; the control is the 1.12 dropdown CAPSULE verbatim (UIDropDownMenuTemplate —
|
||
the kit every 1.12 dropdown wears, UIDropDownMenu.xml), seated so its box ink opens at
|
||
the era control column (the capsule's Left cap carries ~10 units of air before its
|
||
ink, hence the -71 anchor against the sliders' CENTER-80 + 19 groove seat; width 180
|
||
makes the ink span read as the slider track's). SHAPE provenance: the era's own
|
||
control for an enumerated setting is a dropdown (SettingsDropdownControlTemplate — its
|
||
Graphics page is a zoo of them), while 1.12 shaped this row's setting as a 3-stop
|
||
slider; the era grammar wins the shape by the director's call ("some with dropdown"),
|
||
recorded in 0992. The list the capsule opens rides the kit's own law — shared
|
||
DropDownList1, FULLSCREEN_DIALOG strata (above this HIGH window), the owner's
|
||
effective scale (the kit's 0992 correction), the 2-second hover-away close. -->
|
||
<Frame name="OptionsDropdownRowTemplate" virtual="true" enableMouse="true">
|
||
<Size><AbsDimension y="26"/></Size>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="$parentHover" hidden="true">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="-10" y="0"/></Offset></Anchor>
|
||
<Anchor point="BOTTOMRIGHT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Color r="1" g="1" b="1" a="0.1"/>
|
||
</Texture>
|
||
</Layer>
|
||
<Layer level="OVERLAY">
|
||
<FontString name="$parentLabel" inherits="GameFontNormal" justifyH="LEFT">
|
||
<Anchors>
|
||
<Anchor point="LEFT"><Offset><AbsDimension x="37" y="0"/></Offset></Anchor>
|
||
<Anchor point="RIGHT" relativePoint="CENTER"><Offset><AbsDimension x="-85" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- The tooltip's seat — the era label-half region (the checkbox template's comment is
|
||
the recipe). -->
|
||
<Frame name="$parentTip">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"/>
|
||
<Anchor point="BOTTOMRIGHT" relativePoint="BOTTOM"><Offset><AbsDimension x="-80" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentDropdown" inherits="UIDropDownMenuTemplate">
|
||
<Anchors><Anchor point="LEFT" relativePoint="CENTER"><Offset><AbsDimension x="-71" y="-2"/></Offset></Anchor></Anchors>
|
||
</Frame>
|
||
</Frames>
|
||
<Scripts>
|
||
<OnEnter>OptionsRow_Hover(this, 1)</OnEnter>
|
||
<OnLeave>OptionsRow_Hover(this, nil)</OnLeave>
|
||
</Scripts>
|
||
</Frame>
|
||
|
||
<!-- `toplevel` restored (ref OptionsFrame.xml l.3) — same class as the B180/Bagnon dialog
|
||
(decision 1318). NOTE our strata is HIGH where the ref is DIALOG; left as-is, flagged in
|
||
the record rather than silently changed. -->
|
||
<Frame name="BenillaOptionsFrame" parent="UIParent" frameStrata="HIGH" toplevel="true" enableMouse="true" hidden="true">
|
||
<Size><AbsDimension x="920" y="724"/></Size>
|
||
<Anchors><Anchor point="CENTER"/></Anchors>
|
||
<!-- The 1.14 System-window dialog, verbatim (BACKDROP_DIALOG_32_32 — wow-ui-source
|
||
@1.14.4 Backdrop.lua l.17-25, the backdrop OptionsFrameTemplate/
|
||
InterfaceOptionsFrame wear): the tiled UI-DialogBox-Background ground — a uniform
|
||
pure-black 60%-alpha tile, so the world reads through the window exactly like the
|
||
reference screenshot (0981: the reference was never parchment) — inside the rope
|
||
border. Both files are 1.12's own. -->
|
||
<Backdrop bgFile="Interface\DialogFrame\UI-DialogBox-Background" edgeFile="Interface\DialogFrame\UI-DialogBox-Border" tile="true">
|
||
<TileSize><AbsValue val="32"/></TileSize>
|
||
<EdgeSize><AbsValue val="32"/></EdgeSize>
|
||
<BackgroundInsets><AbsInset left="11" right="12" top="12" bottom="11"/></BackgroundInsets>
|
||
</Backdrop>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<!-- THE GROUND DIM (1476) — a plain black fill over the tiled ground, because
|
||
the tile alone is not a readable page. UI-DialogBox-Background decodes to a
|
||
uniform (0,0,0,153) — pure black at 0.6 — so 40% of the world reaches the
|
||
text: over snow, noon water or a lit sky the page ground lands near mid-grey
|
||
and the option labels stop reading (the director's report). 0.6 is right for
|
||
a dialog you glance at; the options window is a page you READ, and the era's
|
||
own answer is an OPAQUE FlatPanelBackgroundTemplate panel — so darkening
|
||
toward it is the era structure 0985 already gives us, wearing a plain colour
|
||
fill, which 0985 names as an art byte we may author.
|
||
Alpha 0.7 over the 0.6 tile composites to 0.88 (the world reaches the page at
|
||
0.12), not 1.0: the faint read-through is the window's character, and 0981's
|
||
"the reference was never parchment" finding stands — this dims the ground, it
|
||
does not replace it.
|
||
SEAT: inset 15 on all four sides, NOT the backdrop's own 11/12/12/11 bg
|
||
insets. Regions sort AFTER the frame's own draw slot, which is where the
|
||
backdrop's bg AND its 8 border pieces both live (extract.rs) — so this fill
|
||
paints OVER the rope, and at the bg insets it would smear 0.7 black across
|
||
the border's inner half. The rope's ink is measured, not guessed: every edge
|
||
slice of UI-DialogBox-Border is opaque only in its outer ~11 units and dead
|
||
by texel 16 of 32, and the corner slices' ink ends by 14 (decoded). 15 clears
|
||
every inked texel and leaves at most a 1-unit lighter hairline inside the
|
||
rope, where the rope reads as frame anyway. -->
|
||
<Texture name="$parentGroundDim">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="15" y="-15"/></Offset></Anchor>
|
||
<Anchor point="BOTTOMRIGHT"><Offset><AbsDimension x="-15" y="15"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Color r="0" g="0" b="0" a="0.7"/>
|
||
</Texture>
|
||
</Layer>
|
||
<Layer level="ARTWORK">
|
||
<!-- The carved title plate at the 1.14 options frames' own seat: 300x68 at
|
||
TOP (0,+12) — OptionsFrameTemplates.xml l.244-255 (GameMenuFrame's plate
|
||
is the smaller 256x64 dialog cut). -->
|
||
<Texture name="$parentHeader" file="Interface\DialogFrame\UI-DialogBox-Header">
|
||
<Size><AbsDimension x="300" y="68"/></Size>
|
||
<Anchors><Anchor point="TOP"><Offset><AbsDimension x="0" y="12"/></Offset></Anchor></Anchors>
|
||
</Texture>
|
||
</Layer>
|
||
<Layer level="OVERLAY">
|
||
<!-- Title ON the plate (GameMenuFrame's seat), not the era's bare TOP (0,-5)
|
||
band seat — the plate is where a 1.12 dialog carries its name. GameFontNormal
|
||
rather than the menu's GameFontNormalMed1: that font object is declared
|
||
beside its consumer in GameMenuFrame.xml (0952's residue convention), which
|
||
loads AFTER this file. -->
|
||
<FontString name="$parentTitleText" inherits="GameFontNormal" text="Options">
|
||
<Anchors>
|
||
<Anchor point="TOP" relativeTo="$parentHeader"><Offset><AbsDimension x="0" y="-14"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- ── The two boxes — 1.14's OptionsFrameListTemplate / $parentPanelContainer
|
||
idiom, verbatim mechanism (OptionsFrameTemplates.xml l.113-116 + l.286-289 +
|
||
SharedTooltipTemplates.xml l.117-121): a TOOLTIP-BORDER backdrop with the
|
||
FILL AT ALPHA 0 — the boxes are outlines; the window's translucent ground
|
||
reads through them — and the border tinted LIGHTGRAY_FONT_COLOR (0.6, the
|
||
engine-side constant; the 0981 record cites it). Declared FIRST so every
|
||
sibling draws above them. Anchors are window-absolute (the boxed frames are
|
||
declared later; no forward refs): both tops at -52 — 0981 took 1.14's -40
|
||
band verbatim, but 1.14's band never held a search box; ours holds the
|
||
era's (structure is the era's — 0985's split), and at -40 the box line ran
|
||
through the search's seat (the director's "make some space up there"). -52
|
||
is the depth that gives the era search seat its clearances while the tabs
|
||
stay tucked on the box line below. -->
|
||
<Frame name="$parentCategoryBox">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="10" y="-52"/></Offset></Anchor>
|
||
<Anchor point="BOTTOMRIGHT"><Offset><AbsDimension x="-695" y="38"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
|
||
<EdgeSize><AbsValue val="16"/></EdgeSize>
|
||
<TileSize><AbsValue val="16"/></TileSize>
|
||
<BackgroundInsets><AbsInset left="5" right="5" top="5" bottom="5"/></BackgroundInsets>
|
||
</Backdrop>
|
||
<Scripts>
|
||
<OnLoad>
|
||
this:SetBackdropColor(0, 0, 0, 0)
|
||
this:SetBackdropBorderColor(0.6, 0.6, 0.6)
|
||
</OnLoad>
|
||
</Scripts>
|
||
</Frame>
|
||
<Frame name="$parentPageBox">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="225" y="-52"/></Offset></Anchor>
|
||
<Anchor point="BOTTOMRIGHT"><Offset><AbsDimension x="-14" y="39"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Backdrop bgFile="Interface\Tooltips\UI-Tooltip-Background" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
|
||
<EdgeSize><AbsValue val="16"/></EdgeSize>
|
||
<TileSize><AbsValue val="16"/></TileSize>
|
||
<BackgroundInsets><AbsInset left="5" right="5" top="5" bottom="5"/></BackgroundInsets>
|
||
</Backdrop>
|
||
<Scripts>
|
||
<OnLoad>
|
||
this:SetBackdropColor(0, 0, 0, 0)
|
||
this:SetBackdropBorderColor(0.6, 0.6, 0.6)
|
||
</OnLoad>
|
||
</Scripts>
|
||
</Frame>
|
||
<!-- ── Tabs — seated the 1.14 way: the tab's BOTTOM sits on the category box's
|
||
top edge, tucked 3 units INTO it (InterfaceOptionsFrame.xml l.152-158:
|
||
Tab1 BOTTOMLEFT → Categories TOPLEFT (6,-3)) — the file-folder read, no dead
|
||
band above (0981; 0978 floated them at the era's TOPLEFT (32,-27) over a
|
||
24-unit bare strip, the director's gap report). Era width/text law kept
|
||
(width text+40 measured once per show, selected white small text at BOTTOM+6
|
||
vs gold at BOTTOM+4),
|
||
authored STATIC: Game is the only tab with anything behind it, so it wears
|
||
the selected state permanently and AddOns the unselected one (still dead to
|
||
clicks; the mixin port comes with an addon list). The PLATE is the 0978
|
||
mapping, kept: one UI-Character-{Active,InActive}Tab piece, bottom-anchored
|
||
at the era plate height (26/23), flipped vertically via TexCoords (1.12 only
|
||
ships bottom-tab plates; the flip turns them top-tab). -->
|
||
<Button name="$parentGameTab">
|
||
<Size><AbsDimension x="72" y="37"/></Size>
|
||
<Anchors>
|
||
<Anchor point="BOTTOMLEFT" relativeTo="$parentCategoryBox" relativePoint="TOPLEFT"><Offset><AbsDimension x="6" y="-3"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="ARTWORK">
|
||
<Texture name="$parentPlate" file="Interface\PaperDollInfoFrame\UI-Character-ActiveTab">
|
||
<Size><AbsDimension y="26"/></Size>
|
||
<Anchors>
|
||
<Anchor point="BOTTOMLEFT"/>
|
||
<Anchor point="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
<TexCoords left="0" right="1" top="1" bottom="0"/>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<ButtonText name="$parentText" text="Game">
|
||
<Anchors><Anchor point="BOTTOM"><Offset><AbsDimension x="0" y="6"/></Offset></Anchor></Anchors>
|
||
</ButtonText>
|
||
<NormalFont inherits="GameFontHighlightSmall"/>
|
||
<HighlightFont inherits="GameFontHighlightSmall"/>
|
||
<DisabledFont inherits="GameFontHighlightSmall"/>
|
||
<Scripts>
|
||
<OnShow>OptionsTab_FitWidth(self)</OnShow>
|
||
</Scripts>
|
||
</Button>
|
||
<Button name="$parentAddOnsTab">
|
||
<Size><AbsDimension x="87" y="37"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentGameTab" relativePoint="TOPRIGHT"><Offset><AbsDimension x="5" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="ARTWORK">
|
||
<Texture name="$parentPlate" file="Interface\PaperDollInfoFrame\UI-Character-InActiveTab">
|
||
<Size><AbsDimension y="23"/></Size>
|
||
<Anchors>
|
||
<Anchor point="BOTTOMLEFT"/>
|
||
<Anchor point="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
<TexCoords left="0" right="1" top="1" bottom="0"/>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<ButtonText name="$parentText" text="AddOns">
|
||
<Anchors><Anchor point="BOTTOM"><Offset><AbsDimension x="0" y="4"/></Offset></Anchor></Anchors>
|
||
</ButtonText>
|
||
<NormalFont inherits="GameFontNormalSmall"/>
|
||
<HighlightFont inherits="GameFontNormalSmall"/>
|
||
<DisabledFont inherits="GameFontNormalSmall"/>
|
||
<!-- No addon list behind it: dead to clicks, but wearing the era's unselected
|
||
GOLD (not disabled grey) — the director's capture is the call. -->
|
||
<Scripts>
|
||
<OnLoad>self:Disable()</OnLoad>
|
||
<OnShow>OptionsTab_FitWidth(self)</OnShow>
|
||
</Scripts>
|
||
</Button>
|
||
|
||
<!-- ── The category list (era CategoryList, static — it fits) ──────────────────── -->
|
||
<Frame name="$parentCategoryList">
|
||
<Size><AbsDimension x="199"/></Size>
|
||
<!-- Top rides the box line: box top -52 + the same 12-unit interior pad the
|
||
-76 seat gave the era's -64 box (the era's own list-to-box air). -->
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="18" y="-64"/></Offset></Anchor>
|
||
<Anchor point="BOTTOMLEFT"><Offset><AbsDimension x="18" y="46"/></Offset></Anchor>
|
||
</Anchors>
|
||
<!-- The era list rhythm (CreateScrollBoxListLinearView spacing=2 + the 18-tall
|
||
SettingsCategoryListSpacerTemplate between groups): 2 between every
|
||
element, 2+18+2 = 22 from a group's last row to the next header. -->
|
||
<Frames>
|
||
<Frame name="$parentHeaderGameplay" inherits="OptionsCategoryHeaderTemplate">
|
||
<Anchors><Anchor point="TOPLEFT"/></Anchors>
|
||
<Scripts>
|
||
<OnLoad>getglobal(self:GetName() .. "Label"):SetText("Gameplay")</OnLoad>
|
||
</Scripts>
|
||
</Frame>
|
||
<Button name="$parentRowControls" inherits="OptionsCategoryRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="$parentHeaderGameplay" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>OptionsCategoryRow_OnLoad(self, "Controls", "Controls")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentRowInterface" inherits="OptionsCategoryRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="$parentRowControls" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>OptionsCategoryRow_OnLoad(self, "Interface", "Interface")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentRowActionBars" inherits="OptionsCategoryRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="$parentRowInterface" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>OptionsCategoryRow_OnLoad(self, "ActionBars", "Action Bars")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentRowCombat" inherits="OptionsCategoryRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="$parentRowActionBars" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>OptionsCategoryRow_OnLoad(self, "Combat", "Combat")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentRowChat" inherits="OptionsCategoryRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="$parentRowCombat" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>OptionsCategoryRow_OnLoad(self, "Chat", "Chat")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentRowKeybindings" inherits="OptionsCategoryRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="$parentRowChat" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>OptionsCategoryRow_OnLoad(self, "Keybindings", "Keybindings")</OnLoad></Scripts>
|
||
</Button>
|
||
<!-- Nameplates — the era Gameplay group's own last row (NAMEPLATE_OPTIONS_LABEL,
|
||
order 15), backed by benilla's real nameplate knobs when the pages land. -->
|
||
<Button name="$parentRowNameplates" inherits="OptionsCategoryRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="$parentRowKeybindings" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>OptionsCategoryRow_OnLoad(self, "Nameplates", "Nameplates")</OnLoad></Scripts>
|
||
</Button>
|
||
<Frame name="$parentHeaderSystem" inherits="OptionsCategoryHeaderTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowNameplates" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-22"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts>
|
||
<OnLoad>getglobal(self:GetName() .. "Label"):SetText("System")</OnLoad>
|
||
</Scripts>
|
||
</Frame>
|
||
<Button name="$parentRowGraphics" inherits="OptionsCategoryRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="$parentHeaderSystem" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>OptionsCategoryRow_OnLoad(self, "Graphics", "Graphics")</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentRowAudio" inherits="OptionsCategoryRowTemplate">
|
||
<Anchors><Anchor point="TOPLEFT" relativeTo="$parentRowGraphics" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-2"/></Offset></Anchor></Anchors>
|
||
<Scripts><OnLoad>OptionsCategoryRow_OnLoad(self, "Audio", "Audio")</OnLoad></Scripts>
|
||
</Button>
|
||
</Frames>
|
||
</Frame>
|
||
|
||
<!-- ── The page area (era SettingsList's header; the body is next slice's) ─────── -->
|
||
<Frame name="$parentContainer">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentCategoryList" relativePoint="TOPRIGHT"><Offset><AbsDimension x="16" y="0"/></Offset></Anchor>
|
||
<Anchor point="BOTTOMRIGHT"><Offset><AbsDimension x="-22" y="47"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="ARTWORK">
|
||
<!-- The era options_horizontaldivider seat (TOP, -50) wearing what
|
||
that atlas member actually IS — decoded from the era sheet
|
||
(fdid 1318750, a 630x1 row): pure white at ~0.3 alpha, a
|
||
hairline. Authored as a 1-unit color fill (0981; no art file —
|
||
0978's UI-DialogBox-Divider ink band stretched thin read as
|
||
artifacts, the director's separator report). Span keeps the
|
||
0978 seat: the container minus 20 units each side. -->
|
||
<Texture name="$parentDivider">
|
||
<Size><AbsDimension y="1"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="20" y="-50"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT"><Offset><AbsDimension x="-20" y="-50"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Color r="1" g="1" b="1" a="0.3"/>
|
||
</Texture>
|
||
</Layer>
|
||
<Layer level="OVERLAY">
|
||
<!-- The page title — BenillaOptionsFrame_SelectCategory writes it. -->
|
||
<FontString name="$parentTitle" inherits="OptionsFontHighlightHuge">
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="7" y="-22"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- Live on any page with rows (OPTIONS_PAGE_ROWS) and on the Keybindings
|
||
page, where it is 1.12's Reset To Default behind the era confirm
|
||
(KeyBindingsPage.xml's popup); BenillaOptionsFrame_SelectCategory
|
||
enables/disables it with the page swap. -->
|
||
<Button name="$parentDefaults" inherits="OptionsRedButtonTemplate" text="Defaults">
|
||
<Anchors><Anchor point="TOPRIGHT"><Offset><AbsDimension x="-36" y="-16"/></Offset></Anchor></Anchors>
|
||
<Scripts>
|
||
<OnLoad>self:Disable()</OnLoad>
|
||
<OnClick>
|
||
if BenillaOptionsFrame.selectedCategory == "Keybindings" then
|
||
StaticPopup_Show("CONFIRM_RESET_KEYBINDINGS")
|
||
else
|
||
OptionsPage_Defaults(BenillaOptionsFrame.selectedCategory)
|
||
end
|
||
</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
<!-- Unbind Key (1.12's own button, reseated in the header band): exists only
|
||
on the Keybindings page, live only while a capsule is selected
|
||
(KeyBindings_UpdateUnbindKey drives the enable). -->
|
||
<Button name="$parentUnbind" inherits="OptionsRedButtonTemplate" hidden="true">
|
||
<Anchors><Anchor point="RIGHT" relativeTo="$parentDefaults" relativePoint="LEFT"><Offset><AbsDimension x="-2" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts>
|
||
<OnLoad>
|
||
self:SetText(KeyBindings_String("UNBIND", "Unbind Key"))
|
||
self:Disable()
|
||
</OnLoad>
|
||
<OnClick>
|
||
PlaySound("igMainMenuOptionCheckBoxOn")
|
||
KeyBindings_Unbind()
|
||
</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
<!-- ── The page area SCROLLS (the real-scroll kit, decision 0112) ────────────
|
||
The body below IS this frame's scroll child, so every page, row, search
|
||
head and keybinding capsule under it pans and CLIPS to the visible page
|
||
rect instead of drawing past the window. 0950's header said "MinimalScrollBar
|
||
arrives when one outgrows the space"; the SEARCH is what outgrew it first —
|
||
a query that matches across categories chains five group heads and every
|
||
matched row into one column, which for a broad query runs ~150 units past
|
||
the body's own bottom and out through the dialog border onto the world
|
||
(B217). The era's answer is the same one: its SettingsList is a ScrollBox
|
||
with a MinimalScrollBar (Blizzard_SettingsList.xml l.48-58), and results and
|
||
pages ride the same one.
|
||
|
||
The body is sized by OptionsScroll_Fit each frame: normally EXACTLY this
|
||
frame's rect — range 0, no bar, every page seated where it has always been,
|
||
including the Keybindings page that fills the body and runs its own faux
|
||
list inside it — and grown to the measured content only when a layout
|
||
outruns it. So nothing about the fitting pages moves; the scroll appears
|
||
only where the overflow is.
|
||
|
||
enableMouse so a wheel spin over blank page area lands here rather than
|
||
falling through to the window (hit-testing only sees mouse-enabled frames);
|
||
a spin over the Keybindings page still hits ITS handler first, which is the
|
||
nearer ancestor, so the inner list keeps the wheel where it owns it. -->
|
||
<ScrollFrame name="$parentScroll" enableMouse="true">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="0" y="-50"/></Offset></Anchor>
|
||
<Anchor point="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
<Scripts>
|
||
<!-- The loader fires OnLoad bottom-up, so the body already exists. -->
|
||
<OnLoad>self:SetScrollChild(BenillaOptionsFrameContainerBody)</OnLoad>
|
||
<OnUpdate>OptionsScroll_Fit()</OnUpdate>
|
||
<OnMouseWheel>BenillaScroll_OnMouseWheel(this, arg1)</OnMouseWheel>
|
||
<OnVerticalScroll>BenillaScroll_SyncBar(this)</OnVerticalScroll>
|
||
<OnScrollRangeChanged>BenillaScroll_SyncBar(this)</OnScrollRangeChanged>
|
||
</Scripts>
|
||
<Frames>
|
||
<!-- The bar's trough (the shared kit's). No anchors: it seats itself on
|
||
the bar named by dropping this frame's "Trough" suffix, at the ref's
|
||
own hang — the socket law is one law and lives in
|
||
BenillaScrollTrough_Seat, not restated here. That puts it in the
|
||
SAME gutter the Keybindings page's own bar uses — the two are never
|
||
live together (this one's range is 0 on that page, since the page
|
||
fills the body), so the gutter holds exactly one bar at a time.
|
||
Declared before the body and the bar so it is beneath both by
|
||
link-stamp as well as by layer. -->
|
||
<Frame name="$parentBarTrough" inherits="BenillaScrollTroughTemplate"/>
|
||
<!-- The page body: one child frame per category with rows, shown by
|
||
BenillaOptionsFrame_SelectCategory (Audio 0957, Graphics 0959). Named in
|
||
full rather than `$parent…`: it keeps the name every page, row and
|
||
search seat is derived from, across the scroll frame that now sits
|
||
between it and the container. Its SIZE is authored here because a
|
||
scroll child's anchors are the engine's (SetScrollChild pins it
|
||
TOPLEFT, offset by the scroll — layout.rs) and only its own width
|
||
and height are read; these are the container's own 665 x (613-50),
|
||
the seat it held before, and OptionsScroll_Fit keeps them true
|
||
against the live rect from there on. -->
|
||
<Frame name="BenillaOptionsFrameContainerBody">
|
||
<Size><AbsDimension x="665" y="563"/></Size>
|
||
<Layers>
|
||
<Layer level="OVERLAY">
|
||
<!-- The empty-search line (era SETTINGS_SEARCH_NOTHING_FOUND
|
||
on the SettingsListSectionHeaderTemplate seat:
|
||
GameFontHighlightLarge, the header's (7,-16) inside the
|
||
first 45-tall slot -> (17,-28) off the body with the
|
||
layout pads). Shown only by a no-match search. -->
|
||
<FontString name="$parentNoResults" inherits="GameFontHighlightLarge" justifyH="LEFT" hidden="true" text="No results found.">
|
||
<Anchors><Anchor point="TOPLEFT"><Offset><AbsDimension x="17" y="-28"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- The Controls page (0961): the gameplay checkboxes with benilla
|
||
knobs behind them, in the era Controls page's own row order
|
||
(Controls.lua @1.15.9: Sticky Targeting #1, Auto Loot #6,
|
||
Invert Mouse #12 — its Mouse section header is cut while one
|
||
row survives under it). Sticky Targeting is value-INVERTED in
|
||
BOTH references (1.12 UIOptionsFrame checks it on
|
||
deselectOnClick=="0"; era wraps the CVar in NegateBoolean);
|
||
labels are 1.12 GlobalStrings where the row exists there
|
||
(GAMEFIELD_DESELECT_TEXT, INVERT_MOUSE), era's for Auto Loot
|
||
(no 1.12 row exists) — and the tooltip keys are those same
|
||
1.12 keys through the panel's own `_TEXT`-stripping lookup
|
||
(UIOptionsFrame.lua l.265), which is why Sticky Targeting's
|
||
description is GAMEFIELD_DESELECT's. -->
|
||
<Frame name="$parentControls" hidden="true">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"/>
|
||
<Anchor point="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
<Frames>
|
||
<Frame name="$parentRowStickyTarget" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="10" y="-12"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT"><Offset><AbsDimension x="-20" y="-12"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "deselectOnClick", "Sticky Targeting",
|
||
"OPTION_TOOLTIP_GAMEFIELD_DESELECT")
|
||
self.invert = 1
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- Block Trades (decision 1764). Seated here because
|
||
this page is where 1.12's Basic Options GENERAL box
|
||
lands, and Sticky Targeting above is the other row we
|
||
ship from it — the reference's own box order runs 45
|
||
(Sticky Targeting) down the left column and 14 (this)
|
||
down the right, so the two belong adjacent when the
|
||
box is flattened to one column. Its tooltip key IS the
|
||
reference's, unlike the row above. -->
|
||
<!-- The three BasicOptionsGeneral switches whose knob this client already had and
|
||
whose box nobody could reach (2180). Labels are the reference's GlobalStrings
|
||
verbatim, ASSIST_ATTACK's sentence case included — the page's own rule is
|
||
"1.12 GlobalStrings where the row exists there", and quietly Title-Casing one
|
||
string is how a transcription starts drifting from what it transcribes. -->
|
||
<Frame name="$parentRowAssistAttack" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowStickyTarget" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowStickyTarget" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "assistAttack", "Attack on assist",
|
||
"OPTION_TOOLTIP_ASSIST_ATTACK")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowClearAFK" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowAssistAttack" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowAssistAttack" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "autoClearAFK", "Auto Clear AFK",
|
||
"OPTION_TOOLTIP_CLEAR_AFK")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowBlockTrades" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowClearAFK" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowClearAFK" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>OptionsRow_OnLoad(self, "BlockTrades", "Block Trades",
|
||
"OPTION_TOOLTIP_BLOCK_TRADES")</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- Auto Self Cast (1745). The one row on this page that ships at a value the
|
||
reference does not register — "1" against its "0", a named deviation in
|
||
`cvars::REGISTERED` because with it off an unbindable friendly cast falls
|
||
into the targeting-cursor machine, which is unmodeled, leaving no path at
|
||
all. The Defaults button walks it back to OUR shipped value, which is what
|
||
GetCVarDefault answers and the only value that is true here. -->
|
||
<Frame name="$parentRowAutoSelfCast" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowBlockTrades" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowBlockTrades" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "autoSelfCast", "Auto Self Cast",
|
||
"OPTION_TOOLTIP_AUTO_SELF_CAST")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowAutoLoot" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowAutoSelfCast" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowAutoSelfCast" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<!-- No tip: 1.12 has no Auto Loot row, so no
|
||
OPTION_TOOLTIP_* for it either (verified — the
|
||
5875 GlobalStrings has no AUTO_LOOT key at all,
|
||
and no 1.12 panel names the CVar). -->
|
||
<Scripts><OnLoad>OptionsRow_OnLoad(self, "autoLootDefault", "Auto Loot")</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowInvertMouse" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowAutoLoot" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowAutoLoot" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>OptionsRow_OnLoad(self, "mouseInvertPitch", "Invert Mouse",
|
||
"OPTION_TOOLTIP_INVERT_MOUSE")</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- Mouse Sensitivity (decision 1140). Last because 1.12
|
||
puts its four sliders in their own box BELOW the
|
||
checkbox columns (UIOptionsFrameSliders), and it was the
|
||
only one of the four whose knob we had when 1140
|
||
wrote this row. All four ship now — the
|
||
max-follow-distance factor below it (1140), and the
|
||
auto-follow and mouse-look speeds in the camera block
|
||
under the following-style dropdown (2180). Range and step are the reference's
|
||
own (0.5 .. 1.5 by 0.05); the percent readout is the
|
||
era's default and reads a multiplier exactly right. -->
|
||
<Frame name="$parentRowMouseSpeed" inherits="OptionsSliderRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowInvertMouse" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowInvertMouse" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "mousespeed", "Mouse Sensitivity",
|
||
"OPTION_TOOLTIP_MOUSE_SENSITIVITY")
|
||
OptionsSliderRow_Setup(self, 0.5, 1.5, 0.05)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- Max Camera Distance (decision 1140), the second of
|
||
1.12's four sliders whose knob we have. The stored
|
||
value is the FACTOR over `cameraDistanceMax`'s 15 yd
|
||
base — the reference's own arrangement, and the reason
|
||
the readout is raw yards here rather than a percent:
|
||
"22" means the wheel stops at 22 yards, which is the
|
||
thing being chosen. The slider rests at 1.0 (15 yd),
|
||
1.12's own registered default — it sat at the top of
|
||
the range (30 yd) from 1140 until 1804. -->
|
||
<!-- Camera Following Style (1493, values re-pinned by
|
||
1502): 1.12's own dropdown
|
||
(UIOptionsFrameCameraDropDown) in its own order —
|
||
Smart, Always, Never — each entry carrying the
|
||
reference's own description key (keyed by POSITION,
|
||
OPTION_TOOLTIP_CAMERA1..3) so the row's plate changes
|
||
with the selection, the way that dropdown's does.
|
||
The VALUES are the ENGINE's, not that dropdown's: the
|
||
reference writes 1/2/3 and 3 is not a style at all —
|
||
its validator accepts it while the terrain-tilt
|
||
consumer indexes 360 bytes off the end of its table.
|
||
0/1/2 is what the client's own tables are indexed by
|
||
(wow-re camera-smooth-style.md §2/§4). Seated at the
|
||
head of the camera block because it decides whether
|
||
the camera follows at all; the distance slider under
|
||
it decides how far. -->
|
||
<Frame name="$parentRowCameraFollowStyle" inherits="OptionsDropdownRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowMouseSpeed" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowMouseSpeed" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "cameraSmoothStyle",
|
||
"Camera Following Style", "OPTION_TOOLTIP_CAMERA1")
|
||
OptionsDropdownRow_Setup(self, {
|
||
{ text = "Smart", value = "1", tip = "OPTION_TOOLTIP_CAMERA1" },
|
||
{ text = "Always", value = "2", tip = "OPTION_TOOLTIP_CAMERA2" },
|
||
{ text = "Never", value = "0", alt = "3", tip = "OPTION_TOOLTIP_CAMERA3" },
|
||
})
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- ── The four 1.12 camera toggles, and the two speed sliders (2180) ──────
|
||
2149 built all four mechanisms and 2179 rebuilt water collision at the
|
||
bytes; until this block none of them could be turned off from inside the
|
||
game. The stock UIOptionsFrame carries all four checkboxes and benilla
|
||
loads that window HIDDEN, deliberately (2115) — so "the reference has the
|
||
box" and "the player can reach the box" had come apart, and only this
|
||
window can close it.
|
||
|
||
Order is BasicOptionsCamera's own, its three columns flattened: the
|
||
following-style dropdown above, then 24 -> 26, then Slider2 -> 27 -> 15,
|
||
then Slider3 -> Slider4. Labels and OPTION_TOOLTIP_* keys are the
|
||
reference's GlobalStrings verbatim. -->
|
||
<Frame name="$parentRowFollowTerrain" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowCameraFollowStyle" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowCameraFollowStyle" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "cameraTerrainTilt", "Follow Terrain",
|
||
"OPTION_TOOLTIP_FOLLOW_TERRAIN")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- Head Bob is FIRST PERSON ONLY, and nothing in the row says so because
|
||
nothing in the reference's row does either: the gate's first conjunct is
|
||
`[cam+0xec] <= 1/6` on the zoom distance (2149 §3). A player who ticks it
|
||
at an over-the-shoulder zoom sees no change, which is the reference's own
|
||
behaviour and not a dead row. -->
|
||
<Frame name="$parentRowHeadBob" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowFollowTerrain" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowFollowTerrain" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "cameraBobbing", "Head Bob",
|
||
"OPTION_TOOLTIP_HEAD_BOB")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- Auto-Follow Speed (1502 built the knob; this is its slider). Range and step
|
||
are UIOptionsFrameSliders row 2's own — 90..270 by 10, deg/s — stated here
|
||
rather than read off that table, which is what the two sliders already on
|
||
this page do. Greyed while the following style is Never, the reference's
|
||
own dependency (see OptionsPage_UpdateDependencies).
|
||
|
||
**One HALF of the reference's write, on purpose.** `UIOptionsFrame_Save`
|
||
also writes `cameraPitchSmoothSpeed` at a quarter of this value; benilla
|
||
does not register that name, because the auto-follow here has ONE rate
|
||
(`FollowRig`, a single `yaw_speed`) and a CVar with no reader is 1134 §4's
|
||
silent pretence. Its Mouse Look Speed neighbour below does carry its
|
||
partner, because that one's twin is real here. -->
|
||
<Frame name="$parentRowAutoFollowSpeed" inherits="OptionsSliderRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowHeadBob" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowHeadBob" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "cameraYawSmoothSpeed", "Auto-Follow Speed",
|
||
"OPTION_TOOLTIP_AUTO_FOLLOW_SPEED")
|
||
OptionsSliderRow_Setup(self, 90, 270, 10, "raw")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- Water Collision (2179). ONE CVar with two consumers that may never again be
|
||
separated: the `0xf0000` nibble rides the trace mask to all three of
|
||
`0x50e570`'s queries, and `0x50e629`'s `test esi,0xf0000` admits the pivot
|
||
floor/cap block. Ticking this box moves both halves or neither. -->
|
||
<Frame name="$parentRowWaterCollision" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowAutoFollowSpeed" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowAutoFollowSpeed" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "cameraWaterCollision", "Water Collision",
|
||
"OPTION_TOOLTIP_WATER_COLLISION")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowSmartPivot" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowWaterCollision" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowWaterCollision" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "cameraPivot", "Smart Pivot",
|
||
"OPTION_TOOLTIP_SMART_PIVOT")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- Mouse Look Speed (2115 registered the CVar; this is the control it never
|
||
had). UIOptionsFrameSliders row 3, 90..270 by 10. It carries the
|
||
reference's PARTNER write — `cameraPitchMoveSpeed` at half the yaw value
|
||
(UIOptionsFrame.lua l.355-356), which is exactly the 180/90 pair both are
|
||
registered at — so dragging this row keeps the two axes in the ratio the
|
||
reference ships them in instead of moving one and leaving the other. -->
|
||
<Frame name="$parentRowMouseLookSpeed" inherits="OptionsSliderRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowSmartPivot" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowSmartPivot" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "cameraYawMoveSpeed", "Mouse Look Speed",
|
||
"OPTION_TOOLTIP_MOUSE_LOOK_SPEED")
|
||
OptionsSliderRow_Setup(self, 90, 270, 10, "raw")
|
||
self.partner = { cvar = "cameraPitchMoveSpeed", scale = 0.5 }
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowMaxCameraDistance" inherits="OptionsSliderRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowMouseLookSpeed" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowMouseLookSpeed" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "cameraDistanceMaxFactor",
|
||
"Max Camera Distance", "OPTION_TOOLTIP_MAX_FOLLOW_DIST")
|
||
OptionsSliderRow_Setup(self, 1.0, 2.0, 0.1, "yards")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
</Frame>
|
||
<!-- The Audio page. Row seats transcribe the era settings list
|
||
(Blizzard_SettingsList.lua l.43-47 + .xml: scroll box hung
|
||
-15/-20 off the header block with padLeft 25 / padRight 0 and
|
||
verticalPad 10 → first row at (10,-12); spacing 9 → 35 pitch).
|
||
Row ORDER is the era Audio page's grammar (volume block first,
|
||
then the enables) over the 1.12 row set: the three category
|
||
volumes ride as CHILDREN of Master Volume exactly like era's,
|
||
in the 1.12 panel's own slider order (Sound, Music, Ambience —
|
||
SoundOptionsFrame.lua's index order). -->
|
||
<Frame name="$parentAudio" hidden="true">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"/>
|
||
<Anchor point="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
<Frames>
|
||
<Frame name="$parentRowEnableAll" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="10" y="-12"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT"><Offset><AbsDimension x="-20" y="-12"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "MasterSoundEffects", "Enable All Sound",
|
||
"OPTION_TOOLTIP_ENABLE_ALL_SOUND")
|
||
self.soundQuirk = 1
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowMaster" inherits="OptionsSliderRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowEnableAll" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowEnableAll" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>OptionsRow_OnLoad(self, "MasterVolume", "Master Volume",
|
||
"OPTION_TOOLTIP_MASTER_VOLUME")</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowSound" inherits="OptionsSliderRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowMaster" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowMaster" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "SoundVolume", "Sound Volume",
|
||
"OPTION_TOOLTIP_SOUND_VOLUME", 1)
|
||
-- era parentInitializer (search pulls Master in
|
||
-- above a matched child, SettingsPanel.lua l.665)
|
||
self.parentRow = "RowMaster"
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowMusic" inherits="OptionsSliderRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowSound" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowSound" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "MusicVolume", "Music Volume",
|
||
"OPTION_TOOLTIP_MUSIC_VOLUME", 1)
|
||
self.parentRow = "RowMaster"
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowAmbience" inherits="OptionsSliderRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowMusic" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowMusic" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "AmbienceVolume", "Ambience Volume",
|
||
"OPTION_TOOLTIP_AMBIENCE_VOLUME", 1)
|
||
self.parentRow = "RowMaster"
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowEnableMusic" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowAmbience" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowAmbience" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "EnableMusic", "Enable Music",
|
||
"OPTION_TOOLTIP_ENABLE_MUSIC")
|
||
self.soundQuirk = 1
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowEnableAmbience" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowEnableMusic" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowEnableMusic" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "EnableAmbience", "Enable Ambience",
|
||
"OPTION_TOOLTIP_ENABLE_AMBIENCE")
|
||
self.soundQuirk = 1
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- 1.12's fourth Sound checkbox, ENABLE_ERROR_SPEECH
|
||
(SoundOptionsFrame.lua l.2) — the race/sex refusal
|
||
lines your character says aloud, decision 1815. Its
|
||
label and tooltip are the reference's own
|
||
GlobalStrings entries. -->
|
||
<Frame name="$parentRowEnableErrorSpeech" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowEnableAmbience" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowEnableAmbience" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "EnableErrorSpeech", "Enable Error Speech",
|
||
"OPTION_TOOLTIP_ENABLE_ERROR_SPEECH")
|
||
self.soundQuirk = 1
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- Sound in the background (decision 1847). The one
|
||
Audio row 1.12 has no checkbox for: it mutes on its
|
||
window-activation event unconditionally, so this row
|
||
offers the way out the reference never did, shipped
|
||
OFF at the reference's own behaviour. Era's label and
|
||
era's CVar spelling, the autoLootDefault posture.
|
||
soundQuirk like every box on this page - the mapping
|
||
belongs to the panel, not to the row's provenance. -->
|
||
<Frame name="$parentRowBackgroundSound" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowEnableErrorSpeech" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowEnableErrorSpeech" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "Sound_EnableSoundWhenGameIsInBG",
|
||
"Enable Sound in Background",
|
||
"BENILLA_TOOLTIP_BACKGROUND_SOUND")
|
||
self.soundQuirk = 1
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
</Frame>
|
||
<!-- The Graphics page (0959): the 1.12 OptionsFrameSliders rows
|
||
that have a benilla knob behind them, in the table's own order
|
||
(OptionsFrame.lua l.25-27). UI Scale: uiscale 0.64..1.0 step
|
||
0.01 (UI_SCALE "UI Scale", percent readout — era's own
|
||
FormatPercentageRounded on its uiscale row); 1.12's useUiScale
|
||
gate has no benilla knob (our scale always applies; off ≡ 1.0)
|
||
so the checkbox doesn't ship. Terrain Distance: farclip
|
||
177..777 step 60 = (max-min)/10 (FARCLIP "Terrain Distance",
|
||
raw-yards readout — era's law when a slider has no formatter);
|
||
retired by the director in 0961 and back by their call in
|
||
1513, now that the one number moves the far-clip wall AND how
|
||
much terrain is resident, as it does in the reference.
|
||
Environment Detail is the same table's WorldDetail row
|
||
(0..2 step 1, label ENVIRONMENT_DETAIL) over the clutter-density
|
||
knob. 0992 wore it as a dropdown; 1649 puts it back on the
|
||
SLIDER the reference actually uses, keeping 0992's stop names
|
||
in the readout seat. -->
|
||
<Frame name="$parentGraphics" hidden="true">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"/>
|
||
<Anchor point="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
<Frames>
|
||
<Frame name="$parentRowUiScale" inherits="OptionsSliderRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="10" y="-12"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT"><Offset><AbsDimension x="-20" y="-12"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "uiScale", "UI Scale",
|
||
"OPTION_TOOLTIP_UI_SCALE")
|
||
OptionsSliderRow_Setup(self, OptionsFrameSliders[1].minValue,
|
||
OptionsFrameSliders[1].maxValue,
|
||
OptionsFrameSliders[1].valueStep)
|
||
-- era registers its uiscale row CommitFlag.Apply
|
||
-- (Graphics.lua l.684): the one row whose live
|
||
-- write would rescale the very slider mid-drag —
|
||
-- it stages and commits through the Apply button.
|
||
self.deferred = 1
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowFarclip" inherits="OptionsSliderRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowUiScale" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowUiScale" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "farclip", "Terrain Distance",
|
||
"OPTION_TOOLTIP_FARCLIP")
|
||
OptionsSliderRow_Setup(self, OptionsFrameSliders[2].minValue,
|
||
OptionsFrameSliders[2].maxValue,
|
||
OptionsFrameSliders[2].valueStep, "raw")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowWorldDetail" inherits="OptionsSliderRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowFarclip" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowFarclip" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "WorldDetail", "Environment Detail",
|
||
"OPTION_TOOLTIP_ENVIRONMENT_DETAIL")
|
||
-- The stop names are the era preset ladder's (its
|
||
-- quality dropdowns say Low/Medium/High); 1.12's
|
||
-- slider had no stop labels to quote.
|
||
OptionsSliderRow_Setup(self, OptionsFrameSliders[3].minValue,
|
||
OptionsFrameSliders[3].maxValue,
|
||
OptionsFrameSliders[3].valueStep, nil,
|
||
{ "Low", "Medium", "High" })
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- Brightness (2182) — the reference's slider 6, and the
|
||
one row on this page whose store is an engine PAIR
|
||
rather than the CVar directly. That is 1.12's own
|
||
arrangement: its slider table gives this row
|
||
`func = "Gamma"`, so `OptionsFrame_Load`/`_Save` reach
|
||
`GetGamma`/`SetGamma` and the CVar is written by the
|
||
engine, not the panel. The reason it matters here is
|
||
the UNIT — `GetGamma()` is `1 - gamma`, an offset
|
||
centred on 0, and a row that wrote the slider value
|
||
into `gamma` directly would invert the control and
|
||
put a fully white ramp at the top of its travel. -->
|
||
<Frame name="$parentRowBrightness" inherits="OptionsSliderRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowWorldDetail" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowWorldDetail" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
-- The default is the reference's own computation
|
||
-- rather than a second copy of the number:
|
||
-- OptionsFrame_SetDefaults displays this row as
|
||
-- `1 - GetCVarDefault("gamma")` (OptionsFrame.lua
|
||
-- l.441-445), so the CVar table stays the single
|
||
-- source and Restore Defaults here lands exactly
|
||
-- where the reference's would. The `or 1` is for a
|
||
-- VM whose host registered nothing (a bare kit),
|
||
-- where the reference would have had a record to
|
||
-- read because its own lookup creates one.
|
||
local gd = tonumber(GetCVarDefault("gamma")) or 1
|
||
OptionsNumFuncRow_OnLoad(self, GetGamma, SetGamma,
|
||
tostring(1 - gd), "Brightness",
|
||
"BENILLA_TOOLTIP_BRIGHTNESS")
|
||
OptionsSliderRow_Setup(self, OptionsFrameSliders[6].minValue,
|
||
OptionsFrameSliders[6].maxValue,
|
||
OptionsFrameSliders[6].valueStep, "travel")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- Weather Intensity (2181) — the reference's slider 9,
|
||
the last of its nine and the nearest of 2177 §10's
|
||
named-not-done: benilla has driven precipitation off
|
||
`weatherDensity` since 0310 and only the switch was
|
||
missing. It rides the CVar directly like every other
|
||
row here; the reference's own row would reach it
|
||
through `SetCVar` too (`func = "weatherDensity"` is a
|
||
CVar name, not one of the four engine bindings — its
|
||
`Setfarclip`-shaped `getglobal("Set".."weatherDensity")`
|
||
finds nothing, so `OptionsFrame_Save` falls through).
|
||
-->
|
||
<Frame name="$parentRowWeatherDensity" inherits="OptionsSliderRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowBrightness" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowBrightness" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "weatherDensity", "Weather Intensity",
|
||
"OPTION_TOOLTIP_WEATHER_DETAIL")
|
||
-- The stop names are OURS, and they name the
|
||
-- reference's own quality table rather than a
|
||
-- borrowed preset ladder: `0x67b870` maps 0/1/2/3
|
||
-- onto the spawn-rate gains {0.1, 0.33, 0.66, 1.0}
|
||
-- in `[0x8680ec]`, so the top stop really is the
|
||
-- full rate and the bottom is a tenth of it. 1.12
|
||
-- labelled no stop on this slider -- it labelled
|
||
-- the two ENDS -- but every slider row in this kit
|
||
-- carries a readout, and "2" is the one thing that
|
||
-- seat could say that means nothing to a player.
|
||
OptionsSliderRow_Setup(self, OptionsFrameSliders[9].minValue,
|
||
OptionsFrameSliders[9].maxValue,
|
||
OptionsFrameSliders[9].valueStep, nil,
|
||
{ "Minimal", "Low", "Medium", "Full" })
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowDisplayMode" inherits="OptionsDropdownRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowWeatherDensity" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowWeatherDensity" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
-- Display Mode (1650): MODERN CLASSIC's row, not
|
||
-- 1.12's, because 1627 already gave us modern
|
||
-- Classic's two states and a checkbox could only
|
||
-- name one of them.
|
||
--
|
||
-- Blizzard_SettingsDefinitions_Shared/Graphics.lua
|
||
-- (live, classic AND classic_era, all identical):
|
||
-- a BOOLEAN proxy rendered as a dropdown, with
|
||
-- exactly two entries -- container:Add(true,
|
||
-- VIDEO_OPTIONS_WINDOWED_FULLSCREEN) and
|
||
-- container:Add(false, VIDEO_OPTIONS_WINDOWED).
|
||
-- There is no Fullscreen entry anywhere in it;
|
||
-- 8.0.1 removed the exclusive mode those clients
|
||
-- had, which is the same reason 1627 ships none.
|
||
--
|
||
-- It rides gxWindow, OUR persisted CVar, not the
|
||
-- gxMaximize the modern client uses -- that client
|
||
-- deleted gxWindow entirely and had to move; we
|
||
-- did not, and repointing would orphan every
|
||
-- config.toml already holding the row for nothing.
|
||
-- Polarity is gxWindow's own: "0" is not-windowed,
|
||
-- which 1627 redefined as the borderless window.
|
||
--
|
||
-- Not deferred, for the same reason as Vertical
|
||
-- Sync below: the reference row carries
|
||
-- gxRestart = 1 and ours applies on the click.
|
||
OptionsRow_OnLoad(self, "gxWindow", "Display Mode",
|
||
"BENILLA_TOOLTIP_DISPLAY_MODE")
|
||
OptionsDropdownRow_Setup(self, {
|
||
{ text = "Windowed (Fullscreen)", value = "0" },
|
||
{ text = "Windowed", value = "1" },
|
||
})
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowVerticalSync" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowDisplayMode" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowDisplayMode" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
-- Vertical Sync: 1.12's own Video Options checkbox
|
||
-- 5 (gxVSync), over the window's present mode.
|
||
-- The reference row carries gxRestart = 1; ours
|
||
-- does not and must not be marked deferred --
|
||
-- wgpu swaps the presentation interval live, so
|
||
-- the box takes effect as you click it.
|
||
OptionsRow_OnLoad(self, "gxVSync", "Vertical Sync",
|
||
"OPTION_TOOLTIP_VERTICAL_SYNC")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowRenderScale" inherits="OptionsSliderRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowVerticalSync" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowVerticalSync" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
-- Render Scale (decision 1639) -- benilla's own
|
||
-- row, no 1.12 counterpart: the reference renders
|
||
-- straight to the backbuffer and has no second
|
||
-- image to size. It CLOSES the page, and it is
|
||
-- the only antialiasing control on it: the
|
||
-- reference's own Multisampling row was pulled
|
||
-- 2026-08-27 (decision 1648, the director's call).
|
||
-- gxMultisample survives as a CVar and $WOW_MSAA
|
||
-- -- what went is the row, because multisampling
|
||
-- cannot touch the alpha-tested cutouts that carry
|
||
-- most of this game's visible aliasing, and above
|
||
-- 100% this row can.
|
||
--
|
||
-- 50-200%, narrower than the CVar's own clamp
|
||
-- (RENDER_SCALE_RANGE, 0.25-4.0). That clamp stops
|
||
-- an absurd value and leaves room for the
|
||
-- supersampling instrument; this is what a player
|
||
-- should be offered, and it is where every engine
|
||
-- puts the same slider.
|
||
--
|
||
-- DEFERRED, and for the reason the flag exists.
|
||
-- Committing live would rebuild the world's render
|
||
-- target on every drag tick -- tens of megabytes,
|
||
-- thirty times across one sweep of the handle.
|
||
-- Staging to Apply makes that exactly one rebuild,
|
||
-- which is the same answer uiScale's row already
|
||
-- reaches for a different reason.
|
||
OptionsRow_OnLoad(self, "renderScale", "Render Scale",
|
||
"BENILLA_TOOLTIP_RENDER_SCALE")
|
||
OptionsSliderRow_Setup(self, 0.5, 2.0, 0.05)
|
||
self.deferred = 1
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
<!-- Re-apply the slider bounds from the REFERENCE's OptionsFrameSliders every time the page is shown.
|
||
The rows read the table at OnLoad, which is long before any addon runs; an addon that
|
||
writes a bound (pfUI's hdgraphic raises Environment Detail's maxValue to 15) would
|
||
otherwise never move the slider it just rewrote. The reference does the same loop in
|
||
OptionsFrame_Load; ours lives here rather than under that name because our page
|
||
implements almost none of the rest of that function's contract and publishing a
|
||
reference name over a partial body is how a gap hides.
|
||
|
||
fmt and stops are read back off the row rather than the table: they are OUR readout
|
||
grammar (0992/1649's stop names), set at OnLoad, and no addon addresses them. -->
|
||
<Scripts>
|
||
<OnShow>
|
||
for i, name in BENILLA_GRAPHICS_SLIDER_ROWS do
|
||
local info = OptionsFrameSliders[i]
|
||
local row = getglobal(this:GetName() .. name)
|
||
if ( info and row ) then
|
||
OptionsSliderRow_Setup(row, info.minValue, info.maxValue,
|
||
info.valueStep, row.fmt, row.stops)
|
||
end
|
||
end
|
||
</OnShow>
|
||
</Scripts>
|
||
</Frame>
|
||
<!-- The COMBAT page (decision 1134) — the first page whose rows
|
||
write saved-variable GLOBALS rather than CVars, and the first
|
||
thing that can change any of the ~20 stock globals 1128
|
||
ported. It is 1.12's AdvancedOptionsCombatText box, whole: the
|
||
master, the scroll-mode dropdown, and the twelve sub-toggles,
|
||
in the reference box's own anchor-chain order, with its
|
||
GlobalStrings labels and OPTION_TOOLTIP_* keys verbatim and
|
||
each sub-toggle at the reference's default (the assignment in
|
||
CombatText.xml, which is also where the Defaults button reads
|
||
from). Every row runs CombatText_UpdateDisplayedMessages as
|
||
its applyFunc — the reference's own post-Save call, moved to
|
||
the click because this window writes live (0961). -->
|
||
<Frame name="$parentCombat" hidden="true">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"/>
|
||
<Anchor point="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
<Frames>
|
||
<Frame name="$parentRowCombatText" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="10" y="-12"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT"><Offset><AbsDimension x="-20" y="-12"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "SHOW_COMBAT_TEXT",
|
||
"Enable Floating Combat Text", "OPTION_TOOLTIP_SHOW_COMBAT_TEXT")
|
||
self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- The scroll mode. 1.12's own dropdown, values and all
|
||
(UIOptionsFrameCombatTextDropDown_Initialize: "1" up,
|
||
"2" down, "3" arc), worn as an era dropdown row. -->
|
||
<Frame name="$parentRowFloatMode" inherits="OptionsDropdownRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowCombatText" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowCombatText" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_FLOAT_MODE",
|
||
"Combat Text Float Mode", "OPTION_TOOLTIP_COMBAT_TEXT_MODE", 1)
|
||
OptionsDropdownRow_Setup(self, {
|
||
{ text = "Scroll Up", value = "1" },
|
||
{ text = "Scroll Down", value = "2" },
|
||
{ text = "Arc", value = "3" },
|
||
})
|
||
self.parentRow = "RowCombatText"
|
||
self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowLowHealthMana" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowFloatMode" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowFloatMode" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_LOW_HEALTH_MANA",
|
||
"Show Low Mana and Health",
|
||
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_LOW_HEALTH_MANA", 1)
|
||
self.parentRow = "RowCombatText"
|
||
self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowAuras" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowLowHealthMana" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowLowHealthMana" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_AURAS",
|
||
"Show Auras", "OPTION_TOOLTIP_COMBAT_TEXT_SHOW_AURAS", 1)
|
||
self.parentRow = "RowCombatText"
|
||
self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowAuraFade" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowAuras" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowAuras" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_AURA_FADE",
|
||
"Show Fading Auras", "OPTION_TOOLTIP_COMBAT_TEXT_SHOW_AURA_FADE", 1)
|
||
self.parentRow = "RowCombatText"
|
||
self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowCombatState" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowAuraFade" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowAuraFade" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_COMBAT_STATE",
|
||
"Show Combat State",
|
||
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_COMBAT_STATE", 1)
|
||
self.parentRow = "RowCombatText"
|
||
self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowDodgeParryMiss" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowCombatState" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowCombatState" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_DODGE_PARRY_MISS",
|
||
"Show Dodge/Parries/Misses",
|
||
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_DODGE_PARRY_MISS", 1)
|
||
self.parentRow = "RowCombatText"
|
||
self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowResistances" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowDodgeParryMiss" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowDodgeParryMiss" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_RESISTANCES",
|
||
"Show Damage Reduction",
|
||
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_RESISTANCES", 1)
|
||
self.parentRow = "RowCombatText"
|
||
self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowReputation" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowResistances" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowResistances" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_REPUTATION",
|
||
"Show Reputation",
|
||
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_REPUTATION", 1)
|
||
self.parentRow = "RowCombatText"
|
||
self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowReactives" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowReputation" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowReputation" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_REACTIVES",
|
||
"Show Reactive Spells and Abilities",
|
||
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_REACTIVES", 1)
|
||
self.parentRow = "RowCombatText"
|
||
self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowFriendlyNames" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowReactives" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowReactives" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_FRIENDLY_NAMES",
|
||
"Show Friendly Healer Names",
|
||
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_FRIENDLY_NAMES", 1)
|
||
self.parentRow = "RowCombatText"
|
||
self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- Combo Points carries the reference's SECOND gate: greyed
|
||
for anyone who is not a rogue or a druid — see
|
||
OptionsPage_UpdateDependencies. -->
|
||
<Frame name="$parentRowComboPoints" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowFriendlyNames" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowFriendlyNames" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_COMBO_POINTS",
|
||
"Show Combo Points",
|
||
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_COMBO_POINTS", 1)
|
||
self.parentRow = "RowCombatText"
|
||
self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowEnergyGains" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowComboPoints" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowComboPoints" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_MANA",
|
||
"Show Energy Gains",
|
||
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_MANA", 1)
|
||
self.parentRow = "RowCombatText"
|
||
self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowHonorGained" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowEnergyGains" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowEnergyGains" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_HONOR_GAINED",
|
||
"Show Honor Gained",
|
||
"OPTION_TOOLTIP_COMBAT_TEXT_SHOW_HONOR_GAINED", 1)
|
||
self.parentRow = "RowCombatText"
|
||
self.applyFunc = "CombatText_UpdateOrLoad" -- by NAME, resolved when applied: this file loads before its definer now (1938)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- ── The damage NUMBERS (2180): a second master and its two children ──────
|
||
Same box as the floating-combat-text family above and a different
|
||
hierarchy: `CombatDamage` is the master of what floats over a UNIT,
|
||
`SHOW_COMBAT_TEXT` of what scrolls beside the player, and the reference
|
||
keeps their dependency blocks apart (UIOptionsFrame.lua l.709-714 against
|
||
l.727-741). All three are CVar rows with host readers, so the write is the
|
||
apply and none carries the family's `applyFunc`.
|
||
|
||
`CombatDamage`'s help text says "damage numbers" and it does more than
|
||
that: its only two readers are the localized-WORD emitter `0x607140` and
|
||
the "%d" NUMBER emitter `0x6128b0`, and both branch targets are epilogues
|
||
— at "0" nothing floats over any unit from any source, misses and
|
||
immunities included. -->
|
||
<Frame name="$parentRowShowDamage" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowHonorGained" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowHonorGained" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "CombatDamage", "Show Target Damage",
|
||
"OPTION_TOOLTIP_SHOW_DAMAGE")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- Periodic Damage reaches further than its label: `CombatLogPeriodicSpells`
|
||
off takes the whole `SMSG_PERIODICAURALOG` body — every
|
||
CHAT_MSG_SPELL_PERIODIC_* line AND the DoT/HoT tick number AND the
|
||
periodic miss word (`0x626dee` jumps to a bare epilogue). The row is the
|
||
reference's wording over the reference's behaviour; neither is ours to
|
||
improve. -->
|
||
<Frame name="$parentRowPeriodicDamage" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowShowDamage" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowShowDamage" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "CombatLogPeriodicSpells", "Periodic Damage",
|
||
"OPTION_TOOLTIP_LOG_PERIODIC_EFFECTS", 1)
|
||
self.parentRow = "RowShowDamage"
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- Pet Damage carries the reference's PARTNER write: its box drives BOTH
|
||
`PetMeleeDamage` and `PetSpellDamage` (UIOptionsFrame_Save l.334-336), the
|
||
second of which appears in no option table at all — which is why 2077's
|
||
census, reading that table, could see two of the three. Without the
|
||
partner the box would say "pet damage off" while pet SPELL damage kept
|
||
floating, and nothing would say so. -->
|
||
<Frame name="$parentRowPetDamage" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowPeriodicDamage" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowPeriodicDamage" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "PetMeleeDamage", "Pet Damage",
|
||
"OPTION_TOOLTIP_SHOW_PET_MELEE_DAMAGE", 1)
|
||
self.parentRow = "RowShowDamage"
|
||
self.partner = { cvar = "PetSpellDamage" }
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
</Frame>
|
||
<!-- The ACTION BARS page (1136's lock row; the five switches above
|
||
it are 1500). 1.12's Advanced Options group, whole.
|
||
|
||
The four bar rows are API (`func`) rows — the third store, the
|
||
one Show Cloak / Show Helm opened in 1472 — because there is
|
||
nothing local to save: the preference is four bits of this
|
||
CHARACTER's server-side PLAYER_FIELD_BYTES byte 2, written with
|
||
CMSG_SET_ACTIONBAR_TOGGLES. The getter reads the live Lua
|
||
global (the client never re-reads the field and nothing fires
|
||
on a change to it, so the global IS the state between logins);
|
||
the setter writes the global, re-derives the bars, and re-sends
|
||
the whole byte. Default OFF for all four — a fresh character's
|
||
byte is 0.
|
||
|
||
Always Show ActionBars is a SAVED-VARIABLE row instead, and the
|
||
split is a verified consequence of the engine binding rather
|
||
than an authoring choice: `SetActionBarToggles` takes exactly
|
||
four arguments and silently DROPS the fifth that the reference
|
||
passes it (`cmp esi,4` at 0x4e770e), so that switch has no
|
||
server store to write and the reference RegisterForSave's it
|
||
locally too (UIOptionsFrame.lua l.106-107). Decision 1500 and
|
||
wow-re action-bar-toggles.md carry the whole byte-level finding.
|
||
|
||
The getters and setters are written here as closures rather
|
||
than captured from the bar file by name, deliberately: a row's
|
||
OnLoad captures a function VALUE, so a named import would make
|
||
this page depend on load ORDER — and a harness (or a manifest
|
||
reordering) that loaded the window without the bars would give
|
||
every row a nil store instead of an unticked box. A closure
|
||
resolves its callee when the player clicks.
|
||
|
||
Labels and OPTION_TOOLTIP_* keys are 1.12's GlobalStrings
|
||
verbatim (SHOW_MULTIBAR1..4_TEXT l.3444-3447,
|
||
ALWAYS_SHOW_MULTIBARS_TEXT l.51) — including the leading
|
||
"Show ", which is part of the reference's own display text.
|
||
|
||
The lock itself had to be BUILT before it could have a row:
|
||
ActionBar.xml and PetActionBar.xml guard their drag ends on it,
|
||
the way the reference does. -->
|
||
<Frame name="$parentActionBars" hidden="true">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"/>
|
||
<Anchor point="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
<Frames>
|
||
<Frame name="$parentRowMultiBar1" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="10" y="-12"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT"><Offset><AbsDimension x="-20" y="-12"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsFuncRow_OnLoad(self,
|
||
function() return SHOW_MULTI_ACTIONBAR_1 end,
|
||
function(value)
|
||
local on
|
||
if value and value ~= "0" and value ~= 0 then on = 1 end
|
||
SHOW_MULTI_ACTIONBAR_1 = on
|
||
MultiActionBar_Update()
|
||
SetActionBarToggles(SHOW_MULTI_ACTIONBAR_1, SHOW_MULTI_ACTIONBAR_2,
|
||
SHOW_MULTI_ACTIONBAR_3, SHOW_MULTI_ACTIONBAR_4)
|
||
UIParent_ManageFramePositions()
|
||
end,
|
||
"0", "Show Bottom Left ActionBar", "OPTION_TOOLTIP_SHOW_MULTIBAR1")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowMultiBar2" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowMultiBar1" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowMultiBar1" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsFuncRow_OnLoad(self,
|
||
function() return SHOW_MULTI_ACTIONBAR_2 end,
|
||
function(value)
|
||
local on
|
||
if value and value ~= "0" and value ~= 0 then on = 1 end
|
||
SHOW_MULTI_ACTIONBAR_2 = on
|
||
MultiActionBar_Update()
|
||
SetActionBarToggles(SHOW_MULTI_ACTIONBAR_1, SHOW_MULTI_ACTIONBAR_2,
|
||
SHOW_MULTI_ACTIONBAR_3, SHOW_MULTI_ACTIONBAR_4)
|
||
UIParent_ManageFramePositions()
|
||
end,
|
||
"0", "Show Bottom Right ActionBar", "OPTION_TOOLTIP_SHOW_MULTIBAR2")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowMultiBar3" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowMultiBar2" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowMultiBar2" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsFuncRow_OnLoad(self,
|
||
function() return SHOW_MULTI_ACTIONBAR_3 end,
|
||
function(value)
|
||
local on
|
||
if value and value ~= "0" and value ~= 0 then on = 1 end
|
||
SHOW_MULTI_ACTIONBAR_3 = on
|
||
MultiActionBar_Update()
|
||
SetActionBarToggles(SHOW_MULTI_ACTIONBAR_1, SHOW_MULTI_ACTIONBAR_2,
|
||
SHOW_MULTI_ACTIONBAR_3, SHOW_MULTI_ACTIONBAR_4)
|
||
UIParent_ManageFramePositions()
|
||
end,
|
||
"0", "Show Right ActionBar", "OPTION_TOOLTIP_SHOW_MULTIBAR3")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- Bar 4 is a CHILD row: MultiBarLeft only shows when bar 3
|
||
is also on (MultiBars.xml's conjunction — its column
|
||
hangs off MultiBarRight's edge), so the switch is
|
||
meaningless on its own. `child` carries the era's
|
||
indent-and-small-font subordination; the GREYING is
|
||
OptionsPage_UpdateDependencies' ActionBars arm, which
|
||
is the reference's own rule for this exact pair
|
||
(UIOptionsFrame.lua l.722-726 disables CheckButton36
|
||
while 35 is unchecked). -->
|
||
<Frame name="$parentRowMultiBar4" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowMultiBar3" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowMultiBar3" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsFuncRow_OnLoad(self,
|
||
function() return SHOW_MULTI_ACTIONBAR_4 end,
|
||
function(value)
|
||
local on
|
||
if value and value ~= "0" and value ~= 0 then on = 1 end
|
||
SHOW_MULTI_ACTIONBAR_4 = on
|
||
MultiActionBar_Update()
|
||
SetActionBarToggles(SHOW_MULTI_ACTIONBAR_1, SHOW_MULTI_ACTIONBAR_2,
|
||
SHOW_MULTI_ACTIONBAR_3, SHOW_MULTI_ACTIONBAR_4)
|
||
UIParent_ManageFramePositions()
|
||
end,
|
||
"0", "Show Right ActionBar 2", "OPTION_TOOLTIP_SHOW_MULTIBAR4", 1)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowAlwaysShowMultibars" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowMultiBar4" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowMultiBar4" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "ALWAYS_SHOW_MULTIBARS",
|
||
"Always Show ActionBars", "OPTION_TOOLTIP_ALWAYS_SHOW_MULTIBARS")
|
||
-- A CLICK runs MultiActionBar_UpdateGridVisibility, the
|
||
-- reference's own click arm (UIOptionsFrame.xml:683).
|
||
-- The LOAD arm — which only ever SHOWS, because every hide
|
||
-- is a counted decrement on each well (ActionButton_HideGrid)
|
||
-- and a load-time hide against wells nobody opened would push
|
||
-- the count negative — is the stock file's
|
||
-- VARIABLES_LOADED arm now (UIOptionsFrame.lua l.218-220),
|
||
-- which is why this row carries no `loadFunc` (2115).
|
||
self.applyFunc = "MultiActionBar_UpdateGridVisibility"
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowLockActionBar" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowAlwaysShowMultibars" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowAlwaysShowMultibars" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "LOCK_ACTIONBAR",
|
||
"Lock ActionBars", "OPTION_TOOLTIP_LOCK_ACTIONBAR")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
</Frame>
|
||
<!-- The INTERFACE page (decision 1136; the Buff Durations row is
|
||
1139, the two equipment-display rows 1472) — the second
|
||
store's second page, and the one 1134 §3 named as ready: stock
|
||
globals already defined AND consumed, needing only a row. Rows
|
||
in the reference's own on-screen order — Basic Options' anchor
|
||
chain runs CheckButton42 → 39 → 62 → 66 in Display, then 29 in
|
||
Help, and we hold all of those but 62
|
||
(HIDE_OUTDOOR_WORLD_STATE: there is no zone-objective tracker
|
||
to hide); Show Cloak → Show Helm (31 → 20) are that box's
|
||
middle column, seated after Status Text because the two rows
|
||
above them there — the player/NPC name toggles — live on our
|
||
Nameplates page. Labels and OPTION_TOOLTIP_* keys are its
|
||
GlobalStrings verbatim.
|
||
|
||
Only Buff Durations carries an `applyFunc`, and the split is
|
||
the honest one rather than an omission: the other three are
|
||
read at the moment their consumer acts — the tooltip as it is
|
||
built, the quest panel as it shows, the auto-watch as progress
|
||
arrives — so the write IS the apply. A setting is owed an
|
||
applyFunc exactly when something DERIVED from it is stated
|
||
once and kept: the buff bar's row pitch, the combat-text
|
||
family's event registrations. -->
|
||
<Frame name="$parentInterface" hidden="true">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"/>
|
||
<Anchor point="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
<Frames>
|
||
<!-- Status Bar Text (decision 1140). First because it is
|
||
first in the reference's file: its own Display column
|
||
runs CheckButton12 -> **2** -> 21, and 2 is declared
|
||
ahead of the 42 chain below it. The one row in this
|
||
window carrying a `cvarEvent`: TextStatusBar.xml has
|
||
had a CVAR_UPDATE watcher since 1082 and nothing to
|
||
wake it. -->
|
||
<!-- Enhanced Tooltips (2180), and it takes the head seat because it takes the
|
||
reference's: the Display box's first column is 12 -> 2 -> 21, and 12 is the
|
||
first CheckButton the file declares. Its consumers are LUA — the action and
|
||
pet bars fork their plate corner on `GetCVar("UberTooltips")` — which is why
|
||
`apply_to_knobs` has nothing to do for it and why the row had none of the
|
||
usual "no reader" reason to be absent; it was simply never seated. -->
|
||
<Frame name="$parentRowEnhancedTooltips" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="10" y="-12"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT"><Offset><AbsDimension x="-20" y="-12"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>OptionsRow_OnLoad(self, "UberTooltips", "Enhanced Tooltips",
|
||
"OPTION_TOOLTIP_USE_UBERTOOLTIPS")</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowStatusText" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowEnhancedTooltips" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowEnhancedTooltips" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "statusBarText",
|
||
"Status Bar Text", "OPTION_TOOLTIP_STATUS_BAR")
|
||
self.cvarEvent = "STATUS_BAR_TEXT"
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- The target-of-target pair (decision 1576): the switch
|
||
and, indented under it, when the frame is allowed to
|
||
stand. Both are `uvar` rows — 1.12 keeps these two as
|
||
saved globals, not CVars (UnitFrames.xml declares and
|
||
RegisterForSave's them) — and both carry the same
|
||
applyFunc, because the saved chunk lands after the XML
|
||
that read it: without the re-run, a saved "1" would
|
||
leave the frame hidden until the next target change.
|
||
The mode row is a CHILD (indent + small font + greyed
|
||
with the switch off), which is the reference's own
|
||
relationship: its dropdown hangs off CheckButton50's
|
||
BOTTOMLEFT and OptionsFrame_DisableDropDown greys it
|
||
from the same test (UIOptionsFrame.lua l.694-700). -->
|
||
<Frame name="$parentRowTargetOfTarget" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowStatusText" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowStatusText" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "SHOW_TARGET_OF_TARGET",
|
||
"Show Target of Target", "OPTION_TOOLTIP_SHOW_TARGET_OF_TARGET")
|
||
self.applyFunc = "TargetofTarget_Update" -- by NAME, resolved when applied: this file loads before its definer now (1938)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- The label is ours: the reference declares a Label
|
||
FontString for this dropdown and never sets its text,
|
||
so in 1.12 the picker sits under the checkbox with no
|
||
name at all. An indented row in this window has to say
|
||
what it picks, and the row above supplies the subject.
|
||
The five values are the reference's own strings, and
|
||
its own order (its OPTION_TOOLTIP_TARGETOFTARGET1..5
|
||
describe them in exactly this sequence). -->
|
||
<Frame name="$parentRowTargetOfTargetMode" inherits="OptionsDropdownRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowTargetOfTarget" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowTargetOfTarget" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "SHOW_TARGET_OF_TARGET_STATE",
|
||
"Show When", "OPTION_TOOLTIP_TARGETOFTARGET5", 1)
|
||
OptionsDropdownRow_Setup(self, {
|
||
{ text = "Raid", value = "1", tip = "OPTION_TOOLTIP_TARGETOFTARGET1" },
|
||
{ text = "Party", value = "2", tip = "OPTION_TOOLTIP_TARGETOFTARGET2" },
|
||
{ text = "Solo", value = "3", tip = "OPTION_TOOLTIP_TARGETOFTARGET3" },
|
||
{ text = "Party or Raid", value = "4", tip = "OPTION_TOOLTIP_TARGETOFTARGET4" },
|
||
{ text = "Always", value = "5", tip = "OPTION_TOOLTIP_TARGETOFTARGET5" },
|
||
})
|
||
self.applyFunc = "TargetofTarget_Update" -- by NAME, resolved when applied: this file loads before its definer now (1938)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- The two equipment-display toggles (decision 1472,
|
||
B123). Neither has a store: the preference is a bit of
|
||
this character's own server-side PLAYER_FLAGS, so the
|
||
row reads the engine getter and writes the engine
|
||
setter — 1.12's own `func`/`setFunc` pair for exactly
|
||
these two rows (UIOptionsFrame.lua l.18-19), and the
|
||
reason there is no CVar to register. Default "1" for
|
||
both, the reference's own hand-written arm. -->
|
||
<Frame name="$parentRowShowCloak" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowTargetOfTargetMode" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowTargetOfTargetMode" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsFuncRow_OnLoad(self, ShowingCloak, ShowCloak, "1",
|
||
"Show Cloak", "OPTION_TOOLTIP_SHOW_CLOAK")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowShowHelm" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowShowCloak" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowShowCloak" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsFuncRow_OnLoad(self, ShowingHelm, ShowHelm, "1",
|
||
"Show Helm", "OPTION_TOOLTIP_SHOW_HELM")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowInstantQuestText" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowShowHelm" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowShowHelm" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "QUEST_FADING_DISABLE",
|
||
"Instant Quest Text", "OPTION_TOOLTIP_SHOW_QUEST_FADING")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- The reference's own next link in that chain
|
||
(CheckButton39, anchored under 42), and the one row on
|
||
this page that DOES carry an applyFunc: the timer text
|
||
is re-decided by the bar's per-frame poll, but the row
|
||
PITCH is stated once and has to be re-stated when the
|
||
switch moves (decision 1139). -->
|
||
<Frame name="$parentRowBuffDurations" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowInstantQuestText" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowInstantQuestText" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "SHOW_BUFF_DURATIONS",
|
||
"Buff Durations", "OPTION_TOOLTIP_SHOW_BUFF_DURATION")
|
||
self.applyFunc = "BuffButtons_UpdatePositions" -- by NAME, resolved when applied: this file loads before its definer now (1938)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowAutoQuestWatch" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowBuffDurations" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowBuffDurations" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "AUTO_QUEST_WATCH",
|
||
"Automatic Quest Tracking", "OPTION_TOOLTIP_AUTO_QUEST_WATCH")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- Column C's last link (decision 2077): 1.12 anchors
|
||
CheckButton5 TOP to CheckButton66's BOTTOM, so
|
||
Profanity Filter closes the 42 -> 39 -> 66 chain the
|
||
three rows above are. It reads as a chat setting and
|
||
the reference files it under Display; the reference's
|
||
seat wins, as everywhere else on this page.
|
||
|
||
What it actually does is wider than its neighbours
|
||
suggest: `profanityFilter` gates INSIDE the shared
|
||
masker (`0x4a1a66`), so one tick covers all thirteen
|
||
of its call sites. benilla wires the largest — the
|
||
fourteen social chat types — and `crate::text_filter`
|
||
names the twelve still to come. -->
|
||
<Frame name="$parentRowProfanityFilter" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowAutoQuestWatch" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowAutoQuestWatch" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>OptionsRow_OnLoad(self, "profanityFilter", "Profanity Filter",
|
||
"OPTION_TOOLTIP_PROFANITY_FILTER")</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- The HELP box opens here (decision 2077). 1.12 seats
|
||
CheckButton28 at its TOPLEFT and hangs 44 (Show
|
||
Loading Screen Tips) under it, with 29 (this page's
|
||
Show Detailed Tooltips) off to the right of the Reset
|
||
Tutorials button — so 28 -> 44 -> 29 is the box's own
|
||
reading order flattened into our column, which is the
|
||
order below.
|
||
The Reset Tutorials BUTTON itself is not here: it is
|
||
not a checkbox, and `ResetTutorials()` is exactly what
|
||
ticking this row already does. -->
|
||
<Frame name="$parentRowShowTutorials" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowProfanityFilter" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowProfanityFilter" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<!-- A `func` row, like Show Cloak / Show Helm: there is
|
||
no store, the bank IS the state. Its default is the
|
||
reference's own hand-written one
|
||
(UIOptionsFrame_SetDefaults l.645,
|
||
`OptionsFrame_EnableCheckBox(checkButton, 1, 1)`). -->
|
||
<Scripts><OnLoad>
|
||
OptionsFuncRow_OnLoad(self, TutorialsEnabled,
|
||
BenillaOptionsFrame_SetTutorialsEnabled, "1",
|
||
"Show Tutorials", "OPTION_TOOLTIP_SHOW_TUTORIALS")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- CheckButton44, anchored under 28 in the reference's own
|
||
Help box. Its LABEL is 1.12's own and it is not the
|
||
name the tooltip uses: `SHOW_TIPOFTHEDAY_TEXT` reads
|
||
"Show Loading Screen Tips", while the description
|
||
under `OPTION_TOOLTIP_SHOW_TIPOFTHEDAY` still calls it
|
||
the tip of the day. Both are the reference's strings,
|
||
so both stand. -->
|
||
<Frame name="$parentRowTipOfTheDay" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowShowTutorials" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowShowTutorials" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>OptionsRow_OnLoad(self, "showGameTips",
|
||
"Show Loading Screen Tips",
|
||
"OPTION_TOOLTIP_SHOW_TIPOFTHEDAY")</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowNewbieTips" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowTipOfTheDay" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowTipOfTheDay" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsGlobalRow_OnLoad(self, "SHOW_NEWBIE_TIPS",
|
||
"Show Detailed Tooltips", "OPTION_TOOLTIP_SHOW_NEWBIE_TIPS")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
</Frame>
|
||
<!-- The SOCIAL page (decision 1139) — the last category in this
|
||
window that opened onto nothing. Both rows are CVar rows, not
|
||
globals: `ChatBubbles`/`ChatBubblesParty` are 1.12's own
|
||
registrar CVars, and chat_bubble.rs held them as a pair of
|
||
`const bool` from 0598 — a gate transcribed faithfully with no
|
||
way to reach it, which is the same shape as the action-bar lock
|
||
and fixed the same way (the knob first, then the row).
|
||
|
||
1.12's own order, with one gap named: its Advanced Options chat
|
||
chain runs CheckButton37 (Chat Bubbles) → 46 (Loot Spam) → 38
|
||
(Party Chat Bubbles), and 46 is not ours to ship — no
|
||
`showLootSpam` knob exists. So these two are adjacent here and
|
||
in the reference's relative order. Neither is a dependency child:
|
||
the client gates party lines on their own CVar, so party bubbles
|
||
survive turning say/yell bubbles off. -->
|
||
<!-- The Chat page (decision 1589 — B246, "no chat section in
|
||
options"). 1.12's Advanced Options CHAT_LABEL box, in its own
|
||
anchor-chain order; which of its nine rows we ship and why the
|
||
other five are absent is the OPTIONS_PAGE_ROWS entry's note.
|
||
The window's *look* — background tint, opacity, font size —
|
||
is deliberately NOT here: the reference puts it on the chat
|
||
tab's right-click menu (ChatFrame.xml), and inventing a second
|
||
home for it would be a divergence, not a convenience. -->
|
||
<Frame name="$parentChat" hidden="true">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"/>
|
||
<Anchor point="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
<Frames>
|
||
<Frame name="$parentRowGuildMemberAlert" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="10" y="-12"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT"><Offset><AbsDimension x="-20" y="-12"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
<!-- Registered "0" — the one row on this page that
|
||
ships its feature OFF, and byte-read rather
|
||
than chosen (cvars.rs cites the site). No
|
||
applyFunc: the guild sign-on handler reads the
|
||
knob as each event lands. -->
|
||
OptionsRow_OnLoad(self, "guildMemberNotify",
|
||
"Guild Member Alert",
|
||
"OPTION_TOOLTIP_GUILDMEMBER_ALERT")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowRemoveChatDelay" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowGuildMemberAlert" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowGuildMemberAlert" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
<!-- A uvar, like the reference's (CheckButton18).
|
||
Its applyFunc is the whole feature: the two
|
||
fade constants live in ChatFrame.xml and
|
||
SetChatMouseOverDelay is what moves them. The
|
||
row needs one because nothing re-reads the
|
||
global per frame — the fade reads the
|
||
constants, and only this writes them. -->
|
||
OptionsGlobalRow_OnLoad(self, "REMOVE_CHAT_DELAY",
|
||
"Remove Chat Hover Delay",
|
||
"OPTION_TOOLTIP_REMOVE_CHAT_DELAY")
|
||
self.applyFunc = "ChatFrame_ApplyMouseOverDelay" -- by NAME, resolved when applied: this file loads before its definer now (1938)
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowChatBubbles" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowRemoveChatDelay" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowRemoveChatDelay" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "ChatBubbles",
|
||
"Show Chat Bubbles", "OPTION_TOOLTIP_CHAT_BUBBLES")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowLootSpam" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowChatBubbles" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowChatBubbles" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
<!-- "Detailed Loot Information" is the label; the
|
||
CVar is `showLootSpam` and it is about GROUP
|
||
LOOT ROLLS, not about loot messages generally
|
||
(its own tooltip: "Uncheck this to hide
|
||
individual loot roll messages and only show
|
||
the winner"). No applyFunc: the loot-roll
|
||
lines read the CVar as each one is composed. -->
|
||
OptionsRow_OnLoad(self, "showLootSpam",
|
||
"Detailed Loot Information",
|
||
"OPTION_TOOLTIP_SHOW_LOOT_SPAM")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowPartyChatBubbles" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowLootSpam" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowLootSpam" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "ChatBubblesParty",
|
||
"Show Party Chat Bubbles", "OPTION_TOOLTIP_PARTY_CHAT_BUBBLES")
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- CheckButton 68, the last link in the reference's chat
|
||
chain, and the row this page's note has been promising
|
||
since 1589 ("the row lands with the filter"). It lands
|
||
with decision 2077.
|
||
|
||
**Value-INVERTED**, like Sticky Targeting: the label
|
||
says *Disable* Spam Filter, so the box is checked when
|
||
`spamFilter` reads "0". That is the reference's own
|
||
pair of arms — `UIOptionsFrame.lua` l.253 checks it on
|
||
`GetCVar == "0"` and l.337 flips the value before
|
||
writing.
|
||
|
||
The filter behind it drops a line matching any of
|
||
`SpamMessages.dbc`'s 28 gold-seller patterns, silently
|
||
and with nothing in its place — every chat type except
|
||
CHAT_MSG_FILTERED, never for a GM-tagged line or a GM
|
||
viewer. See `crate::text_filter`. -->
|
||
<Frame name="$parentRowSpamFilter" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowPartyChatBubbles" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowPartyChatBubbles" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "spamFilter", "Disable Spam Filter",
|
||
"OPTION_TOOLTIP_DISABLE_SPAM_FILTER")
|
||
self.invert = 1
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
</Frame>
|
||
<!-- The Nameplates page (0992 — the page 0952 promised when the
|
||
category row joined). Two groups, plates first: the V-key
|
||
HEALTH-BAR plates (vplates.rs VPlateMode — the engine bitmask
|
||
[0xc4da34] bit 0 / bit 3), then the three 1.12 UnitName*
|
||
checkboxes over the overhead-name gates (nameplates.rs
|
||
NameConfig), rows in the 1.12 Interface Options' own index
|
||
order (21/22/30/67 — 22, Player Guild Names, arrived with
|
||
2180), labels its GlobalStrings verbatim (SHOW_PLAYER_NAMES/
|
||
SHOW_GUILD_NAMES/SHOW_NPC_NAMES/SHOW_OWN_NAME).
|
||
|
||
The plate pair leads because it is what "Nameplates" means to
|
||
a player pressing V, and it is the pair that had no surface at
|
||
all — 1.12's own options UI has NO nameplate row (its
|
||
UIOptionsFrame keeps NAMEPLATES_ON/FRIENDNAMEPLATES_ON as
|
||
RegisterForSave'd globals driven only by the keybinding, and
|
||
says so in a comment), so the rows are era grammar over a
|
||
1.12 knob — 0959's law, the WorldDetail dropdown's posture.
|
||
Labels take the 1.12 binding names' own two-word spelling
|
||
("Name Plates", BINDING_NAME_NAMEPLATES) with the era's
|
||
enemy/friendly split naming the two bits; no 1.12
|
||
OPTION_TOOLTIP string exists for either (nil, like Auto
|
||
Loot). -->
|
||
<Frame name="$parentNameplates" hidden="true">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"/>
|
||
<Anchor point="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
<Frames>
|
||
<Frame name="$parentRowEnemyPlates" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="10" y="-12"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT"><Offset><AbsDimension x="-20" y="-12"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>OptionsRow_OnLoad(self, "nameplateShowEnemies",
|
||
"Enemy Name Plates")</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowFriendlyPlates" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowEnemyPlates" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowEnemyPlates" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>OptionsRow_OnLoad(self, "nameplateShowFriends",
|
||
"Friendly Name Plates")</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowPlayerNames" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowFriendlyPlates" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowFriendlyPlates" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>OptionsRow_OnLoad(self, "UnitNamePlayer", "Player Names",
|
||
"OPTION_TOOLTIP_SHOW_PLAYER_NAMES")</OnLoad></Scripts>
|
||
</Frame>
|
||
<!-- Player Guild Names (2149 §6 built the line; 2180 seats the row). A CHILD of
|
||
Player Names in both of the reference's own senses: its CheckButton22 hangs
|
||
off 21 with a +26 x indent, and UIOptionsFrame_UpdateDependencies greys it
|
||
from 21's tick. `UnitNamePlayerGuild` is not a SHOW gate — ShouldShowName
|
||
reads only bits 0x1/0x2/0x4 — it gates one LINE of the overhead stack, which
|
||
is why the dependency is real rather than cosmetic: with player names off
|
||
there is no stack for the guild line to be the second row of. -->
|
||
<Frame name="$parentRowGuildNames" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowPlayerNames" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowPlayerNames" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>
|
||
OptionsRow_OnLoad(self, "UnitNamePlayerGuild", "Player Guild Names",
|
||
"OPTION_TOOLTIP_SHOW_GUILD_NAMES", 1)
|
||
self.parentRow = "RowPlayerNames"
|
||
</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowNpcNames" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowGuildNames" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowGuildNames" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>OptionsRow_OnLoad(self, "UnitNameNPC", "NPC Names",
|
||
"OPTION_TOOLTIP_SHOW_NPC_NAMES")</OnLoad></Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRowOwnName" inherits="OptionsCheckboxRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRowNpcNames" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRowNpcNames" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnLoad>OptionsRow_OnLoad(self, "UnitNameOwn", "Show Own Name",
|
||
"OPTION_TOOLTIP_SHOW_OWN_NAME")</OnLoad></Scripts>
|
||
</Frame>
|
||
</Frames>
|
||
</Frame>
|
||
<!-- The KEYBINDINGS page body (decision 1008 — the era Settings
|
||
panel's Keybindings category folded into this window; the module,
|
||
provenance and commit law: KeyBindingsPage.xml). First the
|
||
Character Specific row (the era page's first setting row, confirm
|
||
on uncheck only), then the section list — 19 dual-mode rows under
|
||
the shared faux-scroll kit, sections collapsed by default — and
|
||
the 1.12 window's message line (KEY_BOUND / the red steal / the
|
||
refused key string) at the foot. -->
|
||
<!-- enableMouse: the page catches the wheel ITSELF on any point no
|
||
child claims (hit-testing only sees mouse-enabled frames —
|
||
pointer.rs; rows are plain Frames, so a spin over a row's name
|
||
would otherwise fall through to the window and die). -->
|
||
<Frame name="$parentKeybindings" hidden="true" enableMouse="true">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"/>
|
||
<Anchor point="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="OVERLAY">
|
||
<FontString name="$parentOutput" inherits="GameFontNormal">
|
||
<Anchors><Anchor point="BOTTOM"><Offset><AbsDimension x="0" y="8"/></Offset></Anchor></Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- Character Specific Key Bindings — the era checkbox-row
|
||
geometry (label left, the UI-CheckBox set at the
|
||
control column) over 1.12's set model; the click law
|
||
is KeyBindings_CharacterToggle. This bespoke row's
|
||
column sits at CENTER-40, not the shared CENTER-80:
|
||
1.12's string is longer than the era's and clipped at
|
||
the shared split ("…Key Bindin…" — the first capture);
|
||
no other control shares this page's column, so the
|
||
shift is free. -->
|
||
<Frame name="$parentCharacterRow" enableMouse="true">
|
||
<Size><AbsDimension y="26"/></Size>
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="10" y="-12"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT"><Offset><AbsDimension x="-20" y="-12"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="OVERLAY">
|
||
<FontString name="$parentLabel" inherits="GameFontNormal" justifyH="LEFT">
|
||
<Anchors>
|
||
<Anchor point="LEFT"><Offset><AbsDimension x="37" y="0"/></Offset></Anchor>
|
||
<Anchor point="RIGHT" relativePoint="CENTER"><Offset><AbsDimension x="-45" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<CheckButton name="$parentCheck">
|
||
<Size><AbsDimension x="30" y="29"/></Size>
|
||
<Anchors><Anchor point="LEFT" relativePoint="CENTER"><Offset><AbsDimension x="-40" y="0"/></Offset></Anchor></Anchors>
|
||
<NormalTexture file="Interface\Buttons\UI-CheckBox-Up"/>
|
||
<PushedTexture file="Interface\Buttons\UI-CheckBox-Down"/>
|
||
<CheckedTexture file="Interface\Buttons\UI-CheckBox-Check"/>
|
||
<DisabledCheckedTexture file="Interface\Buttons\UI-CheckBox-Check-Disabled"/>
|
||
<Scripts>
|
||
<OnClick>KeyBindings_CharacterToggle(this)</OnClick>
|
||
<OnEnter>
|
||
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
|
||
GameTooltip:SetText(KeyBindings_String("CHARACTER_SPECIFIC_KEYBINDING_TOOLTIP",
|
||
"Click this to toggle between general key bindings and key bindings specific to this character."), nil, nil, nil, nil, 1)
|
||
</OnEnter>
|
||
<OnLeave>GameTooltip:Hide()</OnLeave>
|
||
</Scripts>
|
||
</CheckButton>
|
||
</Frames>
|
||
<Scripts>
|
||
<OnLoad>
|
||
getglobal(this:GetName() .. "Label"):SetText(
|
||
KeyBindings_String("CHARACTER_SPECIFIC_KEYBINDINGS", "Character Specific Key Bindings"))
|
||
</OnLoad>
|
||
</Scripts>
|
||
</Frame>
|
||
<Frame name="$parentRow1" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="10" y="-47"/></Offset></Anchor>
|
||
<Anchor point="TOPRIGHT"><Offset><AbsDimension x="-32" y="-47"/></Offset></Anchor>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentRow2" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRow1" relativePoint="BOTTOMLEFT"/>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRow1" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentRow3" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRow2" relativePoint="BOTTOMLEFT"/>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRow2" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentRow4" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRow3" relativePoint="BOTTOMLEFT"/>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRow3" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentRow5" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRow4" relativePoint="BOTTOMLEFT"/>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRow4" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentRow6" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRow5" relativePoint="BOTTOMLEFT"/>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRow5" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentRow7" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRow6" relativePoint="BOTTOMLEFT"/>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRow6" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentRow8" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRow7" relativePoint="BOTTOMLEFT"/>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRow7" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentRow9" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRow8" relativePoint="BOTTOMLEFT"/>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRow8" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentRow10" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRow9" relativePoint="BOTTOMLEFT"/>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRow9" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentRow11" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRow10" relativePoint="BOTTOMLEFT"/>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRow10" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentRow12" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRow11" relativePoint="BOTTOMLEFT"/>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRow11" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentRow13" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRow12" relativePoint="BOTTOMLEFT"/>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRow12" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentRow14" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRow13" relativePoint="BOTTOMLEFT"/>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRow13" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentRow15" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRow14" relativePoint="BOTTOMLEFT"/>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRow14" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentRow16" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRow15" relativePoint="BOTTOMLEFT"/>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRow15" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentRow17" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRow16" relativePoint="BOTTOMLEFT"/>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRow16" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentRow18" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRow17" relativePoint="BOTTOMLEFT"/>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRow17" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
</Frame>
|
||
<Frame name="$parentRow19" inherits="KeyBindingRowTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT" relativeTo="$parentRow18" relativePoint="BOTTOMLEFT"/>
|
||
<Anchor point="TOPRIGHT" relativeTo="$parentRow18" relativePoint="BOTTOMRIGHT"/>
|
||
</Anchors>
|
||
</Frame>
|
||
<!-- That bar's TROUGH — the recessed channel it rides in (the
|
||
shared kit's template; 1.12 authors this art per window,
|
||
never in the bar template). Named off the bar, which is
|
||
how BenillaScrollBar_SetShown finds it, and carrying no
|
||
anchors of its own: it seats itself on that bar at the
|
||
ref's hang (BenillaScrollTrough_Seat), which is what
|
||
lands the channel's arrow sockets on the arrows. Sits
|
||
here, BEFORE the faux frame, so it draws beneath it. -->
|
||
<Frame name="$parentScrollFrameScrollBarTrough" inherits="BenillaScrollTroughTemplate"/>
|
||
<!-- The faux scroll over the rows (the shared kit, 0997's own
|
||
seam). The kit's bar hangs 6px RIGHT of this frame's edge,
|
||
so the frame ends at the rows' own -32 and the 16-wide bar
|
||
rides the -26..-10 gutter inside the body (the TrainerFrame
|
||
seating). The wheel handler is NOT here: a spin over a row
|
||
bubbles up the PARENT chain (pointer.rs), and this frame is
|
||
the rows' sibling — it lives on the body below. -->
|
||
<ScrollFrame name="$parentScrollFrame" inherits="FauxScrollFrameTemplate">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="10" y="-47"/></Offset></Anchor>
|
||
<Anchor point="BOTTOMRIGHT"><Offset><AbsDimension x="-32" y="28"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts>
|
||
<OnLoad>ScrollFrame_OnLoad()</OnLoad>
|
||
<!-- The reference's kit writes `frame.offset` ONLY
|
||
from here (its `updateFunc` field does not
|
||
exist); without this the bar moves and the list
|
||
does not follow. `KEYBINDINGS_ROW_HEIGHT` is a
|
||
file-scope global in KeyBindingsPage.xml, so it
|
||
is visible to this handler's own chunk — a
|
||
`local` would not be (1860). -->
|
||
<OnVerticalScroll>FauxScrollFrame_OnVerticalScroll(KEYBINDINGS_ROW_HEIGHT, KeyBindingsPage_Update)</OnVerticalScroll>
|
||
<!-- **The armed guard has to be restated HERE.**
|
||
While a capsule is armed the wheel is a BIND,
|
||
never a scroll (1.12's law; the body below
|
||
guards its own arm the same way). Our retired
|
||
`FauxScrollFrameTemplate` was a plain `<Frame>`
|
||
with no wheel handler, so the body's guard was
|
||
the only path. The reference's template
|
||
inherits `UIPanelScrollFrameTemplate`, which
|
||
carries `<OnMouseWheel>` of its own — and that
|
||
one fires on this frame, ahead of the body,
|
||
bypassing the guard entirely. An instance's
|
||
handler REPLACES the inherited one, so this is
|
||
the reference's verb with our law back in front
|
||
of it (1860). -->
|
||
<OnMouseWheel>
|
||
if not KeyBindingsPage.selected then
|
||
ScrollFrameTemplate_OnMouseWheel(arg1)
|
||
end
|
||
</OnMouseWheel>
|
||
</Scripts>
|
||
</ScrollFrame>
|
||
</Frames>
|
||
<!-- The page's wheel: rows and the bar all bubble here (the
|
||
QuestLog/Trainer lesson — a handler on the sibling catcher
|
||
never sees a spin over a row). The guard is 1.12's law:
|
||
while a capsule is armed the wheel is a BIND (the host
|
||
seam swallows it) — never a scroll. -->
|
||
<Scripts>
|
||
<OnMouseWheel>
|
||
if not KeyBindingsPage.selected then
|
||
BenillaFauxScrollFrame_OnMouseWheel(getglobal(this:GetName() .. "ScrollFrame"), arg1)
|
||
end
|
||
</OnMouseWheel>
|
||
</Scripts>
|
||
</Frame>
|
||
<!-- The search-results group headers — one per page WITH rows
|
||
(the OPTIONS_PAGE_ROWS set; a page that gains rows gains its
|
||
head here). Unanchored and hidden until a search chains them
|
||
in; the label is the category's pageTitle, the era
|
||
GetQualifiedName. -->
|
||
<Button name="$parentSearchHeadControls" inherits="OptionsSearchHeadTemplate">
|
||
<Scripts><OnLoad>
|
||
self.categoryKey = "Controls"
|
||
getglobal(self:GetName() .. "Label"):SetText("Controls")
|
||
</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSearchHeadAudio" inherits="OptionsSearchHeadTemplate">
|
||
<Scripts><OnLoad>
|
||
self.categoryKey = "Audio"
|
||
getglobal(self:GetName() .. "Label"):SetText("Audio")
|
||
</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSearchHeadGraphics" inherits="OptionsSearchHeadTemplate">
|
||
<Scripts><OnLoad>
|
||
self.categoryKey = "Graphics"
|
||
getglobal(self:GetName() .. "Label"):SetText("Graphics")
|
||
</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSearchHeadCombat" inherits="OptionsSearchHeadTemplate">
|
||
<Scripts><OnLoad>
|
||
self.categoryKey = "Combat"
|
||
getglobal(self:GetName() .. "Label"):SetText("Combat")
|
||
</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSearchHeadActionBars" inherits="OptionsSearchHeadTemplate">
|
||
<Scripts><OnLoad>
|
||
self.categoryKey = "ActionBars"
|
||
getglobal(self:GetName() .. "Label"):SetText("Action Bars")
|
||
</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSearchHeadInterface" inherits="OptionsSearchHeadTemplate">
|
||
<Scripts><OnLoad>
|
||
self.categoryKey = "Interface"
|
||
getglobal(self:GetName() .. "Label"):SetText("Interface")
|
||
</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSearchHeadChat" inherits="OptionsSearchHeadTemplate">
|
||
<Scripts><OnLoad>
|
||
self.categoryKey = "Chat"
|
||
getglobal(self:GetName() .. "Label"):SetText("Chat")
|
||
</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSearchHeadNameplates" inherits="OptionsSearchHeadTemplate">
|
||
<Scripts><OnLoad>
|
||
self.categoryKey = "Nameplates"
|
||
getglobal(self:GetName() .. "Label"):SetText("Nameplates")
|
||
</OnLoad></Scripts>
|
||
</Button>
|
||
<Button name="$parentSearchHeadKeybindings" inherits="OptionsSearchHeadTemplate">
|
||
<Scripts><OnLoad>
|
||
self.categoryKey = "Keybindings"
|
||
getglobal(self:GetName() .. "Label"):SetText("Keybindings")
|
||
</OnLoad></Scripts>
|
||
</Button>
|
||
<!-- The keybinding search-result pool (decision 1008): the era
|
||
reflows LIVE binding rows into its results; ours is this static
|
||
pool of the same template, painted and chained by the search
|
||
display (capped at KEYBINDINGS_SEARCH_ROWS — the SCOPE note in
|
||
KeyBindingsPage.xml). Unanchored until a search places them;
|
||
the capsules run the full capture law in place. -->
|
||
<Frame name="$parentKeybindSearch1" inherits="KeyBindingRowTemplate" hidden="true"/>
|
||
<Frame name="$parentKeybindSearch2" inherits="KeyBindingRowTemplate" hidden="true"/>
|
||
<Frame name="$parentKeybindSearch3" inherits="KeyBindingRowTemplate" hidden="true"/>
|
||
<Frame name="$parentKeybindSearch4" inherits="KeyBindingRowTemplate" hidden="true"/>
|
||
<Frame name="$parentKeybindSearch5" inherits="KeyBindingRowTemplate" hidden="true"/>
|
||
<Frame name="$parentKeybindSearch6" inherits="KeyBindingRowTemplate" hidden="true"/>
|
||
<Frame name="$parentKeybindSearch7" inherits="KeyBindingRowTemplate" hidden="true"/>
|
||
<Frame name="$parentKeybindSearch8" inherits="KeyBindingRowTemplate" hidden="true"/>
|
||
</Frames>
|
||
</Frame>
|
||
<!-- The bar: the shared Slider (drag + arrows, decision 0250) on the
|
||
real-scroll handler, hidden until the content overflows. Seated
|
||
INSIDE the frame's right edge rather than 6 units outside it (the
|
||
UIPanelScrollFrameTemplate shape the faux kit uses): outside would
|
||
put it past the page box, and the -20 right inset the rows already
|
||
carry leaves the -26..-10 gutter free — the very gutter the
|
||
Keybindings list's bar rides.
|
||
|
||
Inset 21/20 vertically, not the ref's 16/16, because HERE the
|
||
scroll frame IS the page rect: the trough seats itself 21 above and
|
||
20 below the bar (BenillaScrollTrough_Seat), so these are the
|
||
offsets that put the whole channel — caps and all — exactly on the
|
||
page rect instead of poking 5 units up through the header divider
|
||
and 4 down past the container. The bar↔trough relationship is the
|
||
ref's either way; this only chooses which of the two is flush. -->
|
||
<Slider name="$parentBar" inherits="BenillaScrollBarTemplate" hidden="true">
|
||
<Anchors>
|
||
<Anchor point="TOPRIGHT"><Offset><AbsDimension x="-10" y="-21"/></Offset></Anchor>
|
||
<Anchor point="BOTTOMRIGHT"><Offset><AbsDimension x="-10" y="20"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Scripts><OnValueChanged>BenillaScrollBar_OnValueChanged(self, arg1)</OnValueChanged></Scripts>
|
||
</Slider>
|
||
</Frames>
|
||
</ScrollFrame>
|
||
</Frames>
|
||
</Frame>
|
||
|
||
<!-- ── The search box (era SearchBoxTemplate GEOMETRY: a 20-tall three-slice
|
||
vertically centered on the 22 box — left cap 8x20 hung 5 outside, right cap
|
||
8x20 flush, middle stretched between — a 17x17 clear button at RIGHT (-3)
|
||
that appears with text). The slices wear the classic Common-Input-Border
|
||
(0978 mapping) at the InputBoxTemplate UVs (caps u 0..1/16 and 15/16..1,
|
||
ink v 0..0.625 of the 128x32 file). The era magnifier is DROPPED (no 1.12
|
||
counterpart; the "Search" placeholder carries the affordance) — and with it
|
||
the era's 16-left TextInsets seat that cleared it: text and caret sit at 5
|
||
(0989). The clear X wears the UI-Panel-MinimizeButton ball, half-lit,
|
||
full on hover (the era ClearButtonMixin alpha law). -->
|
||
<EditBox name="$parentSearchBox" autoFocus="false" letters="64">
|
||
<Size><AbsDimension x="350" y="22"/></Size>
|
||
<!-- The era seat VERBATIM (SettingsPanel.xml l.76-81: 350x22, BOTTOMRIGHT ->
|
||
Container TOPRIGHT (4, +20)). 0981 rebased y to -4 (the box line ran
|
||
through it — the crowding report); 0984 restored y and bent x/width
|
||
(-18/300) around the corner X ball; 0989 cut that X, so the last bend
|
||
unwinds. The 1.14 title plate's tail (decoded: art ends x=539) still
|
||
clears — this seat's left edge lands at x=552, 13 free. -->
|
||
<Anchors>
|
||
<Anchor point="BOTTOMRIGHT" relativeTo="$parentContainer" relativePoint="TOPRIGHT"><Offset><AbsDimension x="4" y="20"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Layers>
|
||
<Layer level="BACKGROUND">
|
||
<Texture name="$parentBorderLeft" file="Interface\Common\Common-Input-Border">
|
||
<Size><AbsDimension x="8" y="20"/></Size>
|
||
<Anchors><Anchor point="LEFT"><Offset><AbsDimension x="-5" y="0"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="0" right="0.0625" top="0" bottom="0.625"/>
|
||
</Texture>
|
||
<Texture name="$parentBorderRight" file="Interface\Common\Common-Input-Border">
|
||
<Size><AbsDimension x="8" y="20"/></Size>
|
||
<Anchors><Anchor point="RIGHT"><Offset><AbsDimension x="0" y="0"/></Offset></Anchor></Anchors>
|
||
<TexCoords left="0.9375" right="1" top="0" bottom="0.625"/>
|
||
</Texture>
|
||
<Texture name="$parentBorderMiddle" file="Interface\Common\Common-Input-Border">
|
||
<Size><AbsDimension y="20"/></Size>
|
||
<Anchors>
|
||
<Anchor point="LEFT" relativeTo="$parentBorderLeft" relativePoint="RIGHT"/>
|
||
<Anchor point="RIGHT" relativeTo="$parentBorderRight" relativePoint="LEFT"/>
|
||
</Anchors>
|
||
<TexCoords left="0.0625" right="0.9375" top="0" bottom="0.625"/>
|
||
</Texture>
|
||
</Layer>
|
||
<Layer level="ARTWORK">
|
||
<!-- The "Search" placeholder (era instructions label: GameFontDisableSmall
|
||
tinted 0.35). OnTextChanged below toggles it on first text. -->
|
||
<FontString name="$parentInstructions" inherits="GameFontDisableSmall" justifyH="LEFT" text="Search">
|
||
<Anchors>
|
||
<Anchor point="TOPLEFT"><Offset><AbsDimension x="5" y="0"/></Offset></Anchor>
|
||
<Anchor point="BOTTOMRIGHT"><Offset><AbsDimension x="-20" y="0"/></Offset></Anchor>
|
||
</Anchors>
|
||
<Color r="0.35" g="0.35" b="0.35"/>
|
||
</FontString>
|
||
</Layer>
|
||
</Layers>
|
||
<Frames>
|
||
<!-- The clear X (era ClearButtonMixin: shown while text exists, half-alpha
|
||
icon, click wipes). Shown/hidden by the box's OnTextChanged below. -->
|
||
<Button name="$parentClearButton" hidden="true">
|
||
<Size><AbsDimension x="17" y="17"/></Size>
|
||
<Anchors><Anchor point="RIGHT"><Offset><AbsDimension x="-3" y="0"/></Offset></Anchor></Anchors>
|
||
<Layers>
|
||
<Layer level="ARTWORK">
|
||
<Texture name="$parentIcon" file="Interface\Buttons\UI-Panel-MinimizeButton-Up" alpha="0.5">
|
||
<Size><AbsDimension x="17" y="17"/></Size>
|
||
<Anchors><Anchor point="CENTER"/></Anchors>
|
||
</Texture>
|
||
</Layer>
|
||
</Layers>
|
||
<Scripts>
|
||
<OnClick>
|
||
BenillaOptionsFrameSearchBox:SetText("")
|
||
BenillaOptionsFrameSearchBox:ClearFocus()
|
||
</OnClick>
|
||
<OnEnter>getglobal(this:GetName() .. "Icon"):SetAlpha(1.0)</OnEnter>
|
||
<OnLeave>getglobal(this:GetName() .. "Icon"):SetAlpha(0.5)</OnLeave>
|
||
</Scripts>
|
||
</Button>
|
||
</Frames>
|
||
<TextInsets><AbsInset left="5" right="20" top="0" bottom="0"/></TextInsets>
|
||
<Scripts>
|
||
<!-- Placeholder + clear-button toggle, then the search proper (0984). -->
|
||
<OnTextChanged>
|
||
if this:GetText() == "" then
|
||
BenillaOptionsFrameSearchBoxInstructions:Show()
|
||
BenillaOptionsFrameSearchBoxClearButton:Hide()
|
||
else
|
||
BenillaOptionsFrameSearchBoxInstructions:Hide()
|
||
BenillaOptionsFrameSearchBoxClearButton:Show()
|
||
end
|
||
OptionsSearch_OnTextChanged(this:GetText())
|
||
</OnTextChanged>
|
||
<OnEscapePressed>this:ClearFocus()</OnEscapePressed>
|
||
</Scripts>
|
||
<FontString inherits="GameFontHighlightSmall"/>
|
||
</EditBox>
|
||
|
||
<!-- ── Close (no corner X — 0989's directed cut, header SCOPE note; the red
|
||
button and ESC are the window's exits) ─────────────────────────────────── -->
|
||
<!-- The red Close (era SettingsPanel.CloseButton). -->
|
||
<Button name="$parentCloseButton" inherits="OptionsRedButtonTemplate" text="Close">
|
||
<Anchors><Anchor point="BOTTOMRIGHT"><Offset><AbsDimension x="-16" y="16"/></Offset></Anchor></Anchors>
|
||
<Scripts>
|
||
<OnClick>
|
||
PlaySound("igMainMenuClose")
|
||
HideUIPanel(BenillaOptionsFrame)
|
||
</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
<!-- The era Apply (SettingsPanel.ApplyButton: 96x22, RIGHT of Close's LEFT at -2,
|
||
Blizzard_SettingsPanel.xml l.52-57): exists only while a deferred row holds a
|
||
pending value — era enables and SHOWS it together (SetApplyButtonEnabled) —
|
||
and commits every pending edit on click. -->
|
||
<Button name="$parentApplyButton" inherits="OptionsRedButtonTemplate" text="Apply" hidden="true">
|
||
<Anchors><Anchor point="RIGHT" relativeTo="$parentCloseButton" relativePoint="LEFT"><Offset><AbsDimension x="-2" y="0"/></Offset></Anchor></Anchors>
|
||
<Scripts>
|
||
<OnLoad>self:Disable()</OnLoad>
|
||
<OnClick>OptionsPage_Apply()</OnClick>
|
||
</Scripts>
|
||
</Button>
|
||
</Frames>
|
||
<Scripts>
|
||
<!-- Controls is the default page; a re-opened window keeps its last selection (the
|
||
era remembers too — Settings.OpenToCategory's default seat). The scale re-fits
|
||
on every show — the era panel manager re-runs checkFit the same way. -->
|
||
<OnShow>
|
||
BenillaOptionsFrame_UpdateScale()
|
||
BenillaOptionsFrame_SelectCategory(this.selectedCategory or "Controls")
|
||
if UpdateMicroButtons then UpdateMicroButtons() end
|
||
</OnShow>
|
||
<!-- Hiding discards pending edits (the era wipes its modified table on hide; its
|
||
close-time confirm dialog is cut — SCOPE note), ends a live search (the
|
||
era Flush's ClearSearchBox, SettingsPanel.lua l.187-193), and disarms a
|
||
straggling bind capture — the host seam swallowing all input with no window
|
||
on screen would be a lockout (KeyBindingsPage.xml, decision 1008). -->
|
||
<OnHide>
|
||
BenillaOptionsFrameSearchBox:SetText("")
|
||
OptionsPage_DiscardPending()
|
||
KeyBindings_SetSelected(nil)
|
||
KeyBindings_Output("")
|
||
if UpdateMicroButtons then UpdateMicroButtons() end
|
||
</OnHide>
|
||
</Scripts>
|
||
</Frame>
|
||
<!-- ══ NO ALIASES LEFT, AND THIS WINDOW IS NO LONGER `OptionsFrame` (2115, 2147, 2177) ══
|
||
The reference has THREE options windows — `OptionsFrame` (video), `SoundOptionsFrame` and
|
||
`UIOptionsFrame` (interface). **All three are now the reference's own frames, loaded
|
||
hidden off the player's chain**, and none of them may ever be aliased onto this one.
|
||
|
||
The last of the three to arrive was the VIDEO window, and it is the one that took a name
|
||
off this file: the frame above was called `OptionsFrame` for its whole life, and
|
||
`Interface\FrameXML\OptionsFrame.xml` declares that name itself. Two frames cannot hold
|
||
one global — `CreateFrame` publishes into `_G` and the later one simply wins, silently —
|
||
and neither ordering is survivable. Ours later CLOBBERS the stock frame, and pfUI's
|
||
`skins/blizzard/options-video.lua` then runs `CreateBackdrop`, `EnableMovable`,
|
||
`HookScript(…, "OnShow", …)` and `OptionsFrameHeader:SetTexture("")` against the window the
|
||
player opens. Ours earlier is no better: the skin's `OptionsFrameSlider1..9` and
|
||
`OptionsFrameCheckButton1..18` would find the stock frame's children while its
|
||
`CreateBackdrop(OptionsFrame)` found ours — half a skin, on two different windows. So the
|
||
reference's name went back to the reference's window and this one became
|
||
`BenillaOptionsFrame`, the `Benilla…` convention every other frame of our own already
|
||
wears (`BenillaScriptLogFrame`, `BenillaScrollBarTemplate`).
|
||
|
||
**What the rename cost, and where each cost is paid.** Three things keyed on the old name
|
||
had to be restated rather than lost:
|
||
· the **panel-manager row** — `UIParent.lua:16`'s `UIPanelWindows["OptionsFrame"]`, which
|
||
gave this window the centre slot and the while-dead permission. Restated below, verbatim.
|
||
· the **ESC ladder and the micro button** — `ToggleGameMenu`, `IsOptionFrameOpen` and
|
||
`UpdateMicroButtons` all name the reference's three windows literally, so the whole chain
|
||
now reads "no" while ours is up. Three wrappers in `GameMenuFrame.xml` add the one term
|
||
the reference could not know about; that file is the manifest's last row, which is where
|
||
`UpdateMicroButtons` finally exists to wrap.
|
||
· the **`OptionsFrameCancel` alias** — RETIRED, and by the sharper of the two arguments.
|
||
It pointed the reference's name at our Close button so `ToggleGameMenu`'s
|
||
`OptionsFrameCancel:Click()` would discard-and-hide this window. That button is now a
|
||
real frame in the stock video window, and this file loads after it, so the alias would
|
||
not sit beside it — it would **clobber** it, and pfUI's video skin's
|
||
`SkinButton(OptionsFrameCancel)` would land on ours. The ESC rung it existed for is the
|
||
`ToggleGameMenu` wrapper's now, calling our own Close button by our own name.
|
||
|
||
Nothing of ours may `Show()` any of the three stock frames; each is `hidden="true"` in its
|
||
own file and that is what keeps them off the screen.
|
||
|
||
**One behaviour changed when the `UIOptionsFrame` alias went, and it is the right one.**
|
||
`FloatingChatFrame.lua` l.842/860 gate the chat tab and dock hover on
|
||
`not UIOptionsFrame:IsShown()`. That reads the hidden stock frame, so chat-tab hover
|
||
works while OUR options window is open. The reference's gate exists because ITS interface
|
||
window is `frameStrata="FULLSCREEN"` with `setAllPoints` and covers the chat; ours is a
|
||
panel that does not. No adapter is added for it (2115).
|
||
BENILLA_ALLOW_OWN_UI=1 -->
|
||
<Script><![CDATA[
|
||
-- ══ THIS WINDOW'S PANEL-MANAGER ROW ══════════════════════════════════════════════════
|
||
-- `UIPanelWindows` is the table `ShowUIPanel` reads to place a window: `area` picks the
|
||
-- slot ("center" is the native-centre one, which no side panel may push aside),
|
||
-- `pushable` its rank within that slot, `whileDead` whether it may open with the player
|
||
-- dead. A frame with NO row gets none of it — `ShowUIPanel` falls through to a bare
|
||
-- `Show()`, unplaced, and death closes it.
|
||
--
|
||
-- Until now this frame rode the REFERENCE's row. `UIParent.lua:16` keys one on the name
|
||
-- `OptionsFrame`, and that was this frame's name, so the game menu's Options button got
|
||
-- the centre slot and the while-dead permission for free. That name is now the stock
|
||
-- VIDEO options window's, so the row keyed on it is ITS row — and this window needs its
|
||
-- own. The three values below are the reference's own, copied verbatim from that line:
|
||
-- the placement our window has always had, now stated under the name it now answers to.
|
||
--
|
||
-- SAFE TO RUN HERE: `UIParent.xml` — which carries `UIParent.lua`, where `UIPanelWindows`
|
||
-- is created — is the manifest's 7th row (`benilla.toc` l.144) and this file is its 38th
|
||
-- (l.522), so the table is real by the time this executes.
|
||
UIPanelWindows["BenillaOptionsFrame"] = { area = "center", pushable = 0, whileDead = 1 }
|
||
]]></Script>
|
||
</Ui>
|