diff --git a/crates/benilla-app/assets/ui/GameMenuFrame.xml b/crates/benilla-app/assets/ui/GameMenuFrame.xml index 41c37c41..deec951e 100644 --- a/crates/benilla-app/assets/ui/GameMenuFrame.xml +++ b/crates/benilla-app/assets/ui/GameMenuFrame.xml @@ -118,6 +118,98 @@ button:Disable() end + -- ══ THE THREE STOCK CONSUMERS THAT ASK "IS AN OPTIONS WINDOW OPEN?" (decision 2177) ══ + -- All three are the reference's own, off the chain, and all three name the reference's + -- three windows literally. Two of those names are now REAL hidden stock frames + -- (`SoundOptionsFrame` since 2147, `UIOptionsFrame` since 2115) and the third, + -- `OptionsFrame`, became one when the stock VIDEO window joined the manifest — so the + -- whole chain now reads "no", always, while the window the player actually opens is up. + -- Until then `OptionsFrame` WAS our window and every one of them answered by accident. + -- + -- **Wrappers, not replacements.** Each stock function keeps running and keeps deciding; + -- ours adds the one term the reference could not know about. A rewrite would be thirty + -- lines of the reference's ladder copied into our tree to drift. + -- + -- **HERE, not in `OptionsFrame.xml`, because of load order.** `UpdateMicroButtons` is + -- defined by `MainMenuBarMicroButtons.xml`, manifest l.576 — AFTER our options window at + -- l.522, where a wrapper would capture a nil. This file is the manifest's LAST row + -- (l.1273), so all three exist. It is also the right home on the merits: this is the ESC + -- menu, and these three are exactly "the ESC ladder and the micro button know about our + -- options window". + local Ref_IsOptionFrameOpen = IsOptionFrameOpen + local Ref_ToggleGameMenu = ToggleGameMenu + local Ref_UpdateMicroButtons = UpdateMicroButtons + + -- The one term all three add. Existence-guarded because these three wrappers stand in a + -- file that can be seated without the options window: in the client `BenillaOptionsFrame` + -- is manifest row 38 and this file is the last row, so it is always real — but a test kit + -- that seats the game menu alone must get "no options window is open", not a raise inside + -- the ESC handler. + local function BenillaOptions_IsOpen() + return BenillaOptionsFrame and BenillaOptionsFrame:IsVisible() + end + + -- `UIParent.lua:996`. One caller: `CloseAllWindows_WithExceptions`, which passes + -- `ignoreCenter = 1` when an options window is up so the ESC sweep does not close the + -- centre panel out from under it. Ours IS the centre panel (`UIPanelWindows` row, + -- `area = "center"`), so answering "no" would have ESC close it through the sweep instead + -- of through its own rung, discarding pending edits with no Cancel semantics. + function IsOptionFrameOpen() + if BenillaOptions_IsOpen() then + return 1 + end + return Ref_IsOptionFrameOpen() + end + + -- `UIParent.lua:1465-1497`. The ESC ladder, and the rung matters as much as the answer: + -- the reference tries the static popup FIRST, then an open options window, then the game + -- menu. So this runs that first rung itself and returns if it fired — `StaticPopup_Escape -- Pressed` is a pure scan when nothing is shown (`StaticPopup.lua:1879-1893`), so the + -- delegate below re-running it costs nothing and changes nothing — then takes the options + -- rung, then hands the rest of the ladder back untouched. + -- + -- The close is our own Close button's click, which is the same discard-and-hide the + -- reference reaches through `OptionsFrameCancel:Click()`: our `` drops the pending + -- page. (That alias is retired — `OptionsFrameCancel` is the stock video window's own + -- button now, and ours loading later would have clobbered it.) + function ToggleGameMenu(clicked) + if clicked then + -- The reference's `clicked` arm closes an open options window and then goes on to + -- toggle the game menu, rather than returning. Same here. + if BenillaOptions_IsOpen() then + BenillaOptionsFrameCloseButton:Click() + end + return Ref_ToggleGameMenu(clicked) + end + if StaticPopup_EscapePressed() then + return + end + if BenillaOptions_IsOpen() then + BenillaOptionsFrameCloseButton:Click() + return + end + return Ref_ToggleGameMenu(clicked) + end + + -- `MainMenuBarMicroButtons.lua:47-58`. A POST-hook that can only ever push the button, never + -- release it: the reference has already decided from the six frames it knows, and this adds + -- the seventh. Written this way round so it cannot fight that decision — a wrapper that also + -- set NORMAL would be a second copy of the reference's whole `or` chain. + -- + -- **Existence-guarded, and only here.** The shipped manifest always carries + -- `MainMenuBarMicroButtons.xml`, so in the client `Ref_UpdateMicroButtons` and + -- `MainMenuMicroButton` are always real. A partial test kit that seats this file and not + -- the micro bar is the case the guards are for, and a guard is the honest answer there: + -- there is no micro button to push, so there is nothing to do — as against a raise inside + -- an unrelated window's OnShow, which is what an unguarded wrapper turns that into. + function UpdateMicroButtons() + if Ref_UpdateMicroButtons then + Ref_UpdateMicroButtons() + end + if MainMenuMicroButton and BenillaOptions_IsOpen() then + MainMenuMicroButton:SetButtonState("PUSHED", 1) + end + end + -- The CAMP/QUIT dialogs and the three-event driver MOVED OUT, to our UIParent.lua counterpart (the stock UIParent.lua since 1988) — the -- reference's own homes for both (StaticPopup.lua l.564/586; UIParent.lua l.304-315). -- They were here only because this is where they were first needed, and 1751 moving them @@ -179,7 +271,7 @@ something exists behind them. --> @@ -191,7 +283,7 @@ PlaySound("igMainMenuOption") HideUIPanel(GameMenuFrame) - ShowUIPanel(OptionsFrame) + ShowUIPanel(BenillaOptionsFrame) diff --git a/crates/benilla-app/assets/ui/KeyBindingsPage.xml b/crates/benilla-app/assets/ui/KeyBindingsPage.xml index e2f08cde..f25a4bde 100644 --- a/crates/benilla-app/assets/ui/KeyBindingsPage.xml +++ b/crates/benilla-app/assets/ui/KeyBindingsPage.xml @@ -184,7 +184,7 @@ -- and repainted after a bind lands on one. KeyBindingsPage = { sections = {}, items = {} } - KEYBINDINGS_ROW_BASE = "OptionsFrameContainerBodyKeybindingsRow" + KEYBINDINGS_ROW_BASE = "BenillaOptionsFrameContainerBodyKeybindingsRow" KEYBINDINGS_DISPLAYED = 19 KEYBINDINGS_ROW_HEIGHT = 25 KEYBINDINGS_SEARCH_ROWS = 8 @@ -302,7 +302,7 @@ -- ── The list repaint (1.12 KeyBindingFrame_Update over the era section list). ── function KeyBindingsPage_Update() local page = KeyBindingsPage - local scroll = getglobal("OptionsFrameContainerBodyKeybindingsScrollFrame") + local scroll = getglobal("BenillaOptionsFrameContainerBodyKeybindingsScrollFrame") local offset = FauxScrollFrame_GetOffset(scroll) for i = 1, KEYBINDINGS_DISPLAYED do local name = KEYBINDINGS_ROW_BASE .. i @@ -327,23 +327,23 @@ KeyBindings_UpdateUnbindKey() end - -- The page entry (OptionsFrame_SelectCategory's Keybindings arm): rebuild the tree — + -- The page entry (BenillaOptionsFrame_SelectCategory's Keybindings arm): rebuild the tree — -- the table may have moved under us (a rebind, a set switch) — sync the checkbox to -- the live set, park the scroll at the top, repaint. function KeyBindingsPage_Refresh() KeyBindings_BuildSections() - local box = getglobal("OptionsFrameContainerBodyKeybindingsCharacterRowCheck") + local box = getglobal("BenillaOptionsFrameContainerBodyKeybindingsCharacterRowCheck") if GetCurrentBindingSet() == 2 then box:SetChecked(1) else box:SetChecked(nil) end - getglobal("OptionsFrameContainerBodyKeybindingsScrollFrameScrollBar"):SetValue(0) + getglobal("BenillaOptionsFrameContainerBodyKeybindingsScrollFrameScrollBar"):SetValue(0) KeyBindingsPage_Update() end function KeyBindings_Output(text) - getglobal("OptionsFrameContainerBodyKeybindingsOutput"):SetText(text) + getglobal("BenillaOptionsFrameContainerBodyKeybindingsOutput"):SetText(text) end -- ── Selection + the capture arm ── selecting a capsule arms the HOST's capture seam @@ -356,7 +356,7 @@ end function KeyBindings_UpdateUnbindKey() - local unbind = getglobal("OptionsFrameContainerUnbind") + local unbind = getglobal("BenillaOptionsFrameContainerUnbind") if KeyBindingsPage.selected then unbind:Enable() else diff --git a/crates/benilla-app/assets/ui/OptionsFrame.xml b/crates/benilla-app/assets/ui/OptionsFrame.xml index 4879e46a..6311160e 100644 --- a/crates/benilla-app/assets/ui/OptionsFrame.xml +++ b/crates/benilla-app/assets/ui/OptionsFrame.xml @@ -277,7 +277,7 @@ -- 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 OptionsFrame_SetTutorialsEnabled(value) + function BenillaOptionsFrame_SetTutorialsEnabled(value) if ( tonumber(value) ~= TutorialsEnabled() ) then if ( value == "1" ) then ResetTutorials() @@ -343,7 +343,7 @@ -- reference at typical resolutions reads nearer two-thirds. ERA_WINDOW_SCALE = 0.78 - function OptionsFrame_UpdateScale() + 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. @@ -352,7 +352,7 @@ local hFit = GetScreenHeight() / 744 if wFit < k then k = wFit end if hFit < k then k = hFit end - OptionsFrame:SetScale(k) + BenillaOptionsFrame:SetScale(k) end -- The era tab width law (MinimalTab.lua l.7): label width + 40, measured ONCE per show — @@ -361,7 +361,7 @@ -- 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 OptionsFrame_UpdateScale in its own , + -- scales) — and this window's scale is set by BenillaOptionsFrame_UpdateScale in its own , -- after every OnLoad has already run. Fired from the tabs' , 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 @@ -401,20 +401,20 @@ -- 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 OptionsFrame_SelectCategory(key) - OptionsFrame.selectedCategory = key - if OptionsFrameSearchBox:GetText() ~= "" then - OptionsFrameSearchBox:SetText("") + 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("OptionsFrameCategoryListRow" .. k) - local bg = getglobal("OptionsFrameCategoryListRow" .. k .. "Bg") + 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") - OptionsFrameContainerTitle:SetText(row.pageTitle) + BenillaOptionsFrameContainerTitle:SetText(row.pageTitle) else bg:SetVertexColor(0.196, 0.388, 0.8) bg:Hide() @@ -422,7 +422,7 @@ end end for k in pairs(OPTIONS_PAGE_ROWS) do - local body = getglobal("OptionsFrameContainerBody" .. k) + local body = getglobal("BenillaOptionsFrameContainerBody" .. k) if k == key then body:Show() else body:Hide() end end -- The Keybindings page (KeyBindingsPage.xml, decision 1008) body-swaps like the @@ -430,22 +430,22 @@ -- 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("OptionsFrameContainerBodyKeybindings") + local kb = getglobal("BenillaOptionsFrameContainerBodyKeybindings") if key == "Keybindings" then kb:Show() KeyBindingsPage_Refresh() - OptionsFrameContainerUnbind:Show() - OptionsFrameContainerDefaults:Enable() + BenillaOptionsFrameContainerUnbind:Show() + BenillaOptionsFrameContainerDefaults:Enable() else kb:Hide() KeyBindings_SetSelected(nil) KeyBindings_Output("") - OptionsFrameContainerUnbind:Hide() + BenillaOptionsFrameContainerUnbind:Hide() if OPTIONS_PAGE_ROWS[key] then OptionsPage_Refresh(key) - OptionsFrameContainerDefaults:Enable() + BenillaOptionsFrameContainerDefaults:Enable() else - OptionsFrameContainerDefaults:Disable() + BenillaOptionsFrameContainerDefaults:Disable() end end end @@ -495,7 +495,7 @@ 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("OptionsFrameContainerBody" .. key .. rkey) + local row = getglobal("BenillaOptionsFrameContainerBody" .. key .. rkey) local s = OptionsSearch_Score(row.searchTag, words) if s then if not buckets[s] then @@ -557,15 +557,15 @@ end for _, key in ipairs(OPTIONS_CATEGORY_KEYS) do if OPTIONS_PAGE_ROWS[key] then - take("OptionsFrameContainerBodySearchHead" .. key) + take("BenillaOptionsFrameContainerBodySearchHead" .. key) for _, rkey in ipairs(OPTIONS_PAGE_ROWS[key]) do - take("OptionsFrameContainerBody" .. key .. rkey) + take("BenillaOptionsFrameContainerBody" .. key .. rkey) end end end - take("OptionsFrameContainerBodySearchHeadKeybindings") + take("BenillaOptionsFrameContainerBodySearchHeadKeybindings") for i = 1, KEYBINDINGS_SEARCH_ROWS do - take("OptionsFrameContainerBodyKeybindSearch" .. i) + take("BenillaOptionsFrameContainerBodyKeybindSearch" .. i) end return bottom end @@ -577,8 +577,8 @@ -- 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 = OptionsFrameContainerScroll - local body = OptionsFrameContainerBody + 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 @@ -606,8 +606,8 @@ f:SetPoint("TOPLEFT", prev, "BOTTOMLEFT", 0, -9) f:SetPoint("TOPRIGHT", prev, "BOTTOMRIGHT", 0, -9) else - f:SetPoint("TOPLEFT", "OptionsFrameContainerBody", "TOPLEFT", 10, -12) - f:SetPoint("TOPRIGHT", "OptionsFrameContainerBody", "TOPRIGHT", -20, -12) + f:SetPoint("TOPLEFT", "BenillaOptionsFrameContainerBody", "TOPLEFT", 10, -12) + f:SetPoint("TOPRIGHT", "BenillaOptionsFrameContainerBody", "TOPRIGHT", -20, -12) end end @@ -616,7 +616,7 @@ function OptionsPage_Layout(key) local prev = nil for _, rkey in ipairs(OPTIONS_PAGE_ROWS[key]) do - local name = "OptionsFrameContainerBody" .. key .. rkey + local name = "BenillaOptionsFrameContainerBody" .. key .. rkey OptionsSearch_Place(name, prev) getglobal(name):Show() prev = name @@ -632,37 +632,37 @@ -- (l.680-682). function OptionsSearch_Display(text) -- A new result set starts at the top (the era's own ScrollBox reset on a search). - OptionsFrameContainerScroll:SetVerticalScroll(0) + BenillaOptionsFrameContainerScroll:SetVerticalScroll(0) for k in pairs(OPTIONS_PAGE_ROWS) do - getglobal("OptionsFrameContainerBody" .. k):Show() + getglobal("BenillaOptionsFrameContainerBody" .. k):Show() for _, rkey in ipairs(OPTIONS_PAGE_ROWS[k]) do - getglobal("OptionsFrameContainerBody" .. k .. rkey):Hide() + getglobal("BenillaOptionsFrameContainerBody" .. k .. rkey):Hide() end - getglobal("OptionsFrameContainerBodySearchHead" .. k):Hide() + 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("OptionsFrameContainerBodyKeybindings"):Hide() - getglobal("OptionsFrameContainerBodySearchHeadKeybindings"):Hide() + getglobal("BenillaOptionsFrameContainerBodyKeybindings"):Hide() + getglobal("BenillaOptionsFrameContainerBodySearchHeadKeybindings"):Hide() for i = 1, KEYBINDINGS_SEARCH_ROWS do - getglobal("OptionsFrameContainerBodyKeybindSearch" .. i):Hide() + getglobal("BenillaOptionsFrameContainerBodyKeybindSearch" .. i):Hide() end KeyBindingsPage.searchPainted = nil KeyBindings_SetSelected(nil) - OptionsFrameContainerUnbind:Hide() - OptionsFrameContainerTitle:SetText("Search Results") - OptionsFrameContainerDefaults:Hide() + BenillaOptionsFrameContainerUnbind:Hide() + BenillaOptionsFrameContainerTitle:SetText("Search Results") + BenillaOptionsFrameContainerDefaults:Hide() local order, groups = OptionsSearch_FindMatches(text) if table.getn(order) == 0 then - OptionsFrameContainerBodyNoResults:Show() + BenillaOptionsFrameContainerBodyNoResults:Show() return end - OptionsFrameContainerBodyNoResults:Hide() + BenillaOptionsFrameContainerBodyNoResults:Hide() local prev = nil for _, key in ipairs(order) do - local head = "OptionsFrameContainerBodySearchHead" .. key + local head = "BenillaOptionsFrameContainerBodySearchHead" .. key OptionsSearch_Place(head, prev) getglobal(head):Show() prev = head @@ -675,7 +675,7 @@ for _, index in ipairs(groups[key]) do if shown < KEYBINDINGS_SEARCH_ROWS then shown = shown + 1 - local name = "OptionsFrameContainerBodyKeybindSearch" .. shown + local name = "BenillaOptionsFrameContainerBodyKeybindSearch" .. shown KeyBindings_PaintBindRow(name, index) OptionsSearch_Place(name, prev) getglobal(name):Show() @@ -686,17 +686,17 @@ else local placed = {} for _, rkey in ipairs(groups[key]) do - local row = getglobal("OptionsFrameContainerBody" .. key .. rkey) + local row = getglobal("BenillaOptionsFrameContainerBody" .. key .. rkey) if row.parentRow and not placed[row.parentRow] then placed[row.parentRow] = 1 - local pname = "OptionsFrameContainerBody" .. key .. row.parentRow + 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 = "OptionsFrameContainerBody" .. key .. rkey + local name = "BenillaOptionsFrameContainerBody" .. key .. rkey OptionsSearch_Place(name, prev) row:Show() prev = name @@ -711,28 +711,28 @@ -- 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() - OptionsFrameContainerScroll:SetVerticalScroll(0) + BenillaOptionsFrameContainerScroll:SetVerticalScroll(0) for k in pairs(OPTIONS_PAGE_ROWS) do OptionsPage_Layout(k) - getglobal("OptionsFrameContainerBodySearchHead" .. k):Hide() + getglobal("BenillaOptionsFrameContainerBodySearchHead" .. k):Hide() end for i = 1, KEYBINDINGS_SEARCH_ROWS do - getglobal("OptionsFrameContainerBodyKeybindSearch" .. i):Hide() + getglobal("BenillaOptionsFrameContainerBodyKeybindSearch" .. i):Hide() end - getglobal("OptionsFrameContainerBodySearchHeadKeybindings"):Hide() + getglobal("BenillaOptionsFrameContainerBodySearchHeadKeybindings"):Hide() KeyBindingsPage.searchPainted = nil - OptionsFrameContainerBodyNoResults:Hide() - OptionsFrameContainerDefaults:Show() - OptionsFrame_SelectCategory(OptionsFrame.selectedCategory or "Controls") + 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 == OptionsFrame.searchText then return end - local had = OptionsFrame.searchText and OptionsFrame.searchText ~= "" - OptionsFrame.searchText = 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 @@ -1045,38 +1045,44 @@ -- 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 — ref OptionsFrame.lua l.24-34 ────────────────────────────── - -- The reference's options-slider table: one row per graphics slider, carrying the bounds - -- the slider is built with. It is PUBLISHED, so addons read and write it — pfUI's - -- `hdgraphic` module opens with `_G.OptionsFrameSliders[3].maxValue = 15` - -- (modules/hdgraphic.lua l.3) and died on the nil, taking the module with it. + -- ── 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). -- - -- **It is the real thing, not a shape put here to satisfy that write.** The three rows - -- below are the source of truth for our own Graphics page: each row's OnLoad reads its - -- bounds from here rather than carrying literals, and the page re-applies them on every - -- OnShow, which is what makes an addon's write actually move the slider. A table nothing - -- read would be a name with no behaviour behind it (1134 §4) — worse than absent, because - -- the write would appear to succeed. + -- **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. -- - -- **Three rows, not the reference's nine.** Ours are its rows 1-3 in its own order, and the - -- `func` strings match our CVars exactly (uiscale/farclip/WorldDetail) — which is why - -- pfUI's index 3 lands on Environment Detail here as it does there. The other six - -- (TerrainMip, BaseMip, Gamma, anisotropic, spellEffectLevel, weatherDensity) have no - -- benilla knob behind them; listing them would publish six rows whose writes do nothing. - -- 0959/1649 own which knobs this page ships, and this table follows that, not the reverse. + -- **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. -- - -- `benillaRow` is ours: the reference addresses its sliders as OptionsFrameSlider1..9, a - -- numbering our page does not use, so each row names the child it drives instead. + -- 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-9: TerrainMip, BaseMip, Gamma, anisotropic, + -- spellEffectLevel, weatherDensity), and the OnShow re-apply loop skips it. + BENILLA_GRAPHICS_SLIDER_ROWS = { "RowUiScale", "RowFarclip", "RowWorldDetail" } -- - -- **Both WorldDetail verbs are bound now** (2163), which is what makes pfUI's module RUN + -- **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 WILL, once 1751 migrates this - -- window: `OptionsFrame_Save`/`_Load` prefer `getglobal("Set"..func)` / `("Get"..func)` - -- over `SetCVar`/`GetCVar` (`OptionsFrame.lua` l.110/135/206-226). + -- 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 @@ -1094,14 +1100,6 @@ -- `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. - OptionsFrameSliders = { - { text = "UI Scale", func = "uiscale", - minValue = 0.64, maxValue = 1.0, valueStep = 0.01, benillaRow = "RowUiScale" }, - { text = "Terrain Distance", func = "farclip", - minValue = 177, maxValue = 777, valueStep = 60, benillaRow = "RowFarclip" }, - { text = "Environment Detail", func = "WorldDetail", - minValue = 0, maxValue = 2, valueStep = 1, benillaRow = "RowWorldDetail" }, - } function OptionsSliderRow_Setup(row, min, max, step, fmt, stops) local slider = getglobal(row:GetName() .. "ControlSlider") @@ -1299,7 +1297,7 @@ else OptionsRow_Set(row, "0") end - OptionsPage_UpdateDependencies(OptionsFrame.selectedCategory) + OptionsPage_UpdateDependencies(BenillaOptionsFrame.selectedCategory) end function OptionsSlider_OnValueChanged(slider, value) @@ -1349,7 +1347,7 @@ end function OptionsPage_Refresh(key) - local base = "OptionsFrameContainerBody" .. 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") @@ -1405,7 +1403,7 @@ local live = on if rkey == "RowComboPoints" and not combo then live = nil end OptionsRow_SetEnabled( - getglobal("OptionsFrameContainerBodyCombat" .. rkey), live) + getglobal("BenillaOptionsFrameContainerBodyCombat" .. rkey), live) end end return @@ -1414,7 +1412,7 @@ -- 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(OptionsFrameContainerBodyInterfaceRowTargetOfTargetMode, + OptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyInterfaceRowTargetOfTargetMode, SHOW_TARGET_OF_TARGET ~= "0") return end @@ -1424,7 +1422,7 @@ -- 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(OptionsFrameContainerBodyActionBarsRowMultiBar4, + OptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyActionBarsRowMultiBar4, SHOW_MULTI_ACTIONBAR_3) return end @@ -1435,8 +1433,8 @@ -- reference's own file has. local on = GetCVar("MasterSoundEffects") ~= "0" for _, row in {"RowEnableAmbience", "RowEnableErrorSpeech"} do - local box = getglobal("OptionsFrameContainerBodyAudio"..row.."Check") - local label = getglobal("OptionsFrameContainerBodyAudio"..row.."Label") + local box = getglobal("BenillaOptionsFrameContainerBodyAudio"..row.."Check") + local label = getglobal("BenillaOptionsFrameContainerBodyAudio"..row.."Label") if on then box:Enable() label:SetFontObject("GameFontNormal") @@ -1483,7 +1481,7 @@ -- 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 = "OptionsFrameContainerBody" .. key + local base = "BenillaOptionsFrameContainerBody" .. key for _, rkey in ipairs(OPTIONS_PAGE_ROWS[key]) do local row = getglobal(base .. rkey) row.pending = nil @@ -1503,17 +1501,17 @@ function OptionsApply_Update() local pending for key, rows in pairs(OPTIONS_PAGE_ROWS) do - local base = "OptionsFrameContainerBody" .. key + local base = "BenillaOptionsFrameContainerBody" .. key for _, rkey in ipairs(rows) do if getglobal(base .. rkey).pending then pending = 1 end end end if pending then - OptionsFrameApplyButton:Enable() - OptionsFrameApplyButton:Show() + BenillaOptionsFrameApplyButton:Enable() + BenillaOptionsFrameApplyButton:Show() else - OptionsFrameApplyButton:Disable() - OptionsFrameApplyButton:Hide() + BenillaOptionsFrameApplyButton:Disable() + BenillaOptionsFrameApplyButton:Hide() end end @@ -1521,7 +1519,7 @@ -- 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 = "OptionsFrameContainerBody" .. key + local base = "BenillaOptionsFrameContainerBody" .. key for _, rkey in ipairs(rows) do local row = getglobal(base .. rkey) if row.pending then @@ -1537,7 +1535,7 @@ -- 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 = "OptionsFrameContainerBody" .. key + local base = "BenillaOptionsFrameContainerBody" .. key for _, rkey in ipairs(rows) do getglobal(base .. rkey).pending = nil end @@ -1601,16 +1599,16 @@ - OptionsFrame_SelectCategory(this.categoryKey) + BenillaOptionsFrame_SelectCategory(this.categoryKey) - if OptionsFrame.selectedCategory ~= this.categoryKey then + if BenillaOptionsFrame.selectedCategory ~= this.categoryKey then getglobal(this:GetName() .. "Bg"):Show() end - if OptionsFrame.selectedCategory ~= this.categoryKey then + if BenillaOptionsFrame.selectedCategory ~= this.categoryKey then getglobal(this:GetName() .. "Bg"):Hide() end @@ -1658,7 +1656,7 @@ - OptionsFrame_SelectCategory(this.categoryKey) + BenillaOptionsFrame_SelectCategory(this.categoryKey) getglobal(this:GetName() .. "Hover"):Show() getglobal(this:GetName() .. "Hover"):Hide() @@ -1886,7 +1884,7 @@ - + + @@ -2175,17 +2173,17 @@ @@ -4028,8 +4026,9 @@ 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. --> - OptionsFrame_UpdateScale() - OptionsFrame_SelectCategory(this.selectedCategory or "Controls") + BenillaOptionsFrame_UpdateScale() + BenillaOptionsFrame_SelectCategory(this.selectedCategory or "Controls") + if UpdateMicroButtons then UpdateMicroButtons() end - OptionsFrameSearchBox:SetText("") + BenillaOptionsFrameSearchBox:SetText("") OptionsPage_DiscardPending() KeyBindings_SetSelected(nil) KeyBindings_Output("") + if UpdateMicroButtons then UpdateMicroButtons() end - diff --git a/crates/benilla-app/assets/ui/benilla.toc b/crates/benilla-app/assets/ui/benilla.toc index 9c0acb4b..5ee18e5d 100644 --- a/crates/benilla-app/assets/ui/benilla.toc +++ b/crates/benilla-app/assets/ui/benilla.toc @@ -139,8 +139,10 @@ Interface\FrameXML\WorldFrame.xml # the reference keeps it. # What stayed ours moved out: the placeholder icon (ScrollTemplates.xml; the window tab template # and its settle went with it and are the chain's since 1993), 0561's bag verbs (ContainerFrameAdapters.xml), the script log's row -# (ScriptLogFrame.xml), and three aliases in OptionsFrame.xml that answer the reference's three -# options windows and its Cancel button. +# (ScriptLogFrame.xml). The three aliases OptionsFrame.xml used to carry for the reference's three +# options windows and its Cancel button are all gone: each of those four names is a REAL frame off +# the chain now (2115, 2147, 2177), and the last of them — the video window's `OptionsFrame` — is +# why our own window is `BenillaOptionsFrame`. Interface\FrameXML\UIParent.xml # ══ THE ITEM-SLOT BASE — the reference's own, off the player's chain (1751, window 24) ══ # `ItemButtonTemplate` and the eight `SetItemButton*` verbs out of `ItemButtonTemplate.lua`. It @@ -375,55 +377,62 @@ ScrollTemplates.xml Interface\FrameXML\UIPanelTemplates.lua Interface\FrameXML\UIPanelTemplates.xml -# ══ THE OPTIONS WIDGET KIT — the reference's own, off the player's chain (1751, window 29) ══ -# The four templates addons name for an options panel: `OptionFrameBoxTemplate`, -# `OptionsButtonTemplate`, `OptionsCheckButtonTemplate`, `OptionsSliderTemplate`. Self-contained — -# no `.lua`, no `` — and a descendant of UIPanelTemplates (`OptionsCheckButtonTemplate` -# inherits `UICheckButtonTemplate`, `OptionsButtonTemplate` inherits `UIPanelButtonTemplate`), so -# it stays seated after that file, which is the line above. +# ══ THE STOCK VIDEO OPTIONS WINDOW — loaded, and HIDDEN, in the reference's own l.19 seat ══ +# `FrameXML.toc` l.19, whole: the file, its `