@vgai/engine 0.5.40 → 0.5.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/adapter/authoring-seam-contract.d.ts +5 -0
  2. package/dist/adapter/authoring-seam-contract.d.ts.map +1 -1
  3. package/dist/adapter/authoring-seam-contract.js +1 -0
  4. package/dist/adapter/authoring.d.ts +21 -0
  5. package/dist/adapter/authoring.d.ts.map +1 -1
  6. package/dist/adapter/root-adapter.d.ts +16 -0
  7. package/dist/adapter/root-adapter.d.ts.map +1 -1
  8. package/dist/adapter/root-seam-contract.d.ts +5 -0
  9. package/dist/adapter/root-seam-contract.d.ts.map +1 -1
  10. package/dist/adapter/root-seam-contract.js +1 -0
  11. package/dist/ai/navigation.d.ts +30 -0
  12. package/dist/ai/navigation.d.ts.map +1 -1
  13. package/dist/ai/navigation.js +248 -15
  14. package/dist/ecs/user-data.d.ts +12 -0
  15. package/dist/ecs/user-data.d.ts.map +1 -1
  16. package/dist/ecs/user-data.js +6 -0
  17. package/dist/render/environment-capture.d.ts +10 -1
  18. package/dist/render/environment-capture.d.ts.map +1 -1
  19. package/dist/render/environment-capture.js +25 -0
  20. package/dist/render/ibl-override-material.d.ts +11 -2
  21. package/dist/render/ibl-override-material.d.ts.map +1 -1
  22. package/dist/render/ibl-override-material.js +16 -2
  23. package/dist/runtime/debug-bridge.d.ts.map +1 -1
  24. package/dist/runtime/debug-bridge.js +17 -3
  25. package/dist/runtime/game.d.ts +13 -6
  26. package/dist/runtime/game.d.ts.map +1 -1
  27. package/dist/runtime/game.js +41 -6
  28. package/dist/world3d-react/r3f-root-factory.d.ts.map +1 -1
  29. package/dist/world3d-react/r3f-root-factory.js +12 -5
  30. package/package.json +1 -1
  31. package/src/adapter/authoring-seam-contract.ts +1 -0
  32. package/src/adapter/authoring.ts +21 -0
  33. package/src/adapter/root-adapter.ts +17 -0
  34. package/src/adapter/root-seam-contract.ts +1 -0
  35. package/src/ai/navigation.ts +298 -13
  36. package/src/ecs/user-data.ts +12 -0
  37. package/src/render/environment-capture.ts +30 -1
  38. package/src/render/ibl-override-material.ts +32 -2
  39. package/src/runtime/debug-bridge.ts +21 -3
  40. package/src/runtime/game.ts +55 -11
  41. package/src/world3d-react/r3f-root-factory.tsx +12 -5
@@ -10,7 +10,7 @@
10
10
  * game altered.
11
11
  *
12
12
  * Consumers today: the `reflections` capability's native probe system, and
13
- * `godot-compat`'s Godot 3 `ReflectionProbe`.
13
+ * `godot-compat`'s versioned Godot `ReflectionProbe` binding.
14
14
  */
15
15
  import type { Scene, WebGLRenderer } from 'three';
16
16
  /**
@@ -56,6 +56,15 @@ export declare function withCaptureMask(scene: Scene, mask: number, capture: ()
56
56
  * cannot outlive the `finally` that restores it.
57
57
  */
58
58
  export declare function withCaptureShadows(scene: Scene, enabled: boolean, capture: () => void): void;
