The interior lighting rig gets its ten rows, and the audit closes
The last ten CVars `video::on_cvar` answers that a player could not reach. With these the sweep is done: every graphics and video row the observer takes now has a seat, bar the three that are not settings — `frillDensity` (World Detail already drives it, and two dials on one knob is worse than none), `nearclip` (the projection near plane: changing it is a bug, not a preference) and `interiorDebug` (a visualiser). Seven shape the room — the light budget, the ambient floor under every indoor surface, the indoor daylight floor, the bounce gain, the reach past each fixture's authored window, the share of painted-in lighting kept where nothing reaches, and the room gate — and three are the indoor shadow budgets. Named for what they do to a room, not for the quantity they scale, because the quantity is the renderer's word and the room is the player's: "Unlit Room Floor", not "interior bake floor"; "Lights Stay in Their Room", not "room gate". Each description says what the setting is FOR rather than what it multiplies, and three of them carry the thing a player would otherwise misread: - `interiorAttenScale` at 0 is not darkness, it is the authored window switched OFF, so every fixture reaches the whole room. A left end that looks like "no light" and means "all light" needs saying. - `interiorRoomGate` is the one setting whose job is diagnosis: a room the gate leaves on ambient alone looks exactly like a bug, and one click tells the two apart. That belongs in the options window and not only in `/console`. - `interiorShadowEntityRate` is the only row in the indoor shadow block that actually costs frame time — neither count dial above it moved it, which is why it exists as its own row — so its description says to lower it first. Two grooves deliberately offer less than their CVar's clamp, as `RowRenderScale` already does (50-200% inside a 0.25-4 clamp): ambient and indoor daylight run 0..0.1 of a 0..1 clamp, because the shipped value is 0.015 and past about 0.1 a room is not lit, it is fogged. `/console` still reaches the rest. One offers less than its *registration* says: `interiorShadowDynamic`'s help line reads 0..16, but the observer raises 0 to 1 and clamps to `MAX_TORCH_DYNAMIC` (8), so a groove to 16 would be seven stops that all mean 8 and a zero that means 1. The gating is two-level: every row needs the live-fixture lane, and the three shadow budgets need the shadows on top of it. A budget row left live while its shadows are off is a dial that does nothing, which is how settings earn the reputation these ones had. Russian for all ten rows and their descriptions is written to match the register of the column already there; a native reader would still improve it. Verified: ALL GATES GREEN (346 s); `benilla-app --lib` against the install at the exact 269-failure baseline, set-identical by `comm`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn
This commit is contained in:
@@ -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")
|
||||
</OnLoad></Scripts>
|
||||
</Frame>
|
||||
<Frame name="$parentRowInteriorShadows" inherits="OptionsCheckboxRowTemplate">
|
||||
<Frame name="$parentRowInteriorExposure" inherits="OptionsSliderRowTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentRowInteriorLight" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
<Anchor point="TOPRIGHT" relativeTo="$parentRowInteriorLight" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
</Anchors>
|
||||
<Scripts><OnLoad>
|
||||
-- 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)
|
||||
</OnLoad></Scripts>
|
||||
</Frame>
|
||||
<Frame name="$parentRowInteriorAmbient" inherits="OptionsSliderRowTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentRowInteriorExposure" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
<Anchor point="TOPRIGHT" relativeTo="$parentRowInteriorExposure" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
</Anchors>
|
||||
<Scripts><OnLoad>
|
||||
-- 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")
|
||||
</OnLoad></Scripts>
|
||||
</Frame>
|
||||
<Frame name="$parentRowInteriorDaylight" inherits="OptionsSliderRowTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentRowInteriorAmbient" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
<Anchor point="TOPRIGHT" relativeTo="$parentRowInteriorAmbient" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
</Anchors>
|
||||
<Scripts><OnLoad>
|
||||
-- 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")
|
||||
</OnLoad></Scripts>
|
||||
</Frame>
|
||||
<Frame name="$parentRowInteriorFill" inherits="OptionsSliderRowTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentRowInteriorDaylight" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
<Anchor point="TOPRIGHT" relativeTo="$parentRowInteriorDaylight" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
</Anchors>
|
||||
<Scripts><OnLoad>
|
||||
-- 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)
|
||||
</OnLoad></Scripts>
|
||||
</Frame>
|
||||
<Frame name="$parentRowInteriorAttenScale" inherits="OptionsSliderRowTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentRowInteriorFill" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
<Anchor point="TOPRIGHT" relativeTo="$parentRowInteriorFill" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
</Anchors>
|
||||
<Scripts><OnLoad>
|
||||
-- 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)
|
||||
</OnLoad></Scripts>
|
||||
</Frame>
|
||||
<Frame name="$parentRowInteriorBakeFloor" inherits="OptionsSliderRowTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentRowInteriorAttenScale" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
<Anchor point="TOPRIGHT" relativeTo="$parentRowInteriorAttenScale" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
</Anchors>
|
||||
<Scripts><OnLoad>
|
||||
-- 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)
|
||||
</OnLoad></Scripts>
|
||||
</Frame>
|
||||
<Frame name="$parentRowInteriorRoomGate" inherits="OptionsCheckboxRowTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentRowInteriorBakeFloor" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
<Anchor point="TOPRIGHT" relativeTo="$parentRowInteriorBakeFloor" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
</Anchors>
|
||||
<Scripts><OnLoad>
|
||||
-- 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")
|
||||
</OnLoad></Scripts>
|
||||
</Frame>
|
||||
<Frame name="$parentRowInteriorShadows" inherits="OptionsCheckboxRowTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentRowInteriorRoomGate" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
<Anchor point="TOPRIGHT" relativeTo="$parentRowInteriorRoomGate" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
</Anchors>
|
||||
<Scripts><OnLoad>
|
||||
OptionsRow_OnLoad(self, "interiorShadows",
|
||||
BENILLA_ADVGFX.interiorShadows,
|
||||
@@ -3620,11 +3907,62 @@
|
||||
OptionsSliderRow_Setup(self, 0, 1, 0.05)
|
||||
</OnLoad></Scripts>
|
||||
</Frame>
|
||||
<Frame name="$parentRowFireLight" inherits="OptionsSliderRowTemplate">
|
||||
<Frame name="$parentRowInteriorShadowCasters" inherits="OptionsSliderRowTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentRowTorchShadowDarkness" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
<Anchor point="TOPRIGHT" relativeTo="$parentRowTorchShadowDarkness" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
</Anchors>
|
||||
<Scripts><OnLoad>
|
||||
-- 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")
|
||||
</OnLoad></Scripts>
|
||||
</Frame>
|
||||
<Frame name="$parentRowInteriorShadowDynamic" inherits="OptionsSliderRowTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentRowInteriorShadowCasters" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
<Anchor point="TOPRIGHT" relativeTo="$parentRowInteriorShadowCasters" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
</Anchors>
|
||||
<Scripts><OnLoad>
|
||||
-- 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")
|
||||
</OnLoad></Scripts>
|
||||
</Frame>
|
||||
<Frame name="$parentRowInteriorShadowEntityRate" inherits="OptionsSliderRowTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentRowInteriorShadowDynamic" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
<Anchor point="TOPRIGHT" relativeTo="$parentRowInteriorShadowDynamic" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
</Anchors>
|
||||
<Scripts><OnLoad>
|
||||
-- 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")
|
||||
</OnLoad></Scripts>
|
||||
</Frame>
|
||||
<Frame name="$parentRowFireLight" inherits="OptionsSliderRowTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parentRowInteriorShadowEntityRate" relativePoint="BOTTOMLEFT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
<Anchor point="TOPRIGHT" relativeTo="$parentRowInteriorShadowEntityRate" relativePoint="BOTTOMRIGHT"><Offset><AbsDimension x="0" y="-9"/></Offset></Anchor>
|
||||
</Anchors>
|
||||
<Scripts><OnLoad>
|
||||
-- Full 0..4 registry range, in five-percent steps.
|
||||
OptionsRow_OnLoad(self, "fireLightGain",
|
||||
|
||||
@@ -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::<bool>(&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::<String>(&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::<String>("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::<String>(&format!("return {base}RowInteriorRoomGateLabel:GetText()"))
|
||||
.unwrap(),
|
||||
gate,
|
||||
"{locale}"
|
||||
);
|
||||
assert_eq!(
|
||||
s.eval::<String>(&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::<usize>("return table.getn(OPTIONS_PAGE_ROWS.AdvancedGraphics)")
|
||||
.unwrap(),
|
||||
42
|
||||
52
|
||||
);
|
||||
assert_eq!(
|
||||
s.eval::<String>("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
|
||||
|
||||
Reference in New Issue
Block a user