From e0895013ed86f3f0ce9745c088bf266e64474e2b Mon Sep 17 00:00:00 2001 From: Sam Sung <51686767+samwhosung@users.noreply.github.com> Date: Sat, 17 Oct 2026 05:40:07 +0700 Subject: [PATCH] The Benilla scroll bar template scrolls its parent itself (#1730) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `BenillaScrollBarTemplate`'s own OnValueChanged was a faux-list handler that both instances replaced with the real scroll, so a new bar that forgot the override wrote `offset`/`updateFunc` on its parent instead of scrolling. The reference's `UIPanelScrollBarTemplate` carries `this:GetParent():SetVerticalScroll(arg1)` itself (`UIPanelTemplates.xml:156-158`). The template now calls `BenillaScrollBar_OnValueChanged(this, arg1)`; the two instance overrides, the dead faux handler and its header text are gone. Test: a bare bar from the template scrolls its ScrollFrame parent with no `offset` or `updateFunc` write; it fails with the old template. Fixes #359 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 5.5 (cherry picked from commit 142ed718d3a360a5992c78b53540a356cacf6d1e) # Conflicts: # crates/benilla-app/assets/ui/OptionsFrame.xml # crates/benilla-app/assets/ui/ScriptLogFrame.xml # crates/benilla-app/assets/ui/ScrollTemplates.xml # docs/DEVIATIONS.md Absorbed into the octo fork. Upstream's side taken on all three XML files, and it fixes a live fault in this fork as well: our BenillaScrollBarTemplate called BenillaFauxScrollBar_OnValueChanged, a global defined nowhere in the repo, so every bar built from the template raised on value change — survived only because OptionsFrame and ScriptLogFrame each overrode the handler per instance. The template now carries the real handler and the two overrides are gone. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn --- crates/benilla-app/assets/ui/OptionsFrame.xml | 2740 ++++------------- .../benilla-app/assets/ui/ScriptLogFrame.xml | 252 +- .../benilla-app/assets/ui/ScrollTemplates.xml | 34 +- .../tests/create_frame_template.rs | 54 + 4 files changed, 866 insertions(+), 2214 deletions(-) diff --git a/crates/benilla-app/assets/ui/OptionsFrame.xml b/crates/benilla-app/assets/ui/OptionsFrame.xml index 856ae0b7..773d03b6 100644 --- a/crates/benilla-app/assets/ui/OptionsFrame.xml +++ b/crates/benilla-app/assets/ui/OptionsFrame.xml @@ -8,7 +8,7 @@ --> - + @@ -16,7 +16,7 @@ - + @@ -34,7 +34,7 @@ RegisterForSave("AUTO_QUEST_WATCH") -- UIOptionsFrame.lua:370-376: Blizzard_CombatText is LoadOnDemand, so the master loads it. - function CombatText_UpdateOrLoad() + function BenillaCombatText_UpdateOrLoad() if ( SHOW_COMBAT_TEXT == "1" ) then UIParentLoadAddOn("Blizzard_CombatText") end @@ -43,7 +43,7 @@ end end -- The Remove Chat Hover Delay row's applyFunc (UIOptionsFrame.lua:216). - function ChatFrame_ApplyMouseOverDelay() + function BenillaChatFrame_ApplyMouseOverDelay() if SetChatMouseOverDelay then -- nil in a VM loaded without the chat files SetChatMouseOverDelay(REMOVE_CHAT_DELAY) end @@ -63,39 +63,46 @@ end end - -- UIOptionsFrame.lua:768-780. Deviation: stock l.776 is dropped. On 1.12 its show-then-hide - -- clears volatile bits (`[0xc4da34]`); here the verbs write the CVar pair that is the - -- store, so it would erase the saved setting at every world entry. - function UpdateNameplates() - if ( NAMEPLATES_ON ) then + -- The two plate rows' store: FrameXML's own NAMEPLATES_ON/FRIENDNAMEPLATES_ON, the number 1 + -- or nil (a "0" would be truthy), applied through the verbs as the bindings do. + function BenillaOptionsFrame_GetEnemyPlates() + return NAMEPLATES_ON + end + function BenillaOptionsFrame_SetEnemyPlates(value) + if ( value == "1" ) then + NAMEPLATES_ON = 1 ShowNameplates() else + NAMEPLATES_ON = nil HideNameplates() end - if ( FRIENDNAMEPLATES_ON ) then + end + function BenillaOptionsFrame_GetFriendlyPlates() + return FRIENDNAMEPLATES_ON + end + function BenillaOptionsFrame_SetFriendlyPlates(value) + if ( value == "1" ) then + FRIENDNAMEPLATES_ON = 1 ShowFriendNameplates() else + FRIENDNAMEPLATES_ON = nil HideFriendNameplates() end end - -- The category tree in list order; keys are the row name suffixes. - -- MONKEY (advanced graphics): "AdvancedGraphics" joins the System group under Graphics — - -- the seat the era's own tree gives a page that refines the one above it, and the seat - -- that keeps the three shadow rows it inherits one row away from where they used to be. - OPTIONS_CATEGORY_KEYS = { + BENILLA_OPTIONS_CATEGORY_KEYS = { "Controls", "Interface", "ActionBars", "Combat", "Chat", "Keybindings", "Nameplates", - "Graphics", "AdvancedGraphics", "Audio", "AddOns", + "Graphics", "Audio", } -- The era UIParent draws smaller than our 768-unit canvas; a chosen value, not the -- reference's. - ERA_WINDOW_SCALE = 0.78 + BENILLA_ERA_WINDOW_SCALE = 0.78 function BenillaOptionsFrame_UpdateScale() -- The era panel's checkFit: it also shrinks to fit the screen. - local k = ERA_WINDOW_SCALE + local k = BENILLA_ERA_WINDOW_SCALE local wFit = GetScreenWidth() / 940 local hFit = GetScreenHeight() / 744 if wFit < k then k = wFit end @@ -103,13 +110,14 @@ BenillaOptionsFrame:SetScale(k) end - -- The era tab width, label + 40, measured after OnShow sets the scale. - function OptionsTab_FitWidth(tab) + -- The era tab width, label + 40, measured after the window's OnShow sets the scale: + -- the tabs' own OnShows run before it, children first. + function BenillaOptionsTab_FitWidth(tab) tab:SetWidth(getglobal(tab:GetName() .. "Text"):GetStringWidth() + 40) end -- The wash at the era atlas size, in the 1.14 hover steel-blue. - function OptionsCategoryRow_OnLoad(row, key, label) + function BenillaOptionsCategoryRow_OnLoad(row, key, label) row.categoryKey = key row.pageTitle = label row:SetText(label) @@ -126,7 +134,7 @@ BenillaOptionsFrameSearchBox:SetText("") return -- the restore re-entered with this key and finished end - for _, k in ipairs(OPTIONS_CATEGORY_KEYS) do + for _, k in ipairs(BENILLA_OPTIONS_CATEGORY_KEYS) do local row = getglobal("BenillaOptionsFrameCategoryListRow" .. k) local bg = getglobal("BenillaOptionsFrameCategoryListRow" .. k .. "Bg") if k == key then @@ -140,7 +148,7 @@ row:SetTextFontObject("GameFontNormal") end end - for k in pairs(OPTIONS_PAGE_ROWS) do + for k in pairs(BENILLA_OPTIONS_PAGE_ROWS) do local body = getglobal("BenillaOptionsFrameContainerBody" .. k) if k == key then body:Show() else body:Hide() end end @@ -148,27 +156,18 @@ BenillaOptionsFrameContainerScroll:SetVerticalScroll(0) -- Leaving Keybindings disarms a pending capture, which must never outlive the page. local kb = getglobal("BenillaOptionsFrameContainerBodyKeybindings") - local addons = getglobal("BenillaOptionsFrameContainerBodyAddOns") if key == "Keybindings" then kb:Show() - addons:Hide() - KeyBindingsPage_Refresh() + BenillaKeyBindingsPage_Refresh() BenillaOptionsFrameContainerUnbind:Show() BenillaOptionsFrameContainerDefaults:Enable() - elseif key == "AddOns" then - kb:Hide() - addons:Show() - OptionsAddOns_Refresh() - BenillaOptionsFrameContainerUnbind:Hide() - BenillaOptionsFrameContainerDefaults:Disable() else kb:Hide() - addons:Hide() - KeyBindings_SetSelected(nil) - KeyBindings_Output("") + BenillaKeyBindings_SetSelected(nil) + BenillaKeyBindings_Output("") BenillaOptionsFrameContainerUnbind:Hide() - if OPTIONS_PAGE_ROWS[key] then - OptionsPage_Refresh(key) + if BENILLA_OPTIONS_PAGE_ROWS[key] then + BenillaOptionsPage_Refresh(key) BenillaOptionsFrameContainerDefaults:Enable() else BenillaOptionsFrameContainerDefaults:Disable() @@ -180,7 +179,7 @@ -- Tags are labels uppercased, matched by plain substring and scored by matched length. -- Results are the live rows, so writes work mid-search. - function OptionsSearch_Words(text) + function BenillaOptionsSearch_Words(text) local up = string.upper(text) local words = { up } for w in string.gfind(up, "([^, ]+)") do @@ -190,7 +189,7 @@ end -- The era's MatchesSearchTags score, with a plain find. - function OptionsSearch_Score(tag, words) + function BenillaOptionsSearch_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 @@ -198,14 +197,14 @@ return nil end - function OptionsSearch_FindMatches(text) - local words = OptionsSearch_Words(text) + function BenillaOptionsSearch_FindMatches(text) + local words = BenillaOptionsSearch_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 + for _, key in ipairs(BENILLA_OPTIONS_CATEGORY_KEYS) do + if BENILLA_OPTIONS_PAGE_ROWS[key] then + for _, rkey in ipairs(BENILLA_OPTIONS_PAGE_ROWS[key]) do local row = getglobal("BenillaOptionsFrameContainerBody" .. key .. rkey) - local s = OptionsSearch_Score(row.searchTag, words) + local s = BenillaOptionsSearch_Score(row.searchTag, words) if s then if not buckets[s] then buckets[s] = {} @@ -217,7 +216,7 @@ end end -- Keybinding matches join the buckets; their rkey is the binding index. - for _, m in ipairs(KeyBindings_SearchMatches(words)) do + for _, m in ipairs(BenillaKeyBindings_SearchMatches(words)) do if not buckets[m.score] then buckets[m.score] = {} table.insert(scores, m.score) @@ -240,7 +239,7 @@ -- ── The page scroll ── -- Only frames hung off the body's top are measured, so the size converges. - function OptionsScroll_ContentBottom() + function BenillaOptionsScroll_ContentBottom() local bottom = nil local function take(name) local f = getglobal(name) @@ -249,35 +248,48 @@ 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 + for _, key in ipairs(BENILLA_OPTIONS_CATEGORY_KEYS) do + if BENILLA_OPTIONS_PAGE_ROWS[key] then take("BenillaOptionsFrameContainerBodySearchHead" .. key) - for _, rkey in ipairs(OPTIONS_PAGE_ROWS[key]) do + for _, rkey in ipairs(BENILLA_OPTIONS_PAGE_ROWS[key]) do take("BenillaOptionsFrameContainerBody" .. key .. rkey) end end end take("BenillaOptionsFrameContainerBodySearchHeadKeybindings") - for i = 1, KEYBINDINGS_SEARCH_ROWS do + for i = 1, BENILLA_KEYBINDINGS_SEARCH_ROWS do take("BenillaOptionsFrameContainerBodyKeybindSearch" .. i) end - -- The AddOns page's dynamic rows: row 0 is the Load out of date AddOns row. - for i = 0, table.getn(OptionsAddOns_Rows) do - local row = OptionsAddOns_Rows[i] - if row then take(row:GetName()) end - end return bottom end + -- The scroll frame's size in its own units, from its edges: its anchors size it, and + -- GetWidth answers such a frame's span before the window's scale divides it. + local function BenillaOptionsScroll_Size(sf) + local l, r, t, b = sf:GetLeft(), sf:GetRight(), sf:GetTop(), sf:GetBottom() + if not l or not r or not t or not b then return nil end + return r - l, t - b + end + + -- The page's range is the body's overhang, the content Fit measures: the engine's range + -- also counts the Keybindings list's faux scroll child, which is sized to every row. + function BenillaOptionsScroll_Range(sf) + local _, fh = BenillaOptionsScroll_Size(sf) + if not fh then return 0 end + local range = BenillaOptionsFrameContainerBody:GetHeight() - fh + if range > 0 then return range end + return 0 + end + -- From OnUpdate, off the previous frame's rects; SetWidth and SetHeight invalidate layout. - function OptionsScroll_Fit() + function BenillaOptionsScroll_Fit() local sf = BenillaOptionsFrameContainerScroll local body = BenillaOptionsFrameContainerBody - local fw, fh = sf:GetWidth(), sf:GetHeight() + local fw, fh = BenillaOptionsScroll_Size(sf) 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() + local top, bottom = body:GetTop(), BenillaOptionsScroll_ContentBottom() if top and bottom then local content = (top - bottom) + BENILLA_SCROLL_PAD if content > h then h = content end @@ -285,11 +297,14 @@ if math.abs(body:GetHeight() - h) >= 0.5 then body:SetHeight(h) sf:UpdateScrollChildRect() + -- The bar follows the body, which the range notify misses when the engine's range, + -- a whole-subtree union, does not move. + BenillaScroll_SyncBar(sf) end end -- The era SettingsList layout: the head at (10,-12), each next at (0,-9), as in the XML. - function OptionsSearch_Place(name, prev) + function BenillaOptionsSearch_Place(name, prev) local f = getglobal(name) f:ClearAllPoints() if prev then @@ -302,40 +317,38 @@ end -- Back on the XML chain after a search; a test holds the two equal. - function OptionsPage_Layout(key) + function BenillaOptionsPage_Layout(key) local prev = nil - for _, rkey in ipairs(OPTIONS_PAGE_ROWS[key]) do + for _, rkey in ipairs(BENILLA_OPTIONS_PAGE_ROWS[key]) do local name = "BenillaOptionsFrameContainerBody" .. key .. rkey - OptionsSearch_Place(name, prev) + BenillaOptionsSearch_Place(name, prev) getglobal(name):Show() prev = name end end -- The title and no-match strings are ours: the era's are not in its UI source. - function OptionsSearch_Display(text) + function BenillaOptionsSearch_Display(text) BenillaOptionsFrameContainerScroll:SetVerticalScroll(0) - for k in pairs(OPTIONS_PAGE_ROWS) do + for k in pairs(BENILLA_OPTIONS_PAGE_ROWS) do getglobal("BenillaOptionsFrameContainerBody" .. k):Show() - for _, rkey in ipairs(OPTIONS_PAGE_ROWS[k]) do + for _, rkey in ipairs(BENILLA_OPTIONS_PAGE_ROWS[k]) do getglobal("BenillaOptionsFrameContainerBody" .. k .. rkey):Hide() end getglobal("BenillaOptionsFrameContainerBodySearchHead" .. k):Hide() end getglobal("BenillaOptionsFrameContainerBodyKeybindings"):Hide() getglobal("BenillaOptionsFrameContainerBodySearchHeadKeybindings"):Hide() - for i = 1, KEYBINDINGS_SEARCH_ROWS do + for i = 1, BENILLA_KEYBINDINGS_SEARCH_ROWS do getglobal("BenillaOptionsFrameContainerBodyKeybindSearch" .. i):Hide() end - -- The AddOns page is not in OPTIONS_PAGE_ROWS; hide it and its rows with it. - BenillaOptionsFrameContainerBodyAddOns:Hide() - KeyBindingsPage.searchPainted = nil - KeyBindings_SetSelected(nil) + BenillaKeyBindingsPage.searchPainted = nil + BenillaKeyBindings_SetSelected(nil) BenillaOptionsFrameContainerUnbind:Hide() BenillaOptionsFrameContainerTitle:SetText("Search Results") BenillaOptionsFrameContainerDefaults:Hide() - local order, groups = OptionsSearch_FindMatches(text) + local order, groups = BenillaOptionsSearch_FindMatches(text) if table.getn(order) == 0 then BenillaOptionsFrameContainerBodyNoResults:Show() return @@ -344,20 +357,20 @@ local prev = nil for _, key in ipairs(order) do local head = "BenillaOptionsFrameContainerBodySearchHead" .. key - OptionsSearch_Place(head, prev) + BenillaOptionsSearch_Place(head, prev) getglobal(head):Show() prev = head if key == "Keybindings" then - KeyBindingsPage.searchPainted = {} + BenillaKeyBindingsPage.searchPainted = {} local shown = 0 for _, index in ipairs(groups[key]) do - if shown < KEYBINDINGS_SEARCH_ROWS then + if shown < BENILLA_KEYBINDINGS_SEARCH_ROWS then shown = shown + 1 local name = "BenillaOptionsFrameContainerBodyKeybindSearch" .. shown - KeyBindings_PaintBindRow(name, index) - OptionsSearch_Place(name, prev) + BenillaKeyBindings_PaintBindRow(name, index) + BenillaOptionsSearch_Place(name, prev) getglobal(name):Show() - KeyBindingsPage.searchPainted[name] = index + BenillaKeyBindingsPage.searchPainted[name] = index prev = name end end @@ -368,47 +381,47 @@ if row.parentRow and not placed[row.parentRow] then placed[row.parentRow] = 1 local pname = "BenillaOptionsFrameContainerBody" .. key .. row.parentRow - OptionsSearch_Place(pname, prev) + BenillaOptionsSearch_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) + BenillaOptionsSearch_Place(name, prev) row:Show() prev = name end end - OptionsPage_Refresh(key) + BenillaOptionsPage_Refresh(key) end end end - function OptionsSearch_Restore() + function BenillaOptionsSearch_Restore() BenillaOptionsFrameContainerScroll:SetVerticalScroll(0) - for k in pairs(OPTIONS_PAGE_ROWS) do - OptionsPage_Layout(k) + for k in pairs(BENILLA_OPTIONS_PAGE_ROWS) do + BenillaOptionsPage_Layout(k) getglobal("BenillaOptionsFrameContainerBodySearchHead" .. k):Hide() end - for i = 1, KEYBINDINGS_SEARCH_ROWS do + for i = 1, BENILLA_KEYBINDINGS_SEARCH_ROWS do getglobal("BenillaOptionsFrameContainerBodyKeybindSearch" .. i):Hide() end getglobal("BenillaOptionsFrameContainerBodySearchHeadKeybindings"):Hide() - KeyBindingsPage.searchPainted = nil + BenillaKeyBindingsPage.searchPainted = nil BenillaOptionsFrameContainerBodyNoResults:Hide() BenillaOptionsFrameContainerDefaults:Show() BenillaOptionsFrame_SelectCategory(BenillaOptionsFrame.selectedCategory or "Controls") end - function OptionsSearch_OnTextChanged(text) + function BenillaOptionsSearch_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 + if had then BenillaOptionsSearch_Restore() end else - OptionsSearch_Display(text) + BenillaOptionsSearch_Display(text) end end @@ -434,11 +447,6 @@ .. "There is no exclusive fullscreen mode. WoW itself removed one in 8.0.1, and " .. "modern Classic offers these same two." - BENILLA_TOOLTIP_RESOLUTION = - "The size of the game window, from the modes this monitor reports.\n\n" - .. "In Windowed (Fullscreen) the window already fills the screen, so this sets the " - .. "size it returns to in Windowed. Takes effect on Apply." - -- 1.12's GAMMA text points at gray-bar art this page does not have. BENILLA_TOOLTIP_BRIGHTNESS = "Lightens or darkens the whole picture — nights, caves and interiors are what it is " @@ -447,599 +455,12 @@ .. "which it could only do in exclusive fullscreen. benilla applies it to the " .. "finished image instead, so it works in both display modes." - -- ══ MONKEY (advanced graphics): the Advanced Graphics page's own strings, EN + RU ═════ - -- - -- The page that gives a PLAYER the dynamic light and shadow system. Until it existed the - -- lanes were reachable only from `/console` and the native debug panel — and the panel - -- does not ship in a player build, so a player had no way in at all. Three rows move here - -- off the Graphics page (Real Character Shadows, World Shadows, Shadow Distance) with - -- their settings and their descriptions unchanged; the other twelve are new seats on - -- CVars this client has read for some time. - -- - -- **Every string on it is authored in both languages** (the project's own standing rule), - -- picked by `GetLocale()`, and there is no other localisation pattern in this window to - -- follow: every page above is 1.12 GlobalStrings, whose own file IS the localisation. So - -- the table is here, next to the page, rather than in a scheme of its own. - -- - -- TWO CAVEATS, both true of the client and not of this table: benilla's `GetLocale()` - -- answers `enUS` unconditionally today (it ships and reads enUS data only), so the ruRU - -- column is dormant until that changes; and 1.12's own `FRIZQT__.TTF` carries no Cyrillic - -- glyphs, so a Russian build needs a font that does before these read as words. Neither is - -- a reason to ship the page half-authored — both are one line away from being true, and a - -- string written later is a string written to a different standard. - -- - -- The VALUES the rows write are never localised: a dropdown entry carries the engine's own - -- string in `value` and the player's language in `text`, so `config.toml` and `/console` - -- read the same words on every install. - BENILLA_ADVGFX_STRINGS = { - enUS = { - page = "Advanced Graphics", - lightingQuality = "Lighting Quality", - -- MONKEY (presets): the Graphics Preset and Render Distance rows. - graphicsQuality = "Graphics Preset", - renderDistance = "Render Distance", - pClassic = "Classic", - qUltra = "Ultra", - -- MONKEY (volumetric fog): localised atmospheric quality row. - volumetricFog = "Volumetric Fog", - -- MONKEY (post): HDR excess + halo quality. - bloom = "Bloom", - sunShafts = "Sun Shafts", - colorGrading = "Colour Grading", - -- MONKEY (sky): the sky tier row. - skyQuality = "Sky Quality", - fogOff = "Off", - -- MONKEY (skybox): the zone skybox row. - zoneSkyboxes = "Zone Skyboxes", - waterQuality = "Water Quality", - waterClassic = "Classic", - waterEnhanced = "Enhanced", - waterHigh = "High", - lavaGlow = "Lava Glow", - qOff = "Off", - qLow = "Low", - qMedium = "Medium", - qHigh = "High", - qCustom = "Custom", - characterShadows = "Real Character Shadows", - worldShadows = "World Shadows", - shadowDistance = "Shadow Distance", - shadowResolution = "Shadow Resolution", - moonShadows = "Moon Shadows", - interiorLight = "Dynamic Interior Lighting", - interiorShadows = "Indoor Torch Shadows", - exteriorShadows = "Outdoor Torch Shadows", - torchTerrainShadows = "Terrain Blocks Torchlight", - torchSoft = "Torch Shadow Softness", - fireLight = "Fire Light Brightness", - fireFlicker = "Fire Flicker", - spellLights = "Spell Lights", - nightDarkness = "Night Darkness", - interiorDarkness = "Interior Darkness", - -- MONKEY (p0 skyDither) - skyDither = "Sky Dithering", - -- MONKEY (fog) - fogModel = "Modern Fog", - -- MONKEY (wet) - rainSurfaces = "Wet Surfaces in Rain", - -- MONKEY (wind) - foliageWind = "Foliage Wind", - windGrass = "Grass", - windTrees = "Grass + Trees", - foliageWindStrength = "Foliage Wind Strength", -- MONKEY (fix-wind) - -- MONKEY (ao): localised contact-shadow row. - ambientOcclusion = "Ambient Occlusion", - -- MONKEY (lampfog) - lampFog = "Lamp Fog", - -- GFX (volumetric light) / (moonlight) - volumetricLight = "Volumetric Light", - volumetricLightStrength = "Volumetric Light Strength", - moonLight = "Moonlight", - -- MONKEY (integration): the daylight lane's district window split. - daylightWindowSplit = "City Window Daylight", - yards = "%d yd", - tips = { - -- MONKEY (presets) - GRAPHICS_QUALITY = - "Sets every graphics setting at once: Lighting Quality and everything it sets, " - .. "Render Distance, Sky Quality, Sky Dithering, Modern Fog, Wet Surfaces in Rain, " - .. "Terrain Blocks Torchlight, the daylight through city windows, Ambient Occlusion, Lamp Fog, " - .. "Zone Skyboxes, Volumetric Light and Moonlight.\n\n" - .. "Classic is the original client: every enhancement off and the original 350 yd " - .. "view distance. Low and Medium add the enhancements that cost almost nothing; High " - .. "is the recommended look; Ultra raises every quality to its maximum and the view " - .. "distance to 1497 yd, and costs the most.\n\n" - .. "Shadow Distance and Torch Shadow Softness stay as you set them. Changing any " - .. "setting the preset sets shows Custom.", - RENDER_DISTANCE = - "How far the detailed world is drawn, in yards: the same setting as Terrain " - .. "Distance on the Graphics page, with a longer reach. Past 777 yd, the original " - .. "client's limit, the extra distance shows through Modern Fog; with the original " - .. "fog the zone's own fog hides it.\n\n" - .. "Farther costs more memory, loading and GPU time.", - LIGHTING_QUALITY = - "Sets character, world, indoor torch and outdoor torch shadows; dynamic " - .. "interior lighting; moon shadows; volumetric fog; water quality; lava glow; fire and spell brightness; fire flicker; " - .. "foliage wind; and night and interior darkness. Low, Medium and High also set shadow " - .. "resolution; Medium and High also set resident and moving torch shadow counts.\n\n" - .. "Off restores the original client's look: Classic water, no volumetric fog, lava glow or synthesised fire lights, " - .. "night gain 1.0 and interior gain 1.0. All other settings, including " - .. "Shadow Distance and Torch Shadow Softness, stay as you set them. " - .. "Low, Medium and High use Enhanced water; mirror reflections stay opt-in. " - .. "Ultra also raises shadow resolution to 4096 and the torch shadow counts to 16 and 8, " - .. "and uses High water and High volumetric fog. " - .. "Changing a preset member shows Custom when no preset matches.", - -- MONKEY (volumetric fog): explain cost and the shadow-map dependency. - -- MONKEY (post): Off guarantees the pre-HDR image. - BLOOM = - "Makes fire, lava, spells and lit windows carry a soft halo. Low uses a smaller blur chain; High is smoother. Off leaves the original image unchanged.", - SUN_SHAFTS = - "Draws sunlight through gaps in trees and buildings. Scene depth blocks the rays; they fade at night, off-screen and indoors.", - COLOR_GRADING = - "Applies a subtle zone-specific colour palette to the 3D world and blends between its day and night looks. The interface is never graded.", - VOLUMETRIC_FOG = - "Off disables volumetric fog. Low adds nearby haze and sun or moon shafts with fewer steps; High uses more steps for smoother shafts. Mist is heavier at dawn and in bad weather, and subtle indoors. Shafts require shadows; with shadows off only haze remains.", - -- MONKEY (sky): what each sky tier adds. - SKY_QUALITY = - "Classic is the original client's sky. Enhanced smooths the sky's colour " - .. "gradient, adds a soft glow around the sun and a starry night sky with the " - .. "Milky Way. High also gives the clouds finer detail and sunlit edges. " - .. "Costs very little.", - -- MONKEY (skybox): what the zone skybox row changes. - ZONE_SKYBOXES = - "Draws the painted sky a zone's lighting names, as later expansions do: " - .. "the volcanic sky of the Burning Steppes, the alien sky of the Blasted Lands " - .. "and the starry night over Mount Hyjal, fading in at the zone's edge. " - .. "Off keeps the original client's sky everywhere but ghost and dungeon skies. Nearly free.", - WATER_QUALITY = - "Classic is the original client's water. Enhanced adds soft shorelines, " - .. "animated foam around shores and objects, moving wave highlights, sky reflection " - .. "and light glints. High also adds mirror reflections and costs the most.", - LAVA_GLOW = - "How strongly lava lights its surroundings. 0 turns the glow off.", - CHARACTER_SHADOWS = - "Renders real dynamic silhouettes for players, NPCs, creatures, and mounts, replacing " - .. "the legacy oval blob. Matches Wrath's character-only shadow tier. This uses " - .. "additional GPU time and memory.", - WORLD_SHADOWS = - "Casts real dynamic shadows from the static world (trees, buildings, and foliage) " - .. "following the sun, and switches off the baked terrain shadows they replace. " - .. "Independent of Real Character Shadows. This uses additional GPU time and memory.", - SHADOW_DISTANCE = - "How far realtime shadows are drawn, in yards. Higher covers more ground but spreads " - .. "the shadow map thinner (softer edges) and costs more. Applies on Apply.", - SHADOW_RESOLUTION = - "The edge of the sun's shadow map, in texels. Larger is sharper " - .. "everywhere the shadow distance reaches.\n\n" - .. "The cost is quadratic: 4096 draws four times the shadow pass of 2048 " - .. "and holds four times the depth texture.", - MOON_SHADOWS = - "How dark a shadow thrown by moonlight is allowed to get. A little keeps " - .. "the night from reading flat; a lot is stylised moonlight the original " - .. "client never had.\n\n" - .. "At 0 the moon casts nothing at all and the night renders exactly as " - .. "it did before this existed. It costs nothing by day.", - INTERIOR_LIGHT = - "Lights the inside of buildings from the lamps, candles and hearths that " - .. "actually stand in the room, instead of the lighting baked into the " - .. "walls.\n\n" - .. "Off restores the original client's baked interiors. On, it costs a " - .. "little GPU time per lit surface. Indoor Torch Shadows require it; " - .. "Outdoor Torch Shadows work independently.", - INTERIOR_SHADOWS = - "Lets the nearest indoor fires cast real shadows — a candle throws the " - .. "table's shadow across the floor.\n\n" - .. "Each promoted fire costs a shadow map of its own, which makes this " - .. "the most expensive row on the page. Needs Dynamic Interior Lighting.", - EXTERIOR_SHADOWS = - "The same for fires out in the open: campfires, braziers and lampposts " - .. "cast real shadows after dark.\n\n" - .. "It does nothing by day and does not require Dynamic Interior Lighting.", - TORCH_TERRAIN_SHADOWS = - "Lets the ground itself take part in outdoor torch shadows: a hill or a " - .. "bank between a fire and the slope behind it blocks the fire's light.\n\n" - .. "Adds the nearby terrain to each outdoor fire's shadow map when it is " - .. "rebuilt; the per-frame cost is small. Needs Outdoor Torch Shadows.", - TORCH_SOFT = - "How soft the edge of a torch shadow is where the object meets the " - .. "ground. Low is hard and crisp; high spreads the edge the way a real " - .. "flame does.\n\n" - .. "It costs no extra shadow maps — only a wider filter over the ones " - .. "already drawn.", - FIRE_LIGHT = - "How brightly campfires, torches, braziers and forges light the world " - .. "around them. These are lights benilla invents from the flame itself; " - .. "the original client's art carries none.\n\n" - .. "At 0 the invented fire lights are off and only the lights the artists " - .. "placed remain. Moving it costs nothing.", - FIRE_FLICKER = - "How strongly every flame's light breathes — candles quick and shallow, " - .. "bonfires slow and steady.\n\n" - .. "At 0 fires burn at a constant brightness, which is what they did " - .. "before this existed. It is computed on the processor and costs the " - .. "graphics card nothing.", - SPELL_LIGHTS = - "How brightly spells, missiles and impacts light the room around them — a " - .. "fireball's flash, an aura's glow.\n\n" - .. "Separate from Fire Light Brightness on purpose: calming a busy fight " - .. "should not dim the world's hearths. At 0 no spell throws light.", - NIGHT_DARKNESS = - "How dark the world gets outdoors after sunset. " - .. "1.0 = the original client night; lower = darker.\n\n" - .. "It never touches the fires — the point is a darker night around the " - .. "flame, not a dimmer flame. Inert while the sun is up, and free at any " - .. "setting.", - INTERIOR_DARKNESS = - "Scales interior fixture light and room ambient, including the light from " - .. "lamps and candles. Lower values make both dimmer.\n\n" - .. "1.0 leaves these inputs unchanged. Free at any setting.\n\n" - .. "It does not scale the weather. A storm's fog reaches indoors at full " - .. "strength, as it does in the original client, so with this turned well " - .. "down in bad weather that fog is most of what is left and rooms read " - .. "flat and grey. Raise this rather than hunt for the cause elsewhere.", - -- MONKEY (p0 skyDither) - SKY_DITHER = - "Adds a faint noise to the final image so smooth sky and fog gradients do not " - .. "break into visible bands. Off is the original client's look. Practically free.", - -- MONKEY (fog) - FOG_MODEL = - "Softer distance fog in the style of the modern client: it thickens gradually " - .. "instead of in a straight ramp, glows toward the sun by day and shifts to the " - .. "sky's colour in the distance, so the land melts into the horizon. Each zone " - .. "keeps its own fog distance; above the original view-distance limit the fog " - .. "recedes with it.\n\nOff is the original client's fog. Practically free.", - -- MONKEY (wet) - RAIN_SURFACES = - "Rain slowly soaks the ground, stone and wood under the open sky: they darken, " - .. "puddles gather on flat ground and wet tops catch the light; rain drops ring " - .. "the water. It dries over a few minutes after the rain stops. Off is the " - .. "original client's look. Nearly free, and only active while things are wet.", - -- MONKEY (wind) - FOLIAGE_WIND = - "Grass bends in two travelling wind waves and parts around nearby characters. " - .. "Grass + Trees also gives classified tree and bush foliage a gentle sway.\n\n" - .. "Off makes no vertex displacement and restores the unchanged image. Tree shadows stay static.", - -- MONKEY (fix-wind) - FOLIAGE_WIND_STRENGTH = - "How far grass and foliage swing in the wind. 100% is the standard sway; lower " - .. "is calmer, higher is a blustery day. Storms swing everything harder on top. " - .. "Grass still parts around characters the same way. Needs Foliage Wind on.", - -- MONKEY (ao): what the contact shadows touch and what they spare. - AMBIENT_OCCLUSION = - "Soft contact shadows where surfaces meet: under props and furniture, in the corners " - .. "between walls and floors, and around characters' feet. Low uses fewer samples; " - .. "High is smoother and reaches a little further.\n\n" - .. "Fades out with distance and spares the sky, water, lit windows and flames. " - .. "Off leaves the image unchanged.", - -- MONKEY (integration): daylight window split. - DAYLIGHT_WINDOW_SPLIT = - "Large city buildings take daylight through each window on its own instead of " - .. "treating a whole wall of windows as one opening, so halls like the cathedral " - .. "catch the sun pane by pane.\n\nApplies to buildings loaded after the change. " - .. "Off is the earlier look.", - -- MONKEY (lampfog) - LAMP_FOG = - "Makes nearby lamps and fires glow through the air after dark. Low uses the " - .. "nearest 16 lights; High uses 32. Rain and fog strengthen the halos. " - .. "The effect is unshadowed, but stops at visible scene depth.\n\n" - .. "Off is unchanged, and daylight is unchanged at every setting.", - -- GFX (volumetric light) - VOLUMETRIC_LIGHT = - "Sunlight and moonlight shine through the air as visible shafts: rays through " - .. "tree canopies, between buildings and past your character, following the " - .. "real shadows. Thicker at dawn, in fog and in rain. Needs World Shadows or " - .. "Real Character Shadows; not drawn indoors.\n\n" - .. "Medium uses fewer samples; High is smoother. Off is unchanged.", - VOLUMETRIC_LIGHT_STRENGTH = - "How bright the volumetric light shafts are. 100% is the default; 0 hides them.", - -- GFX (moonlight) - MOONLIGHT = - "The moon lights the world at night: a cool, dim light from where the moon " - .. "really stands in the sky, added on top of the original night colours, with " - .. "moon shadows when Moon Shadows is above 0.\n\n" - .. "At 0 the night looks exactly as the original client drew it. Costs nothing by day.", - }, - }, - ruRU = { - page = "Расширенная графика", - lightingQuality = "Качество освещения", - -- MONKEY (presets): the Graphics Preset and Render Distance rows. - graphicsQuality = "Набор графики", - renderDistance = "Дальность прорисовки", - pClassic = "Классика", - qUltra = "Ультра", - -- MONKEY (post): Russian HDR excess + halo quality row. - bloom = "Свечение", - sunShafts = "Солнечные лучи", - colorGrading = "Цветокоррекция", - -- MONKEY (volumetric fog): Russian atmospheric quality row. - volumetricFog = "Объёмный туман", - -- MONKEY (sky): the sky tier row. - skyQuality = "Качество неба", - fogOff = "Выкл", - -- MONKEY (skybox): the zone skybox row. - zoneSkyboxes = "Небосводы зон", - waterQuality = "Качество воды", - waterClassic = "Классическое", - waterEnhanced = "Улучшенное", - waterHigh = "Высокое", - lavaGlow = "Свечение лавы", - qOff = "Выкл.", - qLow = "Низкое", - qMedium = "Среднее", - qHigh = "Высокое", - qCustom = "Своё", - characterShadows = "Настоящие тени персонажей", - worldShadows = "Тени мира", - shadowDistance = "Дальность теней", - shadowResolution = "Разрешение теней", - moonShadows = "Лунные тени", - interiorLight = "Динамическое освещение помещений", - interiorShadows = "Тени факелов в помещениях", - exteriorShadows = "Тени огней под открытым небом", - torchTerrainShadows = "Рельеф заслоняет огни", - torchSoft = "Мягкость теней от огня", - fireLight = "Яркость огня", - fireFlicker = "Мерцание огня", - spellLights = "Свет от заклинаний", - nightDarkness = "Темнота ночи", - interiorDarkness = "Темнота помещений", - -- MONKEY (p0 skyDither) - skyDither = "Дизеринг неба", - -- MONKEY (fog) - fogModel = "Современный туман", - -- MONKEY (wet) - rainSurfaces = "Мокрые поверхности в дождь", - -- MONKEY (wind) - foliageWind = "Ветер листвы", - windGrass = "Трава", - windTrees = "Трава + деревья", - foliageWindStrength = "Сила ветра листвы", -- MONKEY (fix-wind) - -- MONKEY (ao): Russian contact-shadow row. - ambientOcclusion = "Затенение окружения", - -- MONKEY (lampfog) - lampFog = "Свечение фонарей в тумане", - -- GFX (volumetric light) / (moonlight) - volumetricLight = "Объёмный свет", - volumetricLightStrength = "Сила объёмного света", - moonLight = "Лунный свет", - -- MONKEY (integration): the daylight lane's district window split. - daylightWindowSplit = "Дневной свет через окна города", - yards = "%d ярд.", - tips = { - -- MONKEY (presets) - GRAPHICS_QUALITY = - "Задаёт все настройки графики сразу: качество освещения и всё, что оно задаёт, " - .. "дальность прорисовки, качество неба, дизеринг неба, современный туман, мокрые " - .. "поверхности в дождь, заслонение огней рельефом, дневной свет в окнах городов, " - .. "затенение окружения, свечение фонарей в тумане, небосводы зон, объёмный свет и лунный свет.\n\n" - .. "«Классика» — оригинальный клиент: все улучшения выключены, дальность обзора " - .. "прежние 350 ярдов. «Низкое» и «Среднее» добавляют почти бесплатные улучшения; " - .. "«Высокое» — рекомендуемый вид; «Ультра» поднимает всё качество до максимума, а " - .. "дальность — до 1497 ярдов, и стоит дороже всего.\n\n" - .. "Дальность теней и мягкость теней от огня сохраняют ваши значения. Изменение " - .. "любой настройки набора показывает «Своё».", - RENDER_DISTANCE = - "Как далеко рисуется подробный мир, в ярдах: та же настройка, что «Дальность " - .. "обзора» на странице «Графика», но с большим пределом. Дальше 777 ярдов, предела " - .. "оригинального клиента, дополнительное расстояние видно с современным туманом; " - .. "с оригинальным туманом его скрывает туман зоны.\n\n" - .. "Чем дальше, тем больше памяти, загрузки и работы видеокарты.", - LIGHTING_QUALITY = - "Задаёт тени персонажей, мира и огней внутри и снаружи помещений; " - .. "динамическое освещение помещений; лунные тени; объёмный туман; качество воды; свечение лавы; яркость огня и заклинаний; " - .. "мерцание огня; темноту ночи и помещений. «Низкое», «Среднее» и «Высокое» " - .. "также задают разрешение теней; «Среднее» и «Высокое» — число карт теней " - .. "от огней и число огней с тенями движущихся объектов.\n\n" - .. "«Выкл.» возвращает вид оригинального клиента: классическая вода, без объёмного тумана, свечения лавы и созданных из пламени " - .. "источников света, с коэффициентами яркости ночи и помещений 1.0. " - .. "Все остальные настройки, включая дальность теней и мягкость теней от огня, " - .. "сохраняют ваши значения. «Низкое», «Среднее» и «Высокое» используют улучшенную воду; " - .. "зеркальные отражения включаются отдельно. «Ультра» также поднимает разрешение теней " - .. "до 4096 и число теней от огней до 16 и 8, а вода и объёмный туман — «Высокое». " - .. "Изменение настройки набора показывает «Своё», " - .. "если ни один набор больше не совпадает.", - -- MONKEY (post): localised bloom effect and Off contract. - BLOOM = - "Добавляет мягкое сияние огню, лаве, заклинаниям и освещённым окнам. Низкое качество использует короткое размытие, высокое — более плавное. Выключение сохраняет исходное изображение.", - SUN_SHAFTS = - "Показывает солнечные лучи сквозь деревья и здания. Рельеф и здания перекрывают свет; ночью и в помещениях эффект исчезает.", - COLOR_GRADING = - "Применяет мягкую цветовую палитру зоны и плавно меняет дневной вариант на ночной. Интерфейс не изменяется.", - -- MONKEY (volumetric fog): localised effect and cost explanation. - VOLUMETRIC_FOG = - "Выкл отключает объёмный туман. Низкое добавляет дымку вблизи и лучи солнца или луны с меньшим числом шагов; Высокое использует больше шагов для более плавных лучей. Туман гуще на рассвете и в непогоду, а в помещениях слабее. Для лучей нужны тени; без теней остаётся только дымка.", - -- MONKEY (sky): what each sky tier adds. - SKY_QUALITY = - "«Классическое» — небо оригинального клиента. «Улучшенное» сглаживает " - .. "цветовой переход неба, добавляет мягкое сияние вокруг солнца и звёздное " - .. "ночное небо с Млечным Путём. «Высокое» также добавляет облакам мелкие " - .. "детали и освещённые солнцем края. Почти не влияет на производительность.", - -- MONKEY (skybox): what the zone skybox row changes. - ZONE_SKYBOXES = - "Рисует нарисованное небо, заданное освещением зоны, как в поздних дополнениях: " - .. "вулканическое небо Пылающих степей, чужое небо Выжженных земель " - .. "и звёздную ночь над горой Хиджал, с плавным появлением на границе зоны. " - .. "«Выкл.» оставляет небо оригинального клиента везде, кроме неба призрака и подземелий. Почти бесплатно.", - WATER_QUALITY = - "«Классическое» — вода оригинального клиента. «Улучшенное» добавляет плавные переходы у берегов, " - .. "анимированную пену у берегов и вокруг объектов, подвижные блики на волнах, отражение неба " - .. "и блики от источников света. «Высокое» также добавляет зеркальные отражения и требует больше всего ресурсов.", - LAVA_GLOW = - "Насколько сильно лава освещает всё вокруг. При 0 свечение отключено.", - CHARACTER_SHADOWS = - "Рисует настоящие динамические силуэты игроков, НИП, существ и ездовых " - .. "животных вместо старого овального пятна. Соответствует уровню теней " - .. "персонажей из Wrath. Требует дополнительного времени и памяти " - .. "видеокарты.", - WORLD_SHADOWS = - "Заставляет статичный мир — деревья, здания и растительность — " - .. "отбрасывать настоящие динамические тени вслед за солнцем и отключает " - .. "запечённые тени ландшафта, которые они заменяют. Не зависит от " - .. "настоящих теней персонажей. Требует дополнительного времени и памяти " - .. "видеокарты.", - SHADOW_DISTANCE = - "Как далеко рисуются тени в реальном времени, в ярдах. Большее значение " - .. "покрывает больше земли, но растягивает карту теней тоньше (края " - .. "становятся мягче) и стоит дороже. Применяется по кнопке «Применить».", - SHADOW_RESOLUTION = - "Размер карты теней солнца в текселях. Чем больше, тем чётче тени на " - .. "всей дальности их прорисовки.\n\n" - .. "Стоимость растёт квадратично: 4096 — это вчетверо больше работы в " - .. "проходе теней и вчетверо больше видеопамяти под карту глубины, чем " - .. "2048.", - MOON_SHADOWS = - "Насколько тёмной может стать тень, отбрасываемая лунным светом. " - .. "Немного — и ночь перестаёт выглядеть плоской; много — это " - .. "стилизованная луна, какой в оригинальном клиенте не было.\n\n" - .. "При 0 луна не отбрасывает теней вовсе, и ночь выглядит так же, как " - .. "до появления этой возможности. Днём не стоит ничего.", - INTERIOR_LIGHT = - "Освещает помещения от ламп, свечей и очагов, которые действительно " - .. "стоят в комнате, а не от освещения, запечённого в стенах.\n\n" - .. "«Выкл.» возвращает запечённые интерьеры оригинального клиента. " - .. "Включённый режим стоит немного времени видеокарты на каждую " - .. "освещённую поверхность. Тени от огней внутри требуют этого режима; " - .. "тени от огней снаружи работают независимо.", - INTERIOR_SHADOWS = - "Позволяет ближайшим огням в помещении отбрасывать настоящие тени: " - .. "свеча кладёт тень стола на пол.\n\n" - .. "Каждый такой огонь стоит собственной карты теней, поэтому это самая " - .. "дорогая строка на странице. Требует динамического освещения " - .. "помещений.", - EXTERIOR_SHADOWS = - "То же для огней под открытым небом: костры, жаровни и фонари " - .. "отбрасывают настоящие тени после наступления темноты.\n\n" - .. "Днём не действует и не требует динамического освещения помещений.", - TORCH_TERRAIN_SHADOWS = - "Земля сама участвует в тенях от огней снаружи: холм или склон между " - .. "костром и местностью за ним заслоняет свет огня.\n\n" - .. "Добавляет ближний рельеф в карту теней каждого уличного огня при её " - .. "перестройке; затраты на кадр невелики. Требует теней огней под " - .. "открытым небом.", - TORCH_SOFT = - "Насколько мягок край тени от огня там, где предмет касается пола. " - .. "Низкое значение — резкий край, высокое — размытый, как от " - .. "настоящего пламени.\n\n" - .. "Дополнительных карт теней не требует: это лишь более широкий фильтр " - .. "по уже нарисованным.", - FIRE_LIGHT = - "Насколько ярко костры, факелы, жаровни и горны освещают всё вокруг. " - .. "Эти источники benilla создаёт из самого пламени — в оригинальной " - .. "графике их нет.\n\n" - .. "При 0 придуманные огни выключены и остаются лишь источники, " - .. "расставленные художниками. Изменение значения ничего не стоит.", - FIRE_FLICKER = - "Насколько сильно «дышит» свет каждого пламени: свечи — часто и слабо, " - .. "костры — медленно и ровно.\n\n" - .. "При 0 огни горят с постоянной яркостью, как было до появления этой " - .. "возможности. Считается на процессоре и ничего не стоит видеокарте.", - SPELL_LIGHTS = - "Насколько ярко заклинания, снаряды и попадания освещают всё вокруг: " - .. "вспышка огненного шара, свечение ауры.\n\n" - .. "Отделено от яркости огня намеренно: успокоить шумный бой не должно " - .. "значить пригасить очаги во всём мире. При 0 заклинания не дают " - .. "света.", - NIGHT_DARKNESS = - "Насколько темно становится под открытым небом после заката. " - .. "1.0 — ночь оригинального клиента; ниже — темнее.\n\n" - .. "Огней не касается: смысл в том, чтобы ночь вокруг пламени была " - .. "темнее, а не само пламя тусклее. Пока солнце в небе, не действует, и " - .. "ничего не стоит при любом значении.", - INTERIOR_DARKNESS = - "Масштабирует свет светильников и фоновое освещение помещений, включая " - .. "свет ламп и свечей. Меньшие значения ослабляют и то и другое.\n\n" - .. "1.0 оставляет эти составляющие без изменений. Ничего не стоит при любом значении.\n\n" - .. "Погоды не касается: туман непогоды проникает внутрь в полную силу, как " - .. "и в оригинальном клиенте. При сильно пониженном значении в плохую " - .. "погоду именно этот туман и остаётся, и помещения выглядят плоско и " - .. "серо. Поднимите этот ползунок, а не ищите причину в другом месте.", - -- MONKEY (p0 skyDither) - SKY_DITHER = - "Добавляет едва заметный шум в итоговое изображение, чтобы плавные переходы цвета " - .. "неба и тумана не распадались на полосы. Выключено — вид оригинального клиента. " - .. "Почти ничего не стоит.", - -- MONKEY (fog) - FOG_MODEL = - "Более мягкий туман в духе современного клиента: он сгущается постепенно, а не " - .. "по прямой, днём светлеет в сторону солнца, а вдали принимает цвет неба, " - .. "так что земля растворяется в горизонте. Дальность тумана в каждой зоне " - .. "прежняя; за пределом дальности обзора оригинала туман отступает вместе с ней." - .. "\n\nВыключено — туман оригинального клиента. Почти ничего не стоит.", - -- MONKEY (wet) - RAIN_SURFACES = - "Дождь постепенно намачивает землю, камень и дерево под открытым небом: они темнеют, " - .. "на ровной земле собираются лужи, мокрые поверхности блестят, а капли расходятся " - .. "кругами по воде. После дождя всё высыхает за несколько минут. Выключено — вид " - .. "оригинального клиента. Почти ничего не стоит и работает, только пока всё мокрое.", - -- MONKEY (wind) - FOLIAGE_WIND = - "Трава гнётся двумя бегущими волнами ветра и расступается вокруг персонажей. " - .. "Трава + деревья также добавляет мягкое качание листвы деревьев и кустов.\n\n" - .. "Выключено не смещает вершины и восстанавливает исходный вид. Тени деревьев остаются неподвижными.", - -- MONKEY (fix-wind) - FOLIAGE_WIND_STRENGTH = - "Насколько сильно трава и листва качаются на ветру. 100% — обычное качание; меньше — " - .. "спокойнее, больше — ветреный день. В грозу всё качается ещё сильнее. " - .. "Трава по-прежнему расступается вокруг персонажей. Работает, если включён ветер листвы.", - -- MONKEY (ao): Russian contact-shadow explanation. - AMBIENT_OCCLUSION = - "Мягкие контактные тени там, где поверхности соприкасаются: под предметами и мебелью, " - .. "в углах между стенами и полом, у ног персонажей. «Низкое» использует меньше выборок; " - .. "«Высокое» — более плавное и захватывает чуть больше.\n\n" - .. "Ослабевает с расстоянием и не затрагивает небо, воду, освещённые окна и пламя. " - .. "«Выкл» оставляет изображение без изменений.", - -- MONKEY (integration): daylight window split. - DAYLIGHT_WINDOW_SPLIT = - "Большие городские здания пропускают дневной свет через каждое окно отдельно, " - .. "а не через всю стену окон как один проём, поэтому залы вроде собора " - .. "освещаются солнцем окно за окном.\n\nДействует для зданий, загруженных после " - .. "изменения. Выключено — прежний вид.", - -- MONKEY (lampfog) - LAMP_FOG = - "После заката ближайшие фонари и огни светятся сквозь воздух. Низкое " - .. "качество использует 16 ближайших источников, высокое — 32. Дождь и туман усиливают ореолы. " - .. "Эффект не рассчитывает тени, но обрывается на видимой глубине.\n\n" - .. "Выключено — без изменений; днём изображение не меняется при любом значении.", - -- GFX (volumetric light) - VOLUMETRIC_LIGHT = - "Солнечный и лунный свет виден в воздухе лучами: сквозь кроны деревьев, между " - .. "зданиями и рядом с персонажем, по настоящим теням. Гуще на рассвете, в тумане " - .. "и под дождём. Нужны тени мира или реальные тени персонажей; в помещениях не " - .. "рисуется.\n\n" - .. "«Среднее» использует меньше выборок, «Высокое» — более плавное. Выключено — " - .. "без изменений.", - VOLUMETRIC_LIGHT_STRENGTH = - "Яркость лучей объёмного света. 100% — по умолчанию; 0 скрывает их.", - -- GFX (moonlight) - MOONLIGHT = - "Луна освещает мир ночью: холодный тусклый свет с того места, где луна " - .. "действительно стоит на небе, поверх исходных ночных цветов, с лунными тенями, " - .. "если «Лунные тени» больше 0.\n\n" - .. "При 0 ночь выглядит точно так же, как в оригинальном клиенте. Днём не стоит ничего.", - }, - }, - } - - -- The selected column. `or` the English one so an unbuilt locale is a fallback rather - -- than fifteen rows of `nil` labels — 1.12's own GlobalStrings do the same thing by - -- shipping one file per locale with every key present. - BENILLA_ADVGFX = BENILLA_ADVGFX_STRINGS[GetLocale()] or BENILLA_ADVGFX_STRINGS.enUS - - -- A row's description resolves by GLOBAL NAME at hover time (`OptionsRow_ShowTooltip`), so - -- the selected column's copy is published under the key the row carries. Same `BENILLA_` - -- prefix the four rows above use, and for the same reason: the reference's - -- `OPTION_TOOLTIP_` namespace stays the reference's. - for key, text in pairs(BENILLA_ADVGFX.tips) do - setglobal("BENILLA_TOOLTIP_" .. key, text) - end - - OPTIONS_PAGE_ROWS = { + BENILLA_OPTIONS_PAGE_ROWS = { -- The era Controls order first; the rest follow their 1.12 box's columns. Controls = { "RowStickyTarget", "RowAssistAttack", "RowClearAFK", "RowBlockTrades", "RowAutoSelfCast", - "RowAutoLoot", "RowInvertMouse", "RowMouseSpeed", + "RowAutoLoot", "RowInvertMouse", "RowMouseSpeed", "RowClickToMove", "RowCameraFollowStyle", "RowFollowTerrain", "RowHeadBob", "RowAutoFollowSpeed", "RowWaterCollision", "RowSmartPivot", "RowMouseLookSpeed", "RowMaxCameraDistance", @@ -1050,61 +471,15 @@ "RowBackgroundSound", }, Graphics = { - "RowUiScale", "RowFarclip", "RowWorldDetail", "RowBrightness", + "RowUiScale", "RowFarclip", "RowWorldDetail", "RowSpellDetail", "RowBrightness", "RowWeatherDensity", - "RowDisplayMode", "RowResolution", "RowVerticalSync", - "RowRenderScale", + "RowDisplayMode", "RowVerticalSync", "RowRenderScale", }, - -- MONKEY (advanced graphics): the dynamic light + shadow system's own page. Order is - -- the preset first (it writes the rest), then the SUN lanes, then the ROOM lane and - -- its torches, then the invented lights, then the two darkness dials — coarse to - -- fine, and each group's own master above the rows it gates. - -- - -- Real Character Shadows, World Shadows and Shadow Distance MOVED here from Graphics, - -- carrying their CVars and their descriptions unchanged: they belong with the rest of - -- the rig they share, and the Graphics page had become the place where a player found - -- three of eighteen shadow settings and no hint that the other fifteen existed. - AdvancedGraphics = { - -- MONKEY (presets): the ladder over every row below, then the view distance. - "RowGraphicsQuality", "RowRenderDistance", - -- MONKEY (volumetric fog): include in refresh, defaults and search. - "RowLightingQuality", "RowWaterQuality", "RowVolumetricFog", - -- MONKEY (sky): the sky tier row. - "RowSkyQuality", - -- MONKEY (post): the world-only screen effects. - "RowBloom", "RowSunShafts", "RowColorGrading", - "RowCharacterShadows", "RowWorldShadows", "RowShadowDistance", - "RowShadowResolution", "RowMoonShadows", - "RowInteriorLight", "RowInteriorShadows", "RowExteriorShadows", - -- MONKEY (daylight: terrain torch casters) - "RowTorchTerrainShadows", "RowTorchSoft", - "RowFireLight", "RowFireFlicker", "RowSpellLights", "RowLavaGlow", - "RowNightDarkness", "RowInteriorDarkness", - -- MONKEY (p0 skyDither) - "RowSkyDither", - -- MONKEY (fog) - "RowFogModel", - -- MONKEY (wet) - "RowRainSurfaces", - -- MONKEY (wind): appended for conflict-free lane merges. - "RowFoliageWind", - -- MONKEY (fix-wind): the sway strength, right under its tier. - "RowFoliageWindStrength", - -- MONKEY (ao): appended so the other rows keep their indices. - "RowAmbientOcclusion", - -- MONKEY (lampfog) - "RowLampFog", - -- MONKEY (integration): daylight window split. - "RowDaylightWindowSplit", - -- MONKEY (integration): the skybox lane's row (the lane left it out of this list). - "RowZoneSkyboxes", - -- GFX (volumetric light) / (moonlight): appended so the other rows keep their indices. - "RowVolumetricLight", "RowVolumetricLightStrength", "RowMoonLight", - }, - -- Guild Names is a child of Player Names (UIOptionsFrame.lua:703-709). + -- Guild Names and Player Titles are children of Player Names + -- (UIOptionsFrame.lua:703-709). Nameplates = { "RowEnemyPlates", "RowFriendlyPlates", - "RowPlayerNames", "RowGuildNames", "RowNpcNames", "RowOwnName", + "RowPlayerNames", "RowGuildNames", "RowPlayerTitles", "RowNpcNames", "RowOwnName", }, -- 1.12's Display box by column, then Help; target-of-target sits under Status Text. Interface = { @@ -1138,11 +513,11 @@ } -- `tip` is a GlobalStrings key, resolved at hover as UIOptionsFrame.lua:265 does. - function OptionsRow_OnLoad(row, cvar, label, tip, child) + function BenillaOptionsRow_OnLoad(row, cvar, label, tip, child) row.cvar = cvar row.tip = tip row.searchTag = string.upper(label) - -- OptionsRow_SetEnabled's disabled font must keep the child size. + -- BenillaOptionsRow_SetEnabled's disabled font must keep the child size. row.child = child local l = getglobal(row:GetName() .. "Label") l:SetText(label) @@ -1156,12 +531,12 @@ -- ── The row's store ── -- 1.12's `cvar`, `uvar` or `func`/`setFunc` (UIOptionsFrame.lua:230-377), all strings. Keep - -- OptionsRow_HasStore in OptionsRow_Set's order. - function OptionsRow_HasStore(row) + -- BenillaOptionsRow_HasStore in BenillaOptionsRow_Set's order. + function BenillaOptionsRow_HasStore(row) return row.uvar or row.setFunc or row.cvar end - function OptionsRow_Get(row) + function BenillaOptionsRow_Get(row) if row.uvar then return getglobal(row.uvar) end if row.getFunc then -- OptionsFrame.lua:110/135, formatted like the slider's write so strings compare @@ -1175,7 +550,7 @@ end -- A uvar row applies on the click; `cvarEvent` is CVAR_UPDATE's arg1. - function OptionsRow_Set(row, value) + function BenillaOptionsRow_Set(row, value) if row.uvar then setglobal(row.uvar, value) -- Looked up when applied: most definers load after this file. @@ -1195,12 +570,12 @@ return end SetCVar(row.cvar, value, row.cvarEvent) - OptionsRow_WritePartner(row, value) + BenillaOptionsRow_WritePartner(row, value) end -- UIOptionsFrame_Save's partner writes: Pet Melee Damage also writes PetSpellDamage -- (l.334-336); the camera speeds write their pitch twin at yaw/4 and yaw/2 (l.351-356). - function OptionsRow_WritePartner(row, value) + function BenillaOptionsRow_WritePartner(row, value) if not row.partner then return end local v = value if row.partner.scale then @@ -1211,60 +586,44 @@ end -- A uvar's default is captured at OnLoad, before the saved-variables chunk runs. - function OptionsRow_Default(row) + function BenillaOptionsRow_Default(row) if row.uvar then return row.udefault end if row.getFunc then return row.fdefault end return GetCVarDefault(row.cvar) end - -- OptionsRow_OnLoad's signature with the global's name in the cvar seat. - function OptionsGlobalRow_OnLoad(row, uvar, label, tip, child) - OptionsRow_OnLoad(row, nil, label, tip, child) + -- BenillaOptionsRow_OnLoad's signature with the global's name in the cvar seat. + function BenillaOptionsGlobalRow_OnLoad(row, uvar, label, tip, child) + BenillaOptionsRow_OnLoad(row, nil, label, tip, child) row.uvar = uvar row.udefault = getglobal(uvar) end -- Stated, as UIOptionsFrame_SetDefaults hand-writes it (l.631-634). - function OptionsFuncRow_OnLoad(row, getFunc, setFunc, default, label, tip, child) - OptionsRow_OnLoad(row, nil, label, tip, child) + function BenillaOptionsFuncRow_OnLoad(row, getFunc, setFunc, default, label, tip, child) + BenillaOptionsRow_OnLoad(row, nil, label, tip, child) row.getFunc = getFunc row.setFunc = setFunc row.fdefault = default end -- `default` is still a string, since rows compare strings. - function OptionsNumFuncRow_OnLoad(row, getFunc, setFunc, default, label, tip, child) - OptionsFuncRow_OnLoad(row, getFunc, setFunc, default, label, tip, child) + function BenillaOptionsNumFuncRow_OnLoad(row, getFunc, setFunc, default, label, tip, child) + BenillaOptionsFuncRow_OnLoad(row, getFunc, setFunc, default, label, tip, child) row.numeric = 1 end -- UIOptionsFrame.lua:193-227 re-applies saved uvars, so this window has no load ladder. -- OptionsFrameSliders is the stock table (OptionsFrame.lua:24-34), which addons write. - -- Deviation: TurtleWoW's patch-4 replaces OptionsFrame.lua with a 2.0-era file that never - -- defines it, so the rows below restore the 1.12 table verbatim — `OPTIONS_FARCLIP_MIN/MAX` - -- resolved to their 177/777 values (they live in the 1.12 OptionsFrame.lua:1-2, not in - -- GlobalStrings, so a replacement loses them) — for the graphics rows and any addon. - OptionsFrameSliders = { - { text = UI_SCALE, func = "uiscale", minValue = 0.64, maxValue = 1.0, valueStep = 0.01, tooltipText = OPTION_TOOLTIP_UI_SCALE }, - { text = FARCLIP, func = "farclip", minValue = 177, maxValue = 777, valueStep = 60, tooltipText = OPTION_TOOLTIP_FARCLIP }, - { text = ENVIRONMENT_DETAIL, func = "WorldDetail", minValue = 0, maxValue = 2, valueStep = 1, tooltipText = OPTION_TOOLTIP_ENVIRONMENT_DETAIL }, - { text = TERRAIN_MIP, func = "TerrainMip", minValue = 0, maxValue = 1, valueStep = 1, tooltipText = OPTION_TOOLTIP_TERRAIN_TEXTURE, restartClient = 1, tooltipRequirement = OPTION_RESTART_REQUIREMENT }, - { text = TEXTURE_DETAIL, func = "BaseMip", minValue = 0, maxValue = 1, valueStep = 1, tooltipText = OPTION_TOOLTIP_TEXTURE_DETAIL }, - { text = GAMMA, func = "Gamma", cvar1 = "gamma", minValue = -0.5, maxValue = 0.5, valueStep = 0.1, tooltipText = OPTION_TOOLTIP_GAMMA }, - { text = ANISOTROPIC, func = "anisotropic", minValue = 1, maxValue = 4, valueStep = 1, tooltipText = OPTION_TOOLTIP_ANISOTROPIC, restartClient = 1, tooltipRequirement = OPTION_RESTART_REQUIREMENT }, - { text = SPELL_DETAIL, func = "spellEffectLevel", minValue = 0, maxValue = 2, valueStep = 1, tooltipText = OPTION_TOOLTIP_SPELL_DETAIL }, - { text = WEATHER_DETAIL, func = "weatherDensity", minValue = 0, maxValue = 3, valueStep = 1, tooltipText = OPTION_TOOLTIP_WEATHER_DETAIL }, - } - - -- Holes at 4, 5, 7 and 8, so the OnShow loop uses the pairs form: ipairs would stop at 3. + -- Holes at 4, 5 and 7, so the OnShow loop uses the pairs form: ipairs would stop at 3. BENILLA_GRAPHICS_SLIDER_ROWS = { "RowUiScale", "RowFarclip", "RowWorldDetail", - [6] = "RowBrightness", [9] = "RowWeatherDensity", + [6] = "RowBrightness", [8] = "RowSpellDetail", [9] = "RowWeatherDensity", } -- SetMinMaxValues re-clamps and fires OnValueChanged, which must not write back. - function OptionsSliderRow_Setup(row, min, max, step, fmt, stops) + function BenillaOptionsSliderRow_Setup(row, min, max, step, fmt, stops) local slider = getglobal(row:GetName() .. "ControlSlider") row.fmt = fmt -- Kept for the "travel" readout, a share of the row's own range. @@ -1279,88 +638,42 @@ end -- ── The dropdown rows: the 1.12 UIDropDownMenu kit ── - function OptionsDropdownRow_Setup(row, entries) + function BenillaOptionsDropdownRow_Setup(row, entries) row.entries = entries local dd = getglobal(row:GetName() .. "Dropdown") UIDropDownMenu_SetWidth(180, dd) - UIDropDownMenu_Initialize(dd, OptionsDropdownRow_InitMenu) + UIDropDownMenu_Initialize(dd, BenillaOptionsDropdownRow_InitMenu) -- The capsule's button steals hover from the row, so it carries the row wash too. 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) + btn:SetScript("OnEnter", function() BenillaOptionsRow_Hover(this:GetParent():GetParent(), 1) end) + btn:SetScript("OnLeave", function() BenillaOptionsRow_Hover(this:GetParent():GetParent(), nil) end) end - -- A row whose entries come from LIVE ENGINE STATE rather than from a fixed list has to be - -- rebuilt before it is read, because that state is not there yet when this file loads: - -- the display's mode list is pushed by a Bevy system a frame or more later - -- (`video.rs`'s `publish_display_modes`, and `addon_harness/mod.rs` documents the empty - -- list a freshly-loaded VM sees). Built once at OnLoad, such a row ends up with no - -- entries at all — which shows as the raw stored index in the capsule and an empty menu - -- that does nothing when clicked, since there is nothing to list. - function OptionsResolutionRow_Rebuild(row) - local modes = { GetScreenResolutions() } - local entries = {} - for i = 1, table.getn(modes) do - -- A STRING value, as every other dropdown row's is: `OptionsRow_Get` formats a - -- numeric row's value as a string too, so this is what lets - -- `OptionsDropdown_ShowValue` match on equality instead of falling through to - -- its nearest-value search. - table.insert(entries, { text = modes[i], value = tostring(i) }) - end - row.entries = entries - end - - function OptionsDropdownRow_InitMenu() + function BenillaOptionsDropdownRow_InitMenu() local dd = getglobal(UIDROPDOWNMENU_INIT_MENU) local row = dd:GetParent() - if row.rebuild then row.rebuild(row) end for _, e in ipairs(row.entries) do local info = {} info.text = e.text info.value = e.value - info.func = OptionsDropdownEntry_OnClick + info.func = BenillaOptionsDropdownEntry_OnClick UIDropDownMenu_AddButton(info) end end - -- Write a row's value, or stage it for Apply when the row is `deferred`. - -- - -- The slider path had this inline and the checkbox and dropdown paths did not, so a - -- deferred checkbox or dropdown wrote straight through and the Apply button — which only - -- appears when some row is pending — never came up. That is how vertical sync looked - -- like it was not persisting: `gxVSync` is a **latched** CVar, so `SetCVar` only stages - -- it on the host side until `RestartGx`, and with no Apply button there was nothing to - -- press to get there. - function OptionsRow_Commit(row, value) - if row.deferred then - -- A pending equal to the committed value is dropped, as the slider's is. - if value == OptionsRow_Get(row) then - row.pending = nil - else - row.pending = value - end - OptionsApply_Update() - else - OptionsRow_Set(row, value) - end - end - -- `this` is the list button; the kit closes the list and plays the click. - function OptionsDropdownEntry_OnClick() + function BenillaOptionsDropdownEntry_OnClick() local dd = UIDropDownMenu_GetCurrentDropDown() local row = dd:GetParent() - OptionsRow_Commit(row, this.value) - OptionsDropdown_ShowValue(row) + BenillaOptionsRow_Set(row, this.value) + BenillaOptionsDropdown_ShowValue(row) end -- A field, not SetSelectedValue, whose Refresh walks the shared DropDownList1. An off-grid -- value shows the nearest entry. - function OptionsDropdown_ShowValue(row) + function BenillaOptionsDropdown_ShowValue(row) local dd = getglobal(row:GetName() .. "Dropdown") - -- A staged pick shows at once, as `OptionsPage_Refresh` already does for the other - -- control kinds: a deferred row would otherwise snap back to the committed value the - -- instant it was chosen, which reads as the pick not having registered. - local v = row.pending or OptionsRow_Get(row) + local v = BenillaOptionsRow_Get(row) local match for _, e in ipairs(row.entries) do -- `alt`: a stored "3" shows as Never, where the nearest value would show Always. @@ -1387,7 +700,7 @@ end end - function OptionsRow_FormatValue(row, value) + function BenillaOptionsRow_FormatValue(row, value) if row.fmt == "raw" then return string.format("%d", math.floor(value + 0.5)) end @@ -1404,41 +717,19 @@ return string.format("%d%%", math.floor((value - row.minv) / (row.maxv - row.minv) * 100 + 0.5)) end - -- MONKEY (advanced graphics): travel, READ BACKWARDS — the same share of the groove, - -- counted from the right-hand end. The two darkness dials are the case: their stored - -- unit is a GAIN (`nightGain`, `interiorGain`), so the darkest setting is the SMALLEST - -- number and sits at the left of the groove, while the row is named for the darkness - -- rather than the gain. Without this the readout would count UP as the world got - -- LIGHTER under a label that says "Darkness", which is exactly backwards; with it the - -- label, the thumb and the number all agree that further left is darker. The store - -- keeps the gain, unchanged — this is a readout, not a unit. - if row.fmt == "darkness" and row.minv and row.maxv and row.maxv > row.minv then - return string.format("%d%%", - math.floor((row.maxv - value) / (row.maxv - row.minv) * 100 + 0.5)) - end -- "yards": cameraDistanceMaxFactor over the 15 yd base. if row.fmt == "yards" then - return string.format(BENILLA_ADVGFX.yards, math.floor(value * 15 + 0.5)) - end - -- MONKEY (advanced graphics): a row whose stored value ALREADY IS a distance in yards - -- — the realtime-shadow range. Its own format, because the one above it is a - -- CONVERSION and not a unit: `shadowDistance` rode `"yards"` from the day it was - -- seated, so an 80-yard cascade printed "1200 yd" and nothing caught it (no test read - -- that readout, and 1200 is not an absurd-looking number for a view distance). The - -- two formats differ by exactly the factor's 15 yd base, which is why they cannot be - -- one. - if row.fmt == "yd" then - return string.format(BENILLA_ADVGFX.yards, math.floor(value + 0.5)) + return string.format("%d yd", math.floor(value * 15 + 0.5)) end return string.format("%d%%", math.floor(value * 100 + 0.5)) end -- Crossing controls does not blink: OnLeave fires before OnEnter within a move. - function OptionsRow_Hover(row, on) + function BenillaOptionsRow_Hover(row, on) local hover = getglobal(row:GetName() .. "Hover") if on then hover:Show() - OptionsRow_ShowTooltip(row) + BenillaOptionsRow_ShowTooltip(row) else hover:Hide() GameTooltip:Hide() @@ -1446,7 +737,7 @@ end -- 1.12's per-option string alone in gold (OptionsFrameTemplates.xml:52-64). - function OptionsRow_ShowTooltip(row) + function BenillaOptionsRow_ShowTooltip(row) local text = row.tip and getglobal(row.tip) if text then GameTooltip:SetOwner(getglobal(row:GetName() .. "Tip"), "ANCHOR_RIGHT", -10, 0) @@ -1458,7 +749,7 @@ end end - function OptionsCheckbox_OnClick(box) + function BenillaOptionsCheckbox_OnClick(box) local row = box:GetParent() local checked = box:GetChecked() -- The 1.12 panels disagree: the interface panel plays CheckBoxOn when checked @@ -1474,14 +765,14 @@ local on = checked if row.invert then on = not on end if on then - OptionsRow_Commit(row, "1") + BenillaOptionsRow_Set(row, "1") else - OptionsRow_Commit(row, "0") + BenillaOptionsRow_Set(row, "0") end - OptionsPage_UpdateDependencies(BenillaOptionsFrame.selectedCategory) + BenillaOptionsPage_UpdateDependencies(BenillaOptionsFrame.selectedCategory) end - function OptionsSlider_OnValueChanged(slider, value) + function BenillaOptionsSlider_OnValueChanged(slider, value) local control = slider:GetParent() local row = control:GetParent() if not row.refreshing then @@ -1498,160 +789,57 @@ 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 + getglobal(control:GetName() .. "Value"):SetText(BenillaOptionsRow_FormatValue(row, value)) + if BenillaOptionsRow_HasStore(row) and not row.refreshing then -- Trailing zeros stripped, so a value at its default stays out of the config file. local str = string.gsub(string.format("%.2f", value), "%.?0+$", "") if row.deferred then -- Stored on Apply; a pending equal to the committed value is dropped. - if str == OptionsRow_Get(row) then + if str == BenillaOptionsRow_Get(row) then row.pending = nil else row.pending = str end - OptionsApply_Update() + BenillaOptionsApply_Update() else - OptionsRow_Set(row, str) + BenillaOptionsRow_Set(row, str) end end end - function OptionsPage_Refresh(key) + function BenillaOptionsPage_Refresh(key) local base = "BenillaOptionsFrameContainerBody" .. key - for _, rkey in ipairs(OPTIONS_PAGE_ROWS[key]) do + for _, rkey in ipairs(BENILLA_OPTIONS_PAGE_ROWS[key]) do local row = getglobal(base .. rkey) local box = getglobal(base .. rkey .. "Check") if box then -- "0" unchecks; an inverted row checks on "0". if row.invert then local checked - if OptionsRow_Get(row) == "0" then checked = 1 end + if BenillaOptionsRow_Get(row) == "0" then checked = 1 end box:SetChecked(checked) else - box:SetChecked(OptionsRow_Get(row)) + box:SetChecked(BenillaOptionsRow_Get(row)) end elseif row.entries then - if row.rebuild then row.rebuild(row) end - OptionsDropdown_ShowValue(row) + BenillaOptionsDropdown_ShowValue(row) else local slider = getglobal(base .. rkey .. "ControlSlider") row.refreshing = 1 -- A staged value shows first, as the era's GetValue returns it. - slider:SetValue(tonumber(row.pending or OptionsRow_Get(row) or "0") or 0) + slider:SetValue(tonumber(row.pending or BenillaOptionsRow_Get(row) or "0") or 0) row.refreshing = nil -- SetValue fires only on a change, so the readout is written here. getglobal(base .. rkey .. "ControlValue"):SetText( - OptionsRow_FormatValue(row, slider:GetValue())) + BenillaOptionsRow_FormatValue(row, slider:GetValue())) end end - OptionsPage_UpdateDependencies(key) - OptionsApply_Update() - end - - -- ── The AddOns page: the era's per-addon enable list ── - -- Rows are built on show from the AddOn API: one checkbox per installed addon (its - -- `GetAddOnInfo` enabled state), then the Load out of date AddOns row. A toggle calls - -- `EnableAddOn`/`DisableAddOn`, which the host persists to `AddOns.txt` at logout, so the - -- change applies on the next world entry — the reference's own contract for the AddOns - -- screen. Row 0 is the Load out of date AddOns row. - OptionsAddOns_Rows = {} - - function OptionsAddOns_GetRow(i) - local row = OptionsAddOns_Rows[i] - if row then return row end - row = CreateFrame("Frame", "BenillaOptionsFrameContainerBodyAddOnsRow" .. i, - BenillaOptionsFrameContainerBodyAddOns, "OptionsCheckboxRowTemplate") - row.index = i - OptionsAddOns_Rows[i] = row - return row - end - - function OptionsAddOns_OnClick(box) - local row = box:GetParent() - local checked = box:GetChecked() - PlaySound(checked and "igMainMenuOptionCheckBoxOn" or "igMainMenuOptionCheckBoxOff") - if checked then - EnableAddOn(row.index) - else - DisableAddOn(row.index) - end - end - - function OptionsAddOns_Refresh() - local n = GetNumAddOns() - local prev = nil - for i = 1, n do - local name, title, notes, enabled = GetAddOnInfo(i) - local row = OptionsAddOns_GetRow(i) - row:Show() - local label = getglobal(row:GetName() .. "Label") - label:SetText(title or name) - row.searchTag = string.upper(title or name) - local box = getglobal(row:GetName() .. "Check") - box:SetChecked(enabled) - box:SetScript("OnClick", OptionsAddOns_OnClick) - OptionsSearch_Place(row:GetName(), prev) - prev = row:GetName() - end - for i = n + 1, table.getn(OptionsAddOns_Rows) do - OptionsAddOns_Rows[i]:Hide() - end - -- The Load out of date AddOns row, under the list; inverted, `checkAddonVersion` - -- "1" enforces the check (`0x402c3b`), so checked means "0". - local lod = OptionsAddOns_GetRow(0) - if not lod.cvar then - OptionsRow_OnLoad(lod, "checkAddonVersion", "Load out of date AddOns") - lod.invert = 1 - end - lod:Show() - getglobal(lod:GetName() .. "Check"):SetChecked( - OptionsRow_Get(lod) == "0" and 1 or nil) - OptionsSearch_Place(lod:GetName(), prev) - end - - -- ── MONKEY (advanced graphics): the page that has to WATCH its settings ───────────── - -- Every other page in this window owns its rows outright: nothing but a click on the page - -- moves the CVars behind it while it is open, so reading them once on select is the whole - -- contract. The lighting rows are not like that, and deliberately so — they are the live - -- A/B knobs the whole system was tuned with, and there are three other ways to move one - -- with this page on screen: `/console set nightGain 1` in chat, the native lighting panel - -- in a dev build, and — the one that matters to a player — the Lighting Quality row above, - -- which does not write its members here at all. It writes ONE CVar; the host's preset - -- table answers by writing the other ten, and those land a frame or two later. - -- - -- So the page polls. A cheap signature of its own rows' values, four times a second, and a - -- refresh only when that string actually moves — which is never, on a page nobody is - -- touching. The alternative (an event) does not exist: a host-side CVar write reaches the - -- interface as a mirror update, not as `CVAR_UPDATE`, which the reference only ever fires - -- for a script's own `SetCVar` with a token. - -- - -- Safe under a drag, and not by luck: the value the refresh would write back is the value - -- the drag just wrote, `SetValue` fires nothing when it does not change the value, and the - -- `refreshing` guard stops a write even if it did. A staged (deferred) edit is safe too — - -- `OptionsPage_Refresh` shows `row.pending` ahead of the stored value. - BENILLA_ADVGFX_POLL = 0.25 - - function AdvGfx_Signature() - local out = "" - for _, rkey in ipairs(OPTIONS_PAGE_ROWS.AdvancedGraphics) do - local row = getglobal("BenillaOptionsFrameContainerBodyAdvancedGraphics" .. rkey) - out = out .. "|" .. (OptionsRow_Get(row) or "") - end - return out - end - - function AdvGfx_OnUpdate(page, elapsed) - page.since = (page.since or 0) + (elapsed or 0) - if page.since < BENILLA_ADVGFX_POLL then return end - page.since = 0 - local sig = AdvGfx_Signature() - if sig == page.sig then return end - page.sig = sig - OptionsPage_Refresh("AdvancedGraphics") + BenillaOptionsPage_UpdateDependencies(key) + BenillaOptionsApply_Update() end -- Each page's dependency rules, the 1.12 panel's own. - function OptionsPage_UpdateDependencies(key) + function BenillaOptionsPage_UpdateDependencies(key) if key == "Combat" then -- Combo Points is for rogues and druids only. local on = SHOW_COMBAT_TEXT ~= "0" @@ -1662,69 +850,46 @@ local damage = { RowShowDamage = 1, RowPeriodicDamage = 1, RowPetDamage = 1, } - for _, rkey in ipairs(OPTIONS_PAGE_ROWS.Combat) do + for _, rkey in ipairs(BENILLA_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( + BenillaOptionsRow_SetEnabled( getglobal("BenillaOptionsFrameContainerBodyCombat" .. rkey), live) end end -- UIOptionsFrame.lua:710-716: Show Target Damage off greys Periodic and Pet Damage. local dmg = GetCVar("CombatDamage") ~= "0" - OptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyCombatRowPeriodicDamage, dmg) - OptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyCombatRowPetDamage, dmg) - return - end - if key == "AdvancedGraphics" then - -- MONKEY (advanced graphics): the page's own dependencies — the same shape the - -- reference's own rules have (a master's own switch greys what it gates), read - -- off the CVar docs rather than invented: `interiorShadows` "needs - -- interiorLight", the two shadow-rig rows size a cascade that is not rendered - -- with both sun lanes off, and the torch softness is the PCF radius on maps - -- neither torch lane is drawing. The CVars keep their values throughout — this - -- is a dependency, not a write, so turning a master back on finds its children - -- exactly where they were left. - local base = "BenillaOptionsFrameContainerBodyAdvancedGraphics" - local sun = GetCVar("characterShadows") ~= "0" - or GetCVar("worldShadows") ~= "0" - OptionsRow_SetEnabled(getglobal(base .. "RowShadowDistance"), sun) - OptionsRow_SetEnabled(getglobal(base .. "RowShadowResolution"), sun) - local interior = GetCVar("interiorLight") ~= "0" - OptionsRow_SetEnabled(getglobal(base .. "RowInteriorShadows"), interior) - local torch = (interior and GetCVar("interiorShadows") ~= "0") - or GetCVar("exteriorShadows") ~= "0" - OptionsRow_SetEnabled(getglobal(base .. "RowTorchSoft"), torch) - -- MONKEY (daylight: terrain torch casters): the ground only casts for outdoor fires. - OptionsRow_SetEnabled(getglobal(base .. "RowTorchTerrainShadows"), - GetCVar("exteriorShadows") ~= "0") - -- MONKEY (fix-wind): the strength only matters while some foliage sways. - OptionsRow_SetEnabled(getglobal(base .. "RowFoliageWindStrength"), - GetCVar("foliageWind") ~= "0") + BenillaOptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyCombatRowPeriodicDamage, dmg) + BenillaOptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyCombatRowPetDamage, dmg) return end if key == "Controls" then -- UIOptionsFrame.lua:717-721: dead while the style is Never, "0" or a stray "3". local style = GetCVar("cameraSmoothStyle") - OptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyControlsRowAutoFollowSpeed, + BenillaOptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyControlsRowAutoFollowSpeed, style ~= "0" and style ~= "3") return end if key == "Nameplates" then - -- UIOptionsFrame.lua:703-709: Player Names off greys Player Guild Names. - OptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyNameplatesRowGuildNames, - GetCVar("UnitNamePlayer") ~= "0") + -- UIOptionsFrame.lua:703-709: Player Names off greys Player Guild Names and + -- Player Titles. + local on = GetCVar("UnitNamePlayer") ~= "0" + BenillaOptionsRow_SetEnabled( + BenillaOptionsFrameContainerBodyNameplatesRowGuildNames, on) + BenillaOptionsRow_SetEnabled( + BenillaOptionsFrameContainerBodyNameplatesRowPlayerTitles, on) return end if key == "Interface" then -- UIOptionsFrame.lua:697-701: the mode is dead while its switch is off. - OptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyInterfaceRowTargetOfTargetMode, + BenillaOptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyInterfaceRowTargetOfTargetMode, SHOW_TARGET_OF_TARGET ~= "0") return end if key == "ActionBars" then -- UIOptionsFrame.lua:722-726: Right ActionBar 2 needs Right ActionBar. - OptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyActionBarsRowMultiBar4, + BenillaOptionsRow_SetEnabled(BenillaOptionsFrameContainerBodyActionBarsRowMultiBar4, SHOW_MULTI_ACTIONBAR_3) return end @@ -1745,7 +910,7 @@ end -- As OptionsFrame_DisableDropDown; 1.12 has no UIDropDownMenu_DisableDropDown. - function OptionsRow_SetEnabled(row, on) + function BenillaOptionsRow_SetEnabled(row, on) local name = row:GetName() local box = getglobal(name .. "Check") local dd = getglobal(name .. "Dropdown") @@ -1786,35 +951,22 @@ end -- Pending edits dropped. - function OptionsPage_Defaults(key) + function BenillaOptionsPage_Defaults(key) local base = "BenillaOptionsFrameContainerBody" .. key - for _, rkey in ipairs(OPTIONS_PAGE_ROWS[key]) do + for _, rkey in ipairs(BENILLA_OPTIONS_PAGE_ROWS[key]) do local row = getglobal(base .. rkey) row.pending = nil - if not row.preset then - OptionsRow_Set(row, OptionsRow_Default(row)) - end + BenillaOptionsRow_Set(row, BenillaOptionsRow_Default(row)) end - -- MONKEY (presets): a preset row goes last, so its default rung (the Graphics - -- Preset's High) is what the page lands on rather than its members' own defaults. - -- `SetCVar` queues only a moved value, so "Custom" (which the host applies as - -- nothing) goes first: the rung is then always a queued write, after the members. - for _, rkey in ipairs(OPTIONS_PAGE_ROWS[key]) do - local row = getglobal(base .. rkey) - if row.preset then - OptionsRow_Set(row, "Custom") - OptionsRow_Set(row, OptionsRow_Default(row)) - end - end - OptionsPage_Refresh(key) + BenillaOptionsPage_Refresh(key) end -- ── The Apply flow ── -- Pending edits survive a category switch; hiding discards them. - function OptionsApply_Update() + function BenillaOptionsApply_Update() local pending - for key, rows in pairs(OPTIONS_PAGE_ROWS) do + for key, rows in pairs(BENILLA_OPTIONS_PAGE_ROWS) do local base = "BenillaOptionsFrameContainerBody" .. key for _, rkey in ipairs(rows) do if getglobal(base .. rkey).pending then pending = 1 end @@ -1829,41 +981,34 @@ end end - function OptionsPage_Apply() - for key, rows in pairs(OPTIONS_PAGE_ROWS) do + function BenillaOptionsPage_Apply() + for key, rows in pairs(BENILLA_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) + BenillaOptionsRow_Set(row, row.pending) row.pending = nil end end end - -- Commit the latched rows. A CVar registered with the latch flag — gxVSync, - -- gxResolution, gxWindow — does not take the write that `OptionsRow_Set` just made: - -- it is staged until `RestartGx`, which is what the reference's own video options - -- call on Apply. Without this they stayed pending for the whole session, never - -- reached the live value, and so were never written to `config.toml` either: a - -- vertical-sync change that looked accepted and was back on after a relaunch. - RestartGx() - OptionsApply_Update() + BenillaOptionsApply_Update() end - function OptionsPage_DiscardPending() - for key, rows in pairs(OPTIONS_PAGE_ROWS) do + function BenillaOptionsPage_DiscardPending() + for key, rows in pairs(BENILLA_OPTIONS_PAGE_ROWS) do local base = "BenillaOptionsFrameContainerBody" .. key for _, rkey in ipairs(rows) do getglobal(base .. rkey).pending = nil end end - OptionsApply_Update() + BenillaOptionsApply_Update() end ]]> - - - + - + @@ -1924,7 +1069,7 @@ - - + @@ -1988,21 +1133,21 @@ - OptionsCheckbox_OnClick(this) - OptionsRow_Hover(this:GetParent(), 1) - OptionsRow_Hover(this:GetParent(), nil) + BenillaOptionsCheckbox_OnClick(this) + BenillaOptionsRow_Hover(this:GetParent(), 1) + BenillaOptionsRow_Hover(this:GetParent(), nil) - OptionsRow_Hover(this, 1) - OptionsRow_Hover(this, nil) + BenillaOptionsRow_Hover(this, 1) + BenillaOptionsRow_Hover(this, nil) - + @@ -2064,22 +1209,22 @@ - OptionsSlider_OnValueChanged(this, arg1) - OptionsRow_Hover(this:GetParent():GetParent(), 1) - OptionsRow_Hover(this:GetParent():GetParent(), nil) + BenillaOptionsSlider_OnValueChanged(this, arg1) + BenillaOptionsRow_Hover(this:GetParent():GetParent(), 1) + BenillaOptionsRow_Hover(this:GetParent():GetParent(), nil) - OptionsRow_Hover(this, 1) - OptionsRow_Hover(this, nil) + BenillaOptionsRow_Hover(this, 1) + BenillaOptionsRow_Hover(this, nil) - + @@ -2113,8 +1258,8 @@ - OptionsRow_Hover(this, 1) - OptionsRow_Hover(this, nil) + BenillaOptionsRow_Hover(this, 1) + BenillaOptionsRow_Hover(this, nil) @@ -2130,9 +1275,11 @@ - + + + clear of the border's ink, which ends by texel 14. --> @@ -2148,7 +1295,7 @@ - + @@ -2218,9 +1365,6 @@ - - OptionsTab_FitWidth(self) - @@ -2261,68 +1405,56 @@ - + - getglobal(self:GetName() .. "Label"):SetText("Gameplay") + getglobal(this:GetName() .. "Label"):SetText("Gameplay") - - - - - - - - + - getglobal(self:GetName() .. "Label"):SetText("System") + getglobal(this:GetName() .. "Label"):SetText("System") - - - - - @@ -2347,37 +1479,37 @@ - + - - @@ -2389,17 +1521,33 @@ - self:SetScrollChild(BenillaOptionsFrameContainerBody) - OptionsScroll_Fit() - BenillaScroll_OnMouseWheel(this, arg1) + + this:SetScrollChild(BenillaOptionsFrameContainerBody) + this.contentRange = BenillaOptionsScroll_Range + + BenillaOptionsScroll_Fit() + + + if BenillaKeyBindingsPage.selected then + BenillaKeyBindings_OnMouseWheel(arg1) + else + BenillaScroll_OnMouseWheel(this, arg1) + end + BenillaScroll_SyncBar(this) BenillaScroll_SyncBar(this) - - + + + + this:SetFrameLevel(this:GetParent():GetFrameLevel()) + + + BenillaOptionsScroll_Fit sizes it. --> @@ -2419,185 +1567,194 @@ - + - OptionsRow_OnLoad(self, "deselectOnClick", "Sticky Targeting", + BenillaOptionsRow_OnLoad(this, "deselectOnClick", "Sticky Targeting", "OPTION_TOOLTIP_GAMEFIELD_DESELECT") - self.invert = 1 + this.invert = 1 - + - OptionsRow_OnLoad(self, "assistAttack", "Attack on assist", + BenillaOptionsRow_OnLoad(this, "assistAttack", "Attack on assist", "OPTION_TOOLTIP_ASSIST_ATTACK") - + - OptionsRow_OnLoad(self, "autoClearAFK", "Auto Clear AFK", + BenillaOptionsRow_OnLoad(this, "autoClearAFK", "Auto Clear AFK", "OPTION_TOOLTIP_CLEAR_AFK") - + - OptionsRow_OnLoad(self, "BlockTrades", "Block Trades", + BenillaOptionsRow_OnLoad(this, "BlockTrades", "Block Trades", "OPTION_TOOLTIP_BLOCK_TRADES") - + - OptionsRow_OnLoad(self, "autoSelfCast", "Auto Self Cast", + BenillaOptionsRow_OnLoad(this, "autoSelfCast", "Auto Self Cast", "OPTION_TOOLTIP_AUTO_SELF_CAST") - + - OptionsRow_OnLoad(self, "autoLootDefault", "Auto Loot") + BenillaOptionsRow_OnLoad(this, "autoLootDefault", "Auto Loot") - + - OptionsRow_OnLoad(self, "mouseInvertPitch", "Invert Mouse", + BenillaOptionsRow_OnLoad(this, "mouseInvertPitch", "Invert Mouse", "OPTION_TOOLTIP_INVERT_MOUSE") - + - OptionsRow_OnLoad(self, "mousespeed", "Mouse Sensitivity", + BenillaOptionsRow_OnLoad(this, "mousespeed", "Mouse Sensitivity", "OPTION_TOOLTIP_MOUSE_SENSITIVITY") - OptionsSliderRow_Setup(self, 0.5, 1.5, 0.05) + BenillaOptionsSliderRow_Setup(this, 0.5, 1.5, 0.05) - - + + + BenillaOptionsRow_OnLoad(this, "autointeract", "Click-to-Move", + "OPTION_TOOLTIP_CLICK_TO_MOVE") + + + + + + + - OptionsRow_OnLoad(self, "cameraSmoothStyle", + BenillaOptionsRow_OnLoad(this, "cameraSmoothStyle", "Camera Following Style", "OPTION_TOOLTIP_CAMERA1") - OptionsDropdownRow_Setup(self, { + BenillaOptionsDropdownRow_Setup(this, { { 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" }, }) - + - OptionsRow_OnLoad(self, "cameraTerrainTilt", "Follow Terrain", + BenillaOptionsRow_OnLoad(this, "cameraTerrainTilt", "Follow Terrain", "OPTION_TOOLTIP_FOLLOW_TERRAIN") - + - OptionsRow_OnLoad(self, "cameraBobbing", "Head Bob", + BenillaOptionsRow_OnLoad(this, "cameraBobbing", "Head Bob", "OPTION_TOOLTIP_HEAD_BOB") - + - OptionsRow_OnLoad(self, "cameraYawSmoothSpeed", "Auto-Follow Speed", + BenillaOptionsRow_OnLoad(this, "cameraYawSmoothSpeed", "Auto-Follow Speed", "OPTION_TOOLTIP_AUTO_FOLLOW_SPEED") - OptionsSliderRow_Setup(self, 90, 270, 10, "raw") + BenillaOptionsSliderRow_Setup(this, 90, 270, 10, "raw") - + - OptionsRow_OnLoad(self, "cameraWaterCollision", "Water Collision", + BenillaOptionsRow_OnLoad(this, "cameraWaterCollision", "Water Collision", "OPTION_TOOLTIP_WATER_COLLISION") - + - OptionsRow_OnLoad(self, "cameraPivot", "Smart Pivot", + BenillaOptionsRow_OnLoad(this, "cameraPivot", "Smart Pivot", "OPTION_TOOLTIP_SMART_PIVOT") - + - OptionsRow_OnLoad(self, "cameraYawMoveSpeed", "Mouse Look Speed", + BenillaOptionsRow_OnLoad(this, "cameraYawMoveSpeed", "Mouse Look Speed", "OPTION_TOOLTIP_MOUSE_LOOK_SPEED") - OptionsSliderRow_Setup(self, 90, 270, 10, "raw") - self.partner = { cvar = "cameraPitchMoveSpeed", scale = 0.5 } + BenillaOptionsSliderRow_Setup(this, 90, 270, 10, "raw") + this.partner = { cvar = "cameraPitchMoveSpeed", scale = 0.5 } - + - OptionsRow_OnLoad(self, "cameraDistanceMaxFactor", + BenillaOptionsRow_OnLoad(this, "cameraDistanceMaxFactor", "Max Camera Distance", "OPTION_TOOLTIP_MAX_FOLLOW_DIST") - OptionsSliderRow_Setup(self, 1.0, 2.0, 0.1, "yards") + BenillaOptionsSliderRow_Setup(this, 1.0, 2.0, 0.1, "yards") @@ -2609,117 +1766,108 @@ - + - OptionsRow_OnLoad(self, "MasterSoundEffects", "Enable All Sound", + BenillaOptionsRow_OnLoad(this, "MasterSoundEffects", "Enable All Sound", "OPTION_TOOLTIP_ENABLE_ALL_SOUND") - self.soundQuirk = 1 + this.soundQuirk = 1 - + - OptionsRow_OnLoad(self, "MasterVolume", "Master Volume", + BenillaOptionsRow_OnLoad(this, "MasterVolume", "Master Volume", "OPTION_TOOLTIP_MASTER_VOLUME") - + - OptionsRow_OnLoad(self, "SoundVolume", "Sound Volume", + BenillaOptionsRow_OnLoad(this, "SoundVolume", "Sound Volume", "OPTION_TOOLTIP_SOUND_VOLUME", 1) - self.parentRow = "RowMaster" + this.parentRow = "RowMaster" - + - OptionsRow_OnLoad(self, "MusicVolume", "Music Volume", + BenillaOptionsRow_OnLoad(this, "MusicVolume", "Music Volume", "OPTION_TOOLTIP_MUSIC_VOLUME", 1) - self.parentRow = "RowMaster" + this.parentRow = "RowMaster" - + - OptionsRow_OnLoad(self, "AmbienceVolume", "Ambience Volume", + BenillaOptionsRow_OnLoad(this, "AmbienceVolume", "Ambience Volume", "OPTION_TOOLTIP_AMBIENCE_VOLUME", 1) - self.parentRow = "RowMaster" + this.parentRow = "RowMaster" - + - OptionsRow_OnLoad(self, "EnableMusic", "Enable Music", + BenillaOptionsRow_OnLoad(this, "EnableMusic", "Enable Music", "OPTION_TOOLTIP_ENABLE_MUSIC") - self.soundQuirk = 1 + this.soundQuirk = 1 - + - OptionsRow_OnLoad(self, "EnableAmbience", "Enable Ambience", + BenillaOptionsRow_OnLoad(this, "EnableAmbience", "Enable Ambience", "OPTION_TOOLTIP_ENABLE_AMBIENCE") - self.soundQuirk = 1 + this.soundQuirk = 1 - + - OptionsRow_OnLoad(self, "EnableErrorSpeech", "Enable Error Speech", + BenillaOptionsRow_OnLoad(this, "EnableErrorSpeech", "Enable Error Speech", "OPTION_TOOLTIP_ENABLE_ERROR_SPEECH") - self.soundQuirk = 1 + this.soundQuirk = 1 - + - OptionsRow_OnLoad(self, "Sound_EnableSoundWhenGameIsInBG", + BenillaOptionsRow_OnLoad(this, "Sound_EnableSoundWhenGameIsInBG", "Enable Sound in Background", "BENILLA_TOOLTIP_BACKGROUND_SOUND") - self.soundQuirk = 1 + this.soundQuirk = 1 - - - - - - - @@ -2729,88 +1877,106 @@ - + - OptionsRow_OnLoad(self, "uiScale", "UI Scale", + BenillaOptionsRow_OnLoad(this, "uiScale", "UI Scale", "OPTION_TOOLTIP_UI_SCALE") - OptionsSliderRow_Setup(self, OptionsFrameSliders[1].minValue, + BenillaOptionsSliderRow_Setup(this, OptionsFrameSliders[1].minValue, OptionsFrameSliders[1].maxValue, OptionsFrameSliders[1].valueStep) -- A live write would rescale the slider mid-drag. - self.deferred = 1 + this.deferred = 1 - + - OptionsRow_OnLoad(self, "farclip", "Terrain Distance", + BenillaOptionsRow_OnLoad(this, "farclip", "Terrain Distance", "OPTION_TOOLTIP_FARCLIP") - OptionsSliderRow_Setup(self, OptionsFrameSliders[2].minValue, + BenillaOptionsSliderRow_Setup(this, OptionsFrameSliders[2].minValue, OptionsFrameSliders[2].maxValue, OptionsFrameSliders[2].valueStep, "raw") - + - OptionsRow_OnLoad(self, "WorldDetail", "Environment Detail", + BenillaOptionsRow_OnLoad(this, "WorldDetail", "Environment Detail", "OPTION_TOOLTIP_ENVIRONMENT_DETAIL") -- Stop names from the era quality ladder. - OptionsSliderRow_Setup(self, OptionsFrameSliders[3].minValue, + BenillaOptionsSliderRow_Setup(this, OptionsFrameSliders[3].minValue, OptionsFrameSliders[3].maxValue, OptionsFrameSliders[3].valueStep, nil, { "Low", "Medium", "High" }) + + + + + + + + BenillaOptionsRow_OnLoad(this, "spellEffectLevel", SPELL_DETAIL, + "OPTION_TOOLTIP_SPELL_DETAIL") + -- Our names for the handler's emission scalars + -- 0.33, 0.66 and 1.0 (`0x689510`). + BenillaOptionsSliderRow_Setup(this, OptionsFrameSliders[8].minValue, + OptionsFrameSliders[8].maxValue, + OptionsFrameSliders[8].valueStep, nil, + { "Low", "Medium", "High" }) + + - + - - + + -- OptionsFrame_SetDefaults' default (l.444-445); -- `or 1` covers a VM with no CVars. local gd = tonumber(GetCVarDefault("gamma")) or 1 - OptionsNumFuncRow_OnLoad(self, GetGamma, SetGamma, + BenillaOptionsNumFuncRow_OnLoad(this, GetGamma, SetGamma, tostring(1 - gd), "Brightness", "BENILLA_TOOLTIP_BRIGHTNESS") - OptionsSliderRow_Setup(self, OptionsFrameSliders[6].minValue, + BenillaOptionsSliderRow_Setup(this, OptionsFrameSliders[6].minValue, OptionsFrameSliders[6].maxValue, OptionsFrameSliders[6].valueStep, "travel") - + - OptionsRow_OnLoad(self, "weatherDensity", "Weather Intensity", + BenillaOptionsRow_OnLoad(this, "weatherDensity", "Weather Intensity", "OPTION_TOOLTIP_WEATHER_DETAIL") -- Our names for `0x67b870`'s spawn-rate gains -- `{0.1, 0.33, 0.66, 1.0}` (`[0x8680ec]`). - OptionsSliderRow_Setup(self, OptionsFrameSliders[9].minValue, + BenillaOptionsSliderRow_Setup(this, OptionsFrameSliders[9].minValue, OptionsFrameSliders[9].maxValue, OptionsFrameSliders[9].valueStep, nil, { "Minimal", "Low", "Medium", "Full" }) - + @@ -2819,72 +1985,27 @@ -- Deviation: modern Classic's two-entry Display -- Mode, as there is no exclusive fullscreen; -- gxWindow "0" is the borderless window. - -- Latched, like the other two video rows. - self.deferred = 1 - OptionsRow_OnLoad(self, "gxWindow", "Display Mode", + BenillaOptionsRow_OnLoad(this, "gxWindow", "Display Mode", "BENILLA_TOOLTIP_DISPLAY_MODE") - OptionsDropdownRow_Setup(self, { + BenillaOptionsDropdownRow_Setup(this, { { text = "Windowed (Fullscreen)", value = "0" }, { text = "Windowed", value = "1" }, }) - + - -- The window size. Backed by the index verbs, not - -- by `gxResolution` directly: `SetScreenResolution` - -- is 1-based into `GetScreenResolutions`, and - -- `GetCurrentResolution` reports the *live* window - -- rather than the CVar, which in borderless - -- fullscreen are not the same thing. - -- - -- Built from the real list, so the entries are - -- whatever this monitor actually offers. 1.12's - -- own video panel had this row; benilla shipped - -- the display-mode and vsync rows without it, so - -- there was no way to resize from inside the game. - -- `rebuild`, not a list baked here: at OnLoad - -- the engine has pushed no modes yet, so a list - -- built now is empty for the whole session. - self.rebuild = OptionsResolutionRow_Rebuild - self.deferred = 1 - OptionsNumFuncRow_OnLoad(self, - GetCurrentResolution, SetScreenResolution, - "1", "Resolution", - "BENILLA_TOOLTIP_RESOLUTION") - OptionsResolutionRow_Rebuild(self) - OptionsDropdownRow_Setup(self, self.entries) - - - - - - - - - -- Deferred: `gxVSync` is registered **latched** - -- (`cvars.rs`), so a write only stages until - -- `RestartGx`, which is what Apply calls. An - -- earlier comment here said "vsync changes live" - -- — it cannot, and that mismatch is why the - -- setting came back on after a relaunch. - self.deferred = 1 - OptionsRow_OnLoad(self, "gxVSync", "Vertical Sync", + -- Not deferred despite gxRestart: vsync changes + -- live. + BenillaOptionsRow_OnLoad(this, "gxVSync", "Vertical Sync", "OPTION_TOOLTIP_VERTICAL_SYNC") - - + @@ -2894,10 +2015,10 @@ -- the backbuffer), and no Multisampling, which -- misses alpha-tested cutouts. Deferred: a write -- rebuilds the render target. - OptionsRow_OnLoad(self, "renderScale", "Render Scale", + BenillaOptionsRow_OnLoad(this, "renderScale", "Render Scale", "BENILLA_TOOLTIP_RENDER_SCALE") - OptionsSliderRow_Setup(self, 0.5, 2.0, 0.05) - self.deferred = 1 + BenillaOptionsSliderRow_Setup(this, 0.5, 2.0, 0.05) + this.deferred = 1 @@ -2909,610 +2030,13 @@ local info = OptionsFrameSliders[i] local row = getglobal(this:GetName() .. name) if ( info and row ) then - OptionsSliderRow_Setup(row, info.minValue, info.maxValue, + BenillaOptionsSliderRow_Setup(row, info.minValue, info.maxValue, info.valueStep, row.fmt, row.stops) end end - - - - - - - - - - - - - - - OptionsRow_OnLoad(self, "graphicsQuality", - BENILLA_ADVGFX.graphicsQuality, - "BENILLA_TOOLTIP_GRAPHICS_QUALITY") - self.preset = 1 - OptionsDropdownRow_Setup(self, { - { text = BENILLA_ADVGFX.pClassic, value = "Classic" }, - { text = BENILLA_ADVGFX.qLow, value = "Low" }, - { text = BENILLA_ADVGFX.qMedium, value = "Medium" }, - { text = BENILLA_ADVGFX.qHigh, value = "High" }, - { text = BENILLA_ADVGFX.qUltra, value = "Ultra" }, - { text = BENILLA_ADVGFX.qCustom, value = "Custom" }, - }) - - - - - - - - - - OptionsRow_OnLoad(self, "farclip", - BENILLA_ADVGFX.renderDistance, - "BENILLA_TOOLTIP_RENDER_DISTANCE") - OptionsSliderRow_Setup(self, 177, 1497, 60, "yd") - - - - - - - - - -- The preset ladder. This row writes ONE CVar and - -- nothing else: the host's own table - -- (`cvars::LIGHTING_PRESETS`) answers the write by - -- setting the member rows, and re-derives this - -- row's value from them every frame — which is why - -- Custom is an entry the capsule can SHOW but - -- picking it writes nothing anyone keeps. - -- - -- The table is deliberately NOT here. Three other - -- ways reach the same ladder (the console, the - -- native lighting panel, a hand-edited - -- config.toml), and a copy carried by this window - -- would be a copy the other three cannot see. - -- The page's OnUpdate poll is what brings the - -- member rows' new values back onto the screen. - OptionsRow_OnLoad(self, "lightingQuality", - BENILLA_ADVGFX.lightingQuality, - "BENILLA_TOOLTIP_LIGHTING_QUALITY") - OptionsDropdownRow_Setup(self, { - { text = BENILLA_ADVGFX.qOff, value = "Off" }, - { text = BENILLA_ADVGFX.qLow, value = "Low" }, - { text = BENILLA_ADVGFX.qMedium, value = "Medium" }, - { text = BENILLA_ADVGFX.qHigh, value = "High" }, - { text = BENILLA_ADVGFX.qUltra, value = "Ultra" }, - { text = BENILLA_ADVGFX.qCustom, value = "Custom" }, - }) - - - - - - - - - OptionsRow_OnLoad(self, "waterQuality", - BENILLA_ADVGFX.waterQuality, - "BENILLA_TOOLTIP_WATER_QUALITY") - OptionsDropdownRow_Setup(self, { - { text = BENILLA_ADVGFX.waterClassic, value = "0" }, - { text = BENILLA_ADVGFX.waterEnhanced, value = "1" }, - { text = BENILLA_ADVGFX.waterHigh, value = "2" }, - }) - - - - - - - - - - OptionsRow_OnLoad(self, "volumetricFog", BENILLA_ADVGFX.volumetricFog, - "BENILLA_TOOLTIP_VOLUMETRIC_FOG") - OptionsDropdownRow_Setup(self, { - { text = BENILLA_ADVGFX.fogOff, value = "0" }, - { text = BENILLA_ADVGFX.qLow, value = "1" }, - { text = BENILLA_ADVGFX.qHigh, value = "2" }, - }) - - - - - - - - - - OptionsRow_OnLoad(self, "skyQuality", BENILLA_ADVGFX.skyQuality, - "BENILLA_TOOLTIP_SKY_QUALITY") - OptionsDropdownRow_Setup(self, { - { text = BENILLA_ADVGFX.waterClassic, value = "0" }, - { text = BENILLA_ADVGFX.waterEnhanced, value = "1" }, - { text = BENILLA_ADVGFX.waterHigh, value = "2" }, - }) - - - - - - - - - - OptionsRow_OnLoad(self, "bloom", BENILLA_ADVGFX.bloom, - "BENILLA_TOOLTIP_BLOOM") - OptionsDropdownRow_Setup(self, { - { text = BENILLA_ADVGFX.fogOff, value = "0" }, - { text = BENILLA_ADVGFX.qLow, value = "1" }, - { text = BENILLA_ADVGFX.qHigh, value = "2" }, - }) - - - - - - - - - - OptionsRow_OnLoad(self, "sunShafts", BENILLA_ADVGFX.sunShafts, - "BENILLA_TOOLTIP_SUN_SHAFTS") - - - - - - - - - - OptionsRow_OnLoad(self, "colorGrading", BENILLA_ADVGFX.colorGrading, - "BENILLA_TOOLTIP_COLOR_GRADING") - - - - - - - - - - OptionsRow_OnLoad(self, "characterShadows", - BENILLA_ADVGFX.characterShadows, - "BENILLA_TOOLTIP_CHARACTER_SHADOWS") - - - - - - - - - OptionsRow_OnLoad(self, "worldShadows", - BENILLA_ADVGFX.worldShadows, - "BENILLA_TOOLTIP_WORLD_SHADOWS") - - - - - - - - - -- Realtime-shadow render distance (yd): the cascade - -- range + caster reach. 40-200, matching the CVar's - -- own clamp (SHADOW_DISTANCE_RANGE). DEFERRED to - -- Apply so a drag doesn't re-fit the cascade + recollect - -- casters on every tick (one rebuild on commit instead). - OptionsRow_OnLoad(self, "shadowDistance", - BENILLA_ADVGFX.shadowDistance, - "BENILLA_TOOLTIP_SHADOW_DISTANCE") - -- `"yd"`, not `"yards"`: the value is already a - -- distance in yards, where the format beside it - -- multiplies a FACTOR by the 15 yd camera base. - -- This row rode the wrong one from the day it was - -- seated and printed "1200 yd" for an 80 yd - -- cascade. - OptionsSliderRow_Setup(self, 40, 200, 10, "yd") - self.deferred = 1 - - - - - - - - - -- The three stops the CVar's own snap accepts - -- (`shadow_core::SHADOW_MAP_SIZES`): a dropdown - -- rather than a slider because an off-ladder value - -- is not a weaker setting, it is one the renderer - -- rounds UP into a bigger and slower map than the - -- one that was asked for. The entry texts are the - -- numbers themselves — nothing to translate. - OptionsRow_OnLoad(self, "shadowMapSize", - BENILLA_ADVGFX.shadowResolution, - "BENILLA_TOOLTIP_SHADOW_RESOLUTION") - OptionsDropdownRow_Setup(self, { - { text = "1024", value = "1024" }, - { text = "2048", value = "2048" }, - { text = "4096", value = "4096" }, - }) - - - - - - - - - -- 0..1, the CVar's own clamp, and 0 is the FAITHFUL - -- null rather than a floor: every consumer guards - -- on it, so the left end of this groove is the - -- night the client rendered before the moon lane - -- existed. - OptionsRow_OnLoad(self, "moonShadowStrength", - BENILLA_ADVGFX.moonShadows, - "BENILLA_TOOLTIP_MOON_SHADOWS") - OptionsSliderRow_Setup(self, 0, 1, 0.05) - - - - - - - - - OptionsRow_OnLoad(self, "interiorLight", - BENILLA_ADVGFX.interiorLight, - "BENILLA_TOOLTIP_INTERIOR_LIGHT") - - - - - - - - - OptionsRow_OnLoad(self, "interiorShadows", - BENILLA_ADVGFX.interiorShadows, - "BENILLA_TOOLTIP_INTERIOR_SHADOWS") - - - - - - - - - OptionsRow_OnLoad(self, "exteriorShadows", - BENILLA_ADVGFX.exteriorShadows, - "BENILLA_TOOLTIP_EXTERIOR_SHADOWS") - - - - - - - - - - OptionsRow_OnLoad(self, "torchTerrainShadows", - BENILLA_ADVGFX.torchTerrainShadows, - "BENILLA_TOOLTIP_TORCH_TERRAIN_SHADOWS") - - - - - - - - - -- 0.5..3, the CVar's own clamp verbatim: it is a - -- SCALE on the PCF tap radius at a contact, so the - -- readout is a percentage of the shipped radius - -- and 100% is what the lane was tuned at. - OptionsRow_OnLoad(self, "interiorShadowSoft", - BENILLA_ADVGFX.torchSoft, - "BENILLA_TOOLTIP_TORCH_SOFT") - OptionsSliderRow_Setup(self, 0.5, 3, 0.1) - - - - - - - - - -- Full 0..4 registry range, in five-percent steps. - OptionsRow_OnLoad(self, "fireLightGain", - BENILLA_ADVGFX.fireLight, - "BENILLA_TOOLTIP_FIRE_LIGHT") - OptionsSliderRow_Setup(self, 0, 4, 0.05) - - - - - - - - - -- 0..2, the CVar's own clamp verbatim: the - -- amplitudes are authored at 100%, and 200% is the - -- deliberate over-drive for judging the shape. - OptionsRow_OnLoad(self, "fireFlicker", - BENILLA_ADVGFX.fireFlicker, - "BENILLA_TOOLTIP_FIRE_FLICKER") - OptionsSliderRow_Setup(self, 0, 2, 0.05) - - - - - - - - - -- Full 0..4 registry range, in five-percent steps. - OptionsRow_OnLoad(self, "spellLightGain", - BENILLA_ADVGFX.spellLights, - "BENILLA_TOOLTIP_SPELL_LIGHTS") - OptionsSliderRow_Setup(self, 0, 4, 0.05) - - - - - - - - - OptionsRow_OnLoad(self, "lavaLightGain", - BENILLA_ADVGFX.lavaGlow, - "BENILLA_TOOLTIP_LAVA_GLOW") - OptionsSliderRow_Setup(self, 0, 4, 0.05) - - - - - - - - - -- 0.2..1.5, the CVar's own clamp verbatim: the - -- floor is 0.2 rather than 0 because a true 0 is - -- indistinguishable from a broken light pack, and - -- the "off" a player wants is the reference's own - -- night at gain 1. - -- - -- The readout is `darkness` — travel read from the - -- right — because the stored unit is a GAIN while - -- the row is named for the darkness: left is - -- darker, and this is what makes the number say so - -- too. The store keeps the gain, untouched. - OptionsRow_OnLoad(self, "nightGain", - BENILLA_ADVGFX.nightDarkness, - "BENILLA_TOOLTIP_NIGHT_DARKNESS") - OptionsSliderRow_Setup(self, 0.2, 1.5, 0.05, "darkness") - - - - - - - - - -- The room lane's own dim dial, same clamp and same - -- backwards readout as the night one above it. - OptionsRow_OnLoad(self, "interiorGain", - BENILLA_ADVGFX.interiorDarkness, - "BENILLA_TOOLTIP_INTERIOR_DARKNESS") - OptionsSliderRow_Setup(self, 0.2, 1.5, 0.05, "darkness") - - - - - - - - - - OptionsRow_OnLoad(self, "skyDither", - BENILLA_ADVGFX.skyDither, - "BENILLA_TOOLTIP_SKY_DITHER") - - - - - - - - - - OptionsRow_OnLoad(self, "fogModel", - BENILLA_ADVGFX.fogModel, - "BENILLA_TOOLTIP_FOG_MODEL") - - - - - - - - - - OptionsRow_OnLoad(self, "rainSurfaces", - BENILLA_ADVGFX.rainSurfaces, - "BENILLA_TOOLTIP_RAIN_SURFACES") - - - - - - - - - - OptionsRow_OnLoad(self, "foliageWind", - BENILLA_ADVGFX.foliageWind, - "BENILLA_TOOLTIP_FOLIAGE_WIND") - OptionsDropdownRow_Setup(self, { - { text = BENILLA_ADVGFX.qOff, value = "0" }, - { text = BENILLA_ADVGFX.windGrass, value = "1" }, - { text = BENILLA_ADVGFX.windTrees, value = "2" }, - }) - - - - - - - - - - OptionsRow_OnLoad(self, "foliageWindStrength", - BENILLA_ADVGFX.foliageWindStrength, - "BENILLA_TOOLTIP_FOLIAGE_WIND_STRENGTH") - OptionsSliderRow_Setup(self, 0.25, 3, 0.25) - - - - - - - - - - OptionsRow_OnLoad(self, "ambientOcclusion", BENILLA_ADVGFX.ambientOcclusion, - "BENILLA_TOOLTIP_AMBIENT_OCCLUSION") - OptionsDropdownRow_Setup(self, { - { text = BENILLA_ADVGFX.fogOff, value = "0" }, - { text = BENILLA_ADVGFX.qLow, value = "1" }, - { text = BENILLA_ADVGFX.qHigh, value = "2" }, - }) - - - - - - - - - - OptionsRow_OnLoad(self, "lampFog", BENILLA_ADVGFX.lampFog, - "BENILLA_TOOLTIP_LAMP_FOG") - OptionsDropdownRow_Setup(self, { - { text = BENILLA_ADVGFX.fogOff, value = "0" }, - { text = BENILLA_ADVGFX.qLow, value = "1" }, - { text = BENILLA_ADVGFX.qHigh, value = "2" }, - }) - - - - - - - - - - OptionsRow_OnLoad(self, "daylightWindowSplit", - BENILLA_ADVGFX.daylightWindowSplit, - "BENILLA_TOOLTIP_DAYLIGHT_WINDOW_SPLIT") - - - - - - - - - - OptionsRow_OnLoad(self, "zoneSkyboxes", - BENILLA_ADVGFX.zoneSkyboxes, - "BENILLA_TOOLTIP_ZONE_SKYBOXES") - - - - - - - - - - OptionsRow_OnLoad(self, "volumetricLight", BENILLA_ADVGFX.volumetricLight, - "BENILLA_TOOLTIP_VOLUMETRIC_LIGHT") - OptionsDropdownRow_Setup(self, { - { text = BENILLA_ADVGFX.fogOff, value = "0" }, - { text = BENILLA_ADVGFX.qMedium, value = "1" }, - { text = BENILLA_ADVGFX.qHigh, value = "2" }, - }) - - - - - - - - - - OptionsRow_OnLoad(self, "volumetricLightStrength", - BENILLA_ADVGFX.volumetricLightStrength, - "BENILLA_TOOLTIP_VOLUMETRIC_LIGHT_STRENGTH") - OptionsSliderRow_Setup(self, 0, 2, 0.25) - - - - - - - - - - OptionsRow_OnLoad(self, "moonLight", BENILLA_ADVGFX.moonLight, - "BENILLA_TOOLTIP_MOONLIGHT") - OptionsSliderRow_Setup(self, 0, 2, 0.25) - - - - - - AdvGfx_OnUpdate(this, arg1) - - @@ -3520,227 +2044,227 @@ - + - OptionsGlobalRow_OnLoad(self, "SHOW_COMBAT_TEXT", + BenillaOptionsGlobalRow_OnLoad(this, "SHOW_COMBAT_TEXT", "Enable Floating Combat Text", "OPTION_TOOLTIP_SHOW_COMBAT_TEXT") - self.applyFunc = "CombatText_UpdateOrLoad" + this.applyFunc = "BenillaCombatText_UpdateOrLoad" - + - OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_FLOAT_MODE", + BenillaOptionsGlobalRow_OnLoad(this, "COMBAT_TEXT_FLOAT_MODE", "Combat Text Float Mode", "OPTION_TOOLTIP_COMBAT_TEXT_MODE", 1) - OptionsDropdownRow_Setup(self, { + BenillaOptionsDropdownRow_Setup(this, { { text = "Scroll Up", value = "1" }, { text = "Scroll Down", value = "2" }, { text = "Arc", value = "3" }, }) - self.parentRow = "RowCombatText" - self.applyFunc = "CombatText_UpdateOrLoad" + this.parentRow = "RowCombatText" + this.applyFunc = "BenillaCombatText_UpdateOrLoad" - + - OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_LOW_HEALTH_MANA", + BenillaOptionsGlobalRow_OnLoad(this, "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" + this.parentRow = "RowCombatText" + this.applyFunc = "BenillaCombatText_UpdateOrLoad" - + - OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_AURAS", + BenillaOptionsGlobalRow_OnLoad(this, "COMBAT_TEXT_SHOW_AURAS", "Show Auras", "OPTION_TOOLTIP_COMBAT_TEXT_SHOW_AURAS", 1) - self.parentRow = "RowCombatText" - self.applyFunc = "CombatText_UpdateOrLoad" + this.parentRow = "RowCombatText" + this.applyFunc = "BenillaCombatText_UpdateOrLoad" - + - OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_AURA_FADE", + BenillaOptionsGlobalRow_OnLoad(this, "COMBAT_TEXT_SHOW_AURA_FADE", "Show Fading Auras", "OPTION_TOOLTIP_COMBAT_TEXT_SHOW_AURA_FADE", 1) - self.parentRow = "RowCombatText" - self.applyFunc = "CombatText_UpdateOrLoad" + this.parentRow = "RowCombatText" + this.applyFunc = "BenillaCombatText_UpdateOrLoad" - + - OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_COMBAT_STATE", + BenillaOptionsGlobalRow_OnLoad(this, "COMBAT_TEXT_SHOW_COMBAT_STATE", "Show Combat State", "OPTION_TOOLTIP_COMBAT_TEXT_SHOW_COMBAT_STATE", 1) - self.parentRow = "RowCombatText" - self.applyFunc = "CombatText_UpdateOrLoad" + this.parentRow = "RowCombatText" + this.applyFunc = "BenillaCombatText_UpdateOrLoad" - + - OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_DODGE_PARRY_MISS", + BenillaOptionsGlobalRow_OnLoad(this, "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" + this.parentRow = "RowCombatText" + this.applyFunc = "BenillaCombatText_UpdateOrLoad" - + - OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_RESISTANCES", + BenillaOptionsGlobalRow_OnLoad(this, "COMBAT_TEXT_SHOW_RESISTANCES", "Show Damage Reduction", "OPTION_TOOLTIP_COMBAT_TEXT_SHOW_RESISTANCES", 1) - self.parentRow = "RowCombatText" - self.applyFunc = "CombatText_UpdateOrLoad" + this.parentRow = "RowCombatText" + this.applyFunc = "BenillaCombatText_UpdateOrLoad" - + - OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_REPUTATION", + BenillaOptionsGlobalRow_OnLoad(this, "COMBAT_TEXT_SHOW_REPUTATION", "Show Reputation", "OPTION_TOOLTIP_COMBAT_TEXT_SHOW_REPUTATION", 1) - self.parentRow = "RowCombatText" - self.applyFunc = "CombatText_UpdateOrLoad" + this.parentRow = "RowCombatText" + this.applyFunc = "BenillaCombatText_UpdateOrLoad" - + - OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_REACTIVES", + BenillaOptionsGlobalRow_OnLoad(this, "COMBAT_TEXT_SHOW_REACTIVES", "Show Reactive Spells and Abilities", "OPTION_TOOLTIP_COMBAT_TEXT_SHOW_REACTIVES", 1) - self.parentRow = "RowCombatText" - self.applyFunc = "CombatText_UpdateOrLoad" + this.parentRow = "RowCombatText" + this.applyFunc = "BenillaCombatText_UpdateOrLoad" - + - OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_FRIENDLY_NAMES", + BenillaOptionsGlobalRow_OnLoad(this, "COMBAT_TEXT_SHOW_FRIENDLY_NAMES", "Show Friendly Healer Names", "OPTION_TOOLTIP_COMBAT_TEXT_SHOW_FRIENDLY_NAMES", 1) - self.parentRow = "RowCombatText" - self.applyFunc = "CombatText_UpdateOrLoad" + this.parentRow = "RowCombatText" + this.applyFunc = "BenillaCombatText_UpdateOrLoad" - + - OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_COMBO_POINTS", + BenillaOptionsGlobalRow_OnLoad(this, "COMBAT_TEXT_SHOW_COMBO_POINTS", "Show Combo Points", "OPTION_TOOLTIP_COMBAT_TEXT_SHOW_COMBO_POINTS", 1) - self.parentRow = "RowCombatText" - self.applyFunc = "CombatText_UpdateOrLoad" + this.parentRow = "RowCombatText" + this.applyFunc = "BenillaCombatText_UpdateOrLoad" - + - OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_MANA", + BenillaOptionsGlobalRow_OnLoad(this, "COMBAT_TEXT_SHOW_MANA", "Show Energy Gains", "OPTION_TOOLTIP_COMBAT_TEXT_SHOW_MANA", 1) - self.parentRow = "RowCombatText" - self.applyFunc = "CombatText_UpdateOrLoad" + this.parentRow = "RowCombatText" + this.applyFunc = "BenillaCombatText_UpdateOrLoad" - + - OptionsGlobalRow_OnLoad(self, "COMBAT_TEXT_SHOW_HONOR_GAINED", + BenillaOptionsGlobalRow_OnLoad(this, "COMBAT_TEXT_SHOW_HONOR_GAINED", "Show Honor Gained", "OPTION_TOOLTIP_COMBAT_TEXT_SHOW_HONOR_GAINED", 1) - self.parentRow = "RowCombatText" - self.applyFunc = "CombatText_UpdateOrLoad" + this.parentRow = "RowCombatText" + this.applyFunc = "BenillaCombatText_UpdateOrLoad" - + - OptionsRow_OnLoad(self, "CombatDamage", "Show Target Damage", + BenillaOptionsRow_OnLoad(this, "CombatDamage", "Show Target Damage", "OPTION_TOOLTIP_SHOW_DAMAGE") - + - OptionsRow_OnLoad(self, "CombatLogPeriodicSpells", "Periodic Damage", + BenillaOptionsRow_OnLoad(this, "CombatLogPeriodicSpells", "Periodic Damage", "OPTION_TOOLTIP_LOG_PERIODIC_EFFECTS", 1) - self.parentRow = "RowShowDamage" + this.parentRow = "RowShowDamage" - + - OptionsRow_OnLoad(self, "PetMeleeDamage", "Pet Damage", + BenillaOptionsRow_OnLoad(this, "PetMeleeDamage", "Pet Damage", "OPTION_TOOLTIP_SHOW_PET_MELEE_DAMAGE", 1) - self.parentRow = "RowShowDamage" - self.partner = { cvar = "PetSpellDamage" } + this.parentRow = "RowShowDamage" + this.partner = { cvar = "PetSpellDamage" } @@ -3754,13 +2278,13 @@ - + - OptionsFuncRow_OnLoad(self, + BenillaOptionsFuncRow_OnLoad(this, function() return SHOW_MULTI_ACTIONBAR_1 end, function(value) local on @@ -3774,13 +2298,13 @@ "0", "Show Bottom Left ActionBar", "OPTION_TOOLTIP_SHOW_MULTIBAR1") - + - OptionsFuncRow_OnLoad(self, + BenillaOptionsFuncRow_OnLoad(this, function() return SHOW_MULTI_ACTIONBAR_2 end, function(value) local on @@ -3794,13 +2318,13 @@ "0", "Show Bottom Right ActionBar", "OPTION_TOOLTIP_SHOW_MULTIBAR2") - + - OptionsFuncRow_OnLoad(self, + BenillaOptionsFuncRow_OnLoad(this, function() return SHOW_MULTI_ACTIONBAR_3 end, function(value) local on @@ -3815,13 +2339,13 @@ - + - OptionsFuncRow_OnLoad(self, + BenillaOptionsFuncRow_OnLoad(this, function() return SHOW_MULTI_ACTIONBAR_4 end, function(value) local on @@ -3835,25 +2359,25 @@ "0", "Show Right ActionBar 2", "OPTION_TOOLTIP_SHOW_MULTIBAR4", 1) - + - OptionsGlobalRow_OnLoad(self, "ALWAYS_SHOW_MULTIBARS", + BenillaOptionsGlobalRow_OnLoad(this, "ALWAYS_SHOW_MULTIBARS", "Always Show ActionBars", "OPTION_TOOLTIP_ALWAYS_SHOW_MULTIBARS") -- UIOptionsFrame.xml:680-683's click arm. - self.applyFunc = "MultiActionBar_UpdateGridVisibility" + this.applyFunc = "MultiActionBar_UpdateGridVisibility" - + - OptionsGlobalRow_OnLoad(self, "LOCK_ACTIONBAR", + BenillaOptionsGlobalRow_OnLoad(this, "LOCK_ACTIONBAR", "Lock ActionBars", "OPTION_TOOLTIP_LOCK_ACTIONBAR") @@ -3868,153 +2392,153 @@ - + - OptionsRow_OnLoad(self, "UberTooltips", "Enhanced Tooltips", + BenillaOptionsRow_OnLoad(this, "UberTooltips", "Enhanced Tooltips", "OPTION_TOOLTIP_USE_UBERTOOLTIPS") - + - OptionsRow_OnLoad(self, "statusBarText", + BenillaOptionsRow_OnLoad(this, "statusBarText", "Status Bar Text", "OPTION_TOOLTIP_STATUS_BAR") - self.cvarEvent = "STATUS_BAR_TEXT" + this.cvarEvent = "STATUS_BAR_TEXT" - + - OptionsGlobalRow_OnLoad(self, "SHOW_TARGET_OF_TARGET", + BenillaOptionsGlobalRow_OnLoad(this, "SHOW_TARGET_OF_TARGET", "Show Target of Target", "OPTION_TOOLTIP_SHOW_TARGET_OF_TARGET") - self.applyFunc = "TargetofTarget_Update" + this.applyFunc = "TargetofTarget_Update" - + - OptionsGlobalRow_OnLoad(self, "SHOW_TARGET_OF_TARGET_STATE", + BenillaOptionsGlobalRow_OnLoad(this, "SHOW_TARGET_OF_TARGET_STATE", "Show When", "OPTION_TOOLTIP_TARGETOFTARGET5", 1) - OptionsDropdownRow_Setup(self, { + BenillaOptionsDropdownRow_Setup(this, { { 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" + this.applyFunc = "TargetofTarget_Update" - + - OptionsFuncRow_OnLoad(self, ShowingCloak, ShowCloak, "1", + BenillaOptionsFuncRow_OnLoad(this, ShowingCloak, ShowCloak, "1", "Show Cloak", "OPTION_TOOLTIP_SHOW_CLOAK") - + - OptionsFuncRow_OnLoad(self, ShowingHelm, ShowHelm, "1", + BenillaOptionsFuncRow_OnLoad(this, ShowingHelm, ShowHelm, "1", "Show Helm", "OPTION_TOOLTIP_SHOW_HELM") - + - OptionsGlobalRow_OnLoad(self, "QUEST_FADING_DISABLE", + BenillaOptionsGlobalRow_OnLoad(this, "QUEST_FADING_DISABLE", "Instant Quest Text", "OPTION_TOOLTIP_SHOW_QUEST_FADING") - + - OptionsGlobalRow_OnLoad(self, "SHOW_BUFF_DURATIONS", + BenillaOptionsGlobalRow_OnLoad(this, "SHOW_BUFF_DURATIONS", "Buff Durations", "OPTION_TOOLTIP_SHOW_BUFF_DURATION") - self.applyFunc = "BuffButtons_UpdatePositions" + this.applyFunc = "BuffButtons_UpdatePositions" - + - OptionsGlobalRow_OnLoad(self, "AUTO_QUEST_WATCH", + BenillaOptionsGlobalRow_OnLoad(this, "AUTO_QUEST_WATCH", "Automatic Quest Tracking", "OPTION_TOOLTIP_AUTO_QUEST_WATCH") - + - OptionsRow_OnLoad(self, "profanityFilter", "Profanity Filter", + BenillaOptionsRow_OnLoad(this, "profanityFilter", "Profanity Filter", "OPTION_TOOLTIP_PROFANITY_FILTER") - + - OptionsFuncRow_OnLoad(self, TutorialsEnabled, + BenillaOptionsFuncRow_OnLoad(this, TutorialsEnabled, BenillaOptionsFrame_SetTutorialsEnabled, "1", "Show Tutorials", "OPTION_TOOLTIP_SHOW_TUTORIALS") - + - OptionsRow_OnLoad(self, "showGameTips", + BenillaOptionsRow_OnLoad(this, "showGameTips", "Show Loading Screen Tips", "OPTION_TOOLTIP_SHOW_TIPOFTHEDAY") - + - OptionsGlobalRow_OnLoad(self, "SHOW_NEWBIE_TIPS", + BenillaOptionsGlobalRow_OnLoad(this, "SHOW_NEWBIE_TIPS", "Show Detailed Tooltips", "OPTION_TOOLTIP_SHOW_NEWBIE_TIPS") @@ -4028,19 +2552,19 @@ - + - OptionsRow_OnLoad(self, "guildMemberNotify", + BenillaOptionsRow_OnLoad(this, "guildMemberNotify", "Guild Member Alert", "OPTION_TOOLTIP_GUILDMEMBER_ALERT") - + @@ -4048,41 +2572,41 @@ - OptionsGlobalRow_OnLoad(self, "REMOVE_CHAT_DELAY", + BenillaOptionsGlobalRow_OnLoad(this, "REMOVE_CHAT_DELAY", "Remove Chat Hover Delay", "OPTION_TOOLTIP_REMOVE_CHAT_DELAY") - self.applyFunc = "ChatFrame_ApplyMouseOverDelay" + this.applyFunc = "BenillaChatFrame_ApplyMouseOverDelay" - + - OptionsRow_OnLoad(self, "ChatBubbles", + BenillaOptionsRow_OnLoad(this, "ChatBubbles", "Show Chat Bubbles", "OPTION_TOOLTIP_CHAT_BUBBLES") - + - OptionsRow_OnLoad(self, "showLootSpam", + BenillaOptionsRow_OnLoad(this, "showLootSpam", "Detailed Loot Information", "OPTION_TOOLTIP_SHOW_LOOT_SPAM") - + - OptionsRow_OnLoad(self, "ChatBubblesParty", + BenillaOptionsRow_OnLoad(this, "ChatBubblesParty", "Show Party Chat Bubbles", "OPTION_TOOLTIP_PARTY_CHAT_BUBBLES") @@ -4090,78 +2614,91 @@ and writes it (l.337). The filter drops a SpamMessages.dbc match in every chat type but CHAT_MSG_FILTERED (`0x49aad2`). --> - + - OptionsRow_OnLoad(self, "spamFilter", "Disable Spam Filter", + BenillaOptionsRow_OnLoad(this, "spamFilter", "Disable Spam Filter", "OPTION_TOOLTIP_DISABLE_SPAM_FILTER") - self.invert = 1 + this.invert = 1 - + - + - OptionsRow_OnLoad(self, "nameplateShowEnemies", - "Enemy Name Plates") + BenillaOptionsFuncRow_OnLoad(this, BenillaOptionsFrame_GetEnemyPlates, + BenillaOptionsFrame_SetEnemyPlates, "0", "Enemy Name Plates") - + - OptionsRow_OnLoad(self, "nameplateShowFriends", - "Friendly Name Plates") + BenillaOptionsFuncRow_OnLoad(this, BenillaOptionsFrame_GetFriendlyPlates, + BenillaOptionsFrame_SetFriendlyPlates, "0", "Friendly Name Plates") - + - OptionsRow_OnLoad(self, "UnitNamePlayer", "Player Names", + BenillaOptionsRow_OnLoad(this, "UnitNamePlayer", "Player Names", "OPTION_TOOLTIP_SHOW_PLAYER_NAMES") - + - OptionsRow_OnLoad(self, "UnitNamePlayerGuild", "Player Guild Names", + BenillaOptionsRow_OnLoad(this, "UnitNamePlayerGuild", "Player Guild Names", "OPTION_TOOLTIP_SHOW_GUILD_NAMES", 1) - self.parentRow = "RowPlayerNames" + this.parentRow = "RowPlayerNames" - + + - OptionsRow_OnLoad(self, "UnitNameNPC", "NPC Names", + + BenillaOptionsRow_OnLoad(this, "UnitNamePlayerPVPTitle", "Player Titles", + "OPTION_TOOLTIP_SHOW_PLAYER_TITLES", 1) + this.parentRow = "RowPlayerNames" + + + + + + + + BenillaOptionsRow_OnLoad(this, "UnitNameNPC", "NPC Names", "OPTION_TOOLTIP_SHOW_NPC_NAMES") - + - OptionsRow_OnLoad(self, "UnitNameOwn", "Show Own Name", + BenillaOptionsRow_OnLoad(this, "UnitNameOwn", "Show Own Name", "OPTION_TOOLTIP_SHOW_OWN_NAME") @@ -4207,10 +2744,10 @@ - KeyBindings_CharacterToggle(this) + BenillaKeyBindings_CharacterToggle(this) GameTooltip:SetOwner(this, "ANCHOR_RIGHT") - GameTooltip:SetText(KeyBindings_String("CHARACTER_SPECIFIC_KEYBINDING_TOOLTIP", + GameTooltip:SetText(BenillaKeyBindings_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) GameTooltip:Hide() @@ -4220,126 +2757,127 @@ getglobal(this:GetName() .. "Label"):SetText( - KeyBindings_String("CHARACTER_SPECIFIC_KEYBINDINGS", "Character Specific Key Bindings")) + BenillaKeyBindings_String("CHARACTER_SPECIFIC_KEYBINDINGS", "Character Specific Key Bindings")) - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + it: inside the body, the scroll child, link order + draws, not level. --> @@ -4350,100 +2888,98 @@ ScrollFrame_OnLoad() - - FauxScrollFrame_OnVerticalScroll(KEYBINDINGS_ROW_HEIGHT, KeyBindingsPage_Update) + FauxScrollFrame_OnVerticalScroll(BENILLA_KEYBINDINGS_ROW_HEIGHT, BenillaKeyBindingsPage_Update) - if not KeyBindingsPage.selected then + if BenillaKeyBindingsPage.selected then + BenillaKeyBindings_OnMouseWheel(arg1) + else ScrollFrameTemplate_OnMouseWheel(arg1) end - + - if not KeyBindingsPage.selected then + if BenillaKeyBindingsPage.selected then + BenillaKeyBindings_OnMouseWheel(arg1) + else BenillaFauxScrollFrame_OnMouseWheel(getglobal(this:GetName() .. "ScrollFrame"), arg1) end + BenillaKeyBindings_OnKeyDown(arg1) - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - @@ -4562,16 +3097,27 @@ BenillaOptionsFrame_UpdateScale() + BenillaOptionsTab_FitWidth(BenillaOptionsFrameGameTab) + BenillaOptionsTab_FitWidth(BenillaOptionsFrameAddOnsTab) BenillaOptionsFrame_SelectCategory(this.selectedCategory or "Controls") if UpdateMicroButtons then UpdateMicroButtons() end - + + + this:EnableKeyboard(false) + this:EnableMouseWheel(false) + + BenillaKeyBindings_OnKeyDown() + BenillaKeyBindings_OnKeyDown(arg1) + BenillaKeyBindings_OnMouseWheel(arg1) + BenillaOptionsFrameSearchBox:SetText("") - OptionsPage_DiscardPending() - KeyBindings_SetSelected(nil) - KeyBindings_Output("") + BenillaOptionsPage_DiscardPending() + BenillaKeyBindings_SetSelected(nil) + BenillaKeyBindings_Output("") if UpdateMicroButtons then UpdateMicroButtons() end diff --git a/crates/benilla-app/assets/ui/ScriptLogFrame.xml b/crates/benilla-app/assets/ui/ScriptLogFrame.xml index 375c1dcc..c11b5f06 100644 --- a/crates/benilla-app/assets/ui/ScriptLogFrame.xml +++ b/crates/benilla-app/assets/ui/ScriptLogFrame.xml @@ -1,16 +1,20 @@ diff --git a/crates/benilla-app/assets/ui/ScrollTemplates.xml b/crates/benilla-app/assets/ui/ScrollTemplates.xml index 0a7cfd07..8fa7c5fe 100644 --- a/crates/benilla-app/assets/ui/ScrollTemplates.xml +++ b/crates/benilla-app/assets/ui/ScrollTemplates.xml @@ -3,8 +3,8 @@ Benilla's scroll parts: a `Slider` bar with its arrow helpers, an optional trough, and a real-scroll kit that pans a `` child whose height is known only after layout. Faux lists use the stock `FauxScrollFrameTemplate`; this file declares only `Benilla` names. - A real-scroll bar overrides the template's OnValueChanged on its instance, which wins - because the loader runs every `` block in order. + The bar template carries the real-scroll OnValueChanged itself, as the reference's + `UIPanelScrollBarTemplate` does (UIPanelTemplates.xml:156-158); an instance adds nothing. -->