@needle-tools/engine 5.1.0-canary.fbdfce3 → 5.1.0-experimental.03e8105

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 (311) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/SKILL.md +4 -1
  3. package/components.needle.json +1 -1
  4. package/dist/{needle-engine.bundle-BFSj2Fz8.js → needle-engine.bundle-BNqUjnSQ.js} +19180 -18386
  5. package/dist/needle-engine.bundle-Bt8ULD7E.umd.cjs +1733 -0
  6. package/dist/needle-engine.bundle-DF6ovbwD.min.js +1733 -0
  7. package/dist/needle-engine.d.ts +1487 -356
  8. package/dist/needle-engine.js +544 -542
  9. package/dist/needle-engine.min.js +1 -1
  10. package/dist/needle-engine.umd.cjs +1 -1
  11. package/dist/three.js +1 -0
  12. package/dist/three.min.js +21 -21
  13. package/dist/three.umd.cjs +16 -16
  14. package/lib/engine/api.d.ts +8 -1
  15. package/lib/engine/api.js +7 -1
  16. package/lib/engine/api.js.map +1 -1
  17. package/lib/engine/codegen/register_types.js +10 -18
  18. package/lib/engine/codegen/register_types.js.map +1 -1
  19. package/lib/engine/engine_audio.d.ts +68 -0
  20. package/lib/engine/engine_audio.js +172 -0
  21. package/lib/engine/engine_audio.js.map +1 -1
  22. package/lib/engine/engine_camera.fit.js +16 -4
  23. package/lib/engine/engine_camera.fit.js.map +1 -1
  24. package/lib/engine/engine_components.js +1 -1
  25. package/lib/engine/engine_components.js.map +1 -1
  26. package/lib/engine/engine_context.d.ts +21 -8
  27. package/lib/engine/engine_context.js +32 -16
  28. package/lib/engine/engine_context.js.map +1 -1
  29. package/lib/engine/engine_context_eventbus.d.ts +47 -0
  30. package/lib/engine/engine_context_eventbus.js +47 -0
  31. package/lib/engine/engine_context_eventbus.js.map +1 -0
  32. package/lib/engine/engine_disposable.d.ts +172 -0
  33. package/lib/engine/engine_disposable.js +136 -0
  34. package/lib/engine/engine_disposable.js.map +1 -0
  35. package/lib/engine/engine_gameobject.d.ts +1 -10
  36. package/lib/engine/engine_gameobject.js +22 -120
  37. package/lib/engine/engine_gameobject.js.map +1 -1
  38. package/lib/engine/engine_gltf_builtin_components.js +7 -69
  39. package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
  40. package/lib/engine/engine_init.js +7 -7
  41. package/lib/engine/engine_init.js.map +1 -1
  42. package/lib/engine/engine_input.d.ts +24 -5
  43. package/lib/engine/engine_input.js +3 -2
  44. package/lib/engine/engine_input.js.map +1 -1
  45. package/lib/engine/engine_instantiate_resolve.d.ts +42 -0
  46. package/lib/engine/engine_instantiate_resolve.js +372 -0
  47. package/lib/engine/engine_instantiate_resolve.js.map +1 -0
  48. package/lib/engine/engine_license.d.ts +7 -7
  49. package/lib/engine/engine_license.js +183 -57
  50. package/lib/engine/engine_license.js.map +1 -1
  51. package/lib/engine/engine_mainloop_utils.js +7 -4
  52. package/lib/engine/engine_mainloop_utils.js.map +1 -1
  53. package/lib/engine/engine_networking.d.ts +51 -37
  54. package/lib/engine/engine_networking.js +132 -82
  55. package/lib/engine/engine_networking.js.map +1 -1
  56. package/lib/engine/engine_networking.transport.websocket.d.ts +15 -0
  57. package/lib/engine/engine_networking.transport.websocket.js +38 -0
  58. package/lib/engine/engine_networking.transport.websocket.js.map +1 -0
  59. package/lib/engine/engine_networking_blob.js +4 -4
  60. package/lib/engine/engine_networking_blob.js.map +1 -1
  61. package/lib/engine/engine_networking_instantiate.js +2 -2
  62. package/lib/engine/engine_networking_instantiate.js.map +1 -1
  63. package/lib/engine/engine_networking_types.d.ts +39 -1
  64. package/lib/engine/engine_networking_types.js +7 -0
  65. package/lib/engine/engine_networking_types.js.map +1 -1
  66. package/lib/engine/engine_physics_rapier.d.ts +21 -3
  67. package/lib/engine/engine_physics_rapier.js +94 -25
  68. package/lib/engine/engine_physics_rapier.js.map +1 -1
  69. package/lib/engine/engine_scenedata.js +2 -2
  70. package/lib/engine/engine_scenedata.js.map +1 -1
  71. package/lib/engine/engine_serialization_builtin_serializer.js +28 -5
  72. package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
  73. package/lib/engine/engine_serialization_core.d.ts +1 -0
  74. package/lib/engine/engine_serialization_core.js +7 -0
  75. package/lib/engine/engine_serialization_core.js.map +1 -1
  76. package/lib/engine/engine_types.d.ts +29 -11
  77. package/lib/engine/engine_types.js +1 -1
  78. package/lib/engine/engine_types.js.map +1 -1
  79. package/lib/engine/engine_util_decorator.js +7 -2
  80. package/lib/engine/engine_util_decorator.js.map +1 -1
  81. package/lib/engine/engine_utils.d.ts +1 -1
  82. package/lib/engine/engine_utils.js +19 -5
  83. package/lib/engine/engine_utils.js.map +1 -1
  84. package/lib/engine/engine_utils_qrcode.js +2 -2
  85. package/lib/engine/engine_utils_qrcode.js.map +1 -1
  86. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
  87. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js.map +1 -1
  88. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +2 -2
  89. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
  90. package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +1 -1
  91. package/lib/engine/webcomponents/needle menu/needle-menu.js +6 -6
  92. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  93. package/lib/engine/webcomponents/needle-engine.d.ts +10 -4
  94. package/lib/engine/webcomponents/needle-engine.js +3 -3
  95. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  96. package/lib/engine/webcomponents/needle-engine.loading.js +2 -2
  97. package/lib/engine/webcomponents/needle-engine.loading.js.map +1 -1
  98. package/lib/engine/xr/NeedleXRSession.d.ts +3 -2
  99. package/lib/engine/xr/NeedleXRSession.js +50 -14
  100. package/lib/engine/xr/NeedleXRSession.js.map +1 -1
  101. package/lib/engine/xr/TempXRContext.js +2 -2
  102. package/lib/engine/xr/TempXRContext.js.map +1 -1
  103. package/lib/engine/xr/events.d.ts +1 -1
  104. package/lib/engine/xr/events.js.map +1 -1
  105. package/lib/engine-components/Animation.js +17 -16
  106. package/lib/engine-components/Animation.js.map +1 -1
  107. package/lib/engine-components/AnimationBuilder.d.ts +158 -0
  108. package/lib/engine-components/AnimationBuilder.js +305 -0
  109. package/lib/engine-components/AnimationBuilder.js.map +1 -0
  110. package/lib/engine-components/Animator.d.ts +6 -0
  111. package/lib/engine-components/Animator.js +23 -13
  112. package/lib/engine-components/Animator.js.map +1 -1
  113. package/lib/engine-components/AnimatorController.builder.d.ts +191 -0
  114. package/lib/engine-components/AnimatorController.builder.js +263 -0
  115. package/lib/engine-components/AnimatorController.builder.js.map +1 -0
  116. package/lib/engine-components/AnimatorController.d.ts +2 -119
  117. package/lib/engine-components/AnimatorController.js +33 -232
  118. package/lib/engine-components/AnimatorController.js.map +1 -1
  119. package/lib/engine-components/AudioSource.d.ts +19 -3
  120. package/lib/engine-components/AudioSource.js +121 -68
  121. package/lib/engine-components/AudioSource.js.map +1 -1
  122. package/lib/engine-components/Collider.d.ts +18 -9
  123. package/lib/engine-components/Collider.js +61 -14
  124. package/lib/engine-components/Collider.js.map +1 -1
  125. package/lib/engine-components/Component.d.ts +72 -9
  126. package/lib/engine-components/Component.js +114 -10
  127. package/lib/engine-components/Component.js.map +1 -1
  128. package/lib/engine-components/ContactShadows.d.ts +1 -0
  129. package/lib/engine-components/ContactShadows.js +14 -1
  130. package/lib/engine-components/ContactShadows.js.map +1 -1
  131. package/lib/engine-components/DragControls.d.ts +7 -0
  132. package/lib/engine-components/DragControls.js +19 -7
  133. package/lib/engine-components/DragControls.js.map +1 -1
  134. package/lib/engine-components/DropListener.js +3 -0
  135. package/lib/engine-components/DropListener.js.map +1 -1
  136. package/lib/engine-components/EventList.d.ts +31 -9
  137. package/lib/engine-components/EventList.js +37 -76
  138. package/lib/engine-components/EventList.js.map +1 -1
  139. package/lib/engine-components/Joints.d.ts +4 -2
  140. package/lib/engine-components/Joints.js +19 -3
  141. package/lib/engine-components/Joints.js.map +1 -1
  142. package/lib/engine-components/Light.js +9 -1
  143. package/lib/engine-components/Light.js.map +1 -1
  144. package/lib/engine-components/Networking.d.ts +1 -1
  145. package/lib/engine-components/Networking.js +1 -1
  146. package/lib/engine-components/OrbitControls.d.ts +0 -2
  147. package/lib/engine-components/OrbitControls.js +30 -12
  148. package/lib/engine-components/OrbitControls.js.map +1 -1
  149. package/lib/engine-components/RigidBody.d.ts +12 -4
  150. package/lib/engine-components/RigidBody.js +18 -4
  151. package/lib/engine-components/RigidBody.js.map +1 -1
  152. package/lib/engine-components/SceneSwitcher.js +3 -0
  153. package/lib/engine-components/SceneSwitcher.js.map +1 -1
  154. package/lib/engine-components/SeeThrough.js +2 -2
  155. package/lib/engine-components/SeeThrough.js.map +1 -1
  156. package/lib/engine-components/api.d.ts +2 -1
  157. package/lib/engine-components/api.js +2 -1
  158. package/lib/engine-components/api.js.map +1 -1
  159. package/lib/engine-components/codegen/components.d.ts +7 -13
  160. package/lib/engine-components/codegen/components.js +7 -13
  161. package/lib/engine-components/codegen/components.js.map +1 -1
  162. package/lib/engine-components/export/usdz/USDZExporter.js +4 -4
  163. package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
  164. package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
  165. package/lib/engine-components/timeline/PlayableDirector.d.ts +21 -11
  166. package/lib/engine-components/timeline/PlayableDirector.js +75 -67
  167. package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
  168. package/lib/engine-components/timeline/SignalAsset.d.ts +3 -1
  169. package/lib/engine-components/timeline/SignalAsset.js +1 -0
  170. package/lib/engine-components/timeline/SignalAsset.js.map +1 -1
  171. package/lib/engine-components/timeline/TimelineBuilder.d.ts +413 -0
  172. package/lib/engine-components/timeline/TimelineBuilder.js +506 -0
  173. package/lib/engine-components/timeline/TimelineBuilder.js.map +1 -0
  174. package/lib/engine-components/timeline/TimelineModels.d.ts +2 -1
  175. package/lib/engine-components/timeline/TimelineModels.js +3 -0
  176. package/lib/engine-components/timeline/TimelineModels.js.map +1 -1
  177. package/lib/engine-components/timeline/TimelineTracks.d.ts +37 -6
  178. package/lib/engine-components/timeline/TimelineTracks.js +92 -26
  179. package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
  180. package/lib/engine-components/timeline/index.d.ts +2 -1
  181. package/lib/engine-components/timeline/index.js +2 -0
  182. package/lib/engine-components/timeline/index.js.map +1 -1
  183. package/lib/engine-components/ui/Canvas.d.ts +1 -1
  184. package/lib/engine-components/ui/Canvas.js +2 -8
  185. package/lib/engine-components/ui/Canvas.js.map +1 -1
  186. package/lib/engine-components/ui/Text.d.ts +1 -0
  187. package/lib/engine-components/ui/Text.js +10 -7
  188. package/lib/engine-components/ui/Text.js.map +1 -1
  189. package/lib/engine-components/web/CursorFollow.d.ts +0 -1
  190. package/lib/engine-components/web/CursorFollow.js +21 -13
  191. package/lib/engine-components/web/CursorFollow.js.map +1 -1
  192. package/lib/engine-components/webxr/WebXRImageTracking.js +4 -0
  193. package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
  194. package/package.json +2 -83
  195. package/plugins/common/cloud.js +6 -1
  196. package/plugins/common/license.js +31 -10
  197. package/plugins/common/worker.js +9 -4
  198. package/plugins/vite/asap.js +17 -8
  199. package/plugins/vite/dependencies.js +29 -10
  200. package/plugins/vite/dependency-watcher.js +2 -2
  201. package/plugins/vite/editor-connection.js +3 -3
  202. package/plugins/vite/license.js +46 -7
  203. package/plugins/vite/local-files-core.js +3 -3
  204. package/plugins/vite/local-files-utils.d.ts +3 -1
  205. package/plugins/vite/local-files-utils.js +29 -5
  206. package/plugins/vite/reload.js +1 -1
  207. package/plugins/vite/server.js +2 -1
  208. package/src/engine/api.ts +11 -1
  209. package/src/engine/codegen/register_types.ts +10 -18
  210. package/src/engine/engine_audio.ts +184 -0
  211. package/src/engine/engine_camera.fit.ts +15 -4
  212. package/src/engine/engine_components.ts +1 -1
  213. package/src/engine/engine_context.ts +34 -18
  214. package/src/engine/engine_context_eventbus.ts +73 -0
  215. package/src/engine/engine_disposable.ts +214 -0
  216. package/src/engine/engine_gameobject.ts +54 -159
  217. package/src/engine/engine_gltf_builtin_components.ts +7 -76
  218. package/src/engine/engine_init.ts +7 -7
  219. package/src/engine/engine_input.ts +28 -7
  220. package/src/engine/engine_instantiate_resolve.ts +407 -0
  221. package/src/engine/engine_license.ts +197 -55
  222. package/src/engine/engine_mainloop_utils.ts +7 -4
  223. package/src/engine/engine_networking.transport.websocket.ts +45 -0
  224. package/src/engine/engine_networking.ts +161 -137
  225. package/src/engine/engine_networking_blob.ts +4 -4
  226. package/src/engine/engine_networking_instantiate.ts +2 -2
  227. package/src/engine/engine_networking_types.ts +41 -1
  228. package/src/engine/engine_physics_rapier.ts +102 -33
  229. package/src/engine/engine_scenedata.ts +3 -3
  230. package/src/engine/engine_serialization_builtin_serializer.ts +32 -9
  231. package/src/engine/engine_serialization_core.ts +9 -0
  232. package/src/engine/engine_types.ts +46 -27
  233. package/src/engine/engine_util_decorator.ts +7 -2
  234. package/src/engine/engine_utils.ts +16 -5
  235. package/src/engine/engine_utils_qrcode.ts +2 -2
  236. package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
  237. package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +2 -2
  238. package/src/engine/webcomponents/needle menu/needle-menu.ts +6 -6
  239. package/src/engine/webcomponents/needle-engine.loading.ts +6 -6
  240. package/src/engine/webcomponents/needle-engine.ts +12 -6
  241. package/src/engine/xr/NeedleXRSession.ts +48 -13
  242. package/src/engine/xr/TempXRContext.ts +2 -2
  243. package/src/engine/xr/events.ts +1 -1
  244. package/src/engine-components/Animation.ts +19 -16
  245. package/src/engine-components/AnimationBuilder.ts +472 -0
  246. package/src/engine-components/Animator.ts +24 -12
  247. package/src/engine-components/AnimatorController.builder.ts +387 -0
  248. package/src/engine-components/AnimatorController.ts +20 -291
  249. package/src/engine-components/AudioSource.ts +130 -79
  250. package/src/engine-components/Collider.ts +66 -18
  251. package/src/engine-components/Component.ts +118 -20
  252. package/src/engine-components/ContactShadows.ts +15 -1
  253. package/src/engine-components/DragControls.ts +18 -11
  254. package/src/engine-components/DropListener.ts +3 -0
  255. package/src/engine-components/EventList.ts +45 -83
  256. package/src/engine-components/Joints.ts +20 -4
  257. package/src/engine-components/Light.ts +10 -2
  258. package/src/engine-components/Networking.ts +1 -1
  259. package/src/engine-components/OrbitControls.ts +34 -14
  260. package/src/engine-components/RigidBody.ts +18 -4
  261. package/src/engine-components/SceneSwitcher.ts +3 -0
  262. package/src/engine-components/SeeThrough.ts +2 -2
  263. package/src/engine-components/api.ts +2 -1
  264. package/src/engine-components/codegen/components.ts +7 -13
  265. package/src/engine-components/export/usdz/USDZExporter.ts +4 -4
  266. package/src/engine-components/timeline/PlayableDirector.ts +83 -81
  267. package/src/engine-components/timeline/SignalAsset.ts +4 -1
  268. package/src/engine-components/timeline/TimelineBuilder.ts +824 -0
  269. package/src/engine-components/timeline/TimelineModels.ts +5 -1
  270. package/src/engine-components/timeline/TimelineTracks.ts +96 -27
  271. package/src/engine-components/timeline/index.ts +2 -1
  272. package/src/engine-components/ui/Canvas.ts +2 -8
  273. package/src/engine-components/ui/Text.ts +12 -8
  274. package/src/engine-components/web/CursorFollow.ts +21 -14
  275. package/src/engine-components/webxr/WebXRImageTracking.ts +2 -0
  276. package/dist/needle-engine.bundle-CmxIO5uH.min.js +0 -1732
  277. package/dist/needle-engine.bundle-tJIZukCz.umd.cjs +0 -1732
  278. package/lib/engine-components/AvatarLoader.d.ts +0 -80
  279. package/lib/engine-components/AvatarLoader.js +0 -232
  280. package/lib/engine-components/AvatarLoader.js.map +0 -1
  281. package/lib/engine-components/avatar/AvatarBlink_Simple.d.ts +0 -11
  282. package/lib/engine-components/avatar/AvatarBlink_Simple.js +0 -77
  283. package/lib/engine-components/avatar/AvatarBlink_Simple.js.map +0 -1
  284. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.d.ts +0 -14
  285. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js +0 -69
  286. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js.map +0 -1
  287. package/lib/engine-components/avatar/Avatar_Brain_LookAt.d.ts +0 -29
  288. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js +0 -122
  289. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js.map +0 -1
  290. package/lib/engine-components/avatar/Avatar_MouthShapes.d.ts +0 -15
  291. package/lib/engine-components/avatar/Avatar_MouthShapes.js +0 -80
  292. package/lib/engine-components/avatar/Avatar_MouthShapes.js.map +0 -1
  293. package/lib/engine-components/avatar/Avatar_MustacheShake.d.ts +0 -9
  294. package/lib/engine-components/avatar/Avatar_MustacheShake.js +0 -30
  295. package/lib/engine-components/avatar/Avatar_MustacheShake.js.map +0 -1
  296. package/plugins/dts-generator/dts.codegen.js +0 -334
  297. package/plugins/dts-generator/dts.scan.js +0 -99
  298. package/plugins/dts-generator/dts.writer.js +0 -59
  299. package/plugins/dts-generator/glb.discovery.js +0 -279
  300. package/plugins/dts-generator/glb.extractor.js +0 -215
  301. package/plugins/dts-generator/glb.reader.js +0 -167
  302. package/plugins/dts-generator/index.js +0 -36
  303. package/plugins/dts-generator/manifest.types.js +0 -174
  304. package/plugins/gltf-packer.mjs +0 -1
  305. package/src/engine-components/AvatarLoader.ts +0 -264
  306. package/src/engine-components/avatar/AvatarBlink_Simple.ts +0 -70
  307. package/src/engine-components/avatar/AvatarEyeLook_Rotation.ts +0 -64
  308. package/src/engine-components/avatar/Avatar_Brain_LookAt.ts +0 -140
  309. package/src/engine-components/avatar/Avatar_MouthShapes.ts +0 -84
  310. package/src/engine-components/avatar/Avatar_MustacheShake.ts +0 -32
  311. package/src/vite-env.d.ts +0 -16
