refactor(app): compose settings and developer tools
This commit is contained in:
parent
60a1698ce7
commit
cd7b519f78
24 changed files with 2073 additions and 333 deletions
|
|
@ -283,6 +283,7 @@ public sealed class DevToolsFramePresenterTests
|
|||
|
||||
private sealed class RecordingBackend(List<string> calls) : IDevToolsFrameBackend
|
||||
{
|
||||
public void Dispose() { }
|
||||
public HashSet<string> OpenMenus { get; } = [];
|
||||
public HashSet<string> ClickedItems { get; } = [];
|
||||
public List<(string Label, string? Shortcut, bool Selected)> MenuItems { get; } = [];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
using AcDream.App.Rendering;
|
||||
using AcDream.App.Streaming;
|
||||
|
||||
namespace AcDream.App.Tests.Rendering;
|
||||
|
||||
public sealed class DevToolsRuntimeSourcesTests
|
||||
{
|
||||
[Fact]
|
||||
public void FrameDiagnosticsLateBindingPreservesSeedAndExpectedOwnerRelease()
|
||||
{
|
||||
var source = new DeferredRenderFrameDiagnosticsSource();
|
||||
var first = new FrameSource(144, 6.9);
|
||||
var other = new FrameSource(30, 33.3);
|
||||
|
||||
Assert.Equal(RenderFrameDiagnosticsSnapshot.Initial, source.Snapshot);
|
||||
source.Bind(first);
|
||||
Assert.Equal(144, source.Snapshot.Fps);
|
||||
source.Unbind(other);
|
||||
Assert.Equal(144, source.Snapshot.Fps);
|
||||
source.Unbind(first);
|
||||
Assert.Equal(RenderFrameDiagnosticsSnapshot.Initial, source.Snapshot);
|
||||
|
||||
source.Bind(other);
|
||||
source.Deactivate();
|
||||
Assert.Equal(RenderFrameDiagnosticsSnapshot.Initial, source.Snapshot);
|
||||
Assert.Throws<ObjectDisposedException>(() => source.Bind(first));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FrameDiagnosticsRejectsACompetingCanonicalOwner()
|
||||
{
|
||||
var source = new DeferredRenderFrameDiagnosticsSource();
|
||||
source.Bind(new FrameSource(60, 16.7));
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() =>
|
||||
source.Bind(new FrameSource(120, 8.3)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PlayerModeCommandSlotUsesLiveTargetAndRejectsStaleRelease()
|
||||
{
|
||||
var source = new DeferredDevToolsPlayerModeCommands();
|
||||
var first = new PlayerModeTarget();
|
||||
var other = new PlayerModeTarget();
|
||||
|
||||
source.ToggleFlyOrChase();
|
||||
source.Bind(first);
|
||||
source.ToggleFlyOrChase();
|
||||
source.Unbind(other);
|
||||
source.ToggleFlyOrChase();
|
||||
source.Unbind(first);
|
||||
source.ToggleFlyOrChase();
|
||||
|
||||
Assert.Equal(2, first.ToggleCalls);
|
||||
Assert.Equal(0, other.ToggleCalls);
|
||||
|
||||
source.Bind(other);
|
||||
source.Deactivate();
|
||||
source.ToggleFlyOrChase();
|
||||
Assert.Equal(0, other.ToggleCalls);
|
||||
Assert.Throws<ObjectDisposedException>(() => source.Bind(first));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WorldCountSlotCannotFreezeOrReleaseTheWrongWorld()
|
||||
{
|
||||
var source = new DeferredCanonicalWorldEntityCountSource();
|
||||
var first = new GpuWorldState();
|
||||
var other = new GpuWorldState();
|
||||
|
||||
source.Bind(first);
|
||||
source.Unbind(other);
|
||||
Assert.Throws<InvalidOperationException>(() => source.Bind(other));
|
||||
source.Unbind(first);
|
||||
source.Bind(other);
|
||||
source.Deactivate();
|
||||
|
||||
Assert.Equal(0, source.EntityCount);
|
||||
Assert.Throws<ObjectDisposedException>(() => source.Bind(first));
|
||||
}
|
||||
|
||||
private sealed class FrameSource(double fps, double milliseconds)
|
||||
: IRenderFrameDiagnosticsSnapshotSource
|
||||
{
|
||||
public RenderFrameDiagnosticsSnapshot Snapshot { get; } =
|
||||
RenderFrameDiagnosticsSnapshot.Initial with
|
||||
{
|
||||
Fps = fps,
|
||||
FrameMilliseconds = milliseconds,
|
||||
};
|
||||
}
|
||||
|
||||
private sealed class PlayerModeTarget : IDevToolsPlayerModeTarget
|
||||
{
|
||||
public int ToggleCalls { get; private set; }
|
||||
public void ToggleFlyOrChase() => ToggleCalls++;
|
||||
}
|
||||
}
|
||||
|
|
@ -57,6 +57,22 @@ public sealed class FramebufferResizeControllerTests
|
|||
Assert.Equal(["viewport:800x600", "camera:1.333", "devtools:800x600"], calls);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DevToolsBindingReleasesExpectedTargetWithoutReplayingResize()
|
||||
{
|
||||
var calls = new List<string>();
|
||||
var owner = new FramebufferResizeController(new ViewportAspectState());
|
||||
var target = new DevTools(calls);
|
||||
using var binding = new FramebufferDevToolsBinding(owner, target);
|
||||
|
||||
owner.Resize(900, 700);
|
||||
binding.Dispose();
|
||||
binding.Dispose();
|
||||
owner.Resize(1000, 800);
|
||||
|
||||
Assert.Equal(["devtools:900x700"], calls);
|
||||
}
|
||||
|
||||
private sealed class Viewport(List<string> calls) : IFramebufferViewportTarget
|
||||
{
|
||||
public void ResizeViewport(int width, int height) =>
|
||||
|
|
|
|||
|
|
@ -94,7 +94,13 @@ public sealed class GameWindowRenderLeafCompositionTests
|
|||
Assert.DoesNotContain(identifier, source, StringComparison.Ordinal);
|
||||
|
||||
Assert.Contains("new AcDream.App.Rendering.PaperdollFramePresenter(", source);
|
||||
Assert.Contains("new AcDream.App.Rendering.DevToolsFramePresenter(", source);
|
||||
string settingsComposition = File.ReadAllText(Path.Combine(
|
||||
FindRepoRoot(),
|
||||
"src",
|
||||
"AcDream.App",
|
||||
"Composition",
|
||||
"SettingsDevToolsComposition.cs"));
|
||||
Assert.Contains("new DevToolsFramePresenter(", settingsComposition);
|
||||
Assert.Contains("new AcDream.App.Rendering.RenderFrameResourceController(", source);
|
||||
Assert.Contains("new AcDream.App.Rendering.RenderWeatherFrameController(", source);
|
||||
Assert.Contains("new AcDream.App.Rendering.PrivatePresentationRenderer(", source);
|
||||
|
|
@ -119,7 +125,7 @@ public sealed class GameWindowRenderLeafCompositionTests
|
|||
"new ResourceShutdownStage(\"submitted GPU work\"",
|
||||
"new ResourceShutdownStage(\"render frontends\"",
|
||||
"new(\"developer tools\"",
|
||||
"_devToolsBackend?.Dispose()",
|
||||
"owner.DisposeFrontend()",
|
||||
"new(\"portal tunnel\"",
|
||||
"new(\"paperdoll viewport\"",
|
||||
"new ResourceShutdownStage(\"OpenGL context\"");
|
||||
|
|
@ -135,7 +141,7 @@ public sealed class GameWindowRenderLeafCompositionTests
|
|||
AssertAppearsInOrder(
|
||||
source,
|
||||
"_frameGraphs.Withdraw();",
|
||||
"_devToolsBackend?.Dispose()",
|
||||
"owner.DisposeFrontend()",
|
||||
"new ResourceShutdownStage(\"input\"",
|
||||
"_input?.Dispose();",
|
||||
"new ResourceShutdownStage(\"OpenGL context\"");
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ public sealed class GameWindowSlice8BoundaryTests
|
|||
"this).Compose(platform);",
|
||||
"new ContentEffectsAudioCompositionPhase(",
|
||||
"this).Compose(platform, hostInputCamera);",
|
||||
"_runtimeSettings.ApplyStartup(",
|
||||
"new RuntimeSettingsStartupTargets(",
|
||||
"new SettingsDevToolsCompositionPhase(",
|
||||
"this).Compose(platform, hostInputCamera, contentEffectsAudio);",
|
||||
"_uiHost = _retailUiLease.AcquireHost(",
|
||||
"_uiHost.WireMouse(m)",
|
||||
"_uiHost.WireKeyboard(kb)",
|
||||
|
|
@ -138,10 +138,19 @@ public sealed class GameWindowSlice8BoundaryTests
|
|||
|
||||
Assert.DoesNotContain("private void CycleTimeOfDay()", source, StringComparison.Ordinal);
|
||||
Assert.DoesNotContain("private void CycleWeather()", source, StringComparison.Ordinal);
|
||||
string settingsPhase = File.ReadAllText(Path.Combine(
|
||||
FindRepoRoot(),
|
||||
"src",
|
||||
"AcDream.App",
|
||||
"Composition",
|
||||
"SettingsDevToolsComposition.cs"));
|
||||
AssertAppearsInOrder(
|
||||
settingsPhase,
|
||||
"debugVm.CycleTimeOfDay = _dependencies.DiagnosticCommands.CycleTimeOfDay;",
|
||||
"debugVm.CycleWeather = _dependencies.DiagnosticCommands.CycleWeather;",
|
||||
"debugVm.ToggleCollisionWires =");
|
||||
AssertAppearsInOrder(
|
||||
load,
|
||||
"_debugVm.CycleTimeOfDay =",
|
||||
"_runtimeDiagnosticCommands.CycleTimeOfDay;",
|
||||
"new AcDream.App.Diagnostics.RuntimeDiagnosticCommandController(",
|
||||
"_runtimeDiagnosticCommands.Bind(runtimeDiagnostics);");
|
||||
}
|
||||
|
|
@ -267,11 +276,21 @@ public sealed class GameWindowSlice8BoundaryTests
|
|||
"Window.Create(options)");
|
||||
AssertAppearsInOrder(
|
||||
load,
|
||||
"_runtimeSettings.ApplyStartup(",
|
||||
"if (DevToolsEnabled)",
|
||||
"new SettingsDevToolsCompositionPhase(",
|
||||
"this).Compose(platform, hostInputCamera, contentEffectsAudio);",
|
||||
"TerrainAtlas.Build(",
|
||||
"_runtimeSettings.BindRuntimeTargets(",
|
||||
"_liveSessionHost.Start(_options)");
|
||||
string settingsPhase = File.ReadAllText(Path.Combine(
|
||||
FindRepoRoot(),
|
||||
"src",
|
||||
"AcDream.App",
|
||||
"Composition",
|
||||
"SettingsDevToolsComposition.cs"));
|
||||
AssertAppearsInOrder(
|
||||
settingsPhase,
|
||||
"_dependencies.Settings.ApplyStartup(_dependencies.StartupTarget);",
|
||||
"_dependencies.DevTools is { } optional");
|
||||
AssertAppearsInOrder(
|
||||
shutdown,
|
||||
"_runtimeSettings.UnbindViewModel()",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue