@needle-tools/engine 5.1.0-canary.deec6e4 → 5.1.0-canary.e6680fa

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 (326) hide show
  1. package/CHANGELOG.md +99 -1
  2. package/SKILL.md +4 -1
  3. package/components.needle.json +1 -1
  4. package/dist/needle-engine.bundle-Bl_hyH5G.umd.cjs +1734 -0
  5. package/dist/needle-engine.bundle-Cduc1gj6.min.js +1734 -0
  6. package/dist/{needle-engine.bundle-CvtELXh0.js → needle-engine.bundle-DNcqT8nJ.js} +19415 -18452
  7. package/dist/needle-engine.d.ts +1588 -374
  8. package/dist/needle-engine.js +572 -569
  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 +46 -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 +186 -58
  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_pmrem.js +51 -3
  70. package/lib/engine/engine_pmrem.js.map +1 -1
  71. package/lib/engine/engine_scenedata.js +2 -2
  72. package/lib/engine/engine_scenedata.js.map +1 -1
  73. package/lib/engine/engine_serialization_builtin_serializer.js +28 -5
  74. package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
  75. package/lib/engine/engine_serialization_core.d.ts +1 -0
  76. package/lib/engine/engine_serialization_core.js +7 -0
  77. package/lib/engine/engine_serialization_core.js.map +1 -1
  78. package/lib/engine/engine_types.d.ts +29 -11
  79. package/lib/engine/engine_types.js +1 -1
  80. package/lib/engine/engine_types.js.map +1 -1
  81. package/lib/engine/engine_util_decorator.js +7 -2
  82. package/lib/engine/engine_util_decorator.js.map +1 -1
  83. package/lib/engine/engine_utils.d.ts +1 -1
  84. package/lib/engine/engine_utils.js +19 -5
  85. package/lib/engine/engine_utils.js.map +1 -1
  86. package/lib/engine/engine_utils_format.js +20 -14
  87. package/lib/engine/engine_utils_format.js.map +1 -1
  88. package/lib/engine/engine_utils_qrcode.js +2 -2
  89. package/lib/engine/engine_utils_qrcode.js.map +1 -1
  90. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
  91. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js.map +1 -1
  92. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +2 -2
  93. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
  94. package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +1 -1
  95. package/lib/engine/webcomponents/needle menu/needle-menu.js +6 -6
  96. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  97. package/lib/engine/webcomponents/needle-engine.d.ts +10 -4
  98. package/lib/engine/webcomponents/needle-engine.js +3 -3
  99. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  100. package/lib/engine/webcomponents/needle-engine.loading.js +2 -2
  101. package/lib/engine/webcomponents/needle-engine.loading.js.map +1 -1
  102. package/lib/engine/xr/NeedleXRSession.d.ts +3 -2
  103. package/lib/engine/xr/NeedleXRSession.js +50 -14
  104. package/lib/engine/xr/NeedleXRSession.js.map +1 -1
  105. package/lib/engine/xr/TempXRContext.js +2 -2
  106. package/lib/engine/xr/TempXRContext.js.map +1 -1
  107. package/lib/engine/xr/events.d.ts +1 -1
  108. package/lib/engine/xr/events.js.map +1 -1
  109. package/lib/engine-components/Animation.js +17 -16
  110. package/lib/engine-components/Animation.js.map +1 -1
  111. package/lib/engine-components/AnimationBuilder.d.ts +158 -0
  112. package/lib/engine-components/AnimationBuilder.js +305 -0
  113. package/lib/engine-components/AnimationBuilder.js.map +1 -0
  114. package/lib/engine-components/Animator.d.ts +6 -0
  115. package/lib/engine-components/Animator.js +23 -13
  116. package/lib/engine-components/Animator.js.map +1 -1
  117. package/lib/engine-components/AnimatorController.builder.d.ts +191 -0
  118. package/lib/engine-components/AnimatorController.builder.js +263 -0
  119. package/lib/engine-components/AnimatorController.builder.js.map +1 -0
  120. package/lib/engine-components/AnimatorController.d.ts +2 -119
  121. package/lib/engine-components/AnimatorController.js +33 -232
  122. package/lib/engine-components/AnimatorController.js.map +1 -1
  123. package/lib/engine-components/AudioSource.d.ts +19 -3
  124. package/lib/engine-components/AudioSource.js +121 -68
  125. package/lib/engine-components/AudioSource.js.map +1 -1
  126. package/lib/engine-components/Camera.d.ts +6 -1
  127. package/lib/engine-components/Camera.js +16 -3
  128. package/lib/engine-components/Camera.js.map +1 -1
  129. package/lib/engine-components/CameraUtils.js +14 -6
  130. package/lib/engine-components/CameraUtils.js.map +1 -1
  131. package/lib/engine-components/Collider.d.ts +18 -9
  132. package/lib/engine-components/Collider.js +61 -14
  133. package/lib/engine-components/Collider.js.map +1 -1
  134. package/lib/engine-components/Component.d.ts +72 -9
  135. package/lib/engine-components/Component.js +114 -10
  136. package/lib/engine-components/Component.js.map +1 -1
  137. package/lib/engine-components/ContactShadows.d.ts +1 -0
  138. package/lib/engine-components/ContactShadows.js +14 -1
  139. package/lib/engine-components/ContactShadows.js.map +1 -1
  140. package/lib/engine-components/DragControls.d.ts +7 -0
  141. package/lib/engine-components/DragControls.js +19 -7
  142. package/lib/engine-components/DragControls.js.map +1 -1
  143. package/lib/engine-components/DropListener.js +4 -0
  144. package/lib/engine-components/DropListener.js.map +1 -1
  145. package/lib/engine-components/EventList.d.ts +31 -9
  146. package/lib/engine-components/EventList.js +37 -76
  147. package/lib/engine-components/EventList.js.map +1 -1
  148. package/lib/engine-components/Joints.d.ts +4 -2
  149. package/lib/engine-components/Joints.js +19 -3
  150. package/lib/engine-components/Joints.js.map +1 -1
  151. package/lib/engine-components/Light.js +9 -1
  152. package/lib/engine-components/Light.js.map +1 -1
  153. package/lib/engine-components/Networking.d.ts +1 -1
  154. package/lib/engine-components/Networking.js +1 -1
  155. package/lib/engine-components/OrbitControls.d.ts +1 -2
  156. package/lib/engine-components/OrbitControls.js +37 -14
  157. package/lib/engine-components/OrbitControls.js.map +1 -1
  158. package/lib/engine-components/RigidBody.d.ts +12 -4
  159. package/lib/engine-components/RigidBody.js +18 -4
  160. package/lib/engine-components/RigidBody.js.map +1 -1
  161. package/lib/engine-components/SceneSwitcher.js +3 -0
  162. package/lib/engine-components/SceneSwitcher.js.map +1 -1
  163. package/lib/engine-components/SeeThrough.js +2 -2
  164. package/lib/engine-components/SeeThrough.js.map +1 -1
  165. package/lib/engine-components/VideoPlayer.d.ts +8 -2
  166. package/lib/engine-components/VideoPlayer.js +42 -19
  167. package/lib/engine-components/VideoPlayer.js.map +1 -1
  168. package/lib/engine-components/Voip.d.ts +16 -7
  169. package/lib/engine-components/Voip.js +90 -53
  170. package/lib/engine-components/Voip.js.map +1 -1
  171. package/lib/engine-components/api.d.ts +3 -1
  172. package/lib/engine-components/api.js +3 -1
  173. package/lib/engine-components/api.js.map +1 -1
  174. package/lib/engine-components/codegen/components.d.ts +7 -13
  175. package/lib/engine-components/codegen/components.js +7 -13
  176. package/lib/engine-components/codegen/components.js.map +1 -1
  177. package/lib/engine-components/export/usdz/USDZExporter.js +4 -4
  178. package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
  179. package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
  180. package/lib/engine-components/timeline/PlayableDirector.d.ts +21 -11
  181. package/lib/engine-components/timeline/PlayableDirector.js +75 -67
  182. package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
  183. package/lib/engine-components/timeline/SignalAsset.d.ts +3 -1
  184. package/lib/engine-components/timeline/SignalAsset.js +1 -0
  185. package/lib/engine-components/timeline/SignalAsset.js.map +1 -1
  186. package/lib/engine-components/timeline/TimelineBuilder.d.ts +413 -0
  187. package/lib/engine-components/timeline/TimelineBuilder.js +506 -0
  188. package/lib/engine-components/timeline/TimelineBuilder.js.map +1 -0
  189. package/lib/engine-components/timeline/TimelineModels.d.ts +2 -1
  190. package/lib/engine-components/timeline/TimelineModels.js +3 -0
  191. package/lib/engine-components/timeline/TimelineModels.js.map +1 -1
  192. package/lib/engine-components/timeline/TimelineTracks.d.ts +37 -6
  193. package/lib/engine-components/timeline/TimelineTracks.js +92 -26
  194. package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
  195. package/lib/engine-components/timeline/index.d.ts +2 -1
  196. package/lib/engine-components/timeline/index.js +2 -0
  197. package/lib/engine-components/timeline/index.js.map +1 -1
  198. package/lib/engine-components/ui/Canvas.d.ts +1 -1
  199. package/lib/engine-components/ui/Canvas.js +2 -8
  200. package/lib/engine-components/ui/Canvas.js.map +1 -1
  201. package/lib/engine-components/ui/Text.d.ts +1 -0
  202. package/lib/engine-components/ui/Text.js +10 -7
  203. package/lib/engine-components/ui/Text.js.map +1 -1
  204. package/lib/engine-components/web/CursorFollow.d.ts +0 -1
  205. package/lib/engine-components/web/CursorFollow.js +21 -13
  206. package/lib/engine-components/web/CursorFollow.js.map +1 -1
  207. package/lib/engine-components/webxr/WebXRImageTracking.d.ts +62 -1
  208. package/lib/engine-components/webxr/WebXRImageTracking.js +59 -2
  209. package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
  210. package/package.json +2 -83
  211. package/plugins/common/cloud.js +6 -1
  212. package/plugins/common/license.js +55 -12
  213. package/plugins/common/worker.js +9 -4
  214. package/plugins/types/userconfig.d.ts +4 -1
  215. package/plugins/vite/asap.js +17 -8
  216. package/plugins/vite/build-pipeline.js +57 -20
  217. package/plugins/vite/dependencies.js +29 -10
  218. package/plugins/vite/dependency-watcher.js +2 -2
  219. package/plugins/vite/editor-connection.js +3 -3
  220. package/plugins/vite/license.js +42 -7
  221. package/plugins/vite/local-files-core.js +3 -3
  222. package/plugins/vite/local-files-utils.d.ts +3 -1
  223. package/plugins/vite/local-files-utils.js +29 -5
  224. package/plugins/vite/reload.js +1 -1
  225. package/plugins/vite/server.js +2 -1
  226. package/src/engine/api.ts +11 -1
  227. package/src/engine/codegen/register_types.ts +10 -18
  228. package/src/engine/engine_audio.ts +184 -0
  229. package/src/engine/engine_camera.fit.ts +15 -4
  230. package/src/engine/engine_components.ts +1 -1
  231. package/src/engine/engine_context.ts +52 -19
  232. package/src/engine/engine_context_eventbus.ts +73 -0
  233. package/src/engine/engine_disposable.ts +214 -0
  234. package/src/engine/engine_gameobject.ts +54 -159
  235. package/src/engine/engine_gltf_builtin_components.ts +7 -76
  236. package/src/engine/engine_init.ts +7 -7
  237. package/src/engine/engine_input.ts +28 -7
  238. package/src/engine/engine_instantiate_resolve.ts +407 -0
  239. package/src/engine/engine_license.ts +202 -56
  240. package/src/engine/engine_mainloop_utils.ts +7 -4
  241. package/src/engine/engine_networking.transport.websocket.ts +45 -0
  242. package/src/engine/engine_networking.ts +161 -137
  243. package/src/engine/engine_networking_blob.ts +4 -4
  244. package/src/engine/engine_networking_instantiate.ts +2 -2
  245. package/src/engine/engine_networking_types.ts +41 -1
  246. package/src/engine/engine_physics_rapier.ts +102 -33
  247. package/src/engine/engine_pmrem.ts +53 -3
  248. package/src/engine/engine_scenedata.ts +3 -3
  249. package/src/engine/engine_serialization_builtin_serializer.ts +32 -9
  250. package/src/engine/engine_serialization_core.ts +9 -0
  251. package/src/engine/engine_types.ts +46 -27
  252. package/src/engine/engine_util_decorator.ts +7 -2
  253. package/src/engine/engine_utils.ts +16 -5
  254. package/src/engine/engine_utils_format.ts +20 -14
  255. package/src/engine/engine_utils_qrcode.ts +2 -2
  256. package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
  257. package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +2 -2
  258. package/src/engine/webcomponents/needle menu/needle-menu.ts +6 -6
  259. package/src/engine/webcomponents/needle-engine.loading.ts +6 -6
  260. package/src/engine/webcomponents/needle-engine.ts +12 -6
  261. package/src/engine/xr/NeedleXRSession.ts +48 -13
  262. package/src/engine/xr/TempXRContext.ts +2 -2
  263. package/src/engine/xr/events.ts +1 -1
  264. package/src/engine-components/Animation.ts +19 -16
  265. package/src/engine-components/AnimationBuilder.ts +472 -0
  266. package/src/engine-components/Animator.ts +24 -12
  267. package/src/engine-components/AnimatorController.builder.ts +387 -0
  268. package/src/engine-components/AnimatorController.ts +20 -291
  269. package/src/engine-components/AudioSource.ts +130 -79
  270. package/src/engine-components/Camera.ts +16 -3
  271. package/src/engine-components/CameraUtils.ts +12 -5
  272. package/src/engine-components/Collider.ts +66 -18
  273. package/src/engine-components/Component.ts +118 -20
  274. package/src/engine-components/ContactShadows.ts +15 -1
  275. package/src/engine-components/DragControls.ts +18 -11
  276. package/src/engine-components/DropListener.ts +4 -0
  277. package/src/engine-components/EventList.ts +45 -83
  278. package/src/engine-components/Joints.ts +20 -4
  279. package/src/engine-components/Light.ts +10 -2
  280. package/src/engine-components/Networking.ts +1 -1
  281. package/src/engine-components/OrbitControls.ts +42 -16
  282. package/src/engine-components/RigidBody.ts +18 -4
  283. package/src/engine-components/SceneSwitcher.ts +3 -0
  284. package/src/engine-components/SeeThrough.ts +2 -2
  285. package/src/engine-components/VideoPlayer.ts +40 -17
  286. package/src/engine-components/Voip.ts +88 -53
  287. package/src/engine-components/api.ts +3 -1
  288. package/src/engine-components/codegen/components.ts +7 -13
  289. package/src/engine-components/export/usdz/USDZExporter.ts +4 -4
  290. package/src/engine-components/timeline/PlayableDirector.ts +83 -81
  291. package/src/engine-components/timeline/SignalAsset.ts +4 -1
  292. package/src/engine-components/timeline/TimelineBuilder.ts +824 -0
  293. package/src/engine-components/timeline/TimelineModels.ts +5 -1
  294. package/src/engine-components/timeline/TimelineTracks.ts +96 -27
  295. package/src/engine-components/timeline/index.ts +2 -1
  296. package/src/engine-components/ui/Canvas.ts +2 -8
  297. package/src/engine-components/ui/Text.ts +12 -8
  298. package/src/engine-components/web/CursorFollow.ts +21 -14
  299. package/src/engine-components/webxr/WebXRImageTracking.ts +79 -7
  300. package/dist/needle-engine.bundle-1s2gOoKZ.min.js +0 -1732
  301. package/dist/needle-engine.bundle-j4nGJXCs.umd.cjs +0 -1732
  302. package/lib/engine-components/AvatarLoader.d.ts +0 -80
  303. package/lib/engine-components/AvatarLoader.js +0 -232
  304. package/lib/engine-components/AvatarLoader.js.map +0 -1
  305. package/lib/engine-components/avatar/AvatarBlink_Simple.d.ts +0 -11
  306. package/lib/engine-components/avatar/AvatarBlink_Simple.js +0 -77
  307. package/lib/engine-components/avatar/AvatarBlink_Simple.js.map +0 -1
  308. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.d.ts +0 -14
  309. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js +0 -69
  310. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js.map +0 -1
  311. package/lib/engine-components/avatar/Avatar_Brain_LookAt.d.ts +0 -29
  312. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js +0 -122
  313. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js.map +0 -1
  314. package/lib/engine-components/avatar/Avatar_MouthShapes.d.ts +0 -15
  315. package/lib/engine-components/avatar/Avatar_MouthShapes.js +0 -80
  316. package/lib/engine-components/avatar/Avatar_MouthShapes.js.map +0 -1
  317. package/lib/engine-components/avatar/Avatar_MustacheShake.d.ts +0 -9
  318. package/lib/engine-components/avatar/Avatar_MustacheShake.js +0 -30
  319. package/lib/engine-components/avatar/Avatar_MustacheShake.js.map +0 -1
  320. package/src/engine-components/AvatarLoader.ts +0 -264
  321. package/src/engine-components/avatar/AvatarBlink_Simple.ts +0 -70
  322. package/src/engine-components/avatar/AvatarEyeLook_Rotation.ts +0 -64
  323. package/src/engine-components/avatar/Avatar_Brain_LookAt.ts +0 -140
  324. package/src/engine-components/avatar/Avatar_MouthShapes.ts +0 -84
  325. package/src/engine-components/avatar/Avatar_MustacheShake.ts +0 -32
  326. package/src/vite-env.d.ts +0 -16
