fix(selection): port SmartBox click lighting pulse

Port the retail high/low material-lighting cadence for successful world clicks, keep it instance-scoped in the modern renderer, and restore authored lighting after 0.8 seconds. Correct the selection oracle and pin timing plus per-frame buffer lifecycle with tests.

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-17 23:00:04 +02:00
parent 146a963aeb
commit ea4f52ec51
11 changed files with 338 additions and 16 deletions

View file

@ -0,0 +1,75 @@
using AcDream.App.Rendering.Selection;
namespace AcDream.App.Tests.Rendering;
public sealed class RetailSelectionLightingPulseTests
{
[Fact]
public void ClickRunsRetailHighLowHighLowRestoreCadence()
{
double now = 10d;
var pulse = new RetailSelectionLightingPulse(() => now);
pulse.Start(0x5000_1234u);
AssertLighting(pulse, 0x5000_1234u, RetailSelectionLighting.High);
now = 10.199;
pulse.Tick();
AssertLighting(pulse, 0x5000_1234u, RetailSelectionLighting.High);
now = 10.2;
pulse.Tick();
AssertLighting(pulse, 0x5000_1234u, RetailSelectionLighting.Low);
now = 10.4;
pulse.Tick();
AssertLighting(pulse, 0x5000_1234u, RetailSelectionLighting.High);
now = 10.6;
pulse.Tick();
AssertLighting(pulse, 0x5000_1234u, RetailSelectionLighting.Low);
now = 10.8;
pulse.Tick();
Assert.False(pulse.TryGet(0x5000_1234u, out _));
}
[Fact]
public void LongFrameAdvancesOnlyOneRetailGlobalLoopFlip()
{
double now = 1d;
var pulse = new RetailSelectionLightingPulse(() => now);
pulse.Start(0x5000_1234u);
now = 20d;
pulse.Tick();
AssertLighting(pulse, 0x5000_1234u, RetailSelectionLighting.Low);
}
[Fact]
public void NewClickRestoresOldTargetAndRestartsHighOnNewTarget()
{
double now = 4d;
var pulse = new RetailSelectionLightingPulse(() => now);
pulse.Start(0x5000_0001u);
now = 4.2;
pulse.Tick();
AssertLighting(pulse, 0x5000_0001u, RetailSelectionLighting.Low);
pulse.Start(0x5000_0002u);
Assert.False(pulse.TryGet(0x5000_0001u, out _));
AssertLighting(pulse, 0x5000_0002u, RetailSelectionLighting.High);
}
private static void AssertLighting(
RetailSelectionLightingPulse pulse,
uint serverGuid,
RetailSelectionLighting expected)
{
Assert.True(pulse.TryGet(serverGuid, out var actual));
Assert.Equal(expected, actual);
}
}