@@ -1,5 +1,6 @@
1
1
  import 'three/examples/jsm/renderers/webgl-legacy/nodes/WebGLNodes.js';
2
2
 
3
+ import type { SceneData } from 'needle-bindings';
3
4
  import type { EffectComposer } from "postprocessing";
4
5
  import {
5
6
  BufferGeometry, Camera, Color, DepthTexture, Group,
@@ -22,6 +23,7 @@ import { Application } from './engine_application.js';
22
23
  import { AssetDatabase } from './engine_assetdatabase.js';
23
24
  import { FocusRect, FocusRectSettings, updateCameraFocusRect } from './engine_camera.js';
24
25
  import { VERSION } from './engine_constants.js';
26
+ import { EventBus } from './engine_context_eventbus.js';
25
27
  import { ContextEvent, ContextRegistry } from './engine_context_registry.js';
26
28
  import { WaitForPromise } from './engine_coroutine.js';
27
29
  import { ObjectUtils } from "./engine_create_objects.js";
@@ -36,9 +38,8 @@ import * as looputils from './engine_mainloop_utils.js';
36
38
  import { NetworkConnection } from './engine_networking.js';
37
39
  import { Physics } from './engine_physics.js';
38
40
  import { PlayerViewManager } from './engine_playerview.js';
39
- import { RendererData as SceneLighting } from './engine_scenelighting.js';
40
41
  import { getSceneData } from './engine_scenedata.js';
41
- import type { SceneData } from 'needle-bindings';
42
+ import { RendererData as SceneLighting } from './engine_scenelighting.js';
42
43
  import { getTempColor, logHierarchy } from './engine_three_utils.js';
43
44
  import { Time } from './engine_time.js';
44
45
  import { patchTonemapping } from './engine_tonemapping.js';
@@ -151,7 +152,7 @@ export function registerComponent(script: IComponent, context?: Context) {
151
152
  }
152
153
 
153
154
  /**
154
- * The Needle Engine context is the main access point that holds all the data and state of a Needle Engine application.
155
+ * The Needle Engine context is the main access point that holds all the data and state of a Needle Engine application.
155
156
  * It can be used to access the {@link Context.scene}, {@link Context.renderer}, {@link Context.mainCamera}, {@link Context.input}, {@link Context.physics}, {@link Context.time}, {@link Context.connection} (networking), and more.
156
157
  *
157
158
  * The context is automatically created when using the `<needle-engine>` web component.
@@ -522,19 +523,31 @@ export class Context implements IContext {
522
523
  private _fallbackCamera: PerspectiveCamera | null = null;
523
524
 
524
525
  /** access application state (e.g. if all audio should be muted) */
525
- application: Application;
526
+ get application(): Application { return this._application; }
527
+ private _application!: Application;
526
528
  /** access animation mixer used by components in the scene */
527
- animations: AnimationsRegistry;
529
+ get animations(): AnimationsRegistry { return this._animations; }
530
+ private _animations!: AnimationsRegistry;
528
531
  /** access timings (current frame number, deltaTime, timeScale, ...) */
529
- time: Time;
532
+ get time(): Time { return this._time; }
533
+ private _time!: Time;
530
534
  /** access input data (e.g. click or touch events) */
531
- input: Input;
535
+ get input(): Input { return this._input; }
536
+ private _input!: Input;
532
537
  /** access physics related methods (e.g. raycasting). To access the phyiscs engine use `context.physics.engine` */
533
- physics: Physics;
538
+ get physics(): Physics { return this._physics; }
539
+ private _physics!: Physics;
534
540
  /** access postprocessing effects stack. Add/remove effects and configure adaptive performance settings */
535
- postprocessing: PostProcessing;
541
+ get postprocessing(): PostProcessing { return this._postprocessing; }
542
+ private _postprocessing!: PostProcessing;
536
543
  /** access networking methods (use it to send or listen to messages or join a networking backend) */
537
- connection: NetworkConnection;
544
+ get connection(): NetworkConnection { return this._connection; }
545
+ private _connection!: NetworkConnection;
546
+ /** context-level event bus for decoupled component communication
547
+ * @see {@link ContextEventMap} for known event types
548
+ */
549
+ get events(): EventBus { return this._events; }
550
+ private _events = new EventBus();
538
551
  /** @deprecated AssetDatabase is deprecated */
539
552
  assets: AssetDatabase;
540
553
 
@@ -606,12 +619,12 @@ export class Context implements IContext {
606
619
  else this.scene = new Scene();
607
620
  if (args?.camera) this._mainCamera = args.camera;
608
621
 
609
- this.application = new Application(this);
610
- this.time = new Time();
611
- this.input = new Input(this);
612
- this.physics = new Physics(this);
613
- this.postprocessing = new PostProcessing(this);
614
- this.connection = new NetworkConnection(this);
622
+ this._application = new Application(this);
623
+ this._time = new Time();
624
+ this._input = new Input(this);
625
+ this._physics = new Physics(this);
626
+ this._postprocessing = new PostProcessing(this);
627
+ this._connection = new NetworkConnection(this);
615
628
  // eslint-disable-next-line @typescript-eslint/no-deprecated
616
629
  this.assets = new AssetDatabase();
617
630
  this.sceneLighting = new SceneLighting(this);
@@ -620,7 +633,7 @@ export class Context implements IContext {
620
633
  this.players = new PlayerViewManager(this);
621
634
  this.menu = new NeedleMenu(this);
622
635
  this.lodsManager = new LODsManager(this);
623
- this.animations = new AnimationsRegistry(this);
636
+ this._animations = new AnimationsRegistry(this);
624
637
  this.accessibility = new AccessibilityManager(this);
625
638
 
626
639
 
@@ -863,12 +876,14 @@ export class Context implements IContext {
863
876
  this.scene = new Scene();
864
877
  this.addressables?.dispose();
865
878
  this.lightmaps?.clear();
866
- this.physics?.engine?.clearCaches();
879
+ this.physics?.engine?.dispose();
867
880
  this.lodsManager.disable();
868
881
  this.accessibility?.clear();
869
882
 
870
883
  this._onBeforeRenderListeners.clear();
871
884
  this._onAfterRenderListeners.clear();
885
+ this._events.clear();
886
+ this._events = new EventBus();
872
887
 
873
888
  this.lights.length = 0;
874
889
 
@@ -912,6 +927,7 @@ export class Context implements IContext {
912
927
  this.scene = null!;
913
928
  this.renderer = null!;
914
929
  this.input.dispose();
930
+ this.connection.dispose();
915
931
  this.menu.onDestroy();
916
932
  this.animations.onDestroy();
917
933
  for (const cb of this._disposeCallbacks) {
@@ -0,0 +1,73 @@
1
+ import type { Object3D } from "three";
2
+
3
+ import type { IComponent } from "./engine_types.js";
4
+
5
+ /** Typed event map for {@link Context.events}.
6
+ * Known events get full autocomplete; custom events can be typed at the call site via generic parameter.
7
+ */
8
+ export interface ContextEventMap {
9
+ "scene-content-changed": {
10
+ /** The component that triggered the change (e.g. SceneSwitcher, DropListener) */
11
+ readonly source: IComponent;
12
+ /** The root object that was added/loaded */
13
+ readonly object: Object3D;
14
+ };
15
+ }
16
+
17
+ /** Options for {@link EventBus.on}. */
18
+ export interface EventBusListenerOptions {
19
+ /** If true the listener is automatically removed after the first invocation. */
20
+ once?: boolean;
21
+ }
22
+
23
+ /** Typed event bus. Known {@link ContextEventMap} events get full autocomplete.
24
+ * Custom events can be typed at the call site via generic parameter.
25
+ * @example Known events
26
+ * ```ts
27
+ * context.events.on("scene-content-changed", e => e.object);
28
+ * ```
29
+ * @example Custom events — type at call site
30
+ * ```ts
31
+ * context.events.emit<{ pts: number }>("scored", { pts: 10 });
32
+ * context.events.on<{ pts: number }>("scored", e => e.pts);
33
+ * ```
34
+ * @example Once
35
+ * ```ts
36
+ * context.events.on("scene-content-changed", e => { ... }, { once: true });
37
+ * ```
38
+ */
39
+ export class EventBus {
40
+ private _listeners = new Map<string, Function[]>();
41
+
42
+ /** Emit a known {@link ContextEventMap} event */
43
+ emit<K extends keyof ContextEventMap & string>(type: K, detail?: ContextEventMap[K]): void;
44
+ /** Emit a custom event with user-provided type */
45
+ emit<T>(type: string, detail?: T): void;
46
+ emit(type: string, detail?: unknown): void {
47
+ const arr = this._listeners.get(type);
48
+ if (arr) for (const cb of [...arr]) cb(detail);
49
+ }
50
+
51
+ /** Subscribe to a known {@link ContextEventMap} event. Returns an unsubscribe function. */
52
+ on<K extends keyof ContextEventMap & string>(type: K, callback: (args: ContextEventMap[K]) => void, options?: EventBusListenerOptions): () => void;
53
+ /** Subscribe to a custom event with user-provided type. Returns an unsubscribe function. */
54
+ on<T>(type: string, callback: (args: T) => void, options?: EventBusListenerOptions): () => void;
55
+ on(type: string, callback: Function, options?: EventBusListenerOptions): () => void {
56
+ let arr = this._listeners.get(type);
57
+ if (!arr) { arr = []; this._listeners.set(type, arr); }
58
+ const unsub = () => {
59
+ const i = arr.indexOf(wrapped);
60
+ if (i >= 0) arr.splice(i, 1);
61
+ };
62
+ const wrapped = options?.once
63
+ ? (...args: unknown[]) => { unsub(); callback(...args); }
64
+ : callback;
65
+ arr.push(wrapped);
66
+ return unsub;
67
+ }
68
+
69
+ /** Remove all listeners. Called when the context is cleared or destroyed. */
70
+ clear(): void {
71
+ this._listeners.clear();
72
+ }
73
+ }
@@ -0,0 +1,214 @@
1
+ /** A function that performs cleanup when called */
2
+ export type DisposeFn = () => void;
3
+
4
+ /**
5
+ * Interface for objects that hold resources and can be disposed.
6
+ * Implement this interface on any object that needs deterministic cleanup.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * class MyResource implements IDisposable {
11
+ * dispose() { /* release resources *\/ }
12
+ * }
13
+ * ```
14
+ *
15
+ * @category Utilities
16
+ * @group Lifecycle
17
+ */
18
+ export interface IDisposable {
19
+ dispose(): void;
20
+ }
21
+
22
+ /**
23
+ * Type guard to check if an object implements {@link IDisposable}.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * if (isDisposable(obj)) {
28
+ * obj.dispose(); // safe to call
29
+ * }
30
+ * ```
31
+ */
32
+ export function isDisposable(value: unknown): value is IDisposable {
33
+ return value !== null
34
+ && typeof value === "object"
35
+ && "dispose" in (value as object)
36
+ && typeof (value as IDisposable).dispose === "function";
37
+ }
38
+
39
+ /**
40
+ * @experimental
41
+ * Subscribe to a DOM event on any {@link EventTarget} (window, document, HTML elements, etc.)
42
+ * and return an {@link IDisposable} that removes the listener when disposed.
43
+ *
44
+ * Provides full TypeScript event type inference — the callback parameter
45
+ * is automatically typed based on the event name (e.g. `"resize"` → `UIEvent`,
46
+ * `"click"` → `MouseEvent`).
47
+ *
48
+ * Use with {@link DisposableStore.add} for automatic lifecycle cleanup in components.
49
+ *
50
+ * @param target The EventTarget to listen on (window, document, an element, etc.)
51
+ * @param type The event name (e.g. `"resize"`, `"click"`, `"keydown"`)
52
+ * @param listener The event handler callback
53
+ * @param options Optional addEventListener options (passive, capture, once, signal)
54
+ * @returns An {@link IDisposable} that removes the event listener when disposed
55
+ *
56
+ * @example Standalone usage
57
+ * ```ts
58
+ * import { on } from "@needle-tools/engine";
59
+ *
60
+ * const sub = on(window, "resize", (ev) => {
61
+ * // ev is typed as UIEvent
62
+ * console.log("resized", ev.target);
63
+ * });
64
+ *
65
+ * // Later: clean up
66
+ * sub.dispose();
67
+ * ```
68
+ *
69
+ * @example With autoCleanup in a component
70
+ * ```ts
71
+ * import { Behaviour, on } from "@needle-tools/engine";
72
+ *
73
+ * export class MyComponent extends Behaviour {
74
+ * onEnable() {
75
+ * this.autoCleanup(on(window, "resize", (ev) => { /* UIEvent *\/ }));
76
+ * this.autoCleanup(on(document, "keydown", (ev) => { /* KeyboardEvent *\/ }));
77
+ * this.autoCleanup(on(this.context.domElement, "click", (ev) => { /* MouseEvent *\/ }));
78
+ * }
79
+ * // All listeners removed automatically on disable!
80
+ * }
81
+ * ```
82
+ *
83
+ * @category Utilities
84
+ * @group Lifecycle
85
+ */
86
+ // #region on
87
+ export function on<K extends keyof WindowEventMap>(target: Window, type: K, listener: (ev: WindowEventMap[K]) => void, options?: boolean | AddEventListenerOptions): IDisposable;
88
+ export function on<K extends keyof DocumentEventMap>(target: Document, type: K, listener: (ev: DocumentEventMap[K]) => void, options?: boolean | AddEventListenerOptions): IDisposable;
89
+ export function on<K extends keyof HTMLElementEventMap>(target: HTMLElement, type: K, listener: (ev: HTMLElementEventMap[K]) => void, options?: boolean | AddEventListenerOptions): IDisposable;
90
+ export function on(target: EventTarget, type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): IDisposable;
91
+ export function on(target: EventTarget, type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): IDisposable {
92
+ target.addEventListener(type, listener, options);
93
+ return {
94
+ dispose() {
95
+ target.removeEventListener(type, listener, options);
96
+ }
97
+ };
98
+ }
99
+
100
+
101
+ /**
102
+ * A store for managing disposable resources (event subscriptions, listeners, callbacks)
103
+ * that should be cleaned up together.
104
+ *
105
+ * DisposableStore collects disposables and disposes them all at once when
106
+ * {@link dispose} is called. After disposal, the store can be reused — new items
107
+ * can be added and a subsequent {@link dispose} call will clean those up.
108
+ *
109
+ * This is the same pattern used internally by VSCode for lifecycle-bound resource management.
110
+ *
111
+ * @example Basic usage
112
+ * ```ts
113
+ * import { DisposableStore, on } from "@needle-tools/engine";
114
+ *
115
+ * const store = new DisposableStore();
116
+ *
117
+ * // Register a DOM event listener (typed!)
118
+ * store.add(on(window, "resize", (ev) => console.log(ev)));
119
+ *
120
+ * // Register the return value of EventList.on()
121
+ * store.add(myEventList.on(data => console.log(data)));
122
+ *
123
+ * // Register a raw cleanup function
124
+ * store.add(() => someSDK.off("event", handler));
125
+ *
126
+ * // Later: dispose everything at once
127
+ * store.dispose();
128
+ * ```
129
+ *
130
+ * @example Use with Needle Engine components
131
+ * ```ts
132
+ * import { Behaviour, serializable, EventList, on } from "@needle-tools/engine";
133
+ *
134
+ * export class MyComponent extends Behaviour {
135
+ * @serializable(EventList)
136
+ * onClick?: EventList;
137
+ *
138
+ * onEnable() {
139
+ * // DOM events — fully typed
140
+ * this.autoCleanup(on(window, "resize", (ev) => this.onResize(ev)));
141
+ *
142
+ * // EventList — .on() returns a function, autoCleanup accepts it
143
+ * this.autoCleanup(this.onClick?.on(() => console.log("clicked!")));
144
+ * }
145
+ * // No onDisable needed — cleaned up automatically!
146
+ * }
147
+ * ```
148
+ *
149
+ * @category Utilities
150
+ * @group Lifecycle
151
+ */
152
+ // #region DisposableStore
153
+ export class DisposableStore implements IDisposable {
154
+
155
+ private _disposables: Array<DisposeFn> = [];
156
+
157
+ /** The number of registered disposables */
158
+ get size() { return this._disposables.length; }
159
+
160
+ /**
161
+ * Register a disposable resource. Accepts:
162
+ * - An {@link IDisposable} object (has a `dispose()` method) — e.g. from {@link on}
163
+ * - A cleanup function (e.g. return value of `EventList.on()`)
164
+ * - `null` or `undefined` (safe no-op for conditional subscriptions)
165
+ *
166
+ * When {@link dispose} is called, all registered resources are cleaned up.
167
+ *
168
+ * @param disposable The resource to register for disposal
169
+ *
170
+ * @example
171
+ * ```ts
172
+ * const store = new DisposableStore();
173
+ *
174
+ * // IDisposable object from on()
175
+ * store.add(on(window, "resize", handler));
176
+ *
177
+ * // Function returned by EventList.on()
178
+ * store.add(myEvent.on(handler));
179
+ *
180
+ * // Raw cleanup function
181
+ * store.add(() => connection.close());
182
+ *
183
+ * // Conditional — safe with undefined
184
+ * store.add(this.maybeEvent?.on(handler));
185
+ * ```
186
+ */
187
+ add(disposable: IDisposable | DisposeFn | Function | null | undefined): void {
188
+ if (!disposable) return;
189
+ if (typeof disposable === "function") {
190
+ this._disposables.push(disposable as DisposeFn);
191
+ }
192
+ else if (typeof disposable === "object" && "dispose" in disposable) {
193
+ this._disposables.push(() => disposable.dispose());
194
+ }
195
+ }
196
+
197
+ /**
198
+ * Dispose all registered resources. Each registered disposable is cleaned up,
199
+ * then the internal list is cleared. The store can be reused after disposal.
200
+ *
201
+ * Called automatically by the engine when a component's `onDisable` lifecycle fires.
202
+ */
203
+ dispose(): void {
204
+ for (let i = this._disposables.length - 1; i >= 0; i--) {
205
+ try {
206
+ this._disposables[i]();
207
+ }
208
+ catch (err) {
209
+ console.error("Error disposing resource", err);
210
+ }
211
+ }
212
+ this._disposables.length = 0;
213
+ }
214
+ }