@needle-tools/engine 5.1.0-canary.c918d62 → 5.1.0-canary.cce79c8

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 (275) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/components.needle.json +1 -1
  3. package/dist/needle-engine.bundle-B1w7P037.min.js +1733 -0
  4. package/dist/needle-engine.bundle-C4w-9vec.umd.cjs +1733 -0
  5. package/dist/{needle-engine.bundle-GX1Beb5k.js → needle-engine.bundle-CPbnC8NP.js} +12310 -11816
  6. package/dist/needle-engine.d.ts +876 -230
  7. package/dist/needle-engine.js +584 -582
  8. package/dist/needle-engine.min.js +1 -1
  9. package/dist/needle-engine.umd.cjs +1 -1
  10. package/lib/engine/api.d.ts +5 -0
  11. package/lib/engine/api.js +4 -0
  12. package/lib/engine/api.js.map +1 -1
  13. package/lib/engine/codegen/register_types.js +2 -10
  14. package/lib/engine/codegen/register_types.js.map +1 -1
  15. package/lib/engine/debug/debug_spatial_console.d.ts +2 -0
  16. package/lib/engine/debug/debug_spatial_console.js +10 -7
  17. package/lib/engine/debug/debug_spatial_console.js.map +1 -1
  18. package/lib/engine/engine_addressables.d.ts +2 -0
  19. package/lib/engine/engine_addressables.js +6 -3
  20. package/lib/engine/engine_addressables.js.map +1 -1
  21. package/lib/engine/engine_audio.d.ts +68 -0
  22. package/lib/engine/engine_audio.js +172 -0
  23. package/lib/engine/engine_audio.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 +17 -20
  27. package/lib/engine/engine_context.js +15 -17
  28. package/lib/engine/engine_context.js.map +1 -1
  29. package/lib/engine/engine_disposable.d.ts +172 -0
  30. package/lib/engine/engine_disposable.js +136 -0
  31. package/lib/engine/engine_disposable.js.map +1 -0
  32. package/lib/engine/engine_gameobject.d.ts +1 -10
  33. package/lib/engine/engine_gameobject.js +22 -120
  34. package/lib/engine/engine_gameobject.js.map +1 -1
  35. package/lib/engine/engine_gltf_builtin_components.js +7 -69
  36. package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
  37. package/lib/engine/engine_init.js +13 -3
  38. package/lib/engine/engine_init.js.map +1 -1
  39. package/lib/engine/engine_input.d.ts +1 -1
  40. package/lib/engine/engine_input.js +1 -1
  41. package/lib/engine/engine_input.js.map +1 -1
  42. package/lib/engine/engine_instantiate_resolve.d.ts +42 -0
  43. package/lib/engine/engine_instantiate_resolve.js +372 -0
  44. package/lib/engine/engine_instantiate_resolve.js.map +1 -0
  45. package/lib/engine/engine_license.js +1 -1
  46. package/lib/engine/engine_license.js.map +1 -1
  47. package/lib/engine/engine_mainloop_utils.js +7 -4
  48. package/lib/engine/engine_mainloop_utils.js.map +1 -1
  49. package/lib/engine/engine_networking.d.ts +51 -37
  50. package/lib/engine/engine_networking.js +132 -82
  51. package/lib/engine/engine_networking.js.map +1 -1
  52. package/lib/engine/engine_networking.transport.websocket.d.ts +15 -0
  53. package/lib/engine/engine_networking.transport.websocket.js +38 -0
  54. package/lib/engine/engine_networking.transport.websocket.js.map +1 -0
  55. package/lib/engine/engine_networking_blob.js +1 -1
  56. package/lib/engine/engine_networking_blob.js.map +1 -1
  57. package/lib/engine/engine_networking_instantiate.js +2 -2
  58. package/lib/engine/engine_networking_instantiate.js.map +1 -1
  59. package/lib/engine/engine_networking_types.d.ts +39 -1
  60. package/lib/engine/engine_networking_types.js +7 -0
  61. package/lib/engine/engine_networking_types.js.map +1 -1
  62. package/lib/engine/engine_physics_rapier.d.ts +11 -3
  63. package/lib/engine/engine_physics_rapier.js +88 -25
  64. package/lib/engine/engine_physics_rapier.js.map +1 -1
  65. package/lib/engine/engine_scenedata.d.ts +5 -7
  66. package/lib/engine/engine_scenedata.js +16 -13
  67. package/lib/engine/engine_scenedata.js.map +1 -1
  68. package/lib/engine/engine_serialization_builtin_serializer.d.ts +10 -16
  69. package/lib/engine/engine_serialization_builtin_serializer.js +56 -46
  70. package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
  71. package/lib/engine/engine_serialization_core.d.ts +1 -0
  72. package/lib/engine/engine_serialization_core.js +7 -0
  73. package/lib/engine/engine_serialization_core.js.map +1 -1
  74. package/lib/engine/engine_types.d.ts +19 -11
  75. package/lib/engine/engine_types.js +1 -1
  76. package/lib/engine/engine_types.js.map +1 -1
  77. package/lib/engine/engine_util_decorator.js +7 -2
  78. package/lib/engine/engine_util_decorator.js.map +1 -1
  79. package/lib/engine/engine_utils.d.ts +1 -1
  80. package/lib/engine/engine_utils.js +19 -5
  81. package/lib/engine/engine_utils.js.map +1 -1
  82. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
  83. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js.map +1 -1
  84. package/lib/engine/webcomponents/jsx.d.ts +9 -2
  85. package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +1 -1
  86. package/lib/engine/webcomponents/needle menu/needle-menu.js +1 -1
  87. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  88. package/lib/engine/webcomponents/needle-engine.d.ts +10 -4
  89. package/lib/engine/webcomponents/needle-engine.js +1 -1
  90. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  91. package/lib/engine/xr/NeedleXRSession.d.ts +3 -2
  92. package/lib/engine/xr/NeedleXRSession.js +50 -14
  93. package/lib/engine/xr/NeedleXRSession.js.map +1 -1
  94. package/lib/engine/xr/events.d.ts +1 -1
  95. package/lib/engine/xr/events.js.map +1 -1
  96. package/lib/engine-components/Animation.js +17 -16
  97. package/lib/engine-components/Animation.js.map +1 -1
  98. package/lib/engine-components/Animator.d.ts +6 -0
  99. package/lib/engine-components/Animator.js +17 -12
  100. package/lib/engine-components/Animator.js.map +1 -1
  101. package/lib/engine-components/AnimatorController.builder.d.ts +113 -0
  102. package/lib/engine-components/AnimatorController.builder.js +195 -0
  103. package/lib/engine-components/AnimatorController.builder.js.map +1 -0
  104. package/lib/engine-components/AnimatorController.d.ts +4 -119
  105. package/lib/engine-components/AnimatorController.js +35 -233
  106. package/lib/engine-components/AnimatorController.js.map +1 -1
  107. package/lib/engine-components/AudioSource.d.ts +19 -3
  108. package/lib/engine-components/AudioSource.js +121 -68
  109. package/lib/engine-components/AudioSource.js.map +1 -1
  110. package/lib/engine-components/Collider.d.ts +18 -9
  111. package/lib/engine-components/Collider.js +61 -14
  112. package/lib/engine-components/Collider.js.map +1 -1
  113. package/lib/engine-components/Component.d.ts +72 -9
  114. package/lib/engine-components/Component.js +114 -10
  115. package/lib/engine-components/Component.js.map +1 -1
  116. package/lib/engine-components/DragControls.d.ts +7 -0
  117. package/lib/engine-components/DragControls.js +19 -7
  118. package/lib/engine-components/DragControls.js.map +1 -1
  119. package/lib/engine-components/EventList.d.ts +31 -9
  120. package/lib/engine-components/EventList.js +37 -76
  121. package/lib/engine-components/EventList.js.map +1 -1
  122. package/lib/engine-components/Joints.d.ts +4 -2
  123. package/lib/engine-components/Joints.js +19 -3
  124. package/lib/engine-components/Joints.js.map +1 -1
  125. package/lib/engine-components/Light.js +13 -3
  126. package/lib/engine-components/Light.js.map +1 -1
  127. package/lib/engine-components/Networking.d.ts +1 -1
  128. package/lib/engine-components/Networking.js +1 -1
  129. package/lib/engine-components/OrbitControls.js +16 -11
  130. package/lib/engine-components/OrbitControls.js.map +1 -1
  131. package/lib/engine-components/ReflectionProbe.js +2 -0
  132. package/lib/engine-components/ReflectionProbe.js.map +1 -1
  133. package/lib/engine-components/RigidBody.d.ts +12 -4
  134. package/lib/engine-components/RigidBody.js +18 -4
  135. package/lib/engine-components/RigidBody.js.map +1 -1
  136. package/lib/engine-components/SeeThrough.js +2 -2
  137. package/lib/engine-components/SeeThrough.js.map +1 -1
  138. package/lib/engine-components/api.d.ts +1 -1
  139. package/lib/engine-components/api.js +1 -1
  140. package/lib/engine-components/api.js.map +1 -1
  141. package/lib/engine-components/codegen/components.d.ts +3 -9
  142. package/lib/engine-components/codegen/components.js +3 -9
  143. package/lib/engine-components/codegen/components.js.map +1 -1
  144. package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
  145. package/lib/engine-components/postprocessing/VolumeParameter.d.ts +2 -0
  146. package/lib/engine-components/postprocessing/VolumeParameter.js +4 -1
  147. package/lib/engine-components/postprocessing/VolumeParameter.js.map +1 -1
  148. package/lib/engine-components/timeline/PlayableDirector.d.ts +16 -6
  149. package/lib/engine-components/timeline/PlayableDirector.js +63 -61
  150. package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
  151. package/lib/engine-components/timeline/SignalAsset.d.ts +3 -1
  152. package/lib/engine-components/timeline/SignalAsset.js +1 -0
  153. package/lib/engine-components/timeline/SignalAsset.js.map +1 -1
  154. package/lib/engine-components/timeline/TimelineBuilder.d.ts +247 -0
  155. package/lib/engine-components/timeline/TimelineBuilder.js +400 -0
  156. package/lib/engine-components/timeline/TimelineBuilder.js.map +1 -0
  157. package/lib/engine-components/timeline/TimelineModels.d.ts +2 -1
  158. package/lib/engine-components/timeline/TimelineModels.js +3 -0
  159. package/lib/engine-components/timeline/TimelineModels.js.map +1 -1
  160. package/lib/engine-components/timeline/TimelineTracks.d.ts +23 -0
  161. package/lib/engine-components/timeline/TimelineTracks.js +71 -13
  162. package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
  163. package/lib/engine-components/timeline/index.d.ts +2 -1
  164. package/lib/engine-components/timeline/index.js +2 -0
  165. package/lib/engine-components/timeline/index.js.map +1 -1
  166. package/lib/engine-components/ui/Canvas.d.ts +1 -1
  167. package/lib/engine-components/ui/Canvas.js +2 -8
  168. package/lib/engine-components/ui/Canvas.js.map +1 -1
  169. package/lib/engine-components/ui/Text.d.ts +1 -0
  170. package/lib/engine-components/ui/Text.js +10 -7
  171. package/lib/engine-components/ui/Text.js.map +1 -1
  172. package/lib/engine-components/web/CursorFollow.js +21 -12
  173. package/lib/engine-components/web/CursorFollow.js.map +1 -1
  174. package/lib/engine-components/webxr/WebXRImageTracking.js +4 -0
  175. package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
  176. package/package.json +2 -83
  177. package/plugins/common/license.js +5 -2
  178. package/plugins/common/worker.js +9 -4
  179. package/plugins/vite/asap.js +17 -8
  180. package/plugins/vite/dependencies.js +29 -10
  181. package/plugins/vite/dependency-watcher.js +2 -2
  182. package/plugins/vite/editor-connection.js +3 -3
  183. package/plugins/vite/local-files-core.js +3 -3
  184. package/plugins/vite/local-files-utils.d.ts +3 -1
  185. package/plugins/vite/local-files-utils.js +29 -5
  186. package/plugins/vite/reload.js +19 -18
  187. package/plugins/vite/server.js +2 -1
  188. package/src/engine/api.ts +7 -0
  189. package/src/engine/codegen/register_types.ts +2 -10
  190. package/src/engine/debug/debug_spatial_console.ts +10 -7
  191. package/src/engine/engine_addressables.ts +6 -3
  192. package/src/engine/engine_audio.ts +184 -0
  193. package/src/engine/engine_components.ts +1 -1
  194. package/src/engine/engine_context.ts +22 -23
  195. package/src/engine/engine_disposable.ts +214 -0
  196. package/src/engine/engine_gameobject.ts +54 -159
  197. package/src/engine/engine_gltf_builtin_components.ts +7 -76
  198. package/src/engine/engine_init.ts +13 -3
  199. package/src/engine/engine_input.ts +1 -1
  200. package/src/engine/engine_instantiate_resolve.ts +407 -0
  201. package/src/engine/engine_license.ts +1 -1
  202. package/src/engine/engine_mainloop_utils.ts +7 -4
  203. package/src/engine/engine_networking.transport.websocket.ts +45 -0
  204. package/src/engine/engine_networking.ts +161 -137
  205. package/src/engine/engine_networking_blob.ts +1 -1
  206. package/src/engine/engine_networking_instantiate.ts +2 -2
  207. package/src/engine/engine_networking_types.ts +41 -1
  208. package/src/engine/engine_physics_rapier.ts +82 -27
  209. package/src/engine/engine_scenedata.ts +16 -13
  210. package/src/engine/engine_serialization_builtin_serializer.ts +64 -52
  211. package/src/engine/engine_serialization_core.ts +9 -0
  212. package/src/engine/engine_types.ts +24 -15
  213. package/src/engine/engine_util_decorator.ts +7 -2
  214. package/src/engine/engine_utils.ts +16 -5
  215. package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
  216. package/src/engine/webcomponents/jsx.d.ts +9 -2
  217. package/src/engine/webcomponents/needle menu/needle-menu.ts +1 -1
  218. package/src/engine/webcomponents/needle-engine.ts +10 -4
  219. package/src/engine/xr/NeedleXRSession.ts +48 -13
  220. package/src/engine/xr/events.ts +1 -1
  221. package/src/engine-components/Animation.ts +19 -16
  222. package/src/engine-components/Animator.ts +18 -11
  223. package/src/engine-components/AnimatorController.builder.ts +261 -0
  224. package/src/engine-components/AnimatorController.ts +23 -292
  225. package/src/engine-components/AudioSource.ts +130 -79
  226. package/src/engine-components/Collider.ts +66 -18
  227. package/src/engine-components/Component.ts +118 -20
  228. package/src/engine-components/DragControls.ts +18 -11
  229. package/src/engine-components/EventList.ts +45 -83
  230. package/src/engine-components/Joints.ts +20 -4
  231. package/src/engine-components/Light.ts +13 -4
  232. package/src/engine-components/Networking.ts +1 -1
  233. package/src/engine-components/OrbitControls.ts +18 -9
  234. package/src/engine-components/ReflectionProbe.ts +2 -0
  235. package/src/engine-components/RigidBody.ts +18 -4
  236. package/src/engine-components/SeeThrough.ts +2 -2
  237. package/src/engine-components/api.ts +1 -1
  238. package/src/engine-components/codegen/components.ts +3 -9
  239. package/src/engine-components/postprocessing/VolumeParameter.ts +4 -1
  240. package/src/engine-components/timeline/PlayableDirector.ts +61 -64
  241. package/src/engine-components/timeline/SignalAsset.ts +4 -1
  242. package/src/engine-components/timeline/TimelineBuilder.ts +565 -0
  243. package/src/engine-components/timeline/TimelineModels.ts +5 -1
  244. package/src/engine-components/timeline/TimelineTracks.ts +74 -13
  245. package/src/engine-components/timeline/index.ts +2 -1
  246. package/src/engine-components/ui/Canvas.ts +2 -8
  247. package/src/engine-components/ui/Text.ts +12 -8
  248. package/src/engine-components/web/CursorFollow.ts +21 -13
  249. package/src/engine-components/webxr/WebXRImageTracking.ts +2 -0
  250. package/dist/needle-engine.bundle-Bt7fDq8w.umd.cjs +0 -1732
  251. package/dist/needle-engine.bundle-C-jz9yqV.min.js +0 -1732
  252. package/lib/engine-components/AvatarLoader.d.ts +0 -80
  253. package/lib/engine-components/AvatarLoader.js +0 -232
  254. package/lib/engine-components/AvatarLoader.js.map +0 -1
  255. package/lib/engine-components/avatar/AvatarBlink_Simple.d.ts +0 -11
  256. package/lib/engine-components/avatar/AvatarBlink_Simple.js +0 -77
  257. package/lib/engine-components/avatar/AvatarBlink_Simple.js.map +0 -1
  258. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.d.ts +0 -14
  259. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js +0 -69
  260. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js.map +0 -1
  261. package/lib/engine-components/avatar/Avatar_Brain_LookAt.d.ts +0 -29
  262. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js +0 -122
  263. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js.map +0 -1
  264. package/lib/engine-components/avatar/Avatar_MouthShapes.d.ts +0 -15
  265. package/lib/engine-components/avatar/Avatar_MouthShapes.js +0 -80
  266. package/lib/engine-components/avatar/Avatar_MouthShapes.js.map +0 -1
  267. package/lib/engine-components/avatar/Avatar_MustacheShake.d.ts +0 -9
  268. package/lib/engine-components/avatar/Avatar_MustacheShake.js +0 -30
  269. package/lib/engine-components/avatar/Avatar_MustacheShake.js.map +0 -1
  270. package/src/engine-components/AvatarLoader.ts +0 -264
  271. package/src/engine-components/avatar/AvatarBlink_Simple.ts +0 -70
  272. package/src/engine-components/avatar/AvatarEyeLook_Rotation.ts +0 -64
  273. package/src/engine-components/avatar/Avatar_Brain_LookAt.ts +0 -140
  274. package/src/engine-components/avatar/Avatar_MouthShapes.ts +0 -84
  275. package/src/engine-components/avatar/Avatar_MustacheShake.ts +0 -32
