@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
@@ -1,4 +1,4 @@
1
- import type { Ball, Collider, ColliderDesc, Cuboid, EventQueue, QueryFilterFlags, Ray, RigidBody, RigidBodyDesc, World } from '@dimforge/rapier3d-compat';
1
+ import type { Ball, Collider, ColliderDesc, Cuboid, EventQueue, ImpulseJoint, QueryFilterFlags, Ray, RigidBody, RigidBodyDesc, World } from '@dimforge/rapier3d-compat';
2
2
  import { BufferAttribute, BufferGeometry, InterleavedBufferAttribute, LineBasicMaterial, LineSegments, Matrix4, Mesh, Object3D, Quaternion, Vector3, Vector4Like } from 'three'
3
3
  import * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils.js'
4
4
 
@@ -402,11 +402,16 @@ export class RapierPhysics implements IPhysicsEngine {
402
402
  filterGroups?: number,
403
403
  /** Return false to ignore this collider */
404
404
  filterPredicate?: (c: ICollider) => boolean,
405
- /** When enabled the hit object's layer will be tested. If layer 2 is enabled the object will be ignored (Layer 2 == IgnoreRaycast)
405
+ /** When enabled the hit object's layer will be tested. If layer 2 is enabled the object will be ignored (Layer 2 == IgnoreRaycast)
406
406
  * If not set the raycast will ignore objects in the IgnoreRaycast layer (default: true)
407
- * @default undefined
407
+ * @default undefined
408
408
  */
409
- useIgnoreRaycastLayer?: boolean
409
+ useIgnoreRaycastLayer?: boolean,
410
+ /** When true, trigger/sensor colliders will be included in the raycast results.
411
+ * By default trigger colliders are skipped.
412
+ * @default false
413
+ */
414
+ includeTriggers?: boolean,
410
415
  })
