@nodetool-ai/game-renderer 0.8.1 → 0.8.3

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 (277) hide show
  1. package/README.md +46 -0
  2. package/dist/.nodetool-build-stamp +1 -1
  3. package/dist/audio/mixer.d.ts +75 -0
  4. package/dist/audio/mixer.d.ts.map +1 -0
  5. package/dist/audio/mixer.js +345 -0
  6. package/dist/audio/mixer.js.map +1 -0
  7. package/dist/audio/player.d.ts +67 -0
  8. package/dist/audio/player.d.ts.map +1 -0
  9. package/dist/audio/player.js +337 -0
  10. package/dist/audio/player.js.map +1 -0
  11. package/dist/audio/spatial.d.ts +50 -0
  12. package/dist/audio/spatial.d.ts.map +1 -0
  13. package/dist/audio/spatial.js +166 -0
  14. package/dist/audio/spatial.js.map +1 -0
  15. package/dist/audio/voices.d.ts +11 -0
  16. package/dist/audio/voices.d.ts.map +1 -0
  17. package/dist/audio/voices.js +22 -0
  18. package/dist/audio/voices.js.map +1 -0
  19. package/dist/audio.d.ts +6 -38
  20. package/dist/audio.d.ts.map +1 -1
  21. package/dist/audio.js +3 -226
  22. package/dist/audio.js.map +1 -1
  23. package/dist/browser.d.ts +2 -1
  24. package/dist/browser.d.ts.map +1 -1
  25. package/dist/browser.js +5 -5
  26. package/dist/browser.js.map +1 -1
  27. package/dist/browser3d.d.ts +2 -0
  28. package/dist/browser3d.d.ts.map +1 -0
  29. package/dist/browser3d.js +2 -0
  30. package/dist/browser3d.js.map +1 -0
  31. package/dist/build-tauri.d.ts +69 -0
  32. package/dist/build-tauri.d.ts.map +1 -0
  33. package/dist/build-tauri.js +406 -0
  34. package/dist/build-tauri.js.map +1 -0
  35. package/dist/build.d.ts.map +1 -1
  36. package/dist/build.js +29 -19
  37. package/dist/build.js.map +1 -1
  38. package/dist/build3d.d.ts +11 -0
  39. package/dist/build3d.d.ts.map +1 -0
  40. package/dist/build3d.js +126 -0
  41. package/dist/build3d.js.map +1 -0
  42. package/dist/canvas2d.d.ts +12 -3
  43. package/dist/canvas2d.d.ts.map +1 -1
  44. package/dist/canvas2d.js +59 -12
  45. package/dist/canvas2d.js.map +1 -1
  46. package/dist/fixed-tick-host.d.ts +10 -0
  47. package/dist/fixed-tick-host.d.ts.map +1 -0
  48. package/dist/fixed-tick-host.js +29 -0
  49. package/dist/fixed-tick-host.js.map +1 -0
  50. package/dist/frame-budget.d.ts +34 -0
  51. package/dist/frame-budget.d.ts.map +1 -0
  52. package/dist/frame-budget.js +52 -0
  53. package/dist/frame-budget.js.map +1 -0
  54. package/dist/frame.d.ts +20 -1
  55. package/dist/frame.d.ts.map +1 -1
  56. package/dist/frame.js +69 -1
  57. package/dist/frame.js.map +1 -1
  58. package/dist/game3d-capture-page.js +5834 -0
  59. package/dist/game3d-player.js +6001 -0
  60. package/dist/imageDiff.d.ts +9 -0
  61. package/dist/imageDiff.d.ts.map +1 -0
  62. package/dist/imageDiff.js +30 -0
  63. package/dist/imageDiff.js.map +1 -0
  64. package/dist/index.d.ts +12 -1
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +9 -0
  67. package/dist/index.js.map +1 -1
  68. package/dist/input-bindings.d.ts +76 -0
  69. package/dist/input-bindings.d.ts.map +1 -0
  70. package/dist/input-bindings.js +377 -0
  71. package/dist/input-bindings.js.map +1 -0
  72. package/dist/input.d.ts +1 -1
  73. package/dist/input.d.ts.map +1 -1
  74. package/dist/input.js +1 -14
  75. package/dist/input.js.map +1 -1
  76. package/dist/input3d.d.ts +3 -0
  77. package/dist/input3d.d.ts.map +1 -0
  78. package/dist/input3d.js +3 -0
  79. package/dist/input3d.js.map +1 -0
  80. package/dist/node.d.ts +5 -0
  81. package/dist/node.d.ts.map +1 -1
  82. package/dist/node.js +28 -11
  83. package/dist/node.js.map +1 -1
  84. package/dist/node3d.d.ts +29 -0
  85. package/dist/node3d.d.ts.map +1 -0
  86. package/dist/node3d.js +160 -0
  87. package/dist/node3d.js.map +1 -0
  88. package/dist/particles/curves.d.ts +16 -0
  89. package/dist/particles/curves.d.ts.map +1 -0
  90. package/dist/particles/curves.js +49 -0
  91. package/dist/particles/curves.js.map +1 -0
  92. package/dist/particles/index.d.ts +6 -0
  93. package/dist/particles/index.d.ts.map +1 -0
  94. package/dist/particles/index.js +6 -0
  95. package/dist/particles/index.js.map +1 -0
  96. package/dist/particles/random.d.ts +10 -0
  97. package/dist/particles/random.d.ts.map +1 -0
  98. package/dist/particles/random.js +26 -0
  99. package/dist/particles/random.js.map +1 -0
  100. package/dist/particles/render2d.d.ts +40 -0
  101. package/dist/particles/render2d.d.ts.map +1 -0
  102. package/dist/particles/render2d.js +70 -0
  103. package/dist/particles/render2d.js.map +1 -0
  104. package/dist/particles/shapes.d.ts +18 -0
  105. package/dist/particles/shapes.d.ts.map +1 -0
  106. package/dist/particles/shapes.js +92 -0
  107. package/dist/particles/shapes.js.map +1 -0
  108. package/dist/particles/simulator.d.ts +88 -0
  109. package/dist/particles/simulator.d.ts.map +1 -0
  110. package/dist/particles/simulator.js +371 -0
  111. package/dist/particles/simulator.js.map +1 -0
  112. package/dist/player-v1.js +2502 -0
  113. package/dist/preparation3d.d.ts +3 -0
  114. package/dist/preparation3d.d.ts.map +1 -0
  115. package/dist/preparation3d.js +3 -0
  116. package/dist/preparation3d.js.map +1 -0
  117. package/dist/renderPipeline.d.ts +12 -0
  118. package/dist/renderPipeline.d.ts.map +1 -0
  119. package/dist/renderPipeline.js +17 -0
  120. package/dist/renderPipeline.js.map +1 -0
  121. package/dist/renderer3d/animation/index.d.ts +11 -0
  122. package/dist/renderer3d/animation/index.d.ts.map +1 -0
  123. package/dist/renderer3d/animation/index.js +212 -0
  124. package/dist/renderer3d/animation/index.js.map +1 -0
  125. package/dist/renderer3d/assets/cache.d.ts +14 -0
  126. package/dist/renderer3d/assets/cache.d.ts.map +1 -0
  127. package/dist/renderer3d/assets/cache.js +74 -0
  128. package/dist/renderer3d/assets/cache.js.map +1 -0
  129. package/dist/renderer3d/assets/dispose.d.ts +4 -0
  130. package/dist/renderer3d/assets/dispose.d.ts.map +1 -0
  131. package/dist/renderer3d/assets/dispose.js +41 -0
  132. package/dist/renderer3d/assets/dispose.js.map +1 -0
  133. package/dist/renderer3d/assets/hdri-contract.d.ts +23 -0
  134. package/dist/renderer3d/assets/hdri-contract.d.ts.map +1 -0
  135. package/dist/renderer3d/assets/hdri-contract.js +2 -0
  136. package/dist/renderer3d/assets/hdri-contract.js.map +1 -0
  137. package/dist/renderer3d/assets/instances.d.ts +5 -0
  138. package/dist/renderer3d/assets/instances.d.ts.map +1 -0
  139. package/dist/renderer3d/assets/instances.js +86 -0
  140. package/dist/renderer3d/assets/instances.js.map +1 -0
  141. package/dist/renderer3d/capture-driver-types.d.ts +42 -0
  142. package/dist/renderer3d/capture-driver-types.d.ts.map +1 -0
  143. package/dist/renderer3d/capture-driver-types.js +2 -0
  144. package/dist/renderer3d/capture-driver-types.js.map +1 -0
  145. package/dist/renderer3d/capture-page.d.ts +36 -0
  146. package/dist/renderer3d/capture-page.d.ts.map +1 -0
  147. package/dist/renderer3d/capture-page.js +68 -0
  148. package/dist/renderer3d/capture-page.js.map +1 -0
  149. package/dist/renderer3d/culling.d.ts +10 -0
  150. package/dist/renderer3d/culling.d.ts.map +1 -0
  151. package/dist/renderer3d/culling.js +27 -0
  152. package/dist/renderer3d/culling.js.map +1 -0
  153. package/dist/renderer3d/environment/index.d.ts +4 -0
  154. package/dist/renderer3d/environment/index.d.ts.map +1 -0
  155. package/dist/renderer3d/environment/index.js +9 -0
  156. package/dist/renderer3d/environment/index.js.map +1 -0
  157. package/dist/renderer3d/environment/sky.d.ts +45 -0
  158. package/dist/renderer3d/environment/sky.d.ts.map +1 -0
  159. package/dist/renderer3d/environment/sky.js +221 -0
  160. package/dist/renderer3d/environment/sky.js.map +1 -0
  161. package/dist/renderer3d/hud/fonts.d.ts +13 -0
  162. package/dist/renderer3d/hud/fonts.d.ts.map +1 -0
  163. package/dist/renderer3d/hud/fonts.js +69 -0
  164. package/dist/renderer3d/hud/fonts.js.map +1 -0
  165. package/dist/renderer3d/hud/paint.d.ts +4 -0
  166. package/dist/renderer3d/hud/paint.d.ts.map +1 -0
  167. package/dist/renderer3d/hud/paint.js +22 -0
  168. package/dist/renderer3d/hud/paint.js.map +1 -0
  169. package/dist/renderer3d/import.d.ts +34 -0
  170. package/dist/renderer3d/import.d.ts.map +1 -0
  171. package/dist/renderer3d/import.js +408 -0
  172. package/dist/renderer3d/import.js.map +1 -0
  173. package/dist/renderer3d/index.d.ts +74 -0
  174. package/dist/renderer3d/index.d.ts.map +1 -0
  175. package/dist/renderer3d/index.js +338 -0
  176. package/dist/renderer3d/index.js.map +1 -0
  177. package/dist/renderer3d/lights/index.d.ts +7 -0
  178. package/dist/renderer3d/lights/index.d.ts.map +1 -0
  179. package/dist/renderer3d/lights/index.js +67 -0
  180. package/dist/renderer3d/lights/index.js.map +1 -0
  181. package/dist/renderer3d/materials/index.d.ts +4 -0
  182. package/dist/renderer3d/materials/index.d.ts.map +1 -0
  183. package/dist/renderer3d/materials/index.js +8 -0
  184. package/dist/renderer3d/materials/index.js.map +1 -0
  185. package/dist/renderer3d/passes/post-processing.d.ts +44 -0
  186. package/dist/renderer3d/passes/post-processing.d.ts.map +1 -0
  187. package/dist/renderer3d/passes/post-processing.js +213 -0
  188. package/dist/renderer3d/passes/post-processing.js.map +1 -0
  189. package/dist/renderer3d/pipeline.d.ts +15 -0
  190. package/dist/renderer3d/pipeline.d.ts.map +1 -0
  191. package/dist/renderer3d/pipeline.js +10 -0
  192. package/dist/renderer3d/pipeline.js.map +1 -0
  193. package/dist/renderer3d/playwright-contract.d.ts +3 -0
  194. package/dist/renderer3d/playwright-contract.d.ts.map +1 -0
  195. package/dist/renderer3d/playwright-contract.js +4 -0
  196. package/dist/renderer3d/playwright-contract.js.map +1 -0
  197. package/dist/renderer3d/preparation.d.ts +79 -0
  198. package/dist/renderer3d/preparation.d.ts.map +1 -0
  199. package/dist/renderer3d/preparation.js +458 -0
  200. package/dist/renderer3d/preparation.js.map +1 -0
  201. package/dist/renderer3d/scene-sync.d.ts +8 -0
  202. package/dist/renderer3d/scene-sync.d.ts.map +1 -0
  203. package/dist/renderer3d/scene-sync.js +96 -0
  204. package/dist/renderer3d/scene-sync.js.map +1 -0
  205. package/dist/renderer3d/shadows/cascades.d.ts +40 -0
  206. package/dist/renderer3d/shadows/cascades.d.ts.map +1 -0
  207. package/dist/renderer3d/shadows/cascades.js +244 -0
  208. package/dist/renderer3d/shadows/cascades.js.map +1 -0
  209. package/dist/renderer3d/shadows/index.d.ts +44 -0
  210. package/dist/renderer3d/shadows/index.d.ts.map +1 -0
  211. package/dist/renderer3d/shadows/index.js +129 -0
  212. package/dist/renderer3d/shadows/index.js.map +1 -0
  213. package/dist/renderer3d/types.d.ts +18 -0
  214. package/dist/renderer3d/types.d.ts.map +1 -0
  215. package/dist/renderer3d/types.js +2 -0
  216. package/dist/renderer3d/types.js.map +1 -0
  217. package/dist/smoke.d.ts +15 -0
  218. package/dist/smoke.d.ts.map +1 -0
  219. package/dist/smoke.js +138 -0
  220. package/dist/smoke.js.map +1 -0
  221. package/dist/standalone-player.d.ts +11 -1
  222. package/dist/standalone-player.d.ts.map +1 -1
  223. package/dist/standalone-player.js +67 -41
  224. package/dist/standalone-player.js.map +1 -1
  225. package/dist/standalone-player3d.d.ts +14 -0
  226. package/dist/standalone-player3d.d.ts.map +1 -0
  227. package/dist/standalone-player3d.js +255 -0
  228. package/dist/standalone-player3d.js.map +1 -0
  229. package/dist/touch-controls.d.ts +22 -8
  230. package/dist/touch-controls.d.ts.map +1 -1
  231. package/dist/touch-controls.js +88 -21
  232. package/dist/touch-controls.js.map +1 -1
  233. package/dist/ui/controller.d.ts +59 -0
  234. package/dist/ui/controller.d.ts.map +1 -0
  235. package/dist/ui/controller.js +201 -0
  236. package/dist/ui/controller.js.map +1 -0
  237. package/dist/ui/hud2d.d.ts +11 -0
  238. package/dist/ui/hud2d.d.ts.map +1 -0
  239. package/dist/ui/hud2d.js +25 -0
  240. package/dist/ui/hud2d.js.map +1 -0
  241. package/dist/ui/layout.d.ts +42 -0
  242. package/dist/ui/layout.d.ts.map +1 -0
  243. package/dist/ui/layout.js +182 -0
  244. package/dist/ui/layout.js.map +1 -0
  245. package/dist/ui/paint.d.ts +45 -0
  246. package/dist/ui/paint.d.ts.map +1 -0
  247. package/dist/ui/paint.js +121 -0
  248. package/dist/ui/paint.js.map +1 -0
  249. package/dist/webgpu/effects.d.ts +22 -0
  250. package/dist/webgpu/effects.d.ts.map +1 -0
  251. package/dist/webgpu/effects.js +69 -0
  252. package/dist/webgpu/effects.js.map +1 -0
  253. package/dist/webgpu/hud.d.ts +4 -0
  254. package/dist/webgpu/hud.d.ts.map +1 -0
  255. package/dist/webgpu/hud.js +27 -0
  256. package/dist/webgpu/hud.js.map +1 -0
  257. package/dist/webgpu/lighting.d.ts +4 -0
  258. package/dist/webgpu/lighting.d.ts.map +1 -0
  259. package/dist/webgpu/lighting.js +47 -0
  260. package/dist/webgpu/lighting.js.map +1 -0
  261. package/dist/webgpu/pipeline.d.ts +11 -0
  262. package/dist/webgpu/pipeline.d.ts.map +1 -0
  263. package/dist/webgpu/pipeline.js +11 -0
  264. package/dist/webgpu/pipeline.js.map +1 -0
  265. package/dist/webgpu/sprites.d.ts +6 -0
  266. package/dist/webgpu/sprites.d.ts.map +1 -0
  267. package/dist/webgpu/sprites.js +74 -0
  268. package/dist/webgpu/sprites.js.map +1 -0
  269. package/dist/webgpu/types.d.ts +14 -0
  270. package/dist/webgpu/types.d.ts.map +1 -0
  271. package/dist/webgpu/types.js +2 -0
  272. package/dist/webgpu/types.js.map +1 -0
  273. package/dist/webgpu.d.ts +4 -3
  274. package/dist/webgpu.d.ts.map +1 -1
  275. package/dist/webgpu.js +119 -279
  276. package/dist/webgpu.js.map +1 -1
  277. package/package.json +52 -10
@@ -0,0 +1,40 @@
1
+ import * as THREE from "three";
2
+ import type { GameLight3D, GameShadowCascades3D } from "@nodetool-ai/protocol";
3
+ /** Splits [near, far] into `count` ranges, blending even and logarithmic splits by `lambda`. Returns each split's end as a fraction of far. */
4
+ export declare function gameCascadeBreaks3D(count: number, near: number, far: number, lambda: number): number[];
5
+ export declare function resizeGameShadowMap(shadow: THREE.LightShadow, size: number): void;
6
+ /**
7
+ * Cascaded shadow maps for one directional light, after three's CSM addon. Each cascade is a
8
+ * shadow-casting directional light that covers one depth range of the view. Materials receive the
9
+ * cascade lighting chunk through their own onBeforeCompile, after any hook they already had, so three's
10
+ * global shader chunks stay unchanged.
11
+ */
12
+ export declare class GameCascadedShadows3D {
13
+ private readonly group;
14
+ private readonly lights;
15
+ private readonly mainFrustum;
16
+ private readonly frustums;
17
+ private readonly lightSpaceFrustum;
18
+ /** Each patched material with the hooks it had before, restored on release. */
19
+ private readonly materials;
20
+ private readonly uniforms;
21
+ private breaks;
22
+ private frustumKey;
23
+ private count;
24
+ private margin;
25
+ private readonly compile;
26
+ constructor();
27
+ update(scene: THREE.Scene, source: THREE.DirectionalLight, definition: Extract<GameLight3D, {
28
+ kind: "directional";
29
+ }>, settings: GameShadowCascades3D, mapSize: number, camera: THREE.Camera): void;
30
+ detach(): void;
31
+ private rebuild;
32
+ private disposeLights;
33
+ private updateShadowBounds;
34
+ /** Centers each cascade's shadow camera on its slice of the view, snapped to the texel grid. */
35
+ private place;
36
+ private setupMaterials;
37
+ /** Runs the material's existing compile hook first, then adds the cascade chunk, and keys the program on both. */
38
+ private patchMaterial;
39
+ }
40
+ //# sourceMappingURL=cascades.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cascades.d.ts","sourceRoot":"","sources":["../../../src/renderer3d/shadows/cascades.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAU/E,+IAA+I;AAC/I,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAStG;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAMjF;AAOD;;;;;GAKG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;IACvD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAmC;IAC/D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;IAC7C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAmC;IACrE,+EAA+E;IAC/E,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA6C;IACvE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyG;IAClI,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAMtB;IAEF,cAA2D;IAE3D,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,gBAAgB,EAAE,UAAU,EAAE,OAAO,CAAC,WAAW,EAAE;QAAE,IAAI,EAAE,aAAa,CAAA;KAAE,CAAC,EAClH,QAAQ,EAAE,oBAAoB,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAkC7E;IAED,MAAM,IAAI,IAAI,CAOb;IAED,OAAO,CAAC,OAAO;IAef,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,kBAAkB;IAe1B,gGAAgG;IAChG,OAAO,CAAC,KAAK;IA4Bb,OAAO,CAAC,cAAc;IAiBtB,kHAAkH;IAClH,OAAO,CAAC,aAAa;CAgBtB"}
@@ -0,0 +1,244 @@
1
+ import * as THREE from "three";
2
+ import { CSMFrustum } from "three/addons/csm/CSMFrustum.js";
3
+ import * as csmShaderModule from "three/addons/csm/CSMShader.js";
4
+ const cascadeDefines = ["USE_CSM", "CSM_CASCADES"];
5
+ const up = new THREE.Vector3(0, 1, 0);
6
+ // @types/three declares CSMShader as an interface, but the module exports the chunk object.
7
+ const CSMShader = csmShaderModule.CSMShader;
8
+ const origin = new THREE.Vector3();
9
+ /** Splits [near, far] into `count` ranges, blending even and logarithmic splits by `lambda`. Returns each split's end as a fraction of far. */
10
+ export function gameCascadeBreaks3D(count, near, far, lambda) {
11
+ const breaks = [];
12
+ for (let index = 1; index < count; index++) {
13
+ const uniform = (near + (far - near) * index / count) / far;
14
+ const logarithmic = (near * (far / near) ** (index / count)) / far;
15
+ breaks.push(uniform + (logarithmic - uniform) * lambda);
16
+ }
17
+ breaks.push(1);
18
+ return breaks;
19
+ }
20
+ export function resizeGameShadowMap(shadow, size) {
21
+ if (shadow.mapSize.x === size && shadow.mapSize.y === size) {
22
+ return;
23
+ }
24
+ shadow.mapSize.set(size, size);
25
+ shadow.map?.depthTexture?.dispose();
26
+ shadow.map?.dispose();
27
+ shadow.map = null;
28
+ }
29
+ function isCascadeMaterial(material) {
30
+ return material instanceof THREE.MeshStandardMaterial || material instanceof THREE.MeshLambertMaterial ||
31
+ material instanceof THREE.MeshPhongMaterial || material instanceof THREE.MeshToonMaterial;
32
+ }
33
+ /**
34
+ * Cascaded shadow maps for one directional light, after three's CSM addon. Each cascade is a
35
+ * shadow-casting directional light that covers one depth range of the view. Materials receive the
36
+ * cascade lighting chunk through their own onBeforeCompile, after any hook they already had, so three's
37
+ * global shader chunks stay unchanged.
38
+ */
39
+ export class GameCascadedShadows3D {
40
+ group = new THREE.Group();
41
+ lights = [];
42
+ mainFrustum = new CSMFrustum({ webGL: true });
43
+ frustums = [];
44
+ lightSpaceFrustum = new CSMFrustum({ webGL: true });
45
+ /** Each patched material with the hooks it had before, restored on release. */
46
+ materials = new Map();
47
+ uniforms = { CSM_cascades: { value: [] }, cameraNear: { value: 0 }, shadowFar: { value: 0 } };
48
+ breaks = [];
49
+ frustumKey = "";
50
+ count = 0;
51
+ margin = 0;
52
+ compile = (shader) => {
53
+ Object.assign(shader.uniforms, this.uniforms);
54
+ for (const stage of ["vertexShader", "fragmentShader"]) {
55
+ shader[stage] = shader[stage].replace("#include <lights_pars_begin>", CSMShader.lights_pars_begin)
56
+ .replace("#include <lights_fragment_begin>", CSMShader.lights_fragment_begin);
57
+ }
58
+ };
59
+ constructor() { this.group.name = "game-shadow-cascades"; }
60
+ update(scene, source, definition, settings, mapSize, camera) {
61
+ if (this.count !== settings.count) {
62
+ this.rebuild(settings.count);
63
+ }
64
+ if (this.group.parent !== scene) {
65
+ scene.add(this.group);
66
+ // Cascade lights must lead the directional shadow array, so the group renders before every other light.
67
+ scene.children.splice(scene.children.indexOf(this.group), 1);
68
+ scene.children.unshift(this.group);
69
+ }
70
+ this.margin = Math.max(100, settings.maxDistance);
71
+ for (const light of this.lights) {
72
+ light.color.copy(source.color);
73
+ light.intensity = source.intensity;
74
+ resizeGameShadowMap(light.shadow, mapSize);
75
+ light.shadow.bias = definition.shadowBias ?? 0;
76
+ light.shadow.normalBias = definition.shadowNormalBias ?? 0;
77
+ light.shadow.camera.near = 1;
78
+ light.shadow.camera.far = this.margin + settings.maxDistance * 4;
79
+ }
80
+ const projection = camera instanceof THREE.PerspectiveCamera || camera instanceof THREE.OrthographicCamera ? camera : undefined;
81
+ const near = projection?.near ?? 0.1;
82
+ const far = Math.min(projection?.far ?? settings.maxDistance, settings.maxDistance);
83
+ const key = `${camera.projectionMatrix.elements.join(",")}|${settings.split}|${settings.maxDistance}|${mapSize}`;
84
+ if (key !== this.frustumKey) {
85
+ this.frustumKey = key;
86
+ this.breaks = gameCascadeBreaks3D(settings.count, near, far, settings.split);
87
+ this.mainFrustum.setFromProjectionMatrix(camera.projectionMatrix, settings.maxDistance);
88
+ this.mainFrustum.split(this.breaks, this.frustums);
89
+ this.updateShadowBounds(mapSize);
90
+ this.uniforms.cameraNear.value = near;
91
+ this.uniforms.shadowFar.value = far;
92
+ this.uniforms.CSM_cascades.value = this.breaks.map((end, index) => new THREE.Vector2(this.breaks[index - 1] ?? 0, end));
93
+ }
94
+ this.place(source, camera);
95
+ this.setupMaterials(scene);
96
+ }
97
+ detach() {
98
+ for (const [material, hooks] of this.materials) {
99
+ releaseMaterial(material, hooks);
100
+ }
101
+ this.materials.clear();
102
+ this.disposeLights();
103
+ this.group.removeFromParent();
104
+ this.count = 0;
105
+ this.frustumKey = "";
106
+ }
107
+ rebuild(count) {
108
+ this.disposeLights();
109
+ for (let index = 0; index < count; index++) {
110
+ const light = new THREE.DirectionalLight();
111
+ light.castShadow = true;
112
+ light.name = `game-shadow-cascade-${index}`;
113
+ this.group.add(light, light.target);
114
+ this.lights.push(light);
115
+ }
116
+ this.count = count;
117
+ this.frustumKey = "";
118
+ for (const [material, hooks] of this.materials) {
119
+ releaseMaterial(material, hooks);
120
+ }
121
+ this.materials.clear();
122
+ }
123
+ disposeLights() {
124
+ for (const light of this.lights) {
125
+ light.target.removeFromParent();
126
+ light.removeFromParent();
127
+ light.shadow.map?.depthTexture?.dispose();
128
+ light.dispose();
129
+ }
130
+ this.lights.length = 0;
131
+ }
132
+ updateShadowBounds(mapSize) {
133
+ for (const [index, frustum] of this.frustums.entries()) {
134
+ const light = this.lights[index];
135
+ if (!light) {
136
+ continue;
137
+ }
138
+ const nearVertices = frustum.vertices.near;
139
+ const farVertices = frustum.vertices.far;
140
+ const first = farVertices[0];
141
+ const diagonal = first.distanceTo(farVertices[2]) > first.distanceTo(nearVertices[2]) ? farVertices[2] : nearVertices[2];
142
+ // Round the extent to whole texels so the map does not shimmer as the camera moves.
143
+ const width = Math.ceil(first.distanceTo(diagonal) / 2 * mapSize) / mapSize * 2;
144
+ Object.assign(light.shadow.camera, { left: -width / 2, right: width / 2, top: width / 2, bottom: -width / 2 });
145
+ light.shadow.camera.updateProjectionMatrix();
146
+ }
147
+ }
148
+ /** Centers each cascade's shadow camera on its slice of the view, snapped to the texel grid. */
149
+ place(source, camera) {
150
+ const direction = new THREE.Vector3(0, 0, -1).applyQuaternion(source.quaternion).normalize();
151
+ const orientation = new THREE.Matrix4().lookAt(origin, direction, Math.abs(direction.y) > 0.999 ? new THREE.Vector3(0, 0, 1) : up);
152
+ const inverse = orientation.clone().invert();
153
+ const cameraToLight = new THREE.Matrix4().multiplyMatrices(inverse, camera.matrixWorld);
154
+ const box = new THREE.Box3();
155
+ const center = new THREE.Vector3();
156
+ for (const [index, frustum] of this.frustums.entries()) {
157
+ const light = this.lights[index];
158
+ if (!light) {
159
+ continue;
160
+ }
161
+ const shadowCamera = light.shadow.camera;
162
+ const texelWidth = (shadowCamera.right - shadowCamera.left) / light.shadow.mapSize.x;
163
+ const texelHeight = (shadowCamera.top - shadowCamera.bottom) / light.shadow.mapSize.y;
164
+ frustum.toSpace(cameraToLight, this.lightSpaceFrustum);
165
+ box.makeEmpty();
166
+ for (const vertex of [...this.lightSpaceFrustum.vertices.near, ...this.lightSpaceFrustum.vertices.far]) {
167
+ box.expandByPoint(vertex);
168
+ }
169
+ box.getCenter(center);
170
+ center.z = box.max.z + this.margin;
171
+ center.x = Math.floor(center.x / texelWidth) * texelWidth;
172
+ center.y = Math.floor(center.y / texelHeight) * texelHeight;
173
+ center.applyMatrix4(orientation);
174
+ light.position.copy(center);
175
+ light.target.position.copy(center).add(direction);
176
+ light.updateMatrixWorld();
177
+ light.target.updateMatrixWorld();
178
+ }
179
+ }
180
+ setupMaterials(scene) {
181
+ const seen = new Set();
182
+ scene.traverse((object) => {
183
+ if (!(object instanceof THREE.Mesh)) {
184
+ return;
185
+ }
186
+ const materials = Array.isArray(object.material) ? object.material : [object.material];
187
+ for (const material of materials) {
188
+ if (!isCascadeMaterial(material)) {
189
+ continue;
190
+ }
191
+ seen.add(material);
192
+ if (this.materials.has(material)) {
193
+ continue;
194
+ }
195
+ this.materials.set(material, this.patchMaterial(material));
196
+ }
197
+ });
198
+ for (const [material, hooks] of this.materials) {
199
+ if (!seen.has(material)) {
200
+ releaseMaterial(material, hooks);
201
+ this.materials.delete(material);
202
+ }
203
+ }
204
+ }
205
+ /** Runs the material's existing compile hook first, then adds the cascade chunk, and keys the program on both. */
206
+ patchMaterial(material) {
207
+ const hooks = {
208
+ onBeforeCompile: Object.hasOwn(material, "onBeforeCompile") ? material.onBeforeCompile : undefined,
209
+ customProgramCacheKey: Object.hasOwn(material, "customProgramCacheKey") ? material.customProgramCacheKey : undefined
210
+ };
211
+ const previousCompile = material.onBeforeCompile;
212
+ const previousKey = material.customProgramCacheKey;
213
+ material.defines = { ...material.defines, USE_CSM: 1, CSM_CASCADES: this.count };
214
+ material.onBeforeCompile = (shader, renderer) => {
215
+ previousCompile.call(material, shader, renderer);
216
+ this.compile(shader);
217
+ };
218
+ material.customProgramCacheKey = () => `${previousKey.call(material)}|game-shadow-cascades`;
219
+ material.needsUpdate = true;
220
+ return hooks;
221
+ }
222
+ }
223
+ function releaseMaterial(material, hooks) {
224
+ if (material.defines) {
225
+ for (const name of cascadeDefines) {
226
+ delete material.defines[name];
227
+ }
228
+ }
229
+ // Own properties return to their previous values. Otherwise the prototype's hooks show through again.
230
+ if (hooks.onBeforeCompile) {
231
+ material.onBeforeCompile = hooks.onBeforeCompile;
232
+ }
233
+ else {
234
+ Reflect.deleteProperty(material, "onBeforeCompile");
235
+ }
236
+ if (hooks.customProgramCacheKey) {
237
+ material.customProgramCacheKey = hooks.customProgramCacheKey;
238
+ }
239
+ else {
240
+ Reflect.deleteProperty(material, "customProgramCacheKey");
241
+ }
242
+ material.needsUpdate = true;
243
+ }
244
+ //# sourceMappingURL=cascades.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cascades.js","sourceRoot":"","sources":["../../../src/renderer3d/shadows/cascades.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import * as THREE from "three";
2
+ import { type GameLight3D, type GameRenderFrame3D } from "@nodetool-ai/protocol";
3
+ export interface GameShadowOverflow3D {
4
+ /** Shadowed point and spot lights over the scene budget. */
5
+ readonly local: number;
6
+ /** Shadowed directional lights after the one that cascades. */
7
+ readonly directional: number;
8
+ }
9
+ export interface GameShadowPlan3D {
10
+ /** Lights that render a shadow map this frame. */
11
+ readonly casting: ReadonlySet<string>;
12
+ /** The directional light drawn through cascaded shadow maps, when the scene enables cascades. */
13
+ readonly cascadedLightId?: string;
14
+ readonly overflow: GameShadowOverflow3D;
15
+ /** One message per overflowing kind. Messages carry counts, not entity ids, so spawned lights add no new messages. */
16
+ readonly diagnostics: readonly string[];
17
+ }
18
+ /** Decides which lights cast shadows in a frame. Lights over a budget render unshadowed and produce a diagnostic. */
19
+ export declare function planGameShadows3D(frame: Pick<GameRenderFrame3D, "lights" | "environment">): GameShadowPlan3D;
20
+ export declare function applyGameShadowBias(shadow: THREE.LightShadow, definition: GameLight3D): void;
21
+ export declare function configureDirectionalShadow(light: THREE.DirectionalLight, definition: Extract<GameLight3D, {
22
+ kind: "directional";
23
+ }>, environment: GameRenderFrame3D["environment"], casting?: boolean): void;
24
+ /** Point lights render six faces per shadow update, so their maps stay at most 1024 texels square. */
25
+ export declare function configureLocalShadow(light: THREE.PointLight | THREE.SpotLight, definition: Exclude<GameLight3D, {
26
+ kind: "directional";
27
+ }>, environment: GameRenderFrame3D["environment"], casting: boolean): void;
28
+ /**
29
+ * Per-renderer shadow state: the frame's plan, overflow diagnostics and the cascade controller. Each overflow kind
30
+ * keeps one diagnostics entry that is rewritten when the largest count seen grows, so the array stays bounded.
31
+ */
32
+ export declare class GameShadows3D {
33
+ private readonly diagnostics;
34
+ private readonly onDiagnostic?;
35
+ private readonly reported;
36
+ private readonly cascades;
37
+ plan: GameShadowPlan3D;
38
+ constructor(diagnostics: string[], onDiagnostic?: ((message: string) => void) | undefined);
39
+ prepare(frame: GameRenderFrame3D): GameShadowPlan3D;
40
+ /** Draws the cascaded light through per-cascade lights and hides its single-map light. */
41
+ update(scene: THREE.Scene, lights: ReadonlyMap<string, THREE.Light>, frame: GameRenderFrame3D, camera: THREE.Camera): void;
42
+ dispose(): void;
43
+ }
44
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/renderer3d/shadows/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAqC,KAAK,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAGpH,MAAM,WAAW,oBAAoB;IACnC,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,+DAA+D;IAC/D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACtC,iGAAiG;IACjG,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IACxC,sHAAsH;IACtH,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC;AAWD,qHAAqH;AACrH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE,QAAQ,GAAG,aAAa,CAAC,GAAG,gBAAgB,CAqB5G;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,KAAK,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,GAAG,IAAI,CAG5F;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,KAAK,CAAC,gBAAgB,EAAE,UAAU,EAAE,OAAO,CAAC,WAAW,EAAE;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC,EAAE,WAAW,EAAE,iBAAiB,CAAC,aAAa,CAAC,EAAE,OAAO,UAAuD,GAAG,IAAI,CAOxP;AAED,sGAAsG;AACtG,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,WAAW,EAAE;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC,EAAE,WAAW,EAAE,iBAAiB,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAWhN;AAED;;;GAGG;AACH,qBAAa,aAAa;IAKZ,OAAO,CAAC,QAAQ,CAAC,WAAW;IAAY,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IAJlF,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkF;IAC3G,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA+B;IACxD,IAAI,EAAE,gBAAgB,CAAmF;IAEzG,YAA6B,WAAW,EAAE,MAAM,EAAE,EAAmB,YAAY,CAAC,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,aAAA,EAAI;IAEjH,OAAO,CAAC,KAAK,EAAE,iBAAiB,GAAG,gBAAgB,CAiBlD;IAED,0FAA0F;IAC1F,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAWzH;IAED,OAAO,IAAI,IAAI,CAA4B;CAC5C"}
@@ -0,0 +1,129 @@
1
+ import * as THREE from "three";
2
+ import { GAME_LOCAL_SHADOW_LIGHT_BUDGET_3D } from "@nodetool-ai/protocol";
3
+ import { GameCascadedShadows3D } from "./cascades.js";
4
+ const overflowKinds = ["local", "directional"];
5
+ function overflowMessage(kind, count) {
6
+ return kind === "local"
7
+ ? `Shadow budget exceeded: ${count} point and spot ${count === 1 ? "light renders" : "lights render"} without shadows (at most ${GAME_LOCAL_SHADOW_LIGHT_BUDGET_3D} cast shadows per scene)`
8
+ : `Cascaded shadows support one directional light: ${count} other shadowed directional ${count === 1 ? "light renders" : "lights render"} without shadows`;
9
+ }
10
+ /** Decides which lights cast shadows in a frame. Lights over a budget render unshadowed and produce a diagnostic. */
11
+ export function planGameShadows3D(frame) {
12
+ const casting = new Set();
13
+ const overflow = { local: 0, directional: 0 };
14
+ if (!frame.environment.shadows.enabled) {
15
+ return { casting, overflow, diagnostics: [] };
16
+ }
17
+ const cascaded = frame.environment.shadows.cascades !== undefined;
18
+ let cascadedLightId;
19
+ let local = 0;
20
+ for (const { entityId, light } of frame.lights) {
21
+ if (light.kind === "directional") {
22
+ if (!light.castShadow) {
23
+ continue;
24
+ }
25
+ if (!cascaded) {
26
+ casting.add(entityId);
27
+ continue;
28
+ }
29
+ if (cascadedLightId === undefined) {
30
+ cascadedLightId = entityId;
31
+ casting.add(entityId);
32
+ continue;
33
+ }
34
+ overflow.directional++;
35
+ continue;
36
+ }
37
+ if (light.castShadow !== true) {
38
+ continue;
39
+ }
40
+ if (local < GAME_LOCAL_SHADOW_LIGHT_BUDGET_3D) {
41
+ local++;
42
+ casting.add(entityId);
43
+ continue;
44
+ }
45
+ overflow.local++;
46
+ }
47
+ const diagnostics = overflowKinds.filter((kind) => overflow[kind] > 0).map((kind) => overflowMessage(kind, overflow[kind]));
48
+ return cascadedLightId === undefined ? { casting, overflow, diagnostics } : { casting, cascadedLightId, overflow, diagnostics };
49
+ }
50
+ export function applyGameShadowBias(shadow, definition) {
51
+ shadow.bias = definition.shadowBias ?? 0;
52
+ shadow.normalBias = definition.shadowNormalBias ?? 0;
53
+ }
54
+ export function configureDirectionalShadow(light, definition, environment, casting = environment.shadows.enabled && definition.castShadow) {
55
+ light.castShadow = casting;
56
+ light.shadow.mapSize.set(environment.shadows.mapSize, environment.shadows.mapSize);
57
+ const extent = environment.shadows.extent;
58
+ Object.assign(light.shadow.camera, { left: -extent, right: extent, top: extent, bottom: -extent, near: 0.1, far: extent * 4 });
59
+ light.shadow.camera.updateProjectionMatrix();
60
+ applyGameShadowBias(light.shadow, definition);
61
+ }
62
+ /** Point lights render six faces per shadow update, so their maps stay at most 1024 texels square. */
63
+ export function configureLocalShadow(light, definition, environment, casting) {
64
+ light.castShadow = casting;
65
+ if (!casting) {
66
+ return;
67
+ }
68
+ const size = light instanceof THREE.PointLight ? Math.min(1024, environment.shadows.mapSize) : environment.shadows.mapSize;
69
+ if (light.shadow.mapSize.x !== size) {
70
+ light.shadow.mapSize.set(size, size);
71
+ light.shadow.map?.dispose();
72
+ light.shadow.map = null;
73
+ }
74
+ light.shadow.camera.near = Math.min(0.1, definition.range / 100);
75
+ applyGameShadowBias(light.shadow, definition);
76
+ }
77
+ /**
78
+ * Per-renderer shadow state: the frame's plan, overflow diagnostics and the cascade controller. Each overflow kind
79
+ * keeps one diagnostics entry that is rewritten when the largest count seen grows, so the array stays bounded.
80
+ */
81
+ export class GameShadows3D {
82
+ diagnostics;
83
+ onDiagnostic;
84
+ reported = new Map();
85
+ cascades = new GameCascadedShadows3D();
86
+ plan = { casting: new Set(), overflow: { local: 0, directional: 0 }, diagnostics: [] };
87
+ constructor(diagnostics, onDiagnostic) {
88
+ this.diagnostics = diagnostics;
89
+ this.onDiagnostic = onDiagnostic;
90
+ }
91
+ prepare(frame) {
92
+ this.plan = planGameShadows3D(frame);
93
+ for (const kind of overflowKinds) {
94
+ const count = this.plan.overflow[kind];
95
+ const previous = this.reported.get(kind);
96
+ if (count <= (previous?.count ?? 0)) {
97
+ continue;
98
+ }
99
+ const message = overflowMessage(kind, count);
100
+ if (previous) {
101
+ previous.count = count;
102
+ this.diagnostics[previous.index] = message;
103
+ }
104
+ else {
105
+ this.reported.set(kind, { index: this.diagnostics.length, count });
106
+ this.diagnostics.push(message);
107
+ }
108
+ this.onDiagnostic?.(message);
109
+ }
110
+ return this.plan;
111
+ }
112
+ /** Draws the cascaded light through per-cascade lights and hides its single-map light. */
113
+ update(scene, lights, frame, camera) {
114
+ const settings = frame.environment.shadows.cascades;
115
+ const id = this.plan.cascadedLightId;
116
+ const entry = id === undefined ? undefined : frame.lights.find((candidate) => candidate.entityId === id);
117
+ const source = id === undefined ? undefined : lights.get(id);
118
+ for (const [lightId, light] of lights) {
119
+ light.visible = lightId !== id || !(source instanceof THREE.DirectionalLight);
120
+ }
121
+ if (!settings || !entry || entry.light.kind !== "directional" || !(source instanceof THREE.DirectionalLight)) {
122
+ this.cascades.detach();
123
+ return;
124
+ }
125
+ this.cascades.update(scene, source, entry.light, settings, frame.environment.shadows.mapSize, camera);
126
+ }
127
+ dispose() { this.cascades.detach(); }
128
+ }
129
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/renderer3d/shadows/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import * as THREE from "three";
2
+ import type { GLTF } from "three/addons/loaders/GLTFLoader.js";
3
+ import type { PreparedGameModel } from "./preparation.js";
4
+ export interface CachedModel {
5
+ readonly prepared: PreparedGameModel;
6
+ readonly gltf: GLTF;
7
+ }
8
+ export interface RenderInstance {
9
+ modelAssetId?: string;
10
+ sampledAnimationKey?: string;
11
+ readonly descriptor: string;
12
+ readonly object: THREE.Object3D;
13
+ readonly materials: readonly THREE.Material[];
14
+ readonly primitiveGeometry?: THREE.BufferGeometry;
15
+ readonly mixer?: THREE.AnimationMixer;
16
+ readonly clips?: readonly THREE.AnimationClip[];
17
+ }
18
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/renderer3d/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;CACrB;AACD,MAAM,WAAW,cAAc;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC9C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC;IAClD,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,KAAK,CAAC,aAAa,EAAE,CAAC;CACjD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/renderer3d/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ export interface GameSmokeOptions {
2
+ readonly frames?: number;
3
+ readonly timeoutMs?: number;
4
+ readonly executablePath?: string;
5
+ readonly signal?: AbortSignal;
6
+ }
7
+ export interface GameSmokeReport {
8
+ readonly ok: boolean;
9
+ readonly frames: number;
10
+ readonly ticks: number;
11
+ readonly errors: readonly string[];
12
+ }
13
+ /** Serve the exported player without outside network access and exercise its renderer and simulation. */
14
+ export declare function smokeStandaloneGame(directory: string, options?: GameSmokeOptions): Promise<GameSmokeReport>;
15
+ //# sourceMappingURL=smoke.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smoke.d.ts","sourceRoot":"","sources":["../src/smoke.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B;AACD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAUD,yGAAyG;AACzG,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC,CA4FrH"}