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

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 (243) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/components.needle.json +1 -1
  3. package/dist/{needle-engine.bundle-CvtELXh0.js → needle-engine.bundle-D-eWNCu1.js} +15969 -15550
  4. package/dist/needle-engine.bundle-D3ZUII8o.min.js +1733 -0
  5. package/dist/needle-engine.bundle-_rOpvUGL.umd.cjs +1733 -0
  6. package/dist/needle-engine.d.ts +746 -156
  7. package/dist/needle-engine.js +529 -529
  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/engine_audio.d.ts +68 -0
  16. package/lib/engine/engine_audio.js +172 -0
  17. package/lib/engine/engine_audio.js.map +1 -1
  18. package/lib/engine/engine_components.js +1 -1
  19. package/lib/engine/engine_components.js.map +1 -1
  20. package/lib/engine/engine_context.d.ts +1 -1
  21. package/lib/engine/engine_context.js +2 -2
  22. package/lib/engine/engine_context.js.map +1 -1
  23. package/lib/engine/engine_disposable.d.ts +171 -0
  24. package/lib/engine/engine_disposable.js +136 -0
  25. package/lib/engine/engine_disposable.js.map +1 -0
  26. package/lib/engine/engine_gameobject.d.ts +1 -10
  27. package/lib/engine/engine_gameobject.js +22 -120
  28. package/lib/engine/engine_gameobject.js.map +1 -1
  29. package/lib/engine/engine_gltf_builtin_components.js +7 -69
  30. package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
  31. package/lib/engine/engine_init.js +6 -6
  32. package/lib/engine/engine_init.js.map +1 -1
  33. package/lib/engine/engine_input.d.ts +1 -1
  34. package/lib/engine/engine_input.js +1 -1
  35. package/lib/engine/engine_input.js.map +1 -1
  36. package/lib/engine/engine_instantiate_resolve.d.ts +42 -0
  37. package/lib/engine/engine_instantiate_resolve.js +372 -0
  38. package/lib/engine/engine_instantiate_resolve.js.map +1 -0
  39. package/lib/engine/engine_license.js +1 -1
  40. package/lib/engine/engine_license.js.map +1 -1
  41. package/lib/engine/engine_mainloop_utils.js +5 -2
  42. package/lib/engine/engine_mainloop_utils.js.map +1 -1
  43. package/lib/engine/engine_networking.js +3 -1
  44. package/lib/engine/engine_networking.js.map +1 -1
  45. package/lib/engine/engine_networking_blob.js +1 -1
  46. package/lib/engine/engine_networking_blob.js.map +1 -1
  47. package/lib/engine/engine_physics_rapier.d.ts +11 -3
  48. package/lib/engine/engine_physics_rapier.js +88 -25
  49. package/lib/engine/engine_physics_rapier.js.map +1 -1
  50. package/lib/engine/engine_scenedata.js +2 -2
  51. package/lib/engine/engine_scenedata.js.map +1 -1
  52. package/lib/engine/engine_serialization_builtin_serializer.js +28 -5
  53. package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
  54. package/lib/engine/engine_serialization_core.d.ts +1 -0
  55. package/lib/engine/engine_serialization_core.js +7 -0
  56. package/lib/engine/engine_serialization_core.js.map +1 -1
  57. package/lib/engine/engine_types.d.ts +17 -9
  58. package/lib/engine/engine_types.js +1 -1
  59. package/lib/engine/engine_types.js.map +1 -1
  60. package/lib/engine/engine_util_decorator.js +7 -2
  61. package/lib/engine/engine_util_decorator.js.map +1 -1
  62. package/lib/engine/engine_utils.d.ts +1 -1
  63. package/lib/engine/engine_utils.js +19 -5
  64. package/lib/engine/engine_utils.js.map +1 -1
  65. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
  66. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js.map +1 -1
  67. package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +1 -1
  68. package/lib/engine/webcomponents/needle menu/needle-menu.js +1 -1
  69. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  70. package/lib/engine/webcomponents/needle-engine.d.ts +10 -4
  71. package/lib/engine/webcomponents/needle-engine.js +1 -1
  72. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  73. package/lib/engine/xr/NeedleXRSession.d.ts +3 -2
  74. package/lib/engine/xr/NeedleXRSession.js +50 -14
  75. package/lib/engine/xr/NeedleXRSession.js.map +1 -1
  76. package/lib/engine/xr/events.d.ts +1 -1
  77. package/lib/engine/xr/events.js.map +1 -1
  78. package/lib/engine-components/Animation.js +17 -16
  79. package/lib/engine-components/Animation.js.map +1 -1
  80. package/lib/engine-components/Animator.d.ts +6 -0
  81. package/lib/engine-components/Animator.js +17 -12
  82. package/lib/engine-components/Animator.js.map +1 -1
  83. package/lib/engine-components/AnimatorController.builder.d.ts +113 -0
  84. package/lib/engine-components/AnimatorController.builder.js +195 -0
  85. package/lib/engine-components/AnimatorController.builder.js.map +1 -0
  86. package/lib/engine-components/AnimatorController.d.ts +2 -119
  87. package/lib/engine-components/AnimatorController.js +31 -232
  88. package/lib/engine-components/AnimatorController.js.map +1 -1
  89. package/lib/engine-components/AudioSource.d.ts +19 -3
  90. package/lib/engine-components/AudioSource.js +121 -68
  91. package/lib/engine-components/AudioSource.js.map +1 -1
  92. package/lib/engine-components/Collider.d.ts +18 -9
  93. package/lib/engine-components/Collider.js +61 -14
  94. package/lib/engine-components/Collider.js.map +1 -1
  95. package/lib/engine-components/Component.d.ts +58 -6
  96. package/lib/engine-components/Component.js +77 -0
  97. package/lib/engine-components/Component.js.map +1 -1
  98. package/lib/engine-components/DragControls.d.ts +7 -0
  99. package/lib/engine-components/DragControls.js +19 -7
  100. package/lib/engine-components/DragControls.js.map +1 -1
  101. package/lib/engine-components/EventList.d.ts +31 -9
  102. package/lib/engine-components/EventList.js +37 -76
  103. package/lib/engine-components/EventList.js.map +1 -1
  104. package/lib/engine-components/Joints.d.ts +4 -2
  105. package/lib/engine-components/Joints.js +19 -3
  106. package/lib/engine-components/Joints.js.map +1 -1
  107. package/lib/engine-components/Light.js +9 -1
  108. package/lib/engine-components/Light.js.map +1 -1
  109. package/lib/engine-components/Networking.d.ts +1 -1
  110. package/lib/engine-components/Networking.js +1 -1
  111. package/lib/engine-components/OrbitControls.js +16 -11
  112. package/lib/engine-components/OrbitControls.js.map +1 -1
  113. package/lib/engine-components/RigidBody.d.ts +12 -4
  114. package/lib/engine-components/RigidBody.js +18 -4
  115. package/lib/engine-components/RigidBody.js.map +1 -1
  116. package/lib/engine-components/SeeThrough.js +2 -2
  117. package/lib/engine-components/SeeThrough.js.map +1 -1
  118. package/lib/engine-components/api.d.ts +1 -1
  119. package/lib/engine-components/api.js +1 -1
  120. package/lib/engine-components/api.js.map +1 -1
  121. package/lib/engine-components/codegen/components.d.ts +3 -9
  122. package/lib/engine-components/codegen/components.js +3 -9
  123. package/lib/engine-components/codegen/components.js.map +1 -1
  124. package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
  125. package/lib/engine-components/timeline/PlayableDirector.d.ts +16 -6
  126. package/lib/engine-components/timeline/PlayableDirector.js +63 -61
  127. package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
  128. package/lib/engine-components/timeline/SignalAsset.d.ts +3 -1
  129. package/lib/engine-components/timeline/SignalAsset.js +1 -0
  130. package/lib/engine-components/timeline/SignalAsset.js.map +1 -1
  131. package/lib/engine-components/timeline/TimelineBuilder.d.ts +247 -0
  132. package/lib/engine-components/timeline/TimelineBuilder.js +400 -0
  133. package/lib/engine-components/timeline/TimelineBuilder.js.map +1 -0
  134. package/lib/engine-components/timeline/TimelineModels.d.ts +2 -1
  135. package/lib/engine-components/timeline/TimelineModels.js +3 -0
  136. package/lib/engine-components/timeline/TimelineModels.js.map +1 -1
  137. package/lib/engine-components/timeline/TimelineTracks.d.ts +23 -0
  138. package/lib/engine-components/timeline/TimelineTracks.js +71 -13
  139. package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
  140. package/lib/engine-components/timeline/index.d.ts +2 -1
  141. package/lib/engine-components/timeline/index.js +2 -0
  142. package/lib/engine-components/timeline/index.js.map +1 -1
  143. package/lib/engine-components/ui/Canvas.d.ts +1 -1
  144. package/lib/engine-components/ui/Canvas.js +2 -8
  145. package/lib/engine-components/ui/Canvas.js.map +1 -1
  146. package/lib/engine-components/ui/Text.d.ts +1 -0
  147. package/lib/engine-components/ui/Text.js +10 -7
  148. package/lib/engine-components/ui/Text.js.map +1 -1
  149. package/lib/engine-components/web/CursorFollow.js +21 -12
  150. package/lib/engine-components/web/CursorFollow.js.map +1 -1
  151. package/lib/engine-components/webxr/WebXRImageTracking.js +4 -0
  152. package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
  153. package/package.json +2 -83
  154. package/plugins/common/worker.js +9 -4
  155. package/plugins/vite/asap.js +17 -8
  156. package/plugins/vite/dependencies.js +29 -0
  157. package/plugins/vite/dependency-watcher.js +2 -2
  158. package/plugins/vite/editor-connection.js +3 -3
  159. package/plugins/vite/local-files-core.js +3 -3
  160. package/plugins/vite/local-files-utils.d.ts +3 -1
  161. package/plugins/vite/local-files-utils.js +29 -5
  162. package/plugins/vite/reload.js +1 -1
  163. package/plugins/vite/server.js +2 -1
  164. package/src/engine/api.ts +7 -0
  165. package/src/engine/codegen/register_types.ts +2 -10
  166. package/src/engine/engine_audio.ts +184 -0
  167. package/src/engine/engine_components.ts +1 -1
  168. package/src/engine/engine_context.ts +3 -3
  169. package/src/engine/engine_disposable.ts +213 -0
  170. package/src/engine/engine_gameobject.ts +54 -159
  171. package/src/engine/engine_gltf_builtin_components.ts +7 -76
  172. package/src/engine/engine_init.ts +6 -6
  173. package/src/engine/engine_input.ts +1 -1
  174. package/src/engine/engine_instantiate_resolve.ts +407 -0
  175. package/src/engine/engine_license.ts +1 -1
  176. package/src/engine/engine_mainloop_utils.ts +5 -2
  177. package/src/engine/engine_networking.ts +3 -1
  178. package/src/engine/engine_networking_blob.ts +1 -1
  179. package/src/engine/engine_physics_rapier.ts +82 -27
  180. package/src/engine/engine_scenedata.ts +3 -3
  181. package/src/engine/engine_serialization_builtin_serializer.ts +32 -9
  182. package/src/engine/engine_serialization_core.ts +9 -0
  183. package/src/engine/engine_types.ts +22 -13
  184. package/src/engine/engine_util_decorator.ts +7 -2
  185. package/src/engine/engine_utils.ts +16 -5
  186. package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
  187. package/src/engine/webcomponents/needle menu/needle-menu.ts +1 -1
  188. package/src/engine/webcomponents/needle-engine.ts +10 -4
  189. package/src/engine/xr/NeedleXRSession.ts +48 -13
  190. package/src/engine/xr/events.ts +1 -1
  191. package/src/engine-components/Animation.ts +19 -16
  192. package/src/engine-components/Animator.ts +18 -11
  193. package/src/engine-components/AnimatorController.builder.ts +261 -0
  194. package/src/engine-components/AnimatorController.ts +19 -291
  195. package/src/engine-components/AudioSource.ts +130 -79
  196. package/src/engine-components/Collider.ts +66 -18
  197. package/src/engine-components/Component.ts +79 -9
  198. package/src/engine-components/DragControls.ts +18 -11
  199. package/src/engine-components/EventList.ts +45 -83
  200. package/src/engine-components/Joints.ts +20 -4
  201. package/src/engine-components/Light.ts +10 -2
  202. package/src/engine-components/Networking.ts +1 -1
  203. package/src/engine-components/OrbitControls.ts +18 -9
  204. package/src/engine-components/RigidBody.ts +18 -4
  205. package/src/engine-components/SeeThrough.ts +2 -2
  206. package/src/engine-components/api.ts +1 -1
  207. package/src/engine-components/codegen/components.ts +3 -9
  208. package/src/engine-components/timeline/PlayableDirector.ts +61 -64
  209. package/src/engine-components/timeline/SignalAsset.ts +4 -1
  210. package/src/engine-components/timeline/TimelineBuilder.ts +565 -0
  211. package/src/engine-components/timeline/TimelineModels.ts +5 -1
  212. package/src/engine-components/timeline/TimelineTracks.ts +74 -13
  213. package/src/engine-components/timeline/index.ts +2 -1
  214. package/src/engine-components/ui/Canvas.ts +2 -8
  215. package/src/engine-components/ui/Text.ts +12 -8
  216. package/src/engine-components/web/CursorFollow.ts +21 -13
  217. package/src/engine-components/webxr/WebXRImageTracking.ts +2 -0
  218. package/dist/needle-engine.bundle-1s2gOoKZ.min.js +0 -1732
  219. package/dist/needle-engine.bundle-j4nGJXCs.umd.cjs +0 -1732
  220. package/lib/engine-components/AvatarLoader.d.ts +0 -80
  221. package/lib/engine-components/AvatarLoader.js +0 -232
  222. package/lib/engine-components/AvatarLoader.js.map +0 -1
  223. package/lib/engine-components/avatar/AvatarBlink_Simple.d.ts +0 -11
  224. package/lib/engine-components/avatar/AvatarBlink_Simple.js +0 -77
  225. package/lib/engine-components/avatar/AvatarBlink_Simple.js.map +0 -1
  226. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.d.ts +0 -14
  227. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js +0 -69
  228. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js.map +0 -1
  229. package/lib/engine-components/avatar/Avatar_Brain_LookAt.d.ts +0 -29
  230. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js +0 -122
  231. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js.map +0 -1
  232. package/lib/engine-components/avatar/Avatar_MouthShapes.d.ts +0 -15
  233. package/lib/engine-components/avatar/Avatar_MouthShapes.js +0 -80
  234. package/lib/engine-components/avatar/Avatar_MouthShapes.js.map +0 -1
  235. package/lib/engine-components/avatar/Avatar_MustacheShake.d.ts +0 -9
  236. package/lib/engine-components/avatar/Avatar_MustacheShake.js +0 -30
  237. package/lib/engine-components/avatar/Avatar_MustacheShake.js.map +0 -1
  238. package/src/engine-components/AvatarLoader.ts +0 -264
  239. package/src/engine-components/avatar/AvatarBlink_Simple.ts +0 -70
  240. package/src/engine-components/avatar/AvatarEyeLook_Rotation.ts +0 -64
  241. package/src/engine-components/avatar/Avatar_Brain_LookAt.ts +0 -140
  242. package/src/engine-components/avatar/Avatar_MouthShapes.ts +0 -84
  243. package/src/engine-components/avatar/Avatar_MustacheShake.ts +0 -32
