diff --git a/crates/benilla-app/assets/ui/OptionsFrame.xml b/crates/benilla-app/assets/ui/OptionsFrame.xml
index 1431e746..7bbd9a60 100644
--- a/crates/benilla-app/assets/ui/OptionsFrame.xml
+++ b/crates/benilla-app/assets/ui/OptionsFrame.xml
@@ -545,6 +545,19 @@
torchShadowStrength = "Torch Shadow Darkness",
everyFrame = "Every frame",
hz = "%d per second",
+ -- GFX (interior rig): the ten rows of the interior lighting system a player
+ -- could not reach. Named for what they DO to a room, not for the quantity they
+ -- scale, since the quantity is the renderer's word and the room is the player's.
+ interiorAmbient = "Interior Ambient Light",
+ interiorDaylight = "Indoor Daylight",
+ interiorFill = "Interior Bounce Light",
+ interiorBakeFloor = "Unlit Room Floor",
+ interiorExposure = "Interior Light Budget",
+ interiorAttenScale = "Interior Light Reach",
+ interiorRoomGate = "Lights Stay in Their Room",
+ interiorShadowCasters = "Indoor Shadow Maps",
+ interiorShadowDynamic = "Moving Shadows Indoors",
+ interiorShadowEntityRate = "Moving Shadow Updates",
interiorLight = "Dynamic Interior Lighting",
interiorShadows = "Indoor Torch Shadows",
exteriorShadows = "Outdoor Torch Shadows",
@@ -709,6 +722,70 @@
.. "The default leaves some light standing, because this renderer has no "
.. "bounce light to fill a shadow back in - at full strength the shadows "
.. "read as scars cut into the floor rather than as shadows.",
+ INTERIOR_AMBIENT =
+ "The light a room has before any lamp, candle or window is counted - the "
+ .. "floor under everything else indoors.\n\n"
+ .. "At 0 a corner no light reaches is truly black. Raising it lifts every "
+ .. "indoor surface at once and flattens the room, so a little goes a long "
+ .. "way. Interior Darkness scales the result of all of this; this sets "
+ .. "what it scales.",
+ INDOOR_DAYLIGHT =
+ "Daylight for rooms the renderer cannot find a doorway into.\n\n"
+ .. "Some buildings describe no door, window or opening anywhere in their "
+ .. "art - the Goldshire inn's entry is one - so by day they stay as dark "
+ .. "as a cellar. This lifts those rooms while the sun is up, and is "
+ .. "exactly nothing at night, so the night look never moves. At 0 only "
+ .. "rooms with a findable opening get daylight.",
+ INTERIOR_BOUNCE =
+ "How much light each indoor flame throws back off the walls and floor "
+ .. "around it, standing in for light bouncing around a room.\n\n"
+ .. "Higher spreads a torch's glow further into the room and softens the "
+ .. "contrast between lit and unlit; 0 leaves only the direct light.",
+ UNLIT_ROOM_FLOOR =
+ "How much of a room's painted-in lighting survives where no lamp or "
+ .. "candle reaches it.\n\n"
+ .. "The original client draws every room at the lighting its artists "
+ .. "painted in. This one lets the actual lamps decide instead, which "
+ .. "leaves a room nobody lit rendering black - something the original "
+ .. "cannot do. This keeps a share of the painted lighting in exactly "
+ .. "those rooms. At 0 they go black.",
+ INTERIOR_LIGHT_BUDGET =
+ "How much light indoor sources are allowed to add before the result is "
+ .. "rolled back into range.\n\n"
+ .. "Higher makes lit rooms brighter and more contrasty; lower makes them "
+ .. "flatter and dimmer. This is the main dial for how dramatic indoor "
+ .. "lighting looks.",
+ INTERIOR_LIGHT_REACH =
+ "How far each indoor flame's light carries past the distance its artist "
+ .. "marked.\n\n"
+ .. "Those marks are where FULL brightness ends, not where light stops, so "
+ .. "at 100% a torch draws a hard-edged disc with blackness just beyond it. "
+ .. "Above that the light tails off smoothly instead. At 0 the limit is "
+ .. "ignored entirely and every indoor light reaches the whole room.",
+ LIGHTS_STAY_IN_THEIR_ROOM =
+ "Keeps an indoor light inside the rooms it belongs to, instead of lighting "
+ .. "anything nearby.\n\n"
+ .. "With this off, an inn's ground-floor candles light its cellar through "
+ .. "the floor. With it on, a room no light belongs to is left to the "
+ .. "settings above - so if a room looks wrongly dark, turning this off for "
+ .. "a moment tells you whether this is why.",
+ INDOOR_SHADOW_MAPS =
+ "How many indoor flames may cast real shadows at once.\n\n"
+ .. "The nearest get them; the rest still light the room, they just do not "
+ .. "cast. Each one costs memory and drawing time whether or not anything "
+ .. "is moving near it.",
+ MOVING_SHADOWS_INDOORS =
+ "How many of those flames also cast shadows from things that MOVE - you, "
+ .. "other players, creatures.\n\n"
+ .. "The nearest are promoted. Lower is cheaper and leaves moving "
+ .. "characters unshadowed by the more distant fires in a room.",
+ MOVING_SHADOW_UPDATES =
+ "How often the moving things casting indoor shadows are re-gathered, in "
+ .. "times per second.\n\n"
+ .. "This is the one indoor shadow setting that reliably costs frame time: "
+ .. "the gathering happens once a frame no matter how many maps or how "
+ .. "many flames are set above. Lower first if indoor shadows cost too "
+ .. "much.",
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 "
@@ -851,6 +928,17 @@
torchShadowStrength = "Темнота теней от огня",
everyFrame = "Каждый кадр",
hz = "%d в секунду",
+ -- GFX (interior rig)
+ interiorAmbient = "Общий свет в помещениях",
+ interiorDaylight = "Дневной свет в помещениях",
+ interiorFill = "Отражённый свет в помещениях",
+ interiorBakeFloor = "Освещение комнат без источников",
+ interiorExposure = "Световой бюджет помещений",
+ interiorAttenScale = "Дальность света в помещениях",
+ interiorRoomGate = "Свет не проходит сквозь стены",
+ interiorShadowCasters = "Карты теней в помещениях",
+ interiorShadowDynamic = "Движущиеся тени в помещениях",
+ interiorShadowEntityRate = "Обновление движущихся теней",
interiorLight = "Динамическое освещение помещений",
interiorShadows = "Тени факелов в помещениях",
exteriorShadows = "Тени огней под открытым небом",
@@ -1022,6 +1110,70 @@
.. "По умолчанию часть света остаётся: этому движку нечем подсветить тень "
.. "отражённым светом, и на полной силе тени выглядят как шрамы на полу, "
.. "а не как тени.",
+ INTERIOR_AMBIENT =
+ "Свет, который есть в комнате ещё до всех ламп, свечей и окон — основа "
+ .. "всего освещения в помещении.\n\n"
+ .. "При 0 угол, куда не достаёт свет, по-настоящему чёрный. Увеличение "
+ .. "поднимает сразу все поверхности и делает комнату плоской, поэтому "
+ .. "хватает малого. «Темнота помещений» масштабирует итог; здесь задаётся "
+ .. "то, что она масштабирует.",
+ INDOOR_DAYLIGHT =
+ "Дневной свет для комнат, в которые движок не может найти вход.\n\n"
+ .. "В графике некоторых зданий нет ни двери, ни окна, ни проёма — таков, "
+ .. "например, вход таверны Златоземья, — и днём там темно, как в погребе. "
+ .. "Это подсвечивает такие комнаты, пока светит солнце, и ровно ничего не "
+ .. "делает ночью. При 0 дневной свет получают лишь комнаты с найденным "
+ .. "проёмом.",
+ INTERIOR_BOUNCE =
+ "Сколько света каждое пламя в помещении отбрасывает обратно от стен и "
+ .. "пола вокруг себя — замена отражённому свету.\n\n"
+ .. "Больше — свечение факела уходит дальше вглубь комнаты и смягчает "
+ .. "границу света и тьмы; 0 оставляет только прямой свет.",
+ UNLIT_ROOM_FLOOR =
+ "Сколько нарисованного художниками освещения комнаты сохраняется там, "
+ .. "куда не достаёт ни лампа, ни свеча.\n\n"
+ .. "Оригинальный клиент рисует каждую комнату с тем светом, который "
+ .. "нарисовали художники. Здесь решают сами лампы, и комната, которую "
+ .. "никто не освещает, становится чёрной — чего оригинал не умеет. Это "
+ .. "сохраняет долю нарисованного света именно в таких комнатах. При 0 они "
+ .. "чернеют.",
+ INTERIOR_LIGHT_BUDGET =
+ "Сколько света источникам в помещении позволено добавить, прежде чем "
+ .. "результат мягко возвращается в диапазон.\n\n"
+ .. "Больше — освещённые комнаты ярче и контрастнее; меньше — площе и "
+ .. "тусклее. Это главный регулятор того, насколько выразительно выглядит "
+ .. "свет в помещениях.",
+ INTERIOR_LIGHT_REACH =
+ "Насколько далеко свет каждого пламени в помещении уходит за отметку, "
+ .. "поставленную художником.\n\n"
+ .. "Эти отметки — там, где кончается ПОЛНАЯ яркость, а не сам свет, "
+ .. "поэтому при 100% факел рисует диск с резким краем и чернотой сразу за "
+ .. "ним. Выше — свет плавно сходит на нет. При 0 предел не учитывается "
+ .. "вовсе и свет достаёт до всей комнаты.",
+ LIGHTS_STAY_IN_THEIR_ROOM =
+ "Удерживает свет в тех комнатах, которым он принадлежит, вместо того "
+ .. "чтобы освещать всё поблизости.\n\n"
+ .. "Если выключено, свечи первого этажа таверны освещают подвал сквозь "
+ .. "пол. Если включено, комната без собственных источников остаётся на "
+ .. "настройках выше — поэтому, если комната кажется слишком тёмной, "
+ .. "выключите это на минуту и сразу поймёте, в этом ли дело.",
+ INDOOR_SHADOW_MAPS =
+ "Сколько источников пламени в помещении могут отбрасывать настоящие тени "
+ .. "одновременно.\n\n"
+ .. "Их получают ближайшие; остальные по-прежнему освещают комнату, просто "
+ .. "без теней. Каждая карта стоит памяти и времени отрисовки, даже если "
+ .. "рядом ничего не движется.",
+ MOVING_SHADOWS_INDOORS =
+ "Сколько из этих источников отбрасывают ещё и тени от ДВИЖУЩЕГОСЯ — вас, "
+ .. "других игроков, существ.\n\n"
+ .. "Повышаются ближайшие. Меньше — дешевле, и движущиеся персонажи не "
+ .. "отбрасывают тень от более далёких огней комнаты.",
+ MOVING_SHADOW_UPDATES =
+ "Сколько раз в секунду заново собирается движущееся, отбрасывающее тени "
+ .. "в помещении.\n\n"
+ .. "Это единственная настройка теней в помещении, которая заметно стоит "
+ .. "времени кадра: сбор происходит раз в кадр независимо от числа карт и "
+ .. "источников выше. Понижайте её первой, если тени в помещениях дороги.",
TORCH_SOFT =
"Насколько мягок край тени от огня там, где предмет касается пола. "
.. "Низкое значение — резкий край, высокое — размытый, как от "
@@ -1216,6 +1368,12 @@
"RowShadowFilter", "RowShadowCasterReach",
"RowCharacterShadowRate", "RowWorldShadowRate",
"RowTorchShadowDarkness",
+ -- GFX (interior rig): the ten interior-lighting rows, likewise appended.
+ "RowInteriorExposure", "RowInteriorAmbient", "RowInteriorDaylight",
+ "RowInteriorFill", "RowInteriorAttenScale", "RowInteriorBakeFloor",
+ "RowInteriorRoomGate",
+ "RowInteriorShadowCasters", "RowInteriorShadowDynamic",
+ "RowInteriorShadowEntityRate",
},
-- Guild Names is a child of Player Names (UIOptionsFrame.lua:703-709).
Nameplates = {
@@ -1860,6 +2018,21 @@
GetCVar("worldShadows") ~= "0")
local interior = GetCVar("interiorLight") ~= "0"
OptionsRow_SetEnabled(getglobal(base .. "RowInteriorShadows"), interior)
+ -- GFX (interior rig): every row below shapes what the live-fixture lane draws, so
+ -- the lane's own switch is their master — the same rule `RowInteriorShadows`
+ -- above already follows.
+ for _, rkey in ipairs({"RowInteriorExposure", "RowInteriorAmbient",
+ "RowInteriorDaylight", "RowInteriorFill", "RowInteriorAttenScale",
+ "RowInteriorBakeFloor", "RowInteriorRoomGate"}) do
+ OptionsRow_SetEnabled(getglobal(base .. rkey), interior)
+ end
+ -- The three shadow budgets need the shadows themselves, which already need the
+ -- lane: a tighter master, and the honest one.
+ local indoorShadows = interior and GetCVar("interiorShadows") ~= "0"
+ for _, rkey in ipairs({"RowInteriorShadowCasters", "RowInteriorShadowDynamic",
+ "RowInteriorShadowEntityRate"}) do
+ OptionsRow_SetEnabled(getglobal(base .. rkey), indoorShadows)
+ end
local torch = (interior and GetCVar("interiorShadows") ~= "0")
or GetCVar("exteriorShadows") ~= "0"
OptionsRow_SetEnabled(getglobal(base .. "RowTorchSoft"), torch)
@@ -3552,11 +3725,125 @@
"BENILLA_TOOLTIP_INTERIOR_LIGHT")
-
+
+
+ -- The CVar's own clamp, 0.25..8, and the
+ -- shipped 2.5 lands on a stop. No `fmt`: the value
+ -- IS a multiplier, so the default percent reads
+ -- "250%" and means it.
+ OptionsRow_OnLoad(self, "interiorExposure",
+ BENILLA_ADVGFX.interiorExposure,
+ "BENILLA_TOOLTIP_INTERIOR_LIGHT_BUDGET")
+ OptionsSliderRow_Setup(self, 0.25, 8, 0.25)
+
+
+
+
+
+
+
+
+ -- The groove offers 0..0.1 inside the CVar's
+ -- own 0..1, as `RowRenderScale` offers 50..200%
+ -- inside a 0.25..4 clamp: ambient is a FLOOR under
+ -- every indoor surface, the shipped value is
+ -- 0.015, and past about 0.1 a room is not lit, it
+ -- is fogged. `/console` still reaches the rest.
+ -- "travel", because the number has no unit a
+ -- player could read — the dial's own position is
+ -- the honest readout.
+ OptionsRow_OnLoad(self, "interiorAmbient",
+ BENILLA_ADVGFX.interiorAmbient,
+ "BENILLA_TOOLTIP_INTERIOR_AMBIENT")
+ OptionsSliderRow_Setup(self, 0, 0.1, 0.005, "travel")
+
+
+
+
+
+
+
+
+ -- In `interiorAmbient`'s own units, so it
+ -- takes that row's groove. Ships at 0, which is
+ -- the restore: the lane adds nothing until asked.
+ OptionsRow_OnLoad(self, "interiorDaylight",
+ BENILLA_ADVGFX.interiorDaylight,
+ "BENILLA_TOOLTIP_INDOOR_DAYLIGHT")
+ OptionsSliderRow_Setup(self, 0, 0.1, 0.005, "travel")
+
+
+
+
+
+
+
+
+ -- 0..2, the CVar's clamp; the shipped 0.08
+ -- lands on a stop and reads "8%".
+ OptionsRow_OnLoad(self, "interiorFill",
+ BENILLA_ADVGFX.interiorFill,
+ "BENILLA_TOOLTIP_INTERIOR_BOUNCE")
+ OptionsSliderRow_Setup(self, 0, 2, 0.02)
+
+
+
+
+
+
+
+
+ -- 0..8, the CVar's clamp. 0 is not "no
+ -- light": it switches the authored window OFF, so
+ -- every fixture reaches the whole room — which is
+ -- why the description says so rather than letting
+ -- the left end read as darkness.
+ OptionsRow_OnLoad(self, "interiorAttenScale",
+ BENILLA_ADVGFX.interiorAttenScale,
+ "BENILLA_TOOLTIP_INTERIOR_LIGHT_REACH")
+ OptionsSliderRow_Setup(self, 0, 8, 0.1)
+
+
+
+
+
+
+
+
+ -- A SHARE of the batch's own bake, so the
+ -- default percent is the right readout: the
+ -- shipped 0.12 reads "12%".
+ OptionsRow_OnLoad(self, "interiorBakeFloor",
+ BENILLA_ADVGFX.interiorBakeFloor,
+ "BENILLA_TOOLTIP_UNLIT_ROOM_FLOOR")
+ OptionsSliderRow_Setup(self, 0, 1, 0.02)
+
+
+
+
+
+
+
+
+ -- Kept as a dial because a room the gate
+ -- leaves on ambient alone looks exactly like a
+ -- bug, and this tells the two apart in one click
+ -- — which is a thing to be able to do from the
+ -- options window, not only from `/console`.
+ OptionsRow_OnLoad(self, "interiorRoomGate",
+ BENILLA_ADVGFX.interiorRoomGate,
+ "BENILLA_TOOLTIP_LIGHTS_STAY_IN_THEIR_ROOM")
+
+
+
+
+
+
+
OptionsRow_OnLoad(self, "interiorShadows",
BENILLA_ADVGFX.interiorShadows,
@@ -3620,11 +3907,62 @@
OptionsSliderRow_Setup(self, 0, 1, 0.05)
-
+
+
+ -- 1..16, the CVar's own clamp — the RESIDENT
+ -- map budget. "raw", because this is a count of
+ -- maps and a percentage of one would be nonsense.
+ OptionsRow_OnLoad(self, "interiorShadowCasters",
+ BENILLA_ADVGFX.interiorShadowCasters,
+ "BENILLA_TOOLTIP_INDOOR_SHADOW_MAPS")
+ OptionsSliderRow_Setup(self, 1, 16, 1, "raw")
+
+
+
+
+
+
+
+
+ -- 1..8 (`MAX_TORCH_DYNAMIC`), not the 0..16 the
+ -- registration's help line says: the observer
+ -- arm raises 0 to 1 and clamps to the cube-array
+ -- the depth pass actually has room for, so a
+ -- groove to 16 would offer seven stops that all
+ -- mean 8 and a zero that means 1.
+ OptionsRow_OnLoad(self, "interiorShadowDynamic",
+ BENILLA_ADVGFX.interiorShadowDynamic,
+ "BENILLA_TOOLTIP_MOVING_SHADOWS_INDOORS")
+ OptionsSliderRow_Setup(self, 1, 8, 1, "raw")
+
+
+
+
+
+
+
+
+ -- The same groove and the same `hz` readout as
+ -- the two sun-lane rate caps, inside this CVar's
+ -- wider 0..240; `0` is every frame there too.
+ -- This is the row that actually costs frame time
+ -- in the indoor lane — neither count dial above
+ -- moved it — which the description says.
+ OptionsRow_OnLoad(self, "interiorShadowEntityRate",
+ BENILLA_ADVGFX.interiorShadowEntityRate,
+ "BENILLA_TOOLTIP_MOVING_SHADOW_UPDATES")
+ OptionsSliderRow_Setup(self, 0, 120, 10, "hz")
+
+
+
+
+
+
+
-- Full 0..4 registry range, in five-percent steps.
OptionsRow_OnLoad(self, "fireLightGain",
diff --git a/crates/benilla-app/src/ui_script/options_tests.rs b/crates/benilla-app/src/ui_script/options_tests.rs
index 2a149201..be873254 100644
--- a/crates/benilla-app/src/ui_script/options_tests.rs
+++ b/crates/benilla-app/src/ui_script/options_tests.rs
@@ -1980,6 +1980,122 @@ fn the_shadow_rig_rows_are_localised() {
}
}
+/// GFX (interior rig): the ten interior-lighting rows. The thing to hold is the two-level master
+/// — every row needs the live-fixture lane, and the three shadow budgets need the shadows on top
+/// of it — because a budget row left live while its shadows are off is a dial that does nothing,
+/// which is how `/console`-only settings earn their reputation.
+#[test]
+fn the_interior_rows_ride_the_lane_and_its_shadows_as_two_masters() {
+ benilla_formats::wow_data_or_skip!();
+ let base = "BenillaOptionsFrameContainerBodyAdvancedGraphics";
+ let mut s = audio_harness();
+ s.set_cvar_host("interiorLight", "1");
+ s.set_cvar_host("interiorShadows", "1");
+ let mut s = harness_on(s);
+ s.run("ShowUIPanel(BenillaOptionsFrame) BenillaOptionsFrameCategoryListRowAdvancedGraphics:Click()")
+ .unwrap();
+
+ let live = |s: &mut UiScript, row: &str| {
+ s.eval::(&format!(
+ "local t = getglobal(\"{base}Row{row}ControlSliderThumb\") \
+ if t then return t:IsShown() and true or false end \
+ return getglobal(\"{base}Row{row}Check\"):IsEnabled() == 1"
+ ))
+ .unwrap()
+ };
+ let readout = |s: &mut UiScript, row: &str| {
+ s.eval::(&format!("return {base}Row{row}ControlValue:GetText()"))
+ .unwrap()
+ };
+
+ // A count of shadow maps reads as a count, and a multiplier as a percentage of itself.
+ assert_eq!(readout(&mut s, "InteriorShadowCasters"), "12");
+ assert_eq!(readout(&mut s, "InteriorExposure"), "250%");
+ assert_eq!(readout(&mut s, "InteriorShadowEntityRate"), "30 per second");
+ // Ambient has no unit a player could read, so the row reports the dial's own position: the
+ // shipped 0.015 is 15% of a 0..0.1 groove.
+ assert_eq!(readout(&mut s, "InteriorAmbient"), "15%");
+
+ for row in ["InteriorExposure", "InteriorAmbient", "InteriorRoomGate"] {
+ assert!(live(&mut s, row), "{row} is live with the lane on");
+ }
+
+ // Sub-master: the shadows alone, which must take the three budgets and leave the look rows.
+ s.run("SetCVar('interiorShadows', '0') OptionsPage_Refresh(\"AdvancedGraphics\")")
+ .unwrap();
+ for row in [
+ "InteriorShadowCasters",
+ "InteriorShadowDynamic",
+ "InteriorShadowEntityRate",
+ ] {
+ assert!(!live(&mut s, row), "{row} needs indoor shadows");
+ }
+ assert!(
+ live(&mut s, "InteriorExposure"),
+ "the look rows do not need shadows, only the lane"
+ );
+
+ // Master: the lane itself takes everything, the three budgets included.
+ s.run("SetCVar('interiorLight', '0') OptionsPage_Refresh(\"AdvancedGraphics\")")
+ .unwrap();
+ for row in [
+ "InteriorExposure",
+ "InteriorAmbient",
+ "InteriorDaylight",
+ "InteriorFill",
+ "InteriorAttenScale",
+ "InteriorBakeFloor",
+ "InteriorRoomGate",
+ "InteriorShadowCasters",
+ ] {
+ assert!(!live(&mut s, row), "{row} needs the live-fixture lane");
+ }
+ // Greyed, never rewritten: the lane coming back finds every value where it was left.
+ assert_eq!(
+ s.eval::("return GetCVar('interiorExposure')")
+ .unwrap(),
+ "2.5"
+ );
+ assert!(s.errors().is_empty(), "script errors: {:?}", s.errors());
+}
+
+/// The interior rows' labels in both locales, as every Advanced Graphics row carries them.
+#[test]
+fn the_interior_rig_rows_are_localised() {
+ benilla_formats::wow_data_or_skip!();
+ let base = "BenillaOptionsFrameContainerBodyAdvancedGraphics";
+ for (locale, gate, maps) in [
+ ("enUS", "Lights Stay in Their Room", "Indoor Shadow Maps"),
+ (
+ "ruRU",
+ "Свет не проходит сквозь стены",
+ "Карты теней в помещениях",
+ ),
+ ] {
+ let s = audio_harness();
+ s.run(&format!("function GetLocale() return '{locale}' end"))
+ .unwrap();
+ let s = harness_on(s);
+ s.run("ShowUIPanel(BenillaOptionsFrame) BenillaOptionsFrameCategoryListRowAdvancedGraphics:Click()")
+ .unwrap();
+ assert_eq!(
+ s.eval::(&format!("return {base}RowInteriorRoomGateLabel:GetText()"))
+ .unwrap(),
+ gate,
+ "{locale}"
+ );
+ assert_eq!(
+ s.eval::(&format!(
+ "return {base}RowInteriorShadowCastersLabel:GetText()"
+ ))
+ .unwrap(),
+ maps,
+ "{locale}"
+ );
+ assert!(s.errors().is_empty(), "{locale}: {:?}", s.errors());
+ }
+}
+
/// Pending edits are panel-wide, as the era's modified table: a category switch keeps them, and
/// hiding the window discards them.
#[test]
@@ -2383,10 +2499,11 @@ fn water_quality_writes_numeric_tiers_with_localised_labels() {
// rows append after those: 33 -> 37.
// GFX (shadow rig): the five shadow rows a player could not reach — the filter, the
// caster reach, the two update-rate caps and the torch darkness: 37 -> 42.
+ // GFX (interior rig): the ten interior-lighting rows: 42 -> 52.
assert_eq!(
s.eval::("return table.getn(OPTIONS_PAGE_ROWS.AdvancedGraphics)")
.unwrap(),
- 42
+ 52
);
assert_eq!(
s.eval::("return OPTIONS_PAGE_ROWS.AdvancedGraphics[4]")
@@ -3424,6 +3541,48 @@ fn every_row_tooltip_key_resolves_in_the_real_global_strings() {
"BENILLA_TOOLTIP_TORCH_SHADOW_DARKNESS",
"AdvancedGraphicsRowTorchShadowDarkness",
),
+ // GFX (interior rig): the ten interior-lighting rows, likewise ours — 1.12 has none
+ // of these settings, so it has no string for any of them.
+ (
+ "BENILLA_TOOLTIP_INTERIOR_LIGHT_BUDGET",
+ "AdvancedGraphicsRowInteriorExposure",
+ ),
+ (
+ "BENILLA_TOOLTIP_INTERIOR_AMBIENT",
+ "AdvancedGraphicsRowInteriorAmbient",
+ ),
+ (
+ "BENILLA_TOOLTIP_INDOOR_DAYLIGHT",
+ "AdvancedGraphicsRowInteriorDaylight",
+ ),
+ (
+ "BENILLA_TOOLTIP_INTERIOR_BOUNCE",
+ "AdvancedGraphicsRowInteriorFill",
+ ),
+ (
+ "BENILLA_TOOLTIP_INTERIOR_LIGHT_REACH",
+ "AdvancedGraphicsRowInteriorAttenScale",
+ ),
+ (
+ "BENILLA_TOOLTIP_UNLIT_ROOM_FLOOR",
+ "AdvancedGraphicsRowInteriorBakeFloor",
+ ),
+ (
+ "BENILLA_TOOLTIP_LIGHTS_STAY_IN_THEIR_ROOM",
+ "AdvancedGraphicsRowInteriorRoomGate",
+ ),
+ (
+ "BENILLA_TOOLTIP_INDOOR_SHADOW_MAPS",
+ "AdvancedGraphicsRowInteriorShadowCasters",
+ ),
+ (
+ "BENILLA_TOOLTIP_MOVING_SHADOWS_INDOORS",
+ "AdvancedGraphicsRowInteriorShadowDynamic",
+ ),
+ (
+ "BENILLA_TOOLTIP_MOVING_SHADOW_UPDATES",
+ "AdvancedGraphicsRowInteriorShadowEntityRate",
+ ),
("BENILLA_TOOLTIP_RENDER_SCALE", "GraphicsRowRenderScale"),
// GFX (anisotropic): ours, because 1.12's own text describes a four-stop slider
// that needs a restart and this row is neither.
@@ -3573,7 +3732,8 @@ fn every_row_tooltip_key_resolves_in_the_real_global_strings() {
// GFX: Trilinear Filtering and Multisampling, the two other video rows a player could not
// reach. 117 -> 119.
// GFX (shadow rig): the five Advanced Graphics shadow rows. 119 -> 124.
- assert_eq!(checked, 124, "every tipped row carries a live key");
+ // GFX (interior rig): the ten interior-lighting rows. 124 -> 134.
+ assert_eq!(checked, 134, "every tipped row carries a live key");
assert_eq!(
untipped,
vec![
@@ -3680,7 +3840,8 @@ fn every_flavor_of_row_raises_its_plate_from_the_page_it_lives_on() {
// GFX (anisotropic): the Graphics page's anisotropy slider. 116 -> 117.
// GFX: Trilinear Filtering and Multisampling. 117 -> 119.
// GFX (shadow rig): the five Advanced Graphics shadow rows. 119 -> 124.
- assert_eq!(raised, 124, "every row but Auto Loot raises a description");
+ // GFX (interior rig): the ten interior-lighting rows. 124 -> 134.
+ assert_eq!(raised, 134, "every row but Auto Loot raises a description");
}
/// 1.12's AdvancedOptionsCombatText box as saved-global rows: a click writes the global, never a