@needle-tools/engine 5.1.0-canary.db0c38f → 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 (381) hide show
  1. package/.needle/generated/needle-bindings.gen.d.ts +5 -0
  2. package/CHANGELOG.md +133 -1
  3. package/SKILL.md +4 -1
  4. package/components.needle.json +1 -1
  5. package/dist/needle-engine.bundle-Bl_hyH5G.umd.cjs +1734 -0
  6. package/dist/needle-engine.bundle-Cduc1gj6.min.js +1734 -0
  7. package/dist/{needle-engine.bundle-B29kieh0.js → needle-engine.bundle-DNcqT8nJ.js} +13770 -12741
  8. package/dist/needle-engine.d.ts +1628 -402
  9. package/dist/needle-engine.js +591 -586
  10. package/dist/needle-engine.min.js +1 -1
  11. package/dist/needle-engine.umd.cjs +1 -1
  12. package/dist/three.js +1 -0
  13. package/dist/three.min.js +21 -21
  14. package/dist/three.umd.cjs +16 -16
  15. package/lib/engine/api.d.ts +9 -2
  16. package/lib/engine/api.js +7 -1
  17. package/lib/engine/api.js.map +1 -1
  18. package/lib/engine/codegen/register_types.js +10 -18
  19. package/lib/engine/codegen/register_types.js.map +1 -1
  20. package/lib/engine/debug/debug_spatial_console.d.ts +2 -0
  21. package/lib/engine/debug/debug_spatial_console.js +10 -7
  22. package/lib/engine/debug/debug_spatial_console.js.map +1 -1
  23. package/lib/engine/engine_addressables.d.ts +2 -0
  24. package/lib/engine/engine_addressables.js +6 -3
  25. package/lib/engine/engine_addressables.js.map +1 -1
  26. package/lib/engine/engine_audio.d.ts +68 -0
  27. package/lib/engine/engine_audio.js +172 -0
  28. package/lib/engine/engine_audio.js.map +1 -1
  29. package/lib/engine/engine_camera.fit.js +16 -4
  30. package/lib/engine/engine_camera.fit.js.map +1 -1
  31. package/lib/engine/engine_components.js +1 -1
  32. package/lib/engine/engine_components.js.map +1 -1
  33. package/lib/engine/engine_context.d.ts +41 -27
  34. package/lib/engine/engine_context.js +71 -30
  35. package/lib/engine/engine_context.js.map +1 -1
  36. package/lib/engine/engine_context_eventbus.d.ts +47 -0
  37. package/lib/engine/engine_context_eventbus.js +47 -0
  38. package/lib/engine/engine_context_eventbus.js.map +1 -0
  39. package/lib/engine/engine_disposable.d.ts +172 -0
  40. package/lib/engine/engine_disposable.js +136 -0
  41. package/lib/engine/engine_disposable.js.map +1 -0
  42. package/lib/engine/engine_gameobject.d.ts +1 -10
  43. package/lib/engine/engine_gameobject.js +22 -120
  44. package/lib/engine/engine_gameobject.js.map +1 -1
  45. package/lib/engine/engine_gltf_builtin_components.js +7 -69
  46. package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
  47. package/lib/engine/engine_init.js +16 -1
  48. package/lib/engine/engine_init.js.map +1 -1
  49. package/lib/engine/engine_input.d.ts +24 -5
  50. package/lib/engine/engine_input.js +3 -2
  51. package/lib/engine/engine_input.js.map +1 -1
  52. package/lib/engine/engine_instantiate_resolve.d.ts +42 -0
  53. package/lib/engine/engine_instantiate_resolve.js +372 -0
  54. package/lib/engine/engine_instantiate_resolve.js.map +1 -0
  55. package/lib/engine/engine_license.d.ts +8 -6
  56. package/lib/engine/engine_license.js +195 -59
  57. package/lib/engine/engine_license.js.map +1 -1
  58. package/lib/engine/engine_lifecycle_functions_internal.js +5 -0
  59. package/lib/engine/engine_lifecycle_functions_internal.js.map +1 -1
  60. package/lib/engine/engine_mainloop_utils.js +7 -4
  61. package/lib/engine/engine_mainloop_utils.js.map +1 -1
  62. package/lib/engine/engine_networking.d.ts +51 -37
  63. package/lib/engine/engine_networking.js +132 -82
  64. package/lib/engine/engine_networking.js.map +1 -1
  65. package/lib/engine/engine_networking.transport.websocket.d.ts +15 -0
  66. package/lib/engine/engine_networking.transport.websocket.js +38 -0
  67. package/lib/engine/engine_networking.transport.websocket.js.map +1 -0
  68. package/lib/engine/engine_networking_blob.js +4 -4
  69. package/lib/engine/engine_networking_blob.js.map +1 -1
  70. package/lib/engine/engine_networking_instantiate.js +2 -2
  71. package/lib/engine/engine_networking_instantiate.js.map +1 -1
  72. package/lib/engine/engine_networking_types.d.ts +39 -1
  73. package/lib/engine/engine_networking_types.js +7 -0
  74. package/lib/engine/engine_networking_types.js.map +1 -1
  75. package/lib/engine/engine_physics_rapier.d.ts +21 -3
  76. package/lib/engine/engine_physics_rapier.js +94 -25
  77. package/lib/engine/engine_physics_rapier.js.map +1 -1
  78. package/lib/engine/engine_pmrem.js +53 -5
  79. package/lib/engine/engine_pmrem.js.map +1 -1
  80. package/lib/engine/engine_scenedata.d.ts +13 -17
  81. package/lib/engine/engine_scenedata.js +58 -31
  82. package/lib/engine/engine_scenedata.js.map +1 -1
  83. package/lib/engine/engine_serialization_builtin_serializer.d.ts +10 -16
  84. package/lib/engine/engine_serialization_builtin_serializer.js +56 -46
  85. package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
  86. package/lib/engine/engine_serialization_core.d.ts +1 -0
  87. package/lib/engine/engine_serialization_core.js +7 -0
  88. package/lib/engine/engine_serialization_core.js.map +1 -1
  89. package/lib/engine/engine_ssr.d.ts +2 -0
  90. package/lib/engine/engine_ssr.js +20 -0
  91. package/lib/engine/engine_ssr.js.map +1 -1
  92. package/lib/engine/engine_types.d.ts +31 -11
  93. package/lib/engine/engine_types.js +1 -1
  94. package/lib/engine/engine_types.js.map +1 -1
  95. package/lib/engine/engine_util_decorator.js +7 -2
  96. package/lib/engine/engine_util_decorator.js.map +1 -1
  97. package/lib/engine/engine_utils.d.ts +1 -1
  98. package/lib/engine/engine_utils.js +19 -5
  99. package/lib/engine/engine_utils.js.map +1 -1
  100. package/lib/engine/engine_utils_format.js +20 -14
  101. package/lib/engine/engine_utils_format.js.map +1 -1
  102. package/lib/engine/engine_utils_qrcode.js +2 -2
  103. package/lib/engine/engine_utils_qrcode.js.map +1 -1
  104. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
  105. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js.map +1 -1
  106. package/lib/engine/webcomponents/jsx.d.ts +51 -0
  107. package/lib/engine/webcomponents/logo-element.js.map +1 -1
  108. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +2 -2
  109. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
  110. package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +3 -4
  111. package/lib/engine/webcomponents/needle menu/needle-menu.js +6 -6
  112. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  113. package/lib/engine/webcomponents/needle-button.js.map +1 -1
  114. package/lib/engine/webcomponents/needle-engine.d.ts +10 -4
  115. package/lib/engine/webcomponents/needle-engine.js +3 -3
  116. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  117. package/lib/engine/webcomponents/needle-engine.loading.js +2 -2
  118. package/lib/engine/webcomponents/needle-engine.loading.js.map +1 -1
  119. package/lib/engine/xr/NeedleXRSession.d.ts +3 -2
  120. package/lib/engine/xr/NeedleXRSession.js +50 -14
  121. package/lib/engine/xr/NeedleXRSession.js.map +1 -1
  122. package/lib/engine/xr/TempXRContext.js +2 -2
  123. package/lib/engine/xr/TempXRContext.js.map +1 -1
  124. package/lib/engine/xr/events.d.ts +1 -1
  125. package/lib/engine/xr/events.js.map +1 -1
  126. package/lib/engine-components/Animation.js +17 -16
  127. package/lib/engine-components/Animation.js.map +1 -1
  128. package/lib/engine-components/AnimationBuilder.d.ts +158 -0
  129. package/lib/engine-components/AnimationBuilder.js +305 -0
  130. package/lib/engine-components/AnimationBuilder.js.map +1 -0
  131. package/lib/engine-components/Animator.d.ts +6 -0
  132. package/lib/engine-components/Animator.js +23 -13
  133. package/lib/engine-components/Animator.js.map +1 -1
  134. package/lib/engine-components/AnimatorController.builder.d.ts +191 -0
  135. package/lib/engine-components/AnimatorController.builder.js +263 -0
  136. package/lib/engine-components/AnimatorController.builder.js.map +1 -0
  137. package/lib/engine-components/AnimatorController.d.ts +4 -119
  138. package/lib/engine-components/AnimatorController.js +37 -233
  139. package/lib/engine-components/AnimatorController.js.map +1 -1
  140. package/lib/engine-components/AudioSource.d.ts +19 -3
  141. package/lib/engine-components/AudioSource.js +121 -68
  142. package/lib/engine-components/AudioSource.js.map +1 -1
  143. package/lib/engine-components/Camera.d.ts +6 -1
  144. package/lib/engine-components/Camera.js +16 -3
  145. package/lib/engine-components/Camera.js.map +1 -1
  146. package/lib/engine-components/CameraUtils.js +14 -6
  147. package/lib/engine-components/CameraUtils.js.map +1 -1
  148. package/lib/engine-components/Collider.d.ts +18 -9
  149. package/lib/engine-components/Collider.js +61 -14
  150. package/lib/engine-components/Collider.js.map +1 -1
  151. package/lib/engine-components/Component.d.ts +72 -9
  152. package/lib/engine-components/Component.js +114 -10
  153. package/lib/engine-components/Component.js.map +1 -1
  154. package/lib/engine-components/ContactShadows.d.ts +1 -0
  155. package/lib/engine-components/ContactShadows.js +14 -1
  156. package/lib/engine-components/ContactShadows.js.map +1 -1
  157. package/lib/engine-components/DragControls.d.ts +7 -0
  158. package/lib/engine-components/DragControls.js +19 -7
  159. package/lib/engine-components/DragControls.js.map +1 -1
  160. package/lib/engine-components/DropListener.js +4 -0
  161. package/lib/engine-components/DropListener.js.map +1 -1
  162. package/lib/engine-components/EventList.d.ts +31 -9
  163. package/lib/engine-components/EventList.js +37 -76
  164. package/lib/engine-components/EventList.js.map +1 -1
  165. package/lib/engine-components/Joints.d.ts +4 -2
  166. package/lib/engine-components/Joints.js +19 -3
  167. package/lib/engine-components/Joints.js.map +1 -1
  168. package/lib/engine-components/Light.d.ts +6 -8
  169. package/lib/engine-components/Light.js +48 -27
  170. package/lib/engine-components/Light.js.map +1 -1
  171. package/lib/engine-components/Networking.d.ts +1 -1
  172. package/lib/engine-components/Networking.js +1 -1
  173. package/lib/engine-components/OrbitControls.d.ts +1 -2
  174. package/lib/engine-components/OrbitControls.js +37 -14
  175. package/lib/engine-components/OrbitControls.js.map +1 -1
  176. package/lib/engine-components/ReflectionProbe.js +2 -0
  177. package/lib/engine-components/ReflectionProbe.js.map +1 -1
  178. package/lib/engine-components/RigidBody.d.ts +12 -4
  179. package/lib/engine-components/RigidBody.js +18 -4
  180. package/lib/engine-components/RigidBody.js.map +1 -1
  181. package/lib/engine-components/SceneSwitcher.js +3 -0
  182. package/lib/engine-components/SceneSwitcher.js.map +1 -1
  183. package/lib/engine-components/SeeThrough.js +2 -2
  184. package/lib/engine-components/SeeThrough.js.map +1 -1
  185. package/lib/engine-components/VideoPlayer.d.ts +8 -2
  186. package/lib/engine-components/VideoPlayer.js +42 -19
  187. package/lib/engine-components/VideoPlayer.js.map +1 -1
  188. package/lib/engine-components/Voip.d.ts +16 -7
  189. package/lib/engine-components/Voip.js +90 -53
  190. package/lib/engine-components/Voip.js.map +1 -1
  191. package/lib/engine-components/api.d.ts +3 -1
  192. package/lib/engine-components/api.js +3 -1
  193. package/lib/engine-components/api.js.map +1 -1
  194. package/lib/engine-components/codegen/components.d.ts +7 -13
  195. package/lib/engine-components/codegen/components.js +7 -13
  196. package/lib/engine-components/codegen/components.js.map +1 -1
  197. package/lib/engine-components/export/usdz/USDZExporter.js +4 -4
  198. package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
  199. package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
  200. package/lib/engine-components/postprocessing/VolumeParameter.d.ts +2 -0
  201. package/lib/engine-components/postprocessing/VolumeParameter.js +4 -1
  202. package/lib/engine-components/postprocessing/VolumeParameter.js.map +1 -1
  203. package/lib/engine-components/timeline/PlayableDirector.d.ts +21 -11
  204. package/lib/engine-components/timeline/PlayableDirector.js +75 -67
  205. package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
  206. package/lib/engine-components/timeline/SignalAsset.d.ts +3 -1
  207. package/lib/engine-components/timeline/SignalAsset.js +1 -0
  208. package/lib/engine-components/timeline/SignalAsset.js.map +1 -1
  209. package/lib/engine-components/timeline/TimelineBuilder.d.ts +413 -0
  210. package/lib/engine-components/timeline/TimelineBuilder.js +506 -0
  211. package/lib/engine-components/timeline/TimelineBuilder.js.map +1 -0
  212. package/lib/engine-components/timeline/TimelineModels.d.ts +2 -1
  213. package/lib/engine-components/timeline/TimelineModels.js +3 -0
  214. package/lib/engine-components/timeline/TimelineModels.js.map +1 -1
  215. package/lib/engine-components/timeline/TimelineTracks.d.ts +37 -6
  216. package/lib/engine-components/timeline/TimelineTracks.js +92 -26
  217. package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
  218. package/lib/engine-components/timeline/index.d.ts +2 -1
  219. package/lib/engine-components/timeline/index.js +2 -0
  220. package/lib/engine-components/timeline/index.js.map +1 -1
  221. package/lib/engine-components/ui/Canvas.d.ts +1 -1
  222. package/lib/engine-components/ui/Canvas.js +2 -8
  223. package/lib/engine-components/ui/Canvas.js.map +1 -1
  224. package/lib/engine-components/ui/Text.d.ts +1 -0
  225. package/lib/engine-components/ui/Text.js +10 -7
  226. package/lib/engine-components/ui/Text.js.map +1 -1
  227. package/lib/engine-components/web/CursorFollow.d.ts +0 -1
  228. package/lib/engine-components/web/CursorFollow.js +21 -13
  229. package/lib/engine-components/web/CursorFollow.js.map +1 -1
  230. package/lib/engine-components/webxr/WebXRImageTracking.d.ts +62 -1
  231. package/lib/engine-components/webxr/WebXRImageTracking.js +59 -2
  232. package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
  233. package/lib/needle-engine.d.ts +2 -0
  234. package/lib/needle-engine.js +2 -0
  235. package/lib/needle-engine.js.map +1 -1
  236. package/package.json +4 -84
  237. package/plugins/common/cloud.js +6 -1
  238. package/plugins/common/license.js +55 -12
  239. package/plugins/common/worker.js +9 -4
  240. package/plugins/dts-generator/dts.codegen.js +255 -50
  241. package/plugins/dts-generator/dts.scan.js +37 -9
  242. package/plugins/dts-generator/dts.writer.js +1 -1
  243. package/plugins/dts-generator/glb.discovery.js +140 -23
  244. package/plugins/dts-generator/glb.extractor.js +48 -8
  245. package/plugins/dts-generator/glb.reader.js +80 -27
  246. package/plugins/dts-generator/index.js +1 -1
  247. package/plugins/types/needle-bindings.d.ts +25 -14
  248. package/plugins/types/userconfig.d.ts +16 -1
  249. package/plugins/vite/asap.js +18 -9
  250. package/plugins/vite/build-pipeline.js +57 -20
  251. package/plugins/vite/dependencies.js +29 -10
  252. package/plugins/vite/dependency-watcher.d.ts +2 -2
  253. package/plugins/vite/dependency-watcher.js +5 -6
  254. package/plugins/vite/drop.d.ts +2 -2
  255. package/plugins/vite/drop.js +3 -4
  256. package/plugins/vite/dts-generator.d.ts +2 -2
  257. package/plugins/vite/dts-generator.js +43 -9
  258. package/plugins/vite/editor-connection.js +3 -3
  259. package/plugins/vite/index.d.ts +9 -3
  260. package/plugins/vite/index.js +23 -10
  261. package/plugins/vite/license.js +42 -7
  262. package/plugins/vite/local-files-core.js +3 -3
  263. package/plugins/vite/local-files-utils.d.ts +3 -1
  264. package/plugins/vite/local-files-utils.js +29 -5
  265. package/plugins/vite/meta.js +4 -2
  266. package/plugins/vite/poster.d.ts +2 -2
  267. package/plugins/vite/poster.js +3 -5
  268. package/plugins/vite/reload.d.ts +2 -2
  269. package/plugins/vite/reload.js +23 -23
  270. package/plugins/vite/server.js +2 -1
  271. package/src/engine/api.ts +12 -2
  272. package/src/engine/codegen/register_types.ts +10 -18
  273. package/src/engine/debug/debug_spatial_console.ts +10 -7
  274. package/src/engine/engine_addressables.ts +6 -3
  275. package/src/engine/engine_audio.ts +184 -0
  276. package/src/engine/engine_camera.fit.ts +15 -4
  277. package/src/engine/engine_components.ts +1 -1
  278. package/src/engine/engine_context.ts +85 -38
  279. package/src/engine/engine_context_eventbus.ts +73 -0
  280. package/src/engine/engine_disposable.ts +214 -0
  281. package/src/engine/engine_gameobject.ts +54 -159
  282. package/src/engine/engine_gltf_builtin_components.ts +7 -76
  283. package/src/engine/engine_init.ts +15 -1
  284. package/src/engine/engine_input.ts +28 -7
  285. package/src/engine/engine_instantiate_resolve.ts +407 -0
  286. package/src/engine/engine_license.ts +209 -61
  287. package/src/engine/engine_lifecycle_functions_internal.ts +7 -0
  288. package/src/engine/engine_mainloop_utils.ts +7 -4
  289. package/src/engine/engine_networking.transport.websocket.ts +45 -0
  290. package/src/engine/engine_networking.ts +161 -137
  291. package/src/engine/engine_networking_blob.ts +4 -4
  292. package/src/engine/engine_networking_instantiate.ts +2 -2
  293. package/src/engine/engine_networking_types.ts +41 -1
  294. package/src/engine/engine_physics_rapier.ts +102 -33
  295. package/src/engine/engine_pmrem.ts +56 -6
  296. package/src/engine/engine_scenedata.ts +56 -30
  297. package/src/engine/engine_serialization_builtin_serializer.ts +64 -52
  298. package/src/engine/engine_serialization_core.ts +9 -0
  299. package/src/engine/engine_ssr.ts +29 -3
  300. package/src/engine/engine_types.ts +48 -27
  301. package/src/engine/engine_util_decorator.ts +7 -2
  302. package/src/engine/engine_utils.ts +16 -5
  303. package/src/engine/engine_utils_format.ts +20 -14
  304. package/src/engine/engine_utils_qrcode.ts +2 -2
  305. package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
  306. package/src/engine/webcomponents/jsx.d.ts +51 -0
  307. package/src/engine/webcomponents/logo-element.ts +1 -0
  308. package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +2 -2
  309. package/src/engine/webcomponents/needle menu/needle-menu.ts +8 -7
  310. package/src/engine/webcomponents/needle-button.ts +1 -0
  311. package/src/engine/webcomponents/needle-engine.loading.ts +6 -6
  312. package/src/engine/webcomponents/needle-engine.ts +13 -6
  313. package/src/engine/xr/NeedleXRSession.ts +48 -13
  314. package/src/engine/xr/TempXRContext.ts +2 -2
  315. package/src/engine/xr/events.ts +1 -1
  316. package/src/engine-components/Animation.ts +19 -16
  317. package/src/engine-components/AnimationBuilder.ts +472 -0
  318. package/src/engine-components/Animator.ts +24 -12
  319. package/src/engine-components/AnimatorController.builder.ts +387 -0
  320. package/src/engine-components/AnimatorController.ts +24 -292
  321. package/src/engine-components/AudioSource.ts +130 -79
  322. package/src/engine-components/Camera.ts +16 -3
  323. package/src/engine-components/CameraUtils.ts +12 -5
  324. package/src/engine-components/Collider.ts +66 -18
  325. package/src/engine-components/Component.ts +118 -20
  326. package/src/engine-components/ContactShadows.ts +15 -1
  327. package/src/engine-components/DragControls.ts +18 -11
  328. package/src/engine-components/DropListener.ts +4 -0
  329. package/src/engine-components/EventList.ts +45 -83
  330. package/src/engine-components/Joints.ts +20 -4
  331. package/src/engine-components/Light.ts +49 -27
  332. package/src/engine-components/Networking.ts +1 -1
  333. package/src/engine-components/OrbitControls.ts +42 -16
  334. package/src/engine-components/ReflectionProbe.ts +2 -0
  335. package/src/engine-components/RigidBody.ts +18 -4
  336. package/src/engine-components/SceneSwitcher.ts +3 -0
  337. package/src/engine-components/SeeThrough.ts +2 -2
  338. package/src/engine-components/VideoPlayer.ts +40 -17
  339. package/src/engine-components/Voip.ts +88 -53
  340. package/src/engine-components/api.ts +3 -1
  341. package/src/engine-components/codegen/components.ts +7 -13
  342. package/src/engine-components/export/usdz/USDZExporter.ts +4 -4
  343. package/src/engine-components/postprocessing/VolumeParameter.ts +4 -1
  344. package/src/engine-components/timeline/PlayableDirector.ts +83 -81
  345. package/src/engine-components/timeline/SignalAsset.ts +4 -1
  346. package/src/engine-components/timeline/TimelineBuilder.ts +824 -0
  347. package/src/engine-components/timeline/TimelineModels.ts +5 -1
  348. package/src/engine-components/timeline/TimelineTracks.ts +96 -27
  349. package/src/engine-components/timeline/index.ts +2 -1
  350. package/src/engine-components/ui/Canvas.ts +2 -8
  351. package/src/engine-components/ui/Text.ts +12 -8
  352. package/src/engine-components/web/CursorFollow.ts +21 -14
  353. package/src/engine-components/webxr/WebXRImageTracking.ts +79 -7
  354. package/src/needle-engine.ts +3 -0
  355. package/dist/needle-engine.bundle-Dq0Ly8fW.umd.cjs +0 -1732
  356. package/dist/needle-engine.bundle-YnpzzOPL.min.js +0 -1732
  357. package/lib/engine-components/AvatarLoader.d.ts +0 -80
  358. package/lib/engine-components/AvatarLoader.js +0 -232
  359. package/lib/engine-components/AvatarLoader.js.map +0 -1
  360. package/lib/engine-components/avatar/AvatarBlink_Simple.d.ts +0 -11
  361. package/lib/engine-components/avatar/AvatarBlink_Simple.js +0 -77
  362. package/lib/engine-components/avatar/AvatarBlink_Simple.js.map +0 -1
  363. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.d.ts +0 -14
  364. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js +0 -69
  365. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js.map +0 -1
  366. package/lib/engine-components/avatar/Avatar_Brain_LookAt.d.ts +0 -29
  367. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js +0 -122
  368. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js.map +0 -1
  369. package/lib/engine-components/avatar/Avatar_MouthShapes.d.ts +0 -15
  370. package/lib/engine-components/avatar/Avatar_MouthShapes.js +0 -80
  371. package/lib/engine-components/avatar/Avatar_MouthShapes.js.map +0 -1
  372. package/lib/engine-components/avatar/Avatar_MustacheShake.d.ts +0 -9
  373. package/lib/engine-components/avatar/Avatar_MustacheShake.js +0 -30
  374. package/lib/engine-components/avatar/Avatar_MustacheShake.js.map +0 -1
  375. package/src/engine-components/AvatarLoader.ts +0 -264
  376. package/src/engine-components/avatar/AvatarBlink_Simple.ts +0 -70
  377. package/src/engine-components/avatar/AvatarEyeLook_Rotation.ts +0 -64
  378. package/src/engine-components/avatar/Avatar_Brain_LookAt.ts +0 -140
  379. package/src/engine-components/avatar/Avatar_MouthShapes.ts +0 -84
  380. package/src/engine-components/avatar/Avatar_MustacheShake.ts +0 -32
  381. package/src/vite-env.d.ts +0 -16
