@zylem/game-lib 0.5.0 → 0.5.1

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 (441) hide show
  1. package/README.md +23 -41
  2. package/dist/actions.d.ts +25 -0
  3. package/dist/actions.js +287 -8
  4. package/dist/actions.js.map +1 -0
  5. package/dist/behaviors.d.ts +108 -0
  6. package/dist/behaviors.js +396 -6
  7. package/dist/behaviors.js.map +1 -0
  8. package/dist/{src/lib/camera/zylem-camera.d.ts → camera-Dk-fOVZE.d.ts} +55 -8
  9. package/dist/camera.d.ts +5 -0
  10. package/dist/camera.js +504 -4
  11. package/dist/camera.js.map +1 -0
  12. package/dist/core-C2mjetAd.d.ts +431 -0
  13. package/dist/core.d.ts +9 -0
  14. package/dist/core.js +4780 -9
  15. package/dist/core.js.map +1 -0
  16. package/dist/entities.d.ts +269 -0
  17. package/dist/entities.js +2161 -17
  18. package/dist/entities.js.map +1 -0
  19. package/dist/entity-bQElAdpo.d.ts +347 -0
  20. package/dist/entity-spawner-DNnLYnZq.d.ts +11 -0
  21. package/dist/main.d.ts +135 -0
  22. package/dist/main.js +6599 -56
  23. package/dist/main.js.map +1 -0
  24. package/dist/moveable-B_vyA6cw.d.ts +67 -0
  25. package/dist/stage-CrmY7V0i.d.ts +287 -0
  26. package/dist/stage.d.ts +26 -0
  27. package/dist/stage.js +2229 -4
  28. package/dist/stage.js.map +1 -0
  29. package/dist/transformable-CUhvyuYO.d.ts +67 -0
  30. package/package.json +9 -45
  31. package/LICENSE +0 -21
  32. package/dist/.vite/manifest.json +0 -716
  33. package/dist/assets/zylem-logo.png +0 -0
  34. package/dist/examples/00-readme-example.d.ts +0 -2
  35. package/dist/examples/00-readme-example.d.ts.map +0 -1
  36. package/dist/examples/01-basic.d.ts +0 -2
  37. package/dist/examples/01-basic.d.ts.map +0 -1
  38. package/dist/examples/01.1-basic-ball.d.ts +0 -9
  39. package/dist/examples/01.1-basic-ball.d.ts.map +0 -1
  40. package/dist/examples/01.2-ricochet-test.d.ts +0 -2
  41. package/dist/examples/01.2-ricochet-test.d.ts.map +0 -1
  42. package/dist/examples/01.3-rect.d.ts +0 -2
  43. package/dist/examples/01.3-rect.d.ts.map +0 -1
  44. package/dist/examples/02-input.d.ts +0 -2
  45. package/dist/examples/02-input.d.ts.map +0 -1
  46. package/dist/examples/03-stage-test/03-stage-test.d.ts +0 -2
  47. package/dist/examples/03-stage-test/03-stage-test.d.ts.map +0 -1
  48. package/dist/examples/03-stage-test/stage0.d.ts +0 -2
  49. package/dist/examples/03-stage-test/stage0.d.ts.map +0 -1
  50. package/dist/examples/03-stage-test/stage1.d.ts +0 -2
  51. package/dist/examples/03-stage-test/stage1.d.ts.map +0 -1
  52. package/dist/examples/03-stage-test/stage2.d.ts +0 -2
  53. package/dist/examples/03-stage-test/stage2.d.ts.map +0 -1
  54. package/dist/examples/03-stage-test/stage3.d.ts +0 -2
  55. package/dist/examples/03-stage-test/stage3.d.ts.map +0 -1
  56. package/dist/examples/03.1-stage-variable.d.ts +0 -2
  57. package/dist/examples/03.1-stage-variable.d.ts.map +0 -1
  58. package/dist/examples/04-vessel-test.d.ts +0 -18
  59. package/dist/examples/04-vessel-test.d.ts.map +0 -1
  60. package/dist/examples/05-camera-test.d.ts +0 -2
  61. package/dist/examples/05-camera-test.d.ts.map +0 -1
  62. package/dist/examples/06-entity-test.d.ts +0 -2
  63. package/dist/examples/06-entity-test.d.ts.map +0 -1
  64. package/dist/examples/07-behaviors.d.ts +0 -2
  65. package/dist/examples/07-behaviors.d.ts.map +0 -1
  66. package/dist/examples/07.01-behavior-context.d.ts +0 -2
  67. package/dist/examples/07.01-behavior-context.d.ts.map +0 -1
  68. package/dist/examples/08-pong.d.ts +0 -2
  69. package/dist/examples/08-pong.d.ts.map +0 -1
  70. package/dist/examples/08.01-breakout.d.ts +0 -2
  71. package/dist/examples/08.01-breakout.d.ts.map +0 -1
  72. package/dist/examples/09-space-invaders.d.ts +0 -2
  73. package/dist/examples/09-space-invaders.d.ts.map +0 -1
  74. package/dist/examples/10-asteroids.d.ts +0 -2
  75. package/dist/examples/10-asteroids.d.ts.map +0 -1
  76. package/dist/examples/11-2d-platformer.d.ts +0 -2
  77. package/dist/examples/11-2d-platformer.d.ts.map +0 -1
  78. package/dist/examples/12-3d-platformer.d.ts +0 -2
  79. package/dist/examples/12-3d-platformer.d.ts.map +0 -1
  80. package/dist/examples/13-fps.d.ts +0 -2
  81. package/dist/examples/13-fps.d.ts.map +0 -1
  82. package/dist/examples/14-strategy.d.ts +0 -2
  83. package/dist/examples/14-strategy.d.ts.map +0 -1
  84. package/dist/examples/15-zylem-planet-demo.d.ts +0 -2
  85. package/dist/examples/15-zylem-planet-demo.d.ts.map +0 -1
  86. package/dist/examples/16-timbotron.d.ts +0 -2
  87. package/dist/examples/16-timbotron.d.ts.map +0 -1
  88. package/dist/examples/17-stress-test.d.ts +0 -2
  89. package/dist/examples/17-stress-test.d.ts.map +0 -1
  90. package/dist/examples/architecture-test.d.ts +0 -2
  91. package/dist/examples/architecture-test.d.ts.map +0 -1
  92. package/dist/examples/utils.d.ts +0 -10
  93. package/dist/examples/utils.d.ts.map +0 -1
  94. package/dist/lib/actions/behaviors/actions.js +0 -35
  95. package/dist/lib/actions/behaviors/boundaries/boundary.js +0 -40
  96. package/dist/lib/actions/behaviors/ricochet/ricochet-2d-collision.js +0 -100
  97. package/dist/lib/actions/behaviors/ricochet/ricochet-2d-in-bounds.js +0 -37
  98. package/dist/lib/actions/behaviors/ricochet/ricochet.js +0 -6
  99. package/dist/lib/actions/capabilities/moveable.js +0 -108
  100. package/dist/lib/actions/capabilities/rotatable.js +0 -82
  101. package/dist/lib/actions/capabilities/transformable.js +0 -9
  102. package/dist/lib/actions/global-change.js +0 -40
  103. package/dist/lib/camera/camera.js +0 -19
  104. package/dist/lib/camera/fixed-2d.js +0 -30
  105. package/dist/lib/camera/perspective.js +0 -10
  106. package/dist/lib/camera/third-person.js +0 -42
  107. package/dist/lib/camera/zylem-camera.js +0 -208
  108. package/dist/lib/collision/collision-builder.js +0 -46
  109. package/dist/lib/collision/collision-delegate.js +0 -6
  110. package/dist/lib/collision/utils.js +0 -24
  111. package/dist/lib/collision/world.js +0 -77
  112. package/dist/lib/core/base-node.js +0 -61
  113. package/dist/lib/core/entity-asset-loader.js +0 -54
  114. package/dist/lib/core/lifecycle-base.js +0 -20
  115. package/dist/lib/core/preset-shader.js +0 -26
  116. package/dist/lib/core/three-addons/Timer.js +0 -103
  117. package/dist/lib/core/utility/nodes.js +0 -31
  118. package/dist/lib/core/utility/strings.js +0 -14
  119. package/dist/lib/core/utility/vector.js +0 -8
  120. package/dist/lib/core/vessel.js +0 -26
  121. package/dist/lib/debug/console/console-state.js +0 -11
  122. package/dist/lib/debug/debug-state.js +0 -40
  123. package/dist/lib/device/aspect-ratio.js +0 -44
  124. package/dist/lib/entities/actor.js +0 -122
  125. package/dist/lib/entities/box.js +0 -68
  126. package/dist/lib/entities/builder.js +0 -79
  127. package/dist/lib/entities/create.js +0 -31
  128. package/dist/lib/entities/delegates/animation.js +0 -58
  129. package/dist/lib/entities/delegates/debug.js +0 -71
  130. package/dist/lib/entities/delegates/loader.js +0 -19
  131. package/dist/lib/entities/destroy.js +0 -15
  132. package/dist/lib/entities/entity-factory.js +0 -24
  133. package/dist/lib/entities/entity.js +0 -121
  134. package/dist/lib/entities/plane.js +0 -81
  135. package/dist/lib/entities/rect.js +0 -160
  136. package/dist/lib/entities/sphere.js +0 -68
  137. package/dist/lib/entities/sprite.js +0 -125
  138. package/dist/lib/entities/text.js +0 -140
  139. package/dist/lib/entities/zone.js +0 -103
  140. package/dist/lib/game/game-canvas.js +0 -57
  141. package/dist/lib/game/game-config.js +0 -78
  142. package/dist/lib/game/game-default.js +0 -23
  143. package/dist/lib/game/game-retro-resolutions.js +0 -80
  144. package/dist/lib/game/game-state.js +0 -17
  145. package/dist/lib/game/game.js +0 -131
  146. package/dist/lib/game/zylem-game.js +0 -140
  147. package/dist/lib/graphics/geometries/XZPlaneGeometry.js +0 -34
  148. package/dist/lib/graphics/material.js +0 -64
  149. package/dist/lib/graphics/mesh.js +0 -14
  150. package/dist/lib/graphics/render-pass.js +0 -56
  151. package/dist/lib/graphics/shaders/fragment/debug.glsl.js +0 -23
  152. package/dist/lib/graphics/shaders/fragment/fire.glsl.js +0 -52
  153. package/dist/lib/graphics/shaders/fragment/standard.glsl.js +0 -11
  154. package/dist/lib/graphics/shaders/fragment/stars.glsl.js +0 -44
  155. package/dist/lib/graphics/shaders/vertex/debug.glsl.js +0 -15
  156. package/dist/lib/graphics/shaders/vertex/object-shader.glsl.js +0 -11
  157. package/dist/lib/graphics/shaders/vertex/standard.glsl.js +0 -9
  158. package/dist/lib/graphics/zylem-scene.js +0 -75
  159. package/dist/lib/input/gamepad-provider.js +0 -58
  160. package/dist/lib/input/input-manager.js +0 -70
  161. package/dist/lib/input/keyboard-provider.js +0 -120
  162. package/dist/lib/stage/debug-entity-cursor.js +0 -53
  163. package/dist/lib/stage/entity-spawner.js +0 -27
  164. package/dist/lib/stage/stage-debug-delegate.js +0 -100
  165. package/dist/lib/stage/stage-default.js +0 -32
  166. package/dist/lib/stage/stage-factory.js +0 -22
  167. package/dist/lib/stage/stage-manager.js +0 -49
  168. package/dist/lib/stage/stage-state.js +0 -36
  169. package/dist/lib/stage/stage.js +0 -67
  170. package/dist/lib/stage/zylem-stage.js +0 -268
  171. package/dist/lib/systems/transformable.system.js +0 -43
  172. package/dist/node_modules/.pnpm/idb-keyval@6.2.2/node_modules/idb-keyval/dist/index.js +0 -34
  173. package/dist/node_modules/.pnpm/msgpackr@1.11.5/node_modules/msgpackr/pack.js +0 -520
  174. package/dist/node_modules/.pnpm/msgpackr@1.11.5/node_modules/msgpackr/unpack.js +0 -672
  175. package/dist/src/api/actions.d.ts +0 -5
  176. package/dist/src/api/actions.d.ts.map +0 -1
  177. package/dist/src/api/behaviors.d.ts +0 -4
  178. package/dist/src/api/behaviors.d.ts.map +0 -1
  179. package/dist/src/api/camera.d.ts +0 -4
  180. package/dist/src/api/camera.d.ts.map +0 -1
  181. package/dist/src/api/core.d.ts +0 -6
  182. package/dist/src/api/core.d.ts.map +0 -1
  183. package/dist/src/api/entities.d.ts +0 -9
  184. package/dist/src/api/entities.d.ts.map +0 -1
  185. package/dist/src/api/main.d.ts +0 -32
  186. package/dist/src/api/main.d.ts.map +0 -1
  187. package/dist/src/api/stage.d.ts +0 -5
  188. package/dist/src/api/stage.d.ts.map +0 -1
  189. package/dist/src/lib/actions/behaviors/actions.d.ts +0 -11
  190. package/dist/src/lib/actions/behaviors/actions.d.ts.map +0 -1
  191. package/dist/src/lib/actions/behaviors/behavior.d.ts +0 -6
  192. package/dist/src/lib/actions/behaviors/behavior.d.ts.map +0 -1
  193. package/dist/src/lib/actions/behaviors/boundaries/boundary.d.ts +0 -37
  194. package/dist/src/lib/actions/behaviors/boundaries/boundary.d.ts.map +0 -1
  195. package/dist/src/lib/actions/behaviors/character-controller.d.ts +0 -6
  196. package/dist/src/lib/actions/behaviors/character-controller.d.ts.map +0 -1
  197. package/dist/src/lib/actions/behaviors/debug/debug-collision.d.ts +0 -6
  198. package/dist/src/lib/actions/behaviors/debug/debug-collision.d.ts.map +0 -1
  199. package/dist/src/lib/actions/behaviors/debug/debug-update.d.ts +0 -5
  200. package/dist/src/lib/actions/behaviors/debug/debug-update.d.ts.map +0 -1
  201. package/dist/src/lib/actions/behaviors/debug/debug.d.ts +0 -10
  202. package/dist/src/lib/actions/behaviors/debug/debug.d.ts.map +0 -1
  203. package/dist/src/lib/actions/behaviors/movement/movement-sequence-2d.d.ts +0 -24
  204. package/dist/src/lib/actions/behaviors/movement/movement-sequence-2d.d.ts.map +0 -1
  205. package/dist/src/lib/actions/behaviors/ricochet/ricochet-2d-collision.d.ts +0 -11
  206. package/dist/src/lib/actions/behaviors/ricochet/ricochet-2d-collision.d.ts.map +0 -1
  207. package/dist/src/lib/actions/behaviors/ricochet/ricochet-2d-in-bounds.d.ts +0 -12
  208. package/dist/src/lib/actions/behaviors/ricochet/ricochet-2d-in-bounds.d.ts.map +0 -1
  209. package/dist/src/lib/actions/behaviors/ricochet/ricochet.d.ts +0 -44
  210. package/dist/src/lib/actions/behaviors/ricochet/ricochet.d.ts.map +0 -1
  211. package/dist/src/lib/actions/behaviors/zylem-behavior.d.ts +0 -2
  212. package/dist/src/lib/actions/behaviors/zylem-behavior.d.ts.map +0 -1
  213. package/dist/src/lib/actions/capabilities/moveable.d.ts +0 -125
  214. package/dist/src/lib/actions/capabilities/moveable.d.ts.map +0 -1
  215. package/dist/src/lib/actions/capabilities/rotatable.d.ts +0 -111
  216. package/dist/src/lib/actions/capabilities/rotatable.d.ts.map +0 -1
  217. package/dist/src/lib/actions/capabilities/transformable.d.ts +0 -7
  218. package/dist/src/lib/actions/capabilities/transformable.d.ts.map +0 -1
  219. package/dist/src/lib/actions/global-change.d.ts +0 -23
  220. package/dist/src/lib/actions/global-change.d.ts.map +0 -1
  221. package/dist/src/lib/camera/camera.d.ts +0 -16
  222. package/dist/src/lib/camera/camera.d.ts.map +0 -1
  223. package/dist/src/lib/camera/fixed-2d.d.ts +0 -32
  224. package/dist/src/lib/camera/fixed-2d.d.ts.map +0 -1
  225. package/dist/src/lib/camera/perspective.d.ts +0 -9
  226. package/dist/src/lib/camera/perspective.d.ts.map +0 -1
  227. package/dist/src/lib/camera/third-person.d.ts +0 -32
  228. package/dist/src/lib/camera/third-person.d.ts.map +0 -1
  229. package/dist/src/lib/camera/zylem-camera.d.ts.map +0 -1
  230. package/dist/src/lib/collision/collision-builder.d.ts +0 -17
  231. package/dist/src/lib/collision/collision-builder.d.ts.map +0 -1
  232. package/dist/src/lib/collision/collision-delegate.d.ts +0 -6
  233. package/dist/src/lib/collision/collision-delegate.d.ts.map +0 -1
  234. package/dist/src/lib/collision/collision-group.d.ts +0 -11
  235. package/dist/src/lib/collision/collision-group.d.ts.map +0 -1
  236. package/dist/src/lib/collision/collision-mask.d.ts +0 -18
  237. package/dist/src/lib/collision/collision-mask.d.ts.map +0 -1
  238. package/dist/src/lib/collision/collision.d.ts +0 -19
  239. package/dist/src/lib/collision/collision.d.ts.map +0 -1
  240. package/dist/src/lib/collision/utils.d.ts +0 -15
  241. package/dist/src/lib/collision/utils.d.ts.map +0 -1
  242. package/dist/src/lib/collision/world.d.ts +0 -23
  243. package/dist/src/lib/collision/world.d.ts.map +0 -1
  244. package/dist/src/lib/core/asset-manager.d.ts +0 -2
  245. package/dist/src/lib/core/asset-manager.d.ts.map +0 -1
  246. package/dist/src/lib/core/base-node-life-cycle.d.ts +0 -54
  247. package/dist/src/lib/core/base-node-life-cycle.d.ts.map +0 -1
  248. package/dist/src/lib/core/base-node.d.ts +0 -36
  249. package/dist/src/lib/core/base-node.d.ts.map +0 -1
  250. package/dist/src/lib/core/blueprints.d.ts +0 -22
  251. package/dist/src/lib/core/blueprints.d.ts.map +0 -1
  252. package/dist/src/lib/core/entity-asset-loader.d.ts +0 -16
  253. package/dist/src/lib/core/entity-asset-loader.d.ts.map +0 -1
  254. package/dist/src/lib/core/errors.d.ts +0 -5
  255. package/dist/src/lib/core/errors.d.ts.map +0 -1
  256. package/dist/src/lib/core/flags.d.ts +0 -3
  257. package/dist/src/lib/core/flags.d.ts.map +0 -1
  258. package/dist/src/lib/core/index.d.ts +0 -5
  259. package/dist/src/lib/core/index.d.ts.map +0 -1
  260. package/dist/src/lib/core/interfaces.d.ts +0 -25
  261. package/dist/src/lib/core/interfaces.d.ts.map +0 -1
  262. package/dist/src/lib/core/lazy-loader.d.ts +0 -80
  263. package/dist/src/lib/core/lazy-loader.d.ts.map +0 -1
  264. package/dist/src/lib/core/lifecycle-base.d.ts +0 -17
  265. package/dist/src/lib/core/lifecycle-base.d.ts.map +0 -1
  266. package/dist/src/lib/core/node-interface.d.ts +0 -12
  267. package/dist/src/lib/core/node-interface.d.ts.map +0 -1
  268. package/dist/src/lib/core/preset-shader.d.ts +0 -8
  269. package/dist/src/lib/core/preset-shader.d.ts.map +0 -1
  270. package/dist/src/lib/core/three-addons/Timer.d.ts +0 -92
  271. package/dist/src/lib/core/three-addons/Timer.d.ts.map +0 -1
  272. package/dist/src/lib/core/utility/nodes.d.ts +0 -13
  273. package/dist/src/lib/core/utility/nodes.d.ts.map +0 -1
  274. package/dist/src/lib/core/utility/strings.d.ts +0 -3
  275. package/dist/src/lib/core/utility/strings.d.ts.map +0 -1
  276. package/dist/src/lib/core/utility/vector.d.ts +0 -8
  277. package/dist/src/lib/core/utility/vector.d.ts.map +0 -1
  278. package/dist/src/lib/core/vector.d.ts +0 -4
  279. package/dist/src/lib/core/vector.d.ts.map +0 -1
  280. package/dist/src/lib/core/vessel.d.ts +0 -13
  281. package/dist/src/lib/core/vessel.d.ts.map +0 -1
  282. package/dist/src/lib/debug/console/console-state.d.ts +0 -20
  283. package/dist/src/lib/debug/console/console-state.d.ts.map +0 -1
  284. package/dist/src/lib/debug/console/console-store.d.ts +0 -6
  285. package/dist/src/lib/debug/console/console-store.d.ts.map +0 -1
  286. package/dist/src/lib/debug/debug-state.d.ts +0 -38
  287. package/dist/src/lib/debug/debug-state.d.ts.map +0 -1
  288. package/dist/src/lib/debug/debug-store.d.ts +0 -15
  289. package/dist/src/lib/debug/debug-store.d.ts.map +0 -1
  290. package/dist/src/lib/debug/state-based-debug-loader.d.ts +0 -8
  291. package/dist/src/lib/debug/state-based-debug-loader.d.ts.map +0 -1
  292. package/dist/src/lib/device/aspect-ratio.d.ts +0 -38
  293. package/dist/src/lib/device/aspect-ratio.d.ts.map +0 -1
  294. package/dist/src/lib/device/desktop.d.ts +0 -2
  295. package/dist/src/lib/device/desktop.d.ts.map +0 -1
  296. package/dist/src/lib/device/mobile.d.ts +0 -2
  297. package/dist/src/lib/device/mobile.d.ts.map +0 -1
  298. package/dist/src/lib/device/tablet.d.ts +0 -2
  299. package/dist/src/lib/device/tablet.d.ts.map +0 -1
  300. package/dist/src/lib/entities/actor.d.ts +0 -44
  301. package/dist/src/lib/entities/actor.d.ts.map +0 -1
  302. package/dist/src/lib/entities/box.d.ts +0 -27
  303. package/dist/src/lib/entities/box.d.ts.map +0 -1
  304. package/dist/src/lib/entities/builder.d.ts +0 -28
  305. package/dist/src/lib/entities/builder.d.ts.map +0 -1
  306. package/dist/src/lib/entities/create.d.ts +0 -15
  307. package/dist/src/lib/entities/create.d.ts.map +0 -1
  308. package/dist/src/lib/entities/delegates/animation.d.ts +0 -33
  309. package/dist/src/lib/entities/delegates/animation.d.ts.map +0 -1
  310. package/dist/src/lib/entities/delegates/debug.d.ts +0 -29
  311. package/dist/src/lib/entities/delegates/debug.d.ts.map +0 -1
  312. package/dist/src/lib/entities/delegates/loader.d.ts +0 -12
  313. package/dist/src/lib/entities/delegates/loader.d.ts.map +0 -1
  314. package/dist/src/lib/entities/destroy.d.ts +0 -4
  315. package/dist/src/lib/entities/destroy.d.ts.map +0 -1
  316. package/dist/src/lib/entities/entity-factory.d.ts +0 -10
  317. package/dist/src/lib/entities/entity-factory.d.ts.map +0 -1
  318. package/dist/src/lib/entities/entity.d.ts +0 -98
  319. package/dist/src/lib/entities/entity.d.ts.map +0 -1
  320. package/dist/src/lib/entities/index.d.ts +0 -12
  321. package/dist/src/lib/entities/index.d.ts.map +0 -1
  322. package/dist/src/lib/entities/plane.d.ts +0 -36
  323. package/dist/src/lib/entities/plane.d.ts.map +0 -1
  324. package/dist/src/lib/entities/rect.d.ts +0 -63
  325. package/dist/src/lib/entities/rect.d.ts.map +0 -1
  326. package/dist/src/lib/entities/sphere.d.ts +0 -29
  327. package/dist/src/lib/entities/sphere.d.ts.map +0 -1
  328. package/dist/src/lib/entities/sprite.d.ts +0 -54
  329. package/dist/src/lib/entities/sprite.d.ts.map +0 -1
  330. package/dist/src/lib/entities/text.d.ts +0 -49
  331. package/dist/src/lib/entities/text.d.ts.map +0 -1
  332. package/dist/src/lib/entities/zone.d.ts +0 -54
  333. package/dist/src/lib/entities/zone.d.ts.map +0 -1
  334. package/dist/src/lib/game/game-blueprint.d.ts +0 -38
  335. package/dist/src/lib/game/game-blueprint.d.ts.map +0 -1
  336. package/dist/src/lib/game/game-canvas.d.ts +0 -35
  337. package/dist/src/lib/game/game-canvas.d.ts.map +0 -1
  338. package/dist/src/lib/game/game-config.d.ts +0 -59
  339. package/dist/src/lib/game/game-config.d.ts.map +0 -1
  340. package/dist/src/lib/game/game-default.d.ts +0 -14
  341. package/dist/src/lib/game/game-default.d.ts.map +0 -1
  342. package/dist/src/lib/game/game-interfaces.d.ts +0 -29
  343. package/dist/src/lib/game/game-interfaces.d.ts.map +0 -1
  344. package/dist/src/lib/game/game-retro-resolutions.d.ts +0 -25
  345. package/dist/src/lib/game/game-retro-resolutions.d.ts.map +0 -1
  346. package/dist/src/lib/game/game-state.d.ts +0 -11
  347. package/dist/src/lib/game/game-state.d.ts.map +0 -1
  348. package/dist/src/lib/game/game.d.ts +0 -39
  349. package/dist/src/lib/game/game.d.ts.map +0 -1
  350. package/dist/src/lib/game/zylem-game.d.ts +0 -58
  351. package/dist/src/lib/game/zylem-game.d.ts.map +0 -1
  352. package/dist/src/lib/graphics/geometries/XZPlaneGeometry.d.ts +0 -8
  353. package/dist/src/lib/graphics/geometries/XZPlaneGeometry.d.ts.map +0 -1
  354. package/dist/src/lib/graphics/material.d.ts +0 -29
  355. package/dist/src/lib/graphics/material.d.ts.map +0 -1
  356. package/dist/src/lib/graphics/mesh.d.ts +0 -19
  357. package/dist/src/lib/graphics/mesh.d.ts.map +0 -1
  358. package/dist/src/lib/graphics/render-pass.d.ts +0 -17
  359. package/dist/src/lib/graphics/render-pass.d.ts.map +0 -1
  360. package/dist/src/lib/graphics/zylem-scene.d.ts +0 -50
  361. package/dist/src/lib/graphics/zylem-scene.d.ts.map +0 -1
  362. package/dist/src/lib/input/gamepad-provider.d.ts +0 -14
  363. package/dist/src/lib/input/gamepad-provider.d.ts.map +0 -1
  364. package/dist/src/lib/input/input-manager.d.ts +0 -15
  365. package/dist/src/lib/input/input-manager.d.ts.map +0 -1
  366. package/dist/src/lib/input/input-provider.d.ts +0 -7
  367. package/dist/src/lib/input/input-provider.d.ts.map +0 -1
  368. package/dist/src/lib/input/input.d.ts +0 -48
  369. package/dist/src/lib/input/input.d.ts.map +0 -1
  370. package/dist/src/lib/input/keyboard-provider.d.ts +0 -21
  371. package/dist/src/lib/input/keyboard-provider.d.ts.map +0 -1
  372. package/dist/src/lib/interfaces/entity.d.ts +0 -26
  373. package/dist/src/lib/interfaces/entity.d.ts.map +0 -1
  374. package/dist/src/lib/sounds/index.d.ts +0 -3
  375. package/dist/src/lib/sounds/index.d.ts.map +0 -1
  376. package/dist/src/lib/sounds/ping-pong-sound.d.ts +0 -5
  377. package/dist/src/lib/sounds/ping-pong-sound.d.ts.map +0 -1
  378. package/dist/src/lib/sounds/ricochet-sound.d.ts +0 -5
  379. package/dist/src/lib/sounds/ricochet-sound.d.ts.map +0 -1
  380. package/dist/src/lib/stage/debug-entity-cursor.d.ts +0 -24
  381. package/dist/src/lib/stage/debug-entity-cursor.d.ts.map +0 -1
  382. package/dist/src/lib/stage/entity-spawner.d.ts +0 -9
  383. package/dist/src/lib/stage/entity-spawner.d.ts.map +0 -1
  384. package/dist/src/lib/stage/stage-camera-debug-delegate.d.ts +0 -14
  385. package/dist/src/lib/stage/stage-camera-debug-delegate.d.ts.map +0 -1
  386. package/dist/src/lib/stage/stage-debug-delegate.d.ts +0 -26
  387. package/dist/src/lib/stage/stage-debug-delegate.d.ts.map +0 -1
  388. package/dist/src/lib/stage/stage-default.d.ts +0 -3
  389. package/dist/src/lib/stage/stage-default.d.ts.map +0 -1
  390. package/dist/src/lib/stage/stage-factory.d.ts +0 -6
  391. package/dist/src/lib/stage/stage-factory.d.ts.map +0 -1
  392. package/dist/src/lib/stage/stage-manager.d.ts +0 -30
  393. package/dist/src/lib/stage/stage-manager.d.ts.map +0 -1
  394. package/dist/src/lib/stage/stage-state.d.ts +0 -14
  395. package/dist/src/lib/stage/stage-state.d.ts.map +0 -1
  396. package/dist/src/lib/stage/stage.d.ts +0 -35
  397. package/dist/src/lib/stage/stage.d.ts.map +0 -1
  398. package/dist/src/lib/stage/zylem-stage.d.ts +0 -128
  399. package/dist/src/lib/stage/zylem-stage.d.ts.map +0 -1
  400. package/dist/src/lib/systems/test-system.d.ts +0 -2
  401. package/dist/src/lib/systems/test-system.d.ts.map +0 -1
  402. package/dist/src/lib/systems/transformable.system.d.ts +0 -25
  403. package/dist/src/lib/systems/transformable.system.d.ts.map +0 -1
  404. package/dist/src/lib/types/entity-types.d.ts +0 -24
  405. package/dist/src/lib/types/entity-types.d.ts.map +0 -1
  406. package/dist/src/lib/types/index.d.ts +0 -3
  407. package/dist/src/lib/types/index.d.ts.map +0 -1
  408. package/dist/src/lib/types/stage-types.d.ts +0 -26
  409. package/dist/src/lib/types/stage-types.d.ts.map +0 -1
  410. package/dist/src/lib/ui/Debug.d.ts +0 -6
  411. package/dist/src/lib/ui/Debug.d.ts.map +0 -1
  412. package/dist/src/lib/ui/console/Console.d.ts +0 -7
  413. package/dist/src/lib/ui/console/Console.d.ts.map +0 -1
  414. package/dist/src/lib/ui/debug-panel/AccordionMenu.d.ts +0 -7
  415. package/dist/src/lib/ui/debug-panel/AccordionMenu.d.ts.map +0 -1
  416. package/dist/src/lib/ui/debug-panel/Menu.d.ts +0 -6
  417. package/dist/src/lib/ui/debug-panel/Menu.d.ts.map +0 -1
  418. package/dist/src/lib/ui/debug-panel/sections/EntitiesSection.d.ts +0 -4
  419. package/dist/src/lib/ui/debug-panel/sections/EntitiesSection.d.ts.map +0 -1
  420. package/dist/src/lib/ui/debug-panel/sections/GameSection.d.ts +0 -3
  421. package/dist/src/lib/ui/debug-panel/sections/GameSection.d.ts.map +0 -1
  422. package/dist/src/lib/ui/debug-panel/sections/StagesSection.d.ts +0 -3
  423. package/dist/src/lib/ui/debug-panel/sections/StagesSection.d.ts.map +0 -1
  424. package/dist/src/lib/ui/debug-panel/sections/all.d.ts +0 -4
  425. package/dist/src/lib/ui/debug-panel/sections/all.d.ts.map +0 -1
  426. package/dist/src/lib/ui/toolbar/Toolbar.d.ts +0 -6
  427. package/dist/src/lib/ui/toolbar/Toolbar.d.ts.map +0 -1
  428. package/dist/tests/e2e/basic-game.spec.d.ts +0 -2
  429. package/dist/tests/e2e/basic-game.spec.d.ts.map +0 -1
  430. package/dist/tests/integration/debug.sim.spec.d.ts +0 -2
  431. package/dist/tests/integration/debug.sim.spec.d.ts.map +0 -1
  432. package/dist/tests/unit/collision/collision.spec.d.ts +0 -2
  433. package/dist/tests/unit/collision/collision.spec.d.ts.map +0 -1
  434. package/dist/tests/unit/core/base-node.spec.d.ts +0 -2
  435. package/dist/tests/unit/core/base-node.spec.d.ts.map +0 -1
  436. package/dist/tests/unit/core/game.spec.d.ts +0 -2
  437. package/dist/tests/unit/core/game.spec.d.ts.map +0 -1
  438. package/dist/tests/unit/core/stage.spec.d.ts +0 -2
  439. package/dist/tests/unit/core/stage.spec.d.ts.map +0 -1
  440. package/dist/tests/unit/core/vessel.spec.d.ts +0 -2
  441. package/dist/tests/unit/core/vessel.spec.d.ts.map +0 -1