59
+ /**
60
+ * Include or suppress the scene's global sky/environment for one cube capture.
61
+ *
62
+ * This is renderer plumbing rather than a Godot policy: the caller decides whether the capture is
63
+ * interior. Clearing both properties is necessary because Three uses `background` for the cube's
64
+ * visible pixels and `environment` for the materials being photographed. Restoring only one makes
65
+ * a nominally isolated capture retain half of the outside lighting.
66
+ */
67
+ export declare function withCaptureSceneEnvironment(scene: Scene, enabled: boolean, capture: () => void): void;
59
68
  /**
60
69
  * Whether this renderer can run an environment capture at all.
61
70
  *
@@ -1 +1 @@
1
- {"version":3,"file":"environment-capture.d.ts","sourceRoot":"","sources":["../../src/render/environment-capture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAmB,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEnE;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,CAYrF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,CAiB5F;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAGtE"}
1
+ {"version":3,"file":"environment-capture.d.ts","sourceRoot":"","sources":["../../src/render/environment-capture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAmB,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAEnE;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,CAYrF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,GAAG,IAAI,CAiB5F;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,IAAI,GAClB,IAAI,CAeN;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAGtE"}
@@ -76,6 +76,31 @@ export function withCaptureShadows(scene, enabled, capture) {
76
76
  entry.shadow.intensity = entry.intensity;
77
77
  }
78
78
  }
79
+ /**
80
+ * Include or suppress the scene's global sky/environment for one cube capture.
81
+ *
82
+ * This is renderer plumbing rather than a Godot policy: the caller decides whether the capture is
83
+ * interior. Clearing both properties is necessary because Three uses `background` for the cube's
84
+ * visible pixels and `environment` for the materials being photographed. Restoring only one makes
85
+ * a nominally isolated capture retain half of the outside lighting.
86
+ */
87
+ export function withCaptureSceneEnvironment(scene, enabled, capture) {
88
+ if (enabled) {
89
+ capture();
90
+ return;
91
+ }
92
+ const background = scene.background;
93
+ const environment = scene.environment;
94
+ scene.background = null;
95
+ scene.environment = null;
96
+ try {
97
+ capture();
98
+ }
99
+ finally {
100
+ scene.background = background;
101
+ scene.environment = environment;
102
+ }
103
+ }
79
104
  /**
80
105
  * Whether this renderer can run an environment capture at all.
81
106
  *
@@ -24,10 +24,10 @@
24
24
  * hands back three's own shader object and gets out of the way.
25
25
  *
26
26
  * Consumers today: the `reflections` capability's native probe system, and
27
- * `godot-compat`'s Godot 3 `ReflectionProbe`, whose per-fragment models are
27
+ * `godot-compat`'s Godot `ReflectionProbe`, whose per-fragment models are
28
28
  * deliberately different renderers over this one splice.
29
29
  */
30
- import { type Mesh, type MeshStandardMaterial } from 'three';
30
+ import { type Mesh, type MeshStandardMaterial, type Texture } from 'three';
31
31
  /** The shader object three hands to `onBeforeCompile`. */
32
32
  export type IblOverrideShader = Parameters<MeshStandardMaterial['onBeforeCompile']>[0];
33
33
  /**
@@ -53,6 +53,15 @@ export declare function baseIblFunctions(): string;
53
53
  * intent: both compile the physical IBL chunk this module replaces.
54
54
  */
55
55
  export declare function standardMaterialsOf(mesh: Mesh): readonly MeshStandardMaterial[];
56
+ /**
57
+ * A black native texture whose only job is to compile Three's IBL branch.
58
+ *
59
+ * Local reflection systems can light a scene from captured probes when neither
60
+ * `scene.environment` nor a material `envMap` exists. Three removes both IBL
61
+ * entry points from that program unless one native input is present, so the
62
+ * caller temporarily assigns this neutral texture and restores what it found.
63
+ */
64
+ export declare function createIblSentinelTexture(): Texture;
56
65
  export interface IblOverrideOptions {
57
66
  /**
58
67
  * The GLSL that replaces `#include <envmap_physical_pars_fragment>`. Read at
@@ -1 +1 @@
1
- {"version":3,"file":"ibl-override-material.d.ts","sourceRoot":"","sources":["../../src/render/ibl-override-material.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,oBAAoB,EAAe,MAAM,OAAO,CAAC;AAE1E,0DAA0D;AAC1D,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEvF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,yBAAyB,CAAC;AAEzD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAIzC;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,oBAAoB,EAAE,CAK/E;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,MAAM,CAAC;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,MAAM,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAC1D;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IACxC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC1C,6EAA6E;IAC7E,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,oBAAoB,EAC9B,OAAO,EAAE,kBAAkB,GAC1B,WAAW,CAsCb"}
1
+ {"version":3,"file":"ibl-override-material.d.ts","sourceRoot":"","sources":["../../src/render/ibl-override-material.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAGL,KAAK,IAAI,EACT,KAAK,oBAAoB,EAGzB,KAAK,OAAO,EAEb,MAAM,OAAO,CAAC;AAEf,0DAA0D;AAC1D,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEvF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,yBAAyB,CAAC;AAEzD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAIzC;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,oBAAoB,EAAE,CAK/E;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,IAAI,OAAO,CAWlD;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,MAAM,CAAC;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,MAAM,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAC1D;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IACxC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC1C,6EAA6E;IAC7E,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,oBAAoB,EAC9B,OAAO,EAAE,kBAAkB,GAC1B,WAAW,CAsCb"}
@@ -24,10 +24,10 @@
24
24
  * hands back three's own shader object and gets out of the way.
25
25
  *
26
26
  * Consumers today: the `reflections` capability's native probe system, and
27
- * `godot-compat`'s Godot 3 `ReflectionProbe`, whose per-fragment models are
27
+ * `godot-compat`'s Godot `ReflectionProbe`, whose per-fragment models are
28
28
  * deliberately different renderers over this one splice.
29
29
  */
30
- import { ShaderChunk } from 'three';
30
+ import { CubeUVReflectionMapping, DataTexture, RGBAFormat, ShaderChunk, UnsignedByteType, } from 'three';
31
31
  /**
32
32
  * The `varying vec3` the vertex splice publishes and the fragment body reads.
33
33
  *
@@ -58,6 +58,20 @@ export function standardMaterialsOf(mesh) {
58
58
  const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
59
59
  return materials.filter((material) => Boolean(material.isMeshStandardMaterial));
60
60
  }
61
+ /**
62
+ * A black native texture whose only job is to compile Three's IBL branch.
63
+ *
64
+ * Local reflection systems can light a scene from captured probes when neither
65
+ * `scene.environment` nor a material `envMap` exists. Three removes both IBL
66
+ * entry points from that program unless one native input is present, so the
67
+ * caller temporarily assigns this neutral texture and restores what it found.
68
+ */
69
+ export function createIblSentinelTexture() {
70
+ const texture = new DataTexture(new Uint8Array(16 * 16 * 4), 16, 16, RGBAFormat, UnsignedByteType);
71
+ texture.mapping = CubeUVReflectionMapping;
72
+ texture.needsUpdate = true;
73
+ return texture;
74
+ }
61
75
  /**
62
76
  * Install the override. The returned handle is the only way to reach the
63
77
  * compiled shader or to undo the patch; the material is otherwise untouched
@@ -1 +1 @@
1
- {"version":3,"file":"debug-bridge.d.ts","sourceRoot":"","sources":["../../src/runtime/debug-bridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"debug-bridge.d.ts","sourceRoot":"","sources":["../../src/runtime/debug-bridge.ts"],"names":[],"mappings":"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"}
@@ -32,10 +32,13 @@ const HOLD_FOR_POLL_MS = 50;
32
32
  * faster in-process interval so the wall-clock grace period (~5s) lands in
33
33
  * the same neighborhood. */
34
34
  const HOLD_FOR_STALL_POLL_LIMIT = 100;
35
- /** Ticks driven per synchronous starved-loop batch. Sized like
35
+ /** Maximum ticks driven per synchronous starved-loop batch. Sized like
36
36
  * `fast-forward.ts`'s own batching rationale: big enough that per-batch
37
37
  * bookkeeping is negligible, small enough that one batch of a complex game's
38
- * phases stays a short synchronous burst. */
38
+ * phases stays a short synchronous burst. The actual batch is capped to the
39
+ * hold's remaining fixed-tick budget below; otherwise a one-tick `tap()` in a
40
+ * hidden tab becomes a 60-tick hold and releases only after short gameplay
41
+ * interactions have already completed. */
39
42
  const STARVED_DRIVE_BATCH_TICKS = 60;
40
43
  /** Hard ceiling on starved-drive batches for ONE hold — `STARVED_DRIVE_BATCH_TICKS
41
44
  * * this` ≈ 33 sim-minutes. A bound, not a timeout: it exists so a
@@ -106,7 +109,18 @@ export async function waitForHoldBudget(adapter, simSeconds, driveStarvedTicks)
106
109
  if (starvedBatches >= STARVED_DRIVE_MAX_BATCHES)
107
110
  return { stalled: true };
108
111
  starvedBatches += 1;
109
- driveStarvedTicks(STARVED_DRIVE_BATCH_TICKS);
112
+ const remaining = simSeconds - (current.simSeconds - start.simSeconds);
113
+ const fixedDt = current.fixedDt;
114
+ // A real Game publishes its fixed timestep, so drive exactly the number of whole ticks
115
+ // still needed (up to the throughput cap). Subtract a tiny ratio tolerance before `ceil`:
116
+ // repeated floating-point additions can leave an integer tick budget a few ulps above its
117
+ // mathematical value, and that must not manufacture one extra held-input frame. A bare
118
+ // adapter that does not publish `fixedDt` takes the conservative path: one tick, re-read,
119
+ // repeat. Exact input duration matters more than batching a non-Game test stand-in.
120
+ const ticksForRemaining = fixedDt !== undefined && Number.isFinite(fixedDt) && fixedDt > 0
121
+ ? Math.max(1, Math.ceil(remaining / fixedDt - 1e-9))
122
+ : 1;
123
+ driveStarvedTicks(Math.min(STARVED_DRIVE_BATCH_TICKS, ticksForRemaining));
110
124
  const after = readTime();
111
125
  // A batch that moved neither the tick counter nor the sim clock means
112
126
  // the drive is a no-op (paused game, torn-down runtime) — the same
@@ -89,8 +89,9 @@ export type AdapterSurface = AdapterSurfaceLeaf;
89
89
  * A world's per-phase frame hooks.
90
90
  * Populated on a `RootInstance` only for first-party mounts — an opaque/
91
91
  * foreign mount has no phase-partitioned entry point, so it stays
92
- * `undefined` and the Game's frame executor (`GameInternal.runFrame`) falls
93
- * back to calling its single `mounted.update(dt)` once per substep instead.
92
+ * `undefined` and the Game's frame executor falls back to its single
93
+ * `mounted.update(dt)`. The mount's `updateCadence` chooses fixed-substep
94
+ * (the default) or display-rate dispatch.
94
95
  */
95
96
  export interface RootFrameHooks {
96
97
  /** Run this world's engine systems + component ticks + world-bound game
@@ -405,8 +406,8 @@ export interface Game {
405
406
  * sway, a cosmetic bob. It is NOT a gameplay hook: it can fire twice
406
407
  * between two fixed substeps (120 Hz display, 60 Hz sim) and zero times
407
408
  * across a `runTicks` fast-forward, so anything that must be deterministic
408
- * belongs in a fixed phase (`ctx.systems.add`, a `useFrame` hook, a
409
- * `useFrame`) instead.
409
+ * belongs in a fixed engine phase (`ctx.systems.add`) instead. Ecosystem
410
+ * presentation hooks such as R3F's `useFrame` share this display clock.
410
411
  *
411
412
  * Reached from game code as `ctx.game?.onRenderStep(...)`. Returns an
412
413
  * unsubscribe function; pass `opts.signal` to unsubscribe with the same
@@ -449,13 +450,17 @@ export interface GameInternal extends Game {
449
450
  * for world in roots: // after ALL phases
450
451
  * if world.mounted.drivesOwnLoop: continue
451
452
  * if world.frame: world.frame.endFrame?.()
452
- * else: world.mounted.update?.(dt) // opaque world fallback
453
+ * else if updateCadence != 'display' OR render phases are included:
454
+ * world.mounted.update?.(dt) // opaque world fallback
453
455
  * ```
454
456
  *
455
457
  * A single first-party world and its direct `mounted.update(dt)` entry run
456
458
  * the same `SystemRunner` and `postFrame` work. A `drivesOwnLoop` world is
457
459
  * never ticked here. An opaque host-driven world (no `frame`) gets exactly
458
- * one `update(dt)` call per substep, after the phase loop.
460
+ * one `update(dt)` call per substep after the phase loop by default. A
461
+ * display-cadence opaque world is withheld when `skipRenderPhases` is true;
462
+ * the matching host calls it once from {@link runRenderFrame}. A direct
463
+ * `runFrame` with render phases included still calls it once.
459
464
  *
460
465
  * D10/T7.6 play-state addendum: when `Game.play.paused` is true, every
461
466
  * `pausable` (and non-`drivesOwnLoop`) world skips every phase EXCEPT
@@ -495,6 +500,8 @@ export interface GameInternal extends Game {
495
500
  * for world in roots (declaration order):
496
501
  * if world.mounted.drivesOwnLoop: continue
497
502
  * world.frame?.runPhase(phase, frozen ? 0 : displayDt)
503
+ * for opaque world with updateCadence == 'display':
504
+ * world.mounted.update?.(frozen ? 0 : displayDt)
498
505
  * ```
499
506
  *
500
507
  * Advances NOTHING: no `tick`, no `simT`, no sim-clock flush, no state-bridge
@@ -1 +1 @@
1
- {"version":3,"file":"game.d.ts","sourceRoot":"","sources":["../../src/runtime/game.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"game.d.ts","sourceRoot":"","sources":["../../src/runtime/game.ts"],"names":[],"mappings":"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"}
@@ -436,7 +436,12 @@ export function createGame(opts) {
436
436
  reportGateShortfallOnce('loop', world.id, 'self-driven world, adapter declares no setPaused capability');
437
437
  }
438
438
  }
439
- const audio = world.mounted.systems?.audio;
439
+ // A native entry's static `systems` export is this root's primary
440
+ // declaration surface. `computeSystemAdapters()` already gives it
441
+ // precedence over a substrate-seeded mounted adapter; pause must read
442
+ // the same source or a valid entry-declared audio graph is visible to
443
+ // the editor yet paradoxically reported as ungateable here.
444
+ const audio = declaredSystemAdapters.get(world.id)?.audio ?? world.mounted.systems?.audio;
440
445
  if (audio) {
441
446
  audio.setMuted(next);
442
447
  }
@@ -644,11 +649,19 @@ export function createGame(opts) {
644
649
  // Checklist item 2: same isolation for the opaque-world fallback —
645
650
  // one foreign mount's `update` throwing must not starve its
646
651
  // siblings' `endFrame`/`update` calls this same loop.
647
- try {
648
- world.mounted.update?.(dt);
649
- }
650
- catch (err) {
651
- console.error(`[game] world "${world.id}" (kind: ${world.kind}) update() threw:`, err);
652
+ // A display-cadence opaque update is the root's indivisible native
653
+ // presentation (R3F `advance()` is callbacks + draw). The real
654
+ // rAF host withholds render phases from EVERY fixed catch-up step;
655
+ // withhold this update beside them, then run it once in
656
+ // `runRenderFrameImpl`. A direct/offline `runFrame` includes render
657
+ // phases and therefore still advances the root exactly once.
658
+ if (!(skipRenderPhases && world.mounted.updateCadence === 'display')) {
659
+ try {
660
+ world.mounted.update?.(dt);
661
+ }
662
+ catch (err) {
663
+ console.error(`[game] world "${world.id}" (kind: ${world.kind}) update() threw:`, err);
664
+ }
652
665
  }
653
666
  }
654
667
  }
@@ -747,6 +760,28 @@ export function createGame(opts) {
747
760
  }
748
761
  profiler.endPhase(phase);
749
762
  }
763
+ // An opaque display-cadence root cannot expose phase hooks because its
764
+ // native advance is inseparable. It still belongs to THIS presentation
765
+ // frame, once — never to every fixed catch-up substep that preceded it.
766
+ // A frozen world redraws at dt=0, preserving the established pause rule.
767
+ for (let i = 0; i < n; i++) {
768
+ const world = roots[i];
769
+ if (world.disposed)
770
+ continue;
771
+ if (world.mounted.drivesOwnLoop)
772
+ continue;
773
+ if (world.frame)
774
+ continue;
775
+ if (world.mounted.updateCadence !== 'display')
776
+ continue;
777
+ const frozen = paused && world.pausable;
778
+ try {
779
+ world.mounted.update?.(frozen ? 0 : displayDt);
780
+ }
781
+ catch (err) {
782
+ console.error(`[game] world "${world.id}" (kind: ${world.kind}) update() threw (display frame):`, err);
783
+ }
784
+ }
750
785
  profiler.endFrame();
751
786
  if (rngTrapEnabled)
752
787
  rngTrap.disable();
@@ -1 +1 @@
1
- {"version":3,"file":"r3f-root-factory.d.ts","sourceRoot":"","sources":["../../src/world3d-react/r3f-root-factory.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAWH,OAAO,KAAK,EAAoB,WAAW,EAAoB,MAAM,YAAY,CAAC;AAelF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AA4ZnE;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAI/F;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,qBAO5B,CAAC"}
1
+ {"version":3,"file":"r3f-root-factory.d.ts","sourceRoot":"","sources":["../../src/world3d-react/r3f-root-factory.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAWH,OAAO,KAAK,EAAoB,WAAW,EAAoB,MAAM,YAAY,CAAC;AAelF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAmanE;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAI/F;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,qBAO5B,CAAC"}
@@ -292,11 +292,10 @@ function threeWorldAdapter(id, component) {
292
292
  if (renderDebugWiring)
293
293
  systemAdapters.renderDebug = renderDebugWiring.adapter;
294
294
  // The engine drives every `useFrame` through the mounted world's
295
- // `update(dt)` hook, never off a raw host-loop callback. That is the
296
- // whole pause story: `runFrameImpl` (`runtime/game.ts`) calls
297
- // `mounted.update?.(dt)` per substep for a host-driven world and SKIPS
298
- // it while that world is frozen, and `Game.play.step()` ticks it exactly
299
- // once.
295
+ // `update(dt)` hook, never off a raw Fiber loop. This mount declares
296
+ // that indivisible Fiber advance at DISPLAY cadence below: the real
297
+ // host calls it once per presentation, a paused world gets dt=0, and an
298
+ // explicit `Game.play.step()` still ticks it exactly once.
300
299
  //
301
300
  // `advance(timestamp, runGlobalEffects, state)`'s `timestamp` is
302
301
  // consumed as `THREE.Clock.elapsedTime` DIRECTLY when
@@ -328,6 +327,14 @@ function threeWorldAdapter(id, component) {
328
327
  return live().camera;
329
328
  },
330
329
  drivesOwnLoop: false,
330
+ // Fiber's `advance()` cannot separate its `useFrame` callbacks from
331
+ // its WebGL draw. Running this opaque update in every fixed catch-up
332
+ // substep renders N complete frames inside one rAF callback: once a
333
+ // scene costs more than 16.7ms, the accumulator asks for more draws,
334
+ // those draws make the next gap larger, and the loop spirals to its
335
+ // max-substep ceiling. The host's display pass is the one clock that
336
+ // must own this inseparable native advance.
337
+ updateCadence: 'display',
331
338
  // Adapter surface: `debug` (the shared game registry) and, when a real
332
339
  // WebGL2 context exists, `renderDebug` are engine-seeded. The game's
333
340
  // own capabilities arrive as the entry module's declared `systems`.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@vgai/engine",
3
3
  "author": "Volter AI, Inc.",
4
4
  "license": "Apache-2.0",
5
- "version": "0.5.40",
5
+ "version": "0.5.42",
6
6
  "description": "Readable TypeScript game engine and universal host for Three.js, PixiJS, and React games.",
7
7
  "keywords": [
8
8
  "game-engine",
@@ -57,6 +57,7 @@ export const AUTHORING_ADAPTER_SHAPE = defineSeamShape<AuthoringAdapter>()({
57
57
  export const HIERARCHY_PROVIDER_SHAPE = defineSeamShape<HierarchyProvider>()({
58
58
  roots: { optional: false, kind: 'function', required: 'operation' },
59
59
  node: { optional: false, kind: 'function', required: 'operation' },
60
+ crossSurfaceStructureSignature: { optional: true, kind: 'function', required: 'operation' },
60
61
  object3D: { optional: true, kind: 'function', required: 'operation' },
61
62
  idForObject3D: { optional: true, kind: 'function', required: 'effect' },
62
63
  });
@@ -110,6 +110,18 @@ export interface EditorNode {
110
110
  typeLabel?: string;
111
111
  parentId: string | null;
112
112
  childIds: string[];
113
+ /** Opaque project-owned identity shared by authored rows across adapter roots. */
114
+ crossSurfaceId?: string;
115
+ /** Optional authored parent identity resolved against another row's cross-surface id. */
116
+ crossSurfaceParentId?: string;
117
+ /** Source-owned sibling ordinal used only when native rows are joined across surfaces. */
118
+ crossSurfaceOrder?: number;
119
+ /**
120
+ * Live source-owned label for the projected group containing this row's adapter root.
121
+ * Any row may carry it: a native surface can have no semantic root of its own when all of
122
+ * its authored rows are children of entities owned by another surface.
123
+ */
124
+ crossSurfaceGroupLabel?: string;
113
125
  }
114
126
 
115
127
  export interface PropertyDescriptor {
@@ -171,6 +183,15 @@ export interface PropertyDescriptor {
171
183
  export interface HierarchyProvider {
172
184
  roots(): EditorNode[];
173
185
  node(id: string): EditorNode | null;
186
+ /**
187
+ * OPTIONAL semantic-join revision. A composite hierarchy uses explicit
188
+ * `crossSurface*` fields to join native roots; this signature changes if and
189
+ * only if those fields, their semantic ancestry, or their order changed.
190
+ * Ordinary native-only child churn may leave it stable. `null` explicitly
191
+ * means this provider has no semantic participation. Omission means the
192
+ * composite must conservatively re-read the provider's whole hierarchy.
193
+ */
194
+ crossSurfaceStructureSignature?(): string | null;
174
195
  /**
175
196
  * OPTIONAL, THREE-SPECIFIC — the live `Object3D` for raycast/gizmo binding
176
197
  * (null for a node this adapter has no object for). A Pixi, DOM or React
@@ -65,6 +65,23 @@ export interface MountedRootBase {
65
65
  */
66
66
  readonly drivesOwnLoop: boolean;
67
67
 
68
+ /**
69
+ * Which host clock owns an opaque mounted root's single `update(dt)` hook.
70
+ *
71
+ * `fixed` (the default) preserves the adapter seam's original contract:
72
+ * the callback runs once per consumed simulation substep. `display` is for
73
+ * a reconciler whose one native advance is inseparably BOTH its callbacks
74
+ * and its draw (React Three Fiber's `advance()` is the measured case). The
75
+ * real host then withholds it from fixed catch-up substeps and invokes it
76
+ * exactly once from the display pass. A direct/offline `runFrame` that does
77
+ * not skip render phases still invokes it once, preserving capture and
78
+ * explicit-tick semantics.
79
+ *
80
+ * Absent means `fixed`. This changes no foreign/ingest adapter unless that
81
+ * adapter opts in explicitly.
82
+ */
83
+ readonly updateCadence?: 'fixed' | 'display';
84
+
68
85
  update?(dt: number): void; // host-driven only
69
86
  fixedUpdate?(dt: number): void;
70
87
  setPaused?(paused: boolean): void; // capability, not promise — see loop-model note above
@@ -18,6 +18,7 @@ export const ROOT_ADAPTER_SHAPE = defineSeamShape<RootAdapter<AdapterSurface>>()
18
18
 
19
19
  export const MOUNTED_ROOT_BASE_SHAPE = defineSeamShape<MountedRootBase>()({
20
20
  drivesOwnLoop: { optional: false, kind: 'value', required: 'shape' },
21
+ updateCadence: { optional: true, kind: 'value', required: 'shape' },
21
22
  update: { optional: true, kind: 'function', required: 'effect' },
22
23
  fixedUpdate: { optional: true, kind: 'function', required: 'effect' },
23
24
  setPaused: { optional: true, kind: 'function', required: 'effect' },