@@ -10,8 +10,8 @@ import { getBoundingBox, getTempVector, getWorldPosition, setWorldPosition } fro
10
10
  import { type IGameObject } from "../engine/engine_types.js";
11
11
  import { getParam } from "../engine/engine_utils.js";
12
12
  import { NeedleXRSession } from "../engine/engine_xr.js";
13
- import { Avatar_POI } from "./avatar/Avatar_Brain_LookAt.js";
14
13
  import { Behaviour, GameObject } from "./Component.js";
14
+ import { EventList } from "./EventList.js";
15
15
  import { UsageMarker } from "./Interactable.js";
16
16
  import { Rigidbody } from "./RigidBody.js";
17
17
  import { SyncedTransform } from "./SyncedTransform.js";
@@ -155,7 +155,19 @@ export class DragControls extends Behaviour implements IPointerEventHandler {
155
155
  @serializable()
156
156
  public showGizmo: boolean = false;
157
157
 
158
- /**
158
+ /** Invoked once when a drag begins (after the minimum drag distance threshold is met). */
159
+ @serializable(EventList)
160
+ dragStarted: EventList = new EventList();
161
+
162
+ /** Invoked every frame while the object is being dragged. */
163
+ @serializable(EventList)
164
+ dragUpdated: EventList = new EventList();
165
+
166
+ /** Invoked once when the last pointer is released and the drag ends. */
167
+ @serializable(EventList)
168
+ dragEnded: EventList = new EventList();
169
+
170
+ /**
159
171
  * Returns the object currently being dragged by this DragControls component, if any.
160
172
  * @returns The object being dragged or null if no object is currently dragged
161
173
  */
@@ -457,6 +469,7 @@ export class DragControls extends Behaviour implements IPointerEventHandler {
457
469
  if (!object) return;
458
470
 
459
471
  this._isDragging = true;
472
+ this.dragStarted?.invoke();
460
473
 
461
474
  const sync = GameObject.getComponentInChildren(object, SyncedTransform);
462
475
  if (debug) console.log("DRAG START", sync, object);
@@ -497,9 +510,10 @@ export class DragControls extends Behaviour implements IPointerEventHandler {
497
510
  const object = this._targetObject || this.gameObject;
498
511
 
499
512
  InstancingUtil.markDirty(object);
513
+ this.dragUpdated?.invoke();
500
514
  }
501
515
 
502
- /**
516
+ /**
503
517
  * Called when the last pointer has been removed from this object.
504
518
  * Cleans up drag state and applies final velocities to rigidbodies.
505
519
  * @param evt Pointer event data for the last pointer that was lifted
@@ -507,6 +521,7 @@ export class DragControls extends Behaviour implements IPointerEventHandler {
507
521
  private onLastDragEnd(evt: PointerEventData | null) {
508
522
  if (!this || !this._isDragging) return;
509
523
  this._isDragging = false;
524
+ this.dragEnded?.invoke();
510
525
  for (const rb of this._draggingRigidbodies) {
511
526
  rb.setVelocity(rb.smoothedVelocity.multiplyScalar(this.context.time.deltaTime));
512
527
  }
@@ -1484,11 +1499,6 @@ class LegacyDragVisualsHelper {
1484
1499
  }
1485
1500
  }
1486
1501
 
1487
- if (this._selected) {
1488
- // TODO move somewhere else
1489
- Avatar_POI.Remove(context, this._selected);
1490
- }
1491
-
1492
1502
  this._selected = newSelected;
1493
1503
  this._context = context;
1494
1504
  this._rbs.length = 0;
@@ -1508,9 +1518,6 @@ class LegacyDragVisualsHelper {
1508
1518
  return;
1509
1519
  }
1510
1520
 
1511
- // TODO move somewhere else
1512
- Avatar_POI.Add(context, this._selected, null);
1513
-
1514
1521
  this._groundOffsetFactor = 0;
1515
1522
  this._hasGroundPlane = true;
1516
1523
  this._groundOffset.set(0, 0, 0);
@@ -1,13 +1,17 @@
1
1
  import { isDevEnvironment } from "../engine/debug/index.js";
2
- import { InstantiateContext } from "../engine/engine_gameobject.js";
3
2
  import type { IComponent, IEventList } from "../engine/engine_types.js";
4
3
 
5
4
  const argumentsBuffer = new Array<any>();
6
5
 
7
6
  /**
8
- * CallInfo represents a single callback method that can be invoked by the {@link EventList}.
7
+ * CallInfo represents a single callback method that can be invoked by the {@link EventList}.
9
8
  */
10
9
  export class CallInfo {
10
+
11
+ /** @internal Used by the instantiate resolver to recursively resolve references */
12
+ static { CallInfo.prototype.$serializedTypes = { target: Object, arguments: Array }; }
13
+ declare $serializedTypes: Record<string, any>;
14
+
11
15
  /**
12
16
  * When the CallInfo is enabled it will be invoked when the EventList is invoked
13
17
  */
@@ -95,8 +99,7 @@ export class CallInfo {
95
99
  }
96
100
  }
97
101
 
98
- const isUpperCase = (string) => /^[A-Z]*$/.test(string);
99
-
102
+ /** @deprecated No longer automatically dispatched. Use `eventList.on()` directly instead. */
100
103
  export class EventListEvent<TArgs extends any> extends Event { //implements ArrayLike<T> {
101
104
  args?: TArgs;
102
105
  }
@@ -150,73 +153,13 @@ export class EventListEvent<TArgs extends any> extends Event { //implements Arra
150
153
  */
151
154
  export class EventList<TArgs extends any = any> implements IEventList {
152
155
 
156
+ /** @internal Used by the instantiate resolver to recursively resolve references */
157
+ static { EventList.prototype.$serializedTypes = { methods: Array }; }
158
+ declare $serializedTypes: Record<string, any>;
159
+
153
160
  /** checked during instantiate to create a new instance */
154
161
  readonly isEventList = true;
155
162
 
156
- /**
157
- * @internal Used by the Needle Engine instantiate call to remap the event listeners to the new instance
158
- */
159
- __internalOnInstantiate(ctx: InstantiateContext) {
160
- const newMethods = new Array<CallInfo>();
161
- for (let i = 0; i < this.methods.length; i++) {
162
- const method = this.methods[i];
163
- if (method.target instanceof Function) {
164
- // can not clone a function
165
- }
166
- else {
167
- const target = method.target as { uuid?: string };
168
- let key = target?.uuid;
169
- if ((target as IComponent)) {
170
- key = (target as IComponent).guid;
171
- }
172
- if (key) {
173
- const newTarget = ctx[key];
174
- if (newTarget) {
175
- // remap the arguments to the new instance (e.g. if an object is passed as an argument to the event list and this object has been cloned we want to remap it to the clone)
176
- const newArguments = method.arguments?.map(arg => {
177
- if (arg instanceof Object && arg.uuid) {
178
- return ctx[arg.uuid].clone;
179
- }
180
- else if ((arg as IComponent)?.isComponent) {
181
- return ctx[(arg as IComponent).guid].clone;
182
- }
183
- return arg;
184
- });
185
- newMethods.push(new CallInfo(newTarget.clone, method.methodName, newArguments, method.enabled));
186
- }
187
- else if (isDevEnvironment()) {
188
- console.warn("Could not find target for event listener");
189
- }
190
- }
191
- }
192
- }
193
- const newInstance = new EventList(newMethods);
194
- return newInstance;
195
- }
196
-
197
- private target?: object;
198
- private key?: string;
199
-
200
- // TODO: serialization should not take care of the args but instead give them to the eventlist directly
201
- // so we can handle passing them on here instead of in the serializer
202
- // this would also allow us to pass them on to the component EventTarget
203
-
204
- /** set an event target to try invoke the EventTarget dispatchEvent when this EventList is invoked */
205
- setEventTarget(key: string, target: object) {
206
- this.key = key;
207
- this.target = target;
208
- if (this.key !== undefined) {
209
- let temp = "";
210
- let foundFirstLetter = false;
211
- for (const c of this.key) {
212
- if (foundFirstLetter && isUpperCase(c))
213
- temp += "-";
214
- foundFirstLetter = true;
215
- temp += c.toLowerCase();
216
- }
217
- this.key = temp;
218
- }
219
- }
220
163
 
221
164
  /** How many callback methods are subscribed to this event */
222
165
  get listenerCount() { return this.methods?.length ?? 0; }
@@ -285,24 +228,9 @@ export class EventList<TArgs extends any = any> implements IEventList {
285
228
  this._methodsCopy.length = 0;
286
229
  this._methodsCopy.push(...this.methods);
287
230
 
288
- // first invoke all the methods that were subscribed to this eventlist
289
231
  for (const m of this._methodsCopy) {
290
232
  m.invoke(...args);
291
233
  }
292
-
293
-
294
- // then try to dispatch the event on the object that is owning this eventlist
295
- // with this we get automatic event listener support for unity events on all componnets
296
- // so example for a component with a click UnityEvent you can also subscribe to the component like this:
297
- // myComponent.addEventListener("click", args => {...")
298
- if (typeof this.target === "object" && typeof this.key === "string") {
299
- const fn = this.target["dispatchEvent"];
300
- if (typeof fn === "function") {
301
- const evt = new EventListEvent(this.key);
302
- evt.args = args;
303
- fn.call(this.target, evt);
304
- }
305
- }
306
234
  }
307
235
  finally {
308
236
  this._isInvoking = false;
@@ -313,12 +241,32 @@ export class EventList<TArgs extends any = any> implements IEventList {
313
241
 
314
242
  /** Add a new event listener to this event
315
243
  * @returns a function to remove the event listener
244
+ * @see {@link removeEventListener} for more details and return value information
245
+ * @see {@link off} for an alias with better readability when unsubscribing from events
246
+ * @example
247
+ * ```ts
248
+ * const off = myEvent.addEventListener(args => console.log("Clicked!", args));
249
+ * // later
250
+ * off();
251
+ * ```
316
252
  */
317
253
  addEventListener(callback: (args: TArgs) => void): Function {
318
254
  this.methods.push(new CallInfo(callback));
319
255
  return () => this.removeEventListener(callback);
320
256
  }
321
257
 
258
+ /**
259
+ * Alias for addEventListener for better readability when subscribing to events. You can use it like this:
260
+ * ```ts
261
+ * myEvent.on(args => console.log("Clicked!", args));
262
+ * ```
263
+ * @returns a function to remove the event listener
264
+ * @see {@link addEventListener} for more details and return value information
265
+ */
266
+ on(callback: (args: TArgs) => void): Function {
267
+ return this.addEventListener(callback);
268
+ }
269
+
322
270
  /**
323
271
  * Remove an event listener from this event.
324
272
  * @returns true if the event listener was found and removed, false otherwise
@@ -336,6 +284,20 @@ export class EventList<TArgs extends any = any> implements IEventList {
336
284
  return found;
337
285
  }
338
286
 
287
+ /**
288
+ * Alias for removeEventListener for better readability when unsubscribing from events. You can use it like this:
289
+ * ```ts
290
+ * const off = myEvent.on(args => console.log("Clicked!", args));
291
+ * // later
292
+ * off();
293
+ * ```
294
+ *
295
+ * @see {@link removeEventListener} for more details and return value information
296
+ */
297
+ off(callback: Function | null | undefined) {
298
+ return this.removeEventListener(callback);
299
+ }
300
+
339
301
  /**
340
302
  * Remove all event listeners from this event. Use with caution! This will remove all listeners!
341
303
  */
@@ -28,6 +28,7 @@ export abstract class Joint extends Behaviour {
28
28
  return this._rigidBody;
29
29
  }
30
30
  private _rigidBody: Rigidbody | null = null;
31
+ private _jointHandle: any = null;
31
32
 
32
33
 
33
34
  onEnable() {
@@ -36,14 +37,28 @@ export abstract class Joint extends Behaviour {
36
37
  this.startCoroutine(this.create());
37
38
  }
38
39
 
40
+ onDisable() {
41
+ if (this._jointHandle) {
42
+ this.context.physics.engine?.removeJoint(this._jointHandle);
43
+ this._jointHandle = null;
44
+ }
45
+ }
46
+
39
47
  private *create() {
40
48
  yield;
49
+ if (this._jointHandle) return;
41
50
  if (this.rigidBody && this.connectedBody && this.activeAndEnabled) {
42
- this.createJoint(this.rigidBody, this.connectedBody)
51
+ const result = this.createJoint(this.rigidBody, this.connectedBody);
52
+ if (result instanceof Promise) {
53
+ yield result.then(handle => this._jointHandle = handle);
54
+ }
55
+ else {
56
+ this._jointHandle = result;
57
+ }
43
58
  }
44
59
  }
45
60
 
46
- protected abstract createJoint(self: Rigidbody, other: Rigidbody);
61
+ protected abstract createJoint(self: Rigidbody, other: Rigidbody): any;
47
62
  }
48
63
 
49
64
  /**
@@ -70,7 +85,7 @@ export abstract class Joint extends Behaviour {
70
85
  export class FixedJoint extends Joint {
71
86
 
72
87
  protected createJoint(self: Rigidbody, other: Rigidbody) {
73
- this.context.physics.engine?.addFixedJoint(self, other);
88
+ return this.context.physics.engine?.addFixedJoint(self, other) ?? null;
74
89
  }
75
90
  }
76
91
 
@@ -110,7 +125,8 @@ export class HingeJoint extends Joint {
110
125
 
111
126
  protected createJoint(self: Rigidbody, other: Rigidbody) {
112
127
  if (this.axis && this.anchor)
113
- this.context.physics.engine?.addHingeJoint(self, other, this.anchor, this.axis);
128
+ return this.context.physics.engine?.addHingeJoint(self, other, this.anchor, this.axis) ?? null;
129
+ return null;
114
130
  }
115
131
 
116
132
  }
@@ -1,12 +1,12 @@
1
1
  import { CameraHelper, Color, DirectionalLight, DirectionalLightHelper, Light as ThreeLight, OrthographicCamera, PointLight, SpotLight, Vector3 } from "three";
2
2
 
3
3
  import { serializable } from "../engine/engine_serialization_decorator.js";
4
- import { FrameEvent } from "../engine/engine_setup.js";
5
4
  import { setWorldPositionXYZ } from "../engine/engine_three_utils.js";
6
5
  import type { ILight } from "../engine/engine_types.js";
7
6
  import { getParam } from "../engine/engine_utils.js";
8
7
  import type { NeedleXREventArgs } from "../engine/xr/api.js";
9
8
  import { Behaviour, GameObject } from "./Component.js";
9
+ import { isDevEnvironment } from "../engine/debug/index.js";
10
10
 
11
11
  // https://threejs.org/examples/webgl_shadowmap_csm.html
12
12
 
@@ -135,7 +135,10 @@ export class Light extends Behaviour implements ILight {
135
135
  this._type = value;
136
136
  break;
137
137
  default:
138
- throw new Error("Invalid light type: " + value);
138
+ if (debug || isDevEnvironment())
139
+ console.warn(`[Light] Unsupported light type: ${LightType[value]} (${value}) on '${this.name}'`);
140
+ this._type = "unsupported" as any;
141
+ break;
139
142
  }
140
143
  }
141
144
  private _type: ILight["type"] = "point";
@@ -474,6 +477,11 @@ export class Light extends Behaviour implements ILight {
474
477
  // const pointHelper = new PointLightHelper(pointLight, this.range, this.color);
475
478
  // scene.add(pointHelper);
476
479
  break;
480
+
481
+ default:
482
+ if (debug) console.warn(`[Light] Unsupported light type: ${LightType[this.type as any]} (${this.type}) on '${this.name}'`);
483
+ break;
484
+
477
485
  }
478
486
  }
479
487
 
@@ -37,7 +37,7 @@ const debug = getParam("debugnet");
37
37
  * @see {@link RoomEvents} for room lifecycle events
38
38
  * @see {@link isLocalNetwork} for local network detection
39
39
  * @link https://engine.needle.tools/docs/how-to-guides/networking/
40
- * @summary Networking configuration
40
+ * @summary Configures the websocket server URL for multiplayer networking
41
41
  * @category Networking
42
42
  * @group Components
43
43
  */
@@ -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) {
@@ -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";
@@ -172,7 +164,9 @@ export { AnimationTrackHandler } from "../timeline/TimelineTracks.js";
172
164
  export { AudioTrackHandler } from "../timeline/TimelineTracks.js";
173
165
  export { MarkerTrackHandler } from "../timeline/TimelineTracks.js";
174
166
  export { SignalTrackHandler } from "../timeline/TimelineTracks.js";
167
+ export { ActivationTrackHandler } from "../timeline/TimelineTracks.js";
175
168
  export { ControlTrackHandler } from "../timeline/TimelineTracks.js";
169
+ export { TimelineBuilder } from "../timeline/TimelineBuilder.js";
176
170
  export { TransformGizmo } from "../TransformGizmo.js";
177
171
  export { BaseUIComponent } from "../ui/BaseUIComponent.js";
178
172
  export { UIRootComponent } from "../ui/BaseUIComponent.js";