Implement legacy black surface fades
This commit is contained in:
@@ -3193,10 +3193,14 @@ black/white scratch alpha to 255. Re-entry finalizes the named endpoint before s
|
|||||||
Himegari uses only the black pair: three `0x21` calls and eight `0x22` calls, all `(1,30)` and therefore
|
Himegari uses only the black pair: three `0x21` calls and eight `0x22` calls, all `(1,30)` and therefore
|
||||||
about 480 ms. The scripts first select surface 1, clear it, publish a complete retained frame through
|
about 480 ms. The scripts first select surface 1, clear it, publish a complete retained frame through
|
||||||
`0x20c`, restore the backbuffer, then fade. `0x21` is the menu-entry reveal; `0x22` is the corresponding
|
`0x20c`, restore the backbuffer, then fade. `0x21` is the menu-entry reveal; `0x22` is the corresponding
|
||||||
menu/scene exit to black. Together they close 11 of the 39 remaining skipped instructions across seven
|
menu/scene exit to black.
|
||||||
distinct scripts. Implementation should extend the existing `LegacyScreenTransition` host path with an
|
|
||||||
explicit solid-color endpoint; treating a missing numbered surface as black is unsafe because the current
|
The port dispatches both opcodes through the existing blocking `LegacyScreenTransition` clock and terminal
|
||||||
mode-4 fallback snapshots the live retained frame.
|
publication path. Its compositor already clears the whole frame to opaque black, so an empty source list
|
||||||
|
models black-to-captured and an empty target list models captured-to-black without overloading the mode-4
|
||||||
|
missing-surface fallback (which intentionally snapshots the live retained frame). This closes 11 formerly
|
||||||
|
skipped instructions across seven distinct scripts and reduces the effectful-gap inventory from 18 to 16
|
||||||
|
distinct opcodes / 28 instructions.
|
||||||
|
|
||||||
The same manual pass exposed a resource-addressing issue after `0x6c` was fixed: ROOM did execute
|
The same manual pass exposed a resource-addressing issue after `0x6c` was fixed: ROOM did execute
|
||||||
`play-voice`, but `GodotAdvHost` attempted only inferred SC-section resolution. ROOM's voice operands
|
`play-voice`, but `GodotAdvHost` attempted only inferred SC-section resolution. ROOM's voice operands
|
||||||
|
|||||||
@@ -658,12 +658,16 @@ SC0000 label_1235a reaches this when 0x1c7/0x1cc are zero. Native run-state bit
|
|||||||
- **depends on:** 0x20c, 0x20d
|
- **depends on:** 0x20c, 0x20d
|
||||||
- **evidence:** Ghidra /v2: dispatch slot 0x21 resolves to op_0x21_fade_surface_in_from_black@0x41cb00. First entry sets run-state bit 8, converts timing <=64 to interval=argument ms and alpha step=16 (otherwise interval=argument/16 and step=1), then starts screen_transition_begin@0x439da0 mode 0 with the operand surface. screen_transition_tick@0x43a7a0 draws that surface below an opaque-black scratch surface whose alpha falls 255->0; re-entry finalizes the operand surface. Corpus: 3 sites in EVOLVE, SELSTAGE, and STUDY, all (1,30), approximately 480 ms.
|
- **evidence:** Ghidra /v2: dispatch slot 0x21 resolves to op_0x21_fade_surface_in_from_black@0x41cb00. First entry sets run-state bit 8, converts timing <=64 to interval=argument ms and alpha step=16 (otherwise interval=argument/16 and step=1), then starts screen_transition_begin@0x439da0 mode 0 with the operand surface. screen_transition_tick@0x43a7a0 draws that surface below an opaque-black scratch surface whose alpha falls 255->0; re-entry finalizes the operand surface. Corpus: 3 sites in EVOLVE, SELSTAGE, and STUDY, all (1,30), approximately 480 ms.
|
||||||
|
|
||||||
|
Port status (2026-07-29): implemented through the blocking legacy full-frame transition host path. An explicit empty/black source endpoint is composited beneath the captured target; timing and terminal-frame publication share the op-0x25 lifecycle.
|
||||||
|
|
||||||
### 0x22 `fade-surface-out-to-black` (u00418920, argc 2)
|
### 0x22 `fade-surface-out-to-black` (u00418920, argc 2)
|
||||||
- **summary:** (surface_slot)(timing_argument) — block while fading a captured full-frame surface to black. Black remains the terminal frame.
|
- **summary:** (surface_slot)(timing_argument) — block while fading a captured full-frame surface to black. Black remains the terminal frame.
|
||||||
- **grounding:** source=investigation, confidence=high
|
- **grounding:** source=investigation, confidence=high
|
||||||
- **depends on:** 0x20c, 0x20d
|
- **depends on:** 0x20c, 0x20d
|
||||||
- **evidence:** Ghidra /v2: dispatch slot 0x22 resolves to op_0x22_fade_surface_out_to_black@0x41cbc0. It uses the same timer/alpha-step conversion as 0x21 and 0x25, then starts screen_transition_begin@0x439da0 mode 1. screen_transition_tick@0x43a7a0 keeps the operand surface opaque and raises the black scratch-surface alpha 0->255; re-entry finalizes a black endpoint. Corpus: 8 sites across ALCHEMY, CHMENU, EVOLVE, FORT, SELSTAGE, STUDY, and SUMMON, all (1,30), approximately 480 ms.
|
- **evidence:** Ghidra /v2: dispatch slot 0x22 resolves to op_0x22_fade_surface_out_to_black@0x41cbc0. It uses the same timer/alpha-step conversion as 0x21 and 0x25, then starts screen_transition_begin@0x439da0 mode 1. screen_transition_tick@0x43a7a0 keeps the operand surface opaque and raises the black scratch-surface alpha 0->255; re-entry finalizes a black endpoint. Corpus: 8 sites across ALCHEMY, CHMENU, EVOLVE, FORT, SELSTAGE, STUDY, and SUMMON, all (1,30), approximately 480 ms.
|
||||||
|
|
||||||
|
Port status (2026-07-29): implemented through the blocking legacy full-frame transition host path. The captured source is composited beneath an explicit empty/black target endpoint; timing and terminal-frame publication share the op-0x25 lifecycle.
|
||||||
|
|
||||||
### 0x23 `fade-surface-in-from-white` (u004189D0, argc 2)
|
### 0x23 `fade-surface-in-from-white` (u004189D0, argc 2)
|
||||||
- **summary:** (surface_slot)(timing_argument) — broader-AGE mode-2 sibling of 0x21: block while fading from white to a captured full-frame surface.
|
- **summary:** (surface_slot)(timing_argument) — broader-AGE mode-2 sibling of 0x21: block while fading from white to a captured full-frame surface.
|
||||||
- **grounding:** source=investigation, confidence=high
|
- **grounding:** source=investigation, confidence=high
|
||||||
|
|||||||
@@ -828,9 +828,9 @@ native defaults, category isolation, getter/setter round trips, idempotent route
|
|||||||
selectors, native and redirected path resolution, CP932 INI preservation, and persistence. All 476 engine tests, the
|
selectors, native and redirected path resolution, CP932 INI preservation, and persistence. All 476 engine tests, the
|
||||||
warning-free Godot build, opcode lint, and the Himegari-targeted threaded selftest pass.
|
warning-free Godot build, opcode lint, and the Himegari-targeted threaded selftest pass.
|
||||||
|
|
||||||
**Post-tranche rerank:** a fresh 481-script aggregate confirms exactly 18 effectful gaps totaling only
|
**Post-tranche rerank:** a fresh 481-script aggregate found exactly 18 effectful gaps totaling only
|
||||||
39 instructions. The widest are unknown `0x22` (eight sites across seven scripts), unknown `0x230`
|
39 instructions. The widest were `0x22` (eight sites across seven scripts), `0x230`
|
||||||
(six sites across two scripts), then `0x21` and `0x1b2` (three sites each); every other gap has at most two
|
(six sites across two scripts), then `0x21` and `0x1b2` (three sites each); every other gap had at most two
|
||||||
sites. CONFIG itself is now 1659/1665 instructions implemented, with four unrelated calls remaining
|
sites. CONFIG itself is now 1659/1665 instructions implemented, with four unrelated calls remaining
|
||||||
(`0x142` twice, `0xb7`, and `0xb8`).
|
(`0x142` twice, `0xb7`, and `0xb8`).
|
||||||
|
|
||||||
@@ -841,11 +841,19 @@ timer conversion and full-frame snapshot lifecycle. All 11 combined Himegari sit
|
|||||||
480 ms, across menu entry/exit paths. The existing `LegacyScreenTransition` host seam can own the pair,
|
480 ms, across menu entry/exit paths. The existing `LegacyScreenTransition` host seam can own the pair,
|
||||||
but it needs an explicit black endpoint rather than its mode-4 missing-surface fallback.
|
but it needs an explicit black endpoint rather than its mode-4 missing-surface fallback.
|
||||||
|
|
||||||
The follow-up `0x230(handle)` is also decoded: it clears the retained object's cyclic active flag and five
|
**Black-fade pair implemented (2026-07-29):** `0x21` and `0x22` now dispatch through the shared blocking
|
||||||
|
full-frame transition path. The compositor represents the solid-black side explicitly as an empty captured
|
||||||
|
object list over its normal opaque-black clear: source-empty for black-to-surface and target-empty for
|
||||||
|
surface-to-black. This preserves mode-4 `0x25`'s separate missing-target fallback, shares the native timing
|
||||||
|
conversion and exact terminal-frame publication, and closes all 11 sites. The remaining effectful inventory
|
||||||
|
is 16 distinct opcodes / 28 instructions. All 477 engine tests, opcode build/lint, the zero-warning Godot
|
||||||
|
build, and the Himegari-targeted threaded selftest pass.
|
||||||
|
|
||||||
|
The follow-up `0x230(handle)` is decoded: it clears the retained object's cyclic active flag and five
|
||||||
looping-channel start/period pairs without changing current/base transforms. Its six calls are five
|
looping-channel start/period pairs without changing current/base transforms. Its six calls are five
|
||||||
DEBUGADV effect demonstrations plus one FIELD movement setup.
|
DEBUGADV effect demonstrations plus one FIELD movement setup.
|
||||||
|
|
||||||
**NEXT:** implement `0x21` and `0x22` together as one black-fade slice, then implement `0x230`.
|
**NEXT:** implement `0x230`.
|
||||||
|
|
||||||
## Later Phase B breadth
|
## Later Phase B breadth
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Age.Engine.Hosting;
|
||||||
using Age.Engine.Model;
|
using Age.Engine.Model;
|
||||||
using Age.Engine.Sys4;
|
using Age.Engine.Sys4;
|
||||||
using Age.Engine.Vm;
|
using Age.Engine.Vm;
|
||||||
@@ -48,6 +49,31 @@ public class CoreScalarAndScreenTransitionOpsTests
|
|||||||
Assert.InRange(vm.Globals[0x100], 0, 3);
|
Assert.InRange(vm.Globals[0x100], 0, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BlackSurfaceFades_ForwardCapturedSlotTimingAndDirection()
|
||||||
|
{
|
||||||
|
var table = OpcodeTableJson.Load(Paths.OpcodesJson);
|
||||||
|
var script = ScriptAssembler.Assemble(table, "SURFACE_BLACK_FADES", new List<(int, Operand[])>
|
||||||
|
{
|
||||||
|
(0x21, new[] { new Operand(Imm, 1), new Operand(Imm, 30) }),
|
||||||
|
(0x22, new[] { new Operand(Imm, 2), new Operand(Imm, 65) }),
|
||||||
|
(0x2, Array.Empty<Operand>()),
|
||||||
|
}, Array.Empty<string>());
|
||||||
|
var host = new RecordingHost();
|
||||||
|
|
||||||
|
new VirtualMachine(script, table, host).Run();
|
||||||
|
|
||||||
|
Assert.Equal(
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
(1, 30L, SurfaceBlackFadeDirection.FromBlack),
|
||||||
|
(2, 65L, SurfaceBlackFadeDirection.ToBlack),
|
||||||
|
},
|
||||||
|
host.SurfaceBlackFades);
|
||||||
|
Assert.Equal(480, LegacyScreenTransitionTiming.DurationMilliseconds(30));
|
||||||
|
Assert.Equal(1024, LegacyScreenTransitionTiming.DurationMilliseconds(65));
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CrossfadeSurfaces_ForwardsBothCapturedSlotsAndTimingArgument()
|
public void CrossfadeSurfaces_ForwardsBothCapturedSlotsAndTimingArgument()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ internal class RecordingHost : IHost
|
|||||||
public readonly List<(long Resource, int Surface, long Flags)> ModalMovies = new();
|
public readonly List<(long Resource, int Surface, long Flags)> ModalMovies = new();
|
||||||
public readonly List<int> ClearedRenderTargets = new();
|
public readonly List<int> ClearedRenderTargets = new();
|
||||||
public readonly List<(int First, int Count)> ReleasedSurfaceRanges = new();
|
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<(int Source, int Target, long Interval)> SurfaceCrossfades = new();
|
||||||
public readonly List<(long Resource, int Slot)> Textures = new();
|
public readonly List<(long Resource, int Slot)> Textures = new();
|
||||||
public readonly List<bool> MessageSkipChanges = new();
|
public readonly List<bool> MessageSkipChanges = new();
|
||||||
@@ -154,6 +155,9 @@ internal class RecordingHost : IHost
|
|||||||
gfx.StartForegroundTransitions(100);
|
gfx.StartForegroundTransitions(100);
|
||||||
gfx.CompleteForegroundTransitions(100);
|
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)
|
public void CrossfadeSurfaces(GfxState gfx, int sourceSurface, int targetSurface, long intervalArgument)
|
||||||
=> SurfaceCrossfades.Add((sourceSurface, targetSurface, intervalArgument));
|
=> SurfaceCrossfades.Add((sourceSurface, targetSurface, intervalArgument));
|
||||||
public void CreateTexture(int slot, int w, int h) { }
|
public void CreateTexture(int slot, int w, int h) { }
|
||||||
|
|||||||
@@ -28,6 +28,12 @@ public readonly record struct SurfaceRectCopy(
|
|||||||
int SourceSurface, int DestinationSurface, int SourceX, int SourceY,
|
int SourceSurface, int DestinationSurface, int SourceX, int SourceY,
|
||||||
int Width, int Height, int DestinationX, int DestinationY);
|
int Width, int Height, int DestinationX, int DestinationY);
|
||||||
|
|
||||||
|
public enum SurfaceBlackFadeDirection
|
||||||
|
{
|
||||||
|
FromBlack,
|
||||||
|
ToBlack,
|
||||||
|
}
|
||||||
|
|
||||||
public interface IHost
|
public interface IHost
|
||||||
{
|
{
|
||||||
/// <summary>Report a recoverable runtime discrepancy while allowing script execution to continue.</summary>
|
/// <summary>Report a recoverable runtime discrepancy while allowing script execution to continue.</summary>
|
||||||
@@ -103,8 +109,10 @@ public interface IHost
|
|||||||
// read/message-skip branch reaches op 0x20c and presents the completed endpoint immediately.
|
// read/message-skip branch reaches op 0x20c and presents the completed endpoint immediately.
|
||||||
void WaitForForegroundTransition(GfxState gfx) { }
|
void WaitForForegroundTransition(GfxState gfx) { }
|
||||||
void PresentFrame(GfxState gfx) { }
|
void PresentFrame(GfxState gfx) { }
|
||||||
// Legacy SYS4 screen-transition family (op 0x25): scripts render two complete frames into
|
// Legacy SYS4 screen-transition family (ops 0x21, 0x22, and 0x25): scripts render complete
|
||||||
// numbered surfaces, then block while the engine alpha-composites target over source.
|
// frames into numbered surfaces, then block while the engine alpha-composites an endpoint.
|
||||||
|
void FadeSurfaceWithBlack(
|
||||||
|
GfxState gfx, int surface, long intervalArgument, SurfaceBlackFadeDirection direction) { }
|
||||||
void CrossfadeSurfaces(GfxState gfx, int sourceSurface, int targetSurface, long intervalArgument) { }
|
void CrossfadeSurfaces(GfxState gfx, int sourceSurface, int targetSurface, long intervalArgument) { }
|
||||||
void CreateTexture(int slot, int width, int height);
|
void CreateTexture(int slot, int width, int height);
|
||||||
/// <summary>Return a stable RGBA snapshot of one numbered surface, or null when unavailable.</summary>
|
/// <summary>Return a stable RGBA snapshot of one numbered surface, or null when unavailable.</summary>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace Age.Engine.Model;
|
namespace Age.Engine.Model;
|
||||||
|
|
||||||
/// <summary>Native timing conversion shared by the legacy op-0x25 screen-transition family.</summary>
|
/// <summary>Native timing conversion shared by the legacy full-frame screen-transition family.</summary>
|
||||||
public static class LegacyScreenTransitionTiming
|
public static class LegacyScreenTransitionTiming
|
||||||
{
|
{
|
||||||
public static long DurationMilliseconds(long argument)
|
public static long DurationMilliseconds(long argument)
|
||||||
|
|||||||
@@ -2657,6 +2657,16 @@ public sealed class VirtualMachine
|
|||||||
Read(a[4]), (int)Read(a[5]), Read(a[6]), Read(a[7])); return pc + 1;
|
Read(a[4]), (int)Read(a[5]), Read(a[6]), Read(a[7])); return pc + 1;
|
||||||
case "present-frame": // 0x20c: read/message-skip path snaps a queued transition to its endpoint
|
case "present-frame": // 0x20c: read/message-skip path snaps a queued transition to its endpoint
|
||||||
_host.PresentFrame(Gfx); return pc + 1;
|
_host.PresentFrame(Gfx); return pc + 1;
|
||||||
|
case "fade-surface-in-from-black": // 0x21: blocking black -> captured full-frame surface
|
||||||
|
case "u00418860":
|
||||||
|
_host.FadeSurfaceWithBlack(
|
||||||
|
Gfx, (int)Read(a[0]), Read(a[1]), SurfaceBlackFadeDirection.FromBlack);
|
||||||
|
return pc + 1;
|
||||||
|
case "fade-surface-out-to-black": // 0x22: blocking captured full-frame surface -> black
|
||||||
|
case "u00418920":
|
||||||
|
_host.FadeSurfaceWithBlack(
|
||||||
|
Gfx, (int)Read(a[0]), Read(a[1]), SurfaceBlackFadeDirection.ToBlack);
|
||||||
|
return pc + 1;
|
||||||
case "crossfade-surfaces": // 0x25: legacy full-frame surface alpha transition
|
case "crossfade-surfaces": // 0x25: legacy full-frame surface alpha transition
|
||||||
case "u00418B40":
|
case "u00418B40":
|
||||||
_host.CrossfadeSurfaces(Gfx, (int)Read(a[0]), (int)Read(a[1]), Read(a[2]));
|
_host.CrossfadeSurfaces(Gfx, (int)Read(a[0]), (int)Read(a[1]), Read(a[2]));
|
||||||
|
|||||||
@@ -800,33 +800,68 @@ public sealed class GodotAdvHost : IHost
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Op 0x25's native mode-4 path advances an 8-bit alpha accumulator. Values <=64 use the
|
public void FadeSurfaceWithBlack(
|
||||||
// operand as the timer interval and step alpha by sixteen; larger values divide the interval
|
GfxState gfx, int surface, long intervalArgument, SurfaceBlackFadeDirection direction)
|
||||||
// by sixteen and step alpha by one. This reproduces the resulting wall-clock duration.
|
{
|
||||||
|
long start = _clock.NowMs;
|
||||||
|
IReadOnlyList<RenderObject> captured;
|
||||||
|
lock (_screenTransitionLock)
|
||||||
|
captured = _renderTargetSnapshots.TryGetValue(surface, out var snapshot)
|
||||||
|
? snapshot : System.Array.Empty<RenderObject>();
|
||||||
|
|
||||||
|
IReadOnlyList<RenderObject> black = System.Array.Empty<RenderObject>();
|
||||||
|
IReadOnlyList<RenderObject> source =
|
||||||
|
direction == SurfaceBlackFadeDirection.FromBlack ? black : captured;
|
||||||
|
IReadOnlyList<RenderObject> target =
|
||||||
|
direction == SurfaceBlackFadeDirection.FromBlack ? captured : black;
|
||||||
|
RunLegacyScreenTransition(source, target, start, intervalArgument, new()
|
||||||
|
{
|
||||||
|
["kind"] = "surface-black-fade",
|
||||||
|
["surface"] = surface,
|
||||||
|
["direction"] = direction == SurfaceBlackFadeDirection.FromBlack
|
||||||
|
? "from-black" : "to-black",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public void CrossfadeSurfaces(GfxState gfx, int sourceSurface, int targetSurface, long intervalArgument)
|
public void CrossfadeSurfaces(GfxState gfx, int sourceSurface, int targetSurface, long intervalArgument)
|
||||||
{
|
{
|
||||||
IReadOnlyList<RenderObject> source;
|
IReadOnlyList<RenderObject> source;
|
||||||
IReadOnlyList<RenderObject> target;
|
IReadOnlyList<RenderObject> target;
|
||||||
long start = _clock.NowMs;
|
long start = _clock.NowMs;
|
||||||
long duration = LegacyScreenTransitionTiming.DurationMilliseconds(intervalArgument);
|
|
||||||
lock (_screenTransitionLock)
|
lock (_screenTransitionLock)
|
||||||
{
|
{
|
||||||
source = _renderTargetSnapshots.TryGetValue(sourceSurface, out var capturedSource)
|
source = _renderTargetSnapshots.TryGetValue(sourceSurface, out var capturedSource)
|
||||||
? capturedSource : System.Array.Empty<RenderObject>();
|
? capturedSource : System.Array.Empty<RenderObject>();
|
||||||
target = _renderTargetSnapshots.TryGetValue(targetSurface, out var capturedTarget)
|
target = _renderTargetSnapshots.TryGetValue(targetSurface, out var capturedTarget)
|
||||||
? capturedTarget : gfx.SnapshotVisibleObjects(start);
|
? capturedTarget : gfx.SnapshotVisibleObjects(start);
|
||||||
_screenTransition = new LegacyScreenTransition(source, target, start, duration);
|
|
||||||
}
|
}
|
||||||
|
RunLegacyScreenTransition(source, target, start, intervalArgument, new()
|
||||||
|
{
|
||||||
|
["kind"] = "surface-crossfade",
|
||||||
|
["source"] = sourceSurface,
|
||||||
|
["target"] = targetSurface,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// The native 0x21/0x22/0x25 family advances an 8-bit alpha accumulator. Values <=64 use
|
||||||
|
// the operand as the timer interval and step alpha by sixteen; larger values divide the
|
||||||
|
// interval by sixteen and step alpha by one. This reproduces its blocking wall-clock duration.
|
||||||
|
private void RunLegacyScreenTransition(
|
||||||
|
IReadOnlyList<RenderObject> source, IReadOnlyList<RenderObject> target,
|
||||||
|
long start, long intervalArgument, Dictionary<string, object?> timelineDetail)
|
||||||
|
{
|
||||||
|
long duration = LegacyScreenTransitionTiming.DurationMilliseconds(intervalArgument);
|
||||||
|
lock (_screenTransitionLock)
|
||||||
|
_screenTransition = new LegacyScreenTransition(source, target, start, duration);
|
||||||
_foregroundGfx = null;
|
_foregroundGfx = null;
|
||||||
System.Threading.Interlocked.Exchange(ref _transitionStartedAtMs, start);
|
System.Threading.Interlocked.Exchange(ref _transitionStartedAtMs, start);
|
||||||
System.Threading.Interlocked.Exchange(ref _presentRequested, 1);
|
System.Threading.Interlocked.Exchange(ref _presentRequested, 1);
|
||||||
IsTransitionWaiting = true;
|
IsTransitionWaiting = true;
|
||||||
_timeline?.State("screen-transition-start", new()
|
timelineDetail["interval_argument"] = intervalArgument;
|
||||||
{
|
timelineDetail["duration_ms"] = duration;
|
||||||
["source"] = sourceSurface, ["target"] = targetSurface,
|
timelineDetail["source_objects"] = source.Count;
|
||||||
["interval_argument"] = intervalArgument, ["duration_ms"] = duration,
|
timelineDetail["target_objects"] = target.Count;
|
||||||
["source_objects"] = source.Count, ["target_objects"] = target.Count,
|
_timeline?.State("screen-transition-start", timelineDetail);
|
||||||
});
|
|
||||||
bool scriptSuspended = SuspendScriptForPresentation();
|
bool scriptSuspended = SuspendScriptForPresentation();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -202,6 +202,7 @@ abi_source = "kelebek+decode-validated"
|
|||||||
[opcode.semantics]
|
[opcode.semantics]
|
||||||
name = "fade-surface-in-from-black"
|
name = "fade-surface-in-from-black"
|
||||||
category = "draw"
|
category = "draw"
|
||||||
|
details = "Port status (2026-07-29): implemented through the blocking legacy full-frame transition host path. An explicit empty/black source endpoint is composited beneath the captured target; timing and terminal-frame publication share the op-0x25 lifecycle."
|
||||||
summary = "(surface_slot)(timing_argument) — block while fading from black to a captured full-frame surface. The captured surface remains the terminal frame."
|
summary = "(surface_slot)(timing_argument) — block while fading from black to a captured full-frame surface. The captured surface remains the terminal frame."
|
||||||
noop_headless = false
|
noop_headless = false
|
||||||
source = "investigation"
|
source = "investigation"
|
||||||
@@ -228,6 +229,7 @@ abi_source = "kelebek+decode-validated"
|
|||||||
[opcode.semantics]
|
[opcode.semantics]
|
||||||
name = "fade-surface-out-to-black"
|
name = "fade-surface-out-to-black"
|
||||||
category = "draw"
|
category = "draw"
|
||||||
|
details = "Port status (2026-07-29): implemented through the blocking legacy full-frame transition host path. The captured source is composited beneath an explicit empty/black target endpoint; timing and terminal-frame publication share the op-0x25 lifecycle."
|
||||||
summary = "(surface_slot)(timing_argument) — block while fading a captured full-frame surface to black. Black remains the terminal frame."
|
summary = "(surface_slot)(timing_argument) — block while fading a captured full-frame surface to black. Black remains the terminal frame."
|
||||||
noop_headless = false
|
noop_headless = false
|
||||||
source = "investigation"
|
source = "investigation"
|
||||||
|
|||||||
Reference in New Issue
Block a user