@needle-tools/engine 2.31.1-pre → 2.32.0-pre

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 (33) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/needle-engine.d.ts +111 -111
  3. package/dist/needle-engine.js +72 -72
  4. package/dist/needle-engine.js.map +3 -3
  5. package/dist/needle-engine.min.js +17 -17
  6. package/dist/needle-engine.min.js.map +3 -3
  7. package/lib/engine/debug/error_overlay.js +4 -4
  8. package/lib/engine/debug/error_overlay.js.map +1 -1
  9. package/lib/engine/engine_input.d.ts +87 -102
  10. package/lib/engine/engine_input.js +173 -99
  11. package/lib/engine/engine_input.js.map +1 -1
  12. package/lib/engine/engine_mainloop_utils.d.ts +2 -1
  13. package/lib/engine/engine_mainloop_utils.js +5 -2
  14. package/lib/engine/engine_mainloop_utils.js.map +1 -1
  15. package/lib/engine/engine_physics.d.ts +5 -1
  16. package/lib/engine/engine_physics.js +72 -22
  17. package/lib/engine/engine_physics.js.map +1 -1
  18. package/lib/engine/engine_setup.js +7 -3
  19. package/lib/engine/engine_setup.js.map +1 -1
  20. package/lib/engine-components/Component.d.ts +10 -3
  21. package/lib/engine-components/Component.js +98 -40
  22. package/lib/engine-components/Component.js.map +1 -1
  23. package/lib/engine-components/Rigidbody.d.ts +7 -4
  24. package/lib/engine-components/Rigidbody.js +43 -26
  25. package/lib/engine-components/Rigidbody.js.map +1 -1
  26. package/package.json +1 -1
  27. package/src/engine/debug/error_overlay.ts +3 -3
  28. package/src/engine/engine_input.ts +179 -103
  29. package/src/engine/engine_mainloop_utils.ts +6 -2
  30. package/src/engine/engine_physics.ts +86 -24
  31. package/src/engine/engine_setup.ts +8 -3
  32. package/src/engine-components/Component.ts +109 -40
  33. package/src/engine-components/RigidBody.ts +51 -29