@@ -758,19 +758,26 @@ export class OrbitControls extends Behaviour implements ICameraController {
758
758
 
759
759
  if (this.targetBounds) {
760
760
  // #region target bounds
761
- const targetVector = this._controls.target;
762
761
  const boundsCenter = this.targetBounds.worldPosition;
763
762
  const boundsHalfSize = getTempVector(this.targetBounds.worldScale).multiplyScalar(0.5);
764
763
  const min = getTempVector(boundsCenter).sub(boundsHalfSize);
765
764
  const max = getTempVector(boundsCenter).add(boundsHalfSize);
766
- const newTarget = getTempVector(this._controls.target).clamp(min, max);
767
- const duration = .1;
768
- if (duration <= 0) targetVector.copy(newTarget);
769
- else targetVector.lerp(newTarget, this.context.time.deltaTime / duration);
765
+
770
766
  if (this._lookTargetLerpActive) {
771
- if (duration <= 0) this._lookTargetEndPosition.copy(newTarget);
772
- else this._lookTargetEndPosition.lerp(newTarget, this.context.time.deltaTime / (duration * 5));
767
+ // During a programmatic transition (fitCamera / setLookTargetPosition with immediate: false),
768
+ // only clamp the destination. The look-target lerp (above) handles moving _controls.target
769
+ // towards the endpoint — we must not fight it by also lerping _controls.target here.
770
+ this._lookTargetEndPosition.clamp(min, max);
771
+ }
772
+ else {
773
+ // Interactive use (pan/orbit): smoothly push the target back into bounds
774
+ const targetVector = this._controls.target;
775
+ const newTarget = getTempVector(targetVector).clamp(min, max);
776
+ const duration = .1;
777
+ if (duration <= 0) targetVector.copy(newTarget);
778
+ else targetVector.lerp(newTarget, Math.min(1, this.context.time.deltaTime / duration));
773
779
  }
780
+
774
781
  if (debug) {
775
782
  Gizmos.DrawWireBox(boundsCenter, boundsHalfSize.multiplyScalar(2), 0xffaa00);
776
783
  }
@@ -847,7 +854,8 @@ export class OrbitControls extends Behaviour implements ICameraController {
847
854
  this._controls.update(this.context.time.deltaTime);
848
855
 
849
856
  if (debug) {
850
- Gizmos.DrawWireSphere(this._controls.target, 0.1, 0x00ff00);
857
+ const distance = this._controls.getDistance();
858
+ Gizmos.DrawWireSphere(this._controls.target, 0.01 * distance, 0x00ff00);
851
859
  }
852
860
  }
853
861
  }
@@ -1022,7 +1030,8 @@ export class OrbitControls extends Behaviour implements ICameraController {
1022
1030
 
1023
1031
  if (debug) {
1024
1032
  console.warn("OrbitControls: setLookTargetPosition", position, immediateOrDuration);
1025
- Gizmos.DrawWireSphere(this._lookTargetEndPosition, .2, 0xff0000, 2);
1033
+ const distance = this._controls.getDistance();
1034
+ Gizmos.DrawWireSphere(this._lookTargetEndPosition, 0.01 * distance, 0xff5500, 2);
1026
1035
  }
1027
1036
 
1028
1037
  if (immediateOrDuration === true) {
@@ -290,6 +290,8 @@ export class ReflectionProbe extends Behaviour {
290
290
  const current = block.getOverride("envMap")?.value;
291
291
  if (current === this.texture) {
292
292
  block.removeOveride("envMap");
293
+ block.removeOveride("envMapRotation");
294
+ block.removeOveride("envMapIntensity");
293
295
  }
294
296
  }
295
297
  }
@@ -204,12 +204,19 @@ export class Rigidbody extends Behaviour implements IRigidbody {
204
204
 
205
205
  get isRigidbody() { return true; }
206
206
 
207
- /** When true the mass will be automatically calculated by the attached colliders */
207
+ /** When true the mass is automatically computed from the attached colliders using `mass = density × volume`.
208
+ * Each collider's {@link Collider.density} determines how heavy it contributes to the total mass.
209
+ * Disable to set mass explicitly via the `mass` property.
210
+ */
208
211
  @validate()
209
212
  autoMass: boolean = true;
210
213
 
211
- /** By default the mass will be automatically calculated (see `autoMass`) by the physics engine using the collider sizes
212
- * To set the mass manually you can either set the `mass` value or set `autoMass` to `false`
214
+ /** The mass of the rigidbody in kg (when `autoMass` is disabled).
215
+ * When `autoMass` is enabled, reading this returns the computed mass from `density × volume` of all attached colliders.
216
+ * Setting this property automatically disables `autoMass`.
217
+ *
218
+ * **Prefer using {@link Collider.density}** with `autoMass` enabled instead — density scales
219
+ * naturally with collider size, while explicit mass stays fixed regardless of shape changes.
213
220
  */
214
221
  @serializable()
215
222
  set mass(value: number) {
@@ -403,9 +410,16 @@ export class Rigidbody extends Behaviour implements IRigidbody {
403
410
  this.context.physics.engine?.removeBody(this);
404
411
  }
405
412
 
406
- onValidate() {
413
+ onValidate(property?: string) {
407
414
  this._propertiesChanged = true;
415
+ if (property === "autoMass" && !this.autoMass) {
416
+ if (isDevEnvironment() && !Rigidbody._didWarnAutoMass) {
417
+ Rigidbody._didWarnAutoMass = true;
418
+ console.warn("[Rigidbody] autoMass disabled — consider using Collider.density instead of setting mass explicitly. Density scales naturally with collider size.");
419
+ }
420
+ }
408
421
  }
422
+ private static _didWarnAutoMass = false;
409
423
 
410
424
  // need to do this right before updating physics to prevent rendered object glitching through physical bodies
411
425
  * beforePhysics() {
@@ -249,10 +249,10 @@ export class SeeThrough extends Behaviour {
249
249
  }
250
250
 
251
251
  const materials = renderer.sharedMaterials;// : this.rendererMaterials.get(renderer);
252
- if (!materials) return;
252
+ if (!materials?.length) return;
253
253
 
254
254
  const block = MaterialPropertyBlock.get(renderer.gameObject);
255
- const currentOpacity = (block.getOverride("opacity")?.value ?? materials[0].opacity ?? 1);
255
+ const currentOpacity = (block.getOverride("opacity")?.value ?? materials[0]?.opacity ?? 1);
256
256
 
257
257
  let newAlpha = Mathf.lerp(currentOpacity, targetAlpha, duration <= 0 ? 1 : this.context.time.deltaTime / duration);;
258
258
  if (newAlpha >= 0.99) newAlpha = 1;
@@ -34,8 +34,8 @@
34
34
  * @module Built-in Components
35
35
  */
36
36
 
37
+ export { AnimatorControllerBuilder, type ConditionMode, type StateOptions, type TransitionOptions } from "./AnimatorController.builder.js";
37
38
  export * from "./codegen/components.js";
38
- export { AnimatorControllerBuilder, type ConditionMode, type StateOptions, type TransitionOptions } from "./AnimatorController.js";
39
39
  export { Collider } from "./Collider.js"; // export abstract type
40
40
  export { Behaviour, Component, GameObject } from "./Component.js";
41
41
 
@@ -6,18 +6,10 @@ export { Animation } from "../Animation.js";
6
6
  export { Keyframe } from "../AnimationCurve.js";
7
7
  export { AnimationCurve } from "../AnimationCurve.js";
8
8
  export { Animator } from "../Animator.js";
9
- export { AnimatorControllerBuilder } from "../AnimatorController.js";
9
+ export { AnimatorControllerBuilder } from "../AnimatorController.builder.js";
10
10
  export { AnimatorController } from "../AnimatorController.js";
11
11
  export { AudioListener } from "../AudioListener.js";
12
12
  export { AudioSource } from "../AudioSource.js";
13
- export { Avatar_POI } from "../avatar/Avatar_Brain_LookAt.js";
14
- export { Avatar_Brain_LookAt } from "../avatar/Avatar_Brain_LookAt.js";
15
- export { Avatar_MouthShapes } from "../avatar/Avatar_MouthShapes.js";
16
- export { Avatar_MustacheShake } from "../avatar/Avatar_MustacheShake.js";
17
- export { AvatarBlink_Simple } from "../avatar/AvatarBlink_Simple.js";
18
- export { AvatarEyeLook_Rotation } from "../avatar/AvatarEyeLook_Rotation.js";
19
- export { AvatarModel } from "../AvatarLoader.js";
20
- export { AvatarLoader } from "../AvatarLoader.js";
21
13
  export { AxesHelper } from "../AxesHelper.js";
22
14
  export { BasicIKConstraint } from "../BasicIKConstraint.js";
23
15
  export { BoxHelperComponent } from "../BoxHelperComponent.js";
@@ -168,10 +160,12 @@ export { PlayableDirector } from "../timeline/PlayableDirector.js";
168
160
  export { SignalAsset } from "../timeline/SignalAsset.js";
169
161
  export { SignalReceiverEvent } from "../timeline/SignalAsset.js";
170
162
  export { SignalReceiver } from "../timeline/SignalAsset.js";
163
+ export { TimelineBuilder } from "../timeline/TimelineBuilder.js";
171
164
  export { AnimationTrackHandler } from "../timeline/TimelineTracks.js";
172
165
  export { AudioTrackHandler } from "../timeline/TimelineTracks.js";
173
166
  export { MarkerTrackHandler } from "../timeline/TimelineTracks.js";
174
167
  export { SignalTrackHandler } from "../timeline/TimelineTracks.js";
168
+ export { ActivationTrackHandler } from "../timeline/TimelineTracks.js";
175
169
  export { ControlTrackHandler } from "../timeline/TimelineTracks.js";
176
170
  export { TransformGizmo } from "../TransformGizmo.js";
177
171
  export { BaseUIComponent } from "../ui/BaseUIComponent.js";
@@ -156,4 +156,7 @@ class VolumeParameterSerializer extends TypeSerializer {
156
156
  return parameter;
157
157
  }
158
158
  }
159
- new VolumeParameterSerializer();
159
+ /** @internal */
160
+ export function initVolumeParameterSerializer() {
161
+ new VolumeParameterSerializer();
162
+ }
@@ -4,7 +4,6 @@ import { isDevEnvironment } from '../../engine/debug/index.js';
4
4
  import { FrameEvent } from '../../engine/engine_context.js';
5
5
  import { isLocalNetwork } from '../../engine/engine_networking_utils.js';
6
6
  import { serializable } from '../../engine/engine_serialization.js';
7
- import type { GuidsMap } from '../../engine/engine_types.js';
8
7
  import { deepClone, delay, getParam } from '../../engine/engine_utils.js';
9
8
  import { Animator } from '../Animator.js';
10
9
  import { AudioListener } from '../AudioListener.js';
@@ -115,7 +114,15 @@ export class PlayableDirector extends Behaviour {
115
114
  * The timeline asset containing tracks, clips, and markers that this director will play.
116
115
  * Assign a timeline asset exported from Unity or Blender to enable playback.
117
116
  */
118
- playableAsset?: Models.TimelineAssetModel;
117
+ @serializable()
118
+ get playableAsset(): Models.TimelineAssetModel | undefined { return this._playableAsset; }
119
+ set playableAsset(value: Models.TimelineAssetModel | undefined) {
120
+ if (this._playableAsset !== value) {
121
+ this._playableAsset = value;
122
+ this._needsGraphRebuild = true;
123
+ }
124
+ }
125
+ private _playableAsset?: Models.TimelineAssetModel;
119
126
 
120
127
  /**
121
128
  * When true, the timeline starts playing automatically when the component awakens.
@@ -123,7 +130,7 @@ export class PlayableDirector extends Behaviour {
123
130
  * @default false
124
131
  */
125
132
  @serializable()
126
- playOnAwake?: boolean;
133
+ playOnAwake: boolean = false;
127
134
 
128
135
  /**
129
136
  * Determines how the timeline behaves when it reaches the end of its duration.
@@ -207,14 +214,10 @@ export class PlayableDirector extends Behaviour {
207
214
  onEnable() {
208
215
  if (debug) console.log("[Timeline] OnEnable", this.name, this.playOnAwake);
209
216
 
210
- for (const track of this._audioTracks) {
211
- track.onEnable?.();
212
- }
213
- for (const track of this._customTracks) {
214
- track.onEnable?.();
215
- }
216
- for (const track of this._animationTracks) {
217
- track.onEnable?.();
217
+ for (const tracks of this._allTracks) {
218
+ for (const track of tracks) {
219
+ track.onEnable?.();
220
+ }
218
221
  }
219
222
  if (this.playOnAwake) {
220
223
  this.play();
@@ -265,6 +268,7 @@ export class PlayableDirector extends Behaviour {
265
268
  this.resolveBindings();
266
269
  this.updateTimelineDuration();
267
270
  this.setupAndCreateTrackHandlers();
271
+ this._needsGraphRebuild = false;
268
272
  }
269
273
 
270
274
  /**
@@ -273,6 +277,8 @@ export class PlayableDirector extends Behaviour {
273
277
  */
274
278
  async play() {
275
279
  if (!this.isValid()) return;
280
+ // Ensure graph is built (handles the case where playableAsset is assigned after awake)
281
+ if (this._needsGraphRebuild) this.rebuildGraph();
276
282
  const pauseChanged = this._isPaused == true;
277
283
  this._isPaused = false;
278
284
  if (this._isPlaying) return;
@@ -343,6 +349,7 @@ export class PlayableDirector extends Behaviour {
343
349
  * Evaluate the timeline at the current time. This is useful when you want to manually update the timeline e.g. when the timeline is paused and you set `time` to a new value.
344
350
  */
345
351
  evaluate() {
352
+ if (this._needsGraphRebuild) this.rebuildGraph();
346
353
  this.internalEvaluate(true);
347
354
  }
348
355
 
@@ -391,6 +398,20 @@ export class PlayableDirector extends Behaviour {
391
398
  return this._markerTracks;
392
399
  }
393
400
 
401
+ /**
402
+ * @returns all activation tracks of the timeline
403
+ */
404
+ get activationTracks(): Tracks.ActivationTrackHandler[] {
405
+ return this._activationTracks;
406
+ }
407
+
408
+ /**
409
+ * @returns all tracks of the timeline
410
+ */
411
+ get tracks(): ReadonlyArray<Tracks.TrackHandler> {
412
+ return this._allTracks.flat();
413
+ }
414
+
394
415
  /**
395
416
  * Iterates over all markers of the timeline, optionally filtering by type
396
417
  *
@@ -412,19 +433,17 @@ export class PlayableDirector extends Behaviour {
412
433
  }
413
434
 
414
435
 
415
- private _guidsMap?: GuidsMap;
416
- /** @internal */
417
- resolveGuids(map: GuidsMap) {
418
- this._guidsMap = map;
419
- }
420
436
 
421
437
  // INTERNALS
422
438
 
439
+ private _needsGraphRebuild: boolean = false;
423
440
  private _isPlaying: boolean = false;
424
441
  private _internalUpdateRoutine: any;
425
442
  private _isPaused: boolean = false;
426
443
  /** internal, true during the time stop() is being processed */
427
444
  private _isStopping: boolean = false;
445
+ /** @internal Whether the current evaluate() was triggered by user code (not the internal update loop or stop/pause). */
446
+ _isUserEvaluation: boolean = false;
428
447
  private _time: number = 0;
429
448
  private _duration: number = 0;
430
449
  private _weight: number = 1;
@@ -433,6 +452,7 @@ export class PlayableDirector extends Behaviour {
433
452
  private readonly _signalTracks: Array<Tracks.SignalTrackHandler> = [];
434
453
  private readonly _markerTracks: Array<Tracks.MarkerTrackHandler> = [];
435
454
  private readonly _controlTracks: Array<Tracks.ControlTrackHandler> = [];
455
+ private readonly _activationTracks: Array<Tracks.ActivationTrackHandler> = [];
436
456
  private readonly _customTracks: Array<Tracks.TrackHandler> = [];
437
457
 
438
458
  private readonly _tracksArray: Array<Array<Tracks.TrackHandler>> = [];
@@ -443,6 +463,7 @@ export class PlayableDirector extends Behaviour {
443
463
  this._tracksArray.push(this._signalTracks);
444
464
  this._tracksArray.push(this._markerTracks);
445
465
  this._tracksArray.push(this._controlTracks);
466
+ this._tracksArray.push(this._activationTracks);
446
467
  this._tracksArray.push(this._customTracks);
447
468
  return this._tracksArray;
448
469
  }
@@ -503,60 +524,32 @@ export class PlayableDirector extends Behaviour {
503
524
 
504
525
  const time = this._time;
505
526
 
506
- for (const track of this.playableAsset!.tracks) {
507
- if (track.muted) continue;
508
- switch (track.type) {
509
- case Models.TrackType.Activation:
510
- // when the timeline is being disabled or stopped
511
- // then we want to leave objects active state as they were
512
- // see NE-3241
513
- // TODO: support all "post-playback-state" settings an activation track has, this is just "Leave as is"
514
- if (!called_by_user && !this._isPlaying) continue;
515
-
516
- for (let i = 0; i < track.outputs.length; i++) {
517
- const binding = track.outputs[i];
518
- if (typeof binding === "object") {
519
- let isActive: boolean = false;
520
- if (track.clips) {
521
- for (const clip of track.clips) {
522
- if (clip.start <= time && time <= clip.end) {
523
- isActive = true;
524
- }
525
- }
526
- }
527
- const obj = binding as Object3D;
528
- if (obj.visible !== undefined) {
529
- if (obj.visible !== isActive) {
530
- obj.visible = isActive;
531
- if (debug)
532
- console.warn(this.name, "set ActivationTrack-" + i, obj.name, isActive, time);
533
- }
534
- }
535
- }
536
- }
537
- break;
538
-
539
- }
540
- }
541
-
527
+ this._isUserEvaluation = called_by_user;
542
528
  for (const track of this._allTracks) {
543
529
  for (const handler of track) {
544
530
  // When timeline reaches the end "stop()" is called which is evaluating with time 0
545
531
  // We don't want to re-evaluate the animation then in case the timeline is blended with the Animator
546
532
  // e.g then the timeline animation at time 0 is 100% applied on top of the animator animation
547
-
548
533
  if (this._isStopping && handler instanceof Tracks.AnimationTrackHandler) {
549
534
  continue;
550
535
  }
551
536
  handler.evaluate(time);
552
537
  }
553
538
  }
539
+ this._isUserEvaluation = false;
554
540
  }
555
541
 
556
542
  private resolveBindings() {
557
543
  if (!this._clonedPlayableAsset) {
558
544
  this._clonedPlayableAsset = true;
559
- this.playableAsset = deepClone(this.playableAsset);
545
+ // Deep clone so each director owns its own copy of the asset data.
546
+ // Needed because NEEDLE_persistent_assets returns the same shared object for all references —
547
+ // without this, resolving guid strings below would mutate shared data.
548
+ // On instantiated clones this is skipped (_clonedPlayableAsset is copied as true)
549
+ // because the instantiate resolve system already created an independent copy.
550
+ this.playableAsset = deepClone(this.playableAsset, (_obj, _key, val) => {
551
+ return !(val?.isObject3D === true);
552
+ });
560
553
  }
561
554
 
562
555
  if (!this.playableAsset || !this.playableAsset.tracks) return;
@@ -569,15 +562,13 @@ export class PlayableDirector extends Behaviour {
569
562
 
570
563
  for (const track of this.playableAsset.tracks) {
571
564
  for (let i = track.outputs.length - 1; i >= 0; i--) {
572
- let binding = track.outputs[i];
565
+ const binding = track.outputs[i];
573
566
  if (typeof binding === "string") {
574
- if (this._guidsMap && this._guidsMap[binding])
575
- binding = this._guidsMap[binding];
576
567
  const obj = GameObject.findByGuid(binding, root);
577
568
  if (obj === null || typeof obj !== "object") {
578
569
  // if the binding is missing remove it to avoid unnecessary loops
579
570
  track.outputs.splice(i, 1);
580
- console.warn("Failed to resolve binding", binding, track.name, track.type);
571
+ console.warn(`[Timeline] Failed to resolve binding on track '${track.name}' of type '${track.type}' in director '${this.name}' with timeline asset '${this.playableAsset.name}' ('${binding}' not found in scene)`);
581
572
  }
582
573
  else {
583
574
  if (debug)
@@ -592,21 +583,20 @@ export class PlayableDirector extends Behaviour {
592
583
  continue;
593
584
  }
594
585
  // if the binding is missing remove it to avoid unnecessary loops
595
- if (track.type !== Models.TrackType.Audio && track.type !== Models.TrackType.Control && track.type !== Models.TrackType.Marker && track.type !== Models.TrackType.Signal)
596
- console.warn("Missing binding", binding, track.name, track.type, this.name, this.playableAsset.name);
586
+ if (track.type !== Models.TrackType.Audio && track.type !== Models.TrackType.Control && track.type !== Models.TrackType.Marker && track.type !== Models.TrackType.Signal) {
587
+ console.warn(`[Timeline] Missing binding on track '${track.name}' of type '${track.type}' in director '${this.name}' with timeline asset '${this.playableAsset.name}' (null binding)`);
588
+ }
597
589
  }
598
590
  }
599
591
  if (track.type === Models.TrackType.Control) {
600
592
  if (track.clips) {
601
593
  for (let i = 0; i < track.clips.length; i++) {
602
594
  const clip = track.clips[i];
603
- let binding = clip.asset.sourceObject;
595
+ const binding = clip.asset.sourceObject;
604
596
  if (typeof binding === "string") {
605
- if (this._guidsMap && this._guidsMap[binding])
606
- binding = this._guidsMap[binding];
607
597
  const obj = GameObject.findByGuid(binding, root);
608
598
  if (obj === null || typeof obj !== "object") {
609
- console.warn("Failed to resolve sourceObject binding", binding, track.name, clip);
599
+ console.warn(`[Timeline] Failed to resolve sourceObject binding on track '${track.name}' of type '${track.type}' in director '${this.name}' with timeline asset '${this.playableAsset.name}' ('${binding}' not found in scene)`);
610
600
  }
611
601
  else {
612
602
  if (debug)
@@ -649,6 +639,7 @@ export class PlayableDirector extends Behaviour {
649
639
  this._animationTracks.length = 0;
650
640
  this._audioTracks.length = 0;
651
641
  this._signalTracks.length = 0;
642
+ this._activationTracks.length = 0;
652
643
 
653
644
  if (!this.playableAsset) return;
654
645
  let audioListener: AudioListener | null = GameObject.findObjectOfType(AudioListener, this.context);
@@ -810,6 +801,12 @@ export class PlayableDirector extends Behaviour {
810
801
  handler.resolveSourceObjects(this.context);
811
802
  this._controlTracks.push(handler);
812
803
  }
804
+ else if (track.type === Models.TrackType.Activation) {
805
+ const handler = new Tracks.ActivationTrackHandler();
806
+ handler.director = this;
807
+ handler.track = track;
808
+ this._activationTracks.push(handler);
809
+ }
813
810
  }
814
811
  }
815
812
 
@@ -1,4 +1,5 @@
1
1
  import { serializable } from "../../engine/engine_serialization_decorator.js";
2
+ import { ISignalReceiver } from "../../engine/engine_types.js";
2
3
  import { getParam } from "../../engine/engine_utils.js";
3
4
  import { Behaviour } from "../Component.js";
4
5
  import { EventList } from "../EventList.js";
@@ -33,7 +34,9 @@ export class SignalReceiverEvent {
33
34
  * @category Animation and Sequencing
34
35
  * @group Components
35
36
  */
36
- export class SignalReceiver extends Behaviour {
37
+ export class SignalReceiver extends Behaviour implements ISignalReceiver {
38
+
39
+ readonly isSignalReceiver = true;
37
40
 
38
41
  private static receivers: { [key: string]: SignalReceiver[] } = {};
39
42