411
416
  : null | { point: Vector3, collider: ICollider } {
412
417
 
@@ -428,6 +433,8 @@ export class RapierPhysics implements IPhysicsEngine {
428
433
 
429
434
  const hit = this.world?.castRay(ray, maxDistance, solid, options?.queryFilterFlags, options?.filterGroups, undefined, undefined, (c) => {
430
435
  const component = c[$componentKey];
436
+ // Skip trigger/sensor colliders unless explicitly included
437
+ if (options?.includeTriggers !== true && component?.isTrigger) return false;
431
438
  if (options?.filterPredicate) return options.filterPredicate(component);
432
439
  if (options?.useIgnoreRaycastLayer !== false) {
433
440
  // ignore objects in the IgnoreRaycast=2 layer
@@ -453,11 +460,16 @@ export class RapierPhysics implements IPhysicsEngine {
453
460
  filterGroups?: number,
454
461
  /** Return false to ignore this collider */
455
462
  filterPredicate?: (c: ICollider) => boolean,
456
- /** When enabled the hit object's layer will be tested. If layer 2 is enabled the object will be ignored (Layer 2 == IgnoreRaycast)
463
+ /** When enabled the hit object's layer will be tested. If layer 2 is enabled the object will be ignored (Layer 2 == IgnoreRaycast)
457
464
  * If not set the raycast will ignore objects in the IgnoreRaycast layer (default: true)
458
- * @default undefined
465
+ * @default undefined
459
466
  */
460
- useIgnoreRaycastLayer?: boolean
467
+ useIgnoreRaycastLayer?: boolean,
468
+ /** When true, trigger/sensor colliders will be included in the raycast results.
469
+ * By default trigger colliders are skipped.
470
+ * @default false
471
+ */
472
+ includeTriggers?: boolean,
461
473
  })
462
474
  : null | { point: Vector3, normal: Vector3, collider: ICollider } {
463
475
 
@@ -478,6 +490,8 @@ export class RapierPhysics implements IPhysicsEngine {
478
490
 
479
491
  const hit = this.world?.castRayAndGetNormal(ray, maxDistance, solid, options?.queryFilterFlags, options?.filterGroups, undefined, undefined, (c) => {
480
492
  const component = c[$componentKey];
493
+ // Skip trigger/sensor colliders unless explicitly included
494
+ if (options?.includeTriggers !== true && component?.isTrigger) return false;
481
495
  if (options?.filterPredicate) return options.filterPredicate(component);
482
496
  if (options?.useIgnoreRaycastLayer !== false) {
483
497
  // ignore objects in the IgnoreRaycast=2 layer
@@ -690,12 +704,26 @@ export class RapierPhysics implements IPhysicsEngine {
690
704
  }
691
705
  }
692
706
 
693
- clearCaches() {
707
+ /** Tears down the physics world and frees all WASM resources.
708
+ * After calling this, the world will be re-created on next use. */
709
+ dispose() {
694
710
  this._meshCache.clear();
695
- if (this.eventQueue?.raw)
696
- this.eventQueue?.free();
697
- if (this.world?.bodies)
698
- this.world?.free();
711
+ this.eventQueue?.free();
712
+ this._world?.free();
713
+ // Reset initialization state so the world can be recreated
714
+ this._world = undefined;
715
+ this.eventQueue = undefined;
716
+ this.collisionHandler = undefined;
717
+ this._isInitialized = false;
718
+ this._hasCreatedWorld = false;
719
+ this._initializePromise = undefined;
720
+ this.objects.length = 0;
721
+ this.bodies.length = 0;
722
+ }
723
+
724
+ /** @deprecated Use {@link dispose} instead. */
725
+ clearCaches() {
726
+ this.dispose();
699
727
  }
700
728
 
701
729
  async addBoxCollider(collider: ICollider, size: Vector3) {
@@ -981,13 +1009,17 @@ export class RapierPhysics implements IPhysicsEngine {
981
1009
  }
982
1010
  }
983
1011
 
984
- // if we want to use explicit mass properties, we need to set the collider density to 0
985
- // otherwise rapier will compute the mass properties based on the collider shape and density
1012
+ // When using explicit mass (autoMass=false), set collider mass to near-zero
1013
+ // so Rapier doesn't contribute mass from the collider shape.
1014
+ // The actual mass is applied via setAdditionalMass on the rigidbody instead.
1015
+ // Note: setMass overrides any prior setDensity call (they are mutually exclusive in Rapier)
986
1016
  // https://rapier.rs/docs/user_guides/javascript/rigid_bodies#mass-properties
987
1017
  if (collider.attachedRigidbody?.autoMass === false) {
988
- desc.setDensity(.000001);
989
1018
  desc.setMass(.000001);
990
1019
  }
1020
+ else if (collider.density != null) {
1021
+ desc.setDensity(collider.density);
1022
+ }
991
1023
 
992
1024
  try {
993
1025
  const col = this.world.createCollider(desc, rigidBody);
@@ -1130,6 +1162,11 @@ export class RapierPhysics implements IPhysicsEngine {
1130
1162
  break;
1131
1163
  }
1132
1164
 
1165
+ // Update density if specified (setDensity auto-recomputes parent body mass)
1166
+ if (col.density != null) {
1167
+ collider.setDensity(col.density);
1168
+ }
1169
+
1133
1170
  if (sizeHasChanged) {
1134
1171
  const rb = col.attachedRigidbody;
1135
1172
  if (rb?.autoMass) {
@@ -1161,7 +1198,8 @@ export class RapierPhysics implements IPhysicsEngine {
1161
1198
  rigidbody.setAdditionalMass(0, false);
1162
1199
  for (let i = 0; i < rigidbody.numColliders(); i++) {
1163
1200
  const col = rigidbody.collider(i);
1164
- col.setDensity(1);
1201
+ const colliderComponent = col[$componentKey] as ICollider | null;
1202
+ col.setDensity(colliderComponent?.density ?? 1);
1165
1203
  }
1166
1204
  rigidbody.recomputeMassPropertiesFromColliders();
1167
1205
  }
@@ -1477,16 +1515,21 @@ export class RapierPhysics implements IPhysicsEngine {
1477
1515
 
1478
1516
  private static centerConnectionPos = { x: 0, y: 0, z: 0 };
1479
1517
  private static centerConnectionRot = { x: 0, y: 0, z: 0, w: 1 };
1518
+ private _jointTempMatrix = new Matrix4();
1480
1519
 
1481
1520
 
1482
-
1483
- addFixedJoint(body1: IRigidbody, body2: IRigidbody) {
1521
+ async addFixedJoint(body1: IRigidbody, body2: IRigidbody): Promise<ImpulseJoint | null> {
1522
+ if (!this._isInitialized) await this.initialize();
1484
1523
  if (!this.world) {
1485
1524
  console.error("Physics world not initialized");
1486
- return;
1525
+ return null;
1487
1526
  }
1488
1527
  const b1 = body1[$bodyKey] as RigidBody;
1489
1528
  const b2 = body2[$bodyKey] as RigidBody;
1529
+ if (!b1 || !b2) {
1530
+ console.error("Cannot create fixed joint: one or both physics bodies are not initialized");
1531
+ return null;
1532
+ }
1490
1533
 
1491
1534
  this.calculateJointRelativeMatrices(body1.gameObject, body2.gameObject, this._tempMatrix);
1492
1535
  this._tempMatrix.decompose(this._tempPosition, this._tempQuaternion, this._tempScale);
@@ -1498,41 +1541,67 @@ export class RapierPhysics implements IPhysicsEngine {
1498
1541
  const joint = this.world.createImpulseJoint(params, b1, b2, true);
1499
1542
  if (debugPhysics)
1500
1543
  console.log("ADD FIXED JOINT", joint)
1544
+ return joint;
1501
1545
  }
1502
1546
 
1503
1547
 
1504
1548
  /** 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. */
1505
- addHingeJoint(body1: IRigidbody, body2: IRigidbody, anchor: { x: number, y: number, z: number }, axis: { x: number, y: number, z: number }) {
1549
+ async addHingeJoint(body1: IRigidbody, body2: IRigidbody, anchor: { x: number, y: number, z: number }, axis: { x: number, y: number, z: number }): Promise<ImpulseJoint | null> {
1550
+ if (!this._isInitialized) await this.initialize();
1506
1551
  if (!this.world) {
1507
1552
  console.error("Physics world not initialized");
1508
- return;
1553
+ return null;
1509
1554
  }
1510
1555
  const b1 = body1[$bodyKey] as RigidBody;
1511
1556
  const b2 = body2[$bodyKey] as RigidBody;
1557
+ if (!b1 || !b2) {
1558
+ console.error("Cannot create hinge joint: one or both physics bodies are not initialized");
1559
+ return null;
1560
+ }
1512
1561
 
1513
1562
  this.calculateJointRelativeMatrices(body1.gameObject, body2.gameObject, this._tempMatrix);
1514
- this._tempMatrix.decompose(this._tempPosition, this._tempQuaternion, this._tempScale);
1563
+ // Transform anchor from body1's local space to body2's local space
1564
+ const anchor2 = this._tempPosition.set(anchor.x, anchor.y, anchor.z).applyMatrix4(this._tempMatrix);
1515
1565
 
1516
- const params = MODULES.RAPIER_PHYSICS.MODULE.JointData.revolute(anchor, this._tempPosition, axis);
1566
+ const params = MODULES.RAPIER_PHYSICS.MODULE.JointData.revolute(anchor, anchor2, axis);
1517
1567
  const joint = this.world.createImpulseJoint(params, b1, b2, true);
1518
1568
  if (debugPhysics)
1519
1569
  console.log("ADD HINGE JOINT", joint)
1570
+ return joint;
1520
1571
  }
1521
1572
 
1522
1573
 
1574
+ removeJoint(joint: ImpulseJoint) {
1575
+ if (!this.world) return;
1576
+ this.world.removeImpulseJoint(joint, true);
1577
+ }
1578
+
1579
+
1580
+ /** Compute the relative transform from body1's local space to body2's local space (W2⁻¹ * W1), ignoring scale. */
1523
1581
  private calculateJointRelativeMatrices(body1: IGameObject, body2: IGameObject, mat: Matrix4) {
1524
1582
  body1.updateWorldMatrix(true, false);
1525
1583
  body2.updateWorldMatrix(true, false);
1526
- const world1 = body1.matrixWorld;
1527
- const world2 = body2.matrixWorld;
1528
- // set scale to 1
1529
- world1.elements[0] = 1;
1530
- world1.elements[5] = 1;
1531
- world1.elements[10] = 1;
1532
- world2.elements[0] = 1;
1533
- world2.elements[5] = 1;
1534
- world2.elements[10] = 1;
1535
- mat.copy(world2).premultiply(world1.invert()).invert();
1584
+
1585
+ // Work on copies to avoid mutating the actual world matrices
1586
+ mat.copy(body1.matrixWorld);
1587
+ const w2 = this._jointTempMatrix.copy(body2.matrixWorld);
1588
+
1589
+ // Strip scale by normalizing each column of the upper 3x3
1590
+ this.normalizeMatrixColumns(mat);
1591
+ this.normalizeMatrixColumns(w2);
1592
+
1593
+ // mat = W2^-1 * W1 (body1's frame in body2's local space)
1594
+ mat.premultiply(w2.invert());
1595
+ }
1596
+
1597
+ private normalizeMatrixColumns(m: Matrix4) {
1598
+ const e = m.elements;
1599
+ let len = Math.sqrt(e[0] * e[0] + e[1] * e[1] + e[2] * e[2]);
1600
+ if (len > 0) { e[0] /= len; e[1] /= len; e[2] /= len; }
1601
+ len = Math.sqrt(e[4] * e[4] + e[5] * e[5] + e[6] * e[6]);
1602
+ if (len > 0) { e[4] /= len; e[5] /= len; e[6] /= len; }
1603
+ len = Math.sqrt(e[8] * e[8] + e[9] * e[9] + e[10] * e[10]);
1604
+ if (len > 0) { e[8] /= len; e[9] /= len; e[10] /= len; }
1536
1605
  }
1537
1606
  }
1538
1607
 
@@ -1,8 +1,8 @@
1
1
  import { createLoaders } from "@needle-tools/gltf-progressive";
2
2
  import { CubeUVReflectionMapping, EquirectangularRefractionMapping, SRGBColorSpace, Texture, TextureLoader, WebGLRenderer } from "three";
3
- import { EXRLoader } from "three/examples/jsm/loaders/EXRLoader";
4
- import { KTX2Loader } from "three/examples/jsm/loaders/KTX2Loader";
5
- import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
3
+ import { EXRLoader } from "three/examples/jsm/loaders/EXRLoader.js";
4
+ import { KTX2Loader } from "three/examples/jsm/loaders/KTX2Loader.js";
5
+ import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader.js";
6
6
 
7
7
  const running: Map<string, Promise<Texture | null>> = new Map();
8
8
 
@@ -37,9 +37,59 @@ async function internalLoadPMREM(url: URL, renderer: WebGLRenderer) {
37
37
  const pathname = url.pathname;
38
38
  const isPMREM_URL: boolean = url.toString().toLowerCase().includes("pmrem") || url.searchParams.get("pmrem") != null;
39
39
 
40
- const isEXR = pathname.endsWith(".exr");
41
- const isHdr = pathname.endsWith(".hdr");
42
- const isKtx2 = pathname.endsWith(".ktx2");
40
+ let isEXR = pathname.endsWith(".exr");
41
+ let isHdr = pathname.endsWith(".hdr");
42
+ let isKtx2 = pathname.endsWith(".ktx2");
43
+
44
+ // For URLs that don't carry a recognizable extension (e.g. `blob:` URLs
45
+ // from dropped local files, or signed CDN URLs that elide the filename),
46
+ // sniff Content-Type and a few magic bytes to pick the right loader.
47
+ // EXRLoader / RGBELoader / KTX2Loader vs TextureLoader is not interchangeable —
48
+ // routing EXR binary data through TextureLoader fails outright.
49
+ if (!isEXR && !isHdr && !isKtx2) {
50
+ try {
51
+ const probe = await fetch(url.toString(), {
52
+ method: "GET",
53
+ headers: { range: "bytes=0-15" },
54
+ });
55
+ const contentType = probe.headers.get("content-type")?.toLowerCase() ?? "";
56
+
57
+ // Content-Type wins when it's specific — skip reading the body.
58
+ if (contentType === "image/x-exr" || contentType === "image/aces") {
59
+ isEXR = true;
60
+ }
61
+ else if (contentType === "image/vnd.radiance" || contentType === "image/x-hdr") {
62
+ isHdr = true;
63
+ }
64
+ else if (contentType === "image/ktx2") {
65
+ isKtx2 = true;
66
+ }
67
+ // Otherwise fall back to magic-byte sniffing.
68
+ else {
69
+ const bytes = new Uint8Array(await probe.arrayBuffer());
70
+ if (bytes.length >= 4 && bytes[0] === 0x76 && bytes[1] === 0x2f && bytes[2] === 0x31 && bytes[3] === 0x01) {
71
+ // EXR magic: 0x76 0x2f 0x31 0x01
72
+ isEXR = true;
73
+ }
74
+ else if (bytes.length >= 12
75
+ && bytes[0] === 0xAB && bytes[1] === 0x4B && bytes[2] === 0x54 && bytes[3] === 0x58
76
+ && bytes[4] === 0x20 && bytes[5] === 0x32 && bytes[6] === 0x30 && bytes[7] === 0xBB) {
77
+ // KTX2 magic: «KTX 20»\r\n\x1A\n
78
+ isKtx2 = true;
79
+ }
80
+ else if (bytes.length >= 10
81
+ && bytes[0] === 0x23 && bytes[1] === 0x3F // "#?"
82
+ && bytes[2] === 0x52 && bytes[3] === 0x41 && bytes[4] === 0x44 && bytes[5] === 0x49 // "RADI"
83
+ && bytes[6] === 0x41 && bytes[7] === 0x4E && bytes[8] === 0x43 && bytes[9] === 0x45) { // "ANCE"
84
+ // Radiance HDR header: "#?RADIANCE"
85
+ isHdr = true;
86
+ }
87
+ }
88
+ }
89
+ catch (err) {
90
+ console.warn("loadPMREM: failed to probe URL for format detection", url, err);
91
+ }
92
+ }
43
93
 
44
94
  let loader: RGBELoader | EXRLoader | TextureLoader | KTX2Loader;
45
95
 
@@ -1,20 +1,19 @@
1
- import type { SceneData } from "needle:bindings";
2
- import type { IContext } from "./engine_types.js";
3
- import { getComponent } from "./engine_components.js";
4
- import { TypeStore } from "./engine_typestore.js";
1
+ import type { SceneData } from "needle-bindings";
2
+ export type { SceneData };
5
3
  import { isDevEnvironment } from "./debug/index.js";
4
+ import { getComponent } from "./engine_components.js";
6
5
  import { ContextRegistry } from "./engine_context_registry.js";
6
+ import type { IContext } from "./engine_types.js";
7
+ import { TypeStore } from "./engine_typestore.js";
7
8
 
8
9
  /**
9
- * Global proxy for the primary Needle Engine context.
10
- * Resolves lazily on property access via `ContextRegistry.Current` —
11
- * safe to import at module level, including in SSR environments
12
- * (returns a silent error proxy when no context is active).
10
+ * Quick access to the current Needle Engine context from anywhere — no need to pass `ctx` around.
11
+ * Use it in React/Svelte/Vue components, button handlers, or plain JavaScript.
13
12
  *
14
- * Use this outside of Needle component lifecycle (e.g. in Svelte/React/Vue
15
- * components, button handlers, or vanilla JS) instead of threading `ctx` around.
13
+ * Safe to import at module level, including in SSR environments.
14
+ * For pages with multiple `<needle-engine>` elements, use `ctx` directly instead.
16
15
  *
17
- * For multiple `<needle-engine>` elements on the same page, use `ctx` directly.
16
+ * @experimental This API may change in future releases.
18
17
  *
19
18
  * @example
20
19
  * import { needle } from "@needle-tools/engine";
@@ -28,7 +27,7 @@ export const needle: IContext = new Proxy({} as IContext, {
28
27
  const ctx = ContextRegistry.Current;
29
28
  if (!ctx) {
30
29
  const fn = isDevEnvironment() ? console.error : console.warn;
31
- fn(`[needle] needle.${prop} accessed before scene started`);
30
+ fn(`[needle] needle.${prop} was accessed before the scene started. Use "needle" inside event handlers or callbacks, not at module top-level. For setup code use: onStart(ctx => { ... })`);
32
31
  return makeErrorProxy(`needle not ready — scene hasn't started yet`);
33
32
  }
34
33
  const val = (ctx as any)[prop];
@@ -38,7 +37,7 @@ export const needle: IContext = new Proxy({} as IContext, {
38
37
  const ctx = ContextRegistry.Current;
39
38
  if (!ctx) {
40
39
  const fn = isDevEnvironment() ? console.error : console.warn;
41
- fn(`[needle] needle.${prop} set before scene started`);
40
+ fn(`[needle] needle.${prop} was set before the scene started. Use "needle" inside event handlers or callbacks, not at module top-level. For setup code use: onStart(ctx => { ... })`);
42
41
  return true;
43
42
  }
44
43
  (ctx as any)[prop] = value;
@@ -70,36 +69,63 @@ function makeErrorProxy(message: string): object {
70
69
  return new Proxy({}, handler);
71
70
  }
72
71
 
72
+ /**
73
+ * Returns a proxy for a scene node that exposes `$object`, `$components`,
74
+ * and child nodes as nested properties.
75
+ */
76
+ function makeNodeProxy(ctx: IContext, node: import("three").Object3D): object {
77
+ return new Proxy({}, {
78
+ get(_t, prop: string) {
79
+ if (prop === "$object") return node;
80
+ if (prop === "$components") {
81
+ return new Proxy({}, {
82
+ get(_t2, compName: string) {
83
+ if (compName === "then") return undefined;
84
+ const ctor = TypeStore.get(compName);
85
+ if (!ctor) return makeErrorProxy(`Component type "${compName}" not registered (node "${node.name}")`);
86
+ const comp = getComponent(node, ctor);
87
+ if (!comp) return makeErrorProxy(`Component "${compName}" not found on node "${node.name}"`);
88
+ return comp;
89
+ }
90
+ });
91
+ }
92
+ if (prop === "then") return undefined; // not a Promise
93
+ // Child node lookup by name
94
+ const child = node.children.find(c => c.name === prop) ?? null;
95
+ if (!child) {
96
+ const fn = isDevEnvironment() ? console.error : console.warn;
97
+ fn(`[SceneData] "${prop}" is not a child of "${node.name}". Use .$object to get the Three.js object or .$components.Name to access a component.`);
98
+ return makeErrorProxy(`"${prop}" not found on node "${node.name}"`);
99
+ }
100
+ return makeNodeProxy(ctx, child);
101
+ }
102
+ });
103
+ }
104
+
73
105
  /**
74
106
  * Returns a lazily-resolved proxy typed as {@link SceneData}.
75
107
  * The proxy is cached per context — each context gets exactly one instance.
76
108
  *
77
- * Accessing a property traverses the scene graph on demand:
78
- * - First level → find Object3D by node name
79
- * - Second level getComponent by component name (via TypeStore)
80
- * - Third level read/write a field on the real component instance
81
- *
82
- * If a node or component is not found, property accesses log a warning
83
- * instead of throwing, so chained access never crashes.
109
+ * Shape mirrors the generated `needle-bindings.gen.d.ts`:
110
+ * ctx.sceneData.MyGlb.Camera.$components.OrbitControls.autoRotate = true;
111
+ * ctx.sceneData.MyGlb.Camera.$object //THREE.Camera
112
+ * ctx.sceneData.MyGlb.UI.Button.$components.Button //Needle Button component
84
113
  *
85
- * @example
86
- * ctx.sceneData.Camera.OrbitControls.autoRotate = true;
114
+ * GLB name is ignored at runtime (scene is already loaded).
115
+ * Node lookup starts at the scene root.
87
116
  */
88
117
  export function getSceneData(ctx: IContext): SceneData {
89
118
  let proxy = cache.get(ctx);
90
119
  if (!proxy) {
91
120
  proxy = new Proxy({} as SceneData, {
92
- get(_target, nodeName: string) {
121
+ get(_target, _glbName: string) {
122
+ // GLB name level — ignored at runtime, return node-name proxy
93
123
  return new Proxy({}, {
94
- get(_target, compName: string) {
124
+ get(_target, nodeName: string) {
125
+ if (nodeName === "then") return undefined;
95
126
  const node = ctx.scene.getObjectByName(nodeName) ?? null;
96
127
  if (!node) return makeErrorProxy(`Node "${nodeName}" not found in scene`);
97
- if (compName === "$node") return node;
98
- const ctor = TypeStore.get(compName);
99
- if (!ctor) return makeErrorProxy(`Component type "${compName}" not registered (node "${nodeName}")`);
100
- const comp = getComponent(node, ctor);
101
- if (!comp) return makeErrorProxy(`Component "${compName}" not found on node "${nodeName}"`);
102
- return comp;
128
+ return makeNodeProxy(ctx, node);
103
129
  }
104
130
  });
105
131
  }
@@ -4,6 +4,7 @@ import { isDevEnvironment, showBalloonMessage, showBalloonWarning } from "../eng
4
4
  import { Behaviour, Component, GameObject } from "../engine-components/Component.js";
5
5
  import { CallInfo, EventList } from "../engine-components/EventList.js";
6
6
  import { AssetReference } from "./engine_addressables.js";
7
+ import { AudioClip } from "./engine_audio.js";
7
8
  import { debugExtension } from "./engine_default_parameters.js";
8
9
  import { SerializationContext, TypeSerializer } from "./engine_serialization_core.js";
9
10
  import { RenderTexture } from "./engine_texture.js";
@@ -11,25 +12,7 @@ import { IComponent } from "./engine_types.js";
11
12
  import { resolveUrl } from "./engine_utils.js";
12
13
  import { RGBAColor } from "./js-extensions/index.js";
13
14
 
14
- // export class SourcePath {
15
- // src?:string
16
- // };
17
-
18
- // class SourcePathSerializer extends TypeSerializer{
19
- // constructor(){
20
- // super(SourcePath);
21
- // }
22
- // onDeserialize(data: any, _context: SerializationContext) {
23
- // if(data.src && typeof data.src === "string"){
24
- // return data.src;
25
- // }
26
- // }
27
- // onSerialize(_data: any, _context: SerializationContext) {
28
-
29
- // }
30
- // }
31
- // new SourcePathSerializer();
32
-
15
+ // #region Color
33
16
  class ColorSerializer extends TypeSerializer {
34
17
  constructor() {
35
18
  super([Color, RGBAColor], "ColorSerializer")
@@ -52,7 +35,8 @@ class ColorSerializer extends TypeSerializer {
52
35
  return { r: data.r, g: data.g, b: data.b }
53
36
  }
54
37
  }
55
- export const colorSerializer = new ColorSerializer();
38
+
39
+ // #region Euler
56
40
 
57
41
  class EulerSerializer extends TypeSerializer {
58
42
  constructor() {
@@ -72,12 +56,13 @@ class EulerSerializer extends TypeSerializer {
72
56
  return { x: data.x, y: data.y, z: data.z, order: data.order };
73
57
  }
74
58
  }
75
- export const euler = new EulerSerializer();
76
59
 
77
60
  declare type ObjectData = {
78
61
  node?: number;
79
62
  guid?: string;
80
63
  }
64
+
65
+ // #region ObjectSerializer
81
66
  class ObjectSerializer extends TypeSerializer {
82
67
  constructor() {
83
68
  super(Object3D, "ObjectSerializer");
@@ -107,16 +92,6 @@ class ObjectSerializer extends TypeSerializer {
107
92
  console.warn(`Wrong usage of @serializable detected in your script \"${scriptname}\"\n\nIt looks like you used @serializable(Object3D) or @serializable(GameObject) for a prefab or scene reference which is exported to a separate glTF file.\n\nTo fix this please change your code to:\n\n@serializable(AssetReference)\n${context.path}! : AssetReference;\n\0`);
108
93
  }
109
94
  // ACTUALLY: this is already handled by the extension_utils where we resolve json pointers recursively
110
- // if(data.startsWith("/nodes/")){
111
- // const node = parseInt(data.substring("/nodes/".length));
112
- // if (context.nodeToObject) {
113
- // const res = context.nodeToObject[node];
114
- // if (debugExtension)
115
- // console.log("Deserialized object reference?", data, res, context?.nodeToObject);
116
- // if (!res) console.warn("Did not find node: " + data, context.nodeToObject, context.object);
117
- // return res;
118
- // }
119
- // }
120
95
  return undefined;
121
96
  }
122
97
 
@@ -149,7 +124,7 @@ class ObjectSerializer extends TypeSerializer {
149
124
  }
150
125
  if (!res) {
151
126
  if (isDevEnvironment() || debugExtension)
152
- console.warn("Could not resolve object reference", context.path, data, context.target, context.context.scene);
127
+ console.warn(`Could not resolve object reference \"${context.path}\" (guid: ${data.guid}). The referenced object may have been deleted — check if the reference is still valid in your scene.`);
153
128
  data["could_not_resolve"] = true;
154
129
  }
155
130
  else {
@@ -166,9 +141,8 @@ class ObjectSerializer extends TypeSerializer {
166
141
  return undefined;
167
142
  }
168
143
  }
169
- export const objectSerializer = new ObjectSerializer();
170
-
171
144
 
145
+ // #region ComponentSerializer
172
146
  class ComponentSerializer extends TypeSerializer {
173
147
 
174
148
  constructor() {
@@ -241,7 +215,6 @@ class ComponentSerializer extends TypeSerializer {
241
215
  }
242
216
  }
243
217
  }
244
- export const componentSerializer = new ComponentSerializer();
245
218
 
246
219
 
247
220
  declare class EventListData {
@@ -258,6 +231,7 @@ declare type EventListCall = {
258
231
 
259
232
  const $eventListDebugInfo = Symbol("eventListDebugInfo");
260
233
 
234
+ // #region EventListSerializer
261
235
  class EventListSerializer extends TypeSerializer {
262
236
  constructor() {
263
237
  super([EventList]);
@@ -360,11 +334,6 @@ class EventListSerializer extends TypeSerializer {
360
334
  if (debugExtension)
361
335
  console.log(evt);
362
336
 
363
- const eventListOwner = context.target;
364
- if (eventListOwner !== undefined && context.path !== undefined) {
365
- evt.setEventTarget(context.path, eventListOwner);
366
- }
367
-
368
337
  return evt;
369
338
  }
370
339
  return undefined;
@@ -396,22 +365,14 @@ class EventListSerializer extends TypeSerializer {
396
365
  // };
397
366
  // }
398
367
  }
399
- export const eventListSerializer = new EventListSerializer();
400
368
 
401
369
 
402
370
  /** Map<Clone, Original> texture. This is used for compressed textures (or when the GLTFLoader is cloning RenderTextures)
403
371
  * It's a weak map so we don't have to worry about memory leaks
404
372
  */
405
373
  const cloneOriginalMap = new WeakMap<Texture, Texture>();
406
- const textureClone = Texture.prototype.clone;
407
- Texture.prototype.clone = function () {
408
- const clone = textureClone.call(this);
409
- if (!cloneOriginalMap.has(clone)) {
410
- cloneOriginalMap.set(clone, this);
411
- }
412
- return clone;
413
- }
414
374
 
375
+ // #region RenderTextureSerializer
415
376
  export class RenderTextureSerializer extends TypeSerializer {
416
377
  constructor() {
417
378
  super([RenderTexture, WebGLRenderTarget]);
@@ -452,9 +413,8 @@ export class RenderTextureSerializer extends TypeSerializer {
452
413
  return undefined;
453
414
  }
454
415
  }
455
- new RenderTextureSerializer();
456
-
457
416
 
417
+ // #region UriSerializer
458
418
  export class UriSerializer extends TypeSerializer {
459
419
  constructor() {
460
420
  super([URL]);
@@ -471,4 +431,56 @@ export class UriSerializer extends TypeSerializer {
471
431
  return undefined;
472
432
  }
473
433
  }
474
- new UriSerializer();
434
+
435
+ // #region AudioClipSerializer
436
+ class AudioClipSerializer extends TypeSerializer {
437
+ constructor() {
438
+ super([AudioClip]);
439
+ }
440
+
441
+ onSerialize(_data: AudioClip, _context: SerializationContext) {
442
+ return null;
443
+ }
444
+
445
+ onDeserialize(data: string, context: SerializationContext) {
446
+ if (typeof data === "string" && data.length > 0) {
447
+ const url = resolveUrl(context.gltfId, data);
448
+ if (url) return new AudioClip(url);
449
+ }
450
+ return undefined;
451
+ }
452
+ }
453
+
454
+
455
+ // #region Init serializer
456
+ // Module-level references used by EventListSerializer internally
457
+ export let colorSerializer: ColorSerializer;
458
+ export let objectSerializer: ObjectSerializer;
459
+ export let componentSerializer: ComponentSerializer;
460
+ export let eventListSerializer: EventListSerializer;
461
+
462
+ /** Register all builtin serializers and prototype patches.
463
+ * Must be called from {@link initEngine} so the registrations survive tree-shaking
464
+ * when the package declares `sideEffects: false`.
465
+ */
466
+ export function initBuiltinSerializers() {
467
+ // Prototype patches
468
+ const textureClone = Texture.prototype.clone;
469
+ Texture.prototype.clone = function () {
470
+ const clone = textureClone.call(this);
471
+ if (!cloneOriginalMap.has(clone)) {
472
+ cloneOriginalMap.set(clone, this);
473
+ }
474
+ return clone;
475
+ }
476
+
477
+ // Register all serializers
478
+ colorSerializer = new ColorSerializer();
479
+ new EulerSerializer();
480
+ objectSerializer = new ObjectSerializer();
481
+ componentSerializer = new ComponentSerializer();
482
+ eventListSerializer = new EventListSerializer();
483
+ new RenderTextureSerializer();
484
+ new UriSerializer();
485
+ new AudioClipSerializer();
486
+ }