@@ -40,11 +40,13 @@ import { GLTFLoader } from '../../../node_modules/@types/three/examples/jsm/load
40
40
  import { GLTFLoaderPlugin } from '../../../node_modules/@types/three/examples/jsm/loaders/GLTFLoader.js';
41
41
  import { GLTFParser } from '../../../node_modules/@types/three/examples/jsm/loaders/GLTFLoader.js';
42
42
  import { Group } from 'three';
43
+ import { ImpulseJoint } from '@dimforge/rapier3d-compat';
43
44
  import { InstancedMesh } from 'three';
44
45
  import { Intersection } from 'three';
45
46
  import { IParticleSystem as IParticleSystem_2 } from 'three.quarks';
46
47
  import { KeyframeTrack } from 'three';
47
48
  import { Layers } from 'three';
49
+ import { Light as Light_2 } from 'three';
48
50
  import { LightProbe } from 'three';
49
51
  import { Line2 } from '../../../../node_modules/@types/three/examples/jsm/lines/Line2.js';
50
52
  import { Loader } from 'three';
@@ -117,6 +119,12 @@ export declare const $componentName: unique symbol;
117
119
 
118
120
  export declare const $physicsKey: unique symbol;
119
121
 
122
+ /* Excluded from this release type: $TXm */
123
+
124
+ /* Excluded from this release type: __CYjiNy */
125
+
126
+ /* Excluded from this release type: __gGoBKfJa */
127
+
120
128
  export declare class __Ignore {
121
129
  }
122
130
 
@@ -254,6 +262,31 @@ export declare class ActionModel implements IBehaviorElement {
254
262
  writeTo(document: USDDocument, writer: USDWriter): void;
255
263
  }
256
264
 
265
+ /**
266
+ * Options for an activation clip in the timeline builder
267
+ */
268
+ export declare type ActivationClipOptions = {
269
+ /** Start time of the clip in seconds. If omitted, placed after the previous clip on this track. */
270
+ start?: number;
271
+ /** Duration of the clip in seconds (required) */
272
+ duration: number;
273
+ /** Ease-in duration in seconds (default: 0) */
274
+ easeIn?: number;
275
+ /** Ease-out duration in seconds (default: 0) */
276
+ easeOut?: number;
277
+ };
278
+
279
+ /**
280
+ * Builder for activation tracks. Provides `.clip()` for defining activation windows.
281
+ * @category Animation and Sequencing
282
+ */
283
+ export declare interface ActivationTrackBuilder extends TimelineBuilderBase {
284
+ /** Adds an activation clip that shows/hides the bound object */
285
+ clip(options: ActivationClipOptions): ActivationTrackBuilder;
286
+ /** Mutes this track so it is skipped during playback */
287
+ muted(muted?: boolean): ActivationTrackBuilder;
288
+ }
289
+
257
290
  export declare const activeInHierarchyFieldName = "needle_isActiveInHierarchy";
258
291
 
259
292
  /**
@@ -487,6 +520,62 @@ declare class Animation_2 extends Component implements IAnimationComponent {
487
520
  }
488
521
  export { Animation_2 as Animation }
489
522
 
523
+ /**
524
+ * A fluent builder for creating `AnimationClip` instances from code.
525
+ *
526
+ * Use {@link AnimationBuilder.create} to start a new builder, chain `.track()` calls
527
+ * to add animation tracks, and call `.build()` to produce the clip.
528
+ *
529
+ * @example Single track
530
+ * ```ts
531
+ * const clip = AnimationBuilder.create()
532
+ * .track(door, "position", { from: [0,0,0], to: [2,0,0], duration: 1 })
533
+ * .build();
534
+ * ```
535
+ *
536
+ * @example Multiple tracks
537
+ * ```ts
538
+ * const clip = AnimationBuilder.create("DoorOpen")
539
+ * .track(door, "position", { from: [0,0,0], to: [2,0,0], duration: 1 })
540
+ * .track(light, "intensity", { from: 0, to: 5, duration: 1 })
541
+ * .build(room);
542
+ * ```
543
+ *
544
+ * @category Animation and Sequencing
545
+ * @group Utilities
546
+ */
547
+ export declare class AnimationBuilder {
548
+ private _name?;
549
+ private _tracks;
550
+ /** Creates a new AnimationBuilder instance */
551
+ static create(name?: string): AnimationBuilder;
552
+ constructor(name?: string);
553
+ /** Adds an animation track for an Object3D's position or scale */
554
+ track(target: Object3D, property: "position" | "scale", keyframes: KF_2<Vec3Value>, options?: TrackOptions): this;
555
+ /** Adds an animation track for an Object3D's quaternion */
556
+ track(target: Object3D, property: "quaternion", keyframes: KF_2<QuatValue>, options?: TrackOptions): this;
557
+ /** Adds an animation track for an Object3D's rotation (Euler, converted to quaternion) */
558
+ track(target: Object3D, property: "rotation", keyframes: KF_2<EulerValue>, options?: TrackOptions): this;
559
+ /** Adds an animation track for an Object3D's visibility */
560
+ track(target: Object3D, property: "visible", keyframes: KF_2<boolean>, options?: TrackOptions): this;
561
+ /** Adds an animation track for a material's numeric property */
562
+ track(target: Material, property: "opacity" | "roughness" | "metalness" | "alphaTest" | "emissiveIntensity" | "envMapIntensity" | "bumpScale" | "displacementScale" | "displacementBias", keyframes: KF_2<number>, options?: TrackOptions): this;
563
+ /** Adds an animation track for a material's color property */
564
+ track(target: Material, property: "color" | "emissive", keyframes: KF_2<ColorValue>, options?: TrackOptions): this;
565
+ /** Adds an animation track for a light's numeric property */
566
+ track(target: Light_2, property: "intensity" | "distance" | "angle" | "penumbra" | "decay", keyframes: KF_2<number>, options?: TrackOptions): this;
567
+ /** Adds an animation track for a light's color */
568
+ track(target: Light_2, property: "color", keyframes: KF_2<ColorValue>, options?: TrackOptions): this;
569
+ /** Adds an animation track for a camera's numeric property */
570
+ track(target: PerspectiveCamera, property: "fov" | "near" | "far" | "zoom", keyframes: KF_2<number>, options?: TrackOptions): this;
571
+ /**
572
+ * Builds and returns the `AnimationClip`.
573
+ * @param root - Optional root Object3D for resolving track paths.
574
+ * When provided, tracks targeting a different object use `target.name` for named resolution.
575
+ */
576
+ build(root?: Object3D): AnimationClip;
577
+ }
578
+
490
579
  /**
491
580
  * @category Animation and Sequencing
492
581
  * @see {@link PlayableDirector} for the main component to control timelines in Needle Engine.
@@ -500,6 +589,34 @@ export declare type AnimationClipModel = {
500
589
  rotation?: Quat | Quaternion;
501
590
  };
502
591
 
592
+ /**
593
+ * Options for an animation clip in the timeline builder
594
+ */
595
+ export declare type AnimationClipOptions = {
596
+ /** Start time of the clip in seconds. If omitted, placed after the previous clip on this track. */
597
+ start?: number;
598
+ /** Duration of the clip in seconds. Defaults to the animation clip duration. */
599
+ duration?: number;
600
+ /** Playback speed multiplier (default: 1) */
601
+ speed?: number;
602
+ /** Whether the animation should loop within the clip (default: false) */
603
+ loop?: boolean;
604
+ /** Ease-in duration in seconds (default: 0) */
605
+ easeIn?: number;
606
+ /** Ease-out duration in seconds (default: 0) */
607
+ easeOut?: number;
608
+ /** Offset into the source animation clip in seconds (default: 0) */
609
+ clipIn?: number;
610
+ /** Whether to remove the start offset of the animation (default: false) */
611
+ removeStartOffset?: boolean;
612
+ /** Pre-extrapolation mode (default: None) */
613
+ preExtrapolation?: ClipExtrapolation;
614
+ /** Post-extrapolation mode (default: None) */
615
+ postExtrapolation?: ClipExtrapolation;
616
+ /** Play the clip in reverse */
617
+ reversed?: boolean;
618
+ };
619
+
503
620
  /**
504
621
  * AnimationCurve is a representation of a curve that can be used to animate values over time.
505
622
  *
@@ -577,6 +694,19 @@ export declare class AnimationExtension implements IUSDExporterExtension {
577
694
 
578
695
  declare type AnimationIdentifier = AnimationClip | number | string | undefined;
579
696
 
697
+ /** User-friendly interpolation mode names */
698
+ export declare type AnimationInterpolation = "linear" | "smooth" | "step";
699
+
700
+ /** A single keyframe: a time and a value */
701
+ export declare type AnimationKeyframe<V> = {
702
+ /** Time in seconds */
703
+ time: number;
704
+ /** The value at this time */
705
+ value: V;
706
+ /** Interpolation mode for this track (default: `"linear"`). Note: Three.js applies one mode per track; the first keyframe's mode is used. */
707
+ interpolation?: AnimationInterpolation;
708
+ };
709
+
580
710
  /**
581
711
  * Registry for animation related data. Use {@link registerAnimationMixer} to register an animation mixer instance.
582
712
  * Can be accessed from {@link Context.animations} and is used internally e.g. when exporting GLTF files.
@@ -597,43 +727,39 @@ declare class AnimationsRegistry {
597
727
  unregisterAnimationMixer(mixer: AnimationMixer | null | undefined): void;
598
728
  }
599
729
 
600
- export declare class AnimationTrackHandler extends TrackHandler {
601
- /* Excluded from this release type: models */
602
- /* Excluded from this release type: trackOffset */
603
- /** The object that is being animated. */
604
- target?: Object3D;
605
- /** The AnimationMixer, should be shared with the animator if an animator is bound */
606
- mixer?: AnimationMixer;
607
- clips: Array<AnimationClip>;
608
- actions: Array<AnimationAction>;
609
- /**
610
- * You can use the weight to blend the timeline animation tracks with multiple animation tracks on the same object.
611
- * @default 1
612
- */
613
- weight: number;
614
- /** holds data/info about clips differences */
615
- private _actionOffsets;
616
- private _didBind;
617
- private _animator;
618
- onDisable(): void;
619
- onDestroy(): void;
620
- onStateChanged(): void;
621
- createHooks(clipModel: Models.AnimationClipModel, clip: any): void;
622
- bind(): void;
623
- private ensureTrackOffsets;
624
- private _useclipOffsets;
625
- private _totalOffsetPosition;
626
- private _totalOffsetRotation;
627
- private _totalOffsetPosition2;
628
- private _totalOffsetRotation2;
629
- private _summedPos;
630
- private _tempPos;
631
- private _summedRot;
632
- private _tempRot;
633
- private _clipRotQuat;
634
- evaluate(time: number): void;
635
- private createRotationInterpolant;
636
- private createPositionInterpolant;
730
+ /**
731
+ * Builder for animation tracks.
732
+ * Provides `.clip()` for pre-built AnimationClips and `.track()` for inline animation definition.
733
+ *
734
+ * @category Animation and Sequencing
735
+ */
736
+ export declare interface AnimationTrackBuilder extends TimelineBuilderBase {
737
+ /** Adds a pre-built AnimationClip */
738
+ clip(asset: AnimationClip, options?: AnimationClipOptions): AnimationTrackBuilder;
739
+ /** Adds a clip from a single {@link TrackDescriptor} */
740
+ clip(descriptor: TrackDescriptor, options?: AnimationClipOptions): AnimationTrackBuilder;
741
+ /** Adds a clip from multiple {@link TrackDescriptor}s */
742
+ clip(descriptors: TrackDescriptor[], options?: AnimationClipOptions): AnimationTrackBuilder;
743
+ /** Adds an animation track for an Object3D's position or scale */
744
+ track(target: Object3D, property: "position" | "scale", keyframes: KF_3<Vec3Value>, options?: TrackOptions): AnimationTrackBuilder;
745
+ /** Adds an animation track for an Object3D's quaternion */
746
+ track(target: Object3D, property: "quaternion", keyframes: KF_3<QuatValue>, options?: TrackOptions): AnimationTrackBuilder;
747
+ /** Adds an animation track for an Object3D's rotation (Euler, converted to quaternion) */
748
+ track(target: Object3D, property: "rotation", keyframes: KF_3<EulerValue>, options?: TrackOptions): AnimationTrackBuilder;
749
+ /** Adds an animation track for an Object3D's visibility */
750
+ track(target: Object3D, property: "visible", keyframes: KF_3<boolean>, options?: TrackOptions): AnimationTrackBuilder;
751
+ /** Adds an animation track for a material's numeric property */
752
+ track(target: Material, property: "opacity" | "roughness" | "metalness" | "alphaTest" | "emissiveIntensity" | "envMapIntensity" | "bumpScale" | "displacementScale" | "displacementBias", keyframes: KF_3<number>, options?: TrackOptions): AnimationTrackBuilder;
753
+ /** Adds an animation track for a material's color property */
754
+ track(target: Material, property: "color" | "emissive", keyframes: KF_3<ColorValue>, options?: TrackOptions): AnimationTrackBuilder;
755
+ /** Adds an animation track for a light's numeric property */
756
+ track(target: Light_2, property: "intensity" | "distance" | "angle" | "penumbra" | "decay", keyframes: KF_3<number>, options?: TrackOptions): AnimationTrackBuilder;
757
+ /** Adds an animation track for a light's color */
758
+ track(target: Light_2, property: "color", keyframes: KF_3<ColorValue>, options?: TrackOptions): AnimationTrackBuilder;
759
+ /** Adds an animation track for a camera's numeric property */
760
+ track(target: PerspectiveCamera, property: "fov" | "near" | "far" | "zoom", keyframes: KF_3<number>, options?: TrackOptions): AnimationTrackBuilder;
761
+ /** Mutes this track so it is skipped during playback */
762
+ muted(muted?: boolean): AnimationTrackBuilder;
637
763
  }
638
764
 
639
765
  declare class AnimationTriggers {
@@ -726,6 +852,12 @@ export declare class Animator extends Component implements IAnimationComponent {
726
852
  * Identifies this component as an animation component in the engine
727
853
  */
728
854
  get isAnimationComponent(): boolean;
855
+ /**
856
+ * The current animator mixer, used for low-level control of animations. Owned by the AnimatorController
857
+ * @returns The current AnimationMixer, or null if no controller is assigned
858
+ * @see AnimatorController.mixer
859
+ */
860
+ get mixer(): AnimationMixer | null;
729
861
  /**
730
862
  * When enabled, animation will affect the root transform position and rotation
731
863
  */
@@ -1102,13 +1234,6 @@ export declare class AnimatorController {
1102
1234
  * @param animator - The animator to bind this controller to
1103
1235
  */
1104
1236
  bind(animator: Animator): void;
1105
- /**
1106
- * Creates a deep copy of this controller.
1107
- * Clones the model data but does not copy runtime state.
1108
- *
1109
- * @returns A new AnimatorController instance with the same configuration
1110
- */
1111
- clone(): AnimatorController | null;
1112
1237
  /**
1113
1238
  * Updates the controller's state machine and animations.
1114
1239
  * Called each frame by the animator component.
@@ -1151,11 +1276,15 @@ export declare class AnimatorController {
1151
1276
  /**
1152
1277
  * A fluent builder for creating {@link AnimatorController} instances from code.
1153
1278
  *
1154
- * Use {@link AnimatorController.build} to create a new builder.
1279
+ * Use {@link AnimatorControllerBuilder.create} or {@link AnimatorController.build} to create a new builder.
1155
1280
  *
1156
- * @example
1281
+ * The builder tracks state names and parameter types through the fluent chain,
1282
+ * providing autocomplete for state names in `.transition()` and type-aware
1283
+ * `.condition()` calls (e.g., trigger parameters don't require a mode argument).
1284
+ *
1285
+ * @example With pre-built AnimationClips
1157
1286
  * ```ts
1158
- * const controller = AnimatorController.build("CharacterController")
1287
+ * const controller = AnimatorControllerBuilder.create("CharacterController")
1159
1288
  * .floatParameter("Speed", 0)
1160
1289
  * .triggerParameter("Jump")
1161
1290
  * .state("Idle", { clip: idleClip, loop: true })
@@ -1166,36 +1295,70 @@ export declare class AnimatorController {
1166
1295
  * .transition("Walk", "Idle", { duration: 0.25 })
1167
1296
  * .condition("Speed", "less", 0.1)
1168
1297
  * .transition("*", "Jump", { duration: 0.1 })
1169
- * .condition("Jump", "if")
1298
+ * .condition("Jump")
1170
1299
  * .transition("Jump", "Idle", { hasExitTime: true, exitTime: 0.9, duration: 0.25 })
1171
1300
  * .build();
1172
1301
  * ```
1173
1302
  *
1303
+ * @example With inline tracks (no pre-built clips needed)
1304
+ * ```ts
1305
+ * const controller = AnimatorControllerBuilder.create("Door")
1306
+ * .boolParameter("Open", false)
1307
+ * .state("Closed", { loop: true })
1308
+ * .track(door, "position", { from: [0, 0, 0], to: [0, 0, 0], duration: 1 })
1309
+ * .state("Open", { loop: true })
1310
+ * .track(door, "position", { from: [0, 0, 0], to: [2, 0, 0], duration: 1 })
1311
+ * .track(light, "intensity", { from: 0, to: 5, duration: 1 })
1312
+ * .transition("Closed", "Open", { duration: 0.25 })
1313
+ * .condition("Open", "if")
1314
+ * .transition("Open", "Closed", { duration: 0.25 })
1315
+ * .condition("Open", "ifNot")
1316
+ * .build(room);
1317
+ * ```
1318
+ *
1319
+ * @typeParam TStates - Union of state names added via `.state()`. Used for autocomplete and validation in `.transition()` and `.defaultState()`.
1320
+ * @typeParam TParams - Record mapping parameter names to their types (`"trigger"`, `"bool"`, `"float"`, `"int"`). Used for type-aware `.condition()` overloads.
1321
+ *
1174
1322
  * @category Animation and Sequencing
1175
1323
  * @group Utilities
1176
1324
  */
1177
- export declare class AnimatorControllerBuilder {
1325
+ export declare class AnimatorControllerBuilder<TStates extends string = never, TParams extends Record<string, "trigger" | "bool" | "float" | "int"> = {}> {
1178
1326
  private _name;
1179
1327
  private _parameters;
1180
1328
  private _states;
1181
1329
  private _anyStateTransitions;
1182
1330
  private _defaultStateName;
1183
1331
  private _lastTransition;
1332
+ private _lastState;
1333
+ /**
1334
+ * Creates a new AnimatorControllerBuilder instance.
1335
+ * @param name - Optional name for the controller
1336
+ */
1337
+ static create(name?: string): AnimatorControllerBuilder;
1184
1338
  constructor(name?: string);
1185
1339
  /** Adds a float parameter */
1186
- floatParameter(name: string, defaultValue?: number): this;
1340
+ floatParameter<N extends string>(name: N, defaultValue?: number): AnimatorControllerBuilder<TStates, TParams & Record<N, "float">>;
1187
1341
  /** Adds an integer parameter */
1188
- intParameter(name: string, defaultValue?: number): this;
1342
+ intParameter<N extends string>(name: N, defaultValue?: number): AnimatorControllerBuilder<TStates, TParams & Record<N, "int">>;
1189
1343
  /** Adds a boolean parameter */
1190
- boolParameter(name: string, defaultValue?: boolean): this;
1344
+ boolParameter<N extends string>(name: N, defaultValue?: boolean): AnimatorControllerBuilder<TStates, TParams & Record<N, "bool">>;
1191
1345
  /** Adds a trigger parameter */
1192
- triggerParameter(name: string): this;
1346
+ triggerParameter<N extends string>(name: N): AnimatorControllerBuilder<TStates, TParams & Record<N, "trigger">>;
1193
1347
  /**
1194
1348
  * Adds a state to the controller. The first state added becomes the default state.
1349
+ *
1350
+ * When `options.clip` is provided, the state uses that clip directly.
1351
+ * When omitted, chain `.track()` calls to define animation tracks inline:
1352
+ * ```ts
1353
+ * .state("Open", { loop: true })
1354
+ * .track(door, "position", { from: [0,0,0], to: [2,0,0], duration: 1 })
1355
+ * .track(light, "intensity", { from: 0, to: 5, duration: 1 })
1356
+ * ```
1357
+ *
1195
1358
  * @param name - Unique name for the state
1196
- * @param options - State configuration including clip, loop, speed
1359
+ * @param options - State configuration including clip, loop, speed. When omitted, use `.track()` to add animation data.
1197
1360
  */
1198
- state(name: string, options: StateOptions): this;
1361
+ state<N extends string>(name: N, options?: StateOptions): AnimatorControllerBuilder<TStates | N, TParams>;
1199
1362
  /**
1200
1363
  * Adds a transition between two states.
1201
1364
  * Use `"*"` as the source to create a transition from any state.
@@ -1204,26 +1367,52 @@ export declare class AnimatorControllerBuilder {
1204
1367
  * @param to - Destination state name
1205
1368
  * @param options - Transition configuration
1206
1369
  */
1207
- transition(from: string, to: string, options?: TransitionOptions): this;
1370
+ transition(from: TStates | "*", to: TStates, options?: TransitionOptions): AnimatorControllerBuilder<TStates, TParams>;
1208
1371
  /**
1209
1372
  * Adds a condition to the most recently added transition.
1210
1373
  * Multiple conditions on the same transition are AND-ed together.
1374
+ *
1375
+ * The required arguments depend on the parameter type:
1376
+ * - **Trigger**: `.condition("Jump")` — mode defaults to `"if"`, no threshold needed
1377
+ * - **Bool**: `.condition("Open", "if")` or `.condition("Open", "ifNot")`
1378
+ * - **Float/Int**: `.condition("Speed", "greater", 0.1)`
1379
+ *
1211
1380
  * @param parameter - Name of the parameter to evaluate
1212
- * @param mode - Condition mode: `"if"`, `"ifNot"`, `"greater"`, `"less"`, `"equals"`, `"notEqual"`
1213
- * @param threshold - Comparison threshold for numeric conditions (default: 0)
1214
1381
  */
1215
- condition(parameter: string, mode: ConditionMode, threshold?: number): this;
1382
+ condition(parameter: ParamNamesOfType<TParams, "trigger">, mode?: "if" | "ifNot"): AnimatorControllerBuilder<TStates, TParams>;
1383
+ condition(parameter: ParamNamesOfType<TParams, "bool">, mode: "if" | "ifNot"): AnimatorControllerBuilder<TStates, TParams>;
1384
+ condition(parameter: ParamNamesOfType<TParams, "float" | "int">, mode: "greater" | "less" | "equals" | "notEqual", threshold?: number): AnimatorControllerBuilder<TStates, TParams>;
1385
+ /** Adds an animation track for an Object3D's position or scale to the current state */
1386
+ track(target: Object3D, property: "position" | "scale", keyframes: KF<Vec3Value>, options?: TrackOptions): this;
1387
+ /** Adds an animation track for an Object3D's quaternion to the current state */
1388
+ track(target: Object3D, property: "quaternion", keyframes: KF<QuatValue>, options?: TrackOptions): this;
1389
+ /** Adds an animation track for an Object3D's rotation (Euler, converted to quaternion) to the current state */
1390
+ track(target: Object3D, property: "rotation", keyframes: KF<EulerValue>, options?: TrackOptions): this;
1391
+ /** Adds an animation track for an Object3D's visibility to the current state */
1392
+ track(target: Object3D, property: "visible", keyframes: KF<boolean>, options?: TrackOptions): this;
1393
+ /** Adds an animation track for a material's numeric property to the current state */
1394
+ track(target: Material, property: "opacity" | "roughness" | "metalness" | "alphaTest" | "emissiveIntensity" | "envMapIntensity" | "bumpScale" | "displacementScale" | "displacementBias", keyframes: KF<number>, options?: TrackOptions): this;
1395
+ /** Adds an animation track for a material's color property to the current state */
1396
+ track(target: Material, property: "color" | "emissive", keyframes: KF<ColorValue>, options?: TrackOptions): this;
1397
+ /** Adds an animation track for a light's numeric property to the current state */
1398
+ track(target: Light_2, property: "intensity" | "distance" | "angle" | "penumbra" | "decay", keyframes: KF<number>, options?: TrackOptions): this;
1399
+ /** Adds an animation track for a light's color to the current state */
1400
+ track(target: Light_2, property: "color", keyframes: KF<ColorValue>, options?: TrackOptions): this;
1401
+ /** Adds an animation track for a camera's numeric property to the current state */
1402
+ track(target: PerspectiveCamera, property: "fov" | "near" | "far" | "zoom", keyframes: KF<number>, options?: TrackOptions): this;
1216
1403
  /**
1217
1404
  * Sets which state is the default/entry state.
1218
1405
  * If not called, the first added state is used.
1219
1406
  * @param name - Name of the state
1220
1407
  */
1221
- defaultState(name: string): this;
1408
+ defaultState(name: TStates): AnimatorControllerBuilder<TStates, TParams>;
1222
1409
  /**
1223
1410
  * Builds and returns the {@link AnimatorController}.
1224
1411
  * Resolves all state name references to indices.
1412
+ * @param root - Optional root Object3D for resolving {@link TrackDescriptor} track paths.
1413
+ * When provided, tracks targeting a different object use `target.name` for named resolution.
1225
1414
  */
1226
- build(): AnimatorController;
1415
+ build(root?: Object3D): AnimatorController;
1227
1416
  }
1228
1417
 
1229
1418
  export declare type AnimatorControllerModel = {
@@ -1472,6 +1661,75 @@ export declare class Attractor extends Component {
1472
1661
 
1473
1662
  declare type AttributeChangeCallback = (value: string | null) => void;
1474
1663
 
1664
+ /**
1665
+ * Represents an audio clip that can be loaded and played independently.
1666
+ * The AudioClip class encapsulates the URL of the audio resource and provides
1667
+ * methods for playback control (play, pause, stop) and querying duration.
1668
+ */
1669
+ export declare class AudioClip {
1670
+ readonly url: string;
1671
+ /**
1672
+ * Creates a new AudioClip instance with the specified URL.
1673
+ * @param url The URL of the audio resource to load. This can be a path to an audio file or a MediaStream URL.
1674
+ */
1675
+ constructor(url: string);
1676
+ /** Whether the clip is currently playing.
1677
+ * @returns `true` if the clip is actively playing audio.
1678
+ */
1679
+ get isPlaying(): boolean;
1680
+ /**
1681
+ * The total duration of the audio clip in seconds.
1682
+ * Loads the audio metadata if not already available.
1683
+ * @returns A promise that resolves with the duration in seconds.
1684
+ */
1685
+ getDuration(): Promise<number>;
1686
+ /**
1687
+ * Plays the audio clip from the current position.
1688
+ * @returns A promise that resolves when playback finishes, or rejects on error.
1689
+ * If the clip is looping, the promise will never resolve on its own – call {@link stop} or {@link pause} to end playback.
1690
+ */
1691
+ play(): Promise<void>;
1692
+ /**
1693
+ * Pauses playback at the current position.
1694
+ * Call {@link play} to resume.
1695
+ */
1696
+ pause(): void;
1697
+ /**
1698
+ * Stops playback and resets the position to the beginning.
1699
+ */
1700
+ stop(): void;
1701
+ /** Whether the clip should loop when reaching the end. */
1702
+ get loop(): boolean;
1703
+ set loop(value: boolean);
1704
+ /** Playback volume from 0 (silent) to 1 (full). */
1705
+ get volume(): number;
1706
+ set volume(value: number);
1707
+ /** Current playback position in seconds. */
1708
+ get currentTime(): number;
1709
+ set currentTime(value: number);
1710
+ /** Normalized playback progress from 0 to 1.
1711
+ * @returns The current playback position as a value between 0 and 1, or 0 if the duration is unknown.
1712
+ */
1713
+ get progress(): number;
1714
+ /**
1715
+ * Seeks to a normalized position (0–1) in the clip.
1716
+ * @param position A value between 0 (start) and 1 (end).
1717
+ */
1718
+ seek(position: number): void;
1719
+ /** The underlying HTMLAudioElement, or `undefined` if not yet created.
1720
+ * Use this to connect the element to the Web Audio API via `createMediaElementSource()`.
1721
+ * @returns The HTMLAudioElement if the clip has been loaded or played, otherwise `undefined`.
1722
+ */
1723
+ get audioElement(): HTMLAudioElement | undefined;
1724
+ private _audioElement?;
1725
+ private _duration?;
1726
+ private _loadPromise?;
1727
+ private _loop;
1728
+ private _volume;
1729
+ /** Lazily creates and loads the shared HTMLAudioElement. */
1730
+ private ensureAudioElement;
1731
+ }
1732
+
1475
1733
  /**
1476
1734
  * @category Animation and Sequencing
1477
1735
  * @see {@link PlayableDirector} for the main component to control timelines in Needle Engine.
@@ -1486,6 +1744,26 @@ declare type AudioClipModel_2 = Models.ClipModel & {
1486
1744
  _didTriggerPlay: boolean;
1487
1745
  };
1488
1746
 
1747
+ /**
1748
+ * Options for an audio clip in the timeline builder
1749
+ */
1750
+ export declare type AudioClipOptions = {
1751
+ /** Start time of the clip in seconds. If omitted, placed after the previous clip on this track. */
1752
+ start?: number;
1753
+ /** Duration of the clip in seconds (required for audio since we can't infer it) */
1754
+ duration: number;
1755
+ /** Playback speed multiplier (default: 1) */
1756
+ speed?: number;
1757
+ /** Volume multiplier for this clip (default: 1) */
1758
+ volume?: number;
1759
+ /** Whether the audio should loop within the clip (default: false) */
1760
+ loop?: boolean;
1761
+ /** Ease-in duration in seconds (default: 0) */
1762
+ easeIn?: number;
1763
+ /** Ease-out duration in seconds (default: 0) */
1764
+ easeOut?: number;
1765
+ };
1766
+
1489
1767
  export declare class AudioExtension implements IUSDExporterExtension {
1490
1768
  static getName(clip: string): string;
1491
1769
  get extensionName(): string;
@@ -1522,7 +1800,7 @@ export { AudioListener_2 as AudioListener }
1522
1800
  /**
1523
1801
  * Defines how audio volume attenuates over distance from the listener.
1524
1802
  */
1525
- declare enum AudioRolloffMode {
1803
+ export declare enum AudioRolloffMode {
1526
1804
  /**
1527
1805
  * Logarithmic rolloff provides a natural, real-world attenuation where volume decreases
1528
1806
  * exponentially with distance.
@@ -1627,9 +1905,10 @@ export declare class AudioSource extends Component {
1627
1905
  */
1628
1906
  get isPlaying(): boolean;
1629
1907
  /**
1630
- * The total duration of the current audio clip in seconds.
1908
+ * The total duration of the currently loaded audio clip in seconds.
1631
1909
  *
1632
1910
  * @returns Duration in seconds or undefined if no clip is loaded
1911
+ * @remarks For MediaStream clips, duration is not directly available and will return undefined. If the audio clip has not started loading or is still loading, duration may also be undefined until the audio buffer is ready.
1633
1912
  */
1634
1913
  get duration(): number | undefined;
1635
1914
  /**
@@ -1654,7 +1933,8 @@ export declare class AudioSource extends Component {
1654
1933
  /**
1655
1934
  * Controls how the audio is positioned in space.
1656
1935
  * Values range from 0 (2D, non-positional) to 1 (fully 3D positioned).
1657
- * Note: 2D playback is not fully supported in the current implementation.
1936
+ * Internally uses a dual-path audio graph to crossfade between a spatialized (PannerNode)
1937
+ * and a non-spatialized (direct) signal path.
1658
1938
  */
1659
1939
  get spatialBlend(): number;
1660
1940
  set spatialBlend(val: number);
@@ -1702,7 +1982,11 @@ export declare class AudioSource extends Component {
1702
1982
  private audioLoader;
1703
1983
  private shouldPlay;
1704
1984
  private _lastClipStartedLoading;
1985
+ private _loadedClip;
1705
1986
  private _audioElement;
1987
+ private _entryNode;
1988
+ private _spatialGain;
1989
+ private _bypassGain;
1706
1990
  /**
1707
1991
  * Returns the underlying {@link PositionalAudio} object, creating it if necessary.
1708
1992
  * The audio source needs a user interaction to be initialized due to browser autoplay policies.
@@ -1730,6 +2014,15 @@ export declare class AudioSource extends Component {
1730
2014
  private onApplicationMuteChanged;
1731
2015
  private createAudio;
1732
2016
  private __onAllowAudioCallback;
2017
+ /**
2018
+ * Sets up the dual-path audio graph for spatial blend crossfading.
2019
+ * Creates two parallel signal paths from source to output:
2020
+ * - 3D path: entry → panner → spatialGain → gain (spatialized)
2021
+ * - 2D path: entry → bypassGain → gain (non-spatialized)
2022
+ */
2023
+ private setupSpatialBlendNodes;
2024
+ /** Updates the spatial/bypass gain values based on the current spatialBlend. */
2025
+ private updateSpatialBlendGains;
1733
2026
  private applySpatialDistanceSettings;
1734
2027
  private onNewClip;
1735
2028
  /**
@@ -1737,8 +2030,9 @@ export declare class AudioSource extends Component {
1737
2030
  * If no argument is provided, plays the currently assigned clip.
1738
2031
  *
1739
2032
  * @param clip - Optional audio clip or {@link MediaStream} to play
2033
+ * @returns A promise that resolves when playback starts successfully, or rejects on error
1740
2034
  */
1741
- play(clip?: string | MediaStream | undefined): void;
2035
+ play(clip?: string | MediaStream | undefined): Promise<boolean>;
1742
2036
  /**
1743
2037
  * Pauses audio playback while maintaining the current position.
1744
2038
  * Use play() to resume from the paused position.
@@ -1755,30 +2049,15 @@ export declare class AudioSource extends Component {
1755
2049
  /* Excluded from this release type: update */
1756
2050
  }
1757
2051
 
1758
- export declare class AudioTrackHandler extends TrackHandler {
1759
- models: Array<AudioClipModel_2>;
1760
- listener: AudioListener_3;
1761
- audio: Array<Audio_2>;
1762
- audioContextTimeOffset: Array<number>;
1763
- lastTime: number;
1764
- audioSource?: AudioSource;
1765
- private _audioLoader;
1766
- private getAudioFilePath;
1767
- onAllowAudioChanged(allow: boolean): void;
1768
- addModel(model: Models.ClipModel): void;
1769
- onDisable(): void;
1770
- onDestroy(): void;
1771
- onMuteChanged(): void;
1772
- stop(): void;
1773
- private _playableDirectorResumed;
1774
- onPauseChanged(): void;
1775
- evaluate(time: number): void;
1776
- /** Call to load audio buffer for a specific time in the track. Can be used to preload the timeline audio */
1777
- loadAudio(time: number, lookAhead?: number, lookBehind?: number): Promise<(AudioBuffer | null)[]> | null;
1778
- private isInTimeRange;
1779
- private static _audioBuffers;
1780
- static dispose(): void;
1781
- private handleAudioLoading;
2052
+ /**
2053
+ * Builder for audio tracks. Provides `.clip()` for adding audio clips by URL.
2054
+ * @category Animation and Sequencing
2055
+ */
2056
+ export declare interface AudioTrackBuilder extends TimelineBuilderBase {
2057
+ /** Adds an audio clip by URL */
2058
+ clip(url: string, options: AudioClipOptions): AudioTrackBuilder;
2059
+ /** Mutes this track so it is skipped during playback */
2060
+ muted(muted?: boolean): AudioTrackBuilder;
1782
2061
  }
1783
2062
 
1784
2063
  /* Excluded from this release type: AuralMode */
@@ -1811,69 +2090,6 @@ export declare class Avatar extends Component {
1811
2090
  private loadAvatarObjects;
1812
2091
  }
1813
2092
 
1814
- /* Excluded from this release type: Avatar_Brain_LookAt */
1815
-
1816
- /* Excluded from this release type: Avatar_MouthShapes */
1817
-
1818
- /* Excluded from this release type: Avatar_MustacheShake */
1819
-
1820
- /* Excluded from this release type: Avatar_POI */
1821
-
1822
- /* Excluded from this release type: AvatarBlink_Simple */
1823
-
1824
- /* Excluded from this release type: AvatarEyeLook_Rotation */
1825
-
1826
- /**
1827
- * Handles loading and instantiating avatar models from various sources.
1828
- * Provides functionality to find and extract important parts of an avatar (head, hands).
1829
- *
1830
- * Debug mode can be enabled with the URL parameter `?debugavatar`,
1831
- * which will log detailed information about avatar loading and configuration.
1832
- */
1833
- export declare class AvatarLoader {
1834
- private readonly avatarRegistryUrl;
1835
- /**
1836
- * Retrieves or creates a new avatar instance from an ID or existing Object3D.
1837
- * @param context The application context
1838
- * @param avatarId Either a string ID to load an avatar or an existing Object3D to use as avatar
1839
- * @returns Promise resolving to an AvatarModel if successful, or null if failed
1840
- */
1841
- getOrCreateNewAvatarInstance(context: Context, avatarId: string | Object3D): Promise<AvatarModel | null>;
1842
- /**
1843
- * Loads an avatar model from a file or registry using the provided ID.
1844
- * @param context The engine context
1845
- * @param avatarId The ID of the avatar to load
1846
- * @returns Promise resolving to the loaded avatar's Object3D, or null if failed
1847
- */
1848
- private loadAvatar;
1849
- /**
1850
- * Caches an avatar model for reuse.
1851
- * @param _id The ID to associate with the model
1852
- * @param _model The avatar model to cache
1853
- */
1854
- private cacheModel;
1855
- /**
1856
- * Analyzes an Object3D to find avatar parts (head, hands) based on naming conventions.
1857
- * @param obj The Object3D to search for avatar parts
1858
- * @returns A structured AvatarModel with references to found parts
1859
- */
1860
- private findAvatar;
1861
- /**
1862
- * Recursively searches for an avatar part by name within an Object3D hierarchy.
1863
- * @param obj The Object3D to search within
1864
- * @param searchString Array of strings that should all be present in the object name
1865
- * @returns The found Object3D part or null if not found
1866
- */
1867
- private findAvatarPart;
1868
- /**
1869
- * Handles HTTP response errors from avatar loading operations.
1870
- * @param response The fetch API response to check
1871
- * @returns The response if it was ok
1872
- * @throws Error with status text if response was not ok
1873
- */
1874
- private handleCustomAvatarErrors;
1875
- }
1876
-
1877
2093
  /**
1878
2094
  * Marks a GameObject as being controlled or owned by a player in networked XR sessions.
1879
2095
  * This is used internally by the networking system to identify player-controlled objects.
@@ -1934,35 +2150,6 @@ declare type AvatarMarkerEventArgs = {
1934
2150
  gameObject: Object3D;
1935
2151
  };
1936
2152
 
1937
- /**
1938
- * Represents an avatar model with head and hands references.
1939
- * Used for representing characters in 3D space.
1940
- */
1941
- export declare class AvatarModel {
1942
- /** The root object of the avatar model */
1943
- root: Object3D;
1944
- /** The head object of the avatar model */
1945
- head: Object3D;
1946
- /** The left hand object of the avatar model, if available */
1947
- leftHand: Object3D | null;
1948
- /** The right hand object of the avatar model, if available */
1949
- rigthHand: Object3D | null;
1950
- /**
1951
- * Checks if the avatar model has a valid configuration.
1952
- * An avatar is considered valid if it has a head.
1953
- * @returns Whether the avatar has a valid setup
1954
- */
1955
- get isValid(): boolean;
1956
- /**
1957
- * Creates a new avatar model.
1958
- * @param root The root object of the avatar
1959
- * @param head The head object of the avatar
1960
- * @param leftHand The left hand object of the avatar
1961
- * @param rigthHand The right hand object of the avatar
1962
- */
1963
- constructor(root: Object3D, head: Object3D, leftHand: Object3D | null, rigthHand: Object3D | null);
1964
- }
1965
-
1966
2153
  export declare enum Axes {
1967
2154
  None = 0,
1968
2155
  X = 2,
@@ -2326,7 +2513,6 @@ export declare class BoxCollider extends Collider implements IBoxCollider {
2326
2513
  center: Vector3;
2327
2514
  /* Excluded from this release type: onEnable */
2328
2515
  /* Excluded from this release type: onDisable */
2329
- /* Excluded from this release type: onValidate */
2330
2516
  /**
2331
2517
  * Automatically fits the collider to the geometry of the object.
2332
2518
  * Sets the size and center based on the object's bounding box.
@@ -2600,6 +2786,7 @@ declare class CallHandle extends EventDispatcher<any> {
2600
2786
  * CallInfo represents a single callback method that can be invoked by the {@link EventList}.
2601
2787
  */
2602
2788
  export declare class CallInfo {
2789
+ $serializedTypes: Record<string, any>;
2603
2790
  /**
2604
2791
  * When the CallInfo is enabled it will be invoked when the EventList is invoked
2605
2792
  */
@@ -2946,7 +3133,7 @@ export declare class Canvas extends UIRootComponent implements ICanvas {
2946
3133
  private _receivers;
2947
3134
  registerEventReceiver(receiver: ICanvasEventReceiver): void;
2948
3135
  unregisterEventReceiver(receiver: ICanvasEventReceiver): void;
2949
- onEnterXR(args: NeedleXREventArgs): Promise<void>;
3136
+ onEnterXR(args: NeedleXREventArgs): void;
2950
3137
  onLeaveXR(args: NeedleXREventArgs): void;
2951
3138
  onBeforeRenderRoutine: () => void;
2952
3139
  onAfterRenderRoutine: () => void;
@@ -3275,7 +3462,12 @@ export declare enum ClearFlags {
3275
3462
  Skybox = 1,
3276
3463
  /** Clear the background with a solid color. The alpha channel of the color determines the transparency */
3277
3464
  SolidColor = 2,
3278
- /** Clear the background with a transparent color */
3465
+ /**
3466
+ * No declared background intent. Sets the render clear color to fully
3467
+ * transparent so the canvas shows through when nothing else is configured,
3468
+ * but leaves `scene.background` untouched — backgrounds set by other code
3469
+ * (custom loaders, user assignment) are preserved.
3470
+ */
3279
3471
  Uninitialized = 4
3280
3472
  }
3281
3473
 
@@ -3522,6 +3714,22 @@ export declare abstract class Collider extends Component implements ICollider {
3522
3714
  * The layers that this collider will interact with. Used for filtering collision detection.
3523
3715
  */
3524
3716
  filter?: number[];
3717
+ /**
3718
+ * The density of the collider, used for automatic mass calculation when the attached {@link Rigidbody} has `autoMass` enabled.
3719
+ * Rapier computes mass from density using the real-world formula: `mass = density × volume`.
3720
+ * The volume is derived from the collider shape (sphere, box, capsule, or convex hull).
3721
+ *
3722
+ * Reference values (relative to water = 1.0):
3723
+ * - Wood: 0.5–0.9
3724
+ * - Water: 1.0 (engine default)
3725
+ * - Rubber: 1.2
3726
+ * - Steel: 7.8
3727
+ *
3728
+ * @default undefined — uses the physics engine default of 1.0
3729
+ */
3730
+ density?: number;
3731
+ /* Excluded from this release type: _propertiesDirty */
3732
+ /* Excluded from this release type: onValidate */
3525
3733
  /* Excluded from this release type: awake */
3526
3734
  /* Excluded from this release type: start */
3527
3735
  /* Excluded from this release type: onEnable */
@@ -3623,7 +3831,10 @@ declare class ColorSerializer extends TypeSerializer {
3623
3831
  onSerialize(data: any): any | void;
3624
3832
  }
3625
3833
 
3626
- export declare const colorSerializer: ColorSerializer;
3834
+ export declare let colorSerializer: ColorSerializer;
3835
+
3836
+ /** A Color value, either as a Three.js Color or as an `[r, g, b]` tuple (0–1) */
3837
+ declare type ColorValue = Color | [number, number, number];
3627
3838
 
3628
3839
  /**
3629
3840
  * Utility method to check if two materials were created from the same glTF material
@@ -3644,7 +3855,7 @@ export declare function compareAssociation<T extends Material>(obj1: T, obj2: T)
3644
3855
  * **Input event methods:**
3645
3856
  * {@link onPointerDown}, {@link onPointerUp}, {@link onPointerEnter}, {@link onPointerExit} and {@link onPointerMove}.
3646
3857
  *
3647
- * @example
3858
+ * @example Basic component
3648
3859
  * ```typescript
3649
3860
  * import { Behaviour } from "@needle-tools/engine";
3650
3861
  * export class MyComponent extends Behaviour {
@@ -3657,6 +3868,25 @@ export declare function compareAssociation<T extends Material>(obj1: T, obj2: T)
3657
3868
  * }
3658
3869
  * ```
3659
3870
  *
3871
+ * @example Automatic cleanup with autoCleanup
3872
+ * ```typescript
3873
+ * import { Behaviour, serializable, EventList } from "@needle-tools/engine";
3874
+ * export class ScoreTracker extends Behaviour {
3875
+ * @serializable(EventList)
3876
+ * onScoreChanged?: EventList<number>;
3877
+ *
3878
+ * start() {
3879
+ * // Registered during start → survives enable/disable, cleaned up on destroy
3880
+ * this.autoCleanup(this.onScoreChanged?.on(score => console.log("Score:", score)));
3881
+ * }
3882
+ *
3883
+ * onEnable() {
3884
+ * // Registered during onEnable → cleaned up on disable
3885
+ * this.autoCleanup(() => this.cleanupResources());
3886
+ * }
3887
+ * }
3888
+ * ```
3889
+ *
3660
3890
  * @group Components
3661
3891
  */
3662
3892
  declare abstract class Component implements IComponent, EventTarget, Partial<INeedleXRSessionEventReceiver>, Partial<IPointerEventHandler> {
@@ -3707,6 +3937,50 @@ declare abstract class Component implements IComponent, EventTarget, Partial<INe
3707
3937
  * @returns True if the component is enabled and all parent GameObjects are active
3708
3938
  */
3709
3939
  get activeAndEnabled(): boolean;
3940
+ private __disableCleanups?;
3941
+ private __destroyCleanups?;
3942
+ /**
3943
+ * @experimental
3944
+ * Register a resource for automatic cleanup tied to this component's lifecycle.
3945
+ * Accepts {@link IDisposable} objects, cleanup functions, or event unsubscribe functions.
3946
+ * `null` and `undefined` are safe no-ops (convenient for conditional subscriptions).
3947
+ *
3948
+ * **Lifecycle-aware:** The cleanup store is chosen automatically based on when `autoCleanup` is called:
3949
+ * - Called during {@link onEnable} → cleaned up on {@link onDisable} (and re-registered on re-enable)
3950
+ * - Called during {@link awake} or {@link start} → cleaned up on {@link onDestroy} (survives enable/disable cycles)
3951
+ * - Called at any other time (e.g. from update) → cleaned up on {@link onDisable}
3952
+ *
3953
+ * @param disposable An {@link IDisposable}, a cleanup/unsubscribe function, or `null`/`undefined`
3954
+ *
3955
+ * @example EventList subscriptions
3956
+ * ```ts
3957
+ * import { Behaviour, serializable, EventList } from "@needle-tools/engine";
3958
+ *
3959
+ * export class MyComponent extends Behaviour {
3960
+ * @serializable(EventList)
3961
+ * onScoreChanged?: EventList<number>;
3962
+ *
3963
+ * onEnable() {
3964
+ * this.autoCleanup(this.onScoreChanged?.on(score => {
3965
+ * console.log("Score:", score);
3966
+ * }));
3967
+ * }
3968
+ * }
3969
+ * ```
3970
+ *
3971
+ * @example Lifetime subscriptions in awake
3972
+ * ```ts
3973
+ * import { Behaviour } from "@needle-tools/engine";
3974
+ *
3975
+ * export class Persistent extends Behaviour {
3976
+ * awake() {
3977
+ * // Registered during awake → survives enable/disable, cleaned up on destroy
3978
+ * this.autoCleanup(() => this.save());
3979
+ * }
3980
+ * }
3981
+ * ```
3982
+ */
3983
+ protected autoCleanup(disposable: IDisposable | DisposeFn | Function | null | undefined): void;
3710
3984
  private get __isActive();
3711
3985
  private get __isActiveInHierarchy();
3712
3986
  private set __isActiveInHierarchy(value);
@@ -3725,11 +3999,6 @@ declare abstract class Component implements IComponent, EventTarget, Partial<INe
3725
3999
  * For example, URL to the glTF file this component was loaded from
3726
4000
  */
3727
4001
  sourceId?: SourceIdentifier;
3728
- /**
3729
- * Called when this component needs to remap guids after an instantiate operation.
3730
- * @param guidsMap Mapping from old guids to newly generated guids
3731
- */
3732
- resolveGuids?(guidsMap: GuidsMap): void;
3733
4002
  /**
3734
4003
  * Called once when the component becomes active for the first time.
3735
4004
  * This is the first lifecycle callback to be invoked
@@ -3942,6 +4211,10 @@ declare abstract class Component implements IComponent, EventTarget, Partial<INe
3942
4211
  destroy(): void;
3943
4212
  /* Excluded from this release type: __didAwake */
3944
4213
  /* Excluded from this release type: __didStart */
4214
+ /** True while start() has finished executing (used by autoCleanup to distinguish start from update) */
4215
+ private __didCompleteStart;
4216
+ /** True while onEnable() is executing (used by autoCleanup to route to disable store) */
4217
+ private __inEnableOrDisableCallback;
3945
4218
  /* Excluded from this release type: __didEnable */
3946
4219
  /* Excluded from this release type: __isEnabled */
3947
4220
  /* Excluded from this release type: __destroyed */
@@ -4097,7 +4370,7 @@ declare class ComponentSerializer extends TypeSerializer {
4097
4370
  findObjectForGuid(guid: string, root: Object3D): any;
4098
4371
  }
4099
4372
 
4100
- export declare const componentSerializer: ComponentSerializer;
4373
+ export declare let componentSerializer: ComponentSerializer;
4101
4374
 
4102
4375
  declare type ComponentType = "button" | "thumbstick" | "squeeze" | "touchpad";
4103
4376
 
@@ -4231,6 +4504,7 @@ export declare class ContactShadows extends Component {
4231
4504
  set needsUpdate(val: boolean);
4232
4505
  get needsUpdate(): boolean;
4233
4506
  private _needsUpdate;
4507
+ private _needsFit;
4234
4508
  /** All shadow objects are parented to this object.
4235
4509
  * The gameObject itself should not be transformed because we want the ContactShadows object e.g. also have a GroundProjectedEnv component
4236
4510
  * in which case ContactShadows scale would affect the projection
@@ -4460,13 +4734,14 @@ export declare class Context implements IContext {
4460
4734
  * Use `setCurrentCamera` for updating the main camera.
4461
4735
  */
4462
4736
  /**
4463
- * Typed proxy providing direct access to scene components by node and component name.
4464
- * Types are auto-generated from your GLB assets by the `needle:dts-generator` Vite plugin
4465
- * and written to `src/generated/needle-bindings.d.ts` on every dev-server start and GLB change.
4737
+ * Access your scene's full hierarchy, objects, and components directly by name with full autocomplete.
4738
+ * Types are generated automatically from your GLB files when the dev server starts.
4739
+ *
4740
+ * You can store references to objects or components for later use.
4741
+ * Note that the scene hierarchy can change at runtime (e.g. when objects are added, removed, or re-parented),
4742
+ * in which case stored references may become stale.
4466
4743
  *
4467
- * Each property access traverses the live scene graph on demand — no caching, always fresh.
4468
- * This is a convenience shorthand for `getComponent` lookups; the same result can be
4469
- * achieved manually via `scene.getObjectByName(name)` + `getComponent(node, Type)`.
4744
+ * @experimental This API may change in future versions.
4470
4745
  *
4471
4746
  * @example
4472
4747
  * // Toggle auto-rotate on the orbit camera
@@ -4475,12 +4750,6 @@ export declare class Context implements IContext {
4475
4750
  * @example
4476
4751
  * // Change the background color
4477
4752
  * ctx.sceneData.Camera.Camera.backgroundColor = new RGBAColor(1, 0, 0, 1);
4478
- *
4479
- * @example
4480
- * // Equivalent manual approach (without sceneData)
4481
- * const node = ctx.scene.getObjectByName("Camera");
4482
- * const orbit = getComponent(node, OrbitControls);
4483
- * if (orbit) orbit.autoRotate = true;
4484
4753
  */
4485
4754
  get sceneData(): SceneData;
4486
4755
  get mainCamera(): Camera_2;
@@ -4489,30 +4758,48 @@ export declare class Context implements IContext {
4489
4758
  private _mainCamera;
4490
4759
  private _fallbackCamera;
4491
4760
  /** access application state (e.g. if all audio should be muted) */
4492
- application: Application;
4761
+ get application(): Application;
4762
+ private _application;
4493
4763
  /** access animation mixer used by components in the scene */
4494
- animations: AnimationsRegistry;
4764
+ get animations(): AnimationsRegistry;
4765
+ private _animations;
4495
4766
  /** access timings (current frame number, deltaTime, timeScale, ...) */
4496
- time: Time;
4767
+ get time(): Time;
4768
+ private _time;
4497
4769
  /** access input data (e.g. click or touch events) */
4498
- input: Input;
4770
+ get input(): Input;
4771
+ private _input;
4499
4772
  /** access physics related methods (e.g. raycasting). To access the phyiscs engine use `context.physics.engine` */
4500
- physics: Physics;
4773
+ get physics(): Physics;
4774
+ private _physics;
4501
4775
  /** access postprocessing effects stack. Add/remove effects and configure adaptive performance settings */
4502
- postprocessing: PostProcessing;
4776
+ get postprocessing(): PostProcessing;
4777
+ private _postprocessing;
4503
4778
  /** access networking methods (use it to send or listen to messages or join a networking backend) */
4504
- connection: NetworkConnection;
4779
+ get connection(): NetworkConnection;
4780
+ private _connection;
4781
+ /** context-level event bus for decoupled component communication
4782
+ * @see {@link ContextEventMap} for known event types
4783
+ */
4784
+ get events(): EventBus;
4785
+ private _events;
4505
4786
  /** @deprecated AssetDatabase is deprecated */
4506
4787
  assets: AssetDatabase;
4507
- /** The main light in the scene */
4508
- mainLight: ILight | null;
4788
+ /** All registered lights in the scene, maintained by the Light component.
4789
+ * @see mainLight for accessing the main directional light in the scene
4790
+ */
4791
+ readonly lights: ILight[];
4792
+ /** The brightest registered directional light, or null if none are registered
4793
+ * @see lights
4794
+ */
4795
+ get mainLight(): ILight | null;
4509
4796
  /** @deprecated Use sceneLighting */
4510
- get rendererData(): RendererData;
4797
+ private get rendererData();
4511
4798
  /** Access the scene lighting manager to control lighting settings in the context */
4512
- sceneLighting: RendererData;
4513
- addressables: Addressables;
4514
- lightmaps: ILightDataRegistry;
4515
- players: PlayerViewManager;
4799
+ readonly sceneLighting: RendererData;
4800
+ readonly addressables: Addressables;
4801
+ readonly lightmaps: ILightDataRegistry;
4802
+ readonly players: PlayerViewManager;
4516
4803
  /** Access the LODs manager to control LOD behavior in the context */
4517
4804
  readonly lodsManager: LODsManager;
4518
4805
  /** Access the needle menu to add or remove buttons to the menu element */
@@ -4754,6 +5041,18 @@ export declare type ContextEventArgs = {
4754
5041
  files?: LoadedModel[];
4755
5042
  };
4756
5043
 
5044
+ /** Typed event map for {@link Context.events}.
5045
+ * Known events get full autocomplete; custom events can be typed at the call site via generic parameter.
5046
+ */
5047
+ export declare interface ContextEventMap {
5048
+ "scene-content-changed": {
5049
+ /** The component that triggered the change (e.g. SceneSwitcher, DropListener) */
5050
+ readonly source: IComponent;
5051
+ /** The root object that was added/loaded */
5052
+ readonly object: Object3D;
5053
+ };
5054
+ }
5055
+
4757
5056
  /** Use to register to various Needle Engine context events and to get access to all current instances
4758
5057
  * e.g. when being created in the DOM
4759
5058
  * @example
@@ -4805,6 +5104,20 @@ export declare type ControlClipModel = {
4805
5104
  updateDirector: boolean;
4806
5105
  };
4807
5106
 
5107
+ /**
5108
+ * Options for a control clip in the timeline builder
5109
+ */
5110
+ export declare type ControlClipOptions = {
5111
+ /** Start time of the clip in seconds. If omitted, placed after the previous clip on this track. */
5112
+ start?: number;
5113
+ /** Duration of the clip in seconds (required) */
5114
+ duration: number;
5115
+ /** Whether to control the activation of the source object (default: true) */
5116
+ controlActivation?: boolean;
5117
+ /** Whether to update a nested PlayableDirector on the source object (default: true) */
5118
+ updateDirector?: boolean;
5119
+ };
5120
+
4808
5121
  /** true when selectstart was ever received.
4809
5122
  * On VisionOS 1.1 we always have select events (as per the spec), so this is always true
4810
5123
  */
@@ -4815,12 +5128,15 @@ declare type ControllerAxes = "xr-standard-thumbstick" | "xr-standard-touchpad";
4815
5128
  */
4816
5129
  export declare type ControllerChangedEvt = (args: NeedleXRControllerEventArgs) => void;
4817
5130
 
4818
- export declare class ControlTrackHandler extends TrackHandler {
4819
- models: Array<Models.ClipModel>;
4820
- timelines: Array<PlayableDirector | null>;
4821
- resolveSourceObjects(_context: Context): void;
4822
- private _previousActiveModel;
4823
- evaluate(time: number): void;
5131
+ /**
5132
+ * Builder for control tracks. Provides `.clip()` for controlling nested objects/timelines.
5133
+ * @category Animation and Sequencing
5134
+ */
5135
+ export declare interface ControlTrackBuilder extends TimelineBuilderBase {
5136
+ /** Adds a control clip for a source object */
5137
+ clip(sourceObject: Object3D, options: ControlClipOptions): ControlTrackBuilder;
5138
+ /** Mutes this track so it is skipped during playback */
5139
+ muted(muted?: boolean): ControlTrackBuilder;
4824
5140
  }
4825
5141
 
4826
5142
  /**@obsolete use Graphics.copyTexture */
@@ -5008,7 +5324,6 @@ export declare class CursorFollow extends Component {
5008
5324
  * - Cursor that follows terrain or mesh surfaces
5009
5325
  *
5010
5326
  * **Important notes:**
5011
- * - Requires objects in the scene to have colliders for raycasting to work
5012
5327
  * - Works best with {@link keepDistance} set to `false` to allow depth changes
5013
5328
  * - Can be combined with {@link damping} for smooth surface following
5014
5329
  * - The raycast uses the physics system's raycast functionality
@@ -5135,7 +5450,7 @@ export declare function decompressGpuTexture(texture: any, maxTextureSize?: numb
5135
5450
  * return true;
5136
5451
  * });
5137
5452
  * */
5138
- export declare function deepClone(obj: any, predicate?: deepClonePredicate): any;
5453
+ export declare function deepClone(obj: any, predicate?: deepClonePredicate, _visited?: WeakSet<object>): any;
5139
5454
 
5140
5455
  declare type deepClonePredicate = (owner: any, propertyName: string, current: any) => boolean;
5141
5456
 
@@ -5363,7 +5678,7 @@ export declare namespace DeviceUtilities {
5363
5678
  * Controls how the {@link PlayableDirector} behaves when playback reaches the end.
5364
5679
  * @see {@link PlayableDirector.extrapolationMode}
5365
5680
  */
5366
- declare enum DirectorWrapMode {
5681
+ export declare enum DirectorWrapMode {
5367
5682
  /** Hold the last frame when playback reaches the end of the timeline. */
5368
5683
  Hold = 0,
5369
5684
  /** Loop back to the start and continue playing indefinitely. */
@@ -5372,6 +5687,101 @@ declare enum DirectorWrapMode {
5372
5687
  None = 2
5373
5688
  }
5374
5689
 
5690
+ /**
5691
+ * A store for managing disposable resources (event subscriptions, listeners, callbacks)
5692
+ * that should be cleaned up together.
5693
+ *
5694
+ * DisposableStore collects disposables and disposes them all at once when
5695
+ * {@link dispose} is called. After disposal, the store can be reused — new items
5696
+ * can be added and a subsequent {@link dispose} call will clean those up.
5697
+ *
5698
+ * This is the same pattern used internally by VSCode for lifecycle-bound resource management.
5699
+ *
5700
+ * @example Basic usage
5701
+ * ```ts
5702
+ * import { DisposableStore, on } from "@needle-tools/engine";
5703
+ *
5704
+ * const store = new DisposableStore();
5705
+ *
5706
+ * // Register a DOM event listener (typed!)
5707
+ * store.add(on(window, "resize", (ev) => console.log(ev)));
5708
+ *
5709
+ * // Register the return value of EventList.on()
5710
+ * store.add(myEventList.on(data => console.log(data)));
5711
+ *
5712
+ * // Register a raw cleanup function
5713
+ * store.add(() => someSDK.off("event", handler));
5714
+ *
5715
+ * // Later: dispose everything at once
5716
+ * store.dispose();
5717
+ * ```
5718
+ *
5719
+ * @example Use with Needle Engine components
5720
+ * ```ts
5721
+ * import { Behaviour, serializable, EventList, on } from "@needle-tools/engine";
5722
+ *
5723
+ * export class MyComponent extends Behaviour {
5724
+ * @serializable(EventList)
5725
+ * onClick?: EventList;
5726
+ *
5727
+ * onEnable() {
5728
+ * // DOM events — fully typed
5729
+ * this.autoCleanup(on(window, "resize", (ev) => this.onResize(ev)));
5730
+ *
5731
+ * // EventList — .on() returns a function, autoCleanup accepts it
5732
+ * this.autoCleanup(this.onClick?.on(() => console.log("clicked!")));
5733
+ * }
5734
+ * // No onDisable needed — cleaned up automatically!
5735
+ * }
5736
+ * ```
5737
+ *
5738
+ * @category Utilities
5739
+ * @group Lifecycle
5740
+ */
5741
+ export declare class DisposableStore implements IDisposable {
5742
+ private _disposables;
5743
+ /** The number of registered disposables */
5744
+ get size(): number;
5745
+ /**
5746
+ * Register a disposable resource. Accepts:
5747
+ * - An {@link IDisposable} object (has a `dispose()` method) — e.g. from {@link on}
5748
+ * - A cleanup function (e.g. return value of `EventList.on()`)
5749
+ * - `null` or `undefined` (safe no-op for conditional subscriptions)
5750
+ *
5751
+ * When {@link dispose} is called, all registered resources are cleaned up.
5752
+ *
5753
+ * @param disposable The resource to register for disposal
5754
+ *
5755
+ * @example
5756
+ * ```ts
5757
+ * const store = new DisposableStore();
5758
+ *
5759
+ * // IDisposable object from on()
5760
+ * store.add(on(window, "resize", handler));
5761
+ *
5762
+ * // Function returned by EventList.on()
5763
+ * store.add(myEvent.on(handler));
5764
+ *
5765
+ * // Raw cleanup function
5766
+ * store.add(() => connection.close());
5767
+ *
5768
+ * // Conditional — safe with undefined
5769
+ * store.add(this.maybeEvent?.on(handler));
5770
+ * ```
5771
+ */
5772
+ add(disposable: IDisposable | DisposeFn | Function | null | undefined): void;
5773
+ /**
5774
+ * Dispose all registered resources. Each registered disposable is cleaned up,
5775
+ * then the internal list is cleared. The store can be reused after disposal.
5776
+ *
5777
+ * Called automatically by the engine when a component's `onDisable` lifecycle fires.
5778
+ */
5779
+ dispose(): void;
5780
+ }
5781
+
5782
+ /** A function that performs cleanup when called */
5783
+ export declare type DisposeFn = () => void;
5784
+
5375
5785
  /** Recursive disposes all referenced resources by this object. Does not traverse children */
5376
5786
  export declare function disposeObjectResources(obj: object | null | undefined): void;
5377
5787
 
@@ -5479,6 +5889,12 @@ export declare class DragControls extends Component implements IPointerEventHand
5479
5889
  * providing visual feedback about the object's position relative to surfaces below it.
5480
5890
  */
5481
5891
  showGizmo: boolean;
5892
+ /** Invoked once when a drag begins (after the minimum drag distance threshold is met). */
5893
+ dragStarted: EventList;
5894
+ /** Invoked every frame while the object is being dragged. */
5895
+ dragUpdated: EventList;
5896
+ /** Invoked once when the last pointer is released and the drag ends. */
5897
+ dragEnded: EventList;
5482
5898
  /**
5483
5899
  * Returns the object currently being dragged by this DragControls component, if any.
5484
5900
  * @returns The object being dragged or null if no object is currently dragged
@@ -5919,17 +6335,43 @@ export declare class EnvironmentScene extends Scene {
5919
6335
  createAreaLightMaterial(intensity: number): MeshBasicMaterial;
5920
6336
  }
5921
6337
 
5922
- export declare const euler: EulerSerializer;
6338
+ /** An Euler value, either as a Three.js Euler or as a `[x, y, z]` tuple (radians) */
6339
+ declare type EulerValue = Euler | [number, number, number];
5923
6340
 
5924
- declare class EulerSerializer extends TypeSerializer {
5925
- constructor();
5926
- onDeserialize(data: any, _context: SerializationContext): Euler | undefined;
5927
- onSerialize(data: any, _context: SerializationContext): {
5928
- x: any;
5929
- y: any;
5930
- z: any;
5931
- order: any;
5932
- };
6341
+ /** Typed event bus. Known {@link ContextEventMap} events get full autocomplete.
6342
+ * Custom events can be typed at the call site via generic parameter.
6343
+ * @example Known events
6344
+ * ```ts
6345
+ * context.events.on("scene-content-changed", e => e.object);
6346
+ * ```
6347
+ * @example Custom events — type at call site
6348
+ * ```ts
6349
+ * context.events.emit<{ pts: number }>("scored", { pts: 10 });
6350
+ * context.events.on<{ pts: number }>("scored", e => e.pts);
6351
+ * ```
6352
+ * @example Once
6353
+ * ```ts
6354
+ * context.events.on("scene-content-changed", e => { ... }, { once: true });
6355
+ * ```
6356
+ */
6357
+ export declare class EventBus {
6358
+ private _listeners;
6359
+ /** Emit a known {@link ContextEventMap} event */
6360
+ emit<K extends keyof ContextEventMap & string>(type: K, detail?: ContextEventMap[K]): void;
6361
+ /** Emit a custom event with user-provided type */
6362
+ emit<T>(type: string, detail?: T): void;
6363
+ /** Subscribe to a known {@link ContextEventMap} event. Returns an unsubscribe function. */
6364
+ on<K extends keyof ContextEventMap & string>(type: K, callback: (args: ContextEventMap[K]) => void, options?: EventBusListenerOptions): () => void;
6365
+ /** Subscribe to a custom event with user-provided type. Returns an unsubscribe function. */
6366
+ on<T>(type: string, callback: (args: T) => void, options?: EventBusListenerOptions): () => void;
6367
+ /** Remove all listeners. Called when the context is cleared or destroyed. */
6368
+ clear(): void;
6369
+ }
6370
+
6371
+ /** Options for {@link EventBus.on}. */
6372
+ export declare interface EventBusListenerOptions {
6373
+ /** If true the listener is automatically removed after the first invocation. */
6374
+ once?: boolean;
5933
6375
  }
5934
6376
 
5935
6377
  /**
@@ -5978,13 +6420,9 @@ declare class EulerSerializer extends TypeSerializer {
5978
6420
  * @see {@link Button} for UI button events
5979
6421
  */
5980
6422
  export declare class EventList<TArgs extends any = any> implements IEventList {
6423
+ $serializedTypes: Record<string, any>;
5981
6424
  /** checked during instantiate to create a new instance */
5982
6425
  readonly isEventList = true;
5983
- /* Excluded from this release type: __internalOnInstantiate */
5984
- private target?;
5985
- private key?;
5986
- /** set an event target to try invoke the EventTarget dispatchEvent when this EventList is invoked */
5987
- setEventTarget(key: string, target: object): void;
5988
6426
  /** How many callback methods are subscribed to this event */
5989
6427
  get listenerCount(): number;
5990
6428
  /** If the event is currently being invoked */
@@ -6017,13 +6455,41 @@ export declare class EventList<TArgs extends any = any> implements IEventList {
6017
6455
  invoke(...args: Array<TArgs>): boolean;
6018
6456
  /** Add a new event listener to this event
6019
6457
  * @returns a function to remove the event listener
6458
+ * @see {@link removeEventListener} for more details and return value information
6459
+ * @see {@link off} for an alias with better readability when unsubscribing from events
6460
+ * @example
6461
+ * ```ts
6462
+ * const off = myEvent.addEventListener(args => console.log("Clicked!", args));
6463
+ * // later
6464
+ * off();
6465
+ * ```
6020
6466
  */
6021
6467
  addEventListener(callback: (args: TArgs) => void): Function;
6468
+ /**
6469
+ * Alias for addEventListener for better readability when subscribing to events. You can use it like this:
6470
+ * ```ts
6471
+ * myEvent.on(args => console.log("Clicked!", args));
6472
+ * ```
6473
+ * @returns a function to remove the event listener
6474
+ * @see {@link addEventListener} for more details and return value information
6475
+ */
6476
+ on(callback: (args: TArgs) => void): Function;
6022
6477
  /**
6023
6478
  * Remove an event listener from this event.
6024
6479
  * @returns true if the event listener was found and removed, false otherwise
6025
6480
  */
6026
6481
  removeEventListener(fn: Function | null | undefined): boolean;
6482
+ /**
6483
+ * Alias for removeEventListener for better readability when unsubscribing from events. You can use it like this:
6484
+ * ```ts
6485
+ * const off = myEvent.on(args => console.log("Clicked!", args));
6486
+ * // later
6487
+ * off();
6488
+ * ```
6489
+ *
6490
+ * @see {@link removeEventListener} for more details and return value information
6491
+ */
6492
+ off(callback: Function | null | undefined): boolean;
6027
6493
  /**
6028
6494
  * Remove all event listeners from this event. Use with caution! This will remove all listeners!
6029
6495
  */
@@ -6054,6 +6520,7 @@ declare type EventListenerOptions_2 = {
6054
6520
  signal?: AbortSignal;
6055
6521
  };
6056
6522
 
6523
+ /** @deprecated No longer automatically dispatched. Use `eventList.on()` directly instead. */
6057
6524
  export declare class EventListEvent<TArgs extends any> extends Event {
6058
6525
  args?: TArgs;
6059
6526
  }
@@ -6064,7 +6531,7 @@ declare class EventListSerializer extends TypeSerializer {
6064
6531
  onDeserialize(data: EventListData, context: SerializationContext): EventList<any> | undefined | null;
6065
6532
  }
6066
6533
 
6067
- export declare const eventListSerializer: EventListSerializer;
6534
+ export declare let eventListSerializer: EventListSerializer;
6068
6535
 
6069
6536
  /**
6070
6537
  * [EventSystem](https://engine.needle.tools/docs/api/EventSystem) is responsible for managing and dispatching input events to UI components within the scene.
@@ -6507,7 +6974,7 @@ declare type FitParameters = {
6507
6974
  * @see {@link HingeJoint} for rotating connections
6508
6975
  */
6509
6976
  export declare class FixedJoint extends Joint {
6510
- protected createJoint(self: Rigidbody, other: Rigidbody): void;
6977
+ protected createJoint(self: Rigidbody, other: Rigidbody): any;
6511
6978
  }
6512
6979
 
6513
6980
  declare type FocusRect = DOMRect | Element | {
@@ -7159,16 +7626,13 @@ export declare function getResourceUserCount(object: object): number | undefined
7159
7626
  * Returns a lazily-resolved proxy typed as {@link SceneData}.
7160
7627
  * The proxy is cached per context — each context gets exactly one instance.
7161
7628
  *
7162
- * Accessing a property traverses the scene graph on demand:
7163
- * - First level → find Object3D by node name
7164
- * - Second level getComponent by component name (via TypeStore)
7165
- * - Third level read/write a field on the real component instance
7629
+ * Shape mirrors the generated `needle-bindings.gen.d.ts`:
7630
+ * ctx.sceneData.MyGlb.Camera.$components.OrbitControls.autoRotate = true;
7631
+ * ctx.sceneData.MyGlb.Camera.$object //THREE.Camera
7632
+ * ctx.sceneData.MyGlb.UI.Button.$components.Button //Needle Button component
7166
7633
  *
7167
- * If a node or component is not found, property accesses log a warning
7168
- * instead of throwing, so chained access never crashes.
7169
- *
7170
- * @example
7171
- * ctx.sceneData.Camera.OrbitControls.autoRotate = true;
7634
+ * GLB name is ignored at runtime (scene is already loaded).
7635
+ * Node lookup starts at the scene root.
7172
7636
  */
7173
7637
  export declare function getSceneData(ctx: IContext): SceneData;
7174
7638
 
@@ -7694,14 +8158,8 @@ export declare type GuidsMap = {
7694
8158
  [key: string]: string;
7695
8159
  };
7696
8160
 
7697
- /* Excluded from this release type: hasCommercialLicense */
7698
-
7699
- /* Excluded from this release type: hasIndieLicense */
7700
-
7701
8161
  /* Excluded from this release type: hasPointerEventComponent */
7702
8162
 
7703
- /* Excluded from this release type: hasProLicense */
7704
-
7705
8163
  export declare function hideDebugConsole(): void;
7706
8164
 
7707
8165
  export declare enum HideFlags {
@@ -7761,7 +8219,7 @@ export declare class HingeJoint extends Joint {
7761
8219
  anchor?: Vector3;
7762
8220
  /** Axis of rotation for the hinge (e.g., Vector3(0,1,0) for vertical axis) */
7763
8221
  axis?: Vector3;
7764
- protected createJoint(self: Rigidbody, other: Rigidbody): void;
8222
+ protected createJoint(self: Rigidbody, other: Rigidbody): any;
7765
8223
  }
7766
8224
 
7767
8225
  declare type HitPointObject = Object3D & {
@@ -7984,7 +8442,7 @@ declare const HTMLElementBase: typeof HTMLElement;
7984
8442
 
7985
8443
  export declare type IAnimationComponent = Pick<IComponent, "gameObject"> & {
7986
8444
  isAnimationComponent: boolean;
7987
- addClip?(clip: AnimationClip): any;
8445
+ addClip?(clip: AnimationClip): void;
7988
8446
  };
7989
8447
 
7990
8448
  /* Excluded from this release type: IApplyPrototypeExtension */
@@ -8058,6 +8516,12 @@ export declare interface ICollider extends IComponent {
8058
8516
  * Default: undefined
8059
8517
  */
8060
8518
  filter?: number[];
8519
+ /** The density of the collider used for automatic mass calculation.
8520
+ * When the attached Rigidbody has `autoMass` enabled, the mass is computed as `density × volume`.
8521
+ * Note: Make sure to call updateProperties after having changed this property
8522
+ * Default: undefined (uses physics engine default of 1.0)
8523
+ */
8524
+ density?: number;
8061
8525
  }
8062
8526
 
8063
8527
  export declare type ICollisionContext = {
@@ -8084,7 +8548,6 @@ export declare interface IComponent extends IHasGuid {
8084
8548
  /* Excluded from this release type: __internalEnable */
8085
8549
  /* Excluded from this release type: __internalDisable */
8086
8550
  /* Excluded from this release type: __internalDestroy */
8087
- /* Excluded from this release type: resolveGuids */
8088
8551
  /** experimental, called when the script is registered for the first time, this is called even if the component is not enabled. */
8089
8552
  registering?(): any;
8090
8553
  awake(): any;
@@ -8121,6 +8584,24 @@ export declare interface IConnectionData {
8121
8584
 
8122
8585
  export declare type IContext = Context;
8123
8586
 
8587
+ /**
8588
+ * Interface for objects that hold resources and can be disposed.
8589
+ * Implement this interface on any object that needs deterministic cleanup.
8590
+ *
8591
+ * @example
8592
+ * ```ts
8593
+ * class MyResource implements IDisposable {
8594
+ * dispose() { /* release resources *\/ }
8595
+ * }
8596
+ * ```
8597
+ *
8598
+ * @category Utilities
8599
+ * @group Lifecycle
8600
+ */
8601
+ export declare interface IDisposable {
8602
+ dispose(): void;
8603
+ }
8604
+
8124
8605
  /** Implement to receive callbacks from {@type @needle-tools/editor-sync} package */
8125
8606
  declare interface IEditorModification {
8126
8607
  /**
@@ -8140,7 +8621,6 @@ export declare interface IEffectProvider {
8140
8621
 
8141
8622
  export declare interface IEventList {
8142
8623
  readonly isEventList: true;
8143
- __internalOnInstantiate(map: InstantiateContext): IEventList;
8144
8624
  }
8145
8625
 
8146
8626
  export declare interface IGameObject extends Object3D {
@@ -8241,6 +8721,8 @@ declare interface ILayoutGroup extends IComponent {
8241
8721
  export declare interface ILight extends IComponent {
8242
8722
  intensity: number;
8243
8723
  color: Color;
8724
+ /** The type of light as a lowercase string: `"directional"`, `"point"`, `"spot"` */
8725
+ readonly type: "directional" | "point" | "spot";
8244
8726
  }
8245
8727
 
8246
8728
  declare interface ILightDataRegistry {
@@ -8431,13 +8913,45 @@ export declare interface INeedleXRSessionEventReceiver extends Pick<IComponent,
8431
8913
  export declare interface INetworkConnection {
8432
8914
  get isConnected(): boolean;
8433
8915
  get isInRoom(): boolean;
8434
- send(key: string, data: IModel | object | boolean | null | string | number, queue: SendQueue): unknown;
8916
+ send(key: string, data?: IModel | object | boolean | string | number, queue?: SendQueue): unknown;
8435
8917
  }
8436
8918
 
8437
8919
  export declare interface INetworkingWebsocketUrlProvider {
8438
8920
  getWebsocketUrl(): string | null;
8439
8921
  }
8440
8922
 
8923
+ /**
8924
+ * @experimental
8925
+ * Interface for a network transport layer used by {@link NetworkConnection}.
8926
+ * The default implementation wraps a websocket via `websocket-ts`.
8927
+ * Custom implementations can be injected into {@link NetworkConnection.connect}
8928
+ * for testing or alternative transports.
8929
+ *
8930
+ * **Lifecycle:** After creating a transport and passing it to `connect()`,
8931
+ * `NetworkConnection` sets the four event callbacks (`onOpen`, `onClose`,
8932
+ * `onError`, `onMessage`) and then calls {@link start}. The transport
8933
+ * should call `onOpen` when the connection is ready.
8934
+ */
8935
+ export declare interface INetworkTransport {
8936
+ /** Start the connection. Called by NetworkConnection after event callbacks are set.
8937
+ * May return a promise if setup is async (e.g. dynamic imports). */
8938
+ start(): void | Promise<void>;
8939
+ /** Send data (string for JSON messages, Uint8Array for binary) */
8940
+ send(data: string | Uint8Array): void;
8941
+ /** Close the transport */
8942
+ close(): void | Promise<void>;
8943
+ /** The URL this transport is connected to, if applicable */
8944
+ readonly url: string | undefined;
8945
+ /** Called when the transport connection opens */
8946
+ onOpen: (() => void) | null;
8947
+ /** Called when the transport connection closes */
8948
+ onClose: (() => void) | null;
8949
+ /** Called when an error occurs */
8950
+ onError: ((err: any) => void) | null;
8951
+ /** Called when a message is received. Data is either a string (JSON) or Blob (binary). */
8952
+ onMessage: ((data: string | Blob) => void) | null;
8953
+ }
8954
+
8441
8955
  export declare class InheritVelocityModule {
8442
8956
  enabled: boolean;
8443
8957
  curve: MinMaxCurve;
@@ -8457,10 +8971,20 @@ export declare class InheritVelocityModule {
8457
8971
  applyCurrent(vel: Vector3 | Vector3_2, t01: number, lerpFactor: number): void;
8458
8972
  }
8459
8973
 
8974
+ /* Excluded from this release type: initAddressableSerializers */
8975
+
8976
+ /** Register all builtin serializers and prototype patches.
8977
+ * Must be called from {@link initEngine} so the registrations survive tree-shaking
8978
+ * when the package declares `sideEffects: false`.
8979
+ */
8980
+ export declare function initBuiltinSerializers(): void;
8981
+
8460
8982
  /** Register the Rapier physics backend. Called from {@link initEngine}
8461
8983
  * to ensure it runs regardless of tree-shaking. */
8462
8984
  export declare function initPhysics(): void;
8463
8985
 
8986
+ /* Excluded from this release type: initVolumeParameterSerializer */
8987
+
8464
8988
  /**
8465
8989
  * Handles all input events including mouse, touch, keyboard, and XR controllers.
8466
8990
  * Access via `this.context.input` from any component.
@@ -8514,14 +9038,33 @@ export declare class Input implements IInput {
8514
9038
  */
8515
9039
  private readonly _eventListeners;
8516
9040
  /** Adds an event listener for the specified event type. The callback will be called when the event is triggered.
9041
+ *
9042
+ * Returns an unsubscribe function — call it to remove the listener.
9043
+ * Pass it to {@link Behaviour.autoCleanup} for automatic lifecycle management.
9044
+ *
8517
9045
  * @param type The event type to listen for
8518
9046
  * @param callback The callback to call when the event is triggered
8519
9047
  * @param options The options for adding the event listener.
8520
- * @example Basic usage
9048
+ * @returns A function that removes the event listener when called.
9049
+ *
9050
+ * @example With autoCleanup (recommended)
8521
9051
  * ```ts
8522
- * input.addEventListener("pointerdown", (evt) => {
9052
+ * export class MyComponent extends Behaviour {
9053
+ * onEnable() {
9054
+ * this.autoCleanup(this.context.input.addEventListener("pointerdown", (evt) => {
9055
+ * console.log("Pointer down", evt.pointerId, evt.pointerType);
9056
+ * }));
9057
+ * }
9058
+ * // Listener is automatically removed on disable — no manual cleanup needed!
9059
+ * }
9060
+ * ```
9061
+ * @example Manual unsubscribe
9062
+ * ```ts
9063
+ * const off = input.addEventListener("pointerdown", (evt) => {
8523
9064
  * console.log("Pointer down", evt.pointerId, evt.pointerType);
8524
9065
  * });
9066
+ * // later
9067
+ * off();
8525
9068
  * ```
8526
9069
  * @example Adding a listener that is called after all other listeners
8527
9070
  * By using a higher value for the queue the listener will be called after other listeners (default queue is 0).
@@ -8537,8 +9080,8 @@ export declare class Input implements IInput {
8537
9080
  * }, { once: true });
8538
9081
  * ```
8539
9082
  */
8540
- addEventListener(type: PointerEventNames, callback: PointerEventListener, options?: EventListenerOptions_2): any;
8541
- addEventListener(type: KeyboardEventNames, callback: KeyboardEventListener, options?: EventListenerOptions_2): any;
9083
+ addEventListener(type: PointerEventNames, callback: PointerEventListener, options?: EventListenerOptions_2): () => void;
9084
+ addEventListener(type: KeyboardEventNames, callback: KeyboardEventListener, options?: EventListenerOptions_2): () => void;
8542
9085
  /** Removes the event listener from the specified event type. If no queue is specified the listener will be removed from all queues.
8543
9086
  * @param type The event type to remove the listener from
8544
9087
  * @param callback The callback to remove
@@ -8984,7 +9527,7 @@ export declare function instantiate(instance: AssetReference, opts?: IInstantiat
8984
9527
  export declare function instantiate(instance: IGameObject | Object3D, opts?: IInstantiateOptions | null): IGameObject;
8985
9528
 
8986
9529
  /**
8987
- * Provides access to the instantiated object and its clone
9530
+ * Provides access to the instantiated object map (used by EventList etc.)
8988
9531
  */
8989
9532
  export declare type InstantiateContext = Readonly<InstantiateReferenceMap>;
8990
9533
 
@@ -9024,7 +9567,8 @@ export declare class InstantiateOptions implements IInstantiateOptions {
9024
9567
  cloneAssign(other: InstantiateOptions | IInstantiateOptions): void;
9025
9568
  }
9026
9569
 
9027
- declare type InstantiateReferenceMap = Record<string, ObjectCloneReference>;
9570
+ /** Maps uuid/guid { original, clone } for Object3D and Component instances */
9571
+ export declare type InstantiateReferenceMap = Record<string, ObjectCloneReference>;
9028
9572
 
9029
9573
  /**
9030
9574
  * An empty component that can be used to mark an object as interactable.
@@ -9095,8 +9639,10 @@ export declare interface IPhysicsEngine {
9095
9639
  postStep(): any;
9096
9640
  /** Indicates whether the physics engine is currently updating */
9097
9641
  get isUpdating(): boolean;
9098
- /** Clears all cached data (e.g., mesh data when creating scaled mesh colliders) */
9099
- clearCaches(): any;
9642
+ /** Tears down the physics world and frees all resources. The world will be re-created on next use. */
9643
+ dispose(): void;
9644
+ /** @deprecated Use {@link dispose} instead. */
9645
+ clearCaches(): void;
9100
9646
  /** Enables or disables the physics engine */
9101
9647
  enabled: boolean;
9102
9648
  /** Returns the underlying physics world object */
@@ -9143,6 +9689,11 @@ export declare interface IPhysicsEngine {
9143
9689
  * @returns False to ignore this collider, true to include it
9144
9690
  */
9145
9691
  filterPredicate?: (collider: ICollider) => boolean;
9692
+ /** When true, trigger/sensor colliders will be included in the raycast results.
9693
+ * By default trigger colliders are skipped.
9694
+ * @default false
9695
+ */
9696
+ includeTriggers?: boolean;
9146
9697
  }): RaycastResult;
9147
9698
  /**
9148
9699
  * Performs a raycast that also returns the normal vector at the hit point
@@ -9170,6 +9721,11 @@ export declare interface IPhysicsEngine {
9170
9721
  * @returns False to ignore this collider, true to include it
9171
9722
  */
9172
9723
  filterPredicate?: (collider: ICollider) => boolean;
9724
+ /** When true, trigger/sensor colliders will be included in the raycast results.
9725
+ * By default trigger colliders are skipped.
9726
+ * @default false
9727
+ */
9728
+ includeTriggers?: boolean;
9173
9729
  }): RaycastResult;
9174
9730
  /**
9175
9731
  * Finds all colliders within a sphere
@@ -9326,8 +9882,9 @@ export declare interface IPhysicsEngine {
9326
9882
  * @returns The underlying physics body or null if not found
9327
9883
  */
9328
9884
  getBody(obj: ICollider | IRigidbody): null | any;
9329
- addFixedJoint(body1: IRigidbody, body2: IRigidbody): any;
9330
- addHingeJoint(body1: IRigidbody, body2: IRigidbody, anchor: Vec3, axis: Vec3): any;
9885
+ addFixedJoint(body1: IRigidbody, body2: IRigidbody): Promise<any> | any;
9886
+ addHingeJoint(body1: IRigidbody, body2: IRigidbody, anchor: Vec3, axis: Vec3): Promise<any> | any;
9887
+ removeJoint(joint: any): void;
9331
9888
  /** Enable to render collider shapes */
9332
9889
  debugRenderColliders: boolean;
9333
9890
  /** Enable to visualize raycasts in the scene with gizmos */
@@ -9548,6 +10105,18 @@ export declare function isDestroyed(go: Object3D): boolean;
9548
10105
  /** True when the application runs on a local url */
9549
10106
  export declare function isDevEnvironment(): boolean;
9550
10107
 
10108
+ /**
10109
+ * Type guard to check if an object implements {@link IDisposable}.
10110
+ *
10111
+ * @example
10112
+ * ```ts
10113
+ * if (isDisposable(obj)) {
10114
+ * obj.dispose(); // safe to call
10115
+ * }
10116
+ * ```
10117
+ */
10118
+ export declare function isDisposable(value: unknown): value is IDisposable;
10119
+
9551
10120
  export declare function isDisposed(obj: object): boolean;
9552
10121
 
9553
10122
  export declare interface ISerializable {
@@ -9582,6 +10151,10 @@ export declare function isHotReloadEnabled(): boolean;
9582
10151
  /**@returns true if the element is an needle engine icon element */
9583
10152
  export declare function isIconElement(element: Node): boolean;
9584
10153
 
10154
+ export declare interface ISignalReceiver {
10155
+ readonly isSignalReceiver: true;
10156
+ }
10157
+
9585
10158
  /** @deprecated use {@link DeviceUtilities.isiOS} instead */
9586
10159
  export declare function isiOS(): boolean;
9587
10160
 
@@ -9616,6 +10189,8 @@ export declare function isResourceTrackingEnabled(): boolean;
9616
10189
  /** @deprecated use {@link DeviceUtilities.isSafari} instead */
9617
10190
  export declare function isSafari(): boolean;
9618
10191
 
10192
+ export declare function isTrackModel(obj: unknown): obj is TrackModel;
10193
+
9619
10194
  export declare function isUsingInstancing(instance: Object3D): boolean;
9620
10195
 
9621
10196
  export declare interface ITime {
@@ -9740,7 +10315,9 @@ declare abstract class Joint extends Component {
9740
10315
  connectedBody?: Rigidbody;
9741
10316
  get rigidBody(): Rigidbody | null;
9742
10317
  private _rigidBody;
10318
+ private _jointHandle;
9743
10319
  onEnable(): void;
10320
+ onDisable(): void;
9744
10321
  private create;
9745
10322
  protected abstract createJoint(self: Rigidbody, other: Rigidbody): any;
9746
10323
  }
@@ -9782,6 +10359,15 @@ declare class Keyframe_2 {
9782
10359
  }
9783
10360
  export { Keyframe_2 as Keyframe }
9784
10361
 
10362
+ /** Keyframe array or tween shorthand */
10363
+ declare type KF<V> = AnimationKeyframe<V>[] | Tween<V>;
10364
+
10365
+ /** Keyframe array or tween shorthand */
10366
+ declare type KF_2<V> = AnimationKeyframe<V>[] | Tween<V>;
10367
+
10368
+ /** Keyframe array or tween shorthand */
10369
+ declare type KF_3<V> = AnimationKeyframe<V>[] | Tween<V>;
10370
+
9785
10371
  declare type LabelHandle = {
9786
10372
  setText(str: string): any;
9787
10373
  };
@@ -9878,10 +10464,13 @@ declare type LifecycleMethodOptions = {
9878
10464
  */
9879
10465
  export declare class Light extends Component implements ILight {
9880
10466
  /**
9881
- * The type of light (spot, directional, point, etc.)
9882
- * Can not be changed at runtime.
10467
+ * The type of light as a lowercase string: `"directional"`, `"point"`, `"spot"`.
10468
+ * Implements {@link ILight.type}. Can not be changed at runtime.
9883
10469
  */
9884
- private type;
10470
+ get type(): ILight["type"];
10471
+ /** Numeric LightType serialized from Unity/Blender — converts to string on write */
10472
+ set type(value: LightType | ILight["type"]);
10473
+ private _type;
9885
10474
  /**
9886
10475
  * The maximum distance the light affects.
9887
10476
  * Only applicable for spot and point lights.
@@ -9987,11 +10576,6 @@ export declare class Light extends Component implements ILight {
9987
10576
  * and applies all settings like shadows, intensity, and color.
9988
10577
  */
9989
10578
  createLight(): void;
9990
- /**
9991
- * Coroutine that updates the main light reference in the context
9992
- * if this directional light should be the main light
9993
- */
9994
- updateMainLightRoutine(): Generator<undefined, void, unknown>;
9995
10579
  /**
9996
10580
  * Controls whether the renderer's shadow map type can be changed when soft shadows are used
9997
10581
  */
@@ -10040,6 +10624,25 @@ declare enum LightShadows {
10040
10624
  Soft = 2
10041
10625
  }
10042
10626
 
10627
+ /**
10628
+ * Defines the type of light in a scene.
10629
+ * @see {@link Light} for configuring light properties and behavior
10630
+ */
10631
+ declare enum LightType {
10632
+ /** Spot light that emits light in a cone shape */
10633
+ Spot = 0,
10634
+ /** Directional light that emits parallel light rays in a specific direction */
10635
+ Directional = 1,
10636
+ /** Point light that emits light in all directions from a single point */
10637
+ Point = 2,
10638
+ /** Area light */
10639
+ Area = 3,
10640
+ /** Rectangle shaped area light that only affects baked lightmaps and light probes */
10641
+ Rectangle = 3,
10642
+ /** Disc shaped area light that only affects baked lightmaps and light probes */
10643
+ Disc = 4
10644
+ }
10645
+
10043
10646
  export declare class LimitVelocityOverLifetimeModule {
10044
10647
  enabled: boolean;
10045
10648
  dampen: number;
@@ -10433,13 +11036,15 @@ export declare function markAsInstancedRendered(go: Object3D, instanced: boolean
10433
11036
  time: number;
10434
11037
  }
10435
11038
 
10436
- export declare class MarkerTrackHandler extends TrackHandler {
10437
- models: Array<Models.MarkerModel & Record<string, any>>;
10438
- needsSorting: boolean;
10439
- foreachMarker<T>(type?: string | null): Generator<T, void, unknown>;
10440
- onEnable(): void;
10441
- evaluate(_time: number): void;
10442
- private sort;
11039
+ /**
11040
+ * Builder for marker tracks. Provides `.marker()` for adding markers.
11041
+ * @category Animation and Sequencing
11042
+ */
11043
+ export declare interface MarkerTrackBuilder extends TimelineBuilderBase {
11044
+ /** Adds a marker referencing a signal asset by guid */
11045
+ marker(time: number, asset: string, options?: SignalMarkerOptions): MarkerTrackBuilder;
11046
+ /** Mutes this track so it is skipped during playback */
11047
+ muted(muted?: boolean): MarkerTrackBuilder;
10443
11048
  }
10444
11049
 
10445
11050
  export declare enum MarkerType {
@@ -10985,6 +11590,7 @@ export declare type Model = (GLTF | FBX | OBJ | CustomModel);
10985
11590
 
10986
11591
  declare namespace Models {
10987
11592
  export {
11593
+ isTrackModel,
10988
11594
  TimelineAssetModel,
10989
11595
  TrackType,
10990
11596
  ClipExtrapolation,
@@ -11028,15 +11634,13 @@ export declare type MouseButtonName = "left" | "right" | "middle";
11028
11634
  /* Excluded from this release type: nameofFactory */
11029
11635
 
11030
11636
  /**
11031
- * Global proxy for the primary Needle Engine context.
11032
- * Resolves lazily on property access via `ContextRegistry.Current` —
11033
- * safe to import at module level, including in SSR environments
11034
- * (returns a silent error proxy when no context is active).
11637
+ * Quick access to the current Needle Engine context from anywhere — no need to pass `ctx` around.
11638
+ * Use it in React/Svelte/Vue components, button handlers, or plain JavaScript.
11035
11639
  *
11036
- * Use this outside of Needle component lifecycle (e.g. in Svelte/React/Vue
11037
- * components, button handlers, or vanilla JS) instead of threading `ctx` around.
11640
+ * Safe to import at module level, including in SSR environments.
11641
+ * For pages with multiple `<needle-engine>` elements, use `ctx` directly instead.
11038
11642
  *
11039
- * For multiple `<needle-engine>` elements on the same page, use `ctx` directly.
11643
+ * @experimental This API may change in future releases.
11040
11644
  *
11041
11645
  * @example
11042
11646
  * import { needle } from "@needle-tools/engine";
@@ -11194,11 +11798,17 @@ export declare interface NeedleEngineAttributes {
11194
11798
  'hash': string;
11195
11799
  /** Set to automatically add OrbitControls to the loaded scene. */
11196
11800
  'camera-controls': string;
11197
- /** Override the default draco decoder path location. */
11801
+ /** Override the default Draco decoder/decompressor path. Can be a URL or a local path to a directory containing the Draco decoder files.
11802
+ * @default "https://www.gstatic.com/draco/versioned/decoders/1.5.7/"
11803
+ * @example <needle-engine dracoDecoderPath="./decoders/draco/"></needle-engine>
11804
+ */
11198
11805
  'dracoDecoderPath': string;
11199
- /** Override the default draco library type. */
11806
+ /** Override the default Draco decoder type. */
11200
11807
  'dracoDecoderType': 'wasm' | 'js';
11201
- /** Override the default KTX2 transcoder/decoder path. */
11808
+ /** Override the default KTX2 transcoder/decoder path. Can be a URL or a local path to a directory containing the KTX2 transcoder files.
11809
+ * @default "https://cdn.needle.tools/static/three/0.179.1/basis2/"
11810
+ * @example <needle-engine ktx2DecoderPath="./decoders/ktx2/"></needle-engine>
11811
+ */
11202
11812
  'ktx2DecoderPath': string;
11203
11813
  /** Prevent context from being disposed when element is removed from DOM. */
11204
11814
  'keep-alive': 'true' | 'false';
@@ -12152,8 +12762,7 @@ export declare class NeedleXRSession implements INeedleXRSession {
12152
12762
  get referenceSpace(): XRSpace | null;
12153
12763
  /** @returns the XRFrame `viewerpose` using the xr `referenceSpace` */
12154
12764
  get viewerPose(): XRViewerPose | undefined;
12155
- /** @returns `true` if any image is currently being tracked */
12156
- /** returns true if images are currently being tracked */
12765
+ /** @returns `true` if any image is currently being tracked or emulated */
12157
12766
  get isTrackingImages(): boolean;
12158
12767
  /** The currently active XR rig */
12159
12768
  get rig(): IXRRig | null;
@@ -12199,6 +12808,8 @@ export declare class NeedleXRSession implements INeedleXRSession {
12199
12808
  private readonly _xr_update_scripts;
12200
12809
  /** scripts that are in the scene but inactive (e.g. disabled parent gameObject) */
12201
12810
  private readonly _inactive_scripts;
12811
+ /** tracks scripts that have received onEnterXR — prevents spurious onLeaveXR calls */
12812
+ private readonly _scripts_in_xr;
12202
12813
  private readonly _controllerAdded;
12203
12814
  private readonly _controllerRemoved;
12204
12815
  private readonly _originalCameraWorldPosition?;
@@ -12586,7 +13197,7 @@ export declare class NetworkConnection implements INetworkConnection {
12586
13197
  /** Use to leave a room that you are currently connected to (use `leaveRoom()` to disconnect from the currently active room but you can also specify a room name) */
12587
13198
  leaveRoom(room?: string | null): boolean;
12588
13199
  /** Send a message to the networking backend - it will be broadcasted to all connected users (except yourself) in the same room by default */
12589
- send<K extends NetworkEventKey>(key: K, data?: (K extends keyof NetworkEventMap ? NetworkEventData<K> : WebsocketSendType) | null, queue?: SendQueue): void;
13200
+ send<K extends NetworkEventKey>(key: K, data?: (K extends keyof NetworkEventMap ? NetworkEventData<K> : WebsocketSendType), queue?: SendQueue): void;
12590
13201
  /**
12591
13202
  * Deletes the network state for a specific object on the server.
12592
13203
  * This removes the object's state from the room, preventing it from being sent to newly joining users.
@@ -12608,61 +13219,69 @@ export declare class NetworkConnection implements INetworkConnection {
12608
13219
  private _defaultMessagesBufferArray;
12609
13220
  sendBufferedMessagesNow(): void;
12610
13221
  /** Use to start listening to networking events.
12611
- * To unsubscribe from events use the `{@link stopListen}` method.
13222
+ * Returns an unsubscribe function that removes the listener when called.
13223
+ * The returned function can also be passed to {@link stopListen} or {@link Component.autoCleanup} for automatic lifecycle management.
13224
+ *
13225
+ * @example With autoCleanup (recommended)
13226
+ * ```ts
13227
+ * export class MyComponent extends Behaviour {
13228
+ * onEnable() {
13229
+ * this.autoCleanup(this.context.connection.beginListen("joined-room", () => {
13230
+ * console.log("I joined a networked room");
13231
+ * }));
13232
+ * }
13233
+ * // Automatically unsubscribed on disable — no manual cleanup needed!
13234
+ * }
13235
+ * ```
12612
13236
  *
12613
- * @example Custom event example
13237
+ * @example Manual unsubscribe
12614
13238
  * ```ts
12615
- * // Listen to a custom event sent by the server
12616
- * this.context.connection.beginListen<MyDataType>("my-custom-event", (data) => {
12617
- * console.log("Received custom event:", data);
12618
- * });
13239
+ * const unsub = this.context.connection.beginListen("joined-room", () => { });
13240
+ * // Later:
13241
+ * unsub(); // removes the listener
12619
13242
  * ```
12620
13243
  *
12621
- * @example Listening to room events
13244
+ * @example With stopListen (legacy pattern, still supported)
12622
13245
  * ```ts
12623
- * // Make sure to unsubscribe from events when the component is disabled
12624
13246
  * export class MyComponent extends Behaviour {
12625
13247
  * onEnable() {
12626
- * this.connection.beginListen("joined-room", this.onJoinedRoom)
13248
+ * this.context.connection.beginListen("joined-room", this.onJoinedRoom);
12627
13249
  * }
12628
13250
  * onDisable() {
12629
- * this.connection.stopListen("joined-room", this.onJoinedRoom)
13251
+ * this.context.connection.stopListen("joined-room", this.onJoinedRoom);
12630
13252
  * }
12631
13253
  * onJoinedRoom = () => {
12632
- * console.log("I joined a networked room")
13254
+ * console.log("I joined a networked room");
12633
13255
  * }
12634
13256
  * }
12635
13257
  * ```
12636
13258
  * @link https://engine.needle.tools/docs/networking.html
12637
13259
  *
12638
13260
  */
12639
- beginListen<K extends NetworkEventKey>(key: K, callback: K extends keyof NetworkEventMap ? NetworkEventMap[K] : (...args: any[]) => void): K extends keyof NetworkEventMap ? NetworkEventMap[K] : (...args: any[]) => void;
13261
+ beginListen<K extends NetworkEventKey>(key: K, callback: K extends keyof NetworkEventMap ? NetworkEventMap[K] : (...args: any[]) => void): DisposeFn;
12640
13262
  /**@deprecated please use stopListen instead (2.65.2-pre) */
12641
13263
  stopListening<K extends NetworkEventKey>(key: K, callback: (K extends keyof NetworkEventMap ? NetworkEventMap[K] : (...args: any[]) => void) | null): void;
12642
- /** Use to stop listening to networking events
13264
+ /** Use to stop listening to networking events.
13265
+ * Accepts either the original callback or the unsubscribe function returned by {@link beginListen}.
12643
13266
  * To subscribe to events use the `{@link beginListen}` method.
12644
- * See the example below for typical usage:
12645
13267
  *
12646
- * ### Component Example
13268
+ * @example
12647
13269
  * ```ts
12648
- * // Make sure to unsubscribe from events when the component is disabled
12649
- * export class MyComponent extends Behaviour {
12650
- * onEnable() {
12651
- * this.connection.beginListen("joined-room", this.onJoinedRoom)
12652
- * }
12653
- * onDisable() {
12654
- * this.connection.stopListen("joined-room", this.onJoinedRoom)
12655
- * }
12656
- * onJoinedRoom = () => {
12657
- * console.log("I joined a networked room")
12658
- * }
12659
- * }
13270
+ * // Both patterns work:
13271
+ * this.context.connection.stopListen("joined-room", this.onJoinedRoom); // original callback
13272
+ * this.context.connection.stopListen("joined-room", unsub); // unsubscribe fn from beginListen
12660
13273
  * ```
12661
13274
  */
12662
- stopListen<K extends NetworkEventKey>(key: K, callback: (K extends keyof NetworkEventMap ? NetworkEventMap[K] : (...args: any[]) => void) | null): void;
12663
- /** Use to start listening to networking binary events */
12664
- beginListenBinary(identifier: string, callback: BinaryCallback): BinaryCallback;
12665
- /** Use to stop listening to networking binary events */
13275
+ private static _didLogStopListenHint;
13276
+ stopListen<K extends NetworkEventKey>(key: K, callback: (K extends keyof NetworkEventMap ? NetworkEventMap[K] : (...args: any[]) => void) | Function | null): void;
13277
+ /** Use to start listening to networking binary events.
13278
+ * Returns an unsubscribe function that removes the listener when called.
13279
+ * The returned function can also be passed to {@link stopListenBinary} or {@link Component.autoCleanup}.
13280
+ */
13281
+ beginListenBinary(identifier: string, callback: BinaryCallback): DisposeFn;
13282
+ /** Use to stop listening to networking binary events.
13283
+ * Accepts either the original callback or the unsubscribe function returned by {@link beginListenBinary}.
13284
+ */
12666
13285
  stopListenBinary(identifier: string, callback: any): void;
12667
13286
  private netWebSocketUrlProvider?;
12668
13287
  /** Use to override the networking server backend url.
@@ -12671,16 +13290,19 @@ export declare class NetworkConnection implements INetworkConnection {
12671
13290
  registerProvider(prov: INetworkingWebsocketUrlProvider): void;
12672
13291
  /** Used to connect to the networking server
12673
13292
  * @param url Optional url to connect to. If not provided, it will use the url from the registered `INetworkingWebsocketUrlProvider` or the default backend networking url. If you want to change the url after connecting, you need to disconnect first and then connect again with the new url.
13293
+ * @param transport Optional custom transport to use instead of the default websocket. Useful for testing or alternative transports.
12674
13294
  */
12675
- connect(url?: string): Promise<boolean>;
13295
+ connect(url?: string, transport?: INetworkTransport): Promise<boolean>;
12676
13296
  /** Disconnect from the networking backend + reset internal state */
12677
13297
  disconnect(): void;
13298
+ /** Full teardown: disconnect, clear all listeners, and release all resources.
13299
+ * Called when the owning Context is destroyed. After dispose(), this instance should not be reused. */
13300
+ dispose(): void;
12678
13301
  private _listeners;
12679
13302
  private _listenersBinary;
12680
13303
  private connected;
12681
- private channelId;
12682
13304
  private _connectionId;
12683
- private _ws;
13305
+ private _transport;
12684
13306
  private _waitingForSocket;
12685
13307
  private _isInRoom;
12686
13308
  private _currentRoomName;
@@ -12690,6 +13312,8 @@ export declare class NetworkConnection implements INetworkConnection {
12690
13312
  private _state;
12691
13313
  private _currentDelay;
12692
13314
  private _connectingToWebsocketPromise;
13315
+ /** Wire up a transport's event callbacks and start it */
13316
+ private connectTransport;
12693
13317
  private connectWebsocket;
12694
13318
  private onMessage;
12695
13319
  private handleIncomingBinaryMessage;
@@ -12818,7 +13442,7 @@ export declare interface NetworkEventMap {
12818
13442
  * @see {@link RoomEvents} for room lifecycle events
12819
13443
  * @see {@link isLocalNetwork} for local network detection
12820
13444
  * @link https://engine.needle.tools/docs/how-to-guides/networking/
12821
- * @summary Networking configuration
13445
+ * @summary Configures the websocket server URL for multiplayer networking
12822
13446
  * @category Networking
12823
13447
  * @group Components
12824
13448
  */
@@ -12955,7 +13579,7 @@ export declare type OBJ = {
12955
13579
  scenes: Object3D[];
12956
13580
  };
12957
13581
 
12958
- declare type ObjectCloneReference = {
13582
+ export declare type ObjectCloneReference = {
12959
13583
  readonly original: object;
12960
13584
  readonly clone: object;
12961
13585
  };
@@ -13039,7 +13663,7 @@ declare class ObjectSerializer extends TypeSerializer {
13039
13663
  onDeserialize(data: ObjectData | string | null, context: SerializationContext): Object3D<Object3DEventMap> | Component | null | undefined;
13040
13664
  }
13041
13665
 
13042
- export declare const objectSerializer: ObjectSerializer;
13666
+ export declare let objectSerializer: ObjectSerializer;
13043
13667
 
13044
13668
  declare type ObjectToNodeMap = {
13045
13669
  [uuid: string]: number;
@@ -13162,6 +13786,61 @@ export declare function offXRSessionEnd(fn: (evt: XRSessionEventArgs) => void):
13162
13786
  */
13163
13787
  export declare function offXRSessionStart(fn: (evt: XRSessionEventArgs) => void): void;
13164
13788
 
13789
+ /**
13790
+ * @experimental
13791
+ * Subscribe to a DOM event on any {@link EventTarget} (window, document, HTML elements, etc.)
13792
+ * and return an {@link IDisposable} that removes the listener when disposed.
13793
+ *
13794
+ * Provides full TypeScript event type inference — the callback parameter
13795
+ * is automatically typed based on the event name (e.g. `"resize"` → `UIEvent`,
13796
+ * `"click"` → `MouseEvent`).
13797
+ *
13798
+ * Use with {@link DisposableStore.add} for automatic lifecycle cleanup in components.
13799
+ *
13800
+ * @param target The EventTarget to listen on (window, document, an element, etc.)
13801
+ * @param type The event name (e.g. `"resize"`, `"click"`, `"keydown"`)
13802
+ * @param listener The event handler callback
13803
+ * @param options Optional addEventListener options (passive, capture, once, signal)
13804
+ * @returns An {@link IDisposable} that removes the event listener when disposed
13805
+ *
13806
+ * @example Standalone usage
13807
+ * ```ts
13808
+ * import { on } from "@needle-tools/engine";
13809
+ *
13810
+ * const sub = on(window, "resize", (ev) => {
13811
+ * // ev is typed as UIEvent
13812
+ * console.log("resized", ev.target);
13813
+ * });
13814
+ *
13815
+ * // Later: clean up
13816
+ * sub.dispose();
13817
+ * ```
13818
+ *
13819
+ * @example With autoCleanup in a component
13820
+ * ```ts
13821
+ * import { Behaviour, on } from "@needle-tools/engine";
13822
+ *
13823
+ * export class MyComponent extends Behaviour {
13824
+ * onEnable() {
13825
+ * this.autoCleanup(on(window, "resize", (ev) => { /* UIEvent *\/ }));
13826
+ * this.autoCleanup(on(document, "keydown", (ev) => { /* KeyboardEvent *\/ }));
13827
+ * this.autoCleanup(on(this.context.domElement, "click", (ev) => { /* MouseEvent *\/ }));
13828
+ * }
13829
+ * // All listeners removed automatically on disable!
13830
+ * }
13831
+ * ```
13832
+ *
13833
+ * @category Utilities
13834
+ * @group Lifecycle
13835
+ */
13836
+ export declare function on<K extends keyof WindowEventMap>(target: Window, type: K, listener: (ev: WindowEventMap[K]) => void, options?: boolean | AddEventListenerOptions): IDisposable;
13837
+
13838
+ export declare function on<K extends keyof DocumentEventMap>(target: Document, type: K, listener: (ev: DocumentEventMap[K]) => void, options?: boolean | AddEventListenerOptions): IDisposable;
13839
+
13840
+ export declare function on<K extends keyof HTMLElementEventMap>(target: HTMLElement, type: K, listener: (ev: HTMLElementEventMap[K]) => void, options?: boolean | AddEventListenerOptions): IDisposable;
13841
+
13842
+ export declare function on(target: EventTarget, type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): IDisposable;
13843
+
13165
13844
  /**
13166
13845
  * Register a callback in the engine onAfterRender event
13167
13846
  * This is called every frame after the main camera has rendered
@@ -13796,14 +14475,13 @@ export declare class OrbitControls extends Component implements ICameraControlle
13796
14475
  */
13797
14476
  private setLookTargetFromConstraint;
13798
14477
  private lerpLookTarget;
14478
+ private canFocusAtPointer;
13799
14479
  private setTargetFromRaycast;
13800
14480
  /**
13801
14481
  * Fits the camera to show the objects provided (defaults to the scene if no objects are passed in)
13802
14482
  * @param options The options for fitting the camera. Use to provide objects to fit to, fit direction and size and other settings.
13803
14483
  */
13804
14484
  fitCamera(options?: OrbitFitCameraOptions): any;
13805
- /** @deprecated Use fitCamera(options) */
13806
- fitCamera(objects?: Object3D | Array<Object3D>, options?: Omit<OrbitFitCameraOptions, "objects">): any;
13807
14485
  private _haveAttachedKeyboardEvents;
13808
14486
  }
13809
14487
 
@@ -14004,6 +14682,11 @@ export declare class OrbitControls extends Component implements ICameraControlle
14004
14682
  value: number | boolean | string;
14005
14683
  };
14006
14684
 
14685
+ /** Extracts parameter names of a given type from the builder's tracked parameter map */
14686
+ declare type ParamNamesOfType<TParams, PType extends string> = {
14687
+ [K in keyof TParams & string]: TParams[K] extends PType ? K : never;
14688
+ }[keyof TParams & string];
14689
+
14007
14690
  declare type ParseNumber<T> = T extends `${infer U extends number}` ? U : never;
14008
14691
 
14009
14692
  /** Load a gltf file from a url. This is the core method used by Needle Engine to load gltf files. All known extensions are registered here.
@@ -14635,13 +15318,15 @@ export declare class OrbitControls extends Component implements ICameraControlle
14635
15318
  * The timeline asset containing tracks, clips, and markers that this director will play.
14636
15319
  * Assign a timeline asset exported from Unity or Blender to enable playback.
14637
15320
  */
14638
- playableAsset?: Models.TimelineAssetModel;
15321
+ get playableAsset(): Models.TimelineAssetModel | undefined;
15322
+ set playableAsset(value: Models.TimelineAssetModel | undefined);
15323
+ private _playableAsset?;
14639
15324
  /**
14640
15325
  * When true, the timeline starts playing automatically when the component awakens.
14641
15326
  * Set to false to control playback manually via `play()`.
14642
15327
  * @default false
14643
15328
  */
14644
- playOnAwake?: boolean;
15329
+ playOnAwake: boolean;
14645
15330
  /**
14646
15331
  * Determines how the timeline behaves when it reaches the end of its duration.
14647
15332
  * @default DirectorWrapMode.Loop
@@ -14719,15 +15404,15 @@ export declare class OrbitControls extends Component implements ICameraControlle
14719
15404
  /** Iterates over all tracks of the timeline
14720
15405
  * @returns all tracks of the timeline
14721
15406
  */
14722
- forEachTrack(): Generator<Tracks.TrackHandler, void, unknown>;
15407
+ forEachTrack(): Generator<Tracks.TimelineTrackHandler, void, unknown>;
14723
15408
  /**
14724
15409
  * @returns all animation tracks of the timeline
14725
15410
  */
14726
- get animationTracks(): Tracks.AnimationTrackHandler[];
15411
+ get animationTracks(): Tracks.TimelineAnimationTrack[];
14727
15412
  /**
14728
15413
  * @returns all audio tracks of the timeline
14729
15414
  */
14730
- get audioTracks(): Tracks.AudioTrackHandler[];
15415
+ get audioTracks(): Tracks.TimelineAudioTrack[];
14731
15416
  /**
14732
15417
  * @returns all signal tracks of the timeline
14733
15418
  */
@@ -14735,7 +15420,15 @@ export declare class OrbitControls extends Component implements ICameraControlle
14735
15420
  /**
14736
15421
  * @returns all marker tracks of the timeline
14737
15422
  */
14738
- get markerTracks(): Tracks.MarkerTrackHandler[];
15423
+ get markerTracks(): Tracks.TimelineMarkerTrack[];
15424
+ /**
15425
+ * @returns all activation tracks of the timeline
15426
+ */
15427
+ get activationTracks(): Tracks.TimelineActivationTrack[];
15428
+ /**
15429
+ * @returns all tracks of the timeline
15430
+ */
15431
+ get tracks(): ReadonlyArray<Tracks.TimelineTrackHandler>;
14739
15432
  /**
14740
15433
  * Iterates over all markers of the timeline, optionally filtering by type
14741
15434
  *
@@ -14749,13 +15442,13 @@ export declare class OrbitControls extends Component implements ICameraControlle
14749
15442
  *
14750
15443
  */
14751
15444
  foreachMarker<T extends Record<string, any>>(type?: string | null): Generator<(T & Models.MarkerModel)>;
14752
- private _guidsMap?;
14753
- /* Excluded from this release type: resolveGuids */
15445
+ private _needsGraphRebuild;
14754
15446
  private _isPlaying;
14755
15447
  private _internalUpdateRoutine;
14756
15448
  private _isPaused;
14757
15449
  /** internal, true during the time stop() is being processed */
14758
15450
  private _isStopping;
15451
+ /* Excluded from this release type: _isUserEvaluation */
14759
15452
  private _time;
14760
15453
  private _duration;
14761
15454
  private _weight;
@@ -14764,6 +15457,7 @@ export declare class OrbitControls extends Component implements ICameraControlle
14764
15457
  private readonly _signalTracks;
14765
15458
  private readonly _markerTracks;
14766
15459
  private readonly _controlTracks;
15460
+ private readonly _activationTracks;
14767
15461
  private readonly _customTracks;
14768
15462
  private readonly _tracksArray;
14769
15463
  private get _allTracks();
@@ -15755,6 +16449,9 @@ export declare class OrbitControls extends Component implements ICameraControlle
15755
16449
  w: number;
15756
16450
  };
15757
16451
 
16452
+ /** A Quaternion value, either as a Three.js Quaternion or as a `[x, y, z, w]` tuple */
16453
+ declare type QuatValue = Quaternion | [number, number, number, number];
16454
+
15758
16455
  /** Generates a random number
15759
16456
  * @deprecated use Mathf.random(min, max)
15760
16457
  */
@@ -15880,6 +16577,11 @@ export declare class OrbitControls extends Component implements ICameraControlle
15880
16577
  * @default undefined
15881
16578
  */
15882
16579
  useIgnoreRaycastLayer?: boolean;
16580
+ /** When true, trigger/sensor colliders will be included in the raycast results.
16581
+ * By default trigger colliders are skipped.
16582
+ * @default false
16583
+ */
16584
+ includeTriggers?: boolean;
15883
16585
  }): null | {
15884
16586
  point: Vector3;
15885
16587
  collider: ICollider;
@@ -15897,6 +16599,11 @@ export declare class OrbitControls extends Component implements ICameraControlle
15897
16599
  * @default undefined
15898
16600
  */
15899
16601
  useIgnoreRaycastLayer?: boolean;
16602
+ /** When true, trigger/sensor colliders will be included in the raycast results.
16603
+ * By default trigger colliders are skipped.
16604
+ * @default false
16605
+ */
16606
+ includeTriggers?: boolean;
15900
16607
  }): null | {
15901
16608
  point: Vector3;
15902
16609
  normal: Vector3;
@@ -15942,6 +16649,10 @@ export declare class OrbitControls extends Component implements ICameraControlle
15942
16649
  private _gravity;
15943
16650
  get gravity(): Vec3;
15944
16651
  set gravity(value: Vec3);
16652
+ /** Tears down the physics world and frees all WASM resources.
16653
+ * After calling this, the world will be re-created on next use. */
16654
+ dispose(): void;
16655
+ /** @deprecated Use {@link dispose} instead. */
15945
16656
  clearCaches(): void;
15946
16657
  addBoxCollider(collider: ICollider, size: Vector3): Promise<void>;
15947
16658
  addSphereCollider(collider: ICollider): Promise<void>;
@@ -15988,7 +16699,8 @@ export declare class OrbitControls extends Component implements ICameraControlle
15988
16699
  private getRigidbodyRelativeMatrix;
15989
16700
  private static centerConnectionPos;
15990
16701
  private static centerConnectionRot;
15991
- addFixedJoint(body1: IRigidbody, body2: IRigidbody): void;
16702
+ private _jointTempMatrix;
16703
+ addFixedJoint(body1: IRigidbody, body2: IRigidbody): Promise<ImpulseJoint | null>;
15992
16704
  /** The joint prevents any relative movement between two rigid-bodies, except for relative rotations along one axis. This is typically used to simulate wheels, fans, etc. They are characterized by one local anchor as well as one local axis on each rigid-body. */
15993
16705
  addHingeJoint(body1: IRigidbody, body2: IRigidbody, anchor: {
15994
16706
  x: number;
@@ -15998,8 +16710,11 @@ export declare class OrbitControls extends Component implements ICameraControlle
15998
16710
  x: number;
15999
16711
  y: number;
16000
16712
  z: number;
16001
- }): void;
16713
+ }): Promise<ImpulseJoint | null>;
16714
+ removeJoint(joint: ImpulseJoint): void;
16715
+ /** Compute the relative transform from body1's local space to body2's local space (W2⁻¹ * W1), ignoring scale. */
16002
16716
  private calculateJointRelativeMatrices;
16717
+ private normalizeMatrixColumns;
16003
16718
  }
16004
16719
 
16005
16720
  /**
@@ -16802,10 +17517,17 @@ export declare class OrbitControls extends Component implements ICameraControlle
16802
17517
  */
16803
17518
  export declare class Rigidbody extends Component implements IRigidbody {
16804
17519
  get isRigidbody(): boolean;
16805
- /** When true the mass will be automatically calculated by the attached colliders */
17520
+ /** When true the mass is automatically computed from the attached colliders using `mass = density × volume`.
17521
+ * Each collider's {@link Collider.density} determines how heavy it contributes to the total mass.
17522
+ * Disable to set mass explicitly via the `mass` property.
17523
+ */
16806
17524
  autoMass: boolean;
16807
- /** By default the mass will be automatically calculated (see `autoMass`) by the physics engine using the collider sizes
16808
- * To set the mass manually you can either set the `mass` value or set `autoMass` to `false`
17525
+ /** The mass of the rigidbody in kg (when `autoMass` is disabled).
17526
+ * When `autoMass` is enabled, reading this returns the computed mass from `density × volume` of all attached colliders.
17527
+ * Setting this property automatically disables `autoMass`.
17528
+ *
17529
+ * **Prefer using {@link Collider.density}** with `autoMass` enabled instead — density scales
17530
+ * naturally with collider size, while explicit mass stays fixed regardless of shape changes.
16809
17531
  */
16810
17532
  set mass(value: number);
16811
17533
  get mass(): number;
@@ -16888,7 +17610,8 @@ export declare class OrbitControls extends Component implements ICameraControlle
16888
17610
  onEnable(): void;
16889
17611
  onDisable(): void;
16890
17612
  onDestroy(): void;
16891
- onValidate(): void;
17613
+ onValidate(property?: string): void;
17614
+ private static _didWarnAutoMass;
16892
17615
  beforePhysics(): Generator<undefined, void, unknown>;
16893
17616
  /** Teleport the rigidbody to a new position in the world.
16894
17617
  * Will reset forces before setting the object world position
@@ -18108,10 +18831,17 @@ export declare class OrbitControls extends Component implements ICameraControlle
18108
18831
 
18109
18832
  export declare function sendDestroyed(guid: string, con: INetworkConnection, opts?: SyncDestroyOptions): void;
18110
18833
 
18834
+ /** Controls when a network message is actually sent to the server.
18835
+ * @see {@link NetworkConnection.send}
18836
+ */
18111
18837
  export declare enum SendQueue {
18838
+ /** Hold the message until the transport connection opens, then send it. Use for messages that must arrive as soon as the socket is ready (e.g. join-room). */
18112
18839
  OnConnection = 0,
18840
+ /** Hold the message until the client has joined a room, then send it. Use for messages that require room context. */
18113
18841
  OnRoomJoin = 1,
18842
+ /** Buffer the message and send it on the next `sendBufferedMessagesNow()` call (typically once per frame). This is the default for `send()`. */
18114
18843
  Queued = 2,
18844
+ /** Send the message to the server immediately without buffering. */
18115
18845
  Immediate = 3
18116
18846
  }
18117
18847
 
@@ -18544,6 +19274,16 @@ export declare class OrbitControls extends Component implements ICameraControlle
18544
19274
  asset: string;
18545
19275
  }
18546
19276
 
19277
+ /**
19278
+ * Options for a signal marker in the timeline builder
19279
+ */
19280
+ export declare type SignalMarkerOptions = {
19281
+ /** Whether the signal should fire if the playback starts past its time (default: false) */
19282
+ retroActive?: boolean;
19283
+ /** Whether the signal should only fire once (default: false) */
19284
+ emitOnce?: boolean;
19285
+ };
19286
+
18547
19287
  /** SignalReceiver is a component that listens for signals and invokes a reaction when a signal is received.
18548
19288
  * Signals can be added to a signal track on a {@link PlayableDirector}
18549
19289
  *
@@ -18551,7 +19291,8 @@ export declare class OrbitControls extends Component implements ICameraControlle
18551
19291
  * @category Animation and Sequencing
18552
19292
  * @group Components
18553
19293
  */
18554
- export declare class SignalReceiver extends Component {
19294
+ export declare class SignalReceiver extends Component implements ISignalReceiver {
19295
+ readonly isSignalReceiver = true;
18555
19296
  private static receivers;
18556
19297
  static invoke(guid: string): void;
18557
19298
  events?: SignalReceiverEvent[];
@@ -18570,10 +19311,26 @@ export declare class OrbitControls extends Component implements ICameraControlle
18570
19311
  reaction: EventList<void>;
18571
19312
  }
18572
19313
 
18573
- export declare class SignalTrackHandler extends TrackHandler {
19314
+ /**
19315
+ * Builder for signal tracks. Provides `.signal()` for callback-based signals and `.marker()` for asset-based markers.
19316
+ * @category Animation and Sequencing
19317
+ */
19318
+ export declare interface SignalTrackBuilder extends TimelineBuilderBase {
19319
+ /** Adds a signal with a callback that fires at the given time */
19320
+ signal(time: number, callback: Function, options?: SignalMarkerOptions): SignalTrackBuilder;
19321
+ /** Adds a signal marker referencing a signal asset by guid */
19322
+ marker(time: number, asset: string, options?: SignalMarkerOptions): SignalTrackBuilder;
19323
+ /** Mutes this track so it is skipped during playback */
19324
+ muted(muted?: boolean): SignalTrackBuilder;
19325
+ }
19326
+
19327
+ export declare class SignalTrackHandler extends TimelineTrackHandler {
18574
19328
  models: Models.SignalMarkerModel[];
18575
19329
  didTrigger: boolean[];
18576
19330
  receivers: Array<SignalReceiver | null>;
19331
+ private _lastTime;
19332
+ onEnable(): void;
19333
+ onMuteChanged(): void;
18577
19334
  evaluate(time: number): void;
18578
19335
  }
18579
19336
 
@@ -19073,10 +19830,6 @@ export declare class OrbitControls extends Component implements ICameraControlle
19073
19830
  * Removes scale change monitoring when the collider is disabled.
19074
19831
  */
19075
19832
  onDisable(): void;
19076
- /**
19077
- * Updates collider properties when validated in the editor or inspector.
19078
- */
19079
- onValidate(): void;
19080
19833
  }
19081
19834
 
19082
19835
  export declare class SphereIntersection implements Intersection {
@@ -19829,8 +20582,15 @@ export declare class OrbitControls extends Component implements ICameraControlle
19829
20582
  * Configuration for an animation state in the builder
19830
20583
  */
19831
20584
  export declare type StateOptions = {
19832
- /** The animation clip for this state */
19833
- clip: AnimationClip;
20585
+ /**
20586
+ * The animation clip for this state. Accepts:
20587
+ * - A pre-built `AnimationClip`
20588
+ * - A single {@link TrackDescriptor} from {@link track}
20589
+ * - An array of {@link TrackDescriptor}s (multiple tracks combined into one clip)
20590
+ *
20591
+ * When omitted, use {@link AnimatorControllerBuilder.track .track()} to define animation tracks inline.
20592
+ */
20593
+ clip?: AnimationClip | TrackDescriptor | TrackDescriptor[];
19834
20594
  /** Whether the animation should loop (default: false) */
19835
20595
  loop?: boolean;
19836
20596
  /** Base speed multiplier (default: 1) */
@@ -20396,6 +21156,7 @@ export declare class OrbitControls extends Component implements ICameraControlle
20396
21156
  set font(val: string | null);
20397
21157
  get font(): string | null;
20398
21158
  private _font;
21159
+ private _assignedAtRuntime;
20399
21160
  /**
20400
21161
  * Whether to support basic rich text tags in the `text` property. Supported tags include `<b>`, `<i>`, and `<color=hex>`. For example: `Hello <b>World</b>` or `Score: <color=#ff0000>100</color>`
20401
21162
  * @default false
@@ -20651,6 +21412,57 @@ export declare class OrbitControls extends Component implements ICameraControlle
20651
21412
  /* Excluded from this release type: update */
20652
21413
  }
20653
21414
 
21415
+ /**
21416
+ * Handles activation (visibility) of bound objects for a timeline activation track.
21417
+ *
21418
+ * Each clip on the track defines a time range during which the bound objects should be active (visible).
21419
+ * @see TimelineTrackHandler for details on how tracks and clips work in general, and how to mutate them at runtime.
21420
+ * @see PlayableDirector for how to control timeline playback and time.
21421
+ * @see TimelineBuilder for how to create and configure timelines and tracks in the editor.
21422
+ */
21423
+ export declare class TimelineActivationTrack extends TimelineTrackHandler {
21424
+ evaluate(time: number): void;
21425
+ }
21426
+
21427
+ export declare class TimelineAnimationTrack extends TimelineTrackHandler {
21428
+ /* Excluded from this release type: models */
21429
+ /* Excluded from this release type: trackOffset */
21430
+ /** The object that is being animated. */
21431
+ target?: Object3D;
21432
+ /** The AnimationMixer, should be shared with the animator if an animator is bound */
21433
+ mixer?: AnimationMixer;
21434
+ clips: Array<AnimationClip>;
21435
+ actions: Array<AnimationAction>;
21436
+ /**
21437
+ * You can use the weight to blend the timeline animation tracks with multiple animation tracks on the same object.
21438
+ * @default 1
21439
+ */
21440
+ weight: number;
21441
+ /** holds data/info about clips differences */
21442
+ private _actionOffsets;
21443
+ private _didBind;
21444
+ private _animator;
21445
+ onDisable(): void;
21446
+ onDestroy(): void;
21447
+ onStateChanged(): void;
21448
+ createHooks(clipModel: Models.AnimationClipModel, clip: any): void;
21449
+ bind(): void;
21450
+ private ensureTrackOffsets;
21451
+ private _useclipOffsets;
21452
+ private _totalOffsetPosition;
21453
+ private _totalOffsetRotation;
21454
+ private _totalOffsetPosition2;
21455
+ private _totalOffsetRotation2;
21456
+ private _summedPos;
21457
+ private _tempPos;
21458
+ private _summedRot;
21459
+ private _tempRot;
21460
+ private _clipRotQuat;
21461
+ evaluate(time: number): void;
21462
+ private createRotationInterpolant;
21463
+ private createPositionInterpolant;
21464
+ }
21465
+
20654
21466
  /**
20655
21467
  * @category Animation and Sequencing
20656
21468
  * @see {@link PlayableDirector} for the main component to control timelines in Needle Engine.
@@ -20660,6 +21472,325 @@ export declare class OrbitControls extends Component implements ICameraControlle
20660
21472
  tracks: TrackModel[];
20661
21473
  };
20662
21474
 
21475
+ /**
21476
+ * Handles audio playback for a timeline audio track.
21477
+ *
21478
+ * **Runtime mutation:** The track model is read fresh every frame during `evaluate()`.
21479
+ * You can mutate `track.volume`, `clip.start`, `clip.end`, `clip.asset.volume` etc.
21480
+ * at any time — changes take effect on the next frame without rebuilding the timeline.
21481
+ *
21482
+ * **Audio stopping:** Audio clips are automatically stopped when:
21483
+ * - Timeline time moves outside a clip's `[start, end]` range (e.g. jumping or normal playback advancing past a clip)
21484
+ * - The track is muted (via `muted = true`)
21485
+ * - The director is stopped (`director.stop()`)
21486
+ * - The director is paused (`director.pause()`)
21487
+ * - The director is disabled or destroyed
21488
+ */
21489
+ export declare class TimelineAudioTrack extends TimelineTrackHandler {
21490
+ models: Array<AudioClipModel_2>;
21491
+ listener: AudioListener_3;
21492
+ audio: Array<Audio_2>;
21493
+ audioContextTimeOffset: Array<number>;
21494
+ lastTime: number;
21495
+ audioSource?: AudioSource;
21496
+ /** Track-level volume multiplier (0–1). Applied on top of per-clip volume each frame. */
21497
+ get volume(): number;
21498
+ set volume(val: number);
21499
+ private _audioLoader;
21500
+ private getAudioFilePath;
21501
+ onAllowAudioChanged(allow: boolean): void;
21502
+ addModel(model: Models.ClipModel): void;
21503
+ onDisable(): void;
21504
+ onDestroy(): void;
21505
+ onMuteChanged(): void;
21506
+ stop(): void;
21507
+ private _playableDirectorResumed;
21508
+ onPauseChanged(): void;
21509
+ evaluate(time: number): void;
21510
+ /** Call to load audio buffer for a specific time in the track. Can be used to preload the timeline audio */
21511
+ loadAudio(time: number, lookAhead?: number, lookBehind?: number): Promise<(AudioBuffer | null)[]> | null;
21512
+ private isInTimeRange;
21513
+ private static _audioBuffers;
21514
+ static dispose(): void;
21515
+ private handleAudioLoading;
21516
+ }
21517
+
21518
+ /**
21519
+ * A fluent builder for creating timeline assets ({@link TimelineAssetModel}) from code.
21520
+ *
21521
+ * Use {@link TimelineBuilder.create} to start building a timeline.
21522
+ *
21523
+ * @example Using build() for timelines without signal callbacks
21524
+ * ```ts
21525
+ * const timeline = TimelineBuilder.create("MySequence")
21526
+ * .animationTrack("Character", animator)
21527
+ * .clip(walkClip, { duration: 2, easeIn: 0.3 })
21528
+ * .clip(runClip, { duration: 3, easeIn: 0.5, easeOut: 0.5 })
21529
+ * .activationTrack("FX", particleObject)
21530
+ * .clip({ start: 1, duration: 2 })
21531
+ * .audioTrack("Music", audioSource)
21532
+ * .clip("music.mp3", { start: 0, duration: 5, volume: 0.8 })
21533
+ * .build();
21534
+ *
21535
+ * director.playableAsset = timeline;
21536
+ * director.play();
21537
+ * ```
21538
+ *
21539
+ * @example With inline tracks (no pre-built clips needed)
21540
+ * ```ts
21541
+ * TimelineBuilder.create("DoorSequence")
21542
+ * .animationTrack("Door", door)
21543
+ * .track(door, "position", { from: [0, 0, 0], to: [2, 0, 0], duration: 1 })
21544
+ * .track(light, "intensity", { from: 0, to: 5, duration: 1 })
21545
+ * .signalTrack("Events")
21546
+ * .signal(0.5, () => playSound("creak"))
21547
+ * .install(director);
21548
+ *
21549
+ * director.play();
21550
+ * ```
21551
+ *
21552
+ * @example Using install() with signal callbacks
21553
+ * ```ts
21554
+ * TimelineBuilder.create("WithSignals")
21555
+ * .animationTrack("Character", animator)
21556
+ * .clip(walkClip, { duration: 2 })
21557
+ * .signalTrack("Events")
21558
+ * .signal(1.0, () => console.log("1 second!"))
21559
+ * .signal(2.0, () => spawnParticles())
21560
+ * .install(director);
21561
+ *
21562
+ * director.play();
21563
+ * ```
21564
+ *
21565
+ * @category Animation and Sequencing
21566
+ * @group Utilities
21567
+ */
21568
+ export declare class TimelineBuilder {
21569
+ private _name;
21570
+ private _tracks;
21571
+ private _currentTrack;
21572
+ private _pendingSignals;
21573
+ private _idProvider;
21574
+ private constructor();
21575
+ /**
21576
+ * Creates a new TimelineBuilder instance.
21577
+ * @param name - Name for the timeline asset
21578
+ * @param seed - Optional numeric seed for deterministic guid generation. Defaults to `Date.now()`.
21579
+ */
21580
+ static create(name?: string, seed?: number): TimelineBuilderBase;
21581
+ /**
21582
+ * Adds an animation track. Chain `.clip()` calls to add pre-built clips,
21583
+ * or chain `.track()` calls to define animation data inline:
21584
+ *
21585
+ * @example With pre-built AnimationClip
21586
+ * ```ts
21587
+ * .animationTrack("Character", animator)
21588
+ * .clip(walkClip, { duration: 2, easeIn: 0.3 })
21589
+ * .clip(runClip, { duration: 3 })
21590
+ * ```
21591
+ *
21592
+ * @example With inline tracks
21593
+ * ```ts
21594
+ * .animationTrack("Door", door)
21595
+ * .track(door, "position", { from: [0, 0, 0], to: [2, 0, 0], duration: 1 })
21596
+ * .track(light, "intensity", { from: 0, to: 5, duration: 1 })
21597
+ * ```
21598
+ *
21599
+ * @param name - Display name for the track
21600
+ * @param binding - The Animator or Object3D to animate
21601
+ */
21602
+ animationTrack(name: string, binding?: Animator | Object3D | null): AnimationTrackBuilder;
21603
+ /**
21604
+ * Adds an audio track. Subsequent `.clip()` calls add audio clips to this track.
21605
+ * @param name - Display name for the track
21606
+ * @param binding - The AudioSource to play audio on (optional)
21607
+ * @param volume - Track volume multiplier (default: 1)
21608
+ */
21609
+ audioTrack(name: string, binding?: AudioSource | Object3D | null, volume?: number): AudioTrackBuilder;
21610
+ /**
21611
+ * Adds an activation track. Subsequent `.clip()` calls define when the bound object is active.
21612
+ * @param name - Display name for the track
21613
+ * @param binding - The Object3D to show/hide
21614
+ */
21615
+ activationTrack(name: string, binding?: Object3D | null): ActivationTrackBuilder;
21616
+ /**
21617
+ * Adds a control track. Subsequent `.clip()` calls control nested timelines or objects.
21618
+ * @param name - Display name for the track
21619
+ */
21620
+ controlTrack(name: string): ControlTrackBuilder;
21621
+ /**
21622
+ * Adds a signal track. Use `.signal()` or `.marker()` to add signal markers.
21623
+ * @param name - Display name for the track
21624
+ * @param binding - The SignalReceiver component (optional — if using `.signal()` with callbacks, one is created automatically by {@link install})
21625
+ */
21626
+ signalTrack(name: string, binding?: SignalReceiver | Object3D | null): SignalTrackBuilder;
21627
+ /**
21628
+ * Adds a marker track. Use `.marker()` to add markers.
21629
+ * @param name - Display name for the track
21630
+ */
21631
+ markerTrack(name: string): MarkerTrackBuilder;
21632
+ /**
21633
+ * Adds a clip to the current track. The clip type must match the track type.
21634
+ *
21635
+ * - On an **animation track**: pass an `AnimationClip`, a {@link TrackDescriptor}, or a `TrackDescriptor[]` — and optional {@link AnimationClipOptions}
21636
+ * - On an **audio track**: pass a clip URL (string) and {@link AudioClipOptions}
21637
+ * - On an **activation track**: pass {@link ActivationClipOptions}
21638
+ * - On a **control track**: pass an Object3D and {@link ControlClipOptions}
21639
+ */
21640
+ clip(asset: AnimationClip, options?: AnimationClipOptions): this;
21641
+ clip(descriptor: TrackDescriptor, options?: AnimationClipOptions): this;
21642
+ clip(descriptors: TrackDescriptor[], options?: AnimationClipOptions): this;
21643
+ clip(url: string, options: AudioClipOptions): this;
21644
+ clip(options: ActivationClipOptions): this;
21645
+ clip(sourceObject: Object3D, options: ControlClipOptions): this;
21646
+ /**
21647
+ * Adds a signal marker to the current signal or marker track.
21648
+ * @param time - Time in seconds when the signal fires
21649
+ * @param asset - The signal asset identifier (guid string)
21650
+ * @param options - Optional marker configuration
21651
+ */
21652
+ marker(time: number, asset: string, options?: SignalMarkerOptions): this;
21653
+ /**
21654
+ * Adds a signal with a callback to the current signal track.
21655
+ * This is a convenience method that automatically generates a signal asset guid,
21656
+ * adds the marker, and registers the callback so that {@link install} can wire up
21657
+ * the `SignalReceiver` on the director's GameObject.
21658
+ *
21659
+ * @param time - Time in seconds when the signal fires
21660
+ * @param callback - The function to invoke when the signal fires
21661
+ * @param options - Optional marker configuration
21662
+ *
21663
+ * @example
21664
+ * ```ts
21665
+ * const timeline = TimelineBuilder.create("Sequence")
21666
+ * .signalTrack("Events")
21667
+ * .signal(1.0, () => console.log("1 second reached!"))
21668
+ * .signal(3.5, () => console.log("halfway!"), { emitOnce: true })
21669
+ * .install(director);
21670
+ * ```
21671
+ */
21672
+ signal(time: number, callback: Function, options?: SignalMarkerOptions): this;
21673
+ /**
21674
+ * Mutes the current track so it is skipped during playback.
21675
+ */
21676
+ muted(muted?: boolean): this;
21677
+ /** Adds an animation track descriptor for an Object3D's position or scale to the current animation track */
21678
+ track(target: Object3D, property: "position" | "scale", keyframes: KF_3<Vec3Value>, options?: TrackOptions): this;
21679
+ /** Adds an animation track descriptor for an Object3D's quaternion to the current animation track */
21680
+ track(target: Object3D, property: "quaternion", keyframes: KF_3<QuatValue>, options?: TrackOptions): this;
21681
+ /** Adds an animation track descriptor for an Object3D's rotation (Euler, converted to quaternion) to the current animation track */
21682
+ track(target: Object3D, property: "rotation", keyframes: KF_3<EulerValue>, options?: TrackOptions): this;
21683
+ /** Adds an animation track descriptor for an Object3D's visibility to the current animation track */
21684
+ track(target: Object3D, property: "visible", keyframes: KF_3<boolean>, options?: TrackOptions): this;
21685
+ /** Adds an animation track descriptor for a material's numeric property to the current animation track */
21686
+ track(target: Material, property: "opacity" | "roughness" | "metalness" | "alphaTest" | "emissiveIntensity" | "envMapIntensity" | "bumpScale" | "displacementScale" | "displacementBias", keyframes: KF_3<number>, options?: TrackOptions): this;
21687
+ /** Adds an animation track descriptor for a material's color property to the current animation track */
21688
+ track(target: Material, property: "color" | "emissive", keyframes: KF_3<ColorValue>, options?: TrackOptions): this;
21689
+ /** Adds an animation track descriptor for a light's numeric property to the current animation track */
21690
+ track(target: Light_2, property: "intensity" | "distance" | "angle" | "penumbra" | "decay", keyframes: KF_3<number>, options?: TrackOptions): this;
21691
+ /** Adds an animation track descriptor for a light's color to the current animation track */
21692
+ track(target: Light_2, property: "color", keyframes: KF_3<ColorValue>, options?: TrackOptions): this;
21693
+ /** Adds an animation track descriptor for a camera's numeric property to the current animation track */
21694
+ track(target: PerspectiveCamera, property: "fov" | "near" | "far" | "zoom", keyframes: KF_3<number>, options?: TrackOptions): this;
21695
+ /**
21696
+ * Builds and returns the {@link TimelineAssetModel}.
21697
+ * Assign the result to `PlayableDirector.playableAsset` to play it.
21698
+ *
21699
+ * If you used `.signal()` with callbacks, use {@link install} instead — it calls `build()`
21700
+ * internally and also wires up the SignalReceiver on the director's GameObject.
21701
+ */
21702
+ build(): TimelineAssetModel;
21703
+ /**
21704
+ * Builds the timeline asset, assigns it to the director, and wires up any
21705
+ * `.signal()` callbacks by creating/configuring a {@link SignalReceiver} on the
21706
+ * director's GameObject.
21707
+ *
21708
+ * @param director - The PlayableDirector to install the timeline on
21709
+ * @returns The built TimelineAssetModel (also assigned to `director.playableAsset`)
21710
+ *
21711
+ * @example
21712
+ * ```ts
21713
+ * TimelineBuilder.create("MyTimeline")
21714
+ * .animationTrack("Anim", animator)
21715
+ * .clip(walkClip, { duration: 2 })
21716
+ * .signalTrack("Events")
21717
+ * .signal(1.0, () => console.log("signal fired!"))
21718
+ * .install(director);
21719
+ *
21720
+ * director.play();
21721
+ * ```
21722
+ */
21723
+ install(director: PlayableDirector): TimelineAssetModel;
21724
+ private pushTrack;
21725
+ /** Commits any pending `.track()` descriptors on the current animation track into a clip */
21726
+ private commitInlineTracks;
21727
+ }
21728
+
21729
+ /**
21730
+ * Shared methods available on all track builders and the TimelineBuilder entry point.
21731
+ * Provides track creation, build, and install methods.
21732
+ *
21733
+ * @category Animation and Sequencing
21734
+ */
21735
+ export declare interface TimelineBuilderBase {
21736
+ /** Adds an animation track. Chain `.clip()` or `.track()` to add content. */
21737
+ animationTrack(name: string, binding?: Animator | Object3D | null): AnimationTrackBuilder;
21738
+ /** Adds an audio track. Chain `.clip()` to add audio clips. */
21739
+ audioTrack(name: string, binding?: AudioSource | Object3D | null, volume?: number): AudioTrackBuilder;
21740
+ /** Adds an activation track. Chain `.clip()` to define activation windows. */
21741
+ activationTrack(name: string, binding?: Object3D | null): ActivationTrackBuilder;
21742
+ /** Adds a control track. Chain `.clip()` to control nested objects/timelines. */
21743
+ controlTrack(name: string): ControlTrackBuilder;
21744
+ /** Adds a signal track. Chain `.signal()` or `.marker()` to add events. */
21745
+ signalTrack(name: string, binding?: SignalReceiver | Object3D | null): SignalTrackBuilder;
21746
+ /** Adds a marker track. Chain `.marker()` to add markers. */
21747
+ markerTrack(name: string): MarkerTrackBuilder;
21748
+ /** Builds and returns the {@link TimelineAssetModel}. */
21749
+ build(): TimelineAssetModel;
21750
+ /** Builds the timeline, assigns it to the director, and wires up signal callbacks. */
21751
+ install(director: PlayableDirector): TimelineAssetModel;
21752
+ }
21753
+
21754
+ export declare class TimelineControlTrack extends TimelineTrackHandler {
21755
+ models: Array<Models.ClipModel>;
21756
+ timelines: Array<PlayableDirector | null>;
21757
+ resolveSourceObjects(_context: Context): void;
21758
+ private _previousActiveModel;
21759
+ evaluate(time: number): void;
21760
+ }
21761
+
21762
+ export declare class TimelineMarkerTrack extends TimelineTrackHandler {
21763
+ models: Array<Models.MarkerModel & Record<string, any>>;
21764
+ needsSorting: boolean;
21765
+ foreachMarker<T>(type?: string | null): Generator<T, void, unknown>;
21766
+ onEnable(): void;
21767
+ evaluate(_time: number): void;
21768
+ private sort;
21769
+ }
21770
+
21771
+ /**
21772
+ * A TrackHandler is responsible for evaluating a specific type of timeline track.
21773
+ * A timeline track can be an animation track, audio track, signal track, control track etc and is controlled by a {@link PlayableDirector}.
21774
+ */
21775
+ export declare abstract class TimelineTrackHandler {
21776
+ director: PlayableDirector;
21777
+ track: Models.TrackModel;
21778
+ get muted(): boolean;
21779
+ set muted(val: boolean);
21780
+ forEachClip(backwards?: boolean): IterableIterator<Models.ClipModel>;
21781
+ onEnable?(): any;
21782
+ onDisable?(): any;
21783
+ onDestroy?(): any;
21784
+ abstract evaluate(time: number): any;
21785
+ onMuteChanged?(): any;
21786
+ onPauseChanged?(): any;
21787
+ /** invoked when PlayableDirectory playmode state changes (paused, playing, stopped) */
21788
+ onStateChanged?(isPlaying: boolean): any;
21789
+ getClipTime(time: number, model: Models.ClipModel): number;
21790
+ getClipTimeNormalized(time: number, model: Models.ClipModel): number;
21791
+ evaluateWeight(time: number, index: number, models: Array<Models.ClipModel>, isActive?: boolean): number;
21792
+ }
21793
+
20663
21794
  declare type TonemappingAttributeOptions = "none" | "linear" | "neutral" | "agx";
20664
21795
 
20665
21796
  /**
@@ -20688,27 +21819,20 @@ export declare class OrbitControls extends Component implements ICameraControlle
20688
21819
  export declare function toSourceId(src: string | null): SourceIdentifier | undefined;
20689
21820
 
20690
21821
  /**
20691
- * A TrackHandler is responsible for evaluating a specific type of timeline track.
20692
- * A timeline track can be an animation track, audio track, signal track, control track etc and is controlled by a {@link PlayableDirector}.
21822
+ * An opaque descriptor for a single animation track.
21823
+ * Created by {@link track} and resolved into a Three.js KeyframeTrack
21824
+ * when passed to {@link createAnimation}, or inline to
21825
+ * {@link AnimatorControllerBuilder.state} / {@link TimelineBuilder.clip}.
21826
+ *
21827
+ * @category Animation and Sequencing
20693
21828
  */
20694
- export declare abstract class TrackHandler {
20695
- director: PlayableDirector;
20696
- track: Models.TrackModel;
20697
- get muted(): boolean;
20698
- set muted(val: boolean);
20699
- forEachClip(backwards?: boolean): IterableIterator<Models.ClipModel>;
20700
- onEnable?(): any;
20701
- onDisable?(): any;
20702
- onDestroy?(): any;
20703
- abstract evaluate(time: number): any;
20704
- onMuteChanged?(): any;
20705
- onPauseChanged?(): any;
20706
- /** invoked when PlayableDirectory playmode state changes (paused, playing, stopped) */
20707
- onStateChanged?(isPlaying: boolean): any;
20708
- getClipTime(time: number, model: Models.ClipModel): number;
20709
- getClipTimeNormalized(time: number, model: Models.ClipModel): number;
20710
- evaluateWeight(time: number, index: number, models: Array<Models.ClipModel>, isActive?: boolean): number;
20711
- }
21829
+ declare type TrackDescriptor = {
21830
+ readonly __isTrackDescriptor: true;
21831
+ /* Excluded from this release type: _target */
21832
+ /* Excluded from this release type: _property */
21833
+ /* Excluded from this release type: _keyframes */
21834
+ /* Excluded from this release type: _root */
21835
+ };
20712
21836
 
20713
21837
  /**
20714
21838
  * @category Animation and Sequencing
@@ -20734,14 +21858,26 @@ export declare class OrbitControls extends Component implements ICameraControlle
20734
21858
  rotation: Quat | Quaternion;
20735
21859
  };
20736
21860
 
21861
+ /** Options for a single track */
21862
+ declare type TrackOptions = {
21863
+ /**
21864
+ * Root object for resolving the track path.
21865
+ * - If `root === target` → self-targeting (`.property`)
21866
+ * - If `root !== target` → named targeting (`"targetName.property"` using `target.name`)
21867
+ * - If omitted → self-targeting by default
21868
+ */
21869
+ root?: Object3D;
21870
+ };
21871
+
20737
21872
  declare namespace Tracks {
20738
21873
  export {
20739
- TrackHandler,
20740
- AnimationTrackHandler,
20741
- AudioTrackHandler,
20742
- MarkerTrackHandler,
21874
+ TimelineTrackHandler,
21875
+ TimelineAnimationTrack,
21876
+ TimelineAudioTrack,
21877
+ TimelineMarkerTrack,
20743
21878
  SignalTrackHandler,
20744
- ControlTrackHandler
21879
+ TimelineActivationTrack,
21880
+ TimelineControlTrack
20745
21881
  }
20746
21882
  }
20747
21883
 
@@ -20947,10 +22083,8 @@ export declare class OrbitControls extends Component implements ICameraControlle
20947
22083
  export declare type TransitionOptions = {
20948
22084
  /** Duration of the crossfade in seconds (default: 0) */
20949
22085
  duration?: number;
20950
- /** Normalized exit time 0-1 (default: 1). Only used when hasExitTime is true */
22086
+ /** Normalized exit time 0-1. When set, the transition waits until the source animation reaches this point before transitioning. */
20951
22087
  exitTime?: number;
20952
- /** Whether the transition waits for exitTime before transitioning (default: false) */
20953
- hasExitTime?: boolean;
20954
22088
  /** Normalized offset into the destination state's animation (default: 0) */
20955
22089
  offset?: number;
20956
22090
  /** Whether duration is in seconds (true) or normalized (false) (default: false) */
@@ -21020,6 +22154,18 @@ export declare class OrbitControls extends Component implements ICameraControlle
21020
22154
 
21021
22155
  export declare function tryGetGuid(obj: any): string | undefined | null;
21022
22156
 
22157
+ /** Shorthand for a simple two-keyframe animation (start → end) */
22158
+ export declare type Tween<V> = {
22159
+ /** Start value (at time 0) */
22160
+ from: V;
22161
+ /** End value (at time = duration) */
22162
+ to: V;
22163
+ /** Duration in seconds (default: 1) */
22164
+ duration?: number;
22165
+ /** Interpolation mode (default: `"linear"`) */
22166
+ interpolation?: AnimationInterpolation;
22167
+ };
22168
+
21023
22169
  declare type Type = new (...args: any[]) => any;
21024
22170
 
21025
22171
  declare type TypeResolver<T> = (data: any) => Constructor<T> | null;
@@ -21543,6 +22689,9 @@ export declare class OrbitControls extends Component implements ICameraControlle
21543
22689
  z: number;
21544
22690
  };
21545
22691
 
22692
+ /** A Vector3 value, either as a Three.js Vector3 or as a `[x, y, z]` tuple */
22693
+ declare type Vec3Value = Vector3 | [number, number, number];
22694
+
21546
22695
  export declare type Vec4 = {
21547
22696
  x: number;
21548
22697
  y: number;
@@ -21763,8 +22912,14 @@ export declare class OrbitControls extends Component implements ICameraControlle
21763
22912
  private _receivedInput;
21764
22913
  /* Excluded from this release type: __constructor */
21765
22914
  private _playErrors;
21766
- /** start playing the video source */
21767
- play(): void;
22915
+ /**
22916
+ * Plays the assigned video clip, URL, or MediaStream.
22917
+ * If a `clip` argument is passed, it is used as the new video source (mirroring {@link AudioSource.play}).
22918
+ *
22919
+ * @param clip - Optional video URL string or {@link MediaStream} to play. If omitted, plays the currently assigned source.
22920
+ * @returns A promise that resolves to `true` when playback was successfully started, or `false` on error.
22921
+ */
22922
+ play(clip?: string | MediaStream): Promise<boolean>;
21768
22923
  /**
21769
22924
  * Stop the video playback. This will reset the video to the beginning
21770
22925
  */
@@ -22034,9 +23189,9 @@ export declare class OrbitControls extends Component implements ICameraControlle
22034
23189
  * voip.createMenuButton = true;
22035
23190
  *
22036
23191
  * // Manual control
22037
- * voip.connect(); // Start sending audio
22038
- * voip.disconnect(); // Stop sending
22039
- * voip.setMuted(true); // Mute microphone
23192
+ * voip.connect(); // Start sending your microphone
23193
+ * voip.disconnect(); // Stop sending your microphone
23194
+ * voip.setMuted(true); // Mute incoming audio (silence other users)
22040
23195
  * ```
22041
23196
  *
22042
23197
  * @summary Voice over IP for networked audio communication
@@ -22095,8 +23250,8 @@ export declare class OrbitControls extends Component implements ICameraControlle
22095
23250
  */
22096
23251
  get incomingStreams(): ReadonlyMap<string, HTMLAudioElement>;
22097
23252
  /**
22098
- * Threshold for speaking detection (0–255). When a user's audio amplitude exceeds this,
22099
- * they are considered "speaking". Default is 30.
23253
+ * Normalized amplitude threshold for speaking detection (0–1). When a user's average
23254
+ * audio amplitude exceeds this, they are considered "speaking". Default is 0.1.
22100
23255
  */
22101
23256
  speakingThreshold: number;
22102
23257
  /**
@@ -22106,6 +23261,8 @@ export declare class OrbitControls extends Component implements ICameraControlle
22106
23261
  onSpeakingChanged: EventList;
22107
23262
  private _speakingStates;
22108
23263
  private _analysers;
23264
+ private _sharedAudioContext?;
23265
+ private _lastSpeakingPollMs;
22109
23266
  private _net?;
22110
23267
  private _menubutton?;
22111
23268
  /* Excluded from this release type: awake */
@@ -22115,21 +23272,27 @@ export declare class OrbitControls extends Component implements ICameraControlle
22115
23272
  /** Set via the mic button (e.g. when the websocket connection closes and rejoins but the user was muted before we don't want to enable VOIP again automatically) */
22116
23273
  private _allowSending;
22117
23274
  private _outputStream;
23275
+ private _connectInFlight?;
22118
23276
  /**
22119
23277
  * @returns true if the component is currently sending audio
22120
23278
  */
22121
23279
  get isSending(): boolean;
22122
23280
  /** Start sending audio. */
22123
23281
  connect(audioSource?: MediaTrackConstraints): Promise<boolean>;
23282
+ private _connectImpl;
22124
23283
  /** Stop sending audio (muting your own microphone) */
22125
23284
  disconnect(opts?: {
22126
23285
  remember: boolean;
22127
23286
  }): void;
22128
23287
  /**
22129
- * Mute or unmute the audio stream (this will only mute incoming streams and not mute your own microphone. Use disconnect() to mute your own microphone)
23288
+ * Mute or unmute the audio you hear from other users (incoming streams).
23289
+ * This does NOT mute your own microphone — use {@link disconnect} to stop sending your microphone.
22130
23290
  */
22131
23291
  setMuted(mute: boolean): void;
22132
- /** Returns true if the audio stream is currently muted */
23292
+ /**
23293
+ * Returns true if incoming audio is currently muted (you can't hear other users).
23294
+ * When there are no incoming streams, returns false.
23295
+ */
22133
23296
  get isMuted(): boolean;
22134
23297
  private updateButton;
22135
23298
  /** @deprecated */
@@ -22141,6 +23304,7 @@ export declare class OrbitControls extends Component implements ICameraControlle
22141
23304
  /* Excluded from this release type: update */
22142
23305
  private setupAnalyser;
22143
23306
  private cleanupAnalyser;
23307
+ private closeSharedAudioContext;
22144
23308
  private onReceiveStream;
22145
23309
  private onStreamEnded;
22146
23310
  private onEnabledChanged;
@@ -22464,7 +23628,7 @@ export declare class OrbitControls extends Component implements ICameraControlle
22464
23628
  private onApplyPose;
22465
23629
  }
22466
23630
 
22467
- declare type WebsocketSendType = IModel | object | boolean | null | string | number;
23631
+ declare type WebsocketSendType = IModel | object | boolean | string | number;
22468
23632
 
22469
23633
  /**
22470
23634
  * Use the [WebXR](https://engine.needle.tools/docs/api/WebXR) component to enable VR and AR on **iOS and Android** in your scene. VisionOS support is also provided via QuickLook USDZ export.
@@ -22858,6 +24022,25 @@ export declare class OrbitControls extends Component implements ICameraControlle
22858
24022
  * @link https://github.com/immersive-web/marker-tracking/blob/main/explainer.md - WebXR Marker Tracking Specification
22859
24023
  */
22860
24024
  export declare class WebXRImageTracking extends Component {
24025
+ /**
24026
+ * Event invoked every frame when images are being tracked.
24027
+ * @example
24028
+ * ```ts
24029
+ * const tracker = this.gameObject.getComponent(WebXRImageTracking);
24030
+ * tracker?.imageTracked.addEventListener(evt => {
24031
+ * for (const img of evt.trackedImages) {
24032
+ * console.log(img.url, img.state);
24033
+ * }
24034
+ * });
24035
+ * ```
24036
+ */
24037
+ imageTracked: EventList<WebXRImageTrackingEvent>;
24038
+ /** @inheritdoc */
24039
+ addEventListener<K extends keyof WebXRImageTrackingEventMap>(type: K, listener: (evt: WebXRImageTrackingEventMap[K]) => any): void;
24040
+ addEventListener<T extends Event>(type: string, listener: (evt: T) => any): void;
24041
+ /** @inheritdoc */
24042
+ removeEventListener<K extends keyof WebXRImageTrackingEventMap>(type: K, listener: (evt: WebXRImageTrackingEventMap[K]) => any): void;
24043
+ removeEventListener<T extends Event>(type: string, listener: (evt: T) => any): void;
22861
24044
  /**
22862
24045
  * Set which marker should be primary (first in the list).
22863
24046
  * Useful when deploying to QuickLook mode where one marker is tracked at a time.
@@ -22944,6 +24127,18 @@ export declare class OrbitControls extends Component implements ICameraControlle
22944
24127
  private onImageTrackingUpdate;
22945
24128
  }
22946
24129
 
24130
+ /** Data passed to image tracking event listeners. */
24131
+ export declare interface WebXRImageTrackingEvent {
24132
+ /** The images currently being tracked this frame. */
24133
+ readonly trackedImages: readonly WebXRTrackedImage[];
24134
+ }
24135
+
24136
+ /** Event map for {@link WebXRImageTracking} events. Use with `addEventListener` for typed event handling. */
24137
+ export declare interface WebXRImageTrackingEventMap {
24138
+ /** Dispatched every frame when images are being tracked. The event detail contains the tracking data for the current frame. */
24139
+ "image-tracking": CustomEvent<WebXRImageTrackingEvent>;
24140
+ }
24141
+
22947
24142
  /**
22948
24143
  * Configuration model for a tracked image marker.
22949
24144
  * Defines which image to track, its physical size, and which 3D content to display when detected.
@@ -23142,8 +24337,39 @@ export declare class OrbitControls extends Component implements ICameraControlle
23142
24337
  get widthInMeters(): number;
23143
24338
  /** The ImageBitmap used for tracking */
23144
24339
  get bitmap(): ImageBitmap;
23145
- /** The {@link WebXRImageTrackingModel} configuration for this tracked image */
24340
+ /**
24341
+ * The {@link WebXRImageTrackingModel} configuration for this tracked image.
24342
+ * Use this to access the assigned 3D object, marker settings, and other image tracking configuration.
24343
+ * Available on each {@link WebXRTrackedImage} received from the `image-tracking` {@link CustomEvent} (`event.detail`).
24344
+ * @example
24345
+ * ```ts
24346
+ * tracker.addEventListener("image-tracking", event => {
24347
+ * for (const img of event.detail.trackedImages) {
24348
+ * const model = img.model;
24349
+ * // Access the assigned 3D object
24350
+ * const obj = model.object;
24351
+ * // Access other settings
24352
+ * console.log(model.widthInMeters, model.hideWhenTrackingIsLost);
24353
+ * }
24354
+ * });
24355
+ * ```
24356
+ */
23146
24357
  get model(): WebXRImageTrackingModel;
24358
+ /**
24359
+ * The 3D object or prefab assigned to this tracked image marker in the {@link WebXRImageTrackingModel}.
24360
+ * Use this to access the object associated with an AR image tracking marker from the `image-tracking` {@link CustomEvent}.
24361
+ * Shorthand for `this.model.object`.
24362
+ * @example
24363
+ * ```ts
24364
+ * tracker.addEventListener("image-tracking", event => {
24365
+ * for (const img of event.detail.trackedImages) {
24366
+ * const obj = img.trackedModel;
24367
+ * // verbose alternative: img.model.object
24368
+ * }
24369
+ * });
24370
+ * ```
24371
+ */
24372
+ get trackedModel(): AssetReference | undefined;
23147
24373
  /**
23148
24374
  * The measured size of the detected image in the real world.
23149
24375
  * May differ from `widthInMeters` if the physical marker doesn't match the configured size.