@vgai/engine 0.5.22 → 0.5.23

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 (291) hide show
  1. package/README.md +6 -3
  2. package/dist/adapter/adapter-module.d.ts.map +1 -1
  3. package/dist/adapter/adapter-module.js +2 -4
  4. package/dist/adapter/adapter-surface.d.ts +1 -1
  5. package/dist/adapter/adapter-surface.js +1 -1
  6. package/dist/adapter/authoring.d.ts +19 -21
  7. package/dist/adapter/authoring.d.ts.map +1 -1
  8. package/dist/adapter/authoring.js +2 -2
  9. package/dist/adapter/binding.d.ts +341 -0
  10. package/dist/adapter/binding.d.ts.map +1 -0
  11. package/dist/adapter/binding.js +148 -0
  12. package/dist/adapter/colyseus-networking-adapter.d.ts.map +1 -1
  13. package/dist/adapter/colyseus-networking-adapter.js +23 -4
  14. package/dist/adapter/entrypoint-selection-readers.d.ts +24 -0
  15. package/dist/adapter/entrypoint-selection-readers.d.ts.map +1 -0
  16. package/dist/adapter/entrypoint-selection-readers.js +63 -0
  17. package/dist/adapter/entrypoint-selection-source.d.ts.map +1 -1
  18. package/dist/adapter/entrypoint-selection-source.js +1 -44
  19. package/dist/adapter/finders/scenes-from-entrypoint-selection.d.ts.map +1 -1
  20. package/dist/adapter/finders/scenes-from-entrypoint-selection.js +1 -52
  21. package/dist/adapter/host-context.d.ts +46 -15
  22. package/dist/adapter/host-context.d.ts.map +1 -1
  23. package/dist/adapter/host-context.js +2 -9
  24. package/dist/adapter/index.d.ts +11 -12
  25. package/dist/adapter/index.d.ts.map +1 -1
  26. package/dist/adapter/index.js +9 -10
  27. package/dist/adapter/ingest/game-contract.d.ts +0 -3
  28. package/dist/adapter/ingest/game-contract.d.ts.map +1 -1
  29. package/dist/adapter/ingest/game-contract.js +0 -3
  30. package/dist/adapter/ingest/scene-capture.d.ts +19 -23
  31. package/dist/adapter/ingest/scene-capture.d.ts.map +1 -1
  32. package/dist/adapter/ingest/scene-capture.js +143 -17
  33. package/dist/adapter/ingest/visible-capture-window.d.ts +34 -0
  34. package/dist/adapter/ingest/visible-capture-window.d.ts.map +1 -1
  35. package/dist/adapter/native-debug-module.d.ts +31 -5
  36. package/dist/adapter/native-debug-module.d.ts.map +1 -1
  37. package/dist/adapter/native-debug-module.js +25 -7
  38. package/dist/adapter/rapier-physics-adapter.d.ts +31 -1
  39. package/dist/adapter/rapier-physics-adapter.d.ts.map +1 -1
  40. package/dist/adapter/rapier-physics-adapter.js +50 -36
  41. package/dist/adapter/renderer-config.d.ts +2 -2
  42. package/dist/adapter/renderer-config.js +2 -2
  43. package/dist/adapter/root-adapter.d.ts +7 -7
  44. package/dist/adapter/root-adapter.js +4 -4
  45. package/dist/adapter/system-adapter.d.ts +45 -7
  46. package/dist/adapter/system-adapter.d.ts.map +1 -1
  47. package/dist/adapter/system-seam-contract.d.ts +3 -3
  48. package/dist/adapter/system-seam-contract.js +3 -3
  49. package/dist/adapter/system-slot.d.ts +168 -0
  50. package/dist/adapter/system-slot.d.ts.map +1 -0
  51. package/dist/adapter/system-slot.js +229 -0
  52. package/dist/adapter/transform.d.ts +11 -1
  53. package/dist/adapter/transform.d.ts.map +1 -1
  54. package/dist/ai/navigation.d.ts +17 -1
  55. package/dist/ai/navigation.d.ts.map +1 -1
  56. package/dist/ai/navigation.js +26 -5
  57. package/dist/animation/anim-graph-types.d.ts +11 -3
  58. package/dist/animation/anim-graph-types.d.ts.map +1 -1
  59. package/dist/animation/theatre-clock-binding.d.ts +4 -4
  60. package/dist/animation/theatre-clock-binding.js +4 -4
  61. package/dist/animation/xstate-animation-binding.d.ts.map +1 -1
  62. package/dist/animation/xstate-animation-binding.js +2 -2
  63. package/dist/animation/xstate-animation-meta.d.ts +13 -0
  64. package/dist/animation/xstate-animation-meta.d.ts.map +1 -1
  65. package/dist/animation/xstate-animation-meta.js +14 -0
  66. package/dist/asset-formats/index.d.ts +4 -7
  67. package/dist/asset-formats/index.d.ts.map +1 -1
  68. package/dist/asset-formats/index.js +4 -7
  69. package/dist/asset-formats/render-env.d.ts +5 -8
  70. package/dist/asset-formats/render-env.d.ts.map +1 -1
  71. package/dist/asset-formats/render-env.js +3 -6
  72. package/dist/asset-parse-error.d.ts +2 -5
  73. package/dist/asset-parse-error.d.ts.map +1 -1
  74. package/dist/asset-parse-error.js +2 -5
  75. package/dist/audio/bus-mixer.d.ts +101 -0
  76. package/dist/audio/bus-mixer.d.ts.map +1 -0
  77. package/dist/audio/bus-mixer.js +115 -0
  78. package/dist/core/frame-pacing.d.ts +1 -1
  79. package/dist/core/frame-pacing.js +2 -2
  80. package/dist/core/game-loop.d.ts +1 -3
  81. package/dist/core/game-loop.d.ts.map +1 -1
  82. package/dist/core/game-loop.js +1 -3
  83. package/dist/core/seeded-random.d.ts +1 -1
  84. package/dist/core/sim-clock.d.ts +5 -6
  85. package/dist/core/sim-clock.d.ts.map +1 -1
  86. package/dist/core/sim-clock.js +4 -5
  87. package/dist/core/types.d.ts +1 -3
  88. package/dist/core/types.d.ts.map +1 -1
  89. package/dist/defaults.d.ts +6 -14
  90. package/dist/defaults.d.ts.map +1 -1
  91. package/dist/defaults.js +6 -14
  92. package/dist/dev/register-render-vitals.d.ts +1 -4
  93. package/dist/dev/register-render-vitals.d.ts.map +1 -1
  94. package/dist/dev/register-render-vitals.js +1 -4
  95. package/dist/dev/render-debug-adapter.d.ts +2 -3
  96. package/dist/dev/render-debug-adapter.d.ts.map +1 -1
  97. package/dist/dev/render-debug-adapter.js +2 -3
  98. package/dist/dev/render-vitals.d.ts +3 -3
  99. package/dist/dev/render-vitals.js +3 -3
  100. package/dist/dev/webgl-frame-capture.d.ts +1 -1
  101. package/dist/dev/webgl-frame-capture.js +1 -1
  102. package/dist/index.d.ts +2 -5
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/index.js +2 -4
  105. package/dist/input/host-pointer.d.ts +122 -0
  106. package/dist/input/host-pointer.d.ts.map +1 -0
  107. package/dist/input/host-pointer.js +160 -0
  108. package/dist/input/input-manager.d.ts +18 -5
  109. package/dist/input/input-manager.d.ts.map +1 -1
  110. package/dist/input/input-manager.js +33 -13
  111. package/dist/input/rebind-controller.d.ts.map +1 -1
  112. package/dist/input/rebind-controller.js +6 -8
  113. package/dist/input/schema.d.ts.map +1 -1
  114. package/dist/input/schema.js +56 -28
  115. package/dist/manifest/filename.d.ts.map +1 -1
  116. package/dist/manifest/filename.js +8 -12
  117. package/dist/manifest/load.d.ts +10 -10
  118. package/dist/manifest/load.d.ts.map +1 -1
  119. package/dist/manifest/load.js +9 -6
  120. package/dist/manifest/schema.d.ts +17 -21
  121. package/dist/manifest/schema.d.ts.map +1 -1
  122. package/dist/manifest/schema.js +45 -35
  123. package/dist/physics/collider-dimensions.d.ts +8 -12
  124. package/dist/physics/collider-dimensions.d.ts.map +1 -1
  125. package/dist/physics/collider-dimensions.js +8 -12
  126. package/dist/pixi/scene-capture.d.ts +11 -13
  127. package/dist/pixi/scene-capture.d.ts.map +1 -1
  128. package/dist/react/world-state.d.ts +1 -1
  129. package/dist/react/world-state.d.ts.map +1 -1
  130. package/dist/render/light-camera-factory.d.ts +5 -7
  131. package/dist/render/light-camera-factory.d.ts.map +1 -1
  132. package/dist/render/light-camera-factory.js +8 -11
  133. package/dist/render/material-factory.js +1 -1
  134. package/dist/render/render-batch-system.d.ts.map +1 -1
  135. package/dist/render/render-features.d.ts +17 -6
  136. package/dist/render/render-features.d.ts.map +1 -1
  137. package/dist/render/render-features.js +0 -28
  138. package/dist/runtime/create-runtime.d.ts +34 -25
  139. package/dist/runtime/create-runtime.d.ts.map +1 -1
  140. package/dist/runtime/create-runtime.js +218 -93
  141. package/dist/runtime/debug-registry.d.ts +77 -8
  142. package/dist/runtime/debug-registry.d.ts.map +1 -1
  143. package/dist/runtime/debug-registry.js +3 -3
  144. package/dist/runtime/dev-build.d.ts +2 -2
  145. package/dist/runtime/dev-build.js +2 -2
  146. package/dist/runtime/game-input-seams.d.ts +2 -2
  147. package/dist/runtime/game-input-seams.d.ts.map +1 -1
  148. package/dist/runtime/game.d.ts +90 -41
  149. package/dist/runtime/game.d.ts.map +1 -1
  150. package/dist/runtime/game.js +80 -54
  151. package/dist/runtime/mount-game.d.ts +0 -16
  152. package/dist/runtime/mount-game.d.ts.map +1 -1
  153. package/dist/runtime/mount-game.js +8 -39
  154. package/dist/runtime/mount-manifest.d.ts +22 -14
  155. package/dist/runtime/mount-manifest.d.ts.map +1 -1
  156. package/dist/runtime/mount-manifest.js +18 -18
  157. package/dist/runtime/playtest.d.ts +22 -0
  158. package/dist/runtime/playtest.d.ts.map +1 -0
  159. package/dist/runtime/playtest.js +12 -0
  160. package/dist/runtime/state-bridge.d.ts +2 -3
  161. package/dist/runtime/state-bridge.d.ts.map +1 -1
  162. package/dist/runtime/state-bridge.js +1 -0
  163. package/dist/setup/setup-audio.d.ts +12 -0
  164. package/dist/setup/setup-audio.d.ts.map +1 -1
  165. package/dist/setup/setup-audio.js +9 -10
  166. package/dist/setup/setup-renderer.d.ts +2 -25
  167. package/dist/setup/setup-renderer.d.ts.map +1 -1
  168. package/dist/setup/setup-renderer.js +2 -31
  169. package/dist/world3d-react/r3f-root-factory.d.ts +7 -7
  170. package/dist/world3d-react/r3f-root-factory.js +7 -7
  171. package/dist/world3d-react/rapier-physics-bridge.d.ts +9 -8
  172. package/dist/world3d-react/rapier-physics-bridge.d.ts.map +1 -1
  173. package/dist/world3d-react/rapier-physics-bridge.js +100 -48
  174. package/package.json +1 -1
  175. package/schemas/engine-capabilities.json +16 -14
  176. package/schemas/vgai-project.schema.json +35 -26
  177. package/src/adapter/adapter-module.ts +2 -4
  178. package/src/adapter/adapter-surface.ts +1 -1
  179. package/src/adapter/authoring.ts +19 -21
  180. package/src/adapter/binding.ts +468 -0
  181. package/src/adapter/colyseus-networking-adapter.ts +20 -5
  182. package/src/adapter/entrypoint-selection-readers.ts +66 -0
  183. package/src/adapter/entrypoint-selection-source.ts +1 -40
  184. package/src/adapter/finders/scenes-from-entrypoint-selection.ts +1 -48
  185. package/src/adapter/host-context.ts +45 -15
  186. package/src/adapter/index.ts +23 -11
  187. package/src/adapter/ingest/game-contract.ts +0 -3
  188. package/src/adapter/ingest/scene-capture.ts +190 -39
  189. package/src/adapter/ingest/visible-capture-window.ts +35 -0
  190. package/src/adapter/native-debug-module.ts +43 -7
  191. package/src/adapter/rapier-physics-adapter.ts +76 -20
  192. package/src/adapter/renderer-config.ts +2 -2
  193. package/src/adapter/root-adapter.ts +7 -7
  194. package/src/adapter/system-adapter.ts +43 -8
  195. package/src/adapter/system-seam-contract.ts +3 -3
  196. package/src/adapter/system-slot.ts +291 -0
  197. package/src/adapter/transform.ts +18 -1
  198. package/src/ai/navigation.ts +30 -3
  199. package/src/animation/anim-graph-types.ts +11 -3
  200. package/src/animation/theatre-clock-binding.ts +4 -4
  201. package/src/animation/xstate-animation-binding.ts +2 -2
  202. package/src/animation/xstate-animation-meta.ts +16 -0
  203. package/src/asset-formats/index.ts +4 -7
  204. package/src/asset-formats/render-env.ts +3 -6
  205. package/src/asset-parse-error.ts +2 -5
  206. package/src/audio/bus-mixer.ts +161 -0
  207. package/src/core/frame-pacing.ts +2 -2
  208. package/src/core/game-loop.ts +1 -3
  209. package/src/core/seeded-random.ts +1 -1
  210. package/src/core/sim-clock.ts +5 -6
  211. package/src/core/types.ts +1 -3
  212. package/src/defaults.ts +6 -14
  213. package/src/dev/register-render-vitals.ts +1 -4
  214. package/src/dev/render-debug-adapter.ts +2 -3
  215. package/src/dev/render-vitals.ts +3 -3
  216. package/src/dev/webgl-frame-capture.ts +1 -1
  217. package/src/index.ts +2 -5
  218. package/src/input/host-pointer.ts +230 -0
  219. package/src/input/input-manager.ts +34 -13
  220. package/src/input/input-types.ts +1 -1
  221. package/src/input/rebind-controller.ts +6 -8
  222. package/src/input/schema.ts +216 -188
  223. package/src/manifest/filename.ts +8 -12
  224. package/src/manifest/load.ts +17 -13
  225. package/src/manifest/schema.ts +55 -47
  226. package/src/physics/collider-dimensions.ts +8 -12
  227. package/src/pixi/scene-capture.ts +12 -15
  228. package/src/react/world-state.tsx +1 -1
  229. package/src/render/light-camera-factory.ts +8 -11
  230. package/src/render/material-factory.ts +1 -1
  231. package/src/render/render-batch-system.ts +14 -6
  232. package/src/render/render-features.ts +17 -35
  233. package/src/runtime/create-runtime.ts +270 -108
  234. package/src/runtime/debug-registry.ts +84 -8
  235. package/src/runtime/dev-build.ts +2 -2
  236. package/src/runtime/game-input-seams.ts +2 -2
  237. package/src/runtime/game.ts +168 -80
  238. package/src/runtime/mount-game.ts +8 -56
  239. package/src/runtime/mount-manifest.ts +43 -34
  240. package/src/runtime/playtest.ts +22 -0
  241. package/src/runtime/state-bridge.ts +3 -3
  242. package/src/setup/setup-audio.ts +21 -11
  243. package/src/setup/setup-renderer.ts +2 -61
  244. package/src/world3d-react/r3f-root-factory.tsx +7 -7
  245. package/src/world3d-react/rapier-physics-bridge.tsx +107 -50
  246. package/dist/adapter/setup-three-root-adapter.d.ts +0 -86
  247. package/dist/adapter/setup-three-root-adapter.d.ts.map +0 -1
  248. package/dist/adapter/setup-three-root-adapter.js +0 -908
  249. package/dist/animation/clip-map.d.ts +0 -12
  250. package/dist/animation/clip-map.d.ts.map +0 -1
  251. package/dist/animation/clip-map.js +0 -31
  252. package/dist/asset-registry.d.ts +0 -38
  253. package/dist/asset-registry.d.ts.map +0 -1
  254. package/dist/asset-registry.js +0 -66
  255. package/dist/canvas-react/engine-bridge.d.ts +0 -45
  256. package/dist/canvas-react/engine-bridge.d.ts.map +0 -1
  257. package/dist/canvas-react/engine-bridge.js +0 -45
  258. package/dist/canvas-react/pixi-react-adapter.d.ts +0 -77
  259. package/dist/canvas-react/pixi-react-adapter.d.ts.map +0 -1
  260. package/dist/canvas-react/pixi-react-adapter.js +0 -294
  261. package/dist/canvas-react/world-context.d.ts +0 -98
  262. package/dist/canvas-react/world-context.d.ts.map +0 -1
  263. package/dist/canvas-react/world-context.js +0 -173
  264. package/dist/dev/debug-draw.d.ts +0 -24
  265. package/dist/dev/debug-draw.d.ts.map +0 -1
  266. package/dist/dev/debug-draw.js +0 -73
  267. package/dist/render/auto-batcher.d.ts +0 -34
  268. package/dist/render/auto-batcher.d.ts.map +0 -1
  269. package/dist/render/auto-batcher.js +0 -140
  270. package/dist/render/lod.d.ts +0 -13
  271. package/dist/render/lod.d.ts.map +0 -1
  272. package/dist/render/lod.js +0 -16
  273. package/dist/runtime/types.d.ts +0 -303
  274. package/dist/runtime/types.d.ts.map +0 -1
  275. package/dist/runtime/types.js +0 -1
  276. package/dist/world3d-react/engine-bridge.d.ts +0 -47
  277. package/dist/world3d-react/engine-bridge.d.ts.map +0 -1
  278. package/dist/world3d-react/engine-bridge.js +0 -73
  279. package/dist/world3d-react/r3f-adapter.d.ts +0 -58
  280. package/dist/world3d-react/r3f-adapter.d.ts.map +0 -1
  281. package/dist/world3d-react/r3f-adapter.js +0 -634
  282. package/dist/world3d-react/world-context.d.ts +0 -182
  283. package/dist/world3d-react/world-context.d.ts.map +0 -1
  284. package/dist/world3d-react/world-context.js +0 -235
  285. package/src/adapter/setup-three-root-adapter.ts +0 -1032
  286. package/src/animation/clip-map.ts +0 -34
  287. package/src/asset-registry.ts +0 -89
  288. package/src/dev/debug-draw.ts +0 -80
  289. package/src/render/auto-batcher.ts +0 -168
  290. package/src/render/lod.ts +0 -17
  291. package/src/runtime/types.ts +0 -328
