@needle-tools/engine 2.36.0-pre → 2.38.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.
- package/CHANGELOG.md +33 -0
- package/dist/needle-engine.d.ts +248 -151
- package/dist/needle-engine.js +451 -437
- package/dist/needle-engine.js.map +4 -4
- package/dist/needle-engine.min.js +82 -82
- package/dist/needle-engine.min.js.map +4 -4
- package/lib/engine/api.d.ts +1 -0
- package/lib/engine/api.js +1 -0
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/debug/debug.d.ts +1 -0
- package/lib/engine/debug/debug.js +3 -0
- package/lib/engine/debug/debug.js.map +1 -1
- package/lib/engine/engine_addressables.d.ts +3 -1
- package/lib/engine/engine_addressables.js +12 -5
- package/lib/engine/engine_addressables.js.map +1 -1
- package/lib/engine/engine_element.js +3 -2
- package/lib/engine/engine_element.js.map +1 -1
- package/lib/engine/engine_element_overlay.js +4 -3
- package/lib/engine/engine_element_overlay.js.map +1 -1
- package/lib/engine/engine_gameobject.js +2 -1
- package/lib/engine/engine_gameobject.js.map +1 -1
- package/lib/engine/engine_input.d.ts +2 -0
- package/lib/engine/engine_input.js +14 -3
- package/lib/engine/engine_input.js.map +1 -1
- package/lib/engine/engine_physics.d.ts +35 -46
- package/lib/engine/engine_physics.js +479 -386
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_physics.types.d.ts +23 -0
- package/lib/engine/engine_physics.types.js +27 -0
- package/lib/engine/engine_physics.types.js.map +1 -0
- package/lib/engine/engine_serialization_core.d.ts +3 -0
- package/lib/engine/engine_serialization_core.js +5 -0
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_setup.d.ts +7 -1
- package/lib/engine/engine_setup.js +13 -3
- package/lib/engine/engine_setup.js.map +1 -1
- package/lib/engine/engine_types.d.ts +45 -26
- package/lib/engine/engine_types.js +24 -37
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine/engine_util_decorator.d.ts +6 -0
- package/lib/engine/engine_util_decorator.js +54 -0
- package/lib/engine/engine_util_decorator.js.map +1 -0
- package/lib/engine/engine_utils.d.ts +1 -1
- package/lib/engine/engine_utils.js +1 -1
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_gameobject_data.js +2 -0
- package/lib/engine/extensions/NEEDLE_gameobject_data.js.map +1 -1
- package/lib/engine-components/Animation.d.ts +7 -5
- package/lib/engine-components/Animation.js +7 -7
- package/lib/engine-components/Animation.js.map +1 -1
- package/lib/engine-components/AnimatorController.js +14 -7
- package/lib/engine-components/AnimatorController.js.map +1 -1
- package/lib/engine-components/BoxHelperComponent.js +1 -0
- package/lib/engine-components/BoxHelperComponent.js.map +1 -1
- package/lib/engine-components/Camera.d.ts +1 -0
- package/lib/engine-components/Camera.js +20 -5
- package/lib/engine-components/Camera.js.map +1 -1
- package/lib/engine-components/CharacterController.d.ts +31 -0
- package/lib/engine-components/CharacterController.js +167 -0
- package/lib/engine-components/CharacterController.js.map +1 -0
- package/lib/engine-components/Collider.d.ts +16 -5
- package/lib/engine-components/Collider.js +45 -23
- package/lib/engine-components/Collider.js.map +1 -1
- package/lib/engine-components/Component.d.ts +6 -15
- package/lib/engine-components/Component.js +7 -112
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/DragControls.js +9 -6
- package/lib/engine-components/DragControls.js.map +1 -1
- package/lib/engine-components/Light.d.ts +2 -0
- package/lib/engine-components/Light.js +13 -2
- package/lib/engine-components/Light.js.map +1 -1
- package/lib/engine-components/NavMesh.d.ts +0 -5
- package/lib/engine-components/NavMesh.js +100 -10
- package/lib/engine-components/NavMesh.js.map +1 -1
- package/lib/engine-components/NestedGltf.js +2 -0
- package/lib/engine-components/NestedGltf.js.map +1 -1
- package/lib/engine-components/Renderer.js +4 -0
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/RigidBody.d.ts +45 -25
- package/lib/engine-components/RigidBody.js +290 -142
- package/lib/engine-components/RigidBody.js.map +1 -1
- package/lib/engine-components/SmoothFollow.d.ts +2 -1
- package/lib/engine-components/SmoothFollow.js +25 -17
- package/lib/engine-components/SmoothFollow.js.map +1 -1
- package/lib/engine-components/SpatialTrigger.js +1 -1
- package/lib/engine-components/SpatialTrigger.js.map +1 -1
- package/lib/engine-components/SpectatorCamera.d.ts +1 -0
- package/lib/engine-components/SpectatorCamera.js +9 -2
- package/lib/engine-components/SpectatorCamera.js.map +1 -1
- package/lib/engine-components/SpringJoint.d.ts +0 -13
- package/lib/engine-components/SpringJoint.js +42 -41
- package/lib/engine-components/SpringJoint.js.map +1 -1
- package/lib/engine-components/VideoPlayer.js.map +1 -1
- package/lib/engine-components/WebXR.d.ts +1 -0
- package/lib/engine-components/WebXR.js +13 -6
- package/lib/engine-components/WebXR.js.map +1 -1
- package/lib/engine-components/WebXRController.js +12 -6
- package/lib/engine-components/WebXRController.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +4 -3
- package/lib/engine-components/codegen/components.js +4 -3
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/package.json +3 -4
- package/src/engine/api.ts +2 -1
- package/src/engine/codegen/register_types.js +16 -12
- package/src/engine/debug/debug.ts +4 -0
- package/src/engine/dist/engine_physics.js +739 -0
- package/src/engine/dist/engine_setup.js +777 -0
- package/src/engine/engine_addressables.ts +18 -8
- package/src/engine/engine_element.ts +3 -2
- package/src/engine/engine_element_overlay.ts +4 -3
- package/src/engine/engine_gameobject.ts +4 -4
- package/src/engine/engine_input.ts +12 -3
- package/src/engine/engine_physics.ts +492 -418
- package/src/engine/engine_physics.types.ts +28 -0
- package/src/engine/engine_serialization_core.ts +8 -1
- package/src/engine/engine_setup.ts +31 -18
- package/src/engine/engine_types.ts +83 -56
- package/src/engine/engine_util_decorator.ts +69 -0
- package/src/engine/engine_utils.ts +3 -3
- package/src/engine/extensions/NEEDLE_gameobject_data.ts +2 -0
- package/src/engine-components/Animation.ts +18 -12
- package/src/engine-components/AnimatorController.ts +16 -11
- package/src/engine-components/BoxHelperComponent.ts +1 -0
- package/src/engine-components/Camera.ts +21 -4
- package/src/engine-components/CharacterController.ts +171 -0
- package/src/engine-components/Collider.ts +49 -39
- package/src/engine-components/Component.ts +15 -130
- package/src/engine-components/DragControls.ts +9 -5
- package/src/engine-components/Light.ts +17 -3
- package/src/engine-components/NavMesh.ts +114 -115
- package/src/engine-components/NestedGltf.ts +2 -0
- package/src/engine-components/Renderer.ts +5 -1
- package/src/engine-components/RigidBody.ts +292 -149
- package/src/engine-components/SmoothFollow.ts +21 -18
- package/src/engine-components/SpatialTrigger.ts +1 -1
- package/src/engine-components/SpectatorCamera.ts +10 -2
- package/src/engine-components/SpringJoint.ts +41 -41
- package/src/engine-components/VideoPlayer.ts +1 -2
- package/src/engine-components/WebXR.ts +15 -6
- package/src/engine-components/WebXRController.ts +16 -7
- package/src/engine-components/codegen/components.ts +4 -3
- package/src/engine-components/dist/CharacterController.js +123 -0
- package/src/engine-components/dist/RigidBody.js +458 -0
|
@@ -1,234 +1,377 @@
|
|
|
1
1
|
import { Behaviour } from "./Component";
|
|
2
|
-
import { BodyOptions } from '../engine/engine_physics'
|
|
3
|
-
import * as CANNON from 'cannon-es'
|
|
4
2
|
import * as THREE from 'three'
|
|
5
3
|
import { getWorldPosition } from "../engine/engine_three_utils";
|
|
6
4
|
import { serializeable } from "../engine/engine_serialization_decorator";
|
|
7
5
|
import { Watch } from "../engine/engine_utils";
|
|
8
|
-
import { Vector3 } from "three";
|
|
6
|
+
import { Object3D, Vector3 } from "three";
|
|
9
7
|
import { IRigidbody } from "../engine/engine_types";
|
|
8
|
+
import { CollisionDetectionMode, RigidbodyConstraints } from "../engine/engine_physics.types";
|
|
9
|
+
import { validate } from "../engine/engine_util_decorator";
|
|
10
|
+
import { Context, FrameEvent } from "../engine/engine_setup";
|
|
11
|
+
|
|
12
|
+
class TransformWatch {
|
|
13
|
+
|
|
14
|
+
get isDirty(): boolean {
|
|
15
|
+
return this.positionChanged || this.rotationChanged;
|
|
16
|
+
}
|
|
17
|
+
positionChanged: boolean = false;
|
|
18
|
+
rotationChanged: boolean = false;
|
|
19
|
+
|
|
20
|
+
position?: { x?: number, y?: number, z?: number };
|
|
21
|
+
quaternion?: { _x?: number, _y?: number, _z?: number, _w?: number };
|
|
22
|
+
|
|
23
|
+
private _positionKeys: string[] = ["x", "y", "z"];
|
|
24
|
+
private _quaternionKeys: string[] = ["_x", "_y", "_z", "_w"];
|
|
25
|
+
|
|
26
|
+
reset(clearPreviousValues: boolean = false) {
|
|
27
|
+
this.positionChanged = false;
|
|
28
|
+
this.rotationChanged = false;
|
|
29
|
+
this.mute = false;
|
|
30
|
+
|
|
31
|
+
if (clearPreviousValues) {
|
|
32
|
+
if (this.position)
|
|
33
|
+
for (const key of this._positionKeys)
|
|
34
|
+
delete this.position[key];
|
|
35
|
+
if (this.quaternion)
|
|
36
|
+
for (const key of this._quaternionKeys)
|
|
37
|
+
delete this.quaternion[key];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
mute: boolean = false;
|
|
42
|
+
|
|
43
|
+
applyValues() {
|
|
44
|
+
// only apply the values that actually changed
|
|
45
|
+
// since we want to still control all the other values via physics
|
|
46
|
+
if (this.positionChanged && this.position) {
|
|
47
|
+
for (const key of this._positionKeys) {
|
|
48
|
+
const val = this.position[key];
|
|
49
|
+
if (val !== undefined)
|
|
50
|
+
this.obj.position[key] = val;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (this.rotationChanged) {
|
|
54
|
+
if (this.quaternion) {
|
|
55
|
+
for (const key of this._quaternionKeys) {
|
|
56
|
+
const val = this.quaternion[key];
|
|
57
|
+
if (val !== undefined)
|
|
58
|
+
this.obj.quaternion[key] = val;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
readonly context: Context;
|
|
65
|
+
readonly obj: Object3D;
|
|
66
|
+
private _positionWatch?: Watch;
|
|
67
|
+
private _rotationWatch?: Watch;
|
|
68
|
+
|
|
69
|
+
constructor(obj: Object3D, context: Context) {
|
|
70
|
+
this.context = context;
|
|
71
|
+
this.obj = obj;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
start(position: boolean, rotation: boolean) {
|
|
75
|
+
this.reset();
|
|
76
|
+
if (position) {
|
|
77
|
+
if (!this._positionWatch)
|
|
78
|
+
this._positionWatch = new Watch(this.obj.position, ["x", "y", "z"]);
|
|
79
|
+
this._positionWatch.apply();
|
|
80
|
+
this.position = {};
|
|
81
|
+
// this.position = this.obj.position.clone();
|
|
82
|
+
this._positionWatch.subscribeWrite((val, prop) => {
|
|
83
|
+
if (this.context.physics.isUpdating || this.mute) return;
|
|
84
|
+
const prev = this.position![prop];
|
|
85
|
+
if (Math.abs(prev - val) < .00001) return;
|
|
86
|
+
this.position![prop] = val;
|
|
87
|
+
this.positionChanged = true;
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
if (rotation) {
|
|
91
|
+
if (!this._rotationWatch)
|
|
92
|
+
this._rotationWatch = new Watch(this.obj.quaternion, ["_x", "_y", "_z", "_w"]);
|
|
93
|
+
this._rotationWatch.apply();
|
|
94
|
+
this.quaternion = {};
|
|
95
|
+
// this.quaternion = this.obj.quaternion.clone();
|
|
96
|
+
this._rotationWatch.subscribeWrite((val, prop) => {
|
|
97
|
+
if (this.context.physics.isUpdating || this.mute) return;
|
|
98
|
+
const prev = this.quaternion![prop];
|
|
99
|
+
if (Math.abs(prev - val) < .00001) return;
|
|
100
|
+
this.quaternion![prop] = val;
|
|
101
|
+
this.rotationChanged = true;
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
stop() {
|
|
107
|
+
this._positionWatch?.revoke();
|
|
108
|
+
this._rotationWatch?.revoke();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
10
112
|
|
|
11
113
|
export class Rigidbody extends Behaviour implements IRigidbody {
|
|
12
114
|
|
|
115
|
+
@validate()
|
|
13
116
|
@serializeable()
|
|
14
117
|
mass: number = 1;
|
|
15
118
|
|
|
119
|
+
@validate()
|
|
16
120
|
@serializeable()
|
|
17
|
-
|
|
18
|
-
this._isKinematic = kinematic;
|
|
19
|
-
if (this._body) {
|
|
20
|
-
this._body.type = kinematic ? CANNON.Body.KINEMATIC : CANNON.Body.DYNAMIC;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
121
|
+
useGravity: boolean = true;
|
|
23
122
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
private _isKinematic: boolean = false;
|
|
123
|
+
@validate()
|
|
124
|
+
@serializeable()
|
|
125
|
+
constraints: RigidbodyConstraints = RigidbodyConstraints.None;
|
|
28
126
|
|
|
127
|
+
@validate()
|
|
128
|
+
@serializeable()
|
|
129
|
+
isKinematic: boolean = false;
|
|
130
|
+
|
|
131
|
+
@validate()
|
|
29
132
|
@serializeable()
|
|
30
133
|
drag: number = 0;
|
|
134
|
+
|
|
135
|
+
@validate()
|
|
31
136
|
@serializeable()
|
|
32
137
|
angularDrag: number = 1;
|
|
138
|
+
|
|
139
|
+
@validate()
|
|
33
140
|
@serializeable()
|
|
34
141
|
detectCollisions: boolean = true;
|
|
142
|
+
|
|
143
|
+
@validate()
|
|
35
144
|
@serializeable()
|
|
36
145
|
sleepThreshold: number = 0.01;
|
|
37
146
|
|
|
147
|
+
@validate()
|
|
148
|
+
@serializeable()
|
|
149
|
+
collisionDetectionMode: CollisionDetectionMode = CollisionDetectionMode.Discrete;
|
|
38
150
|
|
|
39
|
-
get
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return this.
|
|
151
|
+
get lockPositionX() {
|
|
152
|
+
return (this.constraints & RigidbodyConstraints.FreezePositionX) !== 0;
|
|
153
|
+
}
|
|
154
|
+
get lockPositionY() {
|
|
155
|
+
return (this.constraints & RigidbodyConstraints.FreezePositionY) !== 0;
|
|
156
|
+
}
|
|
157
|
+
get lockPositionZ() {
|
|
158
|
+
return (this.constraints & RigidbodyConstraints.FreezePositionZ) !== 0;
|
|
159
|
+
}
|
|
160
|
+
get lockRotationX() {
|
|
161
|
+
return (this.constraints & RigidbodyConstraints.FreezeRotationX) !== 0;
|
|
162
|
+
}
|
|
163
|
+
get lockRotationY() {
|
|
164
|
+
return (this.constraints & RigidbodyConstraints.FreezeRotationY) !== 0;
|
|
165
|
+
}
|
|
166
|
+
get lockRotationZ() {
|
|
167
|
+
return (this.constraints & RigidbodyConstraints.FreezeRotationZ) !== 0;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
set lockPositionX(v: boolean) {
|
|
171
|
+
if (v) this.constraints |= RigidbodyConstraints.FreezePositionX;
|
|
172
|
+
else this.constraints &= ~RigidbodyConstraints.FreezePositionX;
|
|
173
|
+
}
|
|
174
|
+
set lockPositionY(v: boolean) {
|
|
175
|
+
if (v) this.constraints |= RigidbodyConstraints.FreezePositionY;
|
|
176
|
+
else this.constraints &= ~RigidbodyConstraints.FreezePositionY;
|
|
177
|
+
}
|
|
178
|
+
set lockPositionZ(v: boolean) {
|
|
179
|
+
if (v) this.constraints |= RigidbodyConstraints.FreezePositionZ;
|
|
180
|
+
else this.constraints &= ~RigidbodyConstraints.FreezePositionZ;
|
|
181
|
+
}
|
|
182
|
+
set lockRotationX(v: boolean) {
|
|
183
|
+
if (v) this.constraints |= RigidbodyConstraints.FreezeRotationX;
|
|
184
|
+
else this.constraints &= ~RigidbodyConstraints.FreezeRotationX;
|
|
185
|
+
}
|
|
186
|
+
set lockRotationY(v: boolean) {
|
|
187
|
+
if (v) this.constraints |= RigidbodyConstraints.FreezeRotationY;
|
|
188
|
+
else this.constraints &= ~RigidbodyConstraints.FreezeRotationY;
|
|
189
|
+
}
|
|
190
|
+
set lockRotationZ(v: boolean) {
|
|
191
|
+
if (v) this.constraints |= RigidbodyConstraints.FreezeRotationZ;
|
|
192
|
+
else this.constraints &= ~RigidbodyConstraints.FreezeRotationZ;
|
|
44
193
|
}
|
|
45
194
|
|
|
195
|
+
private _propertiesChanged: boolean = false;
|
|
46
196
|
private static tempPosition: THREE.Vector3 = new THREE.Vector3();
|
|
47
|
-
private
|
|
48
|
-
private currentVelocity!: THREE.Vector3;
|
|
197
|
+
private _currentVelocity!: THREE.Vector3;
|
|
49
198
|
private _smoothedVelocity!: THREE.Vector3;
|
|
50
|
-
private
|
|
199
|
+
private _smoothedVelocityGetter!: THREE.Vector3;
|
|
200
|
+
private _lastPosition!: THREE.Vector3;
|
|
51
201
|
|
|
52
|
-
private
|
|
53
|
-
private _dirty: boolean = false;
|
|
202
|
+
private _watch?: TransformWatch;
|
|
54
203
|
|
|
55
|
-
private _positionWatch?: Watch;
|
|
56
|
-
private _matrixWatch?: Watch;
|
|
57
|
-
private _setMatrix: THREE.Matrix4;
|
|
58
|
-
|
|
59
|
-
constructor() {
|
|
60
|
-
super();
|
|
61
|
-
this._setMatrix = new THREE.Matrix4();
|
|
62
|
-
}
|
|
63
204
|
|
|
64
205
|
awake() {
|
|
65
|
-
this.
|
|
66
|
-
this.
|
|
206
|
+
this._watch = undefined;
|
|
207
|
+
this._currentVelocity = new THREE.Vector3();
|
|
67
208
|
this._smoothedVelocity = new THREE.Vector3();
|
|
68
|
-
this.
|
|
69
|
-
this.
|
|
70
|
-
this._positionWatch = undefined;
|
|
209
|
+
this._smoothedVelocityGetter = new THREE.Vector3();
|
|
210
|
+
this._lastPosition = new THREE.Vector3();
|
|
71
211
|
}
|
|
72
212
|
|
|
73
|
-
// start() {
|
|
74
|
-
// this.setBodyFromGameObject();
|
|
75
|
-
// }
|
|
76
|
-
|
|
77
213
|
onEnable() {
|
|
78
|
-
if (this.
|
|
79
|
-
this.
|
|
80
|
-
}
|
|
81
|
-
else
|
|
82
|
-
this.initialize();
|
|
83
|
-
|
|
84
|
-
if (this.body) {
|
|
85
|
-
this.body.wakeUp();
|
|
86
|
-
this.gameObject.updateWorldMatrix(true, false);
|
|
87
|
-
this.setBodyFromGameObject();
|
|
214
|
+
if (!this._watch) {
|
|
215
|
+
this._watch = new TransformWatch(this.gameObject, this.context);
|
|
88
216
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
this._positionWatch = new Watch(this.gameObject.position, ["x", "y", "z"]);
|
|
92
|
-
this._positionWatch.subscribeWrite(_ => {
|
|
93
|
-
if (!this.context.physics.isUpdating && !this._ignoreChange) {
|
|
94
|
-
this._dirty = true;
|
|
95
|
-
this._setMatrix.copy(this.gameObject.matrix);
|
|
96
|
-
this._setMatrix.setPosition(this.gameObject.position);
|
|
97
|
-
}
|
|
98
|
-
})
|
|
217
|
+
this._watch.start(true, true);
|
|
218
|
+
this.startCoroutine(this.beforePhysics(), FrameEvent.LateUpdate);
|
|
99
219
|
}
|
|
100
220
|
|
|
101
|
-
onDisable()
|
|
102
|
-
|
|
103
|
-
|
|
221
|
+
onDisable() {
|
|
222
|
+
this._watch?.stop();
|
|
223
|
+
this.context.physics.removeBody(this);
|
|
104
224
|
}
|
|
105
225
|
|
|
106
226
|
onDestroy(): void {
|
|
107
|
-
|
|
108
|
-
this.context.physics.removeBody(this.gameObject, this._body);
|
|
227
|
+
this.context.physics.removeBody(this);
|
|
109
228
|
}
|
|
110
229
|
|
|
111
|
-
|
|
112
|
-
this.
|
|
113
|
-
|
|
230
|
+
onValidate() {
|
|
231
|
+
this._propertiesChanged = true;
|
|
232
|
+
}
|
|
114
233
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
this.
|
|
234
|
+
// need to do this right before updating physics to prevent rendered object glitching through physical bodies
|
|
235
|
+
*beforePhysics() {
|
|
236
|
+
while (true) {
|
|
237
|
+
if (this._propertiesChanged) {
|
|
238
|
+
this._propertiesChanged = false;
|
|
239
|
+
this.context.physics.updateProperties(this);
|
|
240
|
+
}
|
|
241
|
+
if (this._watch?.isDirty) {
|
|
242
|
+
this._watch.mute = true;
|
|
243
|
+
this._watch.applyValues();
|
|
244
|
+
this.context.physics.updateBody(this, this._watch.positionChanged, this._watch.rotationChanged);
|
|
245
|
+
this._watch.reset();
|
|
246
|
+
}
|
|
247
|
+
this.captureVelocity();
|
|
248
|
+
yield;
|
|
119
249
|
}
|
|
250
|
+
}
|
|
120
251
|
|
|
121
|
-
|
|
252
|
+
private get body() {
|
|
253
|
+
return this.context.physics.internal_getRigidbody(this);
|
|
122
254
|
}
|
|
123
255
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
options.sleepThreshold = this.sleepThreshold;
|
|
135
|
-
this._body = this.context.physics.createBody(this.gameObject, options);
|
|
256
|
+
public teleport(pt: { x: number, y: number, z: number }, localspace:boolean = true) {
|
|
257
|
+
this._watch?.reset(true);
|
|
258
|
+
if(localspace) this.gameObject.position.set(pt.x, pt.y, pt.z);
|
|
259
|
+
else this.setWorldPosition(pt.x, pt.y, pt.z);
|
|
260
|
+
this.resetForcesAndTorques();
|
|
261
|
+
this.resetVelocities();
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
public resetForces() {
|
|
265
|
+
this.body?.resetForces(true);
|
|
136
266
|
}
|
|
137
267
|
|
|
268
|
+
public resetTorques() {
|
|
269
|
+
this.body?.resetTorques(true);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
public resetVelocities() {
|
|
273
|
+
this.setVelocity(0, 0, 0);
|
|
274
|
+
this.setAngularVelocity(0, 0, 0);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
public resetForcesAndTorques() {
|
|
278
|
+
this.resetForces();
|
|
279
|
+
this.resetTorques();
|
|
280
|
+
}
|
|
138
281
|
|
|
139
282
|
public wakeUp() {
|
|
140
283
|
this.body?.wakeUp();
|
|
141
284
|
}
|
|
142
285
|
|
|
143
|
-
public applyForce(vec:
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
286
|
+
public applyForce(vec: Vector3, _rel?: THREE.Vector3) {
|
|
287
|
+
this.body?.addForce(vec, true);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
public applyImpulse(vec: Vector3) {
|
|
291
|
+
this.body?.applyImpulse(vec, true);
|
|
147
292
|
}
|
|
148
293
|
|
|
149
294
|
public setForce(x: number, y: number, z: number) {
|
|
150
|
-
this.body?.
|
|
295
|
+
this.body?.resetForces(true);
|
|
296
|
+
this.body?.addForce({ x, y, z }, true);
|
|
151
297
|
}
|
|
152
298
|
|
|
153
|
-
public getVelocity():
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
299
|
+
public getVelocity(): Vector3 {
|
|
300
|
+
const vel = this.body?.linvel();
|
|
301
|
+
if (!vel) return this._currentVelocity.set(0, 0, 0);
|
|
302
|
+
this._currentVelocity.x = vel.x;
|
|
303
|
+
this._currentVelocity.y = vel.y;
|
|
304
|
+
this._currentVelocity.z = vel.z;
|
|
305
|
+
return this._currentVelocity;
|
|
157
306
|
}
|
|
158
307
|
|
|
159
|
-
public setVelocity(x: number | Vector3, y
|
|
160
|
-
if (!this.body) return;
|
|
308
|
+
public setVelocity(x: number | Vector3, y?: number, z?: number) {
|
|
161
309
|
if (x instanceof Vector3) {
|
|
162
310
|
const vec = x;
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
z = vec.z;
|
|
311
|
+
this.body?.setLinvel(vec, true);
|
|
312
|
+
return;
|
|
166
313
|
}
|
|
167
|
-
|
|
168
|
-
this.body
|
|
169
|
-
this.body.velocity.z = z / this.context.time.deltaTime;
|
|
314
|
+
if (y === undefined || z === undefined) return;
|
|
315
|
+
this.body?.setLinvel({ x: x, y: y, z: z }, true);
|
|
170
316
|
}
|
|
171
317
|
|
|
172
|
-
public
|
|
173
|
-
if (this.body)
|
|
174
|
-
return Rigidbody.tempPosition.set(this.body?.torque.x, this.body?.torque.y, this.body?.torque.z);
|
|
175
|
-
return Rigidbody.tempPosition.set(0, 0, 0);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
public setTorque(x: number | Vector3, y: number, z: number) {
|
|
179
|
-
if (!this.body) return;
|
|
318
|
+
public setAngularVelocity(x: number | Vector3, y?: number, z?: number) {
|
|
180
319
|
if (x instanceof Vector3) {
|
|
181
320
|
const vec = x;
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
z = vec.z;
|
|
321
|
+
this.body?.setAngvel(vec, true);
|
|
322
|
+
return;
|
|
185
323
|
}
|
|
186
|
-
|
|
187
|
-
this.body
|
|
188
|
-
this.body.torque.z = z / this.context.time.deltaTime;
|
|
189
|
-
|
|
324
|
+
if (y === undefined || z === undefined) return;
|
|
325
|
+
this.body?.setAngvel({ x: x, y: y, z: z }, true);
|
|
190
326
|
}
|
|
191
327
|
|
|
192
|
-
public
|
|
193
|
-
|
|
194
|
-
public setAngularVelocity(x: number, y: number, z: number) {
|
|
195
|
-
if (!this.body) return;
|
|
196
|
-
this.body.angularVelocity.x = x / this.context.time.deltaTime;
|
|
197
|
-
this.body.angularVelocity.y = y / this.context.time.deltaTime;
|
|
198
|
-
this.body.angularVelocity.z = z / this.context.time.deltaTime;
|
|
328
|
+
public setTorque(x: number | Vector3, y: number, z: number) {
|
|
329
|
+
this.setAngularVelocity(x, y, z);
|
|
199
330
|
}
|
|
200
331
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
if (this.body && this.gameObject && !this.destroyed) {
|
|
206
|
-
this._ignoreChange = true;
|
|
207
|
-
const wp = this.worldPosition;
|
|
208
|
-
this.body.position.set(wp.x, wp.y, wp.z);
|
|
209
|
-
const wr = this.worldQuaternion;
|
|
210
|
-
this.body.quaternion.set(wr.x, wr.y, wr.z, wr.w);
|
|
332
|
+
public get smoothedVelocity(): Vector3 {
|
|
333
|
+
this._smoothedVelocityGetter.copy(this._smoothedVelocity);
|
|
334
|
+
return this._smoothedVelocityGetter.multiplyScalar(1 / this.context.time.deltaTime);
|
|
335
|
+
}
|
|
211
336
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
337
|
+
// public get smoothedVelocity() { return this._smoothedVelocity; }
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
/**d
|
|
342
|
+
* @deprecated not used anymore
|
|
343
|
+
*/
|
|
344
|
+
public setBodyFromGameObject(_velocity: THREE.Vector3 | null | { x: number, y: number, z: number } = null) {
|
|
345
|
+
if (this.gameObject && !this.destroyed) {
|
|
346
|
+
// this.context.physics.updateBody(this);
|
|
347
|
+
// this._ignoreChange = true;
|
|
348
|
+
// const wp = this.worldPosition;
|
|
349
|
+
// this.body.position.set(wp.x, wp.y, wp.z);
|
|
350
|
+
// const wr = this.worldQuaternion;
|
|
351
|
+
// this.body.quaternion.set(wr.x, wr.y, wr.z, wr.w);
|
|
352
|
+
|
|
353
|
+
// if (velocity) {
|
|
354
|
+
// Rigidbody.copyVector3.set(velocity.x, velocity.y, velocity.z);
|
|
355
|
+
// this._smoothedVelocity.lerp(Rigidbody.copyVector3, this.context.time.deltaTime / .1);
|
|
356
|
+
// const sm = this._smoothedVelocity;
|
|
357
|
+
// this.body.velocity.x = sm.x;
|
|
358
|
+
// this.body.velocity.y = sm.y;
|
|
359
|
+
// this.body.velocity.z = sm.z;
|
|
360
|
+
// }
|
|
361
|
+
// this._ignoreChange = false;
|
|
221
362
|
}
|
|
222
363
|
}
|
|
223
364
|
|
|
224
365
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
if (this.body
|
|
366
|
+
|
|
367
|
+
private captureVelocity() {
|
|
368
|
+
if (this.body) {
|
|
228
369
|
const wp = getWorldPosition(this.gameObject);
|
|
229
|
-
|
|
230
|
-
this.
|
|
231
|
-
this.
|
|
370
|
+
Rigidbody.tempPosition.copy(wp);
|
|
371
|
+
const vel = wp.sub(this._lastPosition);
|
|
372
|
+
this._lastPosition.copy(Rigidbody.tempPosition);
|
|
373
|
+
this._smoothedVelocity.lerp(vel, this.context.time.deltaTime / .1);
|
|
374
|
+
// this._smoothedVelocity.set(0, 1 / this.context.time.deltaTime, 0);
|
|
232
375
|
}
|
|
233
376
|
}
|
|
234
377
|
}
|
|
@@ -1,53 +1,56 @@
|
|
|
1
1
|
import { Camera } from "./Camera";
|
|
2
2
|
import { Behaviour, GameObject } from "./Component";
|
|
3
|
-
import * as utils from "../engine/engine_three_utils";
|
|
4
3
|
import * as THREE from "three";
|
|
5
4
|
import { Mathf } from "../engine/engine_math";
|
|
6
5
|
import { serializeable } from "../engine/engine_serialization_decorator";
|
|
7
6
|
import { Object3D } from "three";
|
|
7
|
+
import { getWorldPosition, getWorldQuaternion } from "../engine/engine_three_utils";
|
|
8
|
+
import { Axes } from "../engine/engine_physics.types";
|
|
8
9
|
|
|
9
10
|
export class SmoothFollow extends Behaviour {
|
|
10
11
|
|
|
11
12
|
@serializeable(Object3D)
|
|
12
13
|
target: THREE.Object3D | null = null;
|
|
13
14
|
|
|
15
|
+
@serializeable()
|
|
14
16
|
followFactor = .1;
|
|
17
|
+
@serializeable()
|
|
15
18
|
rotateFactor = .1;
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
@serializeable()
|
|
21
|
+
positionAxes : Axes = Axes.All;
|
|
18
22
|
|
|
19
|
-
|
|
20
|
-
|
|
23
|
+
// @serializeable()
|
|
24
|
+
// rotationAxes : Axes = Axes.All;
|
|
21
25
|
|
|
26
|
+
flipForward: boolean = false;
|
|
27
|
+
|
|
28
|
+
private static _invertForward: THREE.Quaternion = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI);
|
|
29
|
+
private _firstUpdate = true;
|
|
22
30
|
|
|
23
|
-
onEnable(): void {
|
|
24
|
-
const cam = GameObject.getComponentInChildren(this.gameObject, Camera) as Camera;
|
|
25
|
-
if (cam && cam.cam) {
|
|
26
|
-
cam.gameObject.position.set(0, 0, 0);
|
|
27
|
-
cam.cam.position.set(0, 0, 0);
|
|
28
|
-
cam.gameObject.quaternion.identity();
|
|
29
|
-
cam.cam.quaternion.setFromEuler(new THREE.Euler(0, Math.PI, 0));
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
31
|
|
|
33
32
|
onBeforeRender(): void {
|
|
34
|
-
if (this.followFactor <= 0) return;
|
|
35
33
|
this.updateNow(false);
|
|
36
34
|
}
|
|
37
35
|
|
|
38
36
|
updateNow(hard: boolean) {
|
|
39
37
|
if (!this.target || this.target === this.gameObject) return;
|
|
40
38
|
if (this.followFactor > 0) {
|
|
41
|
-
const wp =
|
|
39
|
+
const wp = getWorldPosition(this.target);
|
|
42
40
|
const fpos = this._firstUpdate || hard ? 1 : Mathf.clamp01(this.context.time.deltaTime * this.followFactor);
|
|
43
|
-
|
|
41
|
+
const currentPosition = this.worldPosition;
|
|
42
|
+
if(this.positionAxes & Axes.X) currentPosition.x = Mathf.lerp(currentPosition.x, wp.x, fpos);
|
|
43
|
+
if(this.positionAxes & Axes.Y) currentPosition.y = Mathf.lerp(currentPosition.y, wp.y, fpos);
|
|
44
|
+
if(this.positionAxes & Axes.Z) currentPosition.z = Mathf.lerp(currentPosition.z, wp.z, fpos);
|
|
45
|
+
this.worldPosition = currentPosition;
|
|
44
46
|
}
|
|
45
47
|
if (this.rotateFactor > 0) {
|
|
46
|
-
const wr =
|
|
47
|
-
if(this.flipForward){
|
|
48
|
+
const wr = getWorldQuaternion(this.target);
|
|
49
|
+
if (this.flipForward) {
|
|
48
50
|
wr.premultiply(SmoothFollow._invertForward);
|
|
49
51
|
}
|
|
50
52
|
const frot = this._firstUpdate || hard ? 1 : Mathf.clamp01(this.context.time.deltaTime * this.rotateFactor);
|
|
53
|
+
|
|
51
54
|
this.worldQuaternion = this.worldQuaternion.slerp(wr, frot);
|
|
52
55
|
}
|
|
53
56
|
this._firstUpdate = false;
|
|
@@ -95,7 +95,7 @@ export class SpatialTrigger extends Behaviour {
|
|
|
95
95
|
SpatialTrigger.triggers.push(this);
|
|
96
96
|
if (!this.boxHelper) {
|
|
97
97
|
this.boxHelper = GameObject.addNewComponent(this.gameObject, BoxHelperComponent);
|
|
98
|
-
this.boxHelper?.showHelper();
|
|
98
|
+
this.boxHelper?.showHelper(null, debug as boolean);
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
onDisable(): void {
|
|
@@ -61,6 +61,10 @@ export class SpectatorCamera extends Behaviour {
|
|
|
61
61
|
this.target = undefined;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
private get localId() : string {
|
|
65
|
+
return this.context.connection.connectionId ?? "local";
|
|
66
|
+
}
|
|
67
|
+
|
|
64
68
|
/** player view to follow */
|
|
65
69
|
set target(target: PlayerView | undefined) {
|
|
66
70
|
if (this._handler) {
|
|
@@ -74,7 +78,7 @@ export class SpectatorCamera extends Behaviour {
|
|
|
74
78
|
// }
|
|
75
79
|
|
|
76
80
|
const prev = this._handler.currentTarget?.userId;
|
|
77
|
-
const self = this.context.players.getPlayerView(this.
|
|
81
|
+
const self = this.context.players.getPlayerView(this.localId);
|
|
78
82
|
|
|
79
83
|
// if user is in XR and sets target to self disable it
|
|
80
84
|
if (target === undefined || (this.context.isInXR === false && self?.currentObject === target.currentObject)) {
|
|
@@ -103,7 +107,7 @@ export class SpectatorCamera extends Behaviour {
|
|
|
103
107
|
}
|
|
104
108
|
|
|
105
109
|
private get isSpectatingSelf() {
|
|
106
|
-
return this.isSpectating && this.target?.currentObject === this.context.players.getPlayerView(this.
|
|
110
|
+
return this.isSpectating && this.target?.currentObject === this.context.players.getPlayerView(this.localId)?.currentObject;
|
|
107
111
|
}
|
|
108
112
|
|
|
109
113
|
// private currentViewport : THREE.Vector4 = new THREE.Vector4();
|
|
@@ -191,6 +195,10 @@ export class SpectatorCamera extends Behaviour {
|
|
|
191
195
|
|
|
192
196
|
private followSelf() {
|
|
193
197
|
this.target = this.context.players.getPlayerView(this.context.connection.connectionId);
|
|
198
|
+
if (!this.target) {
|
|
199
|
+
this.context.players.setPlayerView(this.localId, this.context.mainCamera, ViewDevice.Headset);
|
|
200
|
+
this.target = this.context.players.getPlayerView(this.localId);
|
|
201
|
+
}
|
|
194
202
|
if (debug) console.log("Follow self", this.target);
|
|
195
203
|
}
|
|
196
204
|
|