@@ -1,8 +1,8 @@
1
1
  import { Intersection, Matrix4, Object3D, Ray, Vector2, Vector3 } from 'three';
2
2
 
3
3
  import { showBalloonMessage, showBalloonWarning } from './debug/debug.js';
4
- import { PointerEventBase, KeyboardEventBase } from './engine_ssr.js';
5
4
  import { Context } from './engine_setup.js';
5
+ import { KeyboardEventBase,PointerEventBase } from './engine_ssr.js';
6
6
  import { getTempVector, getWorldQuaternion } from './engine_three_utils.js';
7
7
  import type { ButtonName, CursorTypeName, IGameObject, IInput, MouseButtonName, Vec2 } from './engine_types.js';
8
8
  import { DeviceUtilities, type EnumToPrimitiveUnion, getParam } from './engine_utils.js';
@@ -343,14 +343,33 @@ export class Input implements IInput {
343
343
  private readonly _eventListeners: Record<string, RegisteredEventListenerValue> = {};
344
344
 
345
345
  /** Adds an event listener for the specified event type. The callback will be called when the event is triggered.
346
+ *
347
+ * Returns an unsubscribe function — call it to remove the listener.
348
+ * Pass it to {@link Behaviour.autoCleanup} for automatic lifecycle management.
349
+ *
346
350
  * @param type The event type to listen for
347
351
  * @param callback The callback to call when the event is triggered
348
352
  * @param options The options for adding the event listener.
349
- * @example Basic usage
353
+ * @returns A function that removes the event listener when called.
354
+ *
355
+ * @example With autoCleanup (recommended)
350
356
  * ```ts
351
- * input.addEventListener("pointerdown", (evt) => {
357
+ * export class MyComponent extends Behaviour {
358
+ * onEnable() {
359
+ * this.autoCleanup(this.context.input.addEventListener("pointerdown", (evt) => {
360
+ * console.log("Pointer down", evt.pointerId, evt.pointerType);
361
+ * }));
362
+ * }
363
+ * // Listener is automatically removed on disable — no manual cleanup needed!
364
+ * }
365
+ * ```
366
+ * @example Manual unsubscribe
367
+ * ```ts
368
+ * const off = input.addEventListener("pointerdown", (evt) => {
352
369
  * console.log("Pointer down", evt.pointerId, evt.pointerType);
353
370
  * });
371
+ * // later
372
+ * off();
354
373
  * ```
355
374
  * @example Adding a listener that is called after all other listeners
356
375
  * By using a higher value for the queue the listener will be called after other listeners (default queue is 0).
@@ -366,14 +385,14 @@ export class Input implements IInput {
366
385
  * }, { once: true });
367
386
  * ```
368
387
  */
369
- addEventListener(type: PointerEventNames, callback: PointerEventListener, options?: EventListenerOptions);
370
- addEventListener(type: KeyboardEventNames, callback: KeyboardEventListener, options?: EventListenerOptions);
371
- addEventListener(type: InputEvents | InputEventNames, callback: InputEventListener, options?: EventListenerOptions): void {
388
+ addEventListener(type: PointerEventNames, callback: PointerEventListener, options?: EventListenerOptions): () => void;
389
+ addEventListener(type: KeyboardEventNames, callback: KeyboardEventListener, options?: EventListenerOptions): () => void;
390
+ addEventListener(type: InputEvents | InputEventNames, callback: InputEventListener, options?: EventListenerOptions): () => void {
372
391
  if (!this._eventListeners[type]) this._eventListeners[type] = [];
373
392
 
374
393
  if (!callback || typeof callback !== "function") {
375
394
  console.error("Invalid call to addEventListener: callback is required and must be a function!");
376
- return;
395
+ return () => {};
377
396
  }
378
397
 
379
398
  if (!options) options = {};
@@ -392,6 +411,8 @@ export class Input implements IInput {
392
411
  } else {
393
412
  queueListeners.listeners.push({ callback, options });
394
413
  }
414
+
415
+ return () => this.removeEventListener(type as any, callback as any, options);
395
416
  }
396
417
  /** Removes the event listener from the specified event type. If no queue is specified the listener will be removed from all queues.
397
418
  * @param type The event type to remove the listener from
@@ -0,0 +1,407 @@
1
+ import type { Color, Euler, Matrix2, Matrix3, Matrix4, Object3D, Quaternion, Vector2, Vector3, Vector4 } from "three";
2
+
3
+ import { InstantiateIdProvider } from "./engine_networking_instantiate.js";
4
+ import { isSerializable } from "./engine_serialization_core.js";
5
+ import { type GuidsMap, type IComponent, type UIDProvider, isComponent } from "./engine_types.js";
6
+ import { getParam } from "./engine_utils.js";
7
+
8
+ const debug = getParam("debuginstantiate");
9
+
10
+ // ————————————————————————————————————————————————————————
11
+ // Types
12
+ // ————————————————————————————————————————————————————————
13
+
14
+ export type ObjectCloneReference = {
15
+ readonly original: object;
16
+ readonly clone: object;
17
+ }
18
+
19
+ /** Maps uuid/guid → { original, clone } for Object3D and Component instances */
20
+ export type InstantiateReferenceMap = Record<string, ObjectCloneReference>;
21
+
22
+ /**
23
+ * Provides access to the instantiated object map (used by EventList etc.)
24
+ */
25
+ export type InstantiateContext = Readonly<InstantiateReferenceMap>;
26
+
27
+
28
+ // ————————————————————————————————————————————————————————
29
+ // ID Provider Cache (moved from engine_gltf_builtin_components.ts)
30
+ // ————————————————————————————————————————————————————————
31
+
32
+ /**
33
+ * Cache of id providers per component/object guid.
34
+ * Ensures deterministic guid generation regardless of scene order.
35
+ */
36
+ const idProviderCache = new Map<string, InstantiateIdProvider>();
37
+
38
+ /** Clear the id provider cache (e.g. when reloading a context) */
39
+ export function clearIdProviderCache() {
40
+ idProviderCache.clear();
41
+ }
42
+
43
+ // ————————————————————————————————————————————————————————
44
+ // Guid Generation (moved from engine_gltf_builtin_components.ts)
45
+ // ————————————————————————————————————————————————————————
46
+
47
+ export const originalComponentNameKey = Symbol("original-component-name");
48
+
49
+ // #region hierarchy guids
50
+ /**
51
+ * Recursively generates new deterministic guids for all objects and components in a hierarchy.
52
+ * Uses the idProviderCache so that the same source guid always produces the same output guid
53
+ * (needed for networking: all clients must agree on the guids of instantiated objects).
54
+ * Populates guidsMap (oldGuid → newGuid) so string references can be remapped afterwards.
55
+ */
56
+ export function generateGuidsForHierarchy(
57
+ obj: Object3D,
58
+ idProvider: UIDProvider | null,
59
+ guidsMap: GuidsMap,
60
+ ): void {
61
+ if (idProvider === null) return;
62
+ if (!obj) return;
63
+ const prev = (obj as any).guid;
64
+
65
+ // Use a cached id provider per object to ensure stable guids regardless of hierarchy order
66
+ const idProviderKey = (obj as any).guid;
67
+ if (idProviderKey?.length) {
68
+ if (!idProviderCache.has(idProviderKey)) {
69
+ if (debug) console.log("Creating InstanceIdProvider with key \"" + idProviderKey + "\" for object " + obj.name);
70
+ idProviderCache.set(idProviderKey, new InstantiateIdProvider(idProviderKey));
71
+ }
72
+ }
73
+ const objectIdProvider = idProviderKey && idProviderCache.get(idProviderKey) || idProvider;
74
+
75
+ (obj as any).guid = objectIdProvider.generateUUID();
76
+ if (prev && prev !== "invalid")
77
+ guidsMap[prev] = (obj as any).guid;
78
+
79
+ if (obj && obj.userData && obj.userData.components) {
80
+ for (const comp of obj.userData.components) {
81
+ if (comp === null) continue;
82
+
83
+ const compIdProviderKey = comp.guid;
84
+ if (compIdProviderKey) {
85
+ if (!idProviderCache.has(compIdProviderKey)) {
86
+ if (debug) console.log("Creating InstanceIdProvider with key \"" + compIdProviderKey + "\" for component " + comp[originalComponentNameKey]);
87
+ idProviderCache.set(compIdProviderKey, new InstantiateIdProvider(compIdProviderKey));
88
+ }
89
+ }
90
+ else if (debug) console.warn("Can not create IdProvider: component " + comp[originalComponentNameKey] + " has no guid", comp.guid);
91
+ const componentIdProvider = idProviderCache.get(compIdProviderKey) || idProvider;
92
+
93
+ const compPrev = comp.guid;
94
+ comp.guid = componentIdProvider.generateUUID();
95
+ if (compPrev && compPrev !== "invalid")
96
+ guidsMap[compPrev] = comp.guid;
97
+ }
98
+ }
99
+ if (obj.children) {
100
+ for (const child of obj.children) {
101
+ generateGuidsForHierarchy(child as Object3D, idProvider, guidsMap);
102
+ }
103
+ }
104
+ }
105
+
106
+ // ————————————————————————————————————————————————————————
107
+ // #region reference resolution
108
+ // ————————————————————————————————————————————————————————
109
+
110
+ /**
111
+ * The unified reference resolution function.
112
+ * Iterates all cloned components in the objectMap and remaps their properties
113
+ * to point at cloned counterparts where appropriate.
114
+ *
115
+ * Handles: Component, Object3D, Array, Map, Set, Record/plain objects,
116
+ * EventList, Vector/Color/Quaternion, and @serializable nested objects.
117
+ */
118
+ export function resolveInstanceReferences(objectMap: InstantiateReferenceMap): void {
119
+ for (const key in objectMap) {
120
+ const val = objectMap[key];
121
+ const clone = val.clone as Object3D | null;
122
+ if (!clone?.isObject3D || !clone?.userData?.components) continue;
123
+
124
+ for (let i = 0; i < clone.userData.components.length; i++) {
125
+ const component = clone.userData.components[i];
126
+ const entries = Object.entries(component);
127
+ for (const [propKey, propValue] of entries) {
128
+ if (propValue === null || propValue === undefined) continue;
129
+ // Skip primitives that can't be remapped, but allow strings for guid resolution
130
+ if (typeof propValue !== "object" && typeof propValue !== "string") continue;
131
+ const resolved = resolveValue(propKey, propValue, objectMap);
132
+ if (resolved !== undefined) {
133
+ component[propKey] = resolved;
134
+ }
135
+ }
136
+ }
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Resolves string-based guid references in all components of a hierarchy using a GuidsMap.
142
+ * Used by the glTF loading path where objects get new guids assigned and string references
143
+ * (e.g. PlayableDirector track.outputs) need to be updated.
144
+ */
145
+ export function resolveStringGuidsInHierarchy(root: Object3D, guidsMap: GuidsMap): void {
146
+ resolveStringGuidsRecursive(root, guidsMap);
147
+ }
148
+
149
+ function resolveStringGuidsRecursive(obj: Object3D, guidsMap: GuidsMap): void {
150
+ if (obj.userData?.components) {
151
+ for (const component of obj.userData.components) {
152
+ if (component === null) continue;
153
+ resolveStringGuidsInObject(component, guidsMap);
154
+ }
155
+ }
156
+ if (obj.children) {
157
+ for (const child of obj.children) {
158
+ resolveStringGuidsRecursive(child as Object3D, guidsMap);
159
+ }
160
+ }
161
+ }
162
+
163
+ function resolveStringGuidsInObject(obj: any, guidsMap: GuidsMap, visited?: WeakSet<object>): void {
164
+ if (!visited) visited = new WeakSet();
165
+ if (visited.has(obj)) return;
166
+ visited.add(obj);
167
+
168
+ for (const key of Object.keys(obj)) {
169
+ const value = obj[key];
170
+ if (value === null || value === undefined) continue;
171
+ if (typeof value === "string") {
172
+ if (guidsMap[value]) {
173
+ obj[key] = guidsMap[value];
174
+ }
175
+ }
176
+ else if (Array.isArray(value)) {
177
+ for (let i = 0; i < value.length; i++) {
178
+ if (typeof value[i] === "string" && guidsMap[value[i]]) {
179
+ value[i] = guidsMap[value[i]];
180
+ }
181
+ else if (typeof value[i] === "object" && value[i] !== null) {
182
+ resolveStringGuidsInObject(value[i], guidsMap, visited);
183
+ }
184
+ }
185
+ }
186
+ else if (typeof value === "object") {
187
+ // Skip known non-data objects
188
+ if (value.isObject3D || value.isComponent) continue;
189
+ resolveStringGuidsInObject(value, guidsMap, visited);
190
+ }
191
+ }
192
+ }
193
+
194
+ // #region resolveValue
195
+ /**
196
+ * Resolve a single value, returning the remapped value or undefined if no remap needed.
197
+ * This is the core remapping logic called recursively for nested structures.
198
+ */
199
+ export function resolveValue(key: string, value: unknown, objectMap: InstantiateReferenceMap): any | undefined {
200
+
201
+ // Handle null/undefined early to avoid unnecessary processing
202
+ if (value === undefined) return undefined;
203
+ if (value === null) return null;
204
+
205
+ // String guid resolution: if this string is a known guid/uuid in the objectMap,
206
+ // resolve it directly to the clone object. This handles e.g. PlayableDirector track.outputs.
207
+ if (typeof value === "string") {
208
+ const ref = objectMap[value];
209
+ if (ref) {
210
+ return ref.clone;
211
+ }
212
+ return undefined;
213
+ }
214
+
215
+ // Primitives: no remapping needed
216
+ if (typeof value !== "object") return undefined;
217
+
218
+ // 1. Component → find cloned counterpart by gameObject.uuid + component index
219
+ if (isComponent(value)) {
220
+ return resolveComponentReference(value, objectMap);
221
+ }
222
+
223
+ // 2. Object3D → uuid lookup, return clone if found (otherwise external, keep as-is)
224
+ if ((value as Object3D).isObject3D === true) {
225
+ if (key === "gameObject") return undefined;
226
+ const id = (value as Object3D).uuid;
227
+ const cloneRef = objectMap[id]?.clone;
228
+ if (cloneRef) {
229
+ if (debug) console.log(key, "old", value, "new", cloneRef);
230
+ return cloneRef;
231
+ }
232
+ return undefined;
233
+ }
234
+
235
+ // 3. Cloneable value types (Vector3, Quaternion, Euler, Color)
236
+ if (isCloneableValueType(value)) {
237
+ return value.clone();
238
+ }
239
+
240
+ // 4. Array → create new array, recursively resolve each element
241
+ if (Array.isArray(value)) {
242
+ return resolveArray(key, value, objectMap);
243
+ }
244
+
245
+ // 5. Map → create new Map, resolve keys and values
246
+ if (value instanceof Map) {
247
+ return resolveMap(value, objectMap);
248
+ }
249
+
250
+ // 6. Set → create new Set, resolve values
251
+ if (value instanceof Set) {
252
+ return resolveSet(value, objectMap);
253
+ }
254
+
255
+ // 7. WeakMap / WeakSet → NOT iterable, cannot remap. Keep as-is.
256
+ if (value instanceof WeakMap || value instanceof WeakSet) {
257
+ return undefined;
258
+ }
259
+
260
+ // 8. @serializable objects (incl. EventList, CallInfo) → shallow clone + recursively resolve $serializedTypes fields
261
+ if (isSerializable(value) && value.$serializedTypes) {
262
+ return resolveSerializableObject(value, objectMap);
263
+ }
264
+
265
+ // 9. Plain objects / Records → shallow clone, resolve each value
266
+ if (isPlainObject(value)) {
267
+ return resolvePlainObject(key, value, objectMap);
268
+ }
269
+
270
+ return undefined;
271
+ }
272
+
273
+ // ————————————————————————————————————————————————————————
274
+ // Internal Helpers
275
+ // ————————————————————————————————————————————————————————
276
+
277
+ function resolveComponentReference(value: IComponent, objectMap: InstantiateReferenceMap): object | undefined {
278
+ const originalGameObject = value["gameObject"] as Object3D | undefined;
279
+ if (!originalGameObject) return undefined;
280
+
281
+ const id = originalGameObject.uuid;
282
+ const newGameObject = objectMap[id]?.clone as Object3D | undefined;
283
+ if (!newGameObject) {
284
+ // Reference points to an object not in the cloned hierarchy (external)
285
+ if (debug) console.log("Component reference did not change (external)", value);
286
+ return undefined;
287
+ }
288
+
289
+ const index = originalGameObject.userData.components.indexOf(value);
290
+ if (index >= 0 && newGameObject.isObject3D) {
291
+ if (debug) console.log("Resolved component", id, "at index", index);
292
+ return newGameObject.userData.components[index];
293
+ }
294
+ else {
295
+ console.warn("Could not find component at expected index", value);
296
+ }
297
+ return undefined;
298
+ }
299
+
300
+ function resolveArray(key: string, arr: unknown[], objectMap: InstantiateReferenceMap): unknown[] {
301
+ const result: unknown[] = [];
302
+ for (let i = 0; i < arr.length; i++) {
303
+ const entry = arr[i];
304
+ if (entry === null || entry === undefined) {
305
+ result.push(entry);
306
+ continue;
307
+ }
308
+ // Skip primitives that can't be remapped (numbers, booleans)
309
+ // but allow strings through for guid resolution
310
+ if (typeof entry !== "object" && typeof entry !== "string") {
311
+ result.push(entry);
312
+ continue;
313
+ }
314
+ const resolved = resolveValue(key, entry, objectMap);
315
+ result.push(resolved !== undefined ? resolved : entry);
316
+ }
317
+ return result;
318
+ }
319
+
320
+ function resolveMap(map: Map<unknown, unknown>, objectMap: InstantiateReferenceMap): Map<any, any> {
321
+ const result = new Map();
322
+ let didChange = false;
323
+ for (const [mapKey, mapValue] of map) {
324
+ let resolvedKey = mapKey;
325
+ let resolvedValue = mapValue;
326
+
327
+ if (typeof mapKey === "object" && mapKey !== null) {
328
+ const rk = resolveValue("", mapKey, objectMap);
329
+ if (rk !== undefined) { resolvedKey = rk; didChange = true; }
330
+ }
331
+ if (typeof mapValue === "object" && mapValue !== null) {
332
+ const rv = resolveValue("", mapValue, objectMap);
333
+ if (rv !== undefined) { resolvedValue = rv; didChange = true; }
334
+ }
335
+ result.set(resolvedKey, resolvedValue);
336
+ }
337
+ return didChange ? result : result; // always return new Map to prevent shared mutation
338
+ }
339
+
340
+ function resolveSet(set: Set<unknown>, objectMap: InstantiateReferenceMap): Set<any> {
341
+ const result = new Set();
342
+ for (const entry of set) {
343
+ if (typeof entry === "object" && entry !== null) {
344
+ const resolved = resolveValue("", entry, objectMap);
345
+ result.add(resolved !== undefined ? resolved : entry);
346
+ } else {
347
+ result.add(entry);
348
+ }
349
+ }
350
+ return result;
351
+ }
352
+
353
+ function resolveSerializableObject(value: unknown, objectMap: InstantiateReferenceMap): any | undefined {
354
+ // Clone the serializable object to avoid mutating the original (which may be shared with source)
355
+ const cloned = Object.assign(Object.create(Object.getPrototypeOf(value)), value);
356
+ let didChange = false;
357
+ for (const key in cloned.$serializedTypes) {
358
+ const val = cloned[key];
359
+ if (val === null || val === undefined) continue;
360
+ if (typeof val === "object") {
361
+ if (debug) console.log("Recursively resolve references for", key, val);
362
+ const resolved = resolveValue(key, val, objectMap);
363
+ if (resolved !== undefined) {
364
+ cloned[key] = resolved;
365
+ didChange = true;
366
+ }
367
+ }
368
+ }
369
+ return didChange ? cloned : undefined;
370
+ }
371
+
372
+ function resolvePlainObject(_parentKey: string, obj: Record<string, unknown>, objectMap: InstantiateReferenceMap): Record<string, unknown> | undefined {
373
+ let didChange = false;
374
+ const clone = { ...obj };
375
+ for (const key of Object.keys(clone)) {
376
+ const val = clone[key];
377
+ if (val === null || val === undefined) continue;
378
+ // Skip primitives that can't be remapped, but allow strings for guid resolution
379
+ if (typeof val !== "object" && typeof val !== "string") continue;
380
+ const resolved = resolveValue(key, val, objectMap);
381
+ if (resolved !== undefined) {
382
+ clone[key] = resolved;
383
+ didChange = true;
384
+ }
385
+ }
386
+ return didChange ? clone : undefined;
387
+ }
388
+
389
+ function isPlainObject(obj: unknown): obj is Record<string, unknown> {
390
+ if (typeof obj !== "object" || obj === null) return false;
391
+ const proto = Object.getPrototypeOf(obj);
392
+ return proto === Object.prototype || proto === null;
393
+ }
394
+
395
+ /** Returns true if the object is a three.js value type that should be cloned (not remapped) */
396
+ function isCloneableValueType(value: object): value is { clone(): object } {
397
+ return (value as Vector2).isVector2 === true ||
398
+ (value as Vector3).isVector3 === true ||
399
+ (value as Vector4).isVector4 === true ||
400
+ (value as Quaternion).isQuaternion === true ||
401
+ (value as Euler).isEuler === true ||
402
+ (value as Color).isColor === true ||
403
+ (value as Matrix2).isMatrix2 === true ||
404
+ (value as Matrix3).isMatrix3 === true ||
405
+ (value as Matrix4).isMatrix4 === true;
406
+ }
407
+