package/dist/stage.js CHANGED
@@ -1,6 +1,2231 @@
1
- import { createStage as t } from "./lib/stage/stage.js";
2
- import { entitySpawner as a } from "./lib/stage/entity-spawner.js";
1
+ // src/lib/stage/zylem-stage.ts
2
+ import { addComponent, addEntity, createWorld as createECS, removeEntity } from "bitecs";
3
+ import { Color as Color6, Vector3 as Vector310, Vector2 as Vector25 } from "three";
4
+
5
+ // src/lib/collision/world.ts
6
+ import RAPIER from "@dimforge/rapier3d-compat";
7
+
8
+ // src/lib/game/game-state.ts
9
+ import { proxy, subscribe } from "valtio/vanilla";
10
+ var state = proxy({
11
+ id: "",
12
+ globals: {},
13
+ time: 0
14
+ });
15
+ function getGlobals() {
16
+ return state.globals;
17
+ }
18
+
19
+ // src/lib/entities/actor.ts
20
+ import { ActiveCollisionTypes, ColliderDesc } from "@dimforge/rapier3d-compat";
21
+ import { SkinnedMesh, Group as Group2, Vector3 } from "three";
22
+
23
+ // src/lib/entities/entity.ts
24
+ import { ShaderMaterial } from "three";
25
+
26
+ // src/lib/systems/transformable.system.ts
27
+ import {
28
+ defineSystem,
29
+ defineQuery,
30
+ defineComponent,
31
+ Types
32
+ } from "bitecs";
33
+ import { Quaternion } from "three";
34
+ var position = defineComponent({
35
+ x: Types.f32,
36
+ y: Types.f32,
37
+ z: Types.f32
38
+ });
39
+ var rotation = defineComponent({
40
+ x: Types.f32,
41
+ y: Types.f32,
42
+ z: Types.f32,
43
+ w: Types.f32
44
+ });
45
+ var scale = defineComponent({
46
+ x: Types.f32,
47
+ y: Types.f32,
48
+ z: Types.f32
49
+ });
50
+ function createTransformSystem(stage) {
51
+ const transformQuery = defineQuery([position, rotation]);
52
+ const stageEntities = stage._childrenMap;
53
+ return defineSystem((world) => {
54
+ const entities = transformQuery(world);
55
+ if (stageEntities === void 0) {
56
+ return world;
57
+ }
58
+ ;
59
+ for (const [key, value] of stageEntities) {
60
+ const id = entities[key];
61
+ const stageEntity = value;
62
+ if (stageEntity === void 0 || !stageEntity?.body || stageEntity.markedForRemoval) {
63
+ continue;
64
+ }
65
+ const { x, y, z } = stageEntity.body.translation();
66
+ position.x[id] = x;
67
+ position.y[id] = y;
68
+ position.z[id] = z;
69
+ if (stageEntity.group) {
70
+ stageEntity.group.position.set(position.x[id], position.y[id], position.z[id]);
71
+ } else if (stageEntity.mesh) {
72
+ stageEntity.mesh.position.set(position.x[id], position.y[id], position.z[id]);
73
+ }
74
+ if (stageEntity.controlledRotation) {
75
+ continue;
76
+ }
77
+ const { x: rx, y: ry, z: rz, w: rw } = stageEntity.body.rotation();
78
+ rotation.x[id] = rx;
79
+ rotation.y[id] = ry;
80
+ rotation.z[id] = rz;
81
+ rotation.w[id] = rw;
82
+ const newRotation = new Quaternion(
83
+ rotation.x[id],
84
+ rotation.y[id],
85
+ rotation.z[id],
86
+ rotation.w[id]
87
+ );
88
+ if (stageEntity.group) {
89
+ stageEntity.group.setRotationFromQuaternion(newRotation);
90
+ } else if (stageEntity.mesh) {
91
+ stageEntity.mesh.setRotationFromQuaternion(newRotation);
92
+ }
93
+ }
94
+ return world;
95
+ });
96
+ }
97
+
98
+ // src/lib/core/flags.ts
99
+ var DEBUG_FLAG = import.meta.env.VITE_DEBUG_FLAG === "true";
100
+
101
+ // src/lib/core/base-node.ts
102
+ import { nanoid } from "nanoid";
103
+ var BaseNode = class _BaseNode {
104
+ parent = null;
105
+ children = [];
106
+ options;
107
+ eid = 0;
108
+ uuid = "";
109
+ name = "";
110
+ markedForRemoval = false;
111
+ setup = () => {
112
+ };
113
+ loaded = () => {
114
+ };
115
+ update = () => {
116
+ };
117
+ destroy = () => {
118
+ };
119
+ cleanup = () => {
120
+ };
121
+ constructor(args = []) {
122
+ const options = args.filter((arg) => !(arg instanceof _BaseNode)).reduce((acc, opt) => ({ ...acc, ...opt }), {});
123
+ this.options = options;
124
+ this.uuid = nanoid();
125
+ }
126
+ setParent(parent) {
127
+ this.parent = parent;
128
+ }
129
+ getParent() {
130
+ return this.parent;
131
+ }
132
+ add(baseNode) {
133
+ this.children.push(baseNode);
134
+ baseNode.setParent(this);
135
+ }
136
+ remove(baseNode) {
137
+ const index = this.children.indexOf(baseNode);
138
+ if (index !== -1) {
139
+ this.children.splice(index, 1);
140
+ baseNode.setParent(null);
141
+ }
142
+ }
143
+ getChildren() {
144
+ return this.children;
145
+ }
146
+ isComposite() {
147
+ return this.children.length > 0;
148
+ }
149
+ nodeSetup(params) {
150
+ if (DEBUG_FLAG) {
151
+ }
152
+ this.markedForRemoval = false;
153
+ if (typeof this._setup === "function") {
154
+ this._setup(params);
155
+ }
156
+ if (this.setup) {
157
+ this.setup(params);
158
+ }
159
+ this.children.forEach((child) => child.nodeSetup(params));
160
+ }
161
+ nodeUpdate(params) {
162
+ if (this.markedForRemoval) {
163
+ return;
164
+ }
165
+ if (typeof this._update === "function") {
166
+ this._update(params);
167
+ }
168
+ if (this.update) {
169
+ this.update(params);
170
+ }
171
+ this.children.forEach((child) => child.nodeUpdate(params));
172
+ }
173
+ nodeDestroy(params) {
174
+ this.children.forEach((child) => child.nodeDestroy(params));
175
+ if (this.destroy) {
176
+ this.destroy(params);
177
+ }
178
+ if (typeof this._destroy === "function") {
179
+ this._destroy(params);
180
+ }
181
+ this.markedForRemoval = true;
182
+ }
183
+ getOptions() {
184
+ return this.options;
185
+ }
186
+ setOptions(options) {
187
+ this.options = { ...this.options, ...options };
188
+ }
189
+ };
190
+
191
+ // src/lib/entities/entity.ts
192
+ var GameEntity = class extends BaseNode {
193
+ behaviors = [];
194
+ group;
195
+ mesh;
196
+ materials;
197
+ bodyDesc = null;
198
+ body = null;
199
+ colliderDesc;
200
+ collider;
201
+ custom = {};
202
+ debugInfo = {};
203
+ debugMaterial;
204
+ lifeCycleDelegate = {
205
+ setup: [],
206
+ update: [],
207
+ destroy: []
208
+ };
209
+ collisionDelegate = {
210
+ collision: []
211
+ };
212
+ collisionType;
213
+ behaviorCallbackMap = {
214
+ setup: [],
215
+ update: [],
216
+ destroy: [],
217
+ collision: []
218
+ };
219
+ constructor() {
220
+ super();
221
+ }
222
+ create() {
223
+ const { position: setupPosition } = this.options;
224
+ const { x, y, z } = setupPosition || { x: 0, y: 0, z: 0 };
225
+ this.behaviors = [
226
+ { component: position, values: { x, y, z } },
227
+ { component: scale, values: { x: 0, y: 0, z: 0 } },
228
+ { component: rotation, values: { x: 0, y: 0, z: 0, w: 0 } }
229
+ ];
230
+ this.name = this.options.name || "";
231
+ return this;
232
+ }
233
+ onSetup(...callbacks) {
234
+ const combineCallbacks = [...this.lifeCycleDelegate.setup ?? [], ...callbacks];
235
+ this.lifeCycleDelegate = {
236
+ ...this.lifeCycleDelegate,
237
+ setup: combineCallbacks
238
+ };
239
+ return this;
240
+ }
241
+ onUpdate(...callbacks) {
242
+ const combineCallbacks = [...this.lifeCycleDelegate.update ?? [], ...callbacks];
243
+ this.lifeCycleDelegate = {
244
+ ...this.lifeCycleDelegate,
245
+ update: combineCallbacks
246
+ };
247
+ return this;
248
+ }
249
+ onDestroy(...callbacks) {
250
+ this.lifeCycleDelegate = {
251
+ ...this.lifeCycleDelegate,
252
+ destroy: callbacks.length > 0 ? callbacks : void 0
253
+ };
254
+ return this;
255
+ }
256
+ onCollision(...callbacks) {
257
+ this.collisionDelegate = {
258
+ collision: callbacks.length > 0 ? callbacks : void 0
259
+ };
260
+ return this;
261
+ }
262
+ _setup(params) {
263
+ this.behaviorCallbackMap.setup.forEach((callback) => {
264
+ callback({ ...params, me: this });
265
+ });
266
+ if (this.lifeCycleDelegate.setup?.length) {
267
+ const callbacks = this.lifeCycleDelegate.setup;
268
+ callbacks.forEach((callback) => {
269
+ callback({ ...params, me: this });
270
+ });
271
+ }
272
+ }
273
+ async _loaded(_params) {
274
+ }
275
+ _update(params) {
276
+ this.updateMaterials(params);
277
+ if (this.lifeCycleDelegate.update?.length) {
278
+ const callbacks = this.lifeCycleDelegate.update;
279
+ callbacks.forEach((callback) => {
280
+ callback({ ...params, me: this });
281
+ });
282
+ }
283
+ this.behaviorCallbackMap.update.forEach((callback) => {
284
+ callback({ ...params, me: this });
285
+ });
286
+ }
287
+ _destroy(params) {
288
+ if (this.lifeCycleDelegate.destroy?.length) {
289
+ const callbacks = this.lifeCycleDelegate.destroy;
290
+ callbacks.forEach((callback) => {
291
+ callback({ ...params, me: this });
292
+ });
293
+ }
294
+ this.behaviorCallbackMap.destroy.forEach((callback) => {
295
+ callback({ ...params, me: this });
296
+ });
297
+ }
298
+ async _cleanup(_params) {
299
+ }
300
+ _collision(other, globals) {
301
+ if (this.collisionDelegate.collision?.length) {
302
+ const callbacks = this.collisionDelegate.collision;
303
+ callbacks.forEach((callback) => {
304
+ callback({ entity: this, other, globals });
305
+ });
306
+ }
307
+ this.behaviorCallbackMap.collision.forEach((callback) => {
308
+ callback({ entity: this, other, globals });
309
+ });
310
+ }
311
+ addBehavior(behaviorCallback) {
312
+ const handler = behaviorCallback.handler;
313
+ if (handler) {
314
+ this.behaviorCallbackMap[behaviorCallback.type].push(handler);
315
+ }
316
+ return this;
317
+ }
318
+ addBehaviors(behaviorCallbacks) {
319
+ behaviorCallbacks.forEach((callback) => {
320
+ const handler = callback.handler;
321
+ if (handler) {
322
+ this.behaviorCallbackMap[callback.type].push(handler);
323
+ }
324
+ });
325
+ return this;
326
+ }
327
+ updateMaterials(params) {
328
+ if (!this.materials?.length) {
329
+ return;
330
+ }
331
+ for (const material of this.materials) {
332
+ if (material instanceof ShaderMaterial) {
333
+ if (material.uniforms) {
334
+ material.uniforms.iTime && (material.uniforms.iTime.value += params.delta);
335
+ }
336
+ }
337
+ }
338
+ }
339
+ buildInfo() {
340
+ const info = {};
341
+ info.name = this.name;
342
+ info.uuid = this.uuid;
343
+ info.eid = this.eid.toString();
344
+ return info;
345
+ }
346
+ };
347
+
348
+ // src/lib/core/entity-asset-loader.ts
349
+ import { FBXLoader } from "three/addons/loaders/FBXLoader.js";
350
+ import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
351
+ var FBXAssetLoader = class {
352
+ loader = new FBXLoader();
353
+ isSupported(file) {
354
+ return file.toLowerCase().endsWith("fbx" /* FBX */);
355
+ }
356
+ async load(file) {
357
+ return new Promise((resolve, reject) => {
358
+ this.loader.load(
359
+ file,
360
+ (object) => {
361
+ const animation = object.animations[0];
362
+ resolve({
363
+ object,
364
+ animation
365
+ });
366
+ },
367
+ void 0,
368
+ reject
369
+ );
370
+ });
371
+ }
372
+ };
373
+ var GLTFAssetLoader = class {
374
+ loader = new GLTFLoader();
375
+ isSupported(file) {
376
+ return file.toLowerCase().endsWith("gltf" /* GLTF */);
377
+ }
378
+ async load(file) {
379
+ return new Promise((resolve, reject) => {
380
+ this.loader.load(
381
+ file,
382
+ (gltf) => {
383
+ resolve({
384
+ object: gltf.scene,
385
+ gltf
386
+ });
387
+ },
388
+ void 0,
389
+ reject
390
+ );
391
+ });
392
+ }
393
+ };
394
+ var EntityAssetLoader = class {
395
+ loaders = [
396
+ new FBXAssetLoader(),
397
+ new GLTFAssetLoader()
398
+ ];
399
+ async loadFile(file) {
400
+ const loader = this.loaders.find((l) => l.isSupported(file));
401
+ if (!loader) {
402
+ throw new Error(`Unsupported file type: ${file}`);
403
+ }
404
+ return loader.load(file);
405
+ }
406
+ };
407
+
408
+ // src/lib/entities/delegates/animation.ts
409
+ import {
410
+ AnimationMixer,
411
+ LoopOnce,
412
+ LoopRepeat
413
+ } from "three";
414
+ var AnimationDelegate = class {
415
+ constructor(target) {
416
+ this.target = target;
417
+ }
418
+ _mixer = null;
419
+ _actions = {};
420
+ _animations = [];
421
+ _currentAction = null;
422
+ _pauseAtPercentage = 0;
423
+ _isPaused = false;
424
+ _queuedKey = null;
425
+ _fadeDuration = 0.5;
426
+ _currentKey = "";
427
+ _assetLoader = new EntityAssetLoader();
428
+ async loadAnimations(animations) {
429
+ if (!animations.length) return;
430
+ const results = await Promise.all(animations.map((a) => this._assetLoader.loadFile(a.path)));
431
+ this._animations = results.filter((r) => !!r.animation).map((r) => r.animation);
432
+ if (!this._animations.length) return;
433
+ this._mixer = new AnimationMixer(this.target);
434
+ this._animations.forEach((clip, i) => {
435
+ const key = animations[i].key || i.toString();
436
+ this._actions[key] = this._mixer.clipAction(clip);
437
+ });
438
+ this.playAnimation({ key: Object.keys(this._actions)[0] });
439
+ }
440
+ update(delta) {
441
+ if (!this._mixer || !this._currentAction) return;
442
+ this._mixer.update(delta);
443
+ const pauseAtTime = this._currentAction.getClip().duration * (this._pauseAtPercentage / 100);
444
+ if (!this._isPaused && this._pauseAtPercentage > 0 && this._currentAction.time >= pauseAtTime) {
445
+ this._currentAction.time = pauseAtTime;
446
+ this._currentAction.paused = true;
447
+ this._isPaused = true;
448
+ if (this._queuedKey !== null) {
449
+ const next = this._actions[this._queuedKey];
450
+ next.reset().play();
451
+ this._currentAction.crossFadeTo(next, this._fadeDuration, false);
452
+ this._currentAction = next;
453
+ this._currentKey = this._queuedKey;
454
+ this._queuedKey = null;
455
+ }
456
+ }
457
+ }
458
+ playAnimation(opts) {
459
+ if (!this._mixer) return;
460
+ const { key, pauseAtPercentage = 0, pauseAtEnd = false, fadeToKey, fadeDuration = 0.5 } = opts;
461
+ if (key === this._currentKey) return;
462
+ this._queuedKey = fadeToKey || null;
463
+ this._fadeDuration = fadeDuration;
464
+ this._pauseAtPercentage = pauseAtEnd ? 100 : pauseAtPercentage;
465
+ this._isPaused = false;
466
+ const prev = this._currentAction;
467
+ if (prev) prev.stop();
468
+ const action = this._actions[key];
469
+ if (!action) return;
470
+ if (this._pauseAtPercentage > 0) {
471
+ action.setLoop(LoopOnce, Infinity);
472
+ action.clampWhenFinished = true;
473
+ } else {
474
+ action.setLoop(LoopRepeat, Infinity);
475
+ action.clampWhenFinished = false;
476
+ }
477
+ if (prev) {
478
+ prev.crossFadeTo(action, fadeDuration, false);
479
+ }
480
+ action.reset().play();
481
+ this._currentAction = action;
482
+ this._currentKey = key;
483
+ }
484
+ get currentAnimationKey() {
485
+ return this._currentKey;
486
+ }
487
+ get animations() {
488
+ return this._animations;
489
+ }
490
+ };
491
+
492
+ // src/lib/graphics/shaders/fragment/standard.glsl
493
+ var standard_default = "uniform sampler2D tDiffuse;\nvarying vec2 vUv;\n\nvoid main() {\n vec4 texel = texture2D( tDiffuse, vUv );\n\n gl_FragColor = texel;\n}";
494
+
495
+ // src/lib/entities/actor.ts
496
+ var actorDefaults = {
497
+ position: { x: 0, y: 0, z: 0 },
498
+ collision: {
499
+ static: false,
500
+ size: new Vector3(0.5, 0.5, 0.5),
501
+ position: new Vector3(0, 0, 0)
502
+ },
503
+ material: {
504
+ shader: "standard"
505
+ },
506
+ animations: [],
507
+ models: []
508
+ };
509
+ var ACTOR_TYPE = Symbol("Actor");
510
+ var ZylemActor = class extends GameEntity {
511
+ static type = ACTOR_TYPE;
512
+ _object = null;
513
+ _animationDelegate = null;
514
+ _modelFileNames = [];
515
+ _assetLoader = new EntityAssetLoader();
516
+ controlledRotation = false;
517
+ constructor(options) {
518
+ super();
519
+ this.options = { ...actorDefaults, ...options };
520
+ this.lifeCycleDelegate = {
521
+ update: [this.actorUpdate.bind(this)]
522
+ };
523
+ this.controlledRotation = true;
524
+ }
525
+ async load() {
526
+ this._modelFileNames = this.options.models || [];
527
+ await this.loadModels();
528
+ if (this._object) {
529
+ this._animationDelegate = new AnimationDelegate(this._object);
530
+ await this._animationDelegate.loadAnimations(this.options.animations || []);
531
+ }
532
+ }
533
+ async data() {
534
+ return {
535
+ animations: this._animationDelegate?.animations,
536
+ objectModel: this._object
537
+ };
538
+ }
539
+ async actorUpdate(params) {
540
+ this._animationDelegate?.update(params.delta);
541
+ }
542
+ async loadModels() {
543
+ if (this._modelFileNames.length === 0) return;
544
+ const promises = this._modelFileNames.map((file) => this._assetLoader.loadFile(file));
545
+ const results = await Promise.all(promises);
546
+ if (results[0]?.object) {
547
+ this._object = results[0].object;
548
+ }
549
+ if (this._object) {
550
+ this.group = new Group2();
551
+ this.group.attach(this._object);
552
+ this.group.scale.set(
553
+ this.options.scale?.x || 1,
554
+ this.options.scale?.y || 1,
555
+ this.options.scale?.z || 1
556
+ );
557
+ }
558
+ }
559
+ playAnimation(animationOptions) {
560
+ this._animationDelegate?.playAnimation(animationOptions);
561
+ }
562
+ get object() {
563
+ return this._object;
564
+ }
565
+ /**
566
+ * Provide custom debug information for the actor
567
+ * This will be merged with the default debug information
568
+ */
569
+ getDebugInfo() {
570
+ const debugInfo = {
571
+ type: "Actor",
572
+ models: this._modelFileNames.length > 0 ? this._modelFileNames : "none",
573
+ modelLoaded: !!this._object,
574
+ scale: this.options.scale ? `${this.options.scale.x}, ${this.options.scale.y}, ${this.options.scale.z}` : "1, 1, 1"
575
+ };
576
+ if (this._animationDelegate) {
577
+ debugInfo.currentAnimation = this._animationDelegate.currentAnimationKey || "none";
578
+ debugInfo.animationsCount = this.options.animations?.length || 0;
579
+ }
580
+ if (this._object) {
581
+ let meshCount = 0;
582
+ let vertexCount = 0;
583
+ this._object.traverse((child) => {
584
+ if (child.isMesh) {
585
+ meshCount++;
586
+ const geometry = child.geometry;
587
+ if (geometry && geometry.attributes.position) {
588
+ vertexCount += geometry.attributes.position.count;
589
+ }
590
+ }
591
+ });
592
+ debugInfo.meshCount = meshCount;
593
+ debugInfo.vertexCount = vertexCount;
594
+ }
595
+ return debugInfo;
596
+ }
597
+ };
598
+
599
+ // src/lib/collision/collision-delegate.ts
600
+ function isCollisionHandlerDelegate(obj) {
601
+ return typeof obj?.handlePostCollision === "function" && typeof obj?.handleIntersectionEvent === "function";
602
+ }
603
+
604
+ // src/lib/collision/world.ts
605
+ var ZylemWorld = class {
606
+ type = "World";
607
+ world;
608
+ collisionMap = /* @__PURE__ */ new Map();
609
+ collisionBehaviorMap = /* @__PURE__ */ new Map();
610
+ _removalMap = /* @__PURE__ */ new Map();
611
+ static async loadPhysics(gravity) {
612
+ await RAPIER.init();
613
+ const physicsWorld = new RAPIER.World(gravity);
614
+ return physicsWorld;
615
+ }
616
+ constructor(world) {
617
+ this.world = world;
618
+ }
619
+ addEntity(entity) {
620
+ const rigidBody = this.world.createRigidBody(entity.bodyDesc);
621
+ entity.body = rigidBody;
622
+ entity.body.userData = { uuid: entity.uuid, ref: entity };
623
+ if (this.world.gravity.x === 0 && this.world.gravity.y === 0 && this.world.gravity.z === 0) {
624
+ entity.body.lockTranslations(true, true);
625
+ entity.body.lockRotations(true, true);
626
+ }
627
+ const collider = this.world.createCollider(entity.colliderDesc, entity.body);
628
+ entity.collider = collider;
629
+ if (entity.controlledRotation || entity instanceof ZylemActor) {
630
+ entity.body.lockRotations(true, true);
631
+ entity.characterController = this.world.createCharacterController(0.01);
632
+ entity.characterController.setMaxSlopeClimbAngle(45 * Math.PI / 180);
633
+ entity.characterController.setMinSlopeSlideAngle(30 * Math.PI / 180);
634
+ entity.characterController.enableSnapToGround(0.01);
635
+ entity.characterController.setSlideEnabled(true);
636
+ entity.characterController.setApplyImpulsesToDynamicBodies(true);
637
+ entity.characterController.setCharacterMass(1);
638
+ }
639
+ this.collisionMap.set(entity.uuid, entity);
640
+ }
641
+ setForRemoval(entity) {
642
+ if (entity.body) {
643
+ this._removalMap.set(entity.uuid, entity);
644
+ }
645
+ }
646
+ destroyEntity(entity) {
647
+ if (entity.collider) {
648
+ this.world.removeCollider(entity.collider, true);
649
+ }
650
+ if (entity.body) {
651
+ this.world.removeRigidBody(entity.body);
652
+ this.collisionMap.delete(entity.uuid);
653
+ this._removalMap.delete(entity.uuid);
654
+ }
655
+ }
656
+ setup() {
657
+ }
658
+ update(params) {
659
+ const { delta } = params;
660
+ if (!this.world) {
661
+ return;
662
+ }
663
+ this.updateColliders(delta);
664
+ this.updatePostCollisionBehaviors(delta);
665
+ this.world.step();
666
+ }
667
+ updatePostCollisionBehaviors(delta) {
668
+ const dictionaryRef = this.collisionBehaviorMap;
669
+ for (let [id, collider] of dictionaryRef) {
670
+ const gameEntity = collider;
671
+ if (!isCollisionHandlerDelegate(gameEntity)) {
672
+ return;
673
+ }
674
+ const active = gameEntity.handlePostCollision({ entity: gameEntity, delta });
675
+ if (!active) {
676
+ this.collisionBehaviorMap.delete(id);
677
+ }
678
+ }
679
+ }
680
+ updateColliders(delta) {
681
+ const dictionaryRef = this.collisionMap;
682
+ for (let [id, collider] of dictionaryRef) {
683
+ const gameEntity = collider;
684
+ if (!gameEntity.body) {
685
+ continue;
686
+ }
687
+ if (this._removalMap.get(gameEntity.uuid)) {
688
+ this.destroyEntity(gameEntity);
689
+ continue;
690
+ }
691
+ this.world.contactsWith(gameEntity.body.collider(0), (otherCollider) => {
692
+ const uuid = otherCollider._parent.userData.uuid;
693
+ const entity = dictionaryRef.get(uuid);
694
+ if (!entity) {
695
+ return;
696
+ }
697
+ if (gameEntity._collision) {
698
+ gameEntity._collision(entity, state.globals);
699
+ }
700
+ });
701
+ this.world.intersectionsWith(gameEntity.body.collider(0), (otherCollider) => {
702
+ const uuid = otherCollider._parent.userData.uuid;
703
+ const entity = dictionaryRef.get(uuid);
704
+ if (!entity) {
705
+ return;
706
+ }
707
+ if (gameEntity._collision) {
708
+ gameEntity._collision(entity, state.globals);
709
+ }
710
+ if (isCollisionHandlerDelegate(entity)) {
711
+ entity.handleIntersectionEvent({ entity, other: gameEntity, delta });
712
+ this.collisionBehaviorMap.set(uuid, entity);
713
+ }
714
+ });
715
+ }
716
+ }
717
+ destroy() {
718
+ try {
719
+ for (const [, entity] of this.collisionMap) {
720
+ try {
721
+ this.destroyEntity(entity);
722
+ } catch {
723
+ }
724
+ }
725
+ this.collisionMap.clear();
726
+ this.collisionBehaviorMap.clear();
727
+ this._removalMap.clear();
728
+ this.world = void 0;
729
+ } catch {
730
+ }
731
+ }
732
+ };
733
+
734
+ // src/lib/graphics/zylem-scene.ts
735
+ import {
736
+ Scene,
737
+ Color as Color2,
738
+ AmbientLight,
739
+ DirectionalLight,
740
+ Vector3 as Vector32,
741
+ TextureLoader,
742
+ GridHelper
743
+ } from "three";
744
+
745
+ // src/lib/debug/debug-state.ts
746
+ import { proxy as proxy2 } from "valtio";
747
+ var debugState = proxy2({
748
+ enabled: false,
749
+ paused: false,
750
+ tool: "none",
751
+ selectedEntity: null,
752
+ hoveredEntity: null,
753
+ flags: /* @__PURE__ */ new Set()
754
+ });
755
+ function getDebugTool() {
756
+ return debugState.tool;
757
+ }
758
+ function setSelectedEntity(entity) {
759
+ debugState.selectedEntity = entity;
760
+ }
761
+ function getHoveredEntity() {
762
+ return debugState.hoveredEntity;
763
+ }
764
+ function setHoveredEntity(entity) {
765
+ debugState.hoveredEntity = entity;
766
+ }
767
+ function resetHoveredEntity() {
768
+ debugState.hoveredEntity = null;
769
+ }
770
+
771
+ // src/lib/graphics/zylem-scene.ts
772
+ var ZylemScene = class {
773
+ type = "Scene";
774
+ _setup;
775
+ scene;
776
+ zylemCamera;
777
+ containerElement = null;
778
+ update = () => {
779
+ };
780
+ _collision;
781
+ _destroy;
782
+ name;
783
+ tag;
784
+ constructor(id, camera, state2) {
785
+ const scene = new Scene();
786
+ const isColor = state2.backgroundColor instanceof Color2;
787
+ const backgroundColor = isColor ? state2.backgroundColor : new Color2(state2.backgroundColor);
788
+ scene.background = backgroundColor;
789
+ if (state2.backgroundImage) {
790
+ const loader = new TextureLoader();
791
+ const texture = loader.load(state2.backgroundImage);
792
+ scene.background = texture;
793
+ }
794
+ this.scene = scene;
795
+ this.zylemCamera = camera;
796
+ this.setupLighting(scene);
797
+ this.setupCamera(scene, camera);
798
+ if (debugState.enabled) {
799
+ this.debugScene();
800
+ }
801
+ }
802
+ setup() {
803
+ if (this._setup) {
804
+ this._setup({ me: this, camera: this.zylemCamera, globals: getGlobals() });
805
+ }
806
+ }
807
+ destroy() {
808
+ if (this.zylemCamera && this.zylemCamera.destroy) {
809
+ this.zylemCamera.destroy();
810
+ }
811
+ if (this.scene) {
812
+ this.scene.traverse((obj) => {
813
+ if (obj.geometry) {
814
+ obj.geometry.dispose?.();
815
+ }
816
+ if (obj.material) {
817
+ if (Array.isArray(obj.material)) {
818
+ obj.material.forEach((m) => m.dispose?.());
819
+ } else {
820
+ obj.material.dispose?.();
821
+ }
822
+ }
823
+ });
824
+ }
825
+ }
826
+ /**
827
+ * Setup camera with the scene
828
+ */
829
+ setupCamera(scene, camera) {
830
+ scene.add(camera.cameraRig);
831
+ camera.setup(scene);
832
+ }
833
+ /**
834
+ * Setup scene lighting
835
+ */
836
+ setupLighting(scene) {
837
+ const ambientLight = new AmbientLight(16777215, 2);
838
+ scene.add(ambientLight);
839
+ const directionalLight = new DirectionalLight(16777215, 2);
840
+ directionalLight.name = "Light";
841
+ directionalLight.position.set(0, 100, 0);
842
+ directionalLight.castShadow = true;
843
+ directionalLight.shadow.camera.near = 0.1;
844
+ directionalLight.shadow.camera.far = 2e3;
845
+ directionalLight.shadow.camera.left = -100;
846
+ directionalLight.shadow.camera.right = 100;
847
+ directionalLight.shadow.camera.top = 100;
848
+ directionalLight.shadow.camera.bottom = -100;
849
+ directionalLight.shadow.mapSize.width = 2048;
850
+ directionalLight.shadow.mapSize.height = 2048;
851
+ scene.add(directionalLight);
852
+ }
853
+ /**
854
+ * Update renderer size - delegates to camera
855
+ */
856
+ updateRenderer(width, height) {
857
+ this.zylemCamera.resize(width, height);
858
+ }
859
+ /**
860
+ * Add object to scene
861
+ */
862
+ add(object, position2 = new Vector32(0, 0, 0)) {
863
+ object.position.set(position2.x, position2.y, position2.z);
864
+ this.scene.add(object);
865
+ }
866
+ /**
867
+ * Add game entity to scene
868
+ */
869
+ addEntity(entity) {
870
+ if (entity.group) {
871
+ this.add(entity.group, entity.options.position);
872
+ } else if (entity.mesh) {
873
+ this.add(entity.mesh, entity.options.position);
874
+ }
875
+ }
876
+ /**
877
+ * Add debug helpers to scene
878
+ */
879
+ debugScene() {
880
+ const size = 1e3;
881
+ const divisions = 100;
882
+ const gridHelper = new GridHelper(size, divisions);
883
+ this.scene.add(gridHelper);
884
+ }
885
+ };
886
+
887
+ // src/lib/stage/stage-state.ts
888
+ import { Color as Color3, Vector3 as Vector33 } from "three";
889
+ import { proxy as proxy3, subscribe as subscribe2 } from "valtio/vanilla";
890
+ var stageState = proxy3({
891
+ backgroundColor: new Color3(Color3.NAMES.cornflowerblue),
892
+ backgroundImage: null,
893
+ inputs: {
894
+ p1: ["gamepad-1", "keyboard-1"],
895
+ p2: ["gamepad-2", "keyboard-2"]
896
+ },
897
+ variables: {},
898
+ gravity: new Vector33(0, 0, 0),
899
+ entities: []
900
+ });
901
+ var setStageBackgroundColor = (value) => {
902
+ stageState.backgroundColor = value;
903
+ };
904
+ var setStageBackgroundImage = (value) => {
905
+ stageState.backgroundImage = value;
906
+ };
907
+ var setStageVariables = (variables) => {
908
+ stageState.variables = { ...variables };
909
+ };
910
+ var resetStageVariables = () => {
911
+ stageState.variables = {};
912
+ };
913
+ var variableProxyStore = /* @__PURE__ */ new Map();
914
+ function clearVariables(target) {
915
+ variableProxyStore.delete(target);
916
+ }
917
+
918
+ // src/lib/core/utility/vector.ts
919
+ import { Color as Color4 } from "three";
920
+ import { Vector3 as Vector34 } from "@dimforge/rapier3d-compat";
921
+ var ZylemBlueColor = new Color4("#0333EC");
922
+ var Vec0 = new Vector34(0, 0, 0);
923
+ var Vec1 = new Vector34(1, 1, 1);
924
+
925
+ // src/lib/core/lifecycle-base.ts
926
+ var LifeCycleBase = class {
927
+ update = () => {
928
+ };
929
+ setup = () => {
930
+ };
931
+ destroy = () => {
932
+ };
933
+ nodeSetup(context) {
934
+ if (typeof this._setup === "function") {
935
+ this._setup(context);
936
+ }
937
+ if (this.setup) {
938
+ this.setup(context);
939
+ }
940
+ }
941
+ nodeUpdate(context) {
942
+ if (typeof this._update === "function") {
943
+ this._update(context);
944
+ }
945
+ if (this.update) {
946
+ this.update(context);
947
+ }
948
+ }
949
+ nodeDestroy(context) {
950
+ if (this.destroy) {
951
+ this.destroy(context);
952
+ }
953
+ if (typeof this._destroy === "function") {
954
+ this._destroy(context);
955
+ }
956
+ }
957
+ };
958
+
959
+ // src/lib/stage/zylem-stage.ts
960
+ import { nanoid as nanoid2 } from "nanoid";
961
+
962
+ // src/lib/camera/perspective.ts
963
+ var Perspectives = {
964
+ FirstPerson: "first-person",
965
+ ThirdPerson: "third-person",
966
+ Isometric: "isometric",
967
+ Flat2D: "flat-2d",
968
+ Fixed2D: "fixed-2d"
969
+ };
970
+
971
+ // src/lib/camera/camera.ts
972
+ import { Vector2 as Vector23, Vector3 as Vector37 } from "three";
973
+
974
+ // src/lib/camera/zylem-camera.ts
975
+ import { PerspectiveCamera, Vector3 as Vector36, Object3D as Object3D4, OrthographicCamera, WebGLRenderer as WebGLRenderer3 } from "three";
976
+ import { OrbitControls } from "three/addons/controls/OrbitControls.js";
977
+
978
+ // src/lib/camera/third-person.ts
979
+ import { Vector3 as Vector35 } from "three";
980
+ var ThirdPersonCamera = class {
981
+ distance;
982
+ screenResolution = null;
983
+ renderer = null;
984
+ scene = null;
985
+ cameraRef = null;
986
+ constructor() {
987
+ this.distance = new Vector35(0, 5, 8);
988
+ }
989
+ /**
990
+ * Setup the third person camera controller
991
+ */
992
+ setup(params) {
993
+ const { screenResolution, renderer, scene, camera } = params;
994
+ this.screenResolution = screenResolution;
995
+ this.renderer = renderer;
996
+ this.scene = scene;
997
+ this.cameraRef = camera;
998
+ }
999
+ /**
1000
+ * Update the third person camera
1001
+ */
1002
+ update(delta) {
1003
+ if (!this.cameraRef.target) {
1004
+ return;
1005
+ }
1006
+ const desiredCameraPosition = this.cameraRef.target.group.position.clone().add(this.distance);
1007
+ this.cameraRef.camera.position.lerp(desiredCameraPosition, 0.1);
1008
+ this.cameraRef.camera.lookAt(this.cameraRef.target.group.position);
1009
+ }
1010
+ /**
1011
+ * Handle resize events
1012
+ */
1013
+ resize(width, height) {
1014
+ if (this.screenResolution) {
1015
+ this.screenResolution.set(width, height);
1016
+ }
1017
+ }
1018
+ /**
1019
+ * Set the distance from the target
1020
+ */
1021
+ setDistance(distance) {
1022
+ this.distance = distance;
1023
+ }
1024
+ };
1025
+
1026
+ // src/lib/camera/fixed-2d.ts
1027
+ var Fixed2DCamera = class {
1028
+ screenResolution = null;
1029
+ renderer = null;
1030
+ scene = null;
1031
+ cameraRef = null;
1032
+ constructor() {
1033
+ }
1034
+ /**
1035
+ * Setup the fixed 2D camera controller
1036
+ */
1037
+ setup(params) {
1038
+ const { screenResolution, renderer, scene, camera } = params;
1039
+ this.screenResolution = screenResolution;
1040
+ this.renderer = renderer;
1041
+ this.scene = scene;
1042
+ this.cameraRef = camera;
1043
+ this.cameraRef.camera.position.set(0, 0, 10);
1044
+ this.cameraRef.camera.lookAt(0, 0, 0);
1045
+ }
1046
+ /**
1047
+ * Update the fixed 2D camera
1048
+ * Fixed cameras don't need to update position/rotation automatically
1049
+ */
1050
+ update(delta) {
1051
+ }
1052
+ /**
1053
+ * Handle resize events for 2D camera
1054
+ */
1055
+ resize(width, height) {
1056
+ if (this.screenResolution) {
1057
+ this.screenResolution.set(width, height);
1058
+ }
1059
+ }
1060
+ };
1061
+
1062
+ // src/lib/camera/zylem-camera.ts
1063
+ import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
1064
+
1065
+ // src/lib/graphics/render-pass.ts
1066
+ import * as THREE from "three";
1067
+
1068
+ // src/lib/graphics/shaders/vertex/standard.glsl
1069
+ var standard_default2 = "varying vec2 vUv;\n\nvoid main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
1070
+
1071
+ // src/lib/graphics/render-pass.ts
1072
+ import { WebGLRenderTarget } from "three";
1073
+ import { Pass, FullScreenQuad } from "three/addons/postprocessing/Pass.js";
1074
+ var RenderPass = class extends Pass {
1075
+ fsQuad;
1076
+ resolution;
1077
+ scene;
1078
+ camera;
1079
+ rgbRenderTarget;
1080
+ normalRenderTarget;
1081
+ normalMaterial;
1082
+ constructor(resolution, scene, camera) {
1083
+ super();
1084
+ this.resolution = resolution;
1085
+ this.fsQuad = new FullScreenQuad(this.material());
1086
+ this.scene = scene;
1087
+ this.camera = camera;
1088
+ this.rgbRenderTarget = new WebGLRenderTarget(resolution.x * 4, resolution.y * 4);
1089
+ this.normalRenderTarget = new WebGLRenderTarget(resolution.x * 4, resolution.y * 4);
1090
+ this.normalMaterial = new THREE.MeshNormalMaterial();
1091
+ }
1092
+ render(renderer, writeBuffer) {
1093
+ renderer.setRenderTarget(this.rgbRenderTarget);
1094
+ renderer.render(this.scene, this.camera);
1095
+ const overrideMaterial_old = this.scene.overrideMaterial;
1096
+ renderer.setRenderTarget(this.normalRenderTarget);
1097
+ this.scene.overrideMaterial = this.normalMaterial;
1098
+ renderer.render(this.scene, this.camera);
1099
+ this.scene.overrideMaterial = overrideMaterial_old;
1100
+ const uniforms = this.fsQuad.material.uniforms;
1101
+ uniforms.tDiffuse.value = this.rgbRenderTarget.texture;
1102
+ uniforms.tDepth.value = this.rgbRenderTarget.depthTexture;
1103
+ uniforms.tNormal.value = this.normalRenderTarget.texture;
1104
+ uniforms.iTime.value += 0.01;
1105
+ if (this.renderToScreen) {
1106
+ renderer.setRenderTarget(null);
1107
+ } else {
1108
+ renderer.setRenderTarget(writeBuffer);
1109
+ }
1110
+ this.fsQuad.render(renderer);
1111
+ }
1112
+ material() {
1113
+ return new THREE.ShaderMaterial({
1114
+ uniforms: {
1115
+ iTime: { value: 0 },
1116
+ tDiffuse: { value: null },
1117
+ tDepth: { value: null },
1118
+ tNormal: { value: null },
1119
+ resolution: {
1120
+ value: new THREE.Vector4(
1121
+ this.resolution.x,
1122
+ this.resolution.y,
1123
+ 1 / this.resolution.x,
1124
+ 1 / this.resolution.y
1125
+ )
1126
+ }
1127
+ },
1128
+ vertexShader: standard_default2,
1129
+ fragmentShader: standard_default
1130
+ });
1131
+ }
1132
+ dispose() {
1133
+ try {
1134
+ this.fsQuad?.dispose?.();
1135
+ } catch {
1136
+ }
1137
+ try {
1138
+ this.rgbRenderTarget?.dispose?.();
1139
+ this.normalRenderTarget?.dispose?.();
1140
+ } catch {
1141
+ }
1142
+ try {
1143
+ this.normalMaterial?.dispose?.();
1144
+ } catch {
1145
+ }
1146
+ }
1147
+ };
1148
+
1149
+ // src/lib/camera/zylem-camera.ts
1150
+ var ZylemCamera = class {
1151
+ cameraRig;
1152
+ camera;
1153
+ screenResolution;
1154
+ renderer;
1155
+ composer;
1156
+ _perspective;
1157
+ orbitControls = null;
1158
+ target = null;
1159
+ sceneRef = null;
1160
+ frustumSize = 10;
1161
+ // Perspective controller delegation
1162
+ perspectiveController = null;
1163
+ debugDelegate = null;
1164
+ debugUnsubscribe = null;
1165
+ debugStateSnapshot = { enabled: false, selected: [] };
1166
+ orbitTarget = null;
1167
+ orbitTargetWorldPos = new Vector36();
1168
+ constructor(perspective, screenResolution, frustumSize = 10) {
1169
+ this._perspective = perspective;
1170
+ this.screenResolution = screenResolution;
1171
+ this.frustumSize = frustumSize;
1172
+ this.renderer = new WebGLRenderer3({ antialias: false, alpha: true });
1173
+ this.renderer.setSize(screenResolution.x, screenResolution.y);
1174
+ this.renderer.shadowMap.enabled = true;
1175
+ this.composer = new EffectComposer(this.renderer);
1176
+ const aspectRatio = screenResolution.x / screenResolution.y;
1177
+ this.camera = this.createCameraForPerspective(aspectRatio);
1178
+ this.cameraRig = new Object3D4();
1179
+ this.cameraRig.position.set(0, 3, 10);
1180
+ this.cameraRig.add(this.camera);
1181
+ this.camera.lookAt(new Vector36(0, 2, 0));
1182
+ this.initializePerspectiveController();
1183
+ }
1184
+ /**
1185
+ * Setup the camera with a scene
1186
+ */
1187
+ async setup(scene) {
1188
+ this.sceneRef = scene;
1189
+ if (this.orbitControls === null) {
1190
+ this.orbitControls = new OrbitControls(this.camera, this.renderer.domElement);
1191
+ this.orbitControls.enableDamping = true;
1192
+ this.orbitControls.dampingFactor = 0.05;
1193
+ this.orbitControls.screenSpacePanning = false;
1194
+ this.orbitControls.minDistance = 1;
1195
+ this.orbitControls.maxDistance = 500;
1196
+ this.orbitControls.maxPolarAngle = Math.PI / 2;
1197
+ }
1198
+ let renderResolution = this.screenResolution.clone().divideScalar(2);
1199
+ renderResolution.x |= 0;
1200
+ renderResolution.y |= 0;
1201
+ const pass = new RenderPass(renderResolution, scene, this.camera);
1202
+ this.composer.addPass(pass);
1203
+ if (this.perspectiveController) {
1204
+ this.perspectiveController.setup({
1205
+ screenResolution: this.screenResolution,
1206
+ renderer: this.renderer,
1207
+ scene,
1208
+ camera: this
1209
+ });
1210
+ }
1211
+ this.renderer.setAnimationLoop((delta) => {
1212
+ this.update(delta || 0);
1213
+ });
1214
+ }
1215
+ /**
1216
+ * Update camera and render
1217
+ */
1218
+ update(delta) {
1219
+ if (this.orbitControls && this.orbitTarget) {
1220
+ this.orbitTarget.getWorldPosition(this.orbitTargetWorldPos);
1221
+ this.orbitControls.target.copy(this.orbitTargetWorldPos);
1222
+ }
1223
+ this.orbitControls?.update();
1224
+ if (this.perspectiveController) {
1225
+ this.perspectiveController.update(delta);
1226
+ }
1227
+ this.composer.render(delta);
1228
+ }
1229
+ /**
1230
+ * Dispose renderer, composer, controls, and detach from scene
1231
+ */
1232
+ destroy() {
1233
+ try {
1234
+ this.renderer.setAnimationLoop(null);
1235
+ } catch {
1236
+ }
1237
+ try {
1238
+ this.disableOrbitControls();
1239
+ } catch {
1240
+ }
1241
+ try {
1242
+ this.composer?.passes?.forEach((p) => p.dispose?.());
1243
+ this.composer?.dispose?.();
1244
+ } catch {
1245
+ }
1246
+ try {
1247
+ this.renderer.dispose();
1248
+ } catch {
1249
+ }
1250
+ this.detachDebugDelegate();
1251
+ this.sceneRef = null;
1252
+ }
1253
+ /**
1254
+ * Attach a delegate to react to debug state changes.
1255
+ */
1256
+ setDebugDelegate(delegate) {
1257
+ if (this.debugDelegate === delegate) {
1258
+ return;
1259
+ }
1260
+ this.detachDebugDelegate();
1261
+ this.debugDelegate = delegate;
1262
+ if (!delegate) {
1263
+ this.applyDebugState({ enabled: false, selected: [] });
1264
+ return;
1265
+ }
1266
+ const unsubscribe = delegate.subscribe((state2) => {
1267
+ this.applyDebugState(state2);
1268
+ });
1269
+ this.debugUnsubscribe = () => {
1270
+ unsubscribe?.();
1271
+ };
1272
+ }
1273
+ /**
1274
+ * Resize camera and renderer
1275
+ */
1276
+ resize(width, height) {
1277
+ this.screenResolution.set(width, height);
1278
+ this.renderer.setSize(width, height, false);
1279
+ this.composer.setSize(width, height);
1280
+ if (this.camera instanceof PerspectiveCamera) {
1281
+ this.camera.aspect = width / height;
1282
+ this.camera.updateProjectionMatrix();
1283
+ }
1284
+ if (this.perspectiveController) {
1285
+ this.perspectiveController.resize(width, height);
1286
+ }
1287
+ }
1288
+ /**
1289
+ * Update renderer pixel ratio (DPR)
1290
+ */
1291
+ setPixelRatio(dpr) {
1292
+ const safe = Math.max(1, Number.isFinite(dpr) ? dpr : 1);
1293
+ this.renderer.setPixelRatio(safe);
1294
+ }
1295
+ /**
1296
+ * Create camera based on perspective type
1297
+ */
1298
+ createCameraForPerspective(aspectRatio) {
1299
+ switch (this._perspective) {
1300
+ case Perspectives.ThirdPerson:
1301
+ return this.createThirdPersonCamera(aspectRatio);
1302
+ case Perspectives.FirstPerson:
1303
+ return this.createFirstPersonCamera(aspectRatio);
1304
+ case Perspectives.Isometric:
1305
+ return this.createIsometricCamera(aspectRatio);
1306
+ case Perspectives.Flat2D:
1307
+ return this.createFlat2DCamera(aspectRatio);
1308
+ case Perspectives.Fixed2D:
1309
+ return this.createFixed2DCamera(aspectRatio);
1310
+ default:
1311
+ return this.createThirdPersonCamera(aspectRatio);
1312
+ }
1313
+ }
1314
+ /**
1315
+ * Initialize perspective-specific controller
1316
+ */
1317
+ initializePerspectiveController() {
1318
+ switch (this._perspective) {
1319
+ case Perspectives.ThirdPerson:
1320
+ this.perspectiveController = new ThirdPersonCamera();
1321
+ break;
1322
+ case Perspectives.Fixed2D:
1323
+ this.perspectiveController = new Fixed2DCamera();
1324
+ break;
1325
+ default:
1326
+ this.perspectiveController = new ThirdPersonCamera();
1327
+ }
1328
+ }
1329
+ createThirdPersonCamera(aspectRatio) {
1330
+ return new PerspectiveCamera(75, aspectRatio, 0.1, 1e3);
1331
+ }
1332
+ createFirstPersonCamera(aspectRatio) {
1333
+ return new PerspectiveCamera(75, aspectRatio, 0.1, 1e3);
1334
+ }
1335
+ createIsometricCamera(aspectRatio) {
1336
+ return new OrthographicCamera(
1337
+ this.frustumSize * aspectRatio / -2,
1338
+ this.frustumSize * aspectRatio / 2,
1339
+ this.frustumSize / 2,
1340
+ this.frustumSize / -2,
1341
+ 1,
1342
+ 1e3
1343
+ );
1344
+ }
1345
+ createFlat2DCamera(aspectRatio) {
1346
+ return new OrthographicCamera(
1347
+ this.frustumSize * aspectRatio / -2,
1348
+ this.frustumSize * aspectRatio / 2,
1349
+ this.frustumSize / 2,
1350
+ this.frustumSize / -2,
1351
+ 1,
1352
+ 1e3
1353
+ );
1354
+ }
1355
+ createFixed2DCamera(aspectRatio) {
1356
+ return this.createFlat2DCamera(aspectRatio);
1357
+ }
1358
+ // Movement methods
1359
+ moveCamera(position2) {
1360
+ if (this._perspective === Perspectives.Flat2D || this._perspective === Perspectives.Fixed2D) {
1361
+ this.frustumSize = position2.z;
1362
+ }
1363
+ this.cameraRig.position.set(position2.x, position2.y, position2.z);
1364
+ }
1365
+ move(position2) {
1366
+ this.moveCamera(position2);
1367
+ }
1368
+ rotate(pitch, yaw, roll) {
1369
+ this.cameraRig.rotateX(pitch);
1370
+ this.cameraRig.rotateY(yaw);
1371
+ this.cameraRig.rotateZ(roll);
1372
+ }
1373
+ /**
1374
+ * Get the DOM element for the renderer
1375
+ */
1376
+ getDomElement() {
1377
+ return this.renderer.domElement;
1378
+ }
1379
+ applyDebugState(state2) {
1380
+ this.debugStateSnapshot = {
1381
+ enabled: state2.enabled,
1382
+ selected: [...state2.selected]
1383
+ };
1384
+ if (state2.enabled) {
1385
+ this.enableOrbitControls();
1386
+ this.updateOrbitTargetFromSelection(state2.selected);
1387
+ } else {
1388
+ this.orbitTarget = null;
1389
+ this.disableOrbitControls();
1390
+ }
1391
+ }
1392
+ enableOrbitControls() {
1393
+ if (this.orbitControls) {
1394
+ return;
1395
+ }
1396
+ this.orbitControls = new OrbitControls(this.camera, this.renderer.domElement);
1397
+ this.orbitControls.enableDamping = true;
1398
+ this.orbitControls.dampingFactor = 0.05;
1399
+ this.orbitControls.screenSpacePanning = false;
1400
+ this.orbitControls.minDistance = 1;
1401
+ this.orbitControls.maxDistance = 500;
1402
+ this.orbitControls.maxPolarAngle = Math.PI / 2;
1403
+ }
1404
+ disableOrbitControls() {
1405
+ if (!this.orbitControls) {
1406
+ return;
1407
+ }
1408
+ this.orbitControls.dispose();
1409
+ this.orbitControls = null;
1410
+ }
1411
+ updateOrbitTargetFromSelection(selected) {
1412
+ if (!this.debugDelegate || selected.length === 0) {
1413
+ this.orbitTarget = null;
1414
+ return;
1415
+ }
1416
+ for (let i = selected.length - 1; i >= 0; i -= 1) {
1417
+ const uuid = selected[i];
1418
+ const targetObject = this.debugDelegate.resolveTarget(uuid);
1419
+ if (targetObject) {
1420
+ this.orbitTarget = targetObject;
1421
+ if (this.orbitControls) {
1422
+ targetObject.getWorldPosition(this.orbitTargetWorldPos);
1423
+ this.orbitControls.target.copy(this.orbitTargetWorldPos);
1424
+ }
1425
+ return;
1426
+ }
1427
+ }
1428
+ this.orbitTarget = null;
1429
+ }
1430
+ detachDebugDelegate() {
1431
+ if (this.debugUnsubscribe) {
1432
+ try {
1433
+ this.debugUnsubscribe();
1434
+ } catch {
1435
+ }
1436
+ }
1437
+ this.debugUnsubscribe = null;
1438
+ this.debugDelegate = null;
1439
+ }
1440
+ };
1441
+
1442
+ // src/lib/camera/camera.ts
1443
+ var CameraWrapper = class {
1444
+ cameraRef;
1445
+ constructor(camera) {
1446
+ this.cameraRef = camera;
1447
+ }
1448
+ };
1449
+
1450
+ // src/lib/stage/stage-debug-delegate.ts
1451
+ import { Ray } from "@dimforge/rapier3d-compat";
1452
+ import { BufferAttribute, BufferGeometry as BufferGeometry2, LineBasicMaterial as LineBasicMaterial2, LineSegments as LineSegments2, Raycaster, Vector2 as Vector24 } from "three";
1453
+
1454
+ // src/lib/stage/debug-entity-cursor.ts
1455
+ import {
1456
+ Box3,
1457
+ BoxGeometry,
1458
+ Color as Color5,
1459
+ EdgesGeometry,
1460
+ Group as Group3,
1461
+ LineBasicMaterial,
1462
+ LineSegments,
1463
+ Mesh as Mesh2,
1464
+ MeshBasicMaterial,
1465
+ Vector3 as Vector38
1466
+ } from "three";
1467
+ var DebugEntityCursor = class {
1468
+ scene;
1469
+ container;
1470
+ fillMesh;
1471
+ edgeLines;
1472
+ currentColor = new Color5(65280);
1473
+ bbox = new Box3();
1474
+ size = new Vector38();
1475
+ center = new Vector38();
1476
+ constructor(scene) {
1477
+ this.scene = scene;
1478
+ const initialGeometry = new BoxGeometry(1, 1, 1);
1479
+ this.fillMesh = new Mesh2(
1480
+ initialGeometry,
1481
+ new MeshBasicMaterial({
1482
+ color: this.currentColor,
1483
+ transparent: true,
1484
+ opacity: 0.12,
1485
+ depthWrite: false
1486
+ })
1487
+ );
1488
+ const edges = new EdgesGeometry(initialGeometry);
1489
+ this.edgeLines = new LineSegments(
1490
+ edges,
1491
+ new LineBasicMaterial({ color: this.currentColor, linewidth: 1 })
1492
+ );
1493
+ this.container = new Group3();
1494
+ this.container.name = "DebugEntityCursor";
1495
+ this.container.add(this.fillMesh);
1496
+ this.container.add(this.edgeLines);
1497
+ this.container.visible = false;
1498
+ this.scene.add(this.container);
1499
+ }
1500
+ setColor(color) {
1501
+ this.currentColor.set(color);
1502
+ this.fillMesh.material.color.set(this.currentColor);
1503
+ this.edgeLines.material.color.set(this.currentColor);
1504
+ }
1505
+ /**
1506
+ * Update the cursor to enclose the provided Object3D using a world-space AABB.
1507
+ */
1508
+ updateFromObject(object) {
1509
+ if (!object) {
1510
+ this.hide();
1511
+ return;
1512
+ }
1513
+ this.bbox.setFromObject(object);
1514
+ if (!isFinite(this.bbox.min.x) || !isFinite(this.bbox.max.x)) {
1515
+ this.hide();
1516
+ return;
1517
+ }
1518
+ this.bbox.getSize(this.size);
1519
+ this.bbox.getCenter(this.center);
1520
+ const newGeom = new BoxGeometry(
1521
+ Math.max(this.size.x, 1e-6),
1522
+ Math.max(this.size.y, 1e-6),
1523
+ Math.max(this.size.z, 1e-6)
1524
+ );
1525
+ this.fillMesh.geometry.dispose();
1526
+ this.fillMesh.geometry = newGeom;
1527
+ const newEdges = new EdgesGeometry(newGeom);
1528
+ this.edgeLines.geometry.dispose();
1529
+ this.edgeLines.geometry = newEdges;
1530
+ this.container.position.copy(this.center);
1531
+ this.container.visible = true;
1532
+ }
1533
+ hide() {
1534
+ this.container.visible = false;
1535
+ }
1536
+ dispose() {
1537
+ this.scene.remove(this.container);
1538
+ this.fillMesh.geometry.dispose();
1539
+ this.fillMesh.material.dispose();
1540
+ this.edgeLines.geometry.dispose();
1541
+ this.edgeLines.material.dispose();
1542
+ }
1543
+ };
1544
+
1545
+ // src/lib/stage/stage-debug-delegate.ts
1546
+ var SELECT_TOOL_COLOR = 2293538;
1547
+ var DELETE_TOOL_COLOR = 16724787;
1548
+ var StageDebugDelegate = class {
1549
+ stage;
1550
+ options;
1551
+ mouseNdc = new Vector24(-2, -2);
1552
+ raycaster = new Raycaster();
1553
+ isMouseDown = false;
1554
+ disposeFns = [];
1555
+ debugCursor = null;
1556
+ debugLines = null;
1557
+ constructor(stage, options) {
1558
+ this.stage = stage;
1559
+ this.options = {
1560
+ maxRayDistance: options?.maxRayDistance ?? 5e3,
1561
+ addEntityFactory: options?.addEntityFactory ?? null
1562
+ };
1563
+ if (this.stage.scene) {
1564
+ this.debugLines = new LineSegments2(
1565
+ new BufferGeometry2(),
1566
+ new LineBasicMaterial2({ vertexColors: true })
1567
+ );
1568
+ this.stage.scene.scene.add(this.debugLines);
1569
+ this.debugLines.visible = true;
1570
+ this.debugCursor = new DebugEntityCursor(this.stage.scene.scene);
1571
+ }
1572
+ this.attachDomListeners();
1573
+ }
1574
+ update() {
1575
+ if (!debugState.enabled) return;
1576
+ if (!this.stage.scene || !this.stage.world || !this.stage.cameraRef) return;
1577
+ const { world, cameraRef } = this.stage;
1578
+ if (this.debugLines) {
1579
+ const { vertices, colors } = world.world.debugRender();
1580
+ this.debugLines.geometry.setAttribute("position", new BufferAttribute(vertices, 3));
1581
+ this.debugLines.geometry.setAttribute("color", new BufferAttribute(colors, 4));
1582
+ }
1583
+ const tool = getDebugTool();
1584
+ const isCursorTool = tool === "select" || tool === "delete";
1585
+ this.raycaster.setFromCamera(this.mouseNdc, cameraRef.camera);
1586
+ const origin = this.raycaster.ray.origin.clone();
1587
+ const direction = this.raycaster.ray.direction.clone().normalize();
1588
+ const rapierRay = new Ray(
1589
+ { x: origin.x, y: origin.y, z: origin.z },
1590
+ { x: direction.x, y: direction.y, z: direction.z }
1591
+ );
1592
+ const hit = world.world.castRay(rapierRay, this.options.maxRayDistance, true);
1593
+ if (hit && isCursorTool) {
1594
+ const rigidBody = hit.collider?._parent;
1595
+ const hoveredUuid2 = rigidBody?.userData?.uuid;
1596
+ if (hoveredUuid2) {
1597
+ const entity = this.stage._debugMap.get(hoveredUuid2);
1598
+ if (entity) setHoveredEntity(entity);
1599
+ } else {
1600
+ resetHoveredEntity();
1601
+ }
1602
+ if (this.isMouseDown) {
1603
+ this.handleActionOnHit(hoveredUuid2 ?? null, origin, direction, hit.toi);
1604
+ }
1605
+ }
1606
+ this.isMouseDown = false;
1607
+ const hoveredUuid = getHoveredEntity();
1608
+ if (!hoveredUuid) {
1609
+ this.debugCursor?.hide();
1610
+ return;
1611
+ }
1612
+ const hoveredEntity = this.stage._debugMap.get(`${hoveredUuid}`);
1613
+ const targetObject = hoveredEntity?.group ?? hoveredEntity?.mesh ?? null;
1614
+ if (!targetObject) {
1615
+ this.debugCursor?.hide();
1616
+ return;
1617
+ }
1618
+ switch (tool) {
1619
+ case "select":
1620
+ this.debugCursor?.setColor(SELECT_TOOL_COLOR);
1621
+ break;
1622
+ case "delete":
1623
+ this.debugCursor?.setColor(DELETE_TOOL_COLOR);
1624
+ break;
1625
+ default:
1626
+ this.debugCursor?.setColor(16777215);
1627
+ break;
1628
+ }
1629
+ this.debugCursor?.updateFromObject(targetObject);
1630
+ }
1631
+ dispose() {
1632
+ this.disposeFns.forEach((fn) => fn());
1633
+ this.disposeFns = [];
1634
+ this.debugCursor?.dispose();
1635
+ if (this.debugLines && this.stage.scene) {
1636
+ this.stage.scene.scene.remove(this.debugLines);
1637
+ this.debugLines.geometry.dispose();
1638
+ this.debugLines.material.dispose();
1639
+ this.debugLines = null;
1640
+ }
1641
+ }
1642
+ handleActionOnHit(hoveredUuid, origin, direction, toi) {
1643
+ const tool = getDebugTool();
1644
+ switch (tool) {
1645
+ case "select": {
1646
+ if (hoveredUuid) {
1647
+ const entity = this.stage._debugMap.get(hoveredUuid);
1648
+ if (entity) setSelectedEntity(entity);
1649
+ }
1650
+ break;
1651
+ }
1652
+ case "delete": {
1653
+ if (hoveredUuid) {
1654
+ this.stage.removeEntityByUuid(hoveredUuid);
1655
+ }
1656
+ break;
1657
+ }
1658
+ case "scale": {
1659
+ if (!this.options.addEntityFactory) break;
1660
+ const hitPosition = origin.clone().add(direction.clone().multiplyScalar(toi));
1661
+ const newNode = this.options.addEntityFactory({ position: hitPosition });
1662
+ if (newNode) {
1663
+ Promise.resolve(newNode).then((node) => {
1664
+ if (node) this.stage.spawnEntity(node);
1665
+ }).catch(() => {
1666
+ });
1667
+ }
1668
+ break;
1669
+ }
1670
+ default:
1671
+ break;
1672
+ }
1673
+ }
1674
+ attachDomListeners() {
1675
+ const canvas = this.stage.cameraRef?.renderer.domElement ?? this.stage.scene?.zylemCamera.renderer.domElement;
1676
+ if (!canvas) return;
1677
+ const onMouseMove = (e) => {
1678
+ const rect = canvas.getBoundingClientRect();
1679
+ const x = (e.clientX - rect.left) / rect.width * 2 - 1;
1680
+ const y = -((e.clientY - rect.top) / rect.height * 2 - 1);
1681
+ this.mouseNdc.set(x, y);
1682
+ };
1683
+ const onMouseDown = (e) => {
1684
+ this.isMouseDown = true;
1685
+ };
1686
+ canvas.addEventListener("mousemove", onMouseMove);
1687
+ canvas.addEventListener("mousedown", onMouseDown);
1688
+ this.disposeFns.push(() => canvas.removeEventListener("mousemove", onMouseMove));
1689
+ this.disposeFns.push(() => canvas.removeEventListener("mousedown", onMouseDown));
1690
+ }
1691
+ };
1692
+
1693
+ // src/lib/stage/zylem-stage.ts
1694
+ var STAGE_TYPE = "Stage";
1695
+ var ZylemStage = class extends LifeCycleBase {
1696
+ type = STAGE_TYPE;
1697
+ state = {
1698
+ backgroundColor: ZylemBlueColor,
1699
+ backgroundImage: null,
1700
+ inputs: {
1701
+ p1: ["gamepad-1", "keyboard"],
1702
+ p2: ["gamepad-2", "keyboard"]
1703
+ },
1704
+ gravity: new Vector310(0, 0, 0),
1705
+ variables: {},
1706
+ entities: []
1707
+ };
1708
+ gravity;
1709
+ world;
1710
+ scene;
1711
+ children = [];
1712
+ _childrenMap = /* @__PURE__ */ new Map();
1713
+ _removalMap = /* @__PURE__ */ new Map();
1714
+ pendingEntities = [];
1715
+ pendingPromises = [];
1716
+ isLoaded = false;
1717
+ _debugMap = /* @__PURE__ */ new Map();
1718
+ entityAddedHandlers = [];
1719
+ loadingHandlers = [];
1720
+ ecs = createECS();
1721
+ testSystem = null;
1722
+ transformSystem = null;
1723
+ debugDelegate = null;
1724
+ cameraDebugDelegate = null;
1725
+ uuid;
1726
+ wrapperRef = null;
1727
+ camera;
1728
+ cameraRef = null;
1729
+ /**
1730
+ * Create a new stage.
1731
+ * @param options Stage options: partial config, camera, and initial entities or factories
1732
+ */
1733
+ constructor(options = []) {
1734
+ super();
1735
+ this.world = null;
1736
+ this.scene = null;
1737
+ this.uuid = nanoid2();
1738
+ const { config, entities, asyncEntities, camera } = this.parseOptions(options);
1739
+ this.camera = camera;
1740
+ this.children = entities;
1741
+ this.pendingEntities = asyncEntities;
1742
+ this.saveState({ ...this.state, ...config, entities: [] });
1743
+ this.gravity = config.gravity ?? new Vector310(0, 0, 0);
1744
+ }
1745
+ parseOptions(options) {
1746
+ let config = {};
1747
+ const entities = [];
1748
+ const asyncEntities = [];
1749
+ let camera;
1750
+ for (const item of options) {
1751
+ if (this.isCameraWrapper(item)) {
1752
+ camera = item;
1753
+ } else if (this.isBaseNode(item)) {
1754
+ entities.push(item);
1755
+ } else if (this.isEntityInput(item)) {
1756
+ asyncEntities.push(item);
1757
+ } else if (this.isZylemStageConfig(item)) {
1758
+ config = { ...config, ...item };
1759
+ }
1760
+ }
1761
+ return { config, entities, asyncEntities, camera };
1762
+ }
1763
+ isZylemStageConfig(item) {
1764
+ return item && typeof item === "object" && !(item instanceof BaseNode) && !(item instanceof CameraWrapper);
1765
+ }
1766
+ isBaseNode(item) {
1767
+ return item && typeof item === "object" && typeof item.create === "function";
1768
+ }
1769
+ isCameraWrapper(item) {
1770
+ return item && typeof item === "object" && item.constructor.name === "CameraWrapper";
1771
+ }
1772
+ isEntityInput(item) {
1773
+ if (!item) return false;
1774
+ if (this.isBaseNode(item)) return true;
1775
+ if (typeof item === "function") return true;
1776
+ if (typeof item === "object" && typeof item.then === "function") return true;
1777
+ return false;
1778
+ }
1779
+ isThenable(value) {
1780
+ return !!value && typeof value.then === "function";
1781
+ }
1782
+ handleEntityImmediatelyOrQueue(entity) {
1783
+ if (this.isLoaded) {
1784
+ this.spawnEntity(entity);
1785
+ } else {
1786
+ this.children.push(entity);
1787
+ }
1788
+ }
1789
+ handlePromiseWithSpawnOnResolve(promise) {
1790
+ if (this.isLoaded) {
1791
+ promise.then((entity) => this.spawnEntity(entity)).catch((e) => console.error("Failed to build async entity", e));
1792
+ } else {
1793
+ this.pendingPromises.push(promise);
1794
+ }
1795
+ }
1796
+ saveState(state2) {
1797
+ this.state = state2;
1798
+ }
1799
+ setState() {
1800
+ const { backgroundColor, backgroundImage } = this.state;
1801
+ const color = backgroundColor instanceof Color6 ? backgroundColor : new Color6(backgroundColor);
1802
+ setStageBackgroundColor(color);
1803
+ setStageBackgroundImage(backgroundImage);
1804
+ setStageVariables(this.state.variables ?? {});
1805
+ }
1806
+ /**
1807
+ * Load and initialize the stage's scene and world.
1808
+ * @param id DOM element id for the renderer container
1809
+ * @param camera Optional camera override
1810
+ */
1811
+ async load(id, camera) {
1812
+ this.setState();
1813
+ const zylemCamera = camera || (this.camera ? this.camera.cameraRef : this.createDefaultCamera());
1814
+ this.cameraRef = zylemCamera;
1815
+ this.scene = new ZylemScene(id, zylemCamera, this.state);
1816
+ const physicsWorld = await ZylemWorld.loadPhysics(this.gravity ?? new Vector310(0, 0, 0));
1817
+ this.world = new ZylemWorld(physicsWorld);
1818
+ this.scene.setup();
1819
+ this.emitLoading({ type: "start", message: "Loading stage...", progress: 0 });
1820
+ const total = this.children.length + this.pendingEntities.length + this.pendingPromises.length;
1821
+ let current = 0;
1822
+ for (let child of this.children) {
1823
+ this.spawnEntity(child);
1824
+ current++;
1825
+ this.emitLoading({
1826
+ type: "progress",
1827
+ message: `Loaded entity ${child.name || "unknown"}`,
1828
+ progress: current / total,
1829
+ current,
1830
+ total
1831
+ });
1832
+ }
1833
+ if (this.pendingEntities.length) {
1834
+ this.enqueue(...this.pendingEntities);
1835
+ current += this.pendingEntities.length;
1836
+ this.pendingEntities = [];
1837
+ }
1838
+ if (this.pendingPromises.length) {
1839
+ for (const promise of this.pendingPromises) {
1840
+ promise.then((entity) => {
1841
+ this.spawnEntity(entity);
1842
+ }).catch((e) => console.error("Failed to resolve pending stage entity", e));
1843
+ }
1844
+ current += this.pendingPromises.length;
1845
+ this.pendingPromises = [];
1846
+ }
1847
+ this.transformSystem = createTransformSystem(this);
1848
+ this.isLoaded = true;
1849
+ this.emitLoading({ type: "complete", message: "Stage loaded", progress: 1 });
1850
+ }
1851
+ createDefaultCamera() {
1852
+ const width = window.innerWidth;
1853
+ const height = window.innerHeight;
1854
+ const screenResolution = new Vector25(width, height);
1855
+ return new ZylemCamera(Perspectives.ThirdPerson, screenResolution);
1856
+ }
1857
+ _setup(params) {
1858
+ if (!this.scene || !this.world) {
1859
+ this.logMissingEntities();
1860
+ return;
1861
+ }
1862
+ if (debugState.enabled) {
1863
+ this.debugDelegate = new StageDebugDelegate(this);
1864
+ }
1865
+ }
1866
+ _update(params) {
1867
+ const { delta } = params;
1868
+ if (!this.scene || !this.world) {
1869
+ this.logMissingEntities();
1870
+ return;
1871
+ }
1872
+ this.world.update(params);
1873
+ this.transformSystem(this.ecs);
1874
+ this._childrenMap.forEach((child, eid) => {
1875
+ child.nodeUpdate({
1876
+ ...params,
1877
+ me: child
1878
+ });
1879
+ if (child.markedForRemoval) {
1880
+ this.removeEntityByUuid(child.uuid);
1881
+ }
1882
+ });
1883
+ this.scene.update({ delta });
1884
+ }
1885
+ outOfLoop() {
1886
+ this.debugUpdate();
1887
+ }
1888
+ /** Update debug overlays and helpers if enabled. */
1889
+ debugUpdate() {
1890
+ if (debugState.enabled) {
1891
+ this.debugDelegate?.update();
1892
+ }
1893
+ }
1894
+ /** Cleanup owned resources when the stage is destroyed. */
1895
+ _destroy(params) {
1896
+ this._childrenMap.forEach((child) => {
1897
+ try {
1898
+ child.nodeDestroy({ me: child, globals: getGlobals() });
1899
+ } catch {
1900
+ }
1901
+ });
1902
+ this._childrenMap.clear();
1903
+ this._removalMap.clear();
1904
+ this._debugMap.clear();
1905
+ this.world?.destroy();
1906
+ this.scene?.destroy();
1907
+ this.debugDelegate?.dispose();
1908
+ this.cameraRef?.setDebugDelegate(null);
1909
+ this.cameraDebugDelegate = null;
1910
+ this.isLoaded = false;
1911
+ this.world = null;
1912
+ this.scene = null;
1913
+ this.cameraRef = null;
1914
+ resetStageVariables();
1915
+ clearVariables(this);
1916
+ }
1917
+ /**
1918
+ * Create, register, and add an entity to the scene/world.
1919
+ * Safe to call only after `load` when scene/world exist.
1920
+ */
1921
+ async spawnEntity(child) {
1922
+ if (!this.scene || !this.world) {
1923
+ return;
1924
+ }
1925
+ const entity = child.create();
1926
+ const eid = addEntity(this.ecs);
1927
+ entity.eid = eid;
1928
+ this.scene.addEntity(entity);
1929
+ if (child.behaviors) {
1930
+ for (let behavior of child.behaviors) {
1931
+ addComponent(this.ecs, behavior.component, entity.eid);
1932
+ const keys = Object.keys(behavior.values);
1933
+ for (const key of keys) {
1934
+ behavior.component[key][entity.eid] = behavior.values[key];
1935
+ }
1936
+ }
1937
+ }
1938
+ if (entity.colliderDesc) {
1939
+ this.world.addEntity(entity);
1940
+ }
1941
+ child.nodeSetup({
1942
+ me: child,
1943
+ globals: getGlobals(),
1944
+ camera: this.scene.zylemCamera
1945
+ });
1946
+ this.addEntityToStage(entity);
1947
+ }
1948
+ buildEntityState(child) {
1949
+ if (child instanceof GameEntity) {
1950
+ return { ...child.buildInfo() };
1951
+ }
1952
+ return {
1953
+ uuid: child.uuid,
1954
+ name: child.name,
1955
+ eid: child.eid
1956
+ };
1957
+ }
1958
+ /** Add the entity to internal maps and notify listeners. */
1959
+ addEntityToStage(entity) {
1960
+ this._childrenMap.set(entity.eid, entity);
1961
+ if (debugState.enabled) {
1962
+ this._debugMap.set(entity.uuid, entity);
1963
+ }
1964
+ for (const handler of this.entityAddedHandlers) {
1965
+ try {
1966
+ handler(entity);
1967
+ } catch (e) {
1968
+ console.error("onEntityAdded handler failed", e);
1969
+ }
1970
+ }
1971
+ }
1972
+ /**
1973
+ * Subscribe to entity-added events.
1974
+ * @param callback Invoked for each entity when added
1975
+ * @param options.replayExisting If true and stage already loaded, replays existing entities
1976
+ * @returns Unsubscribe function
1977
+ */
1978
+ onEntityAdded(callback, options) {
1979
+ this.entityAddedHandlers.push(callback);
1980
+ if (options?.replayExisting && this.isLoaded) {
1981
+ this._childrenMap.forEach((entity) => {
1982
+ try {
1983
+ callback(entity);
1984
+ } catch (e) {
1985
+ console.error("onEntityAdded replay failed", e);
1986
+ }
1987
+ });
1988
+ }
1989
+ return () => {
1990
+ this.entityAddedHandlers = this.entityAddedHandlers.filter((h) => h !== callback);
1991
+ };
1992
+ }
1993
+ onLoading(callback) {
1994
+ this.loadingHandlers.push(callback);
1995
+ return () => {
1996
+ this.loadingHandlers = this.loadingHandlers.filter((h) => h !== callback);
1997
+ };
1998
+ }
1999
+ emitLoading(event) {
2000
+ this.loadingHandlers.forEach((h) => h(event));
2001
+ }
2002
+ /**
2003
+ * Remove an entity and its resources by its UUID.
2004
+ * @returns true if removed, false if not found or stage not ready
2005
+ */
2006
+ removeEntityByUuid(uuid) {
2007
+ if (!this.scene || !this.world) return false;
2008
+ const mapEntity = this.world.collisionMap.get(uuid);
2009
+ const entity = mapEntity ?? this._debugMap.get(uuid);
2010
+ if (!entity) return false;
2011
+ this.world.destroyEntity(entity);
2012
+ if (entity.group) {
2013
+ this.scene.scene.remove(entity.group);
2014
+ } else if (entity.mesh) {
2015
+ this.scene.scene.remove(entity.mesh);
2016
+ }
2017
+ removeEntity(this.ecs, entity.eid);
2018
+ let foundKey = null;
2019
+ this._childrenMap.forEach((value, key) => {
2020
+ if (value.uuid === uuid) {
2021
+ foundKey = key;
2022
+ }
2023
+ });
2024
+ if (foundKey !== null) {
2025
+ this._childrenMap.delete(foundKey);
2026
+ }
2027
+ this._debugMap.delete(uuid);
2028
+ return true;
2029
+ }
2030
+ /** Get an entity by its name; returns null if not found. */
2031
+ getEntityByName(name) {
2032
+ const arr = Object.entries(Object.fromEntries(this._childrenMap)).map((entry) => entry[1]);
2033
+ const entity = arr.find((child) => child.name === name);
2034
+ if (!entity) {
2035
+ console.warn(`Entity ${name} not found`);
2036
+ }
2037
+ return entity ?? null;
2038
+ }
2039
+ logMissingEntities() {
2040
+ console.warn("Zylem world or scene is null");
2041
+ }
2042
+ /** Resize renderer viewport. */
2043
+ resize(width, height) {
2044
+ if (this.scene) {
2045
+ this.scene.updateRenderer(width, height);
2046
+ }
2047
+ }
2048
+ /**
2049
+ * Enqueue items to be spawned. Items can be:
2050
+ * - BaseNode instances (immediate or deferred until load)
2051
+ * - Factory functions returning BaseNode or Promise<BaseNode>
2052
+ * - Promises resolving to BaseNode
2053
+ */
2054
+ enqueue(...items) {
2055
+ for (const item of items) {
2056
+ if (!item) continue;
2057
+ if (this.isBaseNode(item)) {
2058
+ this.handleEntityImmediatelyOrQueue(item);
2059
+ continue;
2060
+ }
2061
+ if (typeof item === "function") {
2062
+ try {
2063
+ const result = item();
2064
+ if (this.isBaseNode(result)) {
2065
+ this.handleEntityImmediatelyOrQueue(result);
2066
+ } else if (this.isThenable(result)) {
2067
+ this.handlePromiseWithSpawnOnResolve(result);
2068
+ }
2069
+ } catch (error) {
2070
+ console.error("Error executing entity factory", error);
2071
+ }
2072
+ continue;
2073
+ }
2074
+ if (this.isThenable(item)) {
2075
+ this.handlePromiseWithSpawnOnResolve(item);
2076
+ }
2077
+ }
2078
+ }
2079
+ };
2080
+
2081
+ // src/lib/stage/stage-default.ts
2082
+ import { proxy as proxy4 } from "valtio/vanilla";
2083
+ import { Vector3 as Vector311 } from "three";
2084
+ var initialDefaults = {
2085
+ backgroundColor: ZylemBlueColor,
2086
+ backgroundImage: null,
2087
+ inputs: {
2088
+ p1: ["gamepad-1", "keyboard"],
2089
+ p2: ["gamepad-2", "keyboard"]
2090
+ },
2091
+ gravity: new Vector311(0, 0, 0),
2092
+ variables: {}
2093
+ };
2094
+ var stageDefaultsState = proxy4({
2095
+ ...initialDefaults
2096
+ });
2097
+ function getStageOptions(options) {
2098
+ const defaults = getStageDefaultConfig();
2099
+ let originalConfig = {};
2100
+ if (typeof options[0] === "object") {
2101
+ originalConfig = options.shift() ?? {};
2102
+ }
2103
+ const combinedConfig = { ...defaults, ...originalConfig };
2104
+ return [combinedConfig, ...options];
2105
+ }
2106
+ function getStageDefaultConfig() {
2107
+ return {
2108
+ backgroundColor: stageDefaultsState.backgroundColor,
2109
+ backgroundImage: stageDefaultsState.backgroundImage ?? null,
2110
+ inputs: stageDefaultsState.inputs ? { ...stageDefaultsState.inputs } : void 0,
2111
+ gravity: stageDefaultsState.gravity,
2112
+ variables: stageDefaultsState.variables ? { ...stageDefaultsState.variables } : void 0
2113
+ };
2114
+ }
2115
+
2116
+ // src/lib/stage/stage.ts
2117
+ var Stage = class {
2118
+ wrappedStage;
2119
+ options = [];
2120
+ // TODO: these shouldn't be here maybe more like nextFrame(stageInstance, () => {})
2121
+ update = () => {
2122
+ };
2123
+ setup = () => {
2124
+ };
2125
+ destroy = () => {
2126
+ };
2127
+ constructor(options) {
2128
+ this.options = options;
2129
+ this.wrappedStage = null;
2130
+ }
2131
+ async load(id, camera) {
2132
+ stageState.entities = [];
2133
+ this.wrappedStage = new ZylemStage(this.options);
2134
+ this.wrappedStage.wrapperRef = this;
2135
+ const zylemCamera = camera instanceof CameraWrapper ? camera.cameraRef : camera;
2136
+ await this.wrappedStage.load(id, zylemCamera);
2137
+ this.wrappedStage.onEntityAdded((child) => {
2138
+ const next = this.wrappedStage.buildEntityState(child);
2139
+ stageState.entities = [...stageState.entities, next];
2140
+ }, { replayExisting: true });
2141
+ }
2142
+ async addEntities(entities) {
2143
+ this.options.push(...entities);
2144
+ if (!this.wrappedStage) {
2145
+ return;
2146
+ }
2147
+ this.wrappedStage.enqueue(...entities);
2148
+ }
2149
+ add(...inputs) {
2150
+ this.addToBlueprints(...inputs);
2151
+ this.addToStage(...inputs);
2152
+ }
2153
+ addToBlueprints(...inputs) {
2154
+ if (this.wrappedStage) {
2155
+ return;
2156
+ }
2157
+ this.options.push(...inputs);
2158
+ }
2159
+ addToStage(...inputs) {
2160
+ if (!this.wrappedStage) {
2161
+ return;
2162
+ }
2163
+ this.wrappedStage.enqueue(...inputs);
2164
+ }
2165
+ start(params) {
2166
+ this.wrappedStage?.nodeSetup(params);
2167
+ }
2168
+ onUpdate(...callbacks) {
2169
+ if (!this.wrappedStage) {
2170
+ return;
2171
+ }
2172
+ this.wrappedStage.update = (params) => {
2173
+ const extended = { ...params, stage: this };
2174
+ callbacks.forEach((cb) => cb(extended));
2175
+ };
2176
+ }
2177
+ onSetup(callback) {
2178
+ this.wrappedStage.setup = callback;
2179
+ }
2180
+ onDestroy(callback) {
2181
+ this.wrappedStage.destroy = callback;
2182
+ }
2183
+ onLoading(callback) {
2184
+ if (!this.wrappedStage) {
2185
+ return () => {
2186
+ };
2187
+ }
2188
+ return this.wrappedStage.onLoading(callback);
2189
+ }
2190
+ };
2191
+ function createStage(...options) {
2192
+ const _options = getStageOptions(options);
2193
+ return new Stage([..._options]);
2194
+ }
2195
+
2196
+ // src/lib/stage/entity-spawner.ts
2197
+ import { Euler, Quaternion as Quaternion2, Vector2 as Vector26 } from "three";
2198
+ function entitySpawner(factory) {
2199
+ return {
2200
+ spawn: async (stage, x, y) => {
2201
+ const instance = await Promise.resolve(factory(x, y));
2202
+ stage.add(instance);
2203
+ return instance;
2204
+ },
2205
+ spawnRelative: async (source, stage, offset = new Vector26(0, 1)) => {
2206
+ if (!source.body) {
2207
+ console.warn("body missing for entity during spawnRelative");
2208
+ return void 0;
2209
+ }
2210
+ const { x, y, z } = source.body.translation();
2211
+ let rz = source._rotation2DAngle ?? 0;
2212
+ try {
2213
+ const r = source.body.rotation();
2214
+ const q = new Quaternion2(r.x, r.y, r.z, r.w);
2215
+ const e = new Euler().setFromQuaternion(q, "XYZ");
2216
+ rz = e.z;
2217
+ } catch {
2218
+ }
2219
+ const offsetX = Math.sin(-rz) * (offset.x ?? 0);
2220
+ const offsetY = Math.cos(-rz) * (offset.y ?? 0);
2221
+ const instance = await Promise.resolve(factory(x + offsetX, y + offsetY));
2222
+ stage.add(instance);
2223
+ return instance;
2224
+ }
2225
+ };
2226
+ }
3
2227
  export {
4
- t as createStage,
5
- a as entitySpawner
2228
+ createStage,
2229
+ entitySpawner
6
2230
  };
2231
+ //# sourceMappingURL=stage.js.map