fix(render): harden portal exit handoff
This commit is contained in:
parent
ddbd7e4096
commit
82e4b4cb6d
17 changed files with 896 additions and 119 deletions
|
|
@ -168,6 +168,31 @@ public sealed class TeleportAnimSequencerTests
|
|||
Assert.Contains(TeleportAnimEvent.Place, evts);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DiagnosticHold_KeepsReadyPortalInStableTunnelUntilReleased()
|
||||
{
|
||||
var seq = new TeleportAnimSequencer();
|
||||
seq.Begin(TeleportEntryKind.Portal);
|
||||
|
||||
var (_, heldEvents) = seq.Tick(
|
||||
dt: 30f,
|
||||
worldReady: true,
|
||||
tunnelAnimationFrame: 72,
|
||||
holdInTunnel: true);
|
||||
|
||||
Assert.Equal(TeleportAnimState.Tunnel, seq.State);
|
||||
Assert.DoesNotContain(TeleportAnimEvent.Place, heldEvents);
|
||||
|
||||
var (_, releasedEvents) = seq.Tick(
|
||||
dt: 0f,
|
||||
worldReady: true,
|
||||
tunnelAnimationFrame: 72,
|
||||
holdInTunnel: false);
|
||||
|
||||
Assert.Equal(TeleportAnimState.TunnelContinue, seq.State);
|
||||
Assert.Contains(TeleportAnimEvent.Place, releasedEvents);
|
||||
}
|
||||
|
||||
// --- TunnelContinue: MIN_CONTINUE hold then TunnelFadeOut ---
|
||||
|
||||
[Fact]
|
||||
|
|
@ -301,6 +326,44 @@ public sealed class TeleportAnimSequencerTests
|
|||
framesPerSecond);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TunnelFadeOut_SwapsAfterLastFullViewportCaptureLevel()
|
||||
{
|
||||
Assert.Equal((short)1001, TeleportAnimSequencer.LastVisibleOutgoingAnimationLevel);
|
||||
|
||||
var seq = new TeleportAnimSequencer();
|
||||
seq.Begin(TeleportEntryKind.Portal);
|
||||
seq.Tick(0f, worldReady: false);
|
||||
seq.Tick(0.016f, worldReady: true);
|
||||
seq.Tick(
|
||||
TeleportAnimSequencer.MinContinue,
|
||||
worldReady: true,
|
||||
tunnelAnimationFrame: 72);
|
||||
Assert.Equal(TeleportAnimState.TunnelFadeOut, seq.State);
|
||||
|
||||
float lastSafeTime = Enumerable.Range(0, 1001)
|
||||
.Select(static i => i / 1000f)
|
||||
.First(t => TeleportAnimSequencer.GetRetailAnimationLevel(t)
|
||||
== TeleportAnimSequencer.LastVisibleOutgoingAnimationLevel);
|
||||
float firstUnsafeTime = Enumerable.Range(0, 1001)
|
||||
.Select(static i => i / 1000f)
|
||||
.First(t => TeleportAnimSequencer.GetRetailAnimationLevel(t)
|
||||
> TeleportAnimSequencer.LastVisibleOutgoingAnimationLevel);
|
||||
|
||||
var (lastSafe, _) = seq.Tick(lastSafeTime, worldReady: true);
|
||||
Assert.Equal(TeleportAnimState.TunnelFadeOut, lastSafe.State);
|
||||
Assert.Equal(
|
||||
TeleportAnimSequencer.LastVisibleOutgoingAnimationLevel / 1024f,
|
||||
lastSafe.ViewPlaneBlend);
|
||||
|
||||
var (swapped, events) = seq.Tick(
|
||||
firstUnsafeTime - lastSafeTime,
|
||||
worldReady: true);
|
||||
Assert.Equal(TeleportAnimState.WorldFadeIn, swapped.State);
|
||||
Assert.False(swapped.ShowTunnel);
|
||||
Assert.Contains(TeleportAnimEvent.PlayExitSound, events);
|
||||
}
|
||||
|
||||
private static void AssertOutgoingViewportRetiresBeforeTerminal(
|
||||
TeleportAnimSequencer seq,
|
||||
TeleportAnimState outgoingState,
|
||||
|
|
@ -314,7 +377,8 @@ public sealed class TeleportAnimSequencerTests
|
|||
if (snapshot.State == outgoingState)
|
||||
{
|
||||
Assert.True(
|
||||
snapshot.ViewPlaneBlend <= 1022f / 1024f,
|
||||
snapshot.ViewPlaneBlend
|
||||
<= TeleportAnimSequencer.LastVisibleOutgoingAnimationLevel / 1024f,
|
||||
$"Published unsafe outgoing blend {snapshot.ViewPlaneBlend}.");
|
||||
continue;
|
||||
}
|
||||
|
|
@ -384,8 +448,13 @@ public sealed class TeleportAnimSequencerTests
|
|||
seq.Begin(TeleportEntryKind.Logout);
|
||||
seq.Tick(0f, worldReady: false); // consume enter-sound tick, elapsed≈0
|
||||
|
||||
// Drive to just BEFORE the transition (so we're still in WorldFadeOut)
|
||||
DriveSeconds(seq, TeleportAnimSequencer.FadeTime - 0.03f, worldReady: false);
|
||||
float lastSafeTime = Enumerable.Range(0, 1001)
|
||||
.Select(static i => i / 1000f)
|
||||
.First(t => TeleportAnimSequencer.GetRetailAnimationLevel(t)
|
||||
== TeleportAnimSequencer.LastVisibleOutgoingAnimationLevel);
|
||||
|
||||
// Drive directly to the last full-viewport quantized table level.
|
||||
seq.Tick(lastSafeTime, worldReady: false);
|
||||
Assert.Equal(TeleportAnimState.WorldFadeOut, seq.State);
|
||||
|
||||
var (snap, _) = seq.Tick(0f, worldReady: false);
|
||||
|
|
@ -393,7 +462,9 @@ public sealed class TeleportAnimSequencerTests
|
|||
Assert.True(
|
||||
snap.ViewPlaneBlend > 0.95f,
|
||||
$"Expected ViewPlaneBlend near 1, got {snap.ViewPlaneBlend}");
|
||||
Assert.True(snap.ViewPlaneBlend <= 1022f / 1024f);
|
||||
Assert.True(
|
||||
snap.ViewPlaneBlend
|
||||
<= TeleportAnimSequencer.LastVisibleOutgoingAnimationLevel / 1024f);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue