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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/SKILL.md +4 -1
  3. package/components.needle.json +1 -1
  4. package/dist/{needle-engine.bundle-BFSj2Fz8.js → needle-engine.bundle-BNqUjnSQ.js} +19180 -18386
  5. package/dist/needle-engine.bundle-Bt8ULD7E.umd.cjs +1733 -0
  6. package/dist/needle-engine.bundle-DF6ovbwD.min.js +1733 -0
  7. package/dist/needle-engine.d.ts +1487 -356
  8. package/dist/needle-engine.js +544 -542
  9. package/dist/needle-engine.min.js +1 -1
  10. package/dist/needle-engine.umd.cjs +1 -1
  11. package/dist/three.js +1 -0
  12. package/dist/three.min.js +21 -21
  13. package/dist/three.umd.cjs +16 -16
  14. package/lib/engine/api.d.ts +8 -1
  15. package/lib/engine/api.js +7 -1
  16. package/lib/engine/api.js.map +1 -1
  17. package/lib/engine/codegen/register_types.js +10 -18
  18. package/lib/engine/codegen/register_types.js.map +1 -1
  19. package/lib/engine/engine_audio.d.ts +68 -0
  20. package/lib/engine/engine_audio.js +172 -0
  21. package/lib/engine/engine_audio.js.map +1 -1
  22. package/lib/engine/engine_camera.fit.js +16 -4
  23. package/lib/engine/engine_camera.fit.js.map +1 -1
  24. package/lib/engine/engine_components.js +1 -1
  25. package/lib/engine/engine_components.js.map +1 -1
  26. package/lib/engine/engine_context.d.ts +21 -8
  27. package/lib/engine/engine_context.js +32 -16
  28. package/lib/engine/engine_context.js.map +1 -1
  29. package/lib/engine/engine_context_eventbus.d.ts +47 -0
  30. package/lib/engine/engine_context_eventbus.js +47 -0
  31. package/lib/engine/engine_context_eventbus.js.map +1 -0
  32. package/lib/engine/engine_disposable.d.ts +172 -0
  33. package/lib/engine/engine_disposable.js +136 -0
  34. package/lib/engine/engine_disposable.js.map +1 -0
  35. package/lib/engine/engine_gameobject.d.ts +1 -10
  36. package/lib/engine/engine_gameobject.js +22 -120
  37. package/lib/engine/engine_gameobject.js.map +1 -1
  38. package/lib/engine/engine_gltf_builtin_components.js +7 -69
  39. package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
  40. package/lib/engine/engine_init.js +7 -7
  41. package/lib/engine/engine_init.js.map +1 -1
  42. package/lib/engine/engine_input.d.ts +24 -5
  43. package/lib/engine/engine_input.js +3 -2
  44. package/lib/engine/engine_input.js.map +1 -1
  45. package/lib/engine/engine_instantiate_resolve.d.ts +42 -0
  46. package/lib/engine/engine_instantiate_resolve.js +372 -0
  47. package/lib/engine/engine_instantiate_resolve.js.map +1 -0
  48. package/lib/engine/engine_license.d.ts +7 -7
  49. package/lib/engine/engine_license.js +183 -57
  50. package/lib/engine/engine_license.js.map +1 -1
  51. package/lib/engine/engine_mainloop_utils.js +7 -4
  52. package/lib/engine/engine_mainloop_utils.js.map +1 -1
  53. package/lib/engine/engine_networking.d.ts +51 -37
  54. package/lib/engine/engine_networking.js +132 -82
  55. package/lib/engine/engine_networking.js.map +1 -1
  56. package/lib/engine/engine_networking.transport.websocket.d.ts +15 -0
  57. package/lib/engine/engine_networking.transport.websocket.js +38 -0
  58. package/lib/engine/engine_networking.transport.websocket.js.map +1 -0
  59. package/lib/engine/engine_networking_blob.js +4 -4
  60. package/lib/engine/engine_networking_blob.js.map +1 -1
  61. package/lib/engine/engine_networking_instantiate.js +2 -2
  62. package/lib/engine/engine_networking_instantiate.js.map +1 -1
  63. package/lib/engine/engine_networking_types.d.ts +39 -1
  64. package/lib/engine/engine_networking_types.js +7 -0
  65. package/lib/engine/engine_networking_types.js.map +1 -1
  66. package/lib/engine/engine_physics_rapier.d.ts +21 -3
  67. package/lib/engine/engine_physics_rapier.js +94 -25
  68. package/lib/engine/engine_physics_rapier.js.map +1 -1
  69. package/lib/engine/engine_scenedata.js +2 -2
  70. package/lib/engine/engine_scenedata.js.map +1 -1
  71. package/lib/engine/engine_serialization_builtin_serializer.js +28 -5
  72. package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
  73. package/lib/engine/engine_serialization_core.d.ts +1 -0
  74. package/lib/engine/engine_serialization_core.js +7 -0
  75. package/lib/engine/engine_serialization_core.js.map +1 -1
  76. package/lib/engine/engine_types.d.ts +29 -11
  77. package/lib/engine/engine_types.js +1 -1
  78. package/lib/engine/engine_types.js.map +1 -1
  79. package/lib/engine/engine_util_decorator.js +7 -2
  80. package/lib/engine/engine_util_decorator.js.map +1 -1
  81. package/lib/engine/engine_utils.d.ts +1 -1
  82. package/lib/engine/engine_utils.js +19 -5
  83. package/lib/engine/engine_utils.js.map +1 -1
  84. package/lib/engine/engine_utils_qrcode.js +2 -2
  85. package/lib/engine/engine_utils_qrcode.js.map +1 -1
  86. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
  87. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js.map +1 -1
  88. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +2 -2
  89. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
  90. package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +1 -1
  91. package/lib/engine/webcomponents/needle menu/needle-menu.js +6 -6
  92. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  93. package/lib/engine/webcomponents/needle-engine.d.ts +10 -4
  94. package/lib/engine/webcomponents/needle-engine.js +3 -3
  95. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  96. package/lib/engine/webcomponents/needle-engine.loading.js +2 -2
  97. package/lib/engine/webcomponents/needle-engine.loading.js.map +1 -1
  98. package/lib/engine/xr/NeedleXRSession.d.ts +3 -2
  99. package/lib/engine/xr/NeedleXRSession.js +50 -14
  100. package/lib/engine/xr/NeedleXRSession.js.map +1 -1
  101. package/lib/engine/xr/TempXRContext.js +2 -2
  102. package/lib/engine/xr/TempXRContext.js.map +1 -1
  103. package/lib/engine/xr/events.d.ts +1 -1
  104. package/lib/engine/xr/events.js.map +1 -1
  105. package/lib/engine-components/Animation.js +17 -16
  106. package/lib/engine-components/Animation.js.map +1 -1
  107. package/lib/engine-components/AnimationBuilder.d.ts +158 -0
  108. package/lib/engine-components/AnimationBuilder.js +305 -0
  109. package/lib/engine-components/AnimationBuilder.js.map +1 -0
  110. package/lib/engine-components/Animator.d.ts +6 -0
  111. package/lib/engine-components/Animator.js +23 -13
  112. package/lib/engine-components/Animator.js.map +1 -1
  113. package/lib/engine-components/AnimatorController.builder.d.ts +191 -0
  114. package/lib/engine-components/AnimatorController.builder.js +263 -0
  115. package/lib/engine-components/AnimatorController.builder.js.map +1 -0
  116. package/lib/engine-components/AnimatorController.d.ts +2 -119
  117. package/lib/engine-components/AnimatorController.js +33 -232
  118. package/lib/engine-components/AnimatorController.js.map +1 -1
  119. package/lib/engine-components/AudioSource.d.ts +19 -3
  120. package/lib/engine-components/AudioSource.js +121 -68
  121. package/lib/engine-components/AudioSource.js.map +1 -1
  122. package/lib/engine-components/Collider.d.ts +18 -9
  123. package/lib/engine-components/Collider.js +61 -14
  124. package/lib/engine-components/Collider.js.map +1 -1
  125. package/lib/engine-components/Component.d.ts +72 -9
  126. package/lib/engine-components/Component.js +114 -10
  127. package/lib/engine-components/Component.js.map +1 -1
  128. package/lib/engine-components/ContactShadows.d.ts +1 -0
  129. package/lib/engine-components/ContactShadows.js +14 -1
  130. package/lib/engine-components/ContactShadows.js.map +1 -1
  131. package/lib/engine-components/DragControls.d.ts +7 -0
  132. package/lib/engine-components/DragControls.js +19 -7
  133. package/lib/engine-components/DragControls.js.map +1 -1
  134. package/lib/engine-components/DropListener.js +3 -0
  135. package/lib/engine-components/DropListener.js.map +1 -1
  136. package/lib/engine-components/EventList.d.ts +31 -9
  137. package/lib/engine-components/EventList.js +37 -76
  138. package/lib/engine-components/EventList.js.map +1 -1
  139. package/lib/engine-components/Joints.d.ts +4 -2
  140. package/lib/engine-components/Joints.js +19 -3
  141. package/lib/engine-components/Joints.js.map +1 -1
  142. package/lib/engine-components/Light.js +9 -1
  143. package/lib/engine-components/Light.js.map +1 -1
  144. package/lib/engine-components/Networking.d.ts +1 -1
  145. package/lib/engine-components/Networking.js +1 -1
  146. package/lib/engine-components/OrbitControls.d.ts +0 -2
  147. package/lib/engine-components/OrbitControls.js +30 -12
  148. package/lib/engine-components/OrbitControls.js.map +1 -1
  149. package/lib/engine-components/RigidBody.d.ts +12 -4
  150. package/lib/engine-components/RigidBody.js +18 -4
  151. package/lib/engine-components/RigidBody.js.map +1 -1
  152. package/lib/engine-components/SceneSwitcher.js +3 -0
  153. package/lib/engine-components/SceneSwitcher.js.map +1 -1
  154. package/lib/engine-components/SeeThrough.js +2 -2
  155. package/lib/engine-components/SeeThrough.js.map +1 -1
  156. package/lib/engine-components/api.d.ts +2 -1
  157. package/lib/engine-components/api.js +2 -1
  158. package/lib/engine-components/api.js.map +1 -1
  159. package/lib/engine-components/codegen/components.d.ts +7 -13
  160. package/lib/engine-components/codegen/components.js +7 -13
  161. package/lib/engine-components/codegen/components.js.map +1 -1
  162. package/lib/engine-components/export/usdz/USDZExporter.js +4 -4
  163. package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
  164. package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
  165. package/lib/engine-components/timeline/PlayableDirector.d.ts +21 -11
  166. package/lib/engine-components/timeline/PlayableDirector.js +75 -67
  167. package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
  168. package/lib/engine-components/timeline/SignalAsset.d.ts +3 -1
  169. package/lib/engine-components/timeline/SignalAsset.js +1 -0
  170. package/lib/engine-components/timeline/SignalAsset.js.map +1 -1
  171. package/lib/engine-components/timeline/TimelineBuilder.d.ts +413 -0
  172. package/lib/engine-components/timeline/TimelineBuilder.js +506 -0
  173. package/lib/engine-components/timeline/TimelineBuilder.js.map +1 -0
  174. package/lib/engine-components/timeline/TimelineModels.d.ts +2 -1
  175. package/lib/engine-components/timeline/TimelineModels.js +3 -0
  176. package/lib/engine-components/timeline/TimelineModels.js.map +1 -1
  177. package/lib/engine-components/timeline/TimelineTracks.d.ts +37 -6
  178. package/lib/engine-components/timeline/TimelineTracks.js +92 -26
  179. package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
  180. package/lib/engine-components/timeline/index.d.ts +2 -1
  181. package/lib/engine-components/timeline/index.js +2 -0
  182. package/lib/engine-components/timeline/index.js.map +1 -1
  183. package/lib/engine-components/ui/Canvas.d.ts +1 -1
  184. package/lib/engine-components/ui/Canvas.js +2 -8
  185. package/lib/engine-components/ui/Canvas.js.map +1 -1
  186. package/lib/engine-components/ui/Text.d.ts +1 -0
  187. package/lib/engine-components/ui/Text.js +10 -7
  188. package/lib/engine-components/ui/Text.js.map +1 -1
  189. package/lib/engine-components/web/CursorFollow.d.ts +0 -1
  190. package/lib/engine-components/web/CursorFollow.js +21 -13
  191. package/lib/engine-components/web/CursorFollow.js.map +1 -1
  192. package/lib/engine-components/webxr/WebXRImageTracking.js +4 -0
  193. package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
  194. package/package.json +2 -83
  195. package/plugins/common/cloud.js +6 -1
  196. package/plugins/common/license.js +31 -10
  197. package/plugins/common/worker.js +9 -4
  198. package/plugins/vite/asap.js +17 -8
  199. package/plugins/vite/dependencies.js +29 -10
  200. package/plugins/vite/dependency-watcher.js +2 -2
  201. package/plugins/vite/editor-connection.js +3 -3
  202. package/plugins/vite/license.js +46 -7
  203. package/plugins/vite/local-files-core.js +3 -3
  204. package/plugins/vite/local-files-utils.d.ts +3 -1
  205. package/plugins/vite/local-files-utils.js +29 -5
  206. package/plugins/vite/reload.js +1 -1
  207. package/plugins/vite/server.js +2 -1
  208. package/src/engine/api.ts +11 -1
  209. package/src/engine/codegen/register_types.ts +10 -18
  210. package/src/engine/engine_audio.ts +184 -0
  211. package/src/engine/engine_camera.fit.ts +15 -4
  212. package/src/engine/engine_components.ts +1 -1
  213. package/src/engine/engine_context.ts +34 -18
  214. package/src/engine/engine_context_eventbus.ts +73 -0
  215. package/src/engine/engine_disposable.ts +214 -0
  216. package/src/engine/engine_gameobject.ts +54 -159
  217. package/src/engine/engine_gltf_builtin_components.ts +7 -76
  218. package/src/engine/engine_init.ts +7 -7
  219. package/src/engine/engine_input.ts +28 -7
  220. package/src/engine/engine_instantiate_resolve.ts +407 -0
  221. package/src/engine/engine_license.ts +197 -55
  222. package/src/engine/engine_mainloop_utils.ts +7 -4
  223. package/src/engine/engine_networking.transport.websocket.ts +45 -0
  224. package/src/engine/engine_networking.ts +161 -137
  225. package/src/engine/engine_networking_blob.ts +4 -4
  226. package/src/engine/engine_networking_instantiate.ts +2 -2
  227. package/src/engine/engine_networking_types.ts +41 -1
  228. package/src/engine/engine_physics_rapier.ts +102 -33
  229. package/src/engine/engine_scenedata.ts +3 -3
  230. package/src/engine/engine_serialization_builtin_serializer.ts +32 -9
  231. package/src/engine/engine_serialization_core.ts +9 -0
  232. package/src/engine/engine_types.ts +46 -27
  233. package/src/engine/engine_util_decorator.ts +7 -2
  234. package/src/engine/engine_utils.ts +16 -5
  235. package/src/engine/engine_utils_qrcode.ts +2 -2
  236. package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
  237. package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +2 -2
  238. package/src/engine/webcomponents/needle menu/needle-menu.ts +6 -6
  239. package/src/engine/webcomponents/needle-engine.loading.ts +6 -6
  240. package/src/engine/webcomponents/needle-engine.ts +12 -6
  241. package/src/engine/xr/NeedleXRSession.ts +48 -13
  242. package/src/engine/xr/TempXRContext.ts +2 -2
  243. package/src/engine/xr/events.ts +1 -1
  244. package/src/engine-components/Animation.ts +19 -16
  245. package/src/engine-components/AnimationBuilder.ts +472 -0
  246. package/src/engine-components/Animator.ts +24 -12
  247. package/src/engine-components/AnimatorController.builder.ts +387 -0
  248. package/src/engine-components/AnimatorController.ts +20 -291
  249. package/src/engine-components/AudioSource.ts +130 -79
  250. package/src/engine-components/Collider.ts +66 -18
  251. package/src/engine-components/Component.ts +118 -20
  252. package/src/engine-components/ContactShadows.ts +15 -1
  253. package/src/engine-components/DragControls.ts +18 -11
  254. package/src/engine-components/DropListener.ts +3 -0
  255. package/src/engine-components/EventList.ts +45 -83
  256. package/src/engine-components/Joints.ts +20 -4
  257. package/src/engine-components/Light.ts +10 -2
  258. package/src/engine-components/Networking.ts +1 -1
  259. package/src/engine-components/OrbitControls.ts +34 -14
  260. package/src/engine-components/RigidBody.ts +18 -4
  261. package/src/engine-components/SceneSwitcher.ts +3 -0
  262. package/src/engine-components/SeeThrough.ts +2 -2
  263. package/src/engine-components/api.ts +2 -1
  264. package/src/engine-components/codegen/components.ts +7 -13
  265. package/src/engine-components/export/usdz/USDZExporter.ts +4 -4
  266. package/src/engine-components/timeline/PlayableDirector.ts +83 -81
  267. package/src/engine-components/timeline/SignalAsset.ts +4 -1
  268. package/src/engine-components/timeline/TimelineBuilder.ts +824 -0
  269. package/src/engine-components/timeline/TimelineModels.ts +5 -1
  270. package/src/engine-components/timeline/TimelineTracks.ts +96 -27
  271. package/src/engine-components/timeline/index.ts +2 -1
  272. package/src/engine-components/ui/Canvas.ts +2 -8
  273. package/src/engine-components/ui/Text.ts +12 -8
  274. package/src/engine-components/web/CursorFollow.ts +21 -14
  275. package/src/engine-components/webxr/WebXRImageTracking.ts +2 -0
  276. package/dist/needle-engine.bundle-CmxIO5uH.min.js +0 -1732
  277. package/dist/needle-engine.bundle-tJIZukCz.umd.cjs +0 -1732
  278. package/lib/engine-components/AvatarLoader.d.ts +0 -80
  279. package/lib/engine-components/AvatarLoader.js +0 -232
  280. package/lib/engine-components/AvatarLoader.js.map +0 -1
  281. package/lib/engine-components/avatar/AvatarBlink_Simple.d.ts +0 -11
  282. package/lib/engine-components/avatar/AvatarBlink_Simple.js +0 -77
  283. package/lib/engine-components/avatar/AvatarBlink_Simple.js.map +0 -1
  284. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.d.ts +0 -14
  285. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js +0 -69
  286. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js.map +0 -1
  287. package/lib/engine-components/avatar/Avatar_Brain_LookAt.d.ts +0 -29
  288. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js +0 -122
  289. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js.map +0 -1
  290. package/lib/engine-components/avatar/Avatar_MouthShapes.d.ts +0 -15
  291. package/lib/engine-components/avatar/Avatar_MouthShapes.js +0 -80
  292. package/lib/engine-components/avatar/Avatar_MouthShapes.js.map +0 -1
  293. package/lib/engine-components/avatar/Avatar_MustacheShake.d.ts +0 -9
  294. package/lib/engine-components/avatar/Avatar_MustacheShake.js +0 -30
  295. package/lib/engine-components/avatar/Avatar_MustacheShake.js.map +0 -1
  296. package/plugins/dts-generator/dts.codegen.js +0 -334
  297. package/plugins/dts-generator/dts.scan.js +0 -99
  298. package/plugins/dts-generator/dts.writer.js +0 -59
  299. package/plugins/dts-generator/glb.discovery.js +0 -279
  300. package/plugins/dts-generator/glb.extractor.js +0 -215
  301. package/plugins/dts-generator/glb.reader.js +0 -167
  302. package/plugins/dts-generator/index.js +0 -36
  303. package/plugins/dts-generator/manifest.types.js +0 -174
  304. package/plugins/gltf-packer.mjs +0 -1
  305. package/src/engine-components/AvatarLoader.ts +0 -264
  306. package/src/engine-components/avatar/AvatarBlink_Simple.ts +0 -70
  307. package/src/engine-components/avatar/AvatarEyeLook_Rotation.ts +0 -64
  308. package/src/engine-components/avatar/Avatar_Brain_LookAt.ts +0 -140
  309. package/src/engine-components/avatar/Avatar_MouthShapes.ts +0 -84
  310. package/src/engine-components/avatar/Avatar_MustacheShake.ts +0 -32
  311. package/src/vite-env.d.ts +0 -16
