feat(ui): Campaign OP slice OP6 — the Config tab
Binds the retail Options panel's Config tab (LayoutDesc 0x21000029, 27 authored rows across 6 sections) through OP2's template mechanism and OP3's per-page OptionPage model, matching the Character/Chat tab controllers' established pattern. The row table is transcribed directly from two decompiled sources — gmConfigUI::InitOptions @0x0049E400 (row order, widget shape, defaults) and gmClient::InitUIPreferences @0x004035b0 (the complete UIPreferences::AttachPreference registration: every label/tooltip key, every slider's real-unit range, every menu's enum choices) — which resolves the research docs' own "U4" unverified slider-caption pairing: retail ships ZERO range captions on this tab (every SetSliderLabel call passes literal string id 0). Consumer disposition: LIVE — Sound/Ambient volume-trio sliders and their toggle halves (AudioSettings.SfxDisabled/AmbientDisabled now gate the already-live engine write; RuntimeSettingsController.SaveAudio newly pushes into OpenAlAudioEngine on every change, not just at startup), Resolution/Full Screen (immediate window resize on save). NEXT-LAUNCH (pre-existing precedent): Sync To Refresh, Field of View. STORE-ONLY (register rows AP-198/199/200, TS-74 extended): Sound Features/Interface trio/Play-Only-When-Active, the nine Graphics/Rendering-Quality rows (Vulkan has no per-feature render knobs), Camera/Input's six rows and Use Mouse Turning (no persistent mouse-turning camera mode), Chat Font Face/Size (distinct new fields from the existing live ChatSettings.FontSize). AudioSettings/DisplaySettings/CameraTurningSettings/ChatSettings each gain new fields for their slice of the 27 rows, backed by SettingsStore round-trips. A real bug caught by testing: the scrollbar scope lookup used the standalone-layout root id (0x100001FF), which does not survive base-merge into the host-mounted tree — fixed to scope from the tab host's own page-slot id (0x10000213), matching Chat's established pattern for the same shared-scrollbar-id hazard (0x10000201, authored by both the Chat and Config ListBoxes). 30 new tests (27 authored rows register as 30 IOptionRow instances — the three toggle+slider trios each register two). Full Release suite: 13,107 passed / 4 skipped / 0 failed (was 13,083/4/0 — net +24, the one existing RuntimeSettingsControllerTests case updated for SaveAudio's new live-apply call, not a regression). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
527a3a4056
commit
f5ac1742ba
16 changed files with 2188 additions and 30 deletions
|
|
@ -70,7 +70,16 @@ public sealed class SettingsStore
|
|||
ShowFps: ReadBool (disp, "showFps", d.ShowFps),
|
||||
Quality: ReadQuality (disp, "quality", d.Quality),
|
||||
ParticleRange: ReadParticleRange(
|
||||
disp, "particleRange", d.ParticleRange));
|
||||
disp, "particleRange", d.ParticleRange),
|
||||
AutomaticDegrades: ReadBool (disp, "automaticDegrades", d.AutomaticDegrades),
|
||||
GraphicsPerformance: ReadFloat(disp, "graphicsPerformance", d.GraphicsPerformance),
|
||||
DegradeDistance: ReadFloat(disp, "degradeDistance", d.DegradeDistance),
|
||||
LandscapeTextureDetail: ReadInt (disp, "landscapeTextureDetail", d.LandscapeTextureDetail),
|
||||
EnvironmentTextureDetail:ReadInt (disp, "environmentTextureDetail",d.EnvironmentTextureDetail),
|
||||
TextureFiltering: ReadInt (disp, "textureFiltering", d.TextureFiltering),
|
||||
LandscapeDrawDistance: ReadInt (disp, "landscapeDrawDistance", d.LandscapeDrawDistance),
|
||||
BuildingDetailTextures: ReadBool (disp, "buildingDetailTextures", d.BuildingDetailTextures),
|
||||
MultiPassAlpha: ReadBool (disp, "multiPassAlpha", d.MultiPassAlpha));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -109,7 +118,13 @@ public sealed class SettingsStore
|
|||
return new AudioSettings(
|
||||
Master: ReadFloat(audio, "master", d.Master),
|
||||
Sfx: ReadFloat(audio, "sfx", d.Sfx),
|
||||
Ambient: ReadFloat(audio, "ambient", d.Ambient));
|
||||
Ambient: ReadFloat(audio, "ambient", d.Ambient),
|
||||
SoundFeatures: ReadInt (audio, "soundFeatures", d.SoundFeatures),
|
||||
SfxDisabled: ReadBool (audio, "sfxDisabled", d.SfxDisabled),
|
||||
AmbientDisabled: ReadBool (audio, "ambientDisabled", d.AmbientDisabled),
|
||||
InterfaceDisabled: ReadBool (audio, "interfaceDisabled", d.InterfaceDisabled),
|
||||
InterfaceVolume: ReadFloat(audio, "interfaceVolume", d.InterfaceVolume),
|
||||
PlaySoundOnlyWhenActive: ReadBool (audio, "playSoundOnlyWhenActive", d.PlaySoundOnlyWhenActive));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -199,7 +214,9 @@ public sealed class SettingsStore
|
|||
ChatWindow4Filter: ReadULong(chat, "chatWindow4Filter", d.ChatWindow4Filter),
|
||||
ChatWindowMainFilter: ReadULong(chat, "chatWindowMainFilter", d.ChatWindowMainFilter),
|
||||
DefaultOpacity: ReadFloat(chat, "defaultOpacity", d.DefaultOpacity),
|
||||
ActiveOpacity: ReadFloat(chat, "activeOpacity", d.ActiveOpacity));
|
||||
ActiveOpacity: ReadFloat(chat, "activeOpacity", d.ActiveOpacity),
|
||||
ChatFontFace: ReadInt(chat, "chatFontFace", d.ChatFontFace),
|
||||
ChatFontSizeIndex: ReadInt(chat, "chatFontSizeIndex", d.ChatFontSizeIndex));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -235,7 +252,8 @@ public sealed class SettingsStore
|
|||
AdjustmentSpeed: ReadFloat(ct, "adjustmentSpeed", d.AdjustmentSpeed),
|
||||
MouseLookSensitivity: ReadFloat(ct, "mouseLookSensitivity", d.MouseLookSensitivity),
|
||||
AlignToSlope: ReadBool (ct, "alignToSlope", d.AlignToSlope),
|
||||
InvertMouseLookYAxis: ReadBool (ct, "invertMouseLookYAxis", d.InvertMouseLookYAxis));
|
||||
InvertMouseLookYAxis: ReadBool (ct, "invertMouseLookYAxis", d.InvertMouseLookYAxis),
|
||||
UseMouseTurning: ReadBool (ct, "useMouseTurning", d.UseMouseTurning));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -580,6 +598,8 @@ public sealed class SettingsStore
|
|||
{
|
||||
["activeOpacity"] = c.ActiveOpacity,
|
||||
["appearOffline"] = c.AppearOffline,
|
||||
["chatFontFace"] = c.ChatFontFace,
|
||||
["chatFontSizeIndex"] = c.ChatFontSizeIndex,
|
||||
["chatWindow1Filter"] = c.ChatWindow1Filter,
|
||||
["chatWindow2Filter"] = c.ChatWindow2Filter,
|
||||
["chatWindow3Filter"] = c.ChatWindow3Filter,
|
||||
|
|
@ -617,13 +637,22 @@ public sealed class SettingsStore
|
|||
private static SortedDictionary<string, object> BuildDisplayObject(DisplaySettings d)
|
||||
=> new(StringComparer.Ordinal)
|
||||
{
|
||||
["automaticDegrades"] = d.AutomaticDegrades,
|
||||
["buildingDetailTextures"] = d.BuildingDetailTextures,
|
||||
["degradeDistance"] = d.DegradeDistance,
|
||||
["environmentTextureDetail"] = d.EnvironmentTextureDetail,
|
||||
["fieldOfView"] = d.FieldOfView,
|
||||
["fullscreen"] = d.Fullscreen,
|
||||
["gamma"] = d.Gamma,
|
||||
["graphicsPerformance"] = d.GraphicsPerformance,
|
||||
["landscapeDrawDistance"] = d.LandscapeDrawDistance,
|
||||
["landscapeTextureDetail"] = d.LandscapeTextureDetail,
|
||||
["multiPassAlpha"] = d.MultiPassAlpha,
|
||||
["particleRange"] = d.ParticleRange.ToString(),
|
||||
["quality"] = d.Quality.ToString(),
|
||||
["resolution"] = d.Resolution,
|
||||
["showFps"] = d.ShowFps,
|
||||
["textureFiltering"] = d.TextureFiltering,
|
||||
["vsync"] = d.VSync,
|
||||
};
|
||||
|
||||
|
|
@ -635,14 +664,21 @@ public sealed class SettingsStore
|
|||
["invertMouseLookYAxis"] = c.InvertMouseLookYAxis,
|
||||
["mouseLookSensitivity"] = c.MouseLookSensitivity,
|
||||
["stiffness"] = c.Stiffness,
|
||||
["useMouseTurning"] = c.UseMouseTurning,
|
||||
};
|
||||
|
||||
private static SortedDictionary<string, object> BuildAudioObject(AudioSettings a)
|
||||
=> new(StringComparer.Ordinal)
|
||||
{
|
||||
["ambient"] = a.Ambient,
|
||||
["master"] = a.Master,
|
||||
["sfx"] = a.Sfx,
|
||||
["ambient"] = a.Ambient,
|
||||
["ambientDisabled"] = a.AmbientDisabled,
|
||||
["interfaceDisabled"] = a.InterfaceDisabled,
|
||||
["interfaceVolume"] = a.InterfaceVolume,
|
||||
["master"] = a.Master,
|
||||
["playSoundOnlyWhenActive"] = a.PlaySoundOnlyWhenActive,
|
||||
["sfx"] = a.Sfx,
|
||||
["sfxDisabled"] = a.SfxDisabled,
|
||||
["soundFeatures"] = a.SoundFeatures,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -710,6 +746,10 @@ public sealed class SettingsStore
|
|||
=> obj.TryGetProperty(name, out var el) && el.ValueKind == JsonValueKind.Number
|
||||
? el.GetSingle() : fallback;
|
||||
|
||||
private static int ReadInt(JsonElement obj, string name, int fallback)
|
||||
=> obj.TryGetProperty(name, out var el) && el.ValueKind == JsonValueKind.Number
|
||||
? el.GetInt32() : fallback;
|
||||
|
||||
private static ulong ReadULong(JsonElement obj, string name, ulong fallback)
|
||||
{
|
||||
if (!obj.TryGetProperty(name, out var el) || el.ValueKind != JsonValueKind.Number)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue