feat(render): implement Campaign AR and terrain fidelity

This commit is contained in:
Erik 2026-08-22 13:13:29 +02:00
parent 99cf26e00c
commit 7a5f96ede5
368 changed files with 50611 additions and 950 deletions

View file

@ -41,10 +41,65 @@ public sealed class RetailUiAutomationProbeTests
public bool IsWorldReady { get; set; }
public bool IsWorldViewportVisible { get; set; }
public int PortalMaterializationCount { get; set; }
public int RenderPackPerformanceSampleCount { get; set; }
public bool RenderPackFailedToRetail { get; set; }
public RetailUiAutomationRenderPackStatus RenderPackStatus { get; set; } =
RetailUiAutomationRenderPackStatus.Retail;
public int FramebufferWidth { get; set; } = 1280;
public int FramebufferHeight { get; set; } = 720;
public int RenderPackPerformanceResetCount { get; private set; }
public List<string> RenderPackSelections { get; } = [];
public int RenderPackDisableCount { get; private set; }
public int RenderPackReenableCount { get; private set; }
public List<(int Width, int Height)> FramebufferResizes { get; } = [];
public int ClientCloseRequestCount { get; private set; }
public List<string> Checkpoints { get; } = new();
public HashSet<string> ScreenshotRequests { get; } = new();
public HashSet<string> CompletedScreenshots { get; } = new();
public bool TryResetRenderPackPerformance(out string error)
{
RenderPackPerformanceResetCount++;
RenderPackPerformanceSampleCount = 0;
error = string.Empty;
return true;
}
public bool TrySelectRenderPack(string presetId, out string error)
{
RenderPackSelections.Add(presetId);
error = string.Empty;
return true;
}
public bool TryDisableRenderPack(out string error)
{
RenderPackDisableCount++;
error = string.Empty;
return true;
}
public bool TryReenableRenderPack(out string error)
{
RenderPackReenableCount++;
error = string.Empty;
return true;
}
public bool TryResizeFramebuffer(int width, int height, out string error)
{
FramebufferResizes.Add((width, height));
error = string.Empty;
return true;
}
public bool TryRequestClientClose(out string error)
{
ClientCloseRequestCount++;
error = string.Empty;
return true;
}
public bool TryRequestCheckpoint(
string name,
out IRetailUiAutomationCheckpoint? checkpoint,
@ -654,6 +709,199 @@ public sealed class RetailUiAutomationProbeTests
}
}
[Fact]
public void ScriptRunner_resetsThenWaitsForCompleteRenderPackEvidenceWindow()
{
var (root, _, _, _, objects) = RootWithTwoItemLists();
var runtime = new FakeRuntime
{
RenderPackPerformanceSampleCount = 1200,
};
var probe = new RetailUiAutomationProbe(root, objects);
string path = Path.Combine(
Path.GetTempPath(),
Path.GetRandomFileName() + ".ui-probe.txt");
File.WriteAllLines(path,
[
"renderpack reset-performance",
"wait render-pack-samples 2048 1000",
"screenshot complete-window 1000",
]);
try
{
using var runner = new RetailUiAutomationScriptRunner(
probe,
path,
dumpOnStart: false,
runtime: runtime);
runner.Tick(0d);
Assert.Equal(1, runtime.RenderPackPerformanceResetCount);
Assert.Equal(0, runtime.RenderPackPerformanceSampleCount);
Assert.Empty(runtime.ScreenshotRequests);
runtime.RenderPackPerformanceSampleCount = 2047;
runner.Tick(0.5d);
Assert.Empty(runtime.ScreenshotRequests);
runtime.RenderPackPerformanceSampleCount = 2048;
runner.Tick(0.001d);
Assert.Contains("complete-window", runtime.ScreenshotRequests);
Assert.False(runner.Completed);
runtime.CompletedScreenshots.Add("complete-window");
runner.Tick(0.001d);
Assert.True(runner.Completed);
}
finally
{
File.Delete(path);
}
}
[Fact]
public void ScriptRunner_renderPackWaitTerminatesEarlyForFailedToRetailFallback()
{
var (root, _, _, _, objects) = RootWithTwoItemLists();
var runtime = new FakeRuntime
{
RenderPackFailedToRetail = true,
};
var probe = new RetailUiAutomationProbe(root, objects);
string path = Path.Combine(
Path.GetTempPath(),
Path.GetRandomFileName() + ".ui-probe.txt");
File.WriteAllLines(path,
[
"renderpack reset-performance",
"wait render-pack-samples 2048 300000",
"screenshot safe-fallback 1000",
]);
try
{
using var runner = new RetailUiAutomationScriptRunner(
probe,
path,
dumpOnStart: false,
runtime: runtime);
runner.Tick(0d);
Assert.Equal(1, runtime.RenderPackPerformanceResetCount);
Assert.Equal(0, runtime.RenderPackPerformanceSampleCount);
Assert.Contains("safe-fallback", runtime.ScreenshotRequests);
Assert.False(runner.Completed);
runtime.CompletedScreenshots.Add("safe-fallback");
runner.Tick(0.001d);
Assert.True(runner.Completed);
}
finally
{
File.Delete(path);
}
}
[Fact]
public void ScriptRunner_renderPackTransitionsAndResizeWaitForPublishedRuntimeState()
{
var (root, _, _, _, objects) = RootWithTwoItemLists();
var runtime = new FakeRuntime();
var probe = new RetailUiAutomationProbe(root, objects);
string path = Path.Combine(
Path.GetTempPath(),
Path.GetRandomFileName() + ".ui-probe.txt");
File.WriteAllLines(path,
[
"renderpack select high",
"wait render-pack high 1000",
"renderpack disable",
"wait render-pack retail 1000",
"renderpack reenable",
"wait render-pack high 1000",
"resize 1024 768",
"wait framebuffer 1024 768 1000",
]);
try
{
using var runner = new RetailUiAutomationScriptRunner(
probe,
path,
dumpOnStart: false,
runtime: runtime);
runner.Tick(0d);
Assert.Equal(["high"], runtime.RenderPackSelections);
Assert.False(runner.Completed);
runtime.RenderPackStatus = new RetailUiAutomationRenderPackStatus(
RetailUiAutomationRenderPackState.Active,
"acdream.atmospheric",
"high",
ActivationGeneration: 1,
FailureReason: null);
runner.Tick(0.001d);
Assert.Equal(1, runtime.RenderPackDisableCount);
runtime.RenderPackStatus = RetailUiAutomationRenderPackStatus.Retail;
runner.Tick(0.001d);
Assert.Equal(1, runtime.RenderPackReenableCount);
runtime.RenderPackStatus = new RetailUiAutomationRenderPackStatus(
RetailUiAutomationRenderPackState.Active,
"acdream.atmospheric",
"high",
ActivationGeneration: 3,
FailureReason: null);
runner.Tick(0.001d);
Assert.Equal([(1024, 768)], runtime.FramebufferResizes);
Assert.False(runner.Completed);
runtime.FramebufferWidth = 1024;
runtime.FramebufferHeight = 768;
runner.Tick(0.001d);
Assert.True(runner.Completed);
}
finally
{
File.Delete(path);
}
}
[Fact]
public void ScriptRunner_closeClientRequestsNormalRuntimeShutdownExactlyOnce()
{
var (root, _, _, _, objects) = RootWithTwoItemLists();
var runtime = new FakeRuntime();
var probe = new RetailUiAutomationProbe(root, objects);
string path = Path.Combine(
Path.GetTempPath(),
Path.GetRandomFileName() + ".ui-probe.txt");
File.WriteAllText(path, "close-client");
try
{
using var runner = new RetailUiAutomationScriptRunner(
probe,
path,
dumpOnStart: false,
runtime: runtime);
runner.Tick(0d);
runner.Tick(0d);
Assert.True(runner.Completed);
Assert.Equal(1, runtime.ClientCloseRequestCount);
}
finally
{
File.Delete(path);
}
}
[Theory]
[InlineData(RetailUiAutomationCheckpointStatus.Failed, "deferred write failed")]
[InlineData(RetailUiAutomationCheckpointStatus.Cancelled, "shutdown cancelled")]