@@ -1,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,10 +1,10 @@
1
1
  import type { SceneData } from "needle-bindings";
2
2
  export type { SceneData };
3
- import type { IContext } from "./engine_types.js";
4
- import { getComponent } from "./engine_components.js";
5
- import { TypeStore } from "./engine_typestore.js";
6
3
  import { isDevEnvironment } from "./debug/index.js";
4
+ import { getComponent } from "./engine_components.js";
7
5
  import { ContextRegistry } from "./engine_context_registry.js";
6
+ import type { IContext } from "./engine_types.js";
7
+ import { TypeStore } from "./engine_typestore.js";
8
8
 
9
9
  /**
10
10
  * Quick access to the current Needle Engine context from anywhere — no need to pass `ctx` around.
@@ -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,7 +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
-
15
+ // #region Color
15
16
  class ColorSerializer extends TypeSerializer {
16
17
  constructor() {
17
18
  super([Color, RGBAColor], "ColorSerializer")
@@ -35,6 +36,8 @@ class ColorSerializer extends TypeSerializer {
35
36
  }
36
37
  }
37
38
 
39
+ // #region Euler
40
+
38
41
  class EulerSerializer extends TypeSerializer {
39
42
  constructor() {
40
43
  super([Euler], "EulerSerializer");
@@ -58,6 +61,8 @@ declare type ObjectData = {
58
61
  node?: number;
59
62
  guid?: string;
60
63
  }
64
+
65
+ // #region ObjectSerializer
61
66
  class ObjectSerializer extends TypeSerializer {
62
67
  constructor() {
63
68
  super(Object3D, "ObjectSerializer");
@@ -119,7 +124,7 @@ class ObjectSerializer extends TypeSerializer {
119
124
  }
120
125
  if (!res) {
121
126
  if (isDevEnvironment() || debugExtension)
122
- 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.`);
123
128
  data["could_not_resolve"] = true;
124
129
  }
125
130
  else {
@@ -137,7 +142,7 @@ class ObjectSerializer extends TypeSerializer {
137
142
  }
138
143
  }
139
144
 
140
-
145
+ // #region ComponentSerializer
141
146
  class ComponentSerializer extends TypeSerializer {
142
147
 
143
148
  constructor() {
@@ -226,6 +231,7 @@ declare type EventListCall = {
226
231
 
227
232
  const $eventListDebugInfo = Symbol("eventListDebugInfo");
228
233
 
234
+ // #region EventListSerializer
229
235
  class EventListSerializer extends TypeSerializer {
230
236
  constructor() {
231
237
  super([EventList]);
@@ -328,11 +334,6 @@ class EventListSerializer extends TypeSerializer {
328
334
  if (debugExtension)
329
335
  console.log(evt);
330
336
 
331
- const eventListOwner = context.target;
332
- if (eventListOwner !== undefined && context.path !== undefined) {
333
- evt.setEventTarget(context.path, eventListOwner);
334
- }
335
-
336
337
  return evt;
337
338
  }
338
339
  return undefined;
@@ -371,6 +372,7 @@ class EventListSerializer extends TypeSerializer {
371
372
  */
372
373
  const cloneOriginalMap = new WeakMap<Texture, Texture>();
373
374
 
375
+ // #region RenderTextureSerializer
374
376
  export class RenderTextureSerializer extends TypeSerializer {
375
377
  constructor() {
376
378
  super([RenderTexture, WebGLRenderTarget]);
@@ -412,7 +414,7 @@ export class RenderTextureSerializer extends TypeSerializer {
412
414
  }
413
415
  }
414
416
 
415
-
417
+ // #region UriSerializer
416
418
  export class UriSerializer extends TypeSerializer {
417
419
  constructor() {
418
420
  super([URL]);
@@ -430,7 +432,27 @@ export class UriSerializer extends TypeSerializer {
430
432
  }
431
433
  }
432
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
+
433
454
 
455
+ // #region Init serializer
434
456
  // Module-level references used by EventListSerializer internally
435
457
  export let colorSerializer: ColorSerializer;
436
458
  export let objectSerializer: ObjectSerializer;
@@ -460,4 +482,5 @@ export function initBuiltinSerializers() {
460
482
  eventListSerializer = new EventListSerializer();
461
483
  new RenderTextureSerializer();
462
484
  new UriSerializer();
485
+ new AudioClipSerializer();
463
486
  }
@@ -207,6 +207,15 @@ export interface ISerializable {
207
207
  onAfterDeserialize?(data: any, context: SerializationContext): void;
208
208
  };
209
209
 
210
+ export function isSerializable(obj: any): obj is ISerializable {
211
+ return obj && typeof obj === "object" && (
212
+ typeof obj.$serializedTypes === "object" ||
213
+ typeof obj.onBeforeDeserialize === "function" ||
214
+ typeof obj.onBeforeDeserializeMember === "function" ||
215
+ typeof obj.onAfterDeserializeMember === "function" ||
216
+ typeof obj.onAfterDeserialize === "function"
217
+ )
218
+ }
210
219
 
211
220
  export function serializeObject(obj: ISerializable, context: SerializationContext): object | null {
212
221
  const types = obj.$serializedTypes;
@@ -5,7 +5,6 @@ import { type GLTF as THREE_GLTF } from "three/examples/jsm/loaders/GLTFLoader.j
5
5
 
6
6
  import type { Camera as CameraComponent } from "../engine-components/api.js";
7
7
  import type { Context } from "./engine_context.js";
8
- import { InstantiateContext } from "./engine_gameobject.js";
9
8
  import { CollisionDetectionMode, type PhysicsMaterial, RigidbodyConstraints } from "./engine_physics.types.js";
10
9
  import { CircularBuffer } from "./engine_utils.js";
11
10
  import type { NeedleXRSession } from "./engine_xr.js";
@@ -196,13 +195,11 @@ export interface IComponent extends IHasGuid {
196
195
  /** @internal */
197
196
  __internalStart();
198
197
  /** @internal */
199
- __internalEnable(isAddingOrRemovingFromScene?: boolean);
198
+ __internalEnable(isHierarchyChange?: boolean);
200
199
  /** @internal */
201
- __internalDisable(isAddingOrRemovingFromScene?: boolean);
200
+ __internalDisable(isHierarchyChange?: boolean);
202
201
  /** @internal */
203
202
  __internalDestroy();
204
- /** @internal */
205
- resolveGuids?(guidsMap: GuidsMap): void;
206
203
 
207
204
  /** experimental, called when the script is registered for the first time, this is called even if the component is not enabled. */
208
205
  registering?();
@@ -240,14 +237,14 @@ export interface IComponent extends IHasGuid {
240
237
  }
241
238
 
242
239
  export function isComponent(obj: any): obj is IComponent {
243
- return obj && obj.isComponent;
240
+ return obj && typeof obj === "object" && obj.isComponent;
244
241
  }
245
242
 
246
243
  export type ICamera = CameraComponent;
247
244
 
248
245
  export type IAnimationComponent = Pick<IComponent, "gameObject"> & {
249
246
  isAnimationComponent: boolean;
250
- addClip?(clip: AnimationClip);
247
+ addClip?(clip: AnimationClip): void;
251
248
  }
252
249
 
253
250
  /** Interface for a camera controller component that can be attached to a camera to control it */
@@ -274,7 +271,10 @@ export declare interface IRenderer extends IComponent {
274
271
 
275
272
  export declare interface IEventList {
276
273
  readonly isEventList: true;
277
- __internalOnInstantiate(map: InstantiateContext): IEventList;
274
+ }
275
+
276
+ export declare interface ISignalReceiver {
277
+ readonly isSignalReceiver: true;
278
278
  }
279
279
 
280
280
  // export declare interface IPhysicsComponent extends IComponent {
@@ -302,12 +302,18 @@ export declare interface ICollider extends IComponent {
302
302
  * Default: [0]
303
303
  */
304
304
  membership?: number[];
305
- /** The collider filter indicates what groups the collider can interact with (e.g. group 3 and 4)
306
- * An `undefined` array indicates that the collider can interact with all groups
307
- * Note: Make sure to call updateProperties after having changed this property
305
+ /** The collider filter indicates what groups the collider can interact with (e.g. group 3 and 4)
306
+ * An `undefined` array indicates that the collider can interact with all groups
307
+ * Note: Make sure to call updateProperties after having changed this property
308
308
  * Default: undefined
309
309
  */
310
310
  filter?: number[];
311
+ /** The density of the collider used for automatic mass calculation.
312
+ * When the attached Rigidbody has `autoMass` enabled, the mass is computed as `density × volume`.
313
+ * Note: Make sure to call updateProperties after having changed this property
314
+ * Default: undefined (uses physics engine default of 1.0)
315
+ */
316
+ density?: number;
311
317
  }
312
318
 
313
319
  export declare interface ISphereCollider extends ICollider {
@@ -475,8 +481,10 @@ export interface IPhysicsEngine {
475
481
  postStep();
476
482
  /** Indicates whether the physics engine is currently updating */
477
483
  get isUpdating(): boolean;
478
- /** Clears all cached data (e.g., mesh data when creating scaled mesh colliders) */
479
- clearCaches();
484
+ /** Tears down the physics world and frees all resources. The world will be re-created on next use. */
485
+ dispose(): void;
486
+ /** @deprecated Use {@link dispose} instead. */
487
+ clearCaches(): void;
480
488
 
481
489
  /** Enables or disables the physics engine */
482
490
  enabled: boolean;
@@ -513,20 +521,25 @@ export interface IPhysicsEngine {
513
521
  /** True if you want to also hit objects when the raycast starts from inside a collider */
514
522
  solid?: boolean,
515
523
  queryFilterFlags?: QueryFilterFlags,
516
- /**
517
- * Raycast filter groups. Groups are used to apply the collision group rules for the scene query.
518
- * The scene query will only consider hits with colliders with collision groups compatible with
524
+ /**
525
+ * Raycast filter groups. Groups are used to apply the collision group rules for the scene query.
526
+ * The scene query will only consider hits with colliders with collision groups compatible with
519
527
  * this collision group (using the bitwise test described in the collision groups section).
520
- * For example membership 0x0001 and filter 0x0002 should be 0x00010002
528
+ * For example membership 0x0001 and filter 0x0002 should be 0x00010002
521
529
  * @see https://rapier.rs/docs/user_guides/javascript/colliders#collision-groups-and-solver-groups
522
530
  */
523
531
  filterGroups?: number,
524
- /**
532
+ /**
525
533
  * Predicate to filter colliders in raycast results
526
534
  * @param collider The collider being tested
527
535
  * @returns False to ignore this collider, true to include it
528
536
  */
529
- filterPredicate?: (collider: ICollider) => boolean
537
+ filterPredicate?: (collider: ICollider) => boolean,
538
+ /** When true, trigger/sensor colliders will be included in the raycast results.
539
+ * By default trigger colliders are skipped.
540
+ * @default false
541
+ */
542
+ includeTriggers?: boolean,
530
543
  }): RaycastResult;
531
544
 
532
545
  /**
@@ -541,20 +554,25 @@ export interface IPhysicsEngine {
541
554
  /** True if you want to also hit objects when the raycast starts from inside a collider */
542
555
  solid?: boolean,
543
556
  queryFilterFlags?: QueryFilterFlags,
544
- /**
545
- * Raycast filter groups. Groups are used to apply the collision group rules for the scene query.
546
- * The scene query will only consider hits with colliders with collision groups compatible with
557
+ /**
558
+ * Raycast filter groups. Groups are used to apply the collision group rules for the scene query.
559
+ * The scene query will only consider hits with colliders with collision groups compatible with
547
560
  * this collision group (using the bitwise test described in the collision groups section).
548
- * For example membership 0x0001 and filter 0x0002 should be 0x00010002
561
+ * For example membership 0x0001 and filter 0x0002 should be 0x00010002
549
562
  * @see https://rapier.rs/docs/user_guides/javascript/colliders#collision-groups-and-solver-groups
550
563
  */
551
564
  filterGroups?: number,
552
- /**
565
+ /**
553
566
  * Predicate to filter colliders in raycast results
554
567
  * @param collider The collider being tested
555
568
  * @returns False to ignore this collider, true to include it
556
569
  */
557
- filterPredicate?: (collider: ICollider) => boolean
570
+ filterPredicate?: (collider: ICollider) => boolean,
571
+ /** When true, trigger/sensor colliders will be included in the raycast results.
572
+ * By default trigger colliders are skipped.
573
+ * @default false
574
+ */
575
+ includeTriggers?: boolean,
558
576
  }): RaycastResult;
559
577
 
560
578
  /**
@@ -738,8 +756,9 @@ export interface IPhysicsEngine {
738
756
  getBody(obj: ICollider | IRigidbody): null | any;
739
757
 
740
758
  // Joints
741
- addFixedJoint(body1: IRigidbody, body2: IRigidbody);
742
- addHingeJoint(body1: IRigidbody, body2: IRigidbody, anchor: Vec3, axis: Vec3);
759
+ addFixedJoint(body1: IRigidbody, body2: IRigidbody): Promise<any> | any;
760
+ addHingeJoint(body1: IRigidbody, body2: IRigidbody, anchor: Vec3, axis: Vec3): Promise<any> | any;
761
+ removeJoint(joint: any): void;
743
762
 
744
763
  /** Enable to render collider shapes */
745
764
  debugRenderColliders: boolean;
@@ -79,8 +79,12 @@ function createPropertyWrapper(target: IComponent | any, _propertyKey: string |
79
79
  return;
80
80
  }
81
81
 
82
- // only build wrapper once per type
83
- if (this[$prop] === undefined) {
82
+ // Only install the getter/setter once per instance.
83
+ // processStart may call __internalAwake again for components that were inactive
84
+ // during processNewScripts — the base Component.__internalAwake has a __didAwake guard
85
+ // but this decorator wrapper runs before reaching it, so we need our own idempotency check.
86
+ const desc = Object.getOwnPropertyDescriptor(this, propertyKey);
87
+ if (!desc || !desc.get) {
84
88
 
85
89
  // make sure the field is initialized in a hidden property
86
90
  this[$prop] = this[propertyKey];
@@ -99,6 +103,7 @@ function createPropertyWrapper(target: IComponent | any, _propertyKey: string |
99
103
  }
100
104
 
101
105
  Object.defineProperty(this, propertyKey, {
106
+ configurable: true,
102
107
  set: function (v) {
103
108
  if (this[$isAssigningProperties] === true) {
104
109
  this[$prop] = v;
@@ -279,24 +279,35 @@ declare type deepClonePredicate = (owner: any, propertyName: string, current: an
279
279
  * return true;
280
280
  * });
281
281
  * */
282
- export function deepClone(obj: any, predicate?: deepClonePredicate): any {
282
+ export function deepClone(obj: any, predicate?: deepClonePredicate, _visited?: WeakSet<object>): any {
283
283
  if (obj !== null && obj !== undefined && typeof obj === "object") {
284
+ if (!_visited) _visited = new WeakSet();
285
+ if (_visited.has(obj)) return obj;
286
+ _visited.add(obj);
287
+
284
288
  let clone;
285
289
  if (Array.isArray(obj)) clone = [];
286
290
  else {
287
- clone = Object.create(obj);
288
- Object.assign(clone, obj);
291
+ clone = Object.create(Object.getPrototypeOf(obj));
292
+ // Copy own properties, skipping getter-only properties that can't be set
293
+ const descriptors = Object.getOwnPropertyDescriptors(obj);
294
+ for (const key in descriptors) {
295
+ const desc = descriptors[key];
296
+ if (desc.set || desc.writable !== false) {
297
+ try { clone[key] = obj[key]; }
298
+ catch { /* skip read-only properties */ }
299
+ }
300
+ }
289
301
  }
290
302
  for (const key of Object.keys(obj)) {
291
303
  const val = obj[key];
292
304
  if (predicate && !predicate(obj, key, val)) {
293
- // console.log("SKIP", val);
294
305
  clone[key] = val;
295
306
  }
296
307
  else if (val?.clone !== undefined && typeof val.clone === "function")
297
308
  clone[key] = val.clone();
298
309
  else
299
- clone[key] = deepClone(val, predicate);
310
+ clone[key] = deepClone(val, predicate, _visited);
300
311
  }
301
312
  return clone;
302
313
  }
@@ -4,7 +4,7 @@ import { Quaternion, Vector2, Vector3, Vector4 } from "three";
4
4
 
5
5
  import { needleLogoOnlySVG } from "./assets/index.js";
6
6
  import { isDevEnvironment } from "./debug/debug.js";
7
- import { hasCommercialLicense } from "./engine_license.js";
7
+ import { _BGpnKD } from "./engine_license.js";
8
8
  import { InternalAttributeUtils } from "./engine_utils_attributes.js";
9
9
  import type { NeedleEngineWebComponent } from "./webcomponents/needle-engine.js";
10
10
 
@@ -135,7 +135,7 @@ async function internalRenderQRCodeOverlays(canvas: HTMLCanvasElement, args: { s
135
135
  console.debug("[QR Code] No web component found")
136
136
  }
137
137
 
138
- const canUseCustomLogo = hasCommercialLicense();
138
+ const canUseCustomLogo = _BGpnKD();
139
139
 
140
140
  // Query logo src from needle-engine attribute.
141
141
  // For any supported attribute it's possible to use "falsey" values (e.g. "0" or "false" to disable the logo in the QR code)
@@ -35,7 +35,7 @@ export class GenerateMeshBVHWorker extends WorkerBase {
35
35
 
36
36
  worker.onerror = e => {
37
37
 
38
- reject(new Error(`[GenerateMeshBVHWorker] ${e.message || "Unknown error. Please check the server console. If you're using vite try adding 'three-mesh-bvh' to 'optimizeDeps.exclude' in your vite.config.js"}`));
38
+ reject(new Error(`[GenerateMeshBVHWorker] ${e.message || "Could not load worker."}`));
39
39
 
40
40
  };
41
41