feat(camera): add CameraDiagnostics static tunable owner
Six knobs for the upcoming retail chase camera: UseRetailChaseCamera master toggle (env ACDREAM_RETAIL_CHASE), AlignToSlope (env ACDREAM_CAMERA_ALIGN_SLOPE, default on), TranslationStiffness + RotationStiffness (both 0.45 retail default), MouseLowPassWindowSec (0.25), CameraAdjustmentSpeed (40.0). DebugPanel mirror lands later; this commit just stands up the static surface + defaults + tests. Per spec docs/superpowers/specs/2026-05-18-retail-chase-camera-design.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
73dee43d14
commit
5945f1d915
2 changed files with 110 additions and 0 deletions
64
src/AcDream.Core/Rendering/CameraDiagnostics.cs
Normal file
64
src/AcDream.Core/Rendering/CameraDiagnostics.cs
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace AcDream.Core.Rendering;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runtime-tunable knobs for the retail-faithful chase camera. Mirrors
|
||||||
|
/// the <see cref="AcDream.Core.Physics.PhysicsDiagnostics"/> pattern:
|
||||||
|
/// static fields seeded from env vars at process start, runtime-settable
|
||||||
|
/// via property setters that the DebugPanel writes to.
|
||||||
|
///
|
||||||
|
/// <para>
|
||||||
|
/// Spec: <c>docs/superpowers/specs/2026-05-18-retail-chase-camera-design.md</c>.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
public static class CameraDiagnostics
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Master toggle. When false (default) the legacy
|
||||||
|
/// <c>AcDream.App.Rendering.ChaseCamera</c> is the active camera;
|
||||||
|
/// when true, the retail-faithful <c>RetailChaseCamera</c> is.
|
||||||
|
/// Initial state from <c>ACDREAM_RETAIL_CHASE=1</c>.
|
||||||
|
/// </summary>
|
||||||
|
public static bool UseRetailChaseCamera { get; set; } =
|
||||||
|
Environment.GetEnvironmentVariable("ACDREAM_RETAIL_CHASE") == "1";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When true (default), the camera basis follows the player's
|
||||||
|
/// 5-frame averaged velocity vector — tilts with the terrain on
|
||||||
|
/// hills. When false, the basis is built from a flat (yaw, 0) vector
|
||||||
|
/// and the camera stays horizontal even on slopes. Initial state
|
||||||
|
/// from <c>ACDREAM_CAMERA_ALIGN_SLOPE</c>; default-on if unset.
|
||||||
|
/// </summary>
|
||||||
|
public static bool AlignToSlope { get; set; } =
|
||||||
|
Environment.GetEnvironmentVariable("ACDREAM_CAMERA_ALIGN_SLOPE") != "0";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Per-frame translation damping rate. Retail default 0.45. Higher
|
||||||
|
/// (→ 1.0) snaps faster; lower (→ 0.0) lags more. Formula per frame:
|
||||||
|
/// <c>alpha = clamp(TranslationStiffness * dt * 10, 0, 1)</c>.
|
||||||
|
/// </summary>
|
||||||
|
public static float TranslationStiffness { get; set; } = 0.45f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Per-frame rotation damping rate. Independent of translation —
|
||||||
|
/// can be tuned higher so the camera swings to look at you faster
|
||||||
|
/// than it physically catches up. Retail default 0.45.
|
||||||
|
/// </summary>
|
||||||
|
public static float RotationStiffness { get; set; } = 0.45f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mouse-delta low-pass window (seconds). Mouse deltas spaced
|
||||||
|
/// closer than this are averaged with the previous delta before
|
||||||
|
/// being fed to pitch/yaw adjustments. Smooths out jitter on
|
||||||
|
/// high-DPI mice. Retail default 0.25.
|
||||||
|
/// </summary>
|
||||||
|
public static float MouseLowPassWindowSec { get; set; } = 0.25f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Per-second rate that held-key offset adjustments
|
||||||
|
/// (CameraZoomIn/Out, CameraRaise/Lower) integrate into the
|
||||||
|
/// camera's Distance / Pitch. Retail default 40.0.
|
||||||
|
/// </summary>
|
||||||
|
public static float CameraAdjustmentSpeed { get; set; } = 40.0f;
|
||||||
|
}
|
||||||
46
tests/AcDream.Core.Tests/Rendering/CameraDiagnosticsTests.cs
Normal file
46
tests/AcDream.Core.Tests/Rendering/CameraDiagnosticsTests.cs
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
using AcDream.Core.Rendering;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace AcDream.Core.Tests.Rendering;
|
||||||
|
|
||||||
|
public class CameraDiagnosticsTests
|
||||||
|
{
|
||||||
|
// NOTE: These tests assume the env vars ACDREAM_RETAIL_CHASE and
|
||||||
|
// ACDREAM_CAMERA_ALIGN_SLOPE are NOT set when running the test
|
||||||
|
// suite. Static class is initialised on first access; values reflect
|
||||||
|
// the env state at that time.
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Defaults_AreRetailValues()
|
||||||
|
{
|
||||||
|
// Reset to defaults explicitly (test isolation; another test may
|
||||||
|
// have flipped these earlier in the run).
|
||||||
|
CameraDiagnostics.TranslationStiffness = 0.45f;
|
||||||
|
CameraDiagnostics.RotationStiffness = 0.45f;
|
||||||
|
CameraDiagnostics.MouseLowPassWindowSec = 0.25f;
|
||||||
|
CameraDiagnostics.CameraAdjustmentSpeed = 40.0f;
|
||||||
|
CameraDiagnostics.AlignToSlope = true;
|
||||||
|
CameraDiagnostics.UseRetailChaseCamera = false;
|
||||||
|
|
||||||
|
Assert.Equal(0.45f, CameraDiagnostics.TranslationStiffness);
|
||||||
|
Assert.Equal(0.45f, CameraDiagnostics.RotationStiffness);
|
||||||
|
Assert.Equal(0.25f, CameraDiagnostics.MouseLowPassWindowSec);
|
||||||
|
Assert.Equal(40.0f, CameraDiagnostics.CameraAdjustmentSpeed);
|
||||||
|
Assert.True(CameraDiagnostics.AlignToSlope);
|
||||||
|
Assert.False(CameraDiagnostics.UseRetailChaseCamera);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Setters_PersistRuntimeChanges()
|
||||||
|
{
|
||||||
|
CameraDiagnostics.TranslationStiffness = 0.8f;
|
||||||
|
CameraDiagnostics.UseRetailChaseCamera = true;
|
||||||
|
|
||||||
|
Assert.Equal(0.8f, CameraDiagnostics.TranslationStiffness);
|
||||||
|
Assert.True(CameraDiagnostics.UseRetailChaseCamera);
|
||||||
|
|
||||||
|
// Reset so other tests aren't poisoned.
|
||||||
|
CameraDiagnostics.TranslationStiffness = 0.45f;
|
||||||
|
CameraDiagnostics.UseRetailChaseCamera = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue