@needle-tools/engine 3.37.3-alpha → 3.37.5-alpha

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 (51) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +5 -3
  3. package/dist/needle-engine.js +325 -248
  4. package/dist/needle-engine.light.js +1614 -1537
  5. package/dist/needle-engine.light.min.js +111 -98
  6. package/dist/needle-engine.light.umd.cjs +146 -133
  7. package/dist/needle-engine.min.js +43 -30
  8. package/dist/needle-engine.umd.cjs +64 -51
  9. package/lib/engine/engine_physics.d.ts +2 -2
  10. package/lib/engine/engine_physics.js +4 -4
  11. package/lib/engine/engine_physics.js.map +1 -1
  12. package/lib/engine/engine_physics_rapier.d.ts +24 -4
  13. package/lib/engine/engine_physics_rapier.js +33 -12
  14. package/lib/engine/engine_physics_rapier.js.map +1 -1
  15. package/lib/engine/engine_types.d.ts +27 -4
  16. package/lib/engine/engine_types.js.map +1 -1
  17. package/lib/engine/extensions/NEEDLE_lighting_settings.d.ts +0 -1
  18. package/lib/engine/extensions/NEEDLE_lighting_settings.js +0 -6
  19. package/lib/engine/extensions/NEEDLE_lighting_settings.js.map +1 -1
  20. package/lib/engine/webcomponents/needle menu/needle-menu.js +14 -1
  21. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  22. package/lib/engine-components/Collider.d.ts +25 -0
  23. package/lib/engine-components/Collider.js +25 -0
  24. package/lib/engine-components/Collider.js.map +1 -1
  25. package/lib/engine-components/OrbitControls.d.ts +16 -3
  26. package/lib/engine-components/OrbitControls.js +25 -9
  27. package/lib/engine-components/OrbitControls.js.map +1 -1
  28. package/lib/engine-components/ParticleSystem.d.ts +31 -1
  29. package/lib/engine-components/ParticleSystem.js +42 -1
  30. package/lib/engine-components/ParticleSystem.js.map +1 -1
  31. package/lib/engine-components/RigidBody.d.ts +3 -0
  32. package/lib/engine-components/RigidBody.js +5 -2
  33. package/lib/engine-components/RigidBody.js.map +1 -1
  34. package/lib/engine-components/SceneSwitcher.d.ts +22 -2
  35. package/lib/engine-components/SceneSwitcher.js +29 -3
  36. package/lib/engine-components/SceneSwitcher.js.map +1 -1
  37. package/lib/engine-components/SyncedTransform.js +3 -15
  38. package/lib/engine-components/SyncedTransform.js.map +1 -1
  39. package/package.json +1 -1
  40. package/src/engine/codegen/register_types.ts +2 -2
  41. package/src/engine/engine_physics.ts +4 -4
  42. package/src/engine/engine_physics_rapier.ts +48 -14
  43. package/src/engine/engine_types.ts +29 -6
  44. package/src/engine/extensions/NEEDLE_lighting_settings.ts +0 -5
  45. package/src/engine/webcomponents/needle menu/needle-menu.ts +14 -1
  46. package/src/engine-components/Collider.ts +27 -4
  47. package/src/engine-components/OrbitControls.ts +29 -11
  48. package/src/engine-components/ParticleSystem.ts +44 -4
  49. package/src/engine-components/RigidBody.ts +5 -2
  50. package/src/engine-components/SceneSwitcher.ts +45 -5
  51. package/src/engine-components/SyncedTransform.ts +4 -17
@@ -35,6 +35,7 @@ export enum SubEmitterType {
35
35
  Manual = 4,
36
36
  }
37
37
 
38
+ /** @internal */
38
39
  export class ParticleSystemRenderer extends Behaviour {
39
40
 
40
41
  @serializable()
@@ -88,7 +89,7 @@ export class ParticleSystemRenderer extends Behaviour {
88
89
  // don't modify the assigned material
89
90
  material = material.clone();
90
91
  material.side = BackSide;
91
- if(trailEnabled) this.trailMaterial = material;
92
+ if (trailEnabled) this.trailMaterial = material;
92
93
  else this.particleMaterial = material;
93
94
  }
94
95
  }
