fix #213: complete suicide and framerate presentation

Translate suicide response 0x004A as retail's successful self-kill notice. Port /framerate onto the authored SmartBox FPS element with live two-decimal FPS and DEG values, keep diagnostic window chrome independent, and synchronize command-driven settings without discarding panel drafts.

Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-13 15:50:47 +02:00
parent 9ea579bdd0
commit 43f7c7807c
17 changed files with 729 additions and 39 deletions

View file

@ -25,19 +25,17 @@ public sealed record DisplaySettings(
QualityPreset Quality)
{
/// <summary>Values used on first launch / when settings.json is absent.
/// All defaults pinned to the pre-L.0 runtime state — Resolution
/// Geometry/render defaults preserve the pre-L.0 runtime state — Resolution
/// matches the WindowOptions startup size (1280×720), FieldOfView
/// matches camera FovY (60°), VSync matches WindowOptions (false),
/// ShowFps preserves the perf string in the title bar. Net effect:
/// opening Display + Save without touching anything is a complete
/// visual no-op.</summary>
/// ShowFps matches retail's initially-hidden SmartBox FPS readout.</summary>
public static DisplaySettings Default { get; } = new(
Resolution: "1280x720",
Fullscreen: false,
VSync: false,
FieldOfView: 60f,
Gamma: 1.0f,
ShowFps: true,
ShowFps: false,
Quality: QualityPreset.High);
/// <summary>16:9 resolution presets offered in the dropdown.</summary>

View file

@ -151,6 +151,20 @@ public sealed class SettingsVM
_displayDraft = value ?? throw new ArgumentNullException(nameof(value));
}
/// <summary>
/// Apply one externally persisted display-option change to both snapshots.
/// Existing unsaved edits to other fields remain drafts rather than being
/// accidentally promoted to persisted state.
/// </summary>
public void ApplyExternalDisplayChange(Func<DisplaySettings, DisplaySettings> update)
{
ArgumentNullException.ThrowIfNull(update);
_displayPersisted = update(_displayPersisted)
?? throw new InvalidOperationException("Display update returned null.");
_displayDraft = update(_displayDraft)
?? throw new InvalidOperationException("Display update returned null.");
}
/// <summary>
/// Replace the entire Audio draft with <paramref name="value"/>.
/// Live audio preview is achieved at the host layer by pushing