@vgai/engine 0.5.4 → 0.5.6

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 (448) hide show
  1. package/dist/adapter/adapter-surface.d.ts +30 -0
  2. package/dist/adapter/adapter-surface.d.ts.map +1 -0
  3. package/dist/adapter/adapter-surface.js +18 -0
  4. package/dist/adapter/authoring.d.ts +597 -0
  5. package/dist/adapter/authoring.d.ts.map +1 -0
  6. package/dist/adapter/authoring.js +22 -0
  7. package/dist/adapter/colyseus-networking-adapter.d.ts +77 -0
  8. package/dist/adapter/colyseus-networking-adapter.d.ts.map +1 -0
  9. package/dist/adapter/colyseus-networking-adapter.js +76 -0
  10. package/dist/adapter/first-party-systems.d.ts +23 -0
  11. package/dist/adapter/first-party-systems.d.ts.map +1 -0
  12. package/dist/adapter/first-party-systems.js +196 -0
  13. package/dist/adapter/host-context.d.ts +194 -0
  14. package/dist/adapter/host-context.d.ts.map +1 -0
  15. package/dist/adapter/host-context.js +80 -0
  16. package/dist/adapter/index.d.ts +33 -0
  17. package/dist/adapter/index.d.ts.map +1 -0
  18. package/dist/adapter/index.js +25 -0
  19. package/dist/adapter/ingest/game-contract.d.ts +53 -0
  20. package/dist/adapter/ingest/game-contract.d.ts.map +1 -0
  21. package/dist/adapter/ingest/game-contract.js +30 -0
  22. package/dist/adapter/ingest/scene-capture.d.ts +121 -0
  23. package/dist/adapter/ingest/scene-capture.d.ts.map +1 -0
  24. package/dist/adapter/ingest/scene-capture.js +270 -0
  25. package/dist/adapter/ingest/structural-ids.d.ts +64 -0
  26. package/dist/adapter/ingest/structural-ids.d.ts.map +1 -0
  27. package/dist/adapter/ingest/structural-ids.js +110 -0
  28. package/dist/adapter/ingest/upstream-pin.d.ts +44 -0
  29. package/dist/adapter/ingest/upstream-pin.d.ts.map +1 -0
  30. package/dist/adapter/ingest/upstream-pin.js +47 -0
  31. package/dist/adapter/loop-gate-report.d.ts +34 -0
  32. package/dist/adapter/loop-gate-report.d.ts.map +1 -0
  33. package/dist/adapter/loop-gate-report.js +37 -0
  34. package/dist/adapter/rapier-physics-adapter.d.ts +69 -0
  35. package/dist/adapter/rapier-physics-adapter.d.ts.map +1 -0
  36. package/dist/adapter/rapier-physics-adapter.js +135 -0
  37. package/dist/adapter/root-adapter.d.ts +195 -0
  38. package/dist/adapter/root-adapter.d.ts.map +1 -0
  39. package/dist/adapter/root-adapter.js +25 -0
  40. package/dist/adapter/setup-three-root-adapter.d.ts +87 -0
  41. package/dist/adapter/setup-three-root-adapter.d.ts.map +1 -0
  42. package/dist/adapter/setup-three-root-adapter.js +791 -0
  43. package/dist/adapter/system-adapter.d.ts +453 -0
  44. package/dist/adapter/system-adapter.d.ts.map +1 -0
  45. package/dist/adapter/system-adapter.js +13 -0
  46. package/dist/adapter/transform.d.ts +18 -0
  47. package/dist/adapter/transform.d.ts.map +1 -0
  48. package/dist/adapter/transform.js +1 -0
  49. package/dist/ai/navigation.d.ts +78 -0
  50. package/dist/ai/navigation.d.ts.map +1 -0
  51. package/dist/ai/navigation.js +152 -0
  52. package/dist/animation/anim-graph-types.d.ts +25 -0
  53. package/dist/animation/anim-graph-types.d.ts.map +1 -0
  54. package/dist/animation/anim-graph-types.js +1 -0
  55. package/dist/animation/animation-clock.d.ts +213 -0
  56. package/dist/animation/animation-clock.d.ts.map +1 -0
  57. package/dist/animation/animation-clock.js +301 -0
  58. package/dist/animation/blend-node.d.ts +22 -0
  59. package/dist/animation/blend-node.d.ts.map +1 -0
  60. package/dist/animation/blend-node.js +97 -0
  61. package/dist/animation/camera-ownership.d.ts +249 -0
  62. package/dist/animation/camera-ownership.d.ts.map +1 -0
  63. package/dist/animation/camera-ownership.js +169 -0
  64. package/dist/animation/cinematic-cues.d.ts +200 -0
  65. package/dist/animation/cinematic-cues.d.ts.map +1 -0
  66. package/dist/animation/cinematic-cues.js +213 -0
  67. package/dist/animation/clip-map.d.ts +12 -0
  68. package/dist/animation/clip-map.d.ts.map +1 -0
  69. package/dist/animation/clip-map.js +31 -0
  70. package/dist/animation/cubic-spline-interpolant.d.ts +54 -0
  71. package/dist/animation/cubic-spline-interpolant.d.ts.map +1 -0
  72. package/dist/animation/cubic-spline-interpolant.js +111 -0
  73. package/dist/animation/theatre-clock-binding.d.ts +89 -0
  74. package/dist/animation/theatre-clock-binding.d.ts.map +1 -0
  75. package/dist/animation/theatre-clock-binding.js +29 -0
  76. package/dist/animation/theatre-director.d.ts +277 -0
  77. package/dist/animation/theatre-director.d.ts.map +1 -0
  78. package/dist/animation/theatre-director.js +248 -0
  79. package/dist/animation/theatre-object-binding.d.ts +305 -0
  80. package/dist/animation/theatre-object-binding.d.ts.map +1 -0
  81. package/dist/animation/theatre-object-binding.js +351 -0
  82. package/dist/animation/xstate-animation-binding.d.ts +119 -0
  83. package/dist/animation/xstate-animation-binding.d.ts.map +1 -0
  84. package/dist/animation/xstate-animation-binding.js +349 -0
  85. package/dist/animation/xstate-animation-meta.d.ts +266 -0
  86. package/dist/animation/xstate-animation-meta.d.ts.map +1 -0
  87. package/dist/animation/xstate-animation-meta.js +252 -0
  88. package/dist/asset-formats/camera.d.ts +15 -0
  89. package/dist/asset-formats/camera.d.ts.map +1 -0
  90. package/dist/asset-formats/camera.js +15 -0
  91. package/dist/asset-formats/collider.d.ts +21 -0
  92. package/dist/asset-formats/collider.d.ts.map +1 -0
  93. package/dist/asset-formats/collider.js +53 -0
  94. package/dist/asset-formats/index.d.ts +46 -0
  95. package/dist/asset-formats/index.d.ts.map +1 -0
  96. package/dist/asset-formats/index.js +36 -0
  97. package/dist/asset-formats/instances.d.ts +17 -0
  98. package/dist/asset-formats/instances.d.ts.map +1 -0
  99. package/dist/asset-formats/instances.js +31 -0
  100. package/dist/asset-formats/light.d.ts +21 -0
  101. package/dist/asset-formats/light.d.ts.map +1 -0
  102. package/dist/asset-formats/light.js +35 -0
  103. package/dist/asset-formats/material.d.ts +129 -0
  104. package/dist/asset-formats/material.d.ts.map +1 -0
  105. package/dist/asset-formats/material.js +88 -0
  106. package/dist/asset-formats/mesh.d.ts +22 -0
  107. package/dist/asset-formats/mesh.d.ts.map +1 -0
  108. package/dist/asset-formats/mesh.js +64 -0
  109. package/dist/asset-formats/parse.d.ts +20 -0
  110. package/dist/asset-formats/parse.d.ts.map +1 -0
  111. package/dist/asset-formats/parse.js +34 -0
  112. package/dist/asset-formats/particles.d.ts +1390 -0
  113. package/dist/asset-formats/particles.d.ts.map +1 -0
  114. package/dist/asset-formats/particles.js +319 -0
  115. package/dist/asset-formats/render-env.d.ts +387 -0
  116. package/dist/asset-formats/render-env.d.ts.map +1 -0
  117. package/dist/asset-formats/render-env.js +300 -0
  118. package/dist/asset-formats/tuples.d.ts +12 -0
  119. package/dist/asset-formats/tuples.d.ts.map +1 -0
  120. package/dist/asset-formats/tuples.js +14 -0
  121. package/dist/asset-loaders.d.ts +97 -0
  122. package/dist/asset-loaders.d.ts.map +1 -0
  123. package/dist/asset-loaders.js +209 -0
  124. package/dist/asset-parse-error.d.ts +24 -0
  125. package/dist/asset-parse-error.d.ts.map +1 -0
  126. package/dist/asset-parse-error.js +29 -0
  127. package/dist/asset-registry.d.ts +38 -0
  128. package/dist/asset-registry.d.ts.map +1 -0
  129. package/dist/asset-registry.js +66 -0
  130. package/dist/assets.d.ts +26 -0
  131. package/dist/assets.d.ts.map +1 -0
  132. package/dist/assets.js +55 -0
  133. package/dist/audio/wav-encode.d.ts +38 -0
  134. package/dist/audio/wav-encode.d.ts.map +1 -0
  135. package/dist/audio/wav-encode.js +97 -0
  136. package/dist/canvas-react/engine-bridge.d.ts +45 -0
  137. package/dist/canvas-react/engine-bridge.d.ts.map +1 -0
  138. package/dist/canvas-react/engine-bridge.js +45 -0
  139. package/dist/canvas-react/index.d.ts +42 -0
  140. package/dist/canvas-react/index.d.ts.map +1 -0
  141. package/dist/canvas-react/index.js +41 -0
  142. package/dist/canvas-react/pixi-primitive.d.ts +85 -0
  143. package/dist/canvas-react/pixi-primitive.d.ts.map +1 -0
  144. package/dist/canvas-react/pixi-primitive.js +181 -0
  145. package/dist/canvas-react/pixi-react-adapter.d.ts +71 -0
  146. package/dist/canvas-react/pixi-react-adapter.d.ts.map +1 -0
  147. package/dist/canvas-react/pixi-react-adapter.js +229 -0
  148. package/dist/canvas-react/pixi-react-root-factory.d.ts +56 -0
  149. package/dist/canvas-react/pixi-react-root-factory.d.ts.map +1 -0
  150. package/dist/canvas-react/pixi-react-root-factory.js +73 -0
  151. package/dist/canvas-react/world-context.d.ts +88 -0
  152. package/dist/canvas-react/world-context.d.ts.map +1 -0
  153. package/dist/canvas-react/world-context.js +212 -0
  154. package/dist/config.d.ts +9 -0
  155. package/dist/config.d.ts.map +1 -0
  156. package/dist/config.js +8 -0
  157. package/dist/core/frame-pacing.d.ts +90 -0
  158. package/dist/core/frame-pacing.d.ts.map +1 -0
  159. package/dist/core/frame-pacing.js +89 -0
  160. package/dist/core/game-loop.d.ts +62 -0
  161. package/dist/core/game-loop.d.ts.map +1 -0
  162. package/dist/core/game-loop.js +189 -0
  163. package/dist/core/seeded-random.d.ts +69 -0
  164. package/dist/core/seeded-random.d.ts.map +1 -0
  165. package/dist/core/seeded-random.js +121 -0
  166. package/dist/core/sim-clock.d.ts +199 -0
  167. package/dist/core/sim-clock.d.ts.map +1 -0
  168. package/dist/core/sim-clock.js +291 -0
  169. package/dist/core/system-runner.d.ts +96 -0
  170. package/dist/core/system-runner.d.ts.map +1 -0
  171. package/dist/core/system-runner.js +253 -0
  172. package/dist/core/types.d.ts +111 -0
  173. package/dist/core/types.d.ts.map +1 -0
  174. package/dist/core/types.js +25 -0
  175. package/dist/data/data-asset.d.ts +101 -0
  176. package/dist/data/data-asset.d.ts.map +1 -0
  177. package/dist/data/data-asset.js +122 -0
  178. package/dist/data/data-check-core.d.ts +109 -0
  179. package/dist/data/data-check-core.d.ts.map +1 -0
  180. package/dist/data/data-check-core.js +177 -0
  181. package/dist/data/data-ref.d.ts +79 -0
  182. package/dist/data/data-ref.d.ts.map +1 -0
  183. package/dist/data/data-ref.js +130 -0
  184. package/dist/data/vite-plugin-data.d.ts +79 -0
  185. package/dist/data/vite-plugin-data.d.ts.map +1 -0
  186. package/dist/data/vite-plugin-data.js +217 -0
  187. package/dist/defaults.d.ts +233 -0
  188. package/dist/defaults.d.ts.map +1 -0
  189. package/dist/defaults.js +137 -0
  190. package/dist/dev/chrome-trace.d.ts +45 -0
  191. package/dist/dev/chrome-trace.d.ts.map +1 -0
  192. package/dist/dev/chrome-trace.js +114 -0
  193. package/dist/dev/console-bridge.d.ts +22 -0
  194. package/dist/dev/console-bridge.d.ts.map +1 -0
  195. package/dist/dev/console-bridge.js +71 -0
  196. package/dist/dev/debug-draw.d.ts +24 -0
  197. package/dist/dev/debug-draw.d.ts.map +1 -0
  198. package/dist/dev/debug-draw.js +73 -0
  199. package/dist/dev/instruments.d.ts +133 -0
  200. package/dist/dev/instruments.d.ts.map +1 -0
  201. package/dist/dev/instruments.js +231 -0
  202. package/dist/dev/logger.d.ts +30 -0
  203. package/dist/dev/logger.d.ts.map +1 -0
  204. package/dist/dev/logger.js +90 -0
  205. package/dist/dev/performance-profiler.d.ts +111 -0
  206. package/dist/dev/performance-profiler.d.ts.map +1 -0
  207. package/dist/dev/performance-profiler.js +215 -0
  208. package/dist/dev/render-debug-adapter.d.ts +57 -0
  209. package/dist/dev/render-debug-adapter.d.ts.map +1 -0
  210. package/dist/dev/render-debug-adapter.js +141 -0
  211. package/dist/dev/render-memory.d.ts +53 -0
  212. package/dist/dev/render-memory.d.ts.map +1 -0
  213. package/dist/dev/render-memory.js +190 -0
  214. package/dist/dev/webgl-frame-capture.d.ts +134 -0
  215. package/dist/dev/webgl-frame-capture.d.ts.map +1 -0
  216. package/dist/dev/webgl-frame-capture.js +270 -0
  217. package/dist/dev/webgl-gpu-timer.d.ts +8 -0
  218. package/dist/dev/webgl-gpu-timer.d.ts.map +1 -0
  219. package/dist/dev/webgl-gpu-timer.js +52 -0
  220. package/dist/ecs/scene-index.d.ts +179 -0
  221. package/dist/ecs/scene-index.d.ts.map +1 -0
  222. package/dist/ecs/scene-index.js +331 -0
  223. package/dist/ecs/scene-query.d.ts +6 -0
  224. package/dist/ecs/scene-query.d.ts.map +1 -0
  225. package/dist/ecs/scene-query.js +40 -0
  226. package/dist/ecs/user-data.d.ts +193 -0
  227. package/dist/ecs/user-data.d.ts.map +1 -0
  228. package/dist/ecs/user-data.js +145 -0
  229. package/dist/index.d.ts +35 -0
  230. package/dist/index.d.ts.map +1 -0
  231. package/dist/index.js +29 -0
  232. package/dist/input/input-manager.d.ts +944 -0
  233. package/dist/input/input-manager.d.ts.map +1 -0
  234. package/dist/input/input-manager.js +2209 -0
  235. package/dist/input/input-types.d.ts +174 -0
  236. package/dist/input/input-types.d.ts.map +1 -0
  237. package/dist/input/input-types.js +1 -0
  238. package/dist/input/prompt-labels.d.ts +21 -0
  239. package/dist/input/prompt-labels.d.ts.map +1 -0
  240. package/dist/input/prompt-labels.js +121 -0
  241. package/dist/input/rebind-controller.d.ts +59 -0
  242. package/dist/input/rebind-controller.d.ts.map +1 -0
  243. package/dist/input/rebind-controller.js +85 -0
  244. package/dist/input/schema.d.ts +16 -0
  245. package/dist/input/schema.d.ts.map +1 -0
  246. package/dist/input/schema.js +228 -0
  247. package/dist/loader.d.ts +76 -0
  248. package/dist/loader.d.ts.map +1 -0
  249. package/dist/loader.js +114 -0
  250. package/dist/manifest/editor-port.d.ts +53 -0
  251. package/dist/manifest/editor-port.d.ts.map +1 -0
  252. package/dist/manifest/editor-port.js +67 -0
  253. package/dist/manifest/filename.d.ts +14 -0
  254. package/dist/manifest/filename.d.ts.map +1 -0
  255. package/dist/manifest/filename.js +43 -0
  256. package/dist/manifest/index.d.ts +6 -0
  257. package/dist/manifest/index.d.ts.map +1 -0
  258. package/dist/manifest/index.js +9 -0
  259. package/dist/manifest/load-file.d.ts +7 -0
  260. package/dist/manifest/load-file.d.ts.map +1 -0
  261. package/dist/manifest/load-file.js +23 -0
  262. package/dist/manifest/load.d.ts +161 -0
  263. package/dist/manifest/load.d.ts.map +1 -0
  264. package/dist/manifest/load.js +269 -0
  265. package/dist/manifest/locate.d.ts +24 -0
  266. package/dist/manifest/locate.d.ts.map +1 -0
  267. package/dist/manifest/locate.js +48 -0
  268. package/dist/manifest/schema.d.ts +293 -0
  269. package/dist/manifest/schema.d.ts.map +1 -0
  270. package/dist/manifest/schema.js +633 -0
  271. package/dist/physics/collider-dimensions.d.ts +63 -0
  272. package/dist/physics/collider-dimensions.d.ts.map +1 -0
  273. package/dist/physics/collider-dimensions.js +98 -0
  274. package/dist/physics/collision-system.d.ts +41 -0
  275. package/dist/physics/collision-system.d.ts.map +1 -0
  276. package/dist/physics/collision-system.js +64 -0
  277. package/dist/physics/physics-registry.d.ts +45 -0
  278. package/dist/physics/physics-registry.d.ts.map +1 -0
  279. package/dist/physics/physics-registry.js +65 -0
  280. package/dist/physics/transform-writer.d.ts +16 -0
  281. package/dist/physics/transform-writer.d.ts.map +1 -0
  282. package/dist/physics/transform-writer.js +38 -0
  283. package/dist/pixi/authoring.d.ts +93 -0
  284. package/dist/pixi/authoring.d.ts.map +1 -0
  285. package/dist/pixi/authoring.js +207 -0
  286. package/dist/pixi/index.d.ts +16 -0
  287. package/dist/pixi/index.d.ts.map +1 -0
  288. package/dist/pixi/index.js +15 -0
  289. package/dist/pixi/ingest-iframe.d.ts +82 -0
  290. package/dist/pixi/ingest-iframe.d.ts.map +1 -0
  291. package/dist/pixi/ingest-iframe.js +166 -0
  292. package/dist/pixi/ingest.d.ts +97 -0
  293. package/dist/pixi/ingest.d.ts.map +1 -0
  294. package/dist/pixi/ingest.js +40 -0
  295. package/dist/pixi/physics-registry.d.ts +24 -0
  296. package/dist/pixi/physics-registry.d.ts.map +1 -0
  297. package/dist/pixi/physics-registry.js +38 -0
  298. package/dist/pixi/scene-capture.d.ts +43 -0
  299. package/dist/pixi/scene-capture.d.ts.map +1 -0
  300. package/dist/pixi/scene-capture.js +92 -0
  301. package/dist/pixi/system-adapters.d.ts +16 -0
  302. package/dist/pixi/system-adapters.d.ts.map +1 -0
  303. package/dist/pixi/system-adapters.js +37 -0
  304. package/dist/react/unmanaged-root-detector.d.ts +18 -0
  305. package/dist/react/unmanaged-root-detector.d.ts.map +1 -0
  306. package/dist/react/unmanaged-root-detector.js +70 -0
  307. package/dist/react/use-data.d.ts +60 -0
  308. package/dist/react/use-data.d.ts.map +1 -0
  309. package/dist/react/use-data.js +101 -0
  310. package/dist/react/use-selection.d.ts +54 -0
  311. package/dist/react/use-selection.d.ts.map +1 -0
  312. package/dist/react/use-selection.js +71 -0
  313. package/dist/react/world-state.d.ts +154 -0
  314. package/dist/react/world-state.d.ts.map +1 -0
  315. package/dist/react/world-state.js +220 -0
  316. package/dist/render/auto-batcher.d.ts +34 -0
  317. package/dist/render/auto-batcher.d.ts.map +1 -0
  318. package/dist/render/auto-batcher.js +140 -0
  319. package/dist/render/instance-mesh.d.ts +5 -0
  320. package/dist/render/instance-mesh.d.ts.map +1 -0
  321. package/dist/render/instance-mesh.js +19 -0
  322. package/dist/render/light-camera-factory.d.ts +24 -0
  323. package/dist/render/light-camera-factory.d.ts.map +1 -0
  324. package/dist/render/light-camera-factory.js +71 -0
  325. package/dist/render/lod.d.ts +13 -0
  326. package/dist/render/lod.d.ts.map +1 -0
  327. package/dist/render/lod.js +16 -0
  328. package/dist/render/material-factory.d.ts +15 -0
  329. package/dist/render/material-factory.d.ts.map +1 -0
  330. package/dist/render/material-factory.js +186 -0
  331. package/dist/render/mesh-shadow.d.ts +11 -0
  332. package/dist/render/mesh-shadow.d.ts.map +1 -0
  333. package/dist/render/mesh-shadow.js +19 -0
  334. package/dist/render/particles-factory.d.ts +99 -0
  335. package/dist/render/particles-factory.d.ts.map +1 -0
  336. package/dist/render/particles-factory.js +361 -0
  337. package/dist/render/render-batch-system.d.ts +33 -0
  338. package/dist/render/render-batch-system.d.ts.map +1 -0
  339. package/dist/render/render-batch-system.js +223 -0
  340. package/dist/render/render-features.d.ts +47 -0
  341. package/dist/render/render-features.d.ts.map +1 -0
  342. package/dist/render/render-features.js +105 -0
  343. package/dist/render/render-settings.d.ts +35 -0
  344. package/dist/render/render-settings.d.ts.map +1 -0
  345. package/dist/render/render-settings.js +51 -0
  346. package/dist/render/spark-renderer-lifecycle.d.ts +18 -0
  347. package/dist/render/spark-renderer-lifecycle.d.ts.map +1 -0
  348. package/dist/render/spark-renderer-lifecycle.js +57 -0
  349. package/dist/render/viewport-shading.d.ts +17 -0
  350. package/dist/render/viewport-shading.d.ts.map +1 -0
  351. package/dist/render/viewport-shading.js +87 -0
  352. package/dist/runtime/create-runtime.d.ts +259 -0
  353. package/dist/runtime/create-runtime.d.ts.map +1 -0
  354. package/dist/runtime/create-runtime.js +666 -0
  355. package/dist/runtime/debug-bridge.d.ts +288 -0
  356. package/dist/runtime/debug-bridge.d.ts.map +1 -0
  357. package/dist/runtime/debug-bridge.js +277 -0
  358. package/dist/runtime/debug-registry.d.ts +287 -0
  359. package/dist/runtime/debug-registry.d.ts.map +1 -0
  360. package/dist/runtime/debug-registry.js +528 -0
  361. package/dist/runtime/dev-layers.d.ts +34 -0
  362. package/dist/runtime/dev-layers.d.ts.map +1 -0
  363. package/dist/runtime/dev-layers.js +40 -0
  364. package/dist/runtime/frame-selector-cache.d.ts +41 -0
  365. package/dist/runtime/frame-selector-cache.d.ts.map +1 -0
  366. package/dist/runtime/frame-selector-cache.js +65 -0
  367. package/dist/runtime/game.d.ts +576 -0
  368. package/dist/runtime/game.d.ts.map +1 -0
  369. package/dist/runtime/game.js +1003 -0
  370. package/dist/runtime/gameplay-rng-trap.d.ts +47 -0
  371. package/dist/runtime/gameplay-rng-trap.d.ts.map +1 -0
  372. package/dist/runtime/gameplay-rng-trap.js +95 -0
  373. package/dist/runtime/input-router.d.ts +78 -0
  374. package/dist/runtime/input-router.d.ts.map +1 -0
  375. package/dist/runtime/input-router.js +171 -0
  376. package/dist/runtime/mount-game.d.ts +126 -0
  377. package/dist/runtime/mount-game.d.ts.map +1 -0
  378. package/dist/runtime/mount-game.js +159 -0
  379. package/dist/runtime/mount-manifest.d.ts +174 -0
  380. package/dist/runtime/mount-manifest.d.ts.map +1 -0
  381. package/dist/runtime/mount-manifest.js +304 -0
  382. package/dist/runtime/presentation.d.ts +85 -0
  383. package/dist/runtime/presentation.d.ts.map +1 -0
  384. package/dist/runtime/presentation.js +92 -0
  385. package/dist/runtime/render-audio-control.d.ts +126 -0
  386. package/dist/runtime/render-audio-control.d.ts.map +1 -0
  387. package/dist/runtime/render-audio-control.js +116 -0
  388. package/dist/runtime/render-control.d.ts +347 -0
  389. package/dist/runtime/render-control.d.ts.map +1 -0
  390. package/dist/runtime/render-control.js +317 -0
  391. package/dist/runtime/render-seed.d.ts +56 -0
  392. package/dist/runtime/render-seed.d.ts.map +1 -0
  393. package/dist/runtime/render-seed.js +73 -0
  394. package/dist/runtime/state-bridge.d.ts +60 -0
  395. package/dist/runtime/state-bridge.d.ts.map +1 -0
  396. package/dist/runtime/state-bridge.js +62 -0
  397. package/dist/runtime/types.d.ts +285 -0
  398. package/dist/runtime/types.d.ts.map +1 -0
  399. package/dist/runtime/types.js +1 -0
  400. package/dist/runtime/unexported-game-trap.d.ts +36 -0
  401. package/dist/runtime/unexported-game-trap.d.ts.map +1 -0
  402. package/dist/runtime/unexported-game-trap.js +80 -0
  403. package/dist/setup/setup-audio.d.ts +20 -0
  404. package/dist/setup/setup-audio.d.ts.map +1 -0
  405. package/dist/setup/setup-audio.js +41 -0
  406. package/dist/setup/setup-particles.d.ts +17 -0
  407. package/dist/setup/setup-particles.d.ts.map +1 -0
  408. package/dist/setup/setup-particles.js +16 -0
  409. package/dist/setup/setup-physics.d.ts +25 -0
  410. package/dist/setup/setup-physics.d.ts.map +1 -0
  411. package/dist/setup/setup-physics.js +51 -0
  412. package/dist/setup/setup-renderer.d.ts +82 -0
  413. package/dist/setup/setup-renderer.d.ts.map +1 -0
  414. package/dist/setup/setup-renderer.js +381 -0
  415. package/dist/world3d-react/engine-bridge.d.ts +47 -0
  416. package/dist/world3d-react/engine-bridge.d.ts.map +1 -0
  417. package/dist/world3d-react/engine-bridge.js +48 -0
  418. package/dist/world3d-react/index.d.ts +47 -0
  419. package/dist/world3d-react/index.d.ts.map +1 -0
  420. package/dist/world3d-react/index.js +46 -0
  421. package/dist/world3d-react/r3f-adapter.d.ts +51 -0
  422. package/dist/world3d-react/r3f-adapter.d.ts.map +1 -0
  423. package/dist/world3d-react/r3f-adapter.js +368 -0
  424. package/dist/world3d-react/r3f-root-factory.d.ts +62 -0
  425. package/dist/world3d-react/r3f-root-factory.d.ts.map +1 -0
  426. package/dist/world3d-react/r3f-root-factory.js +79 -0
  427. package/dist/world3d-react/rapier-physics-bridge.d.ts +76 -0
  428. package/dist/world3d-react/rapier-physics-bridge.d.ts.map +1 -0
  429. package/dist/world3d-react/rapier-physics-bridge.js +120 -0
  430. package/dist/world3d-react/renderer-config.d.ts +58 -0
  431. package/dist/world3d-react/renderer-config.d.ts.map +1 -0
  432. package/dist/world3d-react/renderer-config.js +96 -0
  433. package/dist/world3d-react/world-context.d.ts +123 -0
  434. package/dist/world3d-react/world-context.d.ts.map +1 -0
  435. package/dist/world3d-react/world-context.js +204 -0
  436. package/dist-config/config.js +303 -0
  437. package/dist-config/config.js.map +7 -0
  438. package/package.json +14 -3
  439. package/src/adapter/rapier-physics-adapter.ts +77 -34
  440. package/src/config.ts +8 -0
  441. package/src/core/frame-pacing.ts +26 -0
  442. package/src/core/game-loop.ts +4 -3
  443. package/src/dev/instruments.ts +302 -0
  444. package/src/runtime/mount-game.ts +6 -0
  445. package/src/runtime/unexported-game-trap.ts +82 -0
  446. package/src/setup/setup-renderer.ts +2 -0
  447. package/src/world3d-react/index.ts +9 -0
  448. package/src/world3d-react/rapier-physics-bridge.tsx +137 -0