@@ -642,6 +643,11 @@ class ParticlesEmissionState implements EmissionState {
642
643
  waitEmiting: number = 0;
643
644
  }
644
645
 
646
+ /**
647
+ * The ParticleSystem component efficiently handles the rendering of particles.
648
+ *
649
+ * You can add custom behaviours to the particle system to fully customize the behaviour of the particles. See {@link ParticleSystemBaseBehaviour} and {@link ParticleSystem.addBehaviour} for more information.
650
+ */
645
651
  export class ParticleSystem extends Behaviour implements IParticleSystem {
646
652
 
647
653
  play(includeChildren: boolean = false) {
@@ -838,8 +844,23 @@ export class ParticleSystem extends Behaviour implements IParticleSystem {
838
844
  return this._isUsedAsSubsystem;
839
845
  }
840
846
 
841
- /** Add a custom quarks behaviour to the particle system. You can add a quarks.Behaviour type.
842
- * @link https://github.com/Alchemist0823/three.quarks
847
+ /** Add a custom quarks behaviour to the particle system.
848
+ * You can add a quarks.Behaviour type or derive from {@link ParticleSystemBaseBehaviour}
849
+ * @link https://github.com/Alchemist0823/three.quarks
850
+ * @example
851
+ * ```typescript
852
+ * class MyBehaviour extends ParticleSystemBaseBehaviour {
853
+ * initialize(particle: Particle) {
854
+ * // initialize the particle
855
+ * }
856
+ * update(particle: Particle, delta: number) {
857
+ * // do something with the particle
858
+ * }
859
+ * }
860
+ *
861
+ * const system = gameObject.getComponent(ParticleSystem);
862
+ * system.addBehaviour(new MyBehaviour());
863
+ * ```
843
864
  */
844
865
  addBehaviour(particleSystemBehaviour: Behavior | ParticleSystemBaseBehaviour): boolean {
845
866
  if (!this._particleSystem) {
@@ -852,6 +873,19 @@ export class ParticleSystem extends Behaviour implements IParticleSystem {
852
873
  this._particleSystem.addBehavior(particleSystemBehaviour);
853
874
  return true;
854
875
  }
876
+ /** Remove a custom quarks behaviour from the particle system. **/
877
+ removeBehaviour(particleSystemBehaviour: Behavior | ParticleSystemBaseBehaviour): boolean {
878
+ if (!this._particleSystem) {
879
+ return false;
880
+ }
881
+ const behaviours = this._particleSystem.behaviors;
882
+ const index = behaviours.indexOf(particleSystemBehaviour);
883
+ if (index !== -1) {
884
+ behaviours.splice(index, 1);
885
+ return true;
886
+ }
887
+ return true;
888
+ }
855
889
  /** Removes all behaviours from the particle system
856
890
  * **Note:** this will also remove the default behaviours like SizeBehaviour, ColorBehaviour etc.
857
891
  */
@@ -919,6 +953,7 @@ export class ParticleSystem extends Behaviour implements IParticleSystem {
919
953
  }
920
954
  private _subEmitterSystems?: SubEmitterSystem[];
921
955
 
956
+ /** @internal */
922
957
  onAfterDeserialize(_) {
923
958
  // doing this here to get a chance to resolve the subemitter guid
924
959
  if (this._subEmitterSystems && Array.isArray(this._subEmitterSystems)) {
@@ -928,6 +963,7 @@ export class ParticleSystem extends Behaviour implements IParticleSystem {
928
963
  }
929
964
  }
930
965
 
966
+ /** @internal */
931
967
  awake(): void {
932
968
  this._worldPositionFrame = -1;
933
969
 
@@ -976,11 +1012,13 @@ export class ParticleSystem extends Behaviour implements IParticleSystem {
976
1012
  }
977
1013
  }
978
1014
 
1015
+ /** @internal */
979
1016
  start() {
980
1017
  this.addSubParticleSystems();
981
1018
  this.updateLayers();
982
1019
  }
983
1020
 
1021
+ /** @internal */
984
1022
  onDestroy(): void {
985
1023
  this._container?.removeFromParent();
986
1024
  this._batchSystem?.removeFromParent();
@@ -988,6 +1026,7 @@ export class ParticleSystem extends Behaviour implements IParticleSystem {
988
1026
  this._particleSystem?.dispose();
989
1027
  }
990
1028
 
1029
+ /** @internal */
991
1030
  onEnable() {
992
1031
  if (!this.main) return;
993
1032
  if (this.inheritVelocity)
@@ -1004,6 +1043,7 @@ export class ParticleSystem extends Behaviour implements IParticleSystem {
1004
1043
  this._batchSystem.visible = false;
1005
1044
  }
1006
1045
 
1046
+ /** @internal */
1007
1047
  onBeforeRender() {
1008
1048
  if (!this.main) return;
1009
1049
  if (this._didPreWarm === false && this.main?.prewarm === true) {
@@ -1143,7 +1183,7 @@ export class ParticleSystem extends Behaviour implements IParticleSystem {
1143
1183
  }
1144
1184
 
1145
1185
 
1146
-
1186
+ /** @internal */
1147
1187
  export class SubEmitterSystem {
1148
1188
 
1149
1189
  particleSystem?: ParticleSystem;
@@ -167,8 +167,11 @@ export class Rigidbody extends Behaviour implements IRigidbody {
167
167
  @serializable()
168
168
  useGravity: boolean = true;
169
169
 
170
- @serializable()
171
- centerOfMass: Vector3 = new Vector3();
170
+ /**
171
+ * The center of mass is the point around which the mass of the rigid-body is evenly distributed. It is used to compute the torque applied to the rigid-body when forces are applied to it.
172
+ */
173
+ @serializable(Vector3)
174
+ centerOfMass: Vector3 = new Vector3(0, 0, 0);
172
175
 
173
176
  /**
174
177
  * Constraints are used to lock the position or rotation of an object in a specific axis.
@@ -43,7 +43,23 @@ export type LoadSceneEvent = {
43
43
  index: number;
44
44
  }
45
45
 
46
- /** The ISceneEventListener is called by the SceneSwitcher when a scene is loaded or unloaded. It must be added to the root object of your scene */
46
+ /**
47
+ * The ISceneEventListener is called by the {@link SceneSwitcher} when a scene is loaded or unloaded.
48
+ * It must be added to the root object of your scene (that is being loaded) or on the same object as the SceneSwitcher
49
+ * It can be used to e.g. smooth the transition between scenes or to load additional content when a scene is loaded.
50
+ * @example
51
+ * ```ts
52
+ * import { ISceneEventListener } from "@needle-tools/engine";
53
+ *
54
+ * // Add this component to the root object of a scene loaded by a SceneSwitcher or to the same object as the SceneSwitcher
55
+ * export class MySceneListener implements ISceneEventListener {
56
+ * async sceneOpened(sceneSwitcher: SceneSwitcher) {
57
+ * console.log("Scene opened", sceneSwitcher.currentlyLoadedScene?.uri);
58
+ * }
59
+ * }
60
+ * ```
61
+ *
62
+ **/
47
63
  export interface ISceneEventListener {
48
64
  /** Called when the scene is loaded and added */
49
65
  sceneOpened?(sceneSwitcher: SceneSwitcher): Promise<void>
@@ -60,6 +76,9 @@ export interface ISceneEventListener {
60
76
  * - [Needle Website](https://needle.tools)
61
77
  * - [Songs Of Cultures](https://app.songsofcultures.com)
62
78
  *
79
+ * ### Interfaces
80
+ * Use the {@link ISceneEventListener} interface to listen to scene open and closing events with the ability to modify transitions and stall the scene loading process.
81
+ *
63
82
  * ### Events
64
83
  * - `loadscene-start`: Called when a scene starts loading
65
84
  * - `loadscene-finished`: Called when a scene finished loading
@@ -438,7 +457,8 @@ export class SceneSwitcher extends Behaviour {
438
457
  }
439
458
 
440
459
  private _currentlyLoadingScene?: AssetReference;
441
- async __internalSwitchScene(scene: AssetReference): Promise<boolean> {
460
+ /** @internal */
461
+ private async __internalSwitchScene(scene: AssetReference): Promise<boolean> {
442
462
 
443
463
  if (this._currentScene) {
444
464
  if (debug) console.log("UNLOAD", scene.uri)
@@ -591,15 +611,25 @@ export class SceneSwitcher extends Behaviour {
591
611
  await this._loadingScenePromise;
592
612
  if (this._isCurrentlyLoading && this.loadingScene?.asset) {
593
613
  if (debug) console.log("Add loading scene", this.loadingScene.uri, this.loadingScene.asset)
594
- const obj = this.loadingScene.asset as any as Object3D;
595
- GameObject.add(obj, this.gameObject);
596
- const sceneListener = this.tryGetSceneEventListener(obj);
614
+ const loadingScene = this.loadingScene.asset as any as Object3D;
615
+ GameObject.add(loadingScene, this.gameObject);
616
+ const sceneListener = this.tryGetSceneEventListener(loadingScene);
597
617
  if (sceneListener?.sceneOpened) {
598
618
  const res = sceneListener.sceneOpened(this);
599
619
  if (res instanceof Promise) await res;
600
620
  }
601
621
  }
602
622
  }
623
+ // Invoke the event on a loading listener on the same object as the scene switcher
624
+ if (this._isCurrentlyLoading) {
625
+ const listener = this.tryGetSceneEventListener(this.gameObject);
626
+ if (listener) {
627
+ if (listener.sceneOpened) {
628
+ const res = listener.sceneOpened(this);
629
+ if (res instanceof Promise) await res;
630
+ }
631
+ }
632
+ }
603
633
  }
604
634
  private async onEndLoading() {
605
635
  this._isCurrentlyLoading = false;
@@ -614,6 +644,16 @@ export class SceneSwitcher extends Behaviour {
614
644
  }
615
645
  GameObject.remove(obj);
616
646
  }
647
+ // Invoke the event on a loading listener on the same object as the scene switcher
648
+ if (!this._isCurrentlyLoading) {
649
+ const listener = this.tryGetSceneEventListener(this.gameObject);
650
+ if (listener) {
651
+ if (listener.sceneClosing) {
652
+ const res = listener.sceneClosing();
653
+ if (res instanceof Promise) await res;
654
+ }
655
+ }
656
+ }
617
657
  }
618
658
 
619
659
  private tryGetSceneEventListener(obj: Object3D, level: number = 0): ISceneEventListener | null {
@@ -282,22 +282,14 @@ export class SyncedTransform extends Behaviour {
282
282
  this.lastWorldRotation.copy(wr);
283
283
 
284
284
 
285
- // if (this._model.isOwned === false && this.autoOwnership) {
286
- // this.requestOwnership();
287
- // }
288
-
289
285
  if (!this._model) return;
290
- // only run if we are the owner
286
+
291
287
  if (!this._model || this._model.hasOwnership === undefined || !this._model.hasOwnership) {
292
- if (this.rb) {
293
- this.rb.isKinematic = this._model.isOwned ?? false;
294
- this.rb.setVelocity(0, 0, 0);
295
- }
288
+ // if we're not the owner of this synced transform then don't send any data
296
289
  return;
297
290
  }
298
291
 
299
292
  // local user is owner:
300
-
301
293
  if (this.rb) {
302
294
  if (this._wasKinematic !== undefined) {
303
295
  if (debug)
@@ -305,13 +297,8 @@ export class SyncedTransform extends Behaviour {
305
297
  this.rb.isKinematic = this._wasKinematic;
306
298
  }
307
299
 
308
- // hacky reset if too far off
309
- if (this.gameObject.position.distanceTo(new Vector3(0, 0, 0)) > 1000) {
310
- if (debug)
311
- console.log("RESET", this.name)
312
- this.gameObject.position.set(0, 1, 0);
313
- this.rb.setVelocity(0, 0, 0);
314
- }
300
+ // TODO: if the SyncedTransform has a dynamic rigidbody we should probably synchronize the Rigidbody's properties (velocity etc)
301
+ // Or the Rigidbody should be synchronized separately in which case the SyncedTransform should be passive
315
302
  }
316
303
 
317
304
  const updateInterval = 10;