fix #389: port retail's SmartboxFOV law; retire AD-89 (display slice 1)
Retail's world-camera FOV is not a constant: the applied vertical FOV is m_fGameFOV / (viewportAspect - 0.1), recomputed on every aspect or game-FOV change (CreatureMode smartbox sites 0x00452b2f/0x00453b14), gated by Render::SetFOVRad's open (0, pi) acceptance (0x0054b2d0 - rejected results keep the previous FOV). m_fGameFOV defaults to pi/2 = 90 degrees (0x00454649) and is what the Field of View option sets in degrees (0x00451e6a; registered range [10,160] default 90 - gmClient::InitUIPreferences @0x004035b0). Net effect: the horizontal view stays ~85-90 degrees across aspect ratios; wide screens trim the vertical slice instead of ballooning the sides. acdream hardcoded FovY = pi/3 = 60 degrees on all four world cameras, aspect-independent, and the Config slider wrote raw vertical-FOV degrees. New: RetailFieldOfView (the law + gate, decomp-cited), CameraController.GameFovRadians + SetGameFov + one ApplyProjection chokepoint recomputing every camera on SetAspect/SetGameFov/ EnterChaseMode/RestoreState; ApplyFieldOfView now feeds the law; DisplaySettings.Default.FieldOfView 60 -> 90 (the retail registered default; the stored number changed MEANING with this commit). The same seam closes a second latent bug the 2026-08-13 "squished" gate report exposed: SetAspect only ever updated Orbit/Fly - the CHASE cameras (the ones the player looks through) kept their creation-time aspect across every mid-session resize, drawing the world at the old shape stretched onto the new viewport. The paperdoll camera stays outside the law by design (retail portrait mode is UseSharpMode, not smartbox - DollCamera's own doc). Tests: RetailFieldOfViewTests (golden law values at 4:3/16:9/21:9, the constant-horizontal property, the rejection gate, controller propagation incl. chase attach/restore + rejected-law aspect-still-propagates); DisplaySettingsTests + RuntimeSettingsControllerTests updated to the new semantics. App suite 4,953/3 skips; UI.Abstractions 916/0. AD-89 retired in this commit; user settings.json migrated 60->90 by hand (stale pre-port default). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
a1efc8bcb3
commit
7e0c130344
13 changed files with 334 additions and 22 deletions
|
|
@ -132,15 +132,19 @@ internal sealed class RuntimeSettingsStartupTargets : IRuntimeSettingsStartupTar
|
|||
|
||||
public void ApplyAudio(AudioSettings audio) => ApplyAudio(_audio, audio);
|
||||
|
||||
/// <summary>#389: the stored Field of View is retail's <c>m_fGameFOV</c>
|
||||
/// in DEGREES (registered range [10,160], default 90 —
|
||||
/// <c>gmClient::InitUIPreferences @0x004035b0</c>), converted exactly as
|
||||
/// retail's option setter does (<c>× 0.017453292519943295</c>,
|
||||
/// <c>0x00451e6a</c>) and applied through the smartbox law in
|
||||
/// <see cref="CameraController.SetGameFov"/> — NEVER written to a camera's
|
||||
/// vertical FOV directly (the pre-#389 behavior, which made the slider
|
||||
/// mean a different, aspect-ignorant thing than retail's).</summary>
|
||||
internal static void ApplyFieldOfView(
|
||||
CameraController cameras,
|
||||
float degrees)
|
||||
{
|
||||
float radians = degrees * (MathF.PI / 180f);
|
||||
cameras.Orbit.FovY = radians;
|
||||
cameras.Fly.FovY = radians;
|
||||
if (cameras.Chase is not null)
|
||||
cameras.Chase.FovY = radians;
|
||||
cameras.SetGameFov(degrees * (MathF.PI / 180f));
|
||||
}
|
||||
|
||||
internal static void ApplyAudio(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue