feat(godot): Sleep blocks the VM thread so the compositor presents paced frames

op 0xc8 -> Thread.Sleep(duration ms) on the VM background thread (capped 10s);
main thread keeps compositing -> the sleep-paced opening burst gets frames to show.
Unit = ms (RE-confirmed). Selftest OK (plumbing parity; synthetic scene has no sleep).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-07-08 09:02:01 -04:00
parent 12b066edfa
commit 0ed6ff130d

View File

@@ -42,6 +42,17 @@ public sealed class GodotAdvHost : IHost
// called from the main thread (click) or the selftest auto-clicker
public void SignalInput() { if (_gate.CurrentCount == 0) _gate.Release(); }
// op 0xc8: block the VM background thread so the main-thread compositor (Main.Recomposite in _Process)
// presents the current retained GfxState — this is what makes the sleep-paced opening burst animate.
// Time-based sibling of WaitForInput's suspend. The native op arms a non-blocking main-loop-polled timer;
// blocking this throwaway task thread is behaviorally equivalent given our threading model. Operand is
// MILLISECONDS (docs/engine-re.md sleep section + opcodes.toml 0xc8). Headless CLI hosts no-op it (parity).
public void Sleep(long duration)
{
int ms = (int)System.Math.Clamp(duration, 0, 10_000); // cap so a pathological script can't hang the window
if (ms > 0) Thread.Sleep(ms);
}
// ---- texture ops (run on the VM thread; marshal Godot node work to the main thread) ----
public void CreateTexture(int slot, int width, int height) { _slotBmp[slot] = null; _slotDims[slot] = (width, height); }