@@ -1 +1 @@
1
- {"version":3,"file":"asset-parse-error.d.ts","sourceRoot":"","sources":["../src/asset-parse-error.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAEpC,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC;IAC5B,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;gBAE3B,MAAM,EAAE,QAAQ,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM;CAQlD"}
1
+ {"version":3,"file":"asset-parse-error.d.ts","sourceRoot":"","sources":["../src/asset-parse-error.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAEpC,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC;IAC5B,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;gBAE3B,MAAM,EAAE,QAAQ,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM;CAQlD"}
@@ -7,11 +7,8 @@
7
7
  * every caller (currently the input-map loader in `input/input-manager.ts`)
8
8
  * does not have to reach into an unrelated subsystem for it.
9
9
  *
10
- * It was called `SceneParseError` until WO-9 task #6. The extraction that gave
11
- * this file its name deliberately deferred the class rename ("extraction, not
12
- * redesign"); with `.vscn` gone the old name described nothing — an
13
- * `.inputmap.json` failure is not a scene failure — so the class and its
14
- * message header now say `asset`.
10
+ * The name says ASSET, not scene: an `.inputmap.json` failure is not a scene
11
+ * failure, and the class covers every structured fetched asset.
15
12
  */
16
13
  export class AssetParseError extends Error {
17
14
  issues;
@@ -0,0 +1,101 @@
1
+ /**
2
+ * A named-bus mixer over Web Audio: buses created on demand, routed into each
3
+ * other by name, and set in DECIBELS.
4
+ *
5
+ * Every mixer a game reaches for is this shape — Unity's `AudioMixerGroup`,
6
+ * Godot's bus layout, FMOD's VCAs, and the `music`/`sfx`/`voice` trio
7
+ * `setup/setup-audio.ts` hands a first-party three world. What they share is
8
+ * not the protocol (that part is genuinely per-ecosystem and stays with the
9
+ * lane that speaks it) but the machinery underneath: a `GainNode` per bus, a
10
+ * name → node map, a parent to route into, and the one conversion below. This
11
+ * file owns exactly that, and nothing that names an ecosystem.
12
+ *
13
+ * ## dB is not a gain, and the mistake is silent
14
+ *
15
+ * `GainNode.gain` is a LINEAR amplitude multiplier; every mixer's authored
16
+ * volume is logarithmic dB, where 0 dB is unity and −80 dB is silence. Writing
17
+ * the dB number straight onto `gain.value` gives you a gain of −80 (a phase
18
+ * inversion at 80x) where the author asked for silence, and it does not throw,
19
+ * warn, or look wrong in a debugger — it is just loud. {@link dbToLinear} is
20
+ * the one conversion, `10^(dB/20)`, which is both Godot's `db_to_linear`
21
+ * (`core/math/math_funcs.h`: `exp(db * 0.11512925464970228…)`, the same
22
+ * function written in base e) and Unity's mixer volume curve.
23
+ *
24
+ * It deliberately does NOT clamp. A mixer's RANGE is protocol — Unity's
25
+ * exposed parameters saturate at its slider's ends, Godot's `volume_db` does
26
+ * not — so the lane that knows the range applies it before calling here, and
27
+ * this file cannot silently mute or silently boost anyone's authored value.
28
+ *
29
+ * ## Create-on-demand, and why it is the contract rather than a convenience
30
+ *
31
+ * {@link AudioBusMixer.bus} MINTS a bus the first time it is named and returns
32
+ * the SAME node forever after. The identity is the contract, not the minting:
33
+ * a source connects to a bus long before anything sets that bus's volume, and
34
+ * a parent is usually named by its child before anyone asks for it directly
35
+ * (`bus('music', 'master')` builds `master` too, and the later `bus('master')`
36
+ * must be that same node). A `bus()` that minted per call would hand the
37
+ * volume control a SECOND node — the sources would keep feeding the first one,
38
+ * every later write would land on a node nothing plays through, and nothing
39
+ * would throw or look wrong. So the map is authoritative, and the only way a
40
+ * name stops resolving to its node is {@link AudioBusMixer.remove} or
41
+ * {@link AudioBusMixer.disconnect}.
42
+ *
43
+ * A re-ask that names a DIFFERENT parent throws by name. Routing is decided at
44
+ * creation (the node is already connected by then), so honouring the second
45
+ * parent would mean silently re-routing live audio and ignoring it would mean
46
+ * silently keeping the first — a loud error is the only reading that is not a
47
+ * lie.
48
+ *
49
+ * ## RESOURCE OWNERSHIP
50
+ *
51
+ * No module-scoped state: {@link createAudioBusMixer} is a factory and the
52
+ * OWNER of an instance is whoever called it (a `setupAudio` graph, one
53
+ * translated port's mixer store). What an instance ALLOCATES is one `GainNode`
54
+ * per named bus, and disconnecting those is the whole of its teardown
55
+ * obligation — {@link AudioBusMixer.disconnect}, called once by that same
56
+ * owner. The `context` and the `destination` node are NOT its own: they are
57
+ * passed in, shared with everything else hanging off the same graph, and this
58
+ * file never creates, closes, suspends or disconnects either one.
59
+ */
60
+ /**
61
+ * The graph an {@link AudioBusMixer} hangs off, as the two members it touches.
62
+ *
63
+ * Narrow on purpose: `createGain` is all it needs from the context, so a real
64
+ * `AudioContext`, an `OfflineAudioContext` and a headless stand-in are all
65
+ * acceptable without a cast.
66
+ */
67
+ export interface AudioBusMixerOptions {
68
+ readonly context: {
69
+ createGain(): GainNode;
70
+ };
71
+ /** The node every parentless bus feeds. Usually a master gain or the context's destination. */
72
+ readonly destination: AudioNode;
73
+ }
74
+ export interface AudioBusMixer {
75
+ /**
76
+ * The bus named `name`, created on the first ask and connected to `parent`
77
+ * (itself created on demand) or to the destination.
78
+ *
79
+ * The returned node is the real `GainNode` — set `gain.value`, schedule
80
+ * automation on `gain`, connect sources to it. Nothing here stands between a
81
+ * caller and Web Audio's own API.
82
+ */
83
+ bus(name: string, parent?: string): GainNode;
84
+ /** The bus named `name` if it EXISTS, else null. Never mints one. */
85
+ find(name: string): GainNode | null;
86
+ /** Set this bus's gain from decibels, creating it if absent. Clamp before calling — see the header. */
87
+ setDb(name: string, db: number, parent?: string): void;
88
+ /**
89
+ * Disconnect one bus and forget its name, so a later {@link bus} mints a
90
+ * fresh node. Buses that named it as their parent are NOT re-routed — they
91
+ * keep feeding the removed node, which now reaches nothing.
92
+ */
93
+ remove(name: string): void;
94
+ /** Disconnect every bus and forget them all. The owner's ONE teardown. */
95
+ disconnect(): void;
96
+ }
97
+ /** dB → linear amplitude: `10^(dB/20)`. 0 dB is 1, −6 dB is ~0.5, −80 dB is ~0.0001. Never clamps. */
98
+ export declare function dbToLinear(db: number): number;
99
+ /** Create one named-bus mixer. See the header for what owns the instance and what it allocates. */
100
+ export declare function createAudioBusMixer(options: AudioBusMixerOptions): AudioBusMixer;
101
+ //# sourceMappingURL=bus-mixer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bus-mixer.d.ts","sourceRoot":"","sources":["../../src/audio/bus-mixer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AAEH;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,OAAO,EAAE;QAAE,UAAU,IAAI,QAAQ,CAAA;KAAE,CAAC;IAC7C,+FAA+F;IAC/F,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B;;;;;;;OAOG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC7C,qEAAqE;IACrE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IACpC,uGAAuG;IACvG,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvD;;;;OAIG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,0EAA0E;IAC1E,UAAU,IAAI,IAAI,CAAC;CACpB;AAED,sGAAsG;AACtG,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE7C;AAeD,mGAAmG;AACnG,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CA4ChF"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * A named-bus mixer over Web Audio: buses created on demand, routed into each
3
+ * other by name, and set in DECIBELS.
4
+ *
5
+ * Every mixer a game reaches for is this shape — Unity's `AudioMixerGroup`,
6
+ * Godot's bus layout, FMOD's VCAs, and the `music`/`sfx`/`voice` trio
7
+ * `setup/setup-audio.ts` hands a first-party three world. What they share is
8
+ * not the protocol (that part is genuinely per-ecosystem and stays with the
9
+ * lane that speaks it) but the machinery underneath: a `GainNode` per bus, a
10
+ * name → node map, a parent to route into, and the one conversion below. This
11
+ * file owns exactly that, and nothing that names an ecosystem.
12
+ *
13
+ * ## dB is not a gain, and the mistake is silent
14
+ *
15
+ * `GainNode.gain` is a LINEAR amplitude multiplier; every mixer's authored
16
+ * volume is logarithmic dB, where 0 dB is unity and −80 dB is silence. Writing
17
+ * the dB number straight onto `gain.value` gives you a gain of −80 (a phase
18
+ * inversion at 80x) where the author asked for silence, and it does not throw,
19
+ * warn, or look wrong in a debugger — it is just loud. {@link dbToLinear} is
20
+ * the one conversion, `10^(dB/20)`, which is both Godot's `db_to_linear`
21
+ * (`core/math/math_funcs.h`: `exp(db * 0.11512925464970228…)`, the same
22
+ * function written in base e) and Unity's mixer volume curve.
23
+ *
24
+ * It deliberately does NOT clamp. A mixer's RANGE is protocol — Unity's
25
+ * exposed parameters saturate at its slider's ends, Godot's `volume_db` does
26
+ * not — so the lane that knows the range applies it before calling here, and
27
+ * this file cannot silently mute or silently boost anyone's authored value.
28
+ *
29
+ * ## Create-on-demand, and why it is the contract rather than a convenience
30
+ *
31
+ * {@link AudioBusMixer.bus} MINTS a bus the first time it is named and returns
32
+ * the SAME node forever after. The identity is the contract, not the minting:
33
+ * a source connects to a bus long before anything sets that bus's volume, and
34
+ * a parent is usually named by its child before anyone asks for it directly
35
+ * (`bus('music', 'master')` builds `master` too, and the later `bus('master')`
36
+ * must be that same node). A `bus()` that minted per call would hand the
37
+ * volume control a SECOND node — the sources would keep feeding the first one,
38
+ * every later write would land on a node nothing plays through, and nothing
39
+ * would throw or look wrong. So the map is authoritative, and the only way a
40
+ * name stops resolving to its node is {@link AudioBusMixer.remove} or
41
+ * {@link AudioBusMixer.disconnect}.
42
+ *
43
+ * A re-ask that names a DIFFERENT parent throws by name. Routing is decided at
44
+ * creation (the node is already connected by then), so honouring the second
45
+ * parent would mean silently re-routing live audio and ignoring it would mean
46
+ * silently keeping the first — a loud error is the only reading that is not a
47
+ * lie.
48
+ *
49
+ * ## RESOURCE OWNERSHIP
50
+ *
51
+ * No module-scoped state: {@link createAudioBusMixer} is a factory and the
52
+ * OWNER of an instance is whoever called it (a `setupAudio` graph, one
53
+ * translated port's mixer store). What an instance ALLOCATES is one `GainNode`
54
+ * per named bus, and disconnecting those is the whole of its teardown
55
+ * obligation — {@link AudioBusMixer.disconnect}, called once by that same
56
+ * owner. The `context` and the `destination` node are NOT its own: they are
57
+ * passed in, shared with everything else hanging off the same graph, and this
58
+ * file never creates, closes, suspends or disconnects either one.
59
+ */
60
+ /** dB → linear amplitude: `10^(dB/20)`. 0 dB is 1, −6 dB is ~0.5, −80 dB is ~0.0001. Never clamps. */
61
+ export function dbToLinear(db) {
62
+ return 10 ** (db / 20);
63
+ }
64
+ function safeDisconnect(node) {
65
+ try {
66
+ node.disconnect();
67
+ }
68
+ catch {
69
+ // already disconnected
70
+ }
71
+ }
72
+ /** Create one named-bus mixer. See the header for what owns the instance and what it allocates. */
73
+ export function createAudioBusMixer(options) {
74
+ const { context, destination } = options;
75
+ const buses = new Map();
76
+ function bus(name, parent) {
77
+ const existing = buses.get(name);
78
+ if (existing !== undefined) {
79
+ if (parent !== undefined && parent !== existing.parent) {
80
+ throw new Error(`audio bus ${JSON.stringify(name)} already routes into ` +
81
+ `${existing.parent === undefined ? 'the destination' : JSON.stringify(existing.parent)}` +
82
+ `; it cannot also route into ${JSON.stringify(parent)}. Routing is decided when a bus ` +
83
+ 'is created (see packages/engine/src/audio/bus-mixer.ts).');
84
+ }
85
+ return existing.node;
86
+ }
87
+ // The parent is resolved (and minted, recursively) before this bus is
88
+ // seated, so a conflicting-parent throw upstream leaves nothing half-built.
89
+ const into = parent === undefined ? destination : bus(parent);
90
+ const node = context.createGain();
91
+ node.gain.value = 1;
92
+ node.connect(into);
93
+ buses.set(name, { node, parent });
94
+ return node;
95
+ }
96
+ return {
97
+ bus,
98
+ find: (name) => buses.get(name)?.node ?? null,
99
+ setDb: (name, db, parent) => {
100
+ bus(name, parent).gain.value = dbToLinear(db);
101
+ },
102
+ remove: (name) => {
103
+ const record = buses.get(name);
104
+ if (record === undefined)
105
+ return;
106
+ buses.delete(name);
107
+ safeDisconnect(record.node);
108
+ },
109
+ disconnect: () => {
110
+ for (const record of buses.values())
111
+ safeDisconnect(record.node);
112
+ buses.clear();
113
+ },
114
+ };
115
+ }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Frame pacing — the accumulator/alpha arithmetic of the fixed-timestep loop,
3
- * extracted PURE (WO-P13, `docs/WORK.md` §2 P13).
3
+ * extracted PURE.
4
4
  *
5
5
  * `core/game-loop.ts` owns the browser side (rAF, `visibilitychange`,
6
6
  * `performance.now`); this module owns the arithmetic, so the interesting
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Frame pacing — the accumulator/alpha arithmetic of the fixed-timestep loop,
3
- * extracted PURE (WO-P13, `docs/WORK.md` §2 P13).
3
+ * extracted PURE.
4
4
  *
5
5
  * `core/game-loop.ts` owns the browser side (rAF, `visibilitychange`,
6
6
  * `performance.now`); this module owns the arithmetic, so the interesting
@@ -72,7 +72,7 @@ export function paceFrame(accumulator, rawDt, timeScale, limits) {
72
72
  // Also the accumulator's hard ceiling (see the spiral-of-death clamp below).
73
73
  const maxAccumulator = fixedDt * maxSubSteps;
74
74
  // Clamp large frame gaps (a slow frame, a debugger pause) BEFORE scaling by
75
- // timeScale — unchanged from the pre-WO-P13 loop.
75
+ // timeScale.
76
76
  const displayDt = Math.min(rawDt, maxAccumulator) * timeScale;
77
77
  let next = accumulator + displayDt;
78
78
  // Spiral-of-death guard: bound the accumulator regardless of timeScale or
@@ -1,9 +1,7 @@
1
1
  import type { GameLoopConfig, GameLoopLiveness } from './types';
2
2
  /**
3
3
  * Fixed-timestep game loop with accumulator pattern — SIM at a fixed rate,
4
- * PRESENTATION at the display's rate (WO-P13, `docs/WORK.md` §2 P13, which
5
- * flipped the former D1 "render is fixed-rate too" decision this comment used
6
- * to state).
4
+ * PRESENTATION at the display's rate.
7
5
  *
8
6
  * Per real (rAF) frame:
9
7
  *
@@ -1 +1 @@
1
- {"version":3,"file":"game-loop.d.ts","sourceRoot":"","sources":["../../src/core/game-loop.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAQhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc;;;;IAuIjD;;;;;;;;;;;;OAYG;uBACa,gBAAgB;eASX,MAAM;IAe3B;;;;;;;OAOG;;EAKN"}
1
+ {"version":3,"file":"game-loop.d.ts","sourceRoot":"","sources":["../../src/core/game-loop.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAQhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc;;;;IAuIjD;;;;;;;;;;;;OAYG;uBACa,gBAAgB;eASX,MAAM;IAe3B;;;;;;;OAOG;;EAKN"}
@@ -6,9 +6,7 @@ import { clampTimeScale, paceFrame, TIME_SCALE_RANGE } from './frame-pacing';
6
6
  const LOOP_STARVATION_MS = 1_000;
7
7
  /**
8
8
  * Fixed-timestep game loop with accumulator pattern — SIM at a fixed rate,
9
- * PRESENTATION at the display's rate (WO-P13, `docs/WORK.md` §2 P13, which
10
- * flipped the former D1 "render is fixed-rate too" decision this comment used
11
- * to state).
9
+ * PRESENTATION at the display's rate.
12
10
  *
13
11
  * Per real (rAF) frame:
14
12
  *
@@ -36,7 +36,7 @@ export declare const GAMEPLAY_STREAM = "gameplay";
36
36
  * `determinism.seededRandom` is declared, per T4.1's "no dead field" rule). */
37
37
  export declare const DEFAULT_SEEDED_RANDOM_SEED = 2654435769;
38
38
  /**
39
- * The `ctx.random` surface (`GameContext.random`, `runtime/types.ts`).
39
+ * A game-scoped random surface.
40
40
  * Callable (draws from the `'gameplay'` stream), plus:
41
41
  * - `stream(name)` — an independent named generator, `[0, 1)` floats, same
42
42
  * call signature as `Math.random`/the bare `SeededRandom` call itself.
@@ -93,10 +93,9 @@
93
93
  * controller cancels everything a `setup()` scheduled:
94
94
  *
95
95
  * ```ts
96
- * export async function setup(ctx: GameContext): Promise<GameCleanup> {
97
- * const ac = new AbortController();
98
- * ctx.clock.after(3, () => spawnWave(), { signal: ac.signal });
99
- * return { dispose: () => ac.abort() }; // cancels timers AND listeners
96
+ * const ac = new AbortController();
97
+ * clock.after(3, () => spawnWave(), { signal: ac.signal });
98
+ * // on dispose: ac.abort() cancels timers AND listeners
100
99
  * }
101
100
  * ```
102
101
  *
@@ -164,7 +163,7 @@ export interface SimClock {
164
163
  /**
165
164
  * The runtime-facing half — NOT for game code. Split off the public
166
165
  * {@link SimClock} the same way `runtime/game.ts` splits `GameInternal` off
167
- * `Game`: `GameContext.clock` is typed as `SimClock`, so game code cannot
166
+ * `Game`: game code only ever sees the public `SimClock`, so it cannot
168
167
  * reach `flush`/`dispose`.
169
168
  */
170
169
  export interface SimClockInternal extends SimClock {
@@ -205,7 +204,7 @@ export declare function registerSimClock(owner: object, clock: SimClockInternal)
205
204
  * Returns the INTERNAL view because this registry is engine-only — but a
206
205
  * caller that RESOLVES a clock here is not its owner and must not call
207
206
  * `dispose()` on it (module header, ownership). Game code never reaches it at
208
- * all: `GameContext.clock` is typed as the public {@link SimClock}, which has
207
+ * all: it only ever sees the public {@link SimClock}, which has
209
208
  * neither `flush` nor `dispose`, the same way `Game` hides `GameInternal`. */
210
209
  export declare function getSimClock(owner: object): SimClockInternal | null;
211
210
  //# sourceMappingURL=sim-clock.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sim-clock.d.ts","sourceRoot":"","sources":["../../src/core/sim-clock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6HG;AAEH,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAGpC,sFAAsF;AACtF,MAAM,WAAW,cAAc;IAC7B,4DAA4D;IAC5D,MAAM,IAAI,IAAI,CAAC;CAChB;AAED,iDAAiD;AACjD,MAAM,WAAW,kBAAkB;IACjC,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAC3C;AAED,qEAAqE;AACrE,MAAM,WAAW,QAAQ;IACvB,wEAAwE;IACxE,GAAG,IAAI,MAAM,CAAC;IACd,2EAA2E;IAC3E,OAAO,IAAI,MAAM,CAAC;IAClB;;;;;OAKG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,EAAE,IAAI,CAAC,EAAE,kBAAkB,GAAG,cAAc,CAAC;IAClF;;;;;OAKG;IACH,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CAAC;CACpE;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAiB,SAAQ,QAAQ;IAChD;;;;;OAKG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;;OAKG;IACH,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC;CACjD;AAyBD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,gBAAgB,CAiJzE;AAWD,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAE7E;AAED;;;;;;;;+EAQ+E;AAC/E,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAElE"}
1
+ {"version":3,"file":"sim-clock.d.ts","sourceRoot":"","sources":["../../src/core/sim-clock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4HG;AAEH,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAGpC,sFAAsF;AACtF,MAAM,WAAW,cAAc;IAC7B,4DAA4D;IAC5D,MAAM,IAAI,IAAI,CAAC;CAChB;AAED,iDAAiD;AACjD,MAAM,WAAW,kBAAkB;IACjC,8EAA8E;IAC9E,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,SAAS,CAAC;CAC3C;AAED,qEAAqE;AACrE,MAAM,WAAW,QAAQ;IACvB,wEAAwE;IACxE,GAAG,IAAI,MAAM,CAAC;IACd,2EAA2E;IAC3E,OAAO,IAAI,MAAM,CAAC;IAClB;;;;;OAKG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE;;;OAGG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,EAAE,IAAI,CAAC,EAAE,kBAAkB,GAAG,cAAc,CAAC;IAClF;;;;;OAKG;IACH,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CAAC;CACpE;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAiB,SAAQ,QAAQ;IAChD;;;;;OAKG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;;;OAKG;IACH,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC;CACjD;AAyBD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,gBAAgB,CAiJzE;AAWD,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAE7E;AAED;;;;;;;;+EAQ+E;AAC/E,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAElE"}
@@ -93,10 +93,9 @@
93
93
  * controller cancels everything a `setup()` scheduled:
94
94
  *
95
95
  * ```ts
96
- * export async function setup(ctx: GameContext): Promise<GameCleanup> {
97
- * const ac = new AbortController();
98
- * ctx.clock.after(3, () => spawnWave(), { signal: ac.signal });
99
- * return { dispose: () => ac.abort() }; // cancels timers AND listeners
96
+ * const ac = new AbortController();
97
+ * clock.after(3, () => spawnWave(), { signal: ac.signal });
98
+ * // on dispose: ac.abort() cancels timers AND listeners
100
99
  * }
101
100
  * ```
102
101
  *
@@ -297,7 +296,7 @@ export function registerSimClock(owner, clock) {
297
296
  * Returns the INTERNAL view because this registry is engine-only — but a
298
297
  * caller that RESOLVES a clock here is not its owner and must not call
299
298
  * `dispose()` on it (module header, ownership). Game code never reaches it at
300
- * all: `GameContext.clock` is typed as the public {@link SimClock}, which has
299
+ * all: it only ever sees the public {@link SimClock}, which has
301
300
  * neither `flush` nor `dispose`, the same way `Game` hides `GameInternal`. */
302
301
  export function getSimClock(owner) {
303
302
  return clockByOwner.get(owner) ?? null;
@@ -56,9 +56,7 @@ export interface GameLoopConfig {
56
56
  */
57
57
  update: (dt: number) => void;
58
58
  /**
59
- * Called EXACTLY ONCE per real (rAF) frame — the PRESENTATION half
60
- * (WO-P13, `docs/WORK.md` §2 P13; this is the callback whose absence the
61
- * former D1 decision recorded).
59
+ * Called EXACTLY ONCE per real (rAF) frame — the PRESENTATION half.
62
60
  *
63
61
  * - `alpha` — `accumulator / fixedDt` after this frame's substeps were
64
62
  * consumed, in `[0, 1]`: how far presentation sits past the last
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,WAAW;;;;;;;;;CASd,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAE7E,+BAA+B;AAC/B,eAAO,MAAM,WAAW,EAAE,eAAe,EASxC,CAAC;AAEF,wDAAwD;AACxD,MAAM,MAAM,QAAQ,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;AAE5C,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACvE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACtE;AAED,yDAAyD;AACzD,MAAM,WAAW,SAAS;IACxB,uEAAuE;IACvE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,8CAA8C;IAC9C,KAAK,EAAE,eAAe,CAAC;IACvB,4EAA4E;IAC5E,IAAI,CAAC,IAAI,IAAI,CAAC;IACd,uBAAuB;IACvB,MAAM,EAAE,QAAQ,CAAC;IACjB,8DAA8D;IAC9D,OAAO,CAAC,IAAI,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;;;;OAUG;IACH,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,cAAc,GAAG,SAAS,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,WAAW;;;;;;;;;CASd,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAE7E,+BAA+B;AAC/B,eAAO,MAAM,WAAW,EAAE,eAAe,EASxC,CAAC;AAEF,wDAAwD;AACxD,MAAM,MAAM,QAAQ,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;AAE5C,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACvE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACtE;AAED,yDAAyD;AACzD,MAAM,WAAW,SAAS;IACxB,uEAAuE;IACvE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,8CAA8C;IAC9C,KAAK,EAAE,eAAe,CAAC;IACvB,4EAA4E;IAC5E,IAAI,CAAC,IAAI,IAAI,CAAC;IACd,uBAAuB;IACvB,MAAM,EAAE,QAAQ,CAAC;IACjB,8DAA8D;IAC9D,OAAO,CAAC,IAAI,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;;;;OAUG;IACH,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,cAAc,GAAG,SAAS,CAAC"}
@@ -1,20 +1,12 @@
1
1
  /**
2
2
  * Single source of truth for default values the engine's factories read.
3
3
  *
4
- * WO-8 deleted SEVEN groups `transform`, `entity`, `audio`, `shadow`,
5
- * `animation`, `fog`, `environment` because every one of their readers was a
6
- * `.vscn.json` consumer (`entity-factory.ts`, `scene-loader.ts`,
7
- * `scene-sync.ts`, `scene-serializer.ts`, the per-section inspectors) and
8
- * `defaults-source-scan.test.ts` reported them with ZERO `DEFAULTS.<group>`
9
- * readers anywhere in engine/editor src or tests. That guard offers two remedies
10
- * — wire the group to the factory that reads it, or delete it if truly unused —
11
- * and there is no surviving factory to wire these to: `transform` restated
12
- * THREE's own Object3D constructor values, `entity.locked`/ `pivot` were
13
- * descriptor-only fields, and `fog`/`environment.envMapIntensity`/ `shadow` were
14
- * the `.vscn` `environment` block that `render-env.ts` explicitly did NOT carry
15
- * forward. Keeping them would have been exactly the dead documentation T1.13
16
- * created this guard to prevent.
17
- *
4
+ * A group belongs here only while a FACTORY reads it. A default with no
5
+ * reader is dead documentation: it looks authoritative, nothing consults it,
6
+ * and it drifts from the value the code actually uses. Restating a library's
7
+ * own constructor values (THREE's `Object3D` transform, say) is the same
8
+ * mistake in a different shape — the library is already the source of truth.
9
+ * So when a factory goes, its group goes with it.
18
10
  */
19
11
  export declare const DEFAULTS: {
20
12
  readonly material: {
@@ -1 +1 @@
1
- {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gDAkB0B,CAAC,MAAM,EAAE,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;kCA6BjB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6E5D,CAAC"}
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gDAkB0B,CAAC,MAAM,EAAE,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;kCA6BjB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6E5D,CAAC"}
package/dist/defaults.js CHANGED
@@ -1,20 +1,12 @@
1
1
  /**
2
2
  * Single source of truth for default values the engine's factories read.
3
3
  *
4
- * WO-8 deleted SEVEN groups `transform`, `entity`, `audio`, `shadow`,
5
- * `animation`, `fog`, `environment` because every one of their readers was a
6
- * `.vscn.json` consumer (`entity-factory.ts`, `scene-loader.ts`,
7
- * `scene-sync.ts`, `scene-serializer.ts`, the per-section inspectors) and
8
- * `defaults-source-scan.test.ts` reported them with ZERO `DEFAULTS.<group>`
9
- * readers anywhere in engine/editor src or tests. That guard offers two remedies
10
- * — wire the group to the factory that reads it, or delete it if truly unused —
11
- * and there is no surviving factory to wire these to: `transform` restated
12
- * THREE's own Object3D constructor values, `entity.locked`/ `pivot` were
13
- * descriptor-only fields, and `fog`/`environment.envMapIntensity`/ `shadow` were
14
- * the `.vscn` `environment` block that `render-env.ts` explicitly did NOT carry
15
- * forward. Keeping them would have been exactly the dead documentation T1.13
16
- * created this guard to prevent.
17
- *
4
+ * A group belongs here only while a FACTORY reads it. A default with no
5
+ * reader is dead documentation: it looks authoritative, nothing consults it,
6
+ * and it drifts from the value the code actually uses. Restating a library's
7
+ * own constructor values (THREE's `Object3D` transform, say) is the same
8
+ * mistake in a different shape — the library is already the source of truth.
9
+ * So when a factory goes, its group goes with it.
18
10
  */
19
11
  export const DEFAULTS = {
20
12
  material: {
@@ -8,10 +8,7 @@
8
8
  *
9
9
  * Engine-owned and first-party, seeded by BOTH three-root mount paths — a game
10
10
  * writes nothing to get these, and there is no capability to install:
11
- * - `adapter/setup-three-root-adapter.ts` (the classic imperative
12
- * `setup(ctx)` world), at the same spot it seeds
13
- * `systemAdapters.renderDebug`;
14
- * - `world3d-react/r3f-adapter.tsx` (a TSX/R3F world — the shape EVERY
11
+ * - `world3d-react/r3f-root-factory.tsx` (a TSX/R3F world — the shape EVERY
15
12
  * scaffolded project's three root has), right after fiber's first commit
16
13
  * resolves the scene.
17
14
  * Both is the whole point and not redundancy: they are two independent mounts
@@ -1 +1 @@
1
- {"version":3,"file":"register-render-vitals.d.ts","sourceRoot":"","sources":["../../src/dev/register-render-vitals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAElE,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAOxE,wEAAwE;AACxE,eAAO,MAAM,sBAAsB,kBAAkB,CAAC;AACtD,eAAO,MAAM,qBAAqB,kBAAkB,CAAC;AACrD,eAAO,MAAM,uBAAuB,oBAAoB,CAAC;AACzD,eAAO,MAAM,qBAAqB,kBAAkB,CAAC;AACrD,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAE/C;0EAC0E;AAC1E,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC9C,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACpE,aAAa,IAAI,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1E;AAED,MAAM,WAAW,wBAAwB;IACvC,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,kEAAkE;IAClE,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC;uEACmE;IACnE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,uCAAuC;IACvC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC;IAC/B;uCACmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAAC;CAChD;AAMD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,wBAAwB,GAC7B,wBAAwB,GAAG,IAAI,CA8JjC"}
1
+ {"version":3,"file":"register-render-vitals.d.ts","sourceRoot":"","sources":["../../src/dev/register-render-vitals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAElE,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAOxE,wEAAwE;AACxE,eAAO,MAAM,sBAAsB,kBAAkB,CAAC;AACtD,eAAO,MAAM,qBAAqB,kBAAkB,CAAC;AACrD,eAAO,MAAM,uBAAuB,oBAAoB,CAAC;AACzD,eAAO,MAAM,qBAAqB,kBAAkB,CAAC;AACrD,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAE/C;0EAC0E;AAC1E,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC9C,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACpE,aAAa,IAAI,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1E;AAED,MAAM,WAAW,wBAAwB;IACvC,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,kEAAkE;IAClE,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC;uEACmE;IACnE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,uCAAuC;IACvC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC;IAC/B;uCACmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,CAAC;CAChD;AAMD;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,wBAAwB,GAC7B,wBAAwB,GAAG,IAAI,CA8JjC"}
@@ -8,10 +8,7 @@
8
8
  *
9
9
  * Engine-owned and first-party, seeded by BOTH three-root mount paths — a game
10
10
  * writes nothing to get these, and there is no capability to install:
11
- * - `adapter/setup-three-root-adapter.ts` (the classic imperative
12
- * `setup(ctx)` world), at the same spot it seeds
13
- * `systemAdapters.renderDebug`;
14
- * - `world3d-react/r3f-adapter.tsx` (a TSX/R3F world — the shape EVERY
11
+ * - `world3d-react/r3f-root-factory.tsx` (a TSX/R3F world — the shape EVERY
15
12
  * scaffolded project's three root has), right after fiber's first commit
16
13
  * resolves the scene.
17
14
  * Both is the whole point and not redundancy: they are two independent mounts
@@ -3,11 +3,10 @@
3
3
  * the WebGL2 frame capture (`webgl-frame-capture.ts`), a live three.js scene,
4
4
  * and the render adapter's per-frame render pass.
5
5
  *
6
- * Split OUT of `setup-three-root-adapter.ts` so the capture/attribution/restore
6
+ * Split OUT of `world3d-react/r3f-root-factory.tsx` so the capture/attribution/restore
7
7
  * flow is unit-testable in a headless Node test with a mock GL context and a
8
8
  * plain scene — a real non-headless GPU mount (EffectComposer + WebGLRenderer)
9
- * cannot run under vitest here, the same reason the adapter suite drives
10
- * `setup(ctx)` only through hotReload on a data scene. `mount()` owns the
9
+ * cannot run under vitest here. `mount()` owns the
11
10
  * DECISION to construct this (only under a real WebGL2 context, never
12
11
  * headless — see `frameCaptureContextFor`); this module owns the BEHAVIOR.
13
12
  *
@@ -1 +1 @@
1
- {"version":3,"file":"render-debug-adapter.d.ts","sourceRoot":"","sources":["../../src/dev/render-debug-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,KAAK,EAAgC,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE7F;;;2DAG2D;AAC3D,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,OAAO,EACjB,eAAe,EAAE,OAAO,GACvB,sBAAsB,GAAG,IAAI,CAO/B;AAED,MAAM,WAAW,sBAAsB;IACrC,uEAAuE;IACvE,OAAO,EAAE,iBAAiB,CAAC;IAC3B;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC;IACvB;gFAC4E;IAC5E,MAAM,CAAC,EAAE,MAAM,oBAAoB,CAAC;IACpC;yDACqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;0BACsB;IACtB,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;IACvD,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,+DAA+D;IAC/D,YAAY,IAAI,IAAI,CAAC;IACrB,6EAA6E;IAC7E,WAAW,IAAI,IAAI,CAAC;IACpB,6EAA6E;IAC7E,OAAO,IAAI,IAAI,CAAC;CACjB;AAkDD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,sBAAsB,GAAG,iBAAiB,CAmFxF"}
1
+ {"version":3,"file":"render-debug-adapter.d.ts","sourceRoot":"","sources":["../../src/dev/render-debug-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,KAAK,EAAgC,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE7F;;;2DAG2D;AAC3D,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,OAAO,EACjB,eAAe,EAAE,OAAO,GACvB,sBAAsB,GAAG,IAAI,CAO/B;AAED,MAAM,WAAW,sBAAsB;IACrC,uEAAuE;IACvE,OAAO,EAAE,iBAAiB,CAAC;IAC3B;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC,QAAQ,CAAC;IACvB;gFAC4E;IAC5E,MAAM,CAAC,EAAE,MAAM,oBAAoB,CAAC;IACpC;yDACqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;0BACsB;IACtB,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;IACvD,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;IACrC,+DAA+D;IAC/D,YAAY,IAAI,IAAI,CAAC;IACrB,6EAA6E;IAC7E,WAAW,IAAI,IAAI,CAAC;IACpB,6EAA6E;IAC7E,OAAO,IAAI,IAAI,CAAC;CACjB;AAkDD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,sBAAsB,GAAG,iBAAiB,CAmFxF"}
@@ -3,11 +3,10 @@
3
3
  * the WebGL2 frame capture (`webgl-frame-capture.ts`), a live three.js scene,
4
4
  * and the render adapter's per-frame render pass.
5
5
  *
6
- * Split OUT of `setup-three-root-adapter.ts` so the capture/attribution/restore
6
+ * Split OUT of `world3d-react/r3f-root-factory.tsx` so the capture/attribution/restore
7
7
  * flow is unit-testable in a headless Node test with a mock GL context and a
8
8
  * plain scene — a real non-headless GPU mount (EffectComposer + WebGLRenderer)
9
- * cannot run under vitest here, the same reason the adapter suite drives
10
- * `setup(ctx)` only through hotReload on a data scene. `mount()` owns the
9
+ * cannot run under vitest here. `mount()` owns the
11
10
  * DECISION to construct this (only under a real WebGL2 context, never
12
11
  * headless — see `frameCaptureContextFor`); this module owns the BEHAVIOR.
13
12
  *
@@ -43,14 +43,14 @@
43
43
  * OWNER: the caller of {@link createRenderVitals}, which allocates one state
44
44
  * object and one `profiler.subscribe` registration. SHARER: none — the state
45
45
  * is private to that call. TEARDOWN: the returned `dispose()`, the ONE path
46
- * that ends the subscription (`setup-three-root-adapter.ts` calls it from
47
- * `disposeGame`).
46
+ * that ends the subscription (`world3d-react/r3f-root-factory.tsx` calls it
47
+ * from the mounted root's own `dispose()`).
48
48
  */
49
49
  import type { PerformanceFrame, PerformanceProfiler } from './performance-profiler';
50
50
  /**
51
51
  * The profiler phase name the three adapter brackets its CPU render
52
52
  * submission with — spelled HERE and nowhere else, so the producer
53
- * (`setup-three-root-adapter.ts`) and the consumer ({@link foldProfilerFrame})
53
+ * (`world3d-react/r3f-root-factory.tsx`) and the consumer ({@link foldProfilerFrame})
54
54
  * cannot drift apart. Dotted, so it reads as a decomposition of the enclosing
55
55
  * `render` phase rather than a ninth peer of `SystemPhase`.
56
56
  */
@@ -43,13 +43,13 @@
43
43
  * OWNER: the caller of {@link createRenderVitals}, which allocates one state
44
44
  * object and one `profiler.subscribe` registration. SHARER: none — the state
45
45
  * is private to that call. TEARDOWN: the returned `dispose()`, the ONE path
46
- * that ends the subscription (`setup-three-root-adapter.ts` calls it from
47
- * `disposeGame`).
46
+ * that ends the subscription (`world3d-react/r3f-root-factory.tsx` calls it
47
+ * from the mounted root's own `dispose()`).
48
48
  */
49
49
  /**
50
50
  * The profiler phase name the three adapter brackets its CPU render
51
51
  * submission with — spelled HERE and nowhere else, so the producer
52
- * (`setup-three-root-adapter.ts`) and the consumer ({@link foldProfilerFrame})
52
+ * (`world3d-react/r3f-root-factory.tsx`) and the consumer ({@link foldProfilerFrame})
53
53
  * cannot drift apart. Dotted, so it reads as a decomposition of the enclosing
54
54
  * `render` phase rather than a ninth peer of `SystemPhase`.
55
55
  */
@@ -4,7 +4,7 @@
4
4
  * WHY FIRST-PARTY, NOT spectorjs (recorded per the "use libraries directly, no
5
5
  * wrappers" rule): the capture seam we need is the WebGL2 context this engine
6
6
  * ALREADY owns end-to-end (`renderer.getContext()` in
7
- * `setup-three-root-adapter.ts`). spectorjs is absent from node_modules, and its
7
+ * `world3d-react/r3f-root-factory.tsx`). spectorjs is absent from node_modules, and its
8
8
  * actual value is a bundled inspector UI we would discard — adopting it imports
9
9
  * ~2MB of library to keep ~10% of it, and it wraps the context with its own
10
10
  * global patching model rather than the instance-shadow-and-restore discipline
@@ -4,7 +4,7 @@
4
4
  * WHY FIRST-PARTY, NOT spectorjs (recorded per the "use libraries directly, no
5
5
  * wrappers" rule): the capture seam we need is the WebGL2 context this engine
6
6
  * ALREADY owns end-to-end (`renderer.getContext()` in
7
- * `setup-three-root-adapter.ts`). spectorjs is absent from node_modules, and its
7
+ * `world3d-react/r3f-root-factory.tsx`). spectorjs is absent from node_modules, and its
8
8
  * actual value is a bundled inspector UI we would discard — adopting it imports
9
9
  * ~2MB of library to keep ~10% of it, and it wraps the context with its own
10
10
  * global patching model rather than the instance-shadow-and-restore discipline