@@ -79,9 +79,12 @@ abstract class GameObject extends THREE.Object3D implements THREE.Object3D {
79
79
 
80
80
  guid: string | undefined;
81
81
 
82
- public static setActive(go: THREE.Object3D, active: boolean) {
82
+ public static setActive(go: THREE.Object3D, active: boolean, processStart: boolean = true) {
83
83
  if (!go) return;
84
84
  go.visible = active;
85
+ main.updateActiveInHierarchyWithoutEventCall(go);
86
+ if (active && processStart)
87
+ main.processStart(Context.Current, go);
85
88
  }
86
89
 
87
90
  public static isActiveSelf(go: THREE.Object3D): boolean {
@@ -838,8 +841,13 @@ class Component implements EventTarget {
838
841
 
839
842
  onCollisionEnter?(col: Collision);
840
843
  onCollisionExit?(col: Collision);
844
+ onCollisionExitRaw?(col: Collision);
841
845
  onCollisionStay?(col: Collision);
842
846
 
847
+ onTriggerEnter?(col: Collision);
848
+ onTriggerStay?(col: Collision);
849
+ onTriggerExit?(col: Collision);
850
+
843
851
  startCoroutine(routine: Generator, evt: FrameEvent = FrameEvent.Update): Generator {
844
852
  return this.context.registerCoroutineUpdate(this, routine, evt);
845
853
  }
@@ -900,6 +908,7 @@ class Component implements EventTarget {
900
908
  this.__didEnable = false;
901
909
  this._collisionExitRoutine = undefined;
902
910
  this.onDisable();
911
+ this._collisions?.clear();
903
912
  }
904
913
 
905
914
  constructor() {
@@ -907,55 +916,115 @@ class Component implements EventTarget {
907
916
  }
908
917
 
909
918
  private _collisionExitRoutine: any;
910
- private _collisions: Map<Object3D, { col: Collision, frame: number }> | null = null;
919
+ private _collisions: Map<Object3D, { col: Collision, frame: number, exitFrame?: number }> | null = null;
920
+
921
+ private _triggerExitRoutine: any;
922
+ private _triggerCollisions: Map<Object3D, { col: Collision, frame: number, exitFrame?: number }> | null = null;
923
+
924
+ get collisionsCount() { return this._collisions?.size ?? 0; }
911
925
 
912
926
  private __internalResetsCachedPhysicsData() {
913
927
  this._collisionExitRoutine = null;
914
928
  this._collisions = null;
929
+ this._triggerExitRoutine = null;
930
+ this._triggerCollisions = null;
915
931
  }
916
932
 
917
- __internalHandleCollision(col: Collision) {
918
- if (this.onCollisionEnter || this.onCollisionExit || this.onCollisionStay) {
919
- const otherObject = col.gameObject;
920
- if (!this._collisions) this._collisions = new Map();
921
- if (this._collisions.has(otherObject)) {
922
- const cur = this._collisions.get(otherObject)!;
923
- cur.frame = this.context.time.frameCount;
924
- cur.col = col;
933
+ __internalHandleCollision(col: Collision, isTriggerCollision: boolean) {
934
+ if (isTriggerCollision) {
935
+ if (!this.onTriggerEnter && !this.onTriggerStay && !this.onTriggerExit) return;
936
+ }
937
+ else {
938
+ if (!this.onCollisionEnter && !this.onCollisionStay && !this.onCollisionExit) return;
939
+ }
940
+
941
+ const otherObject = col.gameObject;
942
+
943
+ // lazily create the maps
944
+ if (isTriggerCollision && !this._triggerCollisions) this._triggerCollisions = new Map();
945
+ else if (!this._collisions) this._collisions = new Map();
946
+
947
+ // select the correct map
948
+ const collection = isTriggerCollision ? this._triggerCollisions! : this._collisions!;
949
+
950
+ if (collection.has(otherObject)) {
951
+ const cur = collection.get(otherObject)!;
952
+ // console.log("STAY", this.name, this.context.time.frameCount)
953
+ // cur.exitFrame = undefined;
954
+ cur.frame = this.context.time.frameCount;
955
+ cur.col = col;
956
+ if (isTriggerCollision)
957
+ this.onTriggerStay?.(col);
958
+ else
925
959
  this.onCollisionStay?.call(this, col);
926
- }
927
- else {
928
- const entry = { col, frame: this.context.time.frameCount };
929
- this._collisions.set(otherObject, entry);
960
+ }
961
+ else {
962
+ // console.log("START", this.name);
963
+ const entry = { col, frame: this.context.time.frameCount };
964
+ collection.set(otherObject, entry);
965
+ if (isTriggerCollision)
966
+ this.onTriggerEnter?.(col);
967
+ else
930
968
  this.onCollisionEnter?.call(this, col);
931
- }
932
969
  }
933
970
  }
934
971
 
935
- sendExitCollisionEvent(obj : Object3D) {
936
- if(!this._collisions) return;
937
- const col = this._collisions.get(obj);
938
- if(!col) return;
939
- this.onCollisionExit?.call(this, col.col);
940
- this._collisions.delete(obj);
941
- }
942
-
943
- private __waitForCollisionExit() {
944
- if (this._collisionExitRoutine) return;
945
- // const self = this;
946
- // function* routine() {
947
- // while (self._collisions && self._collisions.size > 0) {
948
- // for (let ob of self._collisions.keys()) {
949
- // const entry = self._collisions!.get(ob)!;
950
- // if (self.context.time.frameCount - entry.frame > 1) {
951
- // self._collisions!.delete(ob);
952
- // self.onCollisionExit?.call(self, entry.col);
953
- // }
954
- // }
955
- // yield;
956
- // }
957
- // }
958
- // this._collisionExitRoutine = this.startCoroutine(routine(), FrameEvent.EarlyUpdate);
972
+ __internalHandleExitCollisionEvent(obj: Object3D, isTriggerCollision: boolean) {
973
+ if (isTriggerCollision) {
974
+ if (!this._triggerCollisions) return;
975
+ }
976
+ else {
977
+ if (!this._collisions) return;
978
+ }
979
+
980
+ const collection = isTriggerCollision ? this._triggerCollisions! : this._collisions!;
981
+
982
+ const collision = collection.get(obj);
983
+ if (!collision) return;
984
+ collision.exitFrame = this.context.time.frameCount;
985
+ // console.log("EXIT col", this.name, this.context.time.frameCount);
986
+ // if (this.onCollisionExit !== undefined)
987
+ this.__waitForCollisionExit(isTriggerCollision);
988
+ if (!isTriggerCollision)
989
+ this.onCollisionExitRaw?.call(this, collision.col);
990
+ // this._collisions.delete(obj);
991
+ }
992
+
993
+ private __waitForCollisionExit(isTriggerCollision: boolean) {
994
+ const routine = isTriggerCollision ? this._triggerExitRoutine : this._collisionExitRoutine;
995
+ if (routine) return;
996
+
997
+ const collection = isTriggerCollision ? this._triggerCollisions! : this._collisions!;
998
+ const self = this;
999
+ const frames = 10;
1000
+ function* delayedExitRoutine() {
1001
+ while (collection && collection.size > 0) {
1002
+ for (let other of collection.keys()) {
1003
+ const entry = collection!.get(other)!;
1004
+ if (entry.frame !== undefined && self.context.time.frameCount - entry.frame >= frames) {
1005
+ // console.log("EXIT real", self.name, entry.col.gameObject.name, collection);
1006
+ collection!.delete(other);
1007
+ if (isTriggerCollision)
1008
+ self.onTriggerExit?.(entry.col);
1009
+ else
1010
+ self.onCollisionExit?.call(self, entry.col);
1011
+ }
1012
+ }
1013
+ for (let i = 0; i < frames; i++)
1014
+ yield;
1015
+ }
1016
+ if (isTriggerCollision)
1017
+ self._triggerExitRoutine = undefined;
1018
+ else
1019
+ self._collisionExitRoutine = null;
1020
+ // console.log("DONE", self.name);
1021
+ }
1022
+
1023
+ const newRoutine = this.startCoroutine(delayedExitRoutine(), FrameEvent.OnAfterRender);
1024
+ if (isTriggerCollision)
1025
+ this._triggerExitRoutine = newRoutine;
1026
+ else
1027
+ this._collisionExitRoutine = newRoutine
959
1028
  }
960
1029
 
961
1030
 
@@ -1046,7 +1115,7 @@ class Component implements EventTarget {
1046
1115
  private static _forward: THREE.Vector3 = new THREE.Vector3(0, 0, 1);
1047
1116
  public get forward(): THREE.Vector3 {
1048
1117
 
1049
- return Component._forward.set(0, 0, 1).applyQuaternion(this.worldQuaternion);
1118
+ return Component._forward.set(0, 0, -1).applyQuaternion(this.worldQuaternion);
1050
1119
  }
1051
1120
 
1052
1121
 
@@ -5,6 +5,7 @@ import * as THREE from 'three'
5
5
  import { getWorldPosition } from "../engine/engine_three_utils";
6
6
  import { serializeable } from "../engine/engine_serialization_decorator";
7
7
  import { Watch } from "../engine/engine_utils";
8
+ import { Vector3 } from "three";
8
9
 
9
10
  export class Rigidbody extends Behaviour {
10
11
 
@@ -51,7 +52,7 @@ export class Rigidbody extends Behaviour {
51
52
  private _dirty: boolean = false;
52
53
 
53
54
  private _positionWatch?: Watch;
54
- // private _matrixWatch?: Watch;
55
+ private _matrixWatch?: Watch;
55
56
  private _setMatrix: THREE.Matrix4;
56
57
 
57
58
  constructor() {
@@ -64,11 +65,13 @@ export class Rigidbody extends Behaviour {
64
65
  this.currentVelocity = new THREE.Vector3();
65
66
  this._smoothedVelocity = new THREE.Vector3();
66
67
  this.lastWorldPosition = getWorldPosition(this.gameObject).clone();
68
+ this._matrixWatch = undefined;
69
+ this._positionWatch = undefined;
67
70
  }
68
71
 
69
- start() {
70
- this.setBodyFromGameObject();
71
- }
72
+ // start() {
73
+ // this.setBodyFromGameObject();
74
+ // }
72
75
 
73
76
  onEnable() {
74
77
  if (this._body) {
@@ -88,22 +91,13 @@ export class Rigidbody extends Behaviour {
88
91
  this._positionWatch.subscribeWrite(_ => {
89
92
  if (!this.context.physics.isUpdating && !this._ignoreChange) {
90
93
  this._dirty = true;
94
+ this._setMatrix.copy(this.gameObject.matrix);
91
95
  this._setMatrix.setPosition(this.gameObject.position);
92
96
  }
93
97
  })
94
-
95
- // this._matrixWatch = onChange(this.gameObject.matrix, "elements", (newValue, oldValue) => {
96
- // if (newValue !== oldValue) {
97
- // if (!this.context.physics.isUpdating && !this._ignoreChange) {
98
- // this.dirty = true;
99
- // this._setMatrix.copy(this.gameObject.matrix);
100
- // }
101
- // }
102
- // });
103
98
  }
104
99
 
105
100
  onDisable(): void {
106
- // this._matrixWatch?.u();
107
101
  if (this._body)
108
102
  this.context.physics.removeBody(this.gameObject, this._body, false);
109
103
  }
@@ -113,27 +107,23 @@ export class Rigidbody extends Behaviour {
113
107
  this.context.physics.removeBody(this.gameObject, this._body);
114
108
  }
115
109
 
116
- earlyUpdate() {
110
+ onBeforeRender() {
111
+ this._ignoreChange = true;
112
+ this.updateVelocity();
113
+
117
114
  if (this._dirty) {
118
- this._ignoreChange = true;
119
115
  this._dirty = false;
120
- // // console.log("RESET");
121
116
  this._setMatrix.decompose(this.gameObject.position, this.gameObject.quaternion, this.gameObject.scale);
122
117
  this.setBodyFromGameObject();
123
- this._ignoreChange = false;
124
118
  }
125
- }
126
- onBeforeRender() {
127
- this._ignoreChange = true;
128
- this.updateVelocity();
129
- // this._ignoreChange = true;
130
- // this._setMatrix.decompose(this.gameObject.position, this.gameObject.quaternion, this.gameObject.scale);
131
- // this.setBodyFromGameObject();
119
+
132
120
  this._ignoreChange = false;
133
121
  }
134
122
 
135
123
  initialize() {
136
- if (this._body) return;
124
+ if (this._body) {
125
+ return;
126
+ }
137
127
  const options = new BodyOptions();
138
128
  options.drag = this.drag;
139
129
  options.angularDrag = this.angularDrag;
@@ -149,8 +139,14 @@ export class Rigidbody extends Behaviour {
149
139
  this.body?.wakeUp();
150
140
  }
151
141
 
152
- public applyForce(vec: THREE.Vector3, rel: THREE.Vector3 | undefined) {
153
- this.body?.applyForce(new CANNON.Vec3(vec.x, vec.y, vec.z), rel ? new CANNON.Vec3(rel.x, rel.y, rel.z) : undefined);
142
+ public applyForce(vec: THREE.Vector3, rel?: THREE.Vector3) {
143
+ const force = new CANNON.Vec3(vec.x, vec.y, vec.z);
144
+ force.scale(1 / this.context.time.deltaTime, force);
145
+ this.body?.applyForce(force, rel ? new CANNON.Vec3(rel.x, rel.y, rel.z) : undefined);
146
+ }
147
+
148
+ public setForce(x: number, y: number, z: number) {
149
+ this.body?.force.set(x, y, z);
154
150
  }
155
151
 
156
152
  public getVelocity(): THREE.Vector3 {
@@ -159,13 +155,39 @@ export class Rigidbody extends Behaviour {
159
155
  return Rigidbody.tempPosition.set(0, 0, 0);
160
156
  }
161
157
 
162
- public setVelocity(x: number, y: number, z: number) {
158
+ public setVelocity(x: number | Vector3, y: number, z: number) {
163
159
  if (!this.body) return;
160
+ if (x instanceof Vector3) {
161
+ const vec = x;
162
+ x = vec.x;
163
+ y = vec.y;
164
+ z = vec.z;
165
+ }
164
166
  this.body.velocity.x = x / this.context.time.deltaTime;
165
167
  this.body.velocity.y = y / this.context.time.deltaTime;
166
168
  this.body.velocity.z = z / this.context.time.deltaTime;
167
169
  }
168
170
 
171
+ public getTorque(): THREE.Vector3 {
172
+ if (this.body)
173
+ return Rigidbody.tempPosition.set(this.body?.torque.x, this.body?.torque.y, this.body?.torque.z);
174
+ return Rigidbody.tempPosition.set(0, 0, 0);
175
+ }
176
+
177
+ public setTorque(x: number | Vector3, y: number, z: number) {
178
+ if (!this.body) return;
179
+ if (x instanceof Vector3) {
180
+ const vec = x;
181
+ x = vec.x;
182
+ y = vec.y;
183
+ z = vec.z;
184
+ }
185
+ this.body.torque.x = x / this.context.time.deltaTime;
186
+ this.body.torque.y = y / this.context.time.deltaTime;
187
+ this.body.torque.z = z / this.context.time.deltaTime;
188
+
189
+ }
190
+
169
191
  public get smoothedVelocity() { return this._smoothedVelocity; }
170
192
 
171
193
  public setAngularVelocity(x: number, y: number, z: number) {