@@ -0,0 +1,134 @@
1
+ /**
2
+ * First-party WebGL2 single-frame draw-call capture (W4b, F11 frame debugger).
3
+ *
4
+ * WHY FIRST-PARTY, NOT spectorjs (recorded per the "use libraries directly, no
5
+ * wrappers" rule): the capture seam we need is the WebGL2 context this engine
6
+ * ALREADY owns end-to-end (`renderer.getContext()` in
7
+ * `setup-three-root-adapter.ts`). spectorjs is absent from node_modules, and its
8
+ * actual value is a bundled inspector UI we would discard — adopting it imports
9
+ * ~2MB of library to keep ~10% of it, and it wraps the context with its own
10
+ * global patching model rather than the instance-shadow-and-restore discipline
11
+ * the rest of dev/ uses (see `webgl-gpu-timer.ts`, the raw-context precedent
12
+ * this mirrors: instance shadowing, restore-in-finally, mock-GL unit test). So
13
+ * we instrument the real context directly, at the one seam we control.
14
+ *
15
+ * DISCIPLINE (mirrors webgl-gpu-timer.ts):
16
+ * - Patching happens ONLY inside `beginPass()` and ONLY while `armed`. Every
17
+ * patch is an OWN-property shadow on the context instance; the WebGL2
18
+ * prototype is NEVER touched. `endPass()` restores every original in a
19
+ * `finally` (own props reassigned, prototype-inherited methods `delete`d so
20
+ * the real method shows through again), so a throwing draw cannot leave the
21
+ * context wrapped.
22
+ * - HONESTY (adapters never fabricate): a value we cannot measure at this seam
23
+ * is recorded as `null` with the reason implied by the field, never zeroed
24
+ * or guessed. Program/framebuffer LABELS are capture-local identity tags
25
+ * (`program#N`), not the object's real GL debug name (raw WebGL2 exposes
26
+ * none). Framebuffer dimensions are only reported when cheaply knowable
27
+ * (renderbuffer color attachment); a texture-attachment FBO's size is not
28
+ * queryable in raw WebGL2, so it is `null`, not invented (see below —
29
+ * a documented deviation from the plan's non-nullable width/height).
30
+ * - Draw attribution is a single pending-annotation slot consumed by the NEXT
31
+ * draw and then cleared: a second draw with no fresh annotation records
32
+ * `annotation: null` (counted as unattributed), never the previous draw's.
33
+ */
34
+ /** The five WebGL2 draw entry points this instrument wraps. */
35
+ export type FrameCaptureEntryPoint = 'drawArrays' | 'drawElements' | 'drawArraysInstanced' | 'drawElementsInstanced' | 'drawRangeElements';
36
+ /** Per-draw attribution supplied by {@link WebGLFrameCapture.annotateNextDraw}
37
+ * (the render adapter derives it from the three.js object about to draw). */
38
+ export interface DrawAnnotation {
39
+ object: {
40
+ name: string;
41
+ type: string;
42
+ entityId?: string;
43
+ };
44
+ geometry: {
45
+ type: string;
46
+ name: string;
47
+ attributes: string[];
48
+ indexed: boolean;
49
+ };
50
+ material: {
51
+ type: string;
52
+ name: string;
53
+ };
54
+ }
55
+ /** Where a draw rendered: the default framebuffer (canvas) or a bound FBO. */
56
+ export type DrawTarget = {
57
+ kind: 'canvas';
58
+ } | {
59
+ kind: 'framebuffer';
60
+ /** Color-attachment width, or `null` when not cheaply queryable
61
+ * (texture attachment — raw WebGL2 has no size query). */
62
+ width: number | null;
63
+ height: number | null;
64
+ /** Capture-local identity tag (`framebuffer#N`), not a GL debug name. */
65
+ label: string | null;
66
+ };
67
+ export interface FrameCaptureDrawCall {
68
+ readonly index: number;
69
+ readonly entryPoint: FrameCaptureEntryPoint;
70
+ /** Decoded primitive mode, e.g. `'TRIANGLES'`, `'LINES'` (raw enum when
71
+ * unrecognised). */
72
+ readonly mode: string;
73
+ /** Vertex/index count passed to the draw. */
74
+ readonly count: number;
75
+ /** Instance count for the instanced entry points, else `null` (not 0 —
76
+ * a non-instanced draw has no instance count to report). */
77
+ readonly instanceCount: number | null;
78
+ /** Capture-local program identity (`program#N`), or `null` when no program
79
+ * was bound via `useProgram`. */
80
+ readonly programLabel: string | null;
81
+ readonly target: DrawTarget;
82
+ /** Shadow-tracked viewport `[x, y, w, h]` at draw time. */
83
+ readonly viewport: readonly [number, number, number, number];
84
+ readonly state: {
85
+ readonly blend: boolean;
86
+ readonly depthTest: boolean;
87
+ readonly depthWrite: boolean;
88
+ readonly cull: 'front' | 'back' | 'none';
89
+ readonly scissor: boolean;
90
+ };
91
+ /** The annotation this draw consumed, or `null` when none was pending
92
+ * (unattributed — e.g. a shadow/composer pass draw). */
93
+ readonly annotation: DrawAnnotation | null;
94
+ }
95
+ export interface FrameCapture {
96
+ readonly id: number;
97
+ /** Injected capture timestamp (ms) — see `createWebGLFrameCapture` options. */
98
+ readonly capturedAt: number;
99
+ readonly drawCalls: readonly FrameCaptureDrawCall[];
100
+ readonly totals: {
101
+ /** Draws RECORDED (excludes any dropped past the cap). */
102
+ readonly drawCalls: number;
103
+ /** Recorded draws with `annotation: null`. */
104
+ readonly unattributed: number;
105
+ /** Draws dropped because the cap was hit (0 when nothing was dropped). */
106
+ readonly truncated: number;
107
+ };
108
+ readonly notes: readonly string[];
109
+ }
110
+ export interface WebGLFrameCaptureOptions {
111
+ /** Injected clock for `capturedAt`; defaults to `Date.now`. Injectable so a
112
+ * test gets deterministic timestamps (mirrors the profiler stamping time
113
+ * through a single `now()` indirection rather than a module-level call). */
114
+ now?: () => number;
115
+ /** Hard cap on recorded draws (default 5000). Draws past it are dropped and
116
+ * counted in `totals.truncated`, with a note. */
117
+ maxDrawCalls?: number;
118
+ }
119
+ export interface WebGLFrameCapture {
120
+ /** Arm a single capture; the NEXT `beginPass()` patches the context. */
121
+ arm(): void;
122
+ readonly armed: boolean;
123
+ /** If armed, shadow-patch the context. No-op otherwise (zero patching when
124
+ * not armed). Must be paired with `endPass()`. */
125
+ beginPass(): void;
126
+ /** Restore all patches (in `finally`) and, if a pass was patched, return the
127
+ * assembled {@link FrameCapture}. Returns `null` if `beginPass` did not
128
+ * patch (was not armed). One-shot: disarms after. */
129
+ endPass(): FrameCapture | null;
130
+ /** Set the annotation the next draw will consume (then cleared). */
131
+ annotateNextDraw(annotation: DrawAnnotation): void;
132
+ }
133
+ export declare function createWebGLFrameCapture(gl: WebGL2RenderingContext, options?: WebGLFrameCaptureOptions): WebGLFrameCapture;
134
+ //# sourceMappingURL=webgl-frame-capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webgl-frame-capture.d.ts","sourceRoot":"","sources":["../../src/dev/webgl-frame-capture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,270 @@
1
+ /**
2
+ * First-party WebGL2 single-frame draw-call capture (W4b, F11 frame debugger).
3
+ *
4
+ * WHY FIRST-PARTY, NOT spectorjs (recorded per the "use libraries directly, no
5
+ * wrappers" rule): the capture seam we need is the WebGL2 context this engine
6
+ * ALREADY owns end-to-end (`renderer.getContext()` in
7
+ * `setup-three-root-adapter.ts`). spectorjs is absent from node_modules, and its
8
+ * actual value is a bundled inspector UI we would discard — adopting it imports
9
+ * ~2MB of library to keep ~10% of it, and it wraps the context with its own
10
+ * global patching model rather than the instance-shadow-and-restore discipline
11
+ * the rest of dev/ uses (see `webgl-gpu-timer.ts`, the raw-context precedent
12
+ * this mirrors: instance shadowing, restore-in-finally, mock-GL unit test). So
13
+ * we instrument the real context directly, at the one seam we control.
14
+ *
15
+ * DISCIPLINE (mirrors webgl-gpu-timer.ts):
16
+ * - Patching happens ONLY inside `beginPass()` and ONLY while `armed`. Every
17
+ * patch is an OWN-property shadow on the context instance; the WebGL2
18
+ * prototype is NEVER touched. `endPass()` restores every original in a
19
+ * `finally` (own props reassigned, prototype-inherited methods `delete`d so
20
+ * the real method shows through again), so a throwing draw cannot leave the
21
+ * context wrapped.
22
+ * - HONESTY (adapters never fabricate): a value we cannot measure at this seam
23
+ * is recorded as `null` with the reason implied by the field, never zeroed
24
+ * or guessed. Program/framebuffer LABELS are capture-local identity tags
25
+ * (`program#N`), not the object's real GL debug name (raw WebGL2 exposes
26
+ * none). Framebuffer dimensions are only reported when cheaply knowable
27
+ * (renderbuffer color attachment); a texture-attachment FBO's size is not
28
+ * queryable in raw WebGL2, so it is `null`, not invented (see below —
29
+ * a documented deviation from the plan's non-nullable width/height).
30
+ * - Draw attribution is a single pending-annotation slot consumed by the NEXT
31
+ * draw and then cleared: a second draw with no fresh annotation records
32
+ * `annotation: null` (counted as unattributed), never the previous draw's.
33
+ */
34
+ const DEFAULT_MAX_DRAW_CALLS = 5000;
35
+ /** GL primitive-mode enum → name (decoded once, from the live context). */
36
+ function buildModeTable(gl) {
37
+ return new Map([
38
+ [gl.POINTS, 'POINTS'],
39
+ [gl.LINES, 'LINES'],
40
+ [gl.LINE_LOOP, 'LINE_LOOP'],
41
+ [gl.LINE_STRIP, 'LINE_STRIP'],
42
+ [gl.TRIANGLES, 'TRIANGLES'],
43
+ [gl.TRIANGLE_STRIP, 'TRIANGLE_STRIP'],
44
+ [gl.TRIANGLE_FAN, 'TRIANGLE_FAN'],
45
+ ]);
46
+ }
47
+ export function createWebGLFrameCapture(gl, options = {}) {
48
+ const nowFn = options.now ?? (() => Date.now());
49
+ const maxDrawCalls = options.maxDrawCalls ?? DEFAULT_MAX_DRAW_CALLS;
50
+ const modeTable = buildModeTable(gl);
51
+ // Persistent identity maps (stable labels across passes).
52
+ const programLabels = new Map();
53
+ const framebufferLabels = new Map();
54
+ let nextProgramId = 0;
55
+ let nextFramebufferId = 0;
56
+ let captureId = 0;
57
+ // Shadow-tracked GL state (updated by the wrapped setters during a pass).
58
+ let currentProgram = null;
59
+ let currentFramebuffer = null;
60
+ let currentViewport = [0, 0, 0, 0];
61
+ // Per-pass accumulators.
62
+ let armed = false;
63
+ let patched = false;
64
+ let drawCalls = [];
65
+ let truncated = 0;
66
+ let notes = [];
67
+ let pendingAnnotation = null;
68
+ // Saved originals for restore. Value is the original fn; a key present in
69
+ // `wasOwn` means it was an own property (restore by assignment), otherwise
70
+ // it was prototype-inherited (restore by delete).
71
+ const originals = new Map();
72
+ const wasOwn = new Set();
73
+ function decodeMode(mode) {
74
+ return modeTable.get(mode) ?? `0x${mode.toString(16)}`;
75
+ }
76
+ function labelForProgram(program) {
77
+ if (!program)
78
+ return null;
79
+ let label = programLabels.get(program);
80
+ if (label === undefined) {
81
+ label = `program#${nextProgramId++}`;
82
+ programLabels.set(program, label);
83
+ }
84
+ return label;
85
+ }
86
+ /** Best-effort color-attachment dimensions for a bound draw FBO. Only a
87
+ * RENDERBUFFER color attachment is cheaply queryable in raw WebGL2; a
88
+ * texture attachment is not, so this returns nulls (honest absence). All
89
+ * reads are guarded — a mock/foreign context returns nulls, never throws. */
90
+ function measureFramebufferSize() {
91
+ try {
92
+ const type = gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE);
93
+ if (type === gl.RENDERBUFFER) {
94
+ const rb = gl.getFramebufferAttachmentParameter(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
95
+ if (!rb)
96
+ return { width: null, height: null };
97
+ const prev = gl.getParameter(gl.RENDERBUFFER_BINDING);
98
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
99
+ const width = gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH);
100
+ const height = gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT);
101
+ gl.bindRenderbuffer(gl.RENDERBUFFER, prev);
102
+ return { width, height };
103
+ }
104
+ }
105
+ catch {
106
+ // Foreign/mock context or an attachment we can't introspect — degrade
107
+ // to unknown dimensions rather than throwing mid-capture.
108
+ }
109
+ return { width: null, height: null };
110
+ }
111
+ function currentTarget() {
112
+ if (!currentFramebuffer)
113
+ return { kind: 'canvas' };
114
+ let label = framebufferLabels.get(currentFramebuffer);
115
+ if (label === undefined) {
116
+ label = `framebuffer#${nextFramebufferId++}`;
117
+ framebufferLabels.set(currentFramebuffer, label);
118
+ }
119
+ const { width, height } = measureFramebufferSize();
120
+ return { kind: 'framebuffer', width, height, label };
121
+ }
122
+ function readCull() {
123
+ if (!gl.getParameter(gl.CULL_FACE))
124
+ return 'none';
125
+ return gl.getParameter(gl.CULL_FACE_MODE) === gl.FRONT ? 'front' : 'back';
126
+ }
127
+ function recordDraw(entryPoint, mode, count, instanceCount) {
128
+ if (drawCalls.length >= maxDrawCalls) {
129
+ truncated++;
130
+ pendingAnnotation = null;
131
+ return;
132
+ }
133
+ const annotation = pendingAnnotation;
134
+ pendingAnnotation = null;
135
+ drawCalls.push({
136
+ index: drawCalls.length,
137
+ entryPoint,
138
+ mode: decodeMode(mode),
139
+ count,
140
+ instanceCount,
141
+ programLabel: labelForProgram(currentProgram),
142
+ target: currentTarget(),
143
+ viewport: [...currentViewport],
144
+ state: {
145
+ blend: Boolean(gl.getParameter(gl.BLEND)),
146
+ depthTest: Boolean(gl.getParameter(gl.DEPTH_TEST)),
147
+ depthWrite: Boolean(gl.getParameter(gl.DEPTH_WRITEMASK)),
148
+ cull: readCull(),
149
+ scissor: Boolean(gl.getParameter(gl.SCISSOR_TEST)),
150
+ },
151
+ annotation: annotation ?? null,
152
+ });
153
+ }
154
+ // Cast to an index signature to shadow methods without fighting the DOM lib
155
+ // types on every wrapped name.
156
+ const target = gl;
157
+ function patch(name, wrapper) {
158
+ const original = target[name];
159
+ originals.set(name, original);
160
+ if (Object.hasOwn(gl, name))
161
+ wasOwn.add(name);
162
+ target[name] = wrapper(original.bind(gl));
163
+ }
164
+ function restoreAll() {
165
+ for (const [name, original] of originals) {
166
+ if (wasOwn.has(name))
167
+ target[name] = original;
168
+ else
169
+ delete target[name];
170
+ }
171
+ originals.clear();
172
+ wasOwn.clear();
173
+ }
174
+ function installPatches() {
175
+ // Seed shadow state from the live context so the first draw's viewport /
176
+ // framebuffer / program reflect reality even before any setter fires.
177
+ try {
178
+ const vp = gl.getParameter(gl.VIEWPORT);
179
+ if (vp && vp.length >= 4)
180
+ currentViewport = [vp[0], vp[1], vp[2], vp[3]];
181
+ currentFramebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING);
182
+ currentProgram = gl.getParameter(gl.CURRENT_PROGRAM);
183
+ }
184
+ catch {
185
+ // Mock context without full getParameter coverage — start from defaults.
186
+ }
187
+ patch('useProgram', (original) => (program) => {
188
+ currentProgram = program ?? null;
189
+ return original(program);
190
+ });
191
+ patch('bindFramebuffer', (original) => (bindTarget, framebuffer) => {
192
+ // Track the DRAW framebuffer binding (FRAMEBUFFER and DRAW_FRAMEBUFFER
193
+ // both affect it; READ_FRAMEBUFFER does not).
194
+ if (bindTarget === gl.FRAMEBUFFER || bindTarget === gl.DRAW_FRAMEBUFFER) {
195
+ currentFramebuffer = framebuffer ?? null;
196
+ }
197
+ return original(bindTarget, framebuffer);
198
+ });
199
+ patch('viewport', (original) => (x, y, w, h) => {
200
+ currentViewport = [x, y, w, h];
201
+ return original(x, y, w, h);
202
+ });
203
+ patch('drawArrays', (original) => (mode, first, count) => {
204
+ recordDraw('drawArrays', mode, count, null);
205
+ return original(mode, first, count);
206
+ });
207
+ patch('drawElements', (original) => (mode, count, type, offset) => {
208
+ recordDraw('drawElements', mode, count, null);
209
+ return original(mode, count, type, offset);
210
+ });
211
+ patch('drawArraysInstanced', (original) => (mode, first, count, instanceCount) => {
212
+ recordDraw('drawArraysInstanced', mode, count, instanceCount);
213
+ return original(mode, first, count, instanceCount);
214
+ });
215
+ patch('drawElementsInstanced', (original) => (mode, count, type, offset, instanceCount) => {
216
+ recordDraw('drawElementsInstanced', mode, count, instanceCount);
217
+ return original(mode, count, type, offset, instanceCount);
218
+ });
219
+ patch('drawRangeElements', (original) => (mode, start, end, count, type, offset) => {
220
+ recordDraw('drawRangeElements', mode, count, null);
221
+ return original(mode, start, end, count, type, offset);
222
+ });
223
+ }
224
+ return {
225
+ arm() {
226
+ armed = true;
227
+ },
228
+ get armed() {
229
+ return armed;
230
+ },
231
+ beginPass() {
232
+ if (!armed || patched)
233
+ return;
234
+ patched = true;
235
+ drawCalls = [];
236
+ truncated = 0;
237
+ notes = [];
238
+ pendingAnnotation = null;
239
+ installPatches();
240
+ },
241
+ endPass() {
242
+ if (!patched) {
243
+ armed = false;
244
+ return null;
245
+ }
246
+ try {
247
+ if (truncated > 0) {
248
+ notes.push(`Draw list capped at ${maxDrawCalls}; ${truncated} later draw(s) were not recorded.`);
249
+ }
250
+ const unattributed = drawCalls.reduce((n, d) => n + (d.annotation === null ? 1 : 0), 0);
251
+ return {
252
+ id: ++captureId,
253
+ capturedAt: nowFn(),
254
+ drawCalls: drawCalls.slice(),
255
+ totals: { drawCalls: drawCalls.length, unattributed, truncated },
256
+ notes: notes.slice(),
257
+ };
258
+ }
259
+ finally {
260
+ restoreAll();
261
+ patched = false;
262
+ armed = false;
263
+ pendingAnnotation = null;
264
+ }
265
+ },
266
+ annotateNextDraw(annotation) {
267
+ pendingAnnotation = annotation;
268
+ },
269
+ };
270
+ }
@@ -0,0 +1,8 @@
1
+ /** Non-blocking WebGL2 timer query; results are consumed on later frames. */
2
+ export declare function createWebGLGpuTimer(context: WebGLRenderingContext | WebGL2RenderingContext): {
3
+ begin(): void;
4
+ end(): void;
5
+ poll(): number | null;
6
+ dispose(): void;
7
+ };
8
+ //# sourceMappingURL=webgl-gpu-timer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webgl-gpu-timer.d.ts","sourceRoot":"","sources":["../../src/dev/webgl-gpu-timer.ts"],"names":[],"mappings":"AAKA,6EAA6E;AAC7E,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,qBAAqB,GAAG,sBAAsB;;;YAsB/E,MAAM,GAAG,IAAI;;EAwBxB"}
@@ -0,0 +1,52 @@
1
+ /** Non-blocking WebGL2 timer query; results are consumed on later frames. */
2
+ export function createWebGLGpuTimer(context) {
3
+ const gl = context;
4
+ const extension = gl.getExtension('EXT_disjoint_timer_query_webgl2');
5
+ const supported = extension !== null && typeof gl.createQuery === 'function';
6
+ const pending = [];
7
+ let active = null;
8
+ let latestMs = null;
9
+ return {
10
+ begin() {
11
+ if (!supported || active)
12
+ return;
13
+ active = gl.createQuery();
14
+ if (active)
15
+ gl.beginQuery(extension.TIME_ELAPSED_EXT, active);
16
+ },
17
+ end() {
18
+ if (!supported || !active)
19
+ return;
20
+ gl.endQuery(extension.TIME_ELAPSED_EXT);
21
+ pending.push(active);
22
+ active = null;
23
+ },
24
+ poll() {
25
+ if (!supported)
26
+ return null;
27
+ if (gl.getParameter(extension.GPU_DISJOINT_EXT)) {
28
+ for (const query of pending.splice(0))
29
+ gl.deleteQuery(query);
30
+ return null;
31
+ }
32
+ while (pending.length > 0) {
33
+ const query = pending[0];
34
+ if (!gl.getQueryParameter(query, gl.QUERY_RESULT_AVAILABLE))
35
+ break;
36
+ pending.shift();
37
+ latestMs = gl.getQueryParameter(query, gl.QUERY_RESULT) / 1_000_000;
38
+ gl.deleteQuery(query);
39
+ }
40
+ return latestMs;
41
+ },
42
+ dispose() {
43
+ if (active) {
44
+ gl.endQuery(extension.TIME_ELAPSED_EXT);
45
+ gl.deleteQuery(active);
46
+ active = null;
47
+ }
48
+ for (const query of pending.splice(0))
49
+ gl.deleteQuery(query);
50
+ },
51
+ };
52
+ }
@@ -0,0 +1,179 @@
1
+ /**
2
+ * `createSceneIndex` — the LIVE scene index (punchlist P2, `observe`).
3
+ *
4
+ * `scene-query.ts` answers "which objects carry tag X?" by walking the whole
5
+ * graph on every call, and it tells nobody when the answer changes. This
6
+ * module is the notified half: a tag/entity-id index kept current as objects
7
+ * join and leave the scene, plus the change signals a game needs so it never
8
+ * has to poll.
9
+ *
10
+ * ## The one event primitive is `EventTarget`
11
+ *
12
+ * There is no bus, no emitter class, no `subscribe()` returning a closure.
13
+ * `index.events` is a plain `EventTarget` dispatching `CustomEvent`s, and
14
+ * **unsubscribe is `AbortSignal`** — the platform's own answer:
15
+ *
16
+ * ```ts
17
+ * const ac = new AbortController();
18
+ * ctx.sceneIndex.events.addEventListener(
19
+ * 'tagadded',
20
+ * (e) => console.log((e as SceneIndexEvent<'tagadded'>).detail.object.name),
21
+ * { signal: ac.signal },
22
+ * );
23
+ * ac.abort(); // done — nothing to remember, nothing to leak
24
+ * ```
25
+ *
26
+ * {@link onSceneIndexEvent} is the same call with the detail typed for you.
27
+ * `index.eventsFor(obj)` is the per-object target (Roblox's `inst.Changed`):
28
+ * the same events, already filtered to one object, so a listener that only
29
+ * cares about one entity does not filter by hand.
30
+ *
31
+ * ## How the index stays live: three's own parent events, not a monkeypatch
32
+ *
33
+ * three r155+ dispatches `childadded`/`childremoved` on the **parent** from
34
+ * `Object3D.add`/`remove` (and therefore from `attach`, `clear`,
35
+ * `removeFromParent`, and R3F's reconciler, which all go through those two).
36
+ * The index subscribes to those two events on every object it indexes; on
37
+ * `childadded` it walks the new subtree, indexes it, and subscribes each
38
+ * node, and on `childremoved` it does the inverse. `Object3D.prototype` is
39
+ * NOT patched — nothing in this repo patches a library prototype.
40
+ *
41
+ * Consequences worth knowing:
42
+ *
43
+ * - **The quiet-frame cost is zero.** The index registers no system and runs
44
+ * no per-frame reconcile; it does work only when three tells it something
45
+ * moved. Nothing here ticks.
46
+ * - **Reparenting nets out to one entry.** `parent.add(obj)` removes `obj`
47
+ * from its old parent first, so a move inside the indexed tree fires
48
+ * `childremoved` then `childadded` — unindex, then index. The object ends
49
+ * up indexed exactly once (and a listener sees an `entityremoved` followed
50
+ * by an `entityadded`, which is the truth about what happened).
51
+ * - **Splicing `parent.children` by hand is invisible to the index**, because
52
+ * it is invisible to three as well. Use `add`/`remove`.
53
+ *
54
+ * ## Tags are stored where they always were
55
+ *
56
+ * `addTag`/`removeTag` write the existing `userData['tags']` array, so
57
+ * `queryByTag` keeps returning the truth and nothing has to be migrated. The
58
+ * index is the fast, notified path over the same storage. A game that writes
59
+ * `userData['tags']` by hand gets a stale index — that is not prevented, it is
60
+ * repaired: call {@link SceneIndex.reindex} on the object.
61
+ *
62
+ * ## Attributes
63
+ *
64
+ * `getAttribute`/`setAttribute`/`deleteAttribute` are typed accessors over ONE
65
+ * new reserved userData key, `attributes` (registered in `ecs/user-data.ts`,
66
+ * `Record<string, string | number | boolean>`). They emit `attributechanged`
67
+ * only when the value actually changes, so a re-set of the same value is
68
+ * silent.
69
+ *
70
+ * ## What this deliberately does NOT do
71
+ *
72
+ * - **No property-level `Changed` on transforms.** three does not notify on
73
+ * `position.set(...)`; faking it means diffing every transform every frame,
74
+ * and a signal that is really a per-frame poll is worse than no signal —
75
+ * it hides its own cost. Read the transform when you need it, or drive the
76
+ * change from the code that made it.
77
+ * - **No `Touched`.** Contact/trigger events are Rapier's, dispatched through
78
+ * `ctx.collisions.onCollision`. A second path would be a second truth.
79
+ * - **No 2D index.** This module indexes a three graph only.
80
+ */
81
+ import type * as THREE from 'three';
82
+ /** The value types an attribute may hold — deliberately JSON-simple, so an
83
+ * attribute survives serialization and network replication unchanged. */
84
+ export type AttributeValue = string | number | boolean;
85
+ /** The `detail` payload of every scene-index event, keyed by event type.
86
+ * Every detail carries `object`, so a scene-wide listener filters without a
87
+ * second lookup. */
88
+ export interface SceneIndexEventDetails {
89
+ /** An object (and, one event each, its descendants) joined the indexed tree. */
90
+ entityadded: {
91
+ object: THREE.Object3D;
92
+ };
93
+ /** An object (and, one event each, its descendants) left the indexed tree. */
94
+ entityremoved: {
95
+ object: THREE.Object3D;
96
+ };
97
+ /** A tag was added via {@link SceneIndex.addTag}. */
98
+ tagadded: {
99
+ object: THREE.Object3D;
100
+ tag: string;
101
+ };
102
+ /** A tag was removed via {@link SceneIndex.removeTag}. */
103
+ tagremoved: {
104
+ object: THREE.Object3D;
105
+ tag: string;
106
+ };
107
+ /** An attribute's value changed (`value` is `undefined` after a delete;
108
+ * `previous` is `undefined` when it was previously unset). */
109
+ attributechanged: {
110
+ object: THREE.Object3D;
111
+ name: string;
112
+ value: AttributeValue | undefined;
113
+ previous: AttributeValue | undefined;
114
+ };
115
+ }
116
+ /** Every event type `index.events` / `index.eventsFor(obj)` dispatches. */
117
+ export type SceneIndexEventType = keyof SceneIndexEventDetails;
118
+ /** The `CustomEvent` a given scene-index event type dispatches. */
119
+ export type SceneIndexEvent<K extends SceneIndexEventType = SceneIndexEventType> = CustomEvent<SceneIndexEventDetails[K]>;
120
+ /** Event-type → event, for callers that want a typed `addEventListener` map. */
121
+ export type SceneIndexEventMap = {
122
+ [K in SceneIndexEventType]: SceneIndexEvent<K>;
123
+ };
124
+ /**
125
+ * `addEventListener` with the detail typed — the ONLY convenience over the
126
+ * platform call, and it returns nothing on purpose: unsubscribe stays
127
+ * `AbortSignal` (`{ signal }`), never a returned closure.
128
+ */
129
+ export declare function onSceneIndexEvent<K extends SceneIndexEventType>(target: EventTarget, type: K, listener: (detail: SceneIndexEventDetails[K], event: SceneIndexEvent<K>) => void, options?: {
130
+ signal?: AbortSignal;
131
+ once?: boolean;
132
+ }): void;
133
+ /** The live scene index — see this module's header. */
134
+ export interface SceneIndex {
135
+ /** The scene-wide signal target. Listen with `addEventListener(type, fn,
136
+ * { signal })`, or {@link onSceneIndexEvent} for a typed `detail`. */
137
+ readonly events: EventTarget;
138
+ /** The per-object signal target (Roblox's `inst.Changed`): the same events,
139
+ * filtered to `obj`. Created lazily and held weakly. */
140
+ eventsFor(obj: THREE.Object3D): EventTarget;
141
+ /** Every indexed object carrying `tag`, in index order. Never traverses. */
142
+ byTag(tag: string): readonly THREE.Object3D[];
143
+ /** The indexed object whose `userData['entityId']` is `id` (the first, in
144
+ * index order, if a project has minted the id twice). Never traverses. */
145
+ byEntityId(id: string): THREE.Object3D | undefined;
146
+ /** True when `obj` is currently in the indexed tree. */
147
+ has(obj: THREE.Object3D): boolean;
148
+ /** Add `tag` to `obj`'s `userData['tags']` and the index; emits `tagadded`.
149
+ * A no-op (and silent) when the tag is already present. Legal on an object
150
+ * that has not joined the scene yet — the tag is stored, and the index
151
+ * picks it up when the object is added. */
152
+ addTag(obj: THREE.Object3D, tag: string): void;
153
+ /** Remove `tag`; emits `tagremoved`. A no-op (and silent) when absent. */
154
+ removeTag(obj: THREE.Object3D, tag: string): void;
155
+ /** True when `obj` carries `tag` (reads `userData['tags']`, so it is
156
+ * truthful even for an object that is not in the scene yet). */
157
+ hasTag(obj: THREE.Object3D, tag: string): boolean;
158
+ /** Read one attribute (`undefined` when unset). */
159
+ getAttribute(obj: THREE.Object3D, name: string): AttributeValue | undefined;
160
+ /** Write one attribute; emits `attributechanged` only if the value changed. */
161
+ setAttribute(obj: THREE.Object3D, name: string, value: AttributeValue): void;
162
+ /** Delete one attribute; emits `attributechanged` with `value: undefined`. */
163
+ deleteAttribute(obj: THREE.Object3D, name: string): void;
164
+ /** Re-read `obj`'s subtree from `userData` — the escape hatch for code that
165
+ * wrote `userData['tags']`/`userData['entityId']` by hand. Indexes anything
166
+ * in the subtree that is not indexed yet (emitting `entityadded`) and
167
+ * re-syncs the tag/id entries of everything that is. */
168
+ reindex(obj: THREE.Object3D): void;
169
+ /** Drop every listener this index installed and forget everything it knows.
170
+ * Called from the owning root's teardown; safe to call twice. */
171
+ dispose(): void;
172
+ }
173
+ /**
174
+ * Build a live index over `root` and everything currently under it. One index
175
+ * per three root; the root adapter creates it and exposes it as
176
+ * `ctx.sceneIndex`.
177
+ */
178
+ export declare function createSceneIndex(root: THREE.Object3D): SceneIndex;
179
+ //# sourceMappingURL=scene-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene-index.d.ts","sourceRoot":"","sources":["../../src/ecs/scene-index.ts"],"names":[],"mappings":"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"}