@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
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export enum CollisionDetectionMode {
|
|
4
|
+
Discrete = 0,
|
|
5
|
+
Continuous = 1,
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export enum RigidbodyConstraints {
|
|
9
|
+
None = 0,
|
|
10
|
+
FreezePositionX = 2,
|
|
11
|
+
FreezePositionY = 4,
|
|
12
|
+
FreezePositionZ = 8,
|
|
13
|
+
FreezePosition = 14,
|
|
14
|
+
FreezeRotationX = 16,
|
|
15
|
+
FreezeRotationY = 32,
|
|
16
|
+
FreezeRotationZ = 64,
|
|
17
|
+
FreezeRotation = 112,
|
|
18
|
+
FreezeAll = 126,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
export enum Axes {
|
|
23
|
+
None = 0,
|
|
24
|
+
X = 2,
|
|
25
|
+
Y = 4,
|
|
26
|
+
Z = 8,
|
|
27
|
+
All = ~0,
|
|
28
|
+
}
|
|
@@ -3,7 +3,7 @@ import { getParam } from "./engine_utils";
|
|
|
3
3
|
import { Object3D } from "three";
|
|
4
4
|
import { Context } from "./engine_setup";
|
|
5
5
|
import { isPersistentAsset } from "./extensions/NEEDLE_persistent_assets";
|
|
6
|
-
import { SourceIdentifier } from "./engine_types";
|
|
6
|
+
import { IComponent, SourceIdentifier } from "./engine_types";
|
|
7
7
|
import { debugExtension } from "../engine/engine_default_parameters";
|
|
8
8
|
import { LogType, showBalloonMessage } from "./debug/debug";
|
|
9
9
|
import { isLocalNetwork } from "./engine_networking_utils";
|
|
@@ -11,6 +11,7 @@ import { $BuiltInTypeFlag } from "./engine_typestore";
|
|
|
11
11
|
|
|
12
12
|
const debug = getParam("debugserializer");
|
|
13
13
|
|
|
14
|
+
|
|
14
15
|
export type Constructor<T> = { new(...args: any[]): T };
|
|
15
16
|
export declare type NodeToObjectMap = { [nodeId: string]: Object3D };
|
|
16
17
|
export declare type ObjectToNodeMap = { [uuid: string]: number };
|
|
@@ -516,6 +517,10 @@ function setBuffer(value): Array<any> {
|
|
|
516
517
|
}
|
|
517
518
|
|
|
518
519
|
|
|
520
|
+
/** set to true while assigning properties during instantiation.
|
|
521
|
+
* Used for validate decorator to not invoke callbacks on components that are currently in the process of being built */
|
|
522
|
+
export const $isAssigningProperties = Symbol("assigned component properties");
|
|
523
|
+
|
|
519
524
|
// const developmentMode = getParam("dev")
|
|
520
525
|
|
|
521
526
|
/** Object.assign behaviour but check if property is writeable (e.g. getter only properties are skipped) */
|
|
@@ -540,6 +545,7 @@ export function assign(target: any, source: any) {
|
|
|
540
545
|
// if (developmentMode)
|
|
541
546
|
// onlyDeclared = false;
|
|
542
547
|
|
|
548
|
+
target[$isAssigningProperties] = true;
|
|
543
549
|
for (const key of Object.keys(source)) {
|
|
544
550
|
const desc = getPropertyDescriptor(target, key);
|
|
545
551
|
if (onlyDeclared && desc === undefined) continue;
|
|
@@ -550,6 +556,7 @@ export function assign(target: any, source: any) {
|
|
|
550
556
|
target[key] = source[key];
|
|
551
557
|
}
|
|
552
558
|
}
|
|
559
|
+
delete target[$isAssigningProperties];
|
|
553
560
|
}
|
|
554
561
|
|
|
555
562
|
// we need to recurse because the property might be defined in a base class
|
|
@@ -58,6 +58,7 @@ export class ContextArgs {
|
|
|
58
58
|
alias: string | undefined | null = undefined;
|
|
59
59
|
domElement: HTMLElement | null;
|
|
60
60
|
renderer?: THREE.WebGLRenderer = undefined;
|
|
61
|
+
hash?: string;
|
|
61
62
|
|
|
62
63
|
constructor(domElement: HTMLElement | null) {
|
|
63
64
|
this.domElement = domElement ?? document.body;
|
|
@@ -70,7 +71,8 @@ export enum FrameEvent {
|
|
|
70
71
|
LateUpdate = 2,
|
|
71
72
|
OnBeforeRender = 3,
|
|
72
73
|
OnAfterRender = 4,
|
|
73
|
-
|
|
74
|
+
PrePhysicsStep = 9,
|
|
75
|
+
PostPhysicsStep = 10,
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
export enum XRSessionMode {
|
|
@@ -81,12 +83,12 @@ export enum XRSessionMode {
|
|
|
81
83
|
export declare type OnBeforeRenderCallback = (renderer: THREE.WebGLRenderer, scene: THREE.Scene, camera: THREE.Camera, geometry: THREE.BufferGeometry, material: THREE.Material, group: THREE.Group) => void
|
|
82
84
|
|
|
83
85
|
|
|
84
|
-
export function registerComponent(script
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
export function registerComponent(script: IComponent, context?: Context) {
|
|
87
|
+
if (!script) return;
|
|
88
|
+
const new_scripts = context?.new_scripts ?? Context.Current.new_scripts;
|
|
89
|
+
if (!new_scripts.includes(script)) {
|
|
90
|
+
new_scripts.push(script);
|
|
91
|
+
}
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
export class Context {
|
|
@@ -105,13 +107,16 @@ export class Context {
|
|
|
105
107
|
alias: string | undefined | null;
|
|
106
108
|
isManagedExternally: boolean = false;
|
|
107
109
|
|
|
110
|
+
/** used to append to loaded assets */
|
|
111
|
+
hash?: string;
|
|
112
|
+
|
|
108
113
|
domElement: HTMLElement;
|
|
109
114
|
get resolutionScaleFactor() { return this._resolutionScaleFactor; }
|
|
110
115
|
/** use to scale the resolution up or down of the renderer. default is 1 */
|
|
111
|
-
set resolutionScaleFactor(val: number) {
|
|
112
|
-
if(val === this._resolutionScaleFactor) return;
|
|
113
|
-
if(typeof val !== "number") return;
|
|
114
|
-
if(val <= 0) {
|
|
116
|
+
set resolutionScaleFactor(val: number) {
|
|
117
|
+
if (val === this._resolutionScaleFactor) return;
|
|
118
|
+
if (typeof val !== "number") return;
|
|
119
|
+
if (val <= 0) {
|
|
115
120
|
console.error("Invalid resolution scale factor", val);
|
|
116
121
|
return;
|
|
117
122
|
}
|
|
@@ -124,7 +129,9 @@ export class Context {
|
|
|
124
129
|
get domX(): number { return this.domElement.offsetLeft; }
|
|
125
130
|
get domY(): number { return this.domElement.offsetTop; }
|
|
126
131
|
get isInXR() { return this.renderer.xr?.isPresenting || false; }
|
|
127
|
-
xrSessionMode
|
|
132
|
+
xrSessionMode: XRSessionMode | undefined = undefined;
|
|
133
|
+
get isInVR() { return this.xrSessionMode === XRSessionMode.ImmersiveVR; }
|
|
134
|
+
get isInAR() { return this.xrSessionMode === XRSessionMode.ImmersiveAR; }
|
|
128
135
|
get xrSession() { return this.renderer.xr?.getSession(); }
|
|
129
136
|
get arOverlayElement(): HTMLElement {
|
|
130
137
|
const el = this.domElement as any;
|
|
@@ -182,7 +189,7 @@ export class Context {
|
|
|
182
189
|
rendererData: RendererData;
|
|
183
190
|
addressables: Addressables;
|
|
184
191
|
lightmaps: ILightDataRegistry;
|
|
185
|
-
players
|
|
192
|
+
players: PlayerViewManager;
|
|
186
193
|
|
|
187
194
|
private _sizeChanged: boolean = false;
|
|
188
195
|
private _isCreated: boolean = false;
|
|
@@ -193,6 +200,7 @@ export class Context {
|
|
|
193
200
|
this.name = args?.name || "";
|
|
194
201
|
this.alias = args?.alias;
|
|
195
202
|
this.domElement = args?.domElement || document.body;
|
|
203
|
+
this.hash = args?.hash;
|
|
196
204
|
if (args?.renderer) {
|
|
197
205
|
this.renderer = args.renderer;
|
|
198
206
|
this.isManagedExternally = true;
|
|
@@ -232,7 +240,7 @@ export class Context {
|
|
|
232
240
|
this.lightmaps = new LightDataRegistry(this);
|
|
233
241
|
this.players = new PlayerViewManager(this);
|
|
234
242
|
|
|
235
|
-
window.addEventListener('resize', () => this._sizeChanged = true
|
|
243
|
+
window.addEventListener('resize', () => this._sizeChanged = true);
|
|
236
244
|
const ro = new ResizeObserver(_ => this._sizeChanged = true);
|
|
237
245
|
ro.observe(this.domElement);
|
|
238
246
|
}
|
|
@@ -335,13 +343,13 @@ export class Context {
|
|
|
335
343
|
}
|
|
336
344
|
|
|
337
345
|
removeCamera(cam?: Camera | null) {
|
|
338
|
-
if(!cam) return;
|
|
346
|
+
if (!cam) return;
|
|
339
347
|
const index = this._cameraStack.indexOf(cam);
|
|
340
348
|
if (index >= 0) this._cameraStack.splice(index, 1);
|
|
341
349
|
|
|
342
350
|
if (this.mainCameraComponent === cam) {
|
|
343
351
|
this.mainCameraComponent = undefined;
|
|
344
|
-
|
|
352
|
+
|
|
345
353
|
if (this._cameraStack.length > 0) {
|
|
346
354
|
const last = this._cameraStack[this._cameraStack.length - 1];
|
|
347
355
|
this.setCurrentCamera(last);
|
|
@@ -400,6 +408,10 @@ export class Context {
|
|
|
400
408
|
}
|
|
401
409
|
|
|
402
410
|
private async internalOnCreate(buildScene: (context: Context, opts?: LoadingOptions) => Promise<void>, opts?: LoadingOptions) {
|
|
411
|
+
|
|
412
|
+
// TODO: we could configure if we need physics
|
|
413
|
+
await this.physics.createWorld();
|
|
414
|
+
|
|
403
415
|
// load and create scene
|
|
404
416
|
let prepare_succeeded = true;
|
|
405
417
|
try {
|
|
@@ -562,11 +574,12 @@ export class Context {
|
|
|
562
574
|
this.executeCoroutines(FrameEvent.LateUpdate);
|
|
563
575
|
|
|
564
576
|
try {
|
|
565
|
-
const physicsSteps =
|
|
577
|
+
const physicsSteps = 1;
|
|
566
578
|
const dt = this.time.deltaTime / physicsSteps;
|
|
567
579
|
for (let i = 0; i < physicsSteps; i++) {
|
|
580
|
+
this.executeCoroutines(FrameEvent.PrePhysicsStep);
|
|
568
581
|
this.physics.step(dt);
|
|
569
|
-
this.executeCoroutines(FrameEvent.
|
|
582
|
+
this.executeCoroutines(FrameEvent.PostPhysicsStep);
|
|
570
583
|
}
|
|
571
584
|
}
|
|
572
585
|
catch (err) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Camera, Color, Material, Object3D, Vector3 } from "three";
|
|
2
|
-
import { Body, ContactEquation } from "cannon-es";
|
|
1
|
+
import { Camera, Color, Material, Object3D, Vector3, Quaternion } from "three";
|
|
3
2
|
import { RGBAColor } from "../engine-components/js-extensions/RGBAColor";
|
|
3
|
+
import { CollisionDetectionMode, RigidbodyConstraints } from "./engine_physics.types";
|
|
4
4
|
|
|
5
5
|
/** used to find data registered via gltf files e.g. find lightmaps for a Renderer component that were shipped inside a gltf */
|
|
6
6
|
export declare type SourceIdentifier = string;
|
|
@@ -58,9 +58,10 @@ export interface IComponent {
|
|
|
58
58
|
onDisable();
|
|
59
59
|
onDestroy();
|
|
60
60
|
|
|
61
|
+
/** called for properties decorated with the @validate decorator */
|
|
62
|
+
onValidate?(property?: string);
|
|
63
|
+
|
|
61
64
|
start?(): void;
|
|
62
|
-
// available update loop events:
|
|
63
|
-
// earlyUpdate, update, lateUpdate, onBeforeRender, onAfterRender
|
|
64
65
|
earlyUpdate?(): void;
|
|
65
66
|
update?(): void;
|
|
66
67
|
lateUpdate?(): void;
|
|
@@ -69,17 +70,15 @@ export interface IComponent {
|
|
|
69
70
|
|
|
70
71
|
onCollisionEnter?(col: Collision);
|
|
71
72
|
onCollisionExit?(col: Collision);
|
|
72
|
-
onCollisionExitRaw?(col: Collision);
|
|
73
73
|
onCollisionStay?(col: Collision);
|
|
74
74
|
|
|
75
|
-
onTriggerEnter?(col:
|
|
76
|
-
onTriggerStay?(col:
|
|
77
|
-
onTriggerExit?(col:
|
|
78
|
-
|
|
79
|
-
__internalHandleCollision(col: Collision, isTriggerCollision: boolean);
|
|
80
|
-
__internalHandleExitCollisionEvent(obj: Object3D, isTriggerCollision: boolean);
|
|
75
|
+
onTriggerEnter?(col: ICollider);
|
|
76
|
+
onTriggerStay?(col: ICollider);
|
|
77
|
+
onTriggerExit?(col: ICollider);
|
|
81
78
|
|
|
82
79
|
get forward(): Vector3;
|
|
80
|
+
get worldPosition(): Vector3;
|
|
81
|
+
get worldQuaternion(): Quaternion;
|
|
83
82
|
}
|
|
84
83
|
|
|
85
84
|
|
|
@@ -101,8 +100,8 @@ export declare interface ILight extends IComponent {
|
|
|
101
100
|
}
|
|
102
101
|
|
|
103
102
|
export declare interface ISharedMaterials {
|
|
104
|
-
[num:number]
|
|
105
|
-
get length()
|
|
103
|
+
[num: number]: Material;
|
|
104
|
+
get length(): number;
|
|
106
105
|
}
|
|
107
106
|
|
|
108
107
|
export declare interface IRenderer extends IComponent {
|
|
@@ -110,6 +109,10 @@ export declare interface IRenderer extends IComponent {
|
|
|
110
109
|
get sharedMaterials(): ISharedMaterials;
|
|
111
110
|
}
|
|
112
111
|
|
|
112
|
+
// export declare interface IPhysicsComponent extends IComponent {
|
|
113
|
+
// get type() : string;
|
|
114
|
+
// }
|
|
115
|
+
|
|
113
116
|
export declare interface ICollider extends IComponent {
|
|
114
117
|
get isCollider();
|
|
115
118
|
attachedRigidbody: IRigidbody | null;
|
|
@@ -117,67 +120,99 @@ export declare interface ICollider extends IComponent {
|
|
|
117
120
|
}
|
|
118
121
|
|
|
119
122
|
export declare interface IRigidbody extends IComponent {
|
|
120
|
-
|
|
121
|
-
|
|
123
|
+
constraints: RigidbodyConstraints;
|
|
124
|
+
isKinematic: boolean;
|
|
125
|
+
mass: number;
|
|
126
|
+
drag: number;
|
|
127
|
+
angularDrag: number;
|
|
128
|
+
useGravity: boolean;
|
|
129
|
+
collisionDetectionMode: CollisionDetectionMode;
|
|
130
|
+
|
|
131
|
+
lockPositionX: boolean;
|
|
132
|
+
lockPositionY: boolean;
|
|
133
|
+
lockPositionZ: boolean;
|
|
134
|
+
lockRotationX: boolean;
|
|
135
|
+
lockRotationY: boolean;
|
|
136
|
+
lockRotationZ: boolean;
|
|
122
137
|
}
|
|
123
138
|
|
|
124
139
|
|
|
140
|
+
export const $physicsKey = Symbol("object");
|
|
125
141
|
|
|
126
142
|
|
|
143
|
+
export declare type ICollisionContext = {
|
|
144
|
+
getCollider(obj: Object3D): ICollider;
|
|
145
|
+
}
|
|
127
146
|
|
|
128
147
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
body: Body;
|
|
134
|
-
contact: ContactEquation;
|
|
135
|
-
target: Body;
|
|
136
|
-
type: string;
|
|
148
|
+
export type Vec3 = {
|
|
149
|
+
x: number,
|
|
150
|
+
y: number,
|
|
151
|
+
z: number
|
|
137
152
|
}
|
|
138
153
|
|
|
139
|
-
export
|
|
140
|
-
|
|
154
|
+
export type Vec2 = {
|
|
155
|
+
x: number,
|
|
156
|
+
y: number
|
|
141
157
|
}
|
|
142
158
|
|
|
143
|
-
export class
|
|
159
|
+
export class ContactPoint {
|
|
144
160
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
161
|
+
readonly localPoint: Vec3;
|
|
162
|
+
readonly distance: number;
|
|
163
|
+
readonly normal: Vec3;
|
|
148
164
|
|
|
149
|
-
|
|
150
|
-
|
|
165
|
+
constructor(localPt: Vec3, dist: number, normal: Vec3) {
|
|
166
|
+
this.localPoint = localPt;
|
|
167
|
+
this.distance = dist;
|
|
168
|
+
this.normal = normal;
|
|
151
169
|
}
|
|
152
170
|
|
|
153
|
-
|
|
154
|
-
private readonly collision: CannonCollision;
|
|
155
|
-
private readonly targetBody: Body;
|
|
156
|
-
private readonly context: ICollisionContext;
|
|
171
|
+
}
|
|
157
172
|
|
|
158
|
-
|
|
173
|
+
/// all info in here must be readonly because the object is only created once per started collision
|
|
174
|
+
export class Collision {
|
|
175
|
+
|
|
176
|
+
readonly contacts: ContactPoint[];
|
|
159
177
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
return this._normal;
|
|
178
|
+
constructor(obj: Object3D, otherCollider: ICollider, contacts: ContactPoint[]) {
|
|
179
|
+
this.me = obj;
|
|
180
|
+
this._collider = otherCollider;
|
|
181
|
+
this._gameObject = otherCollider.gameObject;
|
|
182
|
+
this.contacts = contacts;
|
|
167
183
|
}
|
|
168
184
|
|
|
169
|
-
|
|
185
|
+
readonly me: Object3D;
|
|
186
|
+
private _collider: ICollider;
|
|
187
|
+
|
|
188
|
+
/** the collider the collision happened with */
|
|
170
189
|
get collider(): ICollider {
|
|
171
|
-
if (!this._collider) {
|
|
172
|
-
this._collider = this.context.getCollider(this.gameObject);
|
|
173
|
-
}
|
|
174
190
|
return this._collider;
|
|
175
191
|
}
|
|
176
192
|
|
|
193
|
+
/** the object the collision happened with */
|
|
194
|
+
private _gameObject: Object3D;
|
|
177
195
|
get gameObject(): Object3D {
|
|
178
|
-
return this.
|
|
196
|
+
return this._gameObject;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** the rigidbody we hit, null if none attached */
|
|
200
|
+
get rigidBody(): IRigidbody | null {
|
|
201
|
+
return this.collider?.attachedRigidbody;
|
|
179
202
|
}
|
|
180
203
|
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
// private _normal?: Vector3;
|
|
207
|
+
// get normal(): Vector3 {
|
|
208
|
+
// if (!this._normal) {
|
|
209
|
+
// const vec = this.collision.contact.ni;
|
|
210
|
+
// this._normal = new Vector3(vec.x, vec.y, vec.z);
|
|
211
|
+
// }
|
|
212
|
+
// return this._normal;
|
|
213
|
+
// }
|
|
214
|
+
|
|
215
|
+
|
|
181
216
|
// private _point?: Vector3;
|
|
182
217
|
// get point(): Vector3 {
|
|
183
218
|
// if (!this._point) {
|
|
@@ -187,12 +222,4 @@ export class Collision {
|
|
|
187
222
|
// }
|
|
188
223
|
// return this._point;
|
|
189
224
|
// }
|
|
190
|
-
|
|
191
|
-
constructor(obj: Object3D, collision: CannonCollision, context: ICollisionContext, invert: boolean = false) {
|
|
192
|
-
this.me = obj;
|
|
193
|
-
this.collision = collision;
|
|
194
|
-
this.context = context;
|
|
195
|
-
this.targetBody = invert ? collision.target : collision.body;
|
|
196
|
-
this.invert = invert;
|
|
197
|
-
}
|
|
198
225
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { $isAssigningProperties } from "./engine_serialization_core";
|
|
2
|
+
import { LogType, showBalloonMessage } from "./debug/debug";
|
|
3
|
+
import { IComponent } from "./engine_types";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
declare type setter = (v: any) => void;
|
|
7
|
+
declare type getter = () => any;
|
|
8
|
+
|
|
9
|
+
/** create accessor callbacks for a field */
|
|
10
|
+
export const validate = function (set?: setter, get?: getter) {
|
|
11
|
+
// "descriptor : undefined" prevents @validate() to be added to property getters or setters
|
|
12
|
+
return function (target: IComponent | any, propertyKey: string, descriptor?: undefined) {
|
|
13
|
+
createPropertyWrapper(target, propertyKey, descriptor, set, get);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
function createPropertyWrapper(target: IComponent | any, propertyKey: string, descriptor?: PropertyDescriptor,
|
|
19
|
+
set?: setter,
|
|
20
|
+
get?: getter) {
|
|
21
|
+
|
|
22
|
+
if (!get && !set && !target.onValidate) return;
|
|
23
|
+
|
|
24
|
+
// this is not undefined when its a property getter or setter already and not just a field
|
|
25
|
+
// we currently only support validation of fields
|
|
26
|
+
if (descriptor !== undefined) {
|
|
27
|
+
console.error("Invalid usage of validate decorator. Only fields can be validated.", target, propertyKey, descriptor);
|
|
28
|
+
showBalloonMessage("Invalid usage of validate decorator. Only fields can be validated. Property: " + propertyKey, LogType.Error);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (target.__internalAwake) {
|
|
33
|
+
// this is the hidden key we save the original property to
|
|
34
|
+
const $prop = Symbol(propertyKey);
|
|
35
|
+
// save the original awake method
|
|
36
|
+
// we need to delay decoration until the object has been created
|
|
37
|
+
const awake = target.__internalAwake;
|
|
38
|
+
target.__internalAwake = function () {
|
|
39
|
+
|
|
40
|
+
// only build wrapper once per type
|
|
41
|
+
if (this[$prop] === undefined) {
|
|
42
|
+
|
|
43
|
+
// make sure the field is initialized in a hidden property
|
|
44
|
+
this[$prop] = this[propertyKey];
|
|
45
|
+
|
|
46
|
+
Object.defineProperty(this, propertyKey, {
|
|
47
|
+
set: function (v) {
|
|
48
|
+
if (this[$isAssigningProperties] === true) {
|
|
49
|
+
this[$prop] = v;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
set?.call(this, v);
|
|
53
|
+
const oldValue = this[$prop];
|
|
54
|
+
this[$prop] = v;
|
|
55
|
+
this.onValidate?.call(this, propertyKey, oldValue);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
get: function () {
|
|
59
|
+
get?.call(this);
|
|
60
|
+
return this[$prop];
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// call the original awake method
|
|
66
|
+
awake.call(this);
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -217,7 +217,7 @@ export function getPath(source: SourceIdentifier | undefined, uri: string): stri
|
|
|
217
217
|
// }
|
|
218
218
|
|
|
219
219
|
|
|
220
|
-
export type WriteCallback = (data: any) => void;
|
|
220
|
+
export type WriteCallback = (data: any, prop: string) => void;
|
|
221
221
|
|
|
222
222
|
export interface IWatch {
|
|
223
223
|
subscribeWrite(callback: WriteCallback);
|
|
@@ -268,7 +268,7 @@ class WatchImpl implements IWatch {
|
|
|
268
268
|
const setter = (value) => {
|
|
269
269
|
object[this._wrapperProp] = value;
|
|
270
270
|
for (const write of this.writeCallbacks) {
|
|
271
|
-
write(value);
|
|
271
|
+
write(value, this._prop);
|
|
272
272
|
}
|
|
273
273
|
}
|
|
274
274
|
// add the wrapper to the object
|
|
@@ -321,7 +321,7 @@ export class Watch implements IWatch {
|
|
|
321
321
|
apply() {
|
|
322
322
|
for (const w of this._watches) {
|
|
323
323
|
w.apply();
|
|
324
|
-
}
|
|
324
|
+
}
|
|
325
325
|
}
|
|
326
326
|
|
|
327
327
|
revoke() {
|
|
@@ -66,6 +66,8 @@ export class NEEDLE_gameobject_data implements GLTFLoaderPlugin {
|
|
|
66
66
|
|
|
67
67
|
private applyExtensionData(node: Object3D, ext: GameObjectData) {
|
|
68
68
|
node.userData.layer = ext.layers;
|
|
69
|
+
node.layers.disableAll();
|
|
70
|
+
node.layers.set(ext.layers);
|
|
69
71
|
node.userData.tag = ext.tag;
|
|
70
72
|
node.userData.hideFlags = ext.hideFlags;
|
|
71
73
|
node.userData.static = ext.static;
|
|
@@ -5,6 +5,7 @@ import { MixerEvent } from "./Animator";
|
|
|
5
5
|
import { serializeable } from "../engine/engine_serialization_decorator";
|
|
6
6
|
import { InstancingUtil } from "../engine/engine_instancing";
|
|
7
7
|
import { Mathf } from "../engine/engine_math";
|
|
8
|
+
import { Vec2 } from "../engine/engine_types";
|
|
8
9
|
|
|
9
10
|
export declare class PlayOptions {
|
|
10
11
|
fadeDuration?: number;
|
|
@@ -13,8 +14,8 @@ export declare class PlayOptions {
|
|
|
13
14
|
startTime?: number;
|
|
14
15
|
endTime?: number;
|
|
15
16
|
clampWhenFinished?: boolean;
|
|
16
|
-
minMaxSpeed?:
|
|
17
|
-
minMaxOffsetNormalized?:
|
|
17
|
+
minMaxSpeed?: Vec2;
|
|
18
|
+
minMaxOffsetNormalized?: Vec2;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export class Animation extends Behaviour {
|
|
@@ -24,11 +25,8 @@ export class Animation extends Behaviour {
|
|
|
24
25
|
@serializeable()
|
|
25
26
|
randomStartTime: boolean = true;
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@serializeable(Vector2)
|
|
31
|
-
minMaxOffsetNormalized?: Vector2;
|
|
28
|
+
minMaxSpeed?: Vec2;
|
|
29
|
+
minMaxOffsetNormalized?: Vec2;
|
|
32
30
|
|
|
33
31
|
private _tempAnimationClipBeforeGameObjectExisted: AnimationClip | null = null;
|
|
34
32
|
get clip(): AnimationClip | null {
|
|
@@ -114,6 +112,14 @@ export class Animation extends Behaviour {
|
|
|
114
112
|
return this.actions?.find(a => a.getClip().name === name);
|
|
115
113
|
}
|
|
116
114
|
|
|
115
|
+
get isPlaying() {
|
|
116
|
+
for (let i = 0; i < this._currentActions.length; i++) {
|
|
117
|
+
if (this._currentActions[i].isRunning())
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
|
|
117
123
|
play(clipOrNumber: AnimationClip | number | string, options?: PlayOptions): Promise<AnimationAction> | void {
|
|
118
124
|
this.init();
|
|
119
125
|
if (!this.mixer) return;
|
|
@@ -129,9 +135,9 @@ export class Animation extends Behaviour {
|
|
|
129
135
|
console.error("Could not find clip", clipOrNumber)
|
|
130
136
|
return;
|
|
131
137
|
}
|
|
132
|
-
if(!options) options = {};
|
|
133
|
-
if(!options.minMaxOffsetNormalized) options.minMaxOffsetNormalized = this.minMaxOffsetNormalized;
|
|
134
|
-
if(!options.minMaxSpeed) options.minMaxSpeed = this.minMaxSpeed;
|
|
138
|
+
if (!options) options = {};
|
|
139
|
+
if (!options.minMaxOffsetNormalized) options.minMaxOffsetNormalized = this.minMaxOffsetNormalized;
|
|
140
|
+
if (!options.minMaxSpeed) options.minMaxSpeed = this.minMaxSpeed;
|
|
135
141
|
for (const act of this.actions) {
|
|
136
142
|
if (act.getClip() === clip) {
|
|
137
143
|
return this.internalOnPlay(act, options);
|
|
@@ -163,8 +169,8 @@ export class Animation extends Behaviour {
|
|
|
163
169
|
action.time = 0;
|
|
164
170
|
action.timeScale = 1;
|
|
165
171
|
const clip = action.getClip();
|
|
166
|
-
if(options?.minMaxOffsetNormalized) action.time = Mathf.lerp(options.minMaxOffsetNormalized.x, options.minMaxOffsetNormalized.y, Math.random()) * clip.duration;
|
|
167
|
-
if(options?.minMaxSpeed) action.timeScale = Mathf.lerp(options.minMaxSpeed.x, options.minMaxSpeed.y, Math.random());
|
|
172
|
+
if (options?.minMaxOffsetNormalized) action.time = Mathf.lerp(options.minMaxOffsetNormalized.x, options.minMaxOffsetNormalized.y, Math.random()) * clip.duration;
|
|
173
|
+
if (options?.minMaxSpeed) action.timeScale = Mathf.lerp(options.minMaxSpeed.x, options.minMaxSpeed.y, Math.random());
|
|
168
174
|
if (options?.clampWhenFinished) action.clampWhenFinished = true;
|
|
169
175
|
if (options?.startTime !== undefined) action.time = options.startTime;
|
|
170
176
|
|
|
@@ -218,7 +218,7 @@ export class AnimatorController {
|
|
|
218
218
|
if (!allConditionsAreMet) continue;
|
|
219
219
|
|
|
220
220
|
if (debug && allConditionsAreMet) {
|
|
221
|
-
console.log("All conditions are met", transition);
|
|
221
|
+
// console.log("All conditions are met", transition);
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
// disable triggers
|
|
@@ -232,16 +232,16 @@ export class AnimatorController {
|
|
|
232
232
|
if (action) {
|
|
233
233
|
const dur = state.motion.clip!.duration;
|
|
234
234
|
const normalizedTime = dur <= 0 ? 1 : action.time / dur;
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
) {
|
|
235
|
+
const makeTransition = transition.hasExitTime ? normalizedTime >= transition.exitTime : true;
|
|
236
|
+
// console.log(state.name, makeTransition, transition.hasExitTime, normalizedTime, transition.exitTime)
|
|
237
|
+
if (makeTransition) {
|
|
239
238
|
// if (transition.hasExitTime && transition.exitTime >= .9999)
|
|
240
239
|
action.clampWhenFinished = true;
|
|
241
240
|
// else action.clampWhenFinished = false;
|
|
242
|
-
if (debug)
|
|
243
|
-
|
|
244
|
-
console.log(
|
|
241
|
+
if (debug)
|
|
242
|
+
{
|
|
243
|
+
console.log("transition to " + transition.destinationState, transition, normalizedTime, transition.exitTime, transition.hasExitTime);
|
|
244
|
+
// console.log(action.time, transition.exitTime);
|
|
245
245
|
}
|
|
246
246
|
this.transitionTo(transition.destinationState as State, transition.duration, transition.offset);
|
|
247
247
|
// use the first transition that matches all conditions and make the transition as soon as in range
|
|
@@ -252,7 +252,7 @@ export class AnimatorController {
|
|
|
252
252
|
this.transitionTo(transition.destinationState as State, transition.duration, transition.offset);
|
|
253
253
|
return;
|
|
254
254
|
}
|
|
255
|
-
|
|
255
|
+
// if none of the transitions can be made continue searching for another transition meeting the conditions
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
let didTriggerLooping = false;
|
|
@@ -376,7 +376,13 @@ export class AnimatorController {
|
|
|
376
376
|
}
|
|
377
377
|
|
|
378
378
|
private createAction(clip: AnimationClip) {
|
|
379
|
-
|
|
379
|
+
|
|
380
|
+
// uncache clip causes issues when multiple states use the same clip
|
|
381
|
+
// this._mixer.uncacheClip(clip);
|
|
382
|
+
// instead only uncache the action when one already exists to make sure
|
|
383
|
+
// we get unique actions per state
|
|
384
|
+
const existing = this._mixer.existingAction(clip);
|
|
385
|
+
if (existing) this._mixer.uncacheAction(clip, this.animator?.gameObject);
|
|
380
386
|
|
|
381
387
|
if (this.animator?.applyRootMotion) {
|
|
382
388
|
if (!this.rootMotionHandler) {
|
|
@@ -387,7 +393,6 @@ export class AnimatorController {
|
|
|
387
393
|
return this.rootMotionHandler.createClip(this._mixer, root, clip);
|
|
388
394
|
}
|
|
389
395
|
else {
|
|
390
|
-
|
|
391
396
|
const action = this._mixer.clipAction(clip);
|
|
392
397
|
return action;
|
|
393
398
|
}
|
|
@@ -55,6 +55,7 @@ export class BoxHelperComponent extends Behaviour {
|
|
|
55
55
|
// this.tp.applyMatrix4(obj.matrixWorld);
|
|
56
56
|
// console.log(this.tp);
|
|
57
57
|
// console.log(this.box?.min, this.box?.max, this.tp.min, this.tp.max);
|
|
58
|
+
this.updateBox();
|
|
58
59
|
return this.box?.intersectsBox(BoxHelperComponent.testBox);
|
|
59
60
|
}
|
|
60
61
|
|