Fix skip completion for visual transitions

This commit is contained in:
gamer147
2026-07-29 17:09:37 -04:00
parent 3378abdeca
commit 09d765d89d
12 changed files with 271 additions and 50 deletions

View File

@@ -92,4 +92,26 @@ public class CoreScalarAndScreenTransitionOpsTests
Assert.Equal(480, LegacyScreenTransitionTiming.DurationMilliseconds(30));
Assert.Equal(1024, LegacyScreenTransitionTiming.DurationMilliseconds(65));
}
[Fact]
public void ActiveAdvSkip_ForcesLegacyScreenTransitionEndpointsAtDispatch()
{
var table = OpcodeTableJson.Load(Paths.OpcodesJson);
var script = ScriptAssembler.Assemble(table, "SKIPPED_SCREEN_TRANSITIONS",
new List<(int, Operand[])>
{
(0x21, new[] { new Operand(Imm, 1), new Operand(Imm, 30) }),
(0x25, new[]
{
new Operand(Imm, 1), new Operand(Imm, 2), new Operand(Imm, 10),
}),
(0x2, Array.Empty<Operand>()),
}, Array.Empty<string>());
var host = new RecordingHost { MessageSkip = true };
new VirtualMachine(script, table, host).Run();
Assert.Equal(new[] { true }, host.SurfaceBlackFadeForceEndpoints);
Assert.Equal(new[] { true }, host.SurfaceCrossfadeForceEndpoints);
}
}

View File

@@ -93,4 +93,47 @@ public class ForegroundTransitionTests
Assert.False(gfx.HasActiveForegroundTransitions(100));
Assert.True(gfx.SnapshotMovieMaskTransitions().Single().Completed);
}
[Fact]
public void ClickCompletionFinishesSurfaceAndOrdinaryOneShotsButPreservesExcludedChannels()
{
var gfx = new GfxState();
gfx.SetSurface(4, 0x25, -1);
gfx.BindDraw(100, 4, 0, 0, 800, 600, 0, 0);
gfx.BindDraw(101, 4, 0, 0, 800, 600, 0, 0);
gfx.SetAnimatedObjectColorResolved(100, 0, 1000, 0, 0xffffff);
gfx.SetScaleChannel(100, 0, 1000, (200, 200, 100));
gfx.SetAnimatedObjectColorResolved(101, 0, 1000, 0, 0xffffff);
gfx.SetOneShotAnimationControl(101, 1);
gfx.SetRotationCycle(100, 1000, (0, 0, 1));
gfx.QueueSurfaceAlphaTransition(102, 6, 101, 1, 100, 1, 0, 1000);
gfx.StartForegroundTransitions(100);
gfx.QueueMovieMaskTransition(new MovieMaskTransitionRequest(
11, 45, 10, 1, -184, 0, 800, 600, 0, 0x325e, 0, 1000));
Assert.Equal(3, gfx.CompleteClickSkippableTimedPresentation(200));
Assert.Equal(1.0, gfx.SnapshotForegroundTransitions(200).Single().Progress);
Assert.False(gfx.TryGet(100)!.OneShotColorEnabled);
Assert.False(gfx.TryGet(100)!.ScaleEnabled);
Assert.True(gfx.TryGet(100)!.RotationEnabled);
Assert.True(gfx.TryGet(101)!.OneShotColorEnabled);
Assert.False(gfx.SnapshotMovieMaskTransitions().Single().Completed);
}
[Theory]
[InlineData(1)]
[InlineData(2)]
[InlineData(3)]
public void AnimationServiceFlagsSuppressClickCompletion(long flags)
{
var gfx = new GfxState();
gfx.SetSurface(4, 0x25, -1);
gfx.BindDraw(100, 4, 0, 0, 800, 600, 0, 0);
gfx.SetAnimatedObjectColorResolved(100, 0, 1000, 0, 0xffffff);
gfx.SetAnimationServiceFlags(flags);
Assert.Equal(0, gfx.CompleteClickSkippableTimedPresentation(100));
Assert.True(gfx.TryGet(100)!.OneShotColorEnabled);
}
}

View File

@@ -60,6 +60,8 @@ internal class RecordingHost : IHost
public readonly List<(int First, int Count)> ReleasedSurfaceRanges = new();
public readonly List<(int Surface, long Interval, SurfaceBlackFadeDirection Direction)> SurfaceBlackFades = new();
public readonly List<(int Source, int Target, long Interval)> SurfaceCrossfades = new();
public readonly List<bool> SurfaceBlackFadeForceEndpoints = new();
public readonly List<bool> SurfaceCrossfadeForceEndpoints = new();
public readonly List<(long Resource, int Slot)> Textures = new();
public readonly List<bool> MessageSkipChanges = new();
public readonly List<bool> PhysicalMessageSkipChanges = new();
@@ -175,10 +177,19 @@ internal class RecordingHost : IHost
gfx.CompleteForegroundTransitions(100);
}
public void FadeSurfaceWithBlack(
GfxState gfx, int surface, long intervalArgument, SurfaceBlackFadeDirection direction)
=> SurfaceBlackFades.Add((surface, intervalArgument, direction));
public void CrossfadeSurfaces(GfxState gfx, int sourceSurface, int targetSurface, long intervalArgument)
=> SurfaceCrossfades.Add((sourceSurface, targetSurface, intervalArgument));
GfxState gfx, int surface, long intervalArgument, SurfaceBlackFadeDirection direction,
bool forceEndpoint = false)
{
SurfaceBlackFades.Add((surface, intervalArgument, direction));
SurfaceBlackFadeForceEndpoints.Add(forceEndpoint);
}
public void CrossfadeSurfaces(
GfxState gfx, int sourceSurface, int targetSurface, long intervalArgument,
bool forceEndpoint = false)
{
SurfaceCrossfades.Add((sourceSurface, targetSurface, intervalArgument));
SurfaceCrossfadeForceEndpoints.Add(forceEndpoint);
}
public void CreateTexture(int slot, int w, int h) { }
public void SetTexture(long resId, int slot) => Textures.Add((resId, slot));
public void ClearRenderTarget(int surfaceSlot) => ClearedRenderTargets.Add(surfaceSlot);