@@ -1,6 +1,6 @@
|
|
1
|
-
import
|
1
|
+
import { FileLoader } from "three";
|
2
2
|
|
3
|
-
export const loader = new
|
3
|
+
export const loader = new FileLoader();
|
4
4
|
|
5
5
|
export async function loadFileAsync(url) {
|
6
6
|
return new Promise((resolve, reject) => {
|
@@ -7,11 +7,11 @@
|
|
7
7
|
name: "needle-license",
|
8
8
|
enforce: 'pre',
|
9
9
|
async transform(src, id) {
|
10
|
-
if (id.includes("engine/engine_license.
|
10
|
+
if (id.includes("engine/engine_license") || id.includes("needle-tools_engine.js")) {
|
11
11
|
const needleConfig = await loadConfig();
|
12
12
|
if (needleConfig) {
|
13
13
|
if (needleConfig.hasProLicense !== undefined && typeof needleConfig.hasProLicense === "boolean") {
|
14
|
-
src = src.replace("
|
14
|
+
src = src.replace("NEEDLE_ENGINE_COMMERCIAL_USE_LICENSE = false;", "NEEDLE_ENGINE_COMMERCIAL_USE_LICENSE = " + needleConfig.hasProLicense + ";");
|
15
15
|
return { code: src, map: null }
|
16
16
|
}
|
17
17
|
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { TypeStore } from "./../engine_typestore"
|
2
|
-
|
2
|
+
|
3
3
|
// Import types
|
4
4
|
import { __Ignore } from "../../engine-components/codegen/components";
|
5
5
|
import { AlignmentConstraint } from "../../engine-components/AlignmentConstraint";
|
@@ -184,7 +184,7 @@
|
|
184
184
|
import { XRGrabRendering } from "../../engine-components/WebXRGrabRendering";
|
185
185
|
import { XRRig } from "../../engine-components/WebXRRig";
|
186
186
|
import { XRState } from "../../engine-components/XRFlag";
|
187
|
-
|
187
|
+
|
188
188
|
// Register types
|
189
189
|
TypeStore.add("__Ignore", __Ignore);
|
190
190
|
TypeStore.add("AlignmentConstraint", AlignmentConstraint);
|
@@ -1,9 +1,7 @@
|
|
1
1
|
import { Behaviour } from "./Component";
|
2
|
-
import
|
3
|
-
import { AnimationAction, AnimationClip, Vector2 } from "three";
|
2
|
+
import { AnimationAction, AnimationClip, AnimationMixer, LoopOnce, LoopRepeat } from "three";
|
4
3
|
import { MixerEvent } from "./Animator";
|
5
4
|
import { serializable } from "../engine/engine_serialization_decorator";
|
6
|
-
import { InstancingUtil } from "../engine/engine_instancing";
|
7
5
|
import { Mathf } from "../engine/engine_math";
|
8
6
|
import { Vec2 } from "../engine/engine_types";
|
9
7
|
import { getParam } from "../engine/engine_utils";
|
@@ -63,7 +61,7 @@
|
|
63
61
|
this.animations = animations;
|
64
62
|
}
|
65
63
|
|
66
|
-
set animations(animations:
|
64
|
+
set animations(animations: AnimationClip[]) {
|
67
65
|
if (debug) console.log("assign animations", animations);
|
68
66
|
this.gameObject.animations = animations;
|
69
67
|
}
|
@@ -74,29 +72,29 @@
|
|
74
72
|
/**
|
75
73
|
* @deprecated Currently unsupported
|
76
74
|
*/
|
77
|
-
get currentAction():
|
75
|
+
get currentAction(): AnimationAction | null {
|
78
76
|
return this._currentActions[0];
|
79
77
|
}
|
80
78
|
|
81
79
|
/**
|
82
80
|
* @deprecated Currently unsupported
|
83
81
|
*/
|
84
|
-
get currentActions():
|
82
|
+
get currentActions(): AnimationAction[] {
|
85
83
|
return this._currentActions;
|
86
84
|
}
|
87
85
|
|
88
|
-
private mixer:
|
89
|
-
get actions(): Array<
|
86
|
+
private mixer: AnimationMixer | undefined = undefined;
|
87
|
+
get actions(): Array<AnimationAction> {
|
90
88
|
return this._actions;
|
91
89
|
}
|
92
|
-
set actions(val: Array<
|
90
|
+
set actions(val: Array<AnimationAction>) {
|
93
91
|
this._actions = val;
|
94
92
|
}
|
95
|
-
private _actions: Array<
|
93
|
+
private _actions: Array<AnimationAction> = [];
|
96
94
|
|
97
|
-
// private _currentAction:
|
95
|
+
// private _currentAction: AnimationAction | null = null;
|
98
96
|
|
99
|
-
private _currentActions:
|
97
|
+
private _currentActions: AnimationAction[] = [];
|
100
98
|
private _handles: AnimationHandle[] = [];
|
101
99
|
|
102
100
|
awake() {
|
@@ -133,7 +131,7 @@
|
|
133
131
|
// InstancingUtil.markDirty(this.gameObject);
|
134
132
|
}
|
135
133
|
|
136
|
-
getAction(name: string):
|
134
|
+
getAction(name: string): AnimationAction | undefined | null {
|
137
135
|
return this.actions?.find(a => a.getClip().name === name);
|
138
136
|
}
|
139
137
|
|
@@ -210,8 +208,8 @@
|
|
210
208
|
if (options?.startTime !== undefined) action.time = options.startTime;
|
211
209
|
|
212
210
|
if (options?.loop !== undefined)
|
213
|
-
action.loop = options.loop ?
|
214
|
-
else action.loop =
|
211
|
+
action.loop = options.loop ? LoopRepeat : LoopOnce;
|
212
|
+
else action.loop = LoopOnce;
|
215
213
|
action.play();
|
216
214
|
if (debug)
|
217
215
|
console.log("PLAY", action.getClip().name, action)
|
@@ -239,14 +237,14 @@
|
|
239
237
|
this._didInit = true;
|
240
238
|
if (!this.gameObject) return;
|
241
239
|
this.actions = [];
|
242
|
-
this.mixer = new
|
240
|
+
this.mixer = new AnimationMixer(this.gameObject);
|
243
241
|
}
|
244
242
|
}
|
245
243
|
|
246
244
|
|
247
245
|
class AnimationHandle {
|
248
|
-
mixer:
|
249
|
-
action:
|
246
|
+
mixer: AnimationMixer;
|
247
|
+
action: AnimationAction;
|
250
248
|
promise: Promise<AnimationAction> | null = null;
|
251
249
|
resolve: Function | null = null;
|
252
250
|
reject: Function | null = null;
|
@@ -258,7 +256,7 @@
|
|
258
256
|
private _finishedCallback?: any;
|
259
257
|
private _resolvedOrRejectedCallback?: (AnimationHandle) => void;
|
260
258
|
|
261
|
-
constructor(action:
|
259
|
+
constructor(action: AnimationAction, mixer: AnimationMixer, opts?: PlayOptions, cb?: (handle: AnimationHandle) => void) {
|
262
260
|
this.action = action;
|
263
261
|
this.mixer = mixer;
|
264
262
|
this._resolvedOrRejectedCallback = cb;
|
@@ -1,7 +1,6 @@
|
|
1
1
|
import { Behaviour } from "./Component";
|
2
|
-
import
|
3
|
-
import {
|
4
|
-
import { getParam, deepClone } from "../engine/engine_utils";
|
2
|
+
import { AnimationActionLoopStyles, AnimationAction, AnimationMixer } from "three";
|
3
|
+
import { getParam } from "../engine/engine_utils";
|
5
4
|
import { AnimatorControllerModel } from "../engine/extensions/NEEDLE_animator_controller_model";
|
6
5
|
import { AnimatorController } from "./AnimatorController";
|
7
6
|
import { serializable } from "../engine/engine_serialization_decorator";
|
@@ -12,9 +11,9 @@
|
|
12
11
|
|
13
12
|
export declare class MixerEvent {
|
14
13
|
type: string;
|
15
|
-
action:
|
14
|
+
action: AnimationAction;
|
16
15
|
loopDelta: number;
|
17
|
-
target:
|
16
|
+
target: AnimationMixer;
|
18
17
|
}
|
19
18
|
|
20
19
|
export declare class PlayOptions {
|
@@ -1,9 +1,8 @@
|
|
1
1
|
import { Animator } from "./Animator";
|
2
2
|
import { AnimatorConditionMode, AnimatorControllerModel, AnimatorControllerParameterType, AnimatorStateInfo, Condition, createMotion, State, StateMachineBehaviour } from "../engine/extensions/NEEDLE_animator_controller_model";
|
3
|
-
import { AnimationAction, AnimationClip, AnimationMixer, AxesHelper, Euler, KeyframeTrack, LoopOnce,
|
3
|
+
import { AnimationAction, AnimationClip, AnimationMixer, AxesHelper, Euler, KeyframeTrack, LoopOnce, Object3D, Quaternion, Vector3 } from "three";
|
4
4
|
import { deepClone, getParam } from "../engine/engine_utils";
|
5
5
|
import { Context } from "../engine/engine_setup";
|
6
|
-
import * as THREE from "three";
|
7
6
|
import { TypeStore } from "../engine/engine_typestore";
|
8
7
|
import { assign } from "../engine/engine_serialization_core";
|
9
8
|
import { Mathf } from "../engine/engine_math";
|
@@ -110,7 +109,7 @@
|
|
110
109
|
get context(): Context | undefined | null { return this.animator?.context; }
|
111
110
|
|
112
111
|
|
113
|
-
// applyRootMotion(obj:
|
112
|
+
// applyRootMotion(obj: Object3D) {
|
114
113
|
// // this.internalApplyRootMotion(obj);
|
115
114
|
// }
|
116
115
|
|
@@ -160,7 +159,7 @@
|
|
160
159
|
}
|
161
160
|
|
162
161
|
|
163
|
-
private _mixer!:
|
162
|
+
private _mixer!: AnimationMixer;
|
164
163
|
private _activeState?: State;
|
165
164
|
|
166
165
|
constructor(model: AnimatorControllerModel) {
|
@@ -541,10 +540,10 @@
|
|
541
540
|
private rootMotionHandler?: RootMotionHandler;
|
542
541
|
|
543
542
|
|
544
|
-
// private findRootBone(obj:
|
543
|
+
// private findRootBone(obj: Object3D): Object3D | null {
|
545
544
|
// if (this.animationRoot) return this.animationRoot;
|
546
545
|
// if (obj.type === "Bone") {
|
547
|
-
// this.animationRoot = obj as
|
546
|
+
// this.animationRoot = obj as Bone;
|
548
547
|
// return this.animationRoot;
|
549
548
|
// }
|
550
549
|
// if (obj.children) {
|
@@ -601,16 +600,16 @@
|
|
601
600
|
|
602
601
|
class RootMotionAction {
|
603
602
|
|
604
|
-
private static lastObjPosition: { [key: string]:
|
605
|
-
static lastObjRotation: { [key: string]:
|
603
|
+
private static lastObjPosition: { [key: string]: Vector3 } = {};
|
604
|
+
static lastObjRotation: { [key: string]: Quaternion } = {};
|
606
605
|
|
607
606
|
// we remove the first keyframe rotation from the space rotation when updating
|
608
|
-
private static firstKeyframeRotation: { [key: string]:
|
607
|
+
private static firstKeyframeRotation: { [key: string]: Quaternion } = {};
|
609
608
|
// this is used to rotate the space on clip end / start (so the transform direction is correct)
|
610
|
-
private static spaceRotation: { [key: string]:
|
611
|
-
private static effectiveSpaceRotation: { [key: string]:
|
609
|
+
private static spaceRotation: { [key: string]: Quaternion } = {};
|
610
|
+
private static effectiveSpaceRotation: { [key: string]: Quaternion } = {};
|
612
611
|
|
613
|
-
private static clipOffsetRotation: { [key: string]:
|
612
|
+
private static clipOffsetRotation: { [key: string]: Quaternion } = {};
|
614
613
|
|
615
614
|
|
616
615
|
set action(val: AnimationAction) {
|
@@ -631,14 +630,14 @@
|
|
631
630
|
positionChange: Vector3 = new Vector3();
|
632
631
|
rotationChange: Quaternion = new Quaternion();
|
633
632
|
|
634
|
-
constructor(context: Context, root:
|
633
|
+
constructor(context: Context, root: Object3D, clip: AnimationClip, positionTrack: KeyframeTrack | null, rotationTrack: KeyframeTrack | null) {
|
635
634
|
// console.log(this, positionTrack, rotationTrack);
|
636
635
|
this.context = context;
|
637
636
|
this.root = root;
|
638
637
|
this.clip = clip;
|
639
638
|
|
640
639
|
if (!RootMotionAction.firstKeyframeRotation[clip.uuid])
|
641
|
-
RootMotionAction.firstKeyframeRotation[clip.uuid] = new
|
640
|
+
RootMotionAction.firstKeyframeRotation[clip.uuid] = new Quaternion();
|
642
641
|
if (rotationTrack) {
|
643
642
|
const values = rotationTrack.values;
|
644
643
|
RootMotionAction.firstKeyframeRotation[clip.uuid]
|
@@ -672,7 +671,7 @@
|
|
672
671
|
|
673
672
|
if (debugRootMotion)
|
674
673
|
{
|
675
|
-
const euler = new
|
674
|
+
const euler = new Euler().setFromQuaternion(lastRotation);
|
676
675
|
console.log("START", this.clip.name, Mathf.toDegrees(euler.y));
|
677
676
|
}
|
678
677
|
}
|
@@ -799,13 +798,13 @@
|
|
799
798
|
|
800
799
|
private controller: AnimatorController;
|
801
800
|
private handler: RootMotionAction[] = [];
|
802
|
-
private root!:
|
801
|
+
private root!: Object3D;
|
803
802
|
|
804
803
|
constructor(controller: AnimatorController) {
|
805
804
|
this.controller = controller;
|
806
805
|
}
|
807
806
|
|
808
|
-
createClip(mixer: AnimationMixer, root:
|
807
|
+
createClip(mixer: AnimationMixer, root: Object3D, clip: AnimationClip): AnimationAction {
|
809
808
|
this.root = root;
|
810
809
|
let rootName = "";
|
811
810
|
if (root && "name" in root) {
|
@@ -1,1 +1,3 @@
|
|
1
|
+
export * from "./codegen/components";
|
2
|
+
export * from "./js-extensions/Object3D";
|
1
3
|
export * from "./ui/PointerEvents"
|
@@ -3,9 +3,12 @@
|
|
3
3
|
export * from "./engine_context_registry";
|
4
4
|
export * from "./extensions/extensions"
|
5
5
|
export { InstancingUtil } from "./engine_instancing";
|
6
|
+
export * from "./engine_types"
|
6
7
|
export * from "./engine_gameobject";
|
7
8
|
export * from "./engine_components";
|
8
9
|
export * from "./engine_components_internal";
|
10
|
+
export * from "./engine_input"
|
11
|
+
export * from "./engine_coroutine"
|
9
12
|
export { AssetReference, ImageReference } from "./engine_addressables";
|
10
13
|
export { Context, FrameEvent } from "./engine_setup";
|
11
14
|
export * from "./debug/debug";
|
@@ -14,7 +17,8 @@
|
|
14
17
|
export * from "./engine_scenetools";
|
15
18
|
export * from "./engine_math"
|
16
19
|
export * from "./js-extensions"
|
17
|
-
export { hasProLicense } from "./engine_license"
|
20
|
+
export { hasProLicense } from "./engine_license";
|
21
|
+
export { syncField } from "./engine_networking_auto";
|
18
22
|
|
19
23
|
export {
|
20
24
|
// url params
|
@@ -1,18 +1,18 @@
|
|
1
1
|
import { Behaviour, GameObject } from "./Component";
|
2
|
-
import
|
2
|
+
import { AudioListener as ThreeAudioListener } from "three";
|
3
3
|
import { AudioSource } from "./AudioSource";
|
4
4
|
import { Camera } from "./Camera";
|
5
5
|
|
6
6
|
|
7
7
|
export class AudioListener extends Behaviour {
|
8
8
|
|
9
|
-
get listener():
|
9
|
+
get listener(): ThreeAudioListener {
|
10
10
|
if (this._listener == null)
|
11
|
-
this._listener = new
|
11
|
+
this._listener = new ThreeAudioListener();
|
12
12
|
return this._listener;
|
13
13
|
}
|
14
14
|
|
15
|
-
private _listener:
|
15
|
+
private _listener: ThreeAudioListener | null = null;
|
16
16
|
|
17
17
|
awake() {
|
18
18
|
AudioSource.registerWaitForAllowAudio(() => {
|
@@ -1,10 +1,10 @@
|
|
1
1
|
import { Behaviour, GameObject } from "./Component";
|
2
|
-
import * as THREE from "three";
|
3
2
|
import { PositionalAudioHelper } from 'three/examples/jsm/helpers/PositionalAudioHelper.js';
|
4
3
|
import { AudioListener } from "./AudioListener";
|
5
4
|
import * as utils from "../engine/engine_utils";
|
6
5
|
import { serializable } from "../engine/engine_serialization_decorator";
|
7
|
-
import {
|
6
|
+
import { ApplicationEvents } from "../engine/engine_application";
|
7
|
+
import { AudioLoader, PositionalAudio } from "three";
|
8
8
|
|
9
9
|
|
10
10
|
const debug = utils.getParam("debugaudio");
|
@@ -146,20 +146,20 @@
|
|
146
146
|
playInBackground: boolean = true;
|
147
147
|
|
148
148
|
private _loop: boolean = false;
|
149
|
-
private sound:
|
149
|
+
private sound: PositionalAudio | null = null;
|
150
150
|
private helper: PositionalAudioHelper | null = null;
|
151
151
|
private wasPlaying = false;
|
152
|
-
private audioLoader:
|
152
|
+
private audioLoader: AudioLoader | null = null;
|
153
153
|
private shouldPlay: boolean = false;
|
154
154
|
// set this from audio context time, used to set clip offset when setting "time" property
|
155
155
|
// there is maybe a better way to set a audio clip current time?!
|
156
156
|
private _lastClipStartedLoading: string | null = null;
|
157
157
|
|
158
|
-
public get Sound():
|
158
|
+
public get Sound(): PositionalAudio | null {
|
159
159
|
if (!this.sound && AudioSource._userInteractionRegistered) {
|
160
160
|
const listener = GameObject.getComponent(this.context.mainCamera, AudioListener) ?? GameObject.findObjectOfType(AudioListener, this.context);
|
161
161
|
if (listener?.listener) {
|
162
|
-
this.sound = new
|
162
|
+
this.sound = new PositionalAudio(listener.listener);
|
163
163
|
this.gameObject.add(this.sound);
|
164
164
|
}
|
165
165
|
}
|
@@ -170,7 +170,7 @@
|
|
170
170
|
|
171
171
|
|
172
172
|
awake() {
|
173
|
-
this.audioLoader = new
|
173
|
+
this.audioLoader = new AudioLoader();
|
174
174
|
if (this.playOnAwake) this.shouldPlay = true;
|
175
175
|
}
|
176
176
|
|
@@ -294,7 +294,7 @@
|
|
294
294
|
console.log(this.clip);
|
295
295
|
if (this.clip.endsWith(".mp3") || this.clip.endsWith(".wav")) {
|
296
296
|
if (!this.audioLoader)
|
297
|
-
this.audioLoader = new
|
297
|
+
this.audioLoader = new AudioLoader();
|
298
298
|
this.shouldPlay = true;
|
299
299
|
if (this._lastClipStartedLoading === this.clip) {
|
300
300
|
if (debug) console.log("Is currently loading:", this._lastClipStartedLoading, this)
|
@@ -1,28 +1,27 @@
|
|
1
|
-
import {
|
2
|
-
import * as THREE from "three";
|
1
|
+
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
|
3
2
|
import * as utils from "../engine/engine_utils"
|
4
|
-
// import * as object from "../engine/engine_gltf_builtin_components";
|
5
3
|
import * as loaders from "../engine/engine_loaders"
|
6
4
|
import { Context } from "../engine/engine_setup";
|
7
5
|
import { GameObject } from "./Component";
|
8
6
|
import { download_file } from "../engine/engine_web_api";
|
9
7
|
import { getLoader } from "../engine/engine_gltf";
|
10
8
|
import { InstantiateOptions } from "../engine/engine_gameobject";
|
9
|
+
import { Box3, Object3D, Vector3 } from "three";
|
11
10
|
|
12
11
|
const debug = utils.getParam("debugavatar");
|
13
12
|
|
14
13
|
export class AvatarModel {
|
15
|
-
root:
|
16
|
-
head:
|
17
|
-
leftHand:
|
18
|
-
rigthHand:
|
14
|
+
root: Object3D;
|
15
|
+
head: Object3D;
|
16
|
+
leftHand: Object3D | null;
|
17
|
+
rigthHand: Object3D | null;
|
19
18
|
|
20
19
|
|
21
20
|
get isValid(): boolean {
|
22
21
|
return this.head !== null && this.head !== undefined;
|
23
22
|
}
|
24
23
|
|
25
|
-
constructor(root:
|
24
|
+
constructor(root: Object3D, head: Object3D, leftHand: Object3D | null, rigthHand: Object3D | null) {
|
26
25
|
this.root = root;
|
27
26
|
this.head = head;
|
28
27
|
this.leftHand = leftHand;
|
@@ -40,14 +39,14 @@
|
|
40
39
|
// private loader: GLTFLoader | null;
|
41
40
|
// private avatarModelCache: Map<string, AvatarModel | null> = new Map<string, AvatarModel | null>();
|
42
41
|
|
43
|
-
public async getOrCreateNewAvatarInstance(context: Context, avatarId: string |
|
42
|
+
public async getOrCreateNewAvatarInstance(context: Context, avatarId: string | Object3D): Promise<AvatarModel | null> {
|
44
43
|
|
45
44
|
if (!avatarId) {
|
46
45
|
console.error("Can not create avatar: failed to provide id or root object");
|
47
46
|
return null;
|
48
47
|
}
|
49
48
|
|
50
|
-
let root:
|
49
|
+
let root: Object3D | null = null;
|
51
50
|
if (typeof avatarId === "string") {
|
52
51
|
root = await this.loadAvatar(context, avatarId);
|
53
52
|
if (!root) {
|
@@ -77,7 +76,7 @@
|
|
77
76
|
}
|
78
77
|
|
79
78
|
|
80
|
-
private async loadAvatar(context: Context, avatarId: string): Promise<
|
79
|
+
private async loadAvatar(context: Context, avatarId: string): Promise<Object3D | null> {
|
81
80
|
|
82
81
|
console.assert(avatarId !== undefined && avatarId !== null && typeof avatarId === "string", "Avatar id must not be null");
|
83
82
|
if (avatarId.length <= 0) return null;
|
@@ -146,9 +145,9 @@
|
|
146
145
|
}
|
147
146
|
|
148
147
|
// TODO this should be burned to the ground once 🤞 we have proper extras that define object relations.
|
149
|
-
private findAvatar(obj:
|
148
|
+
private findAvatar(obj: Object3D): AvatarModel {
|
150
149
|
|
151
|
-
const root:
|
150
|
+
const root: Object3D = obj;
|
152
151
|
let searchIn = root;
|
153
152
|
// some GLTFs have a "scene" root it seems, others don't, we skip the root here if there's only one child
|
154
153
|
if (searchIn.children.length == 1)
|
@@ -163,8 +162,8 @@
|
|
163
162
|
head = root;
|
164
163
|
|
165
164
|
// normalize size, if the object isn't properly setup the scale might be totally off
|
166
|
-
const boundsSize = new
|
167
|
-
new
|
165
|
+
const boundsSize = new Vector3();
|
166
|
+
new Box3().setFromObject(head).getSize(boundsSize);
|
168
167
|
const maxAxis = Math.max(boundsSize.x, boundsSize.y, boundsSize.z);
|
169
168
|
console.warn("[Custom Avatar] " + "Normalizing head scale, it's too big: " + maxAxis + " meters! Should be < 0.3m");
|
170
169
|
if (maxAxis > 0.3) {
|
@@ -177,7 +176,7 @@
|
|
177
176
|
}
|
178
177
|
|
179
178
|
|
180
|
-
private findAvatarPart(obj:
|
179
|
+
private findAvatarPart(obj: Object3D, searchString: string[]): Object3D | null {
|
181
180
|
|
182
181
|
const name = obj.name.toLowerCase();
|
183
182
|
let matchesAll = true;
|
@@ -11,7 +11,7 @@
|
|
11
11
|
@serializable()
|
12
12
|
public isGizmo:boolean = true;
|
13
13
|
|
14
|
-
private _axes:
|
14
|
+
private _axes: _AxesHelper | null = null;
|
15
15
|
|
16
16
|
onEnable(): void {
|
17
17
|
if (this.isGizmo && !params.showGizmos) return;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { Behaviour, GameObject } from "./Component";
|
2
2
|
import * as utils from "./../engine/engine_three_utils";
|
3
|
-
import
|
3
|
+
import { Vector3 } from "three";
|
4
4
|
|
5
5
|
export class BasicIKConstraint extends Behaviour {
|
6
6
|
|
@@ -33,7 +33,7 @@
|
|
33
33
|
let hintDir = utils.getWorldPosition(this.hint).clone();
|
34
34
|
hintDir.sub(center);
|
35
35
|
|
36
|
-
let offsetDir = new
|
36
|
+
let offsetDir = new Vector3();
|
37
37
|
offsetDir.crossVectors(hintDir, dir0);
|
38
38
|
offsetDir.crossVectors(dir0, offsetDir);
|
39
39
|
offsetDir.normalize();
|
@@ -1,28 +1,28 @@
|
|
1
1
|
import { Behaviour } from "./Component";
|
2
|
-
import * as THREE from "three";
|
3
2
|
import { getParam } from "../engine/engine_utils";
|
4
3
|
import { CreateWireCube, Gizmos } from "../engine/engine_gizmos";
|
5
4
|
import { getWorldPosition, getWorldScale } from "../engine/engine_three_utils";
|
5
|
+
import { Box3, Color, ColorRepresentation, LineSegments, Object3D, Vector3 } from "three";
|
6
6
|
|
7
7
|
const gizmos = getParam("gizmos");
|
8
8
|
const debug = getParam("debugboxhelper");
|
9
9
|
|
10
10
|
export class BoxHelperComponent extends Behaviour {
|
11
11
|
|
12
|
-
private box:
|
13
|
-
private static testBox:
|
12
|
+
private box: Box3 | null = null;
|
13
|
+
private static testBox: Box3 = new Box3();
|
14
14
|
private _lastMatrixUpdateFrame: number = -1;
|
15
|
-
private static _position:
|
16
|
-
private static _size:
|
15
|
+
private static _position: Vector3 = new Vector3();
|
16
|
+
private static _size: Vector3 = new Vector3(.01, .01, .01);
|
17
17
|
|
18
|
-
public isInBox(obj:
|
18
|
+
public isInBox(obj: Object3D, scaleFactor?: number): boolean | undefined {
|
19
19
|
if (!obj) return undefined;
|
20
20
|
|
21
21
|
// if (!obj.geometry.boundingBox) obj.geometry.computeBoundingBox();
|
22
22
|
// if (!obj.geometry.boundingBox) return undefined;
|
23
23
|
|
24
24
|
if (!this.box) {
|
25
|
-
this.box = new
|
25
|
+
this.box = new Box3();
|
26
26
|
}
|
27
27
|
|
28
28
|
|
@@ -56,14 +56,14 @@
|
|
56
56
|
return intersects;
|
57
57
|
}
|
58
58
|
|
59
|
-
public intersects(box:
|
59
|
+
public intersects(box: Box3): boolean {
|
60
60
|
if (!box) return false;
|
61
61
|
return this.updateBox(false).intersectsBox(box);
|
62
62
|
}
|
63
63
|
|
64
|
-
public updateBox(force: boolean = false):
|
64
|
+
public updateBox(force: boolean = false): Box3 {
|
65
65
|
if (!this.box) {
|
66
|
-
this.box = new
|
66
|
+
this.box = new Box3();
|
67
67
|
}
|
68
68
|
if (force || this.context.time.frameCount != this._lastMatrixUpdateFrame) {
|
69
69
|
const firstUpdate = this._lastMatrixUpdateFrame < 0;
|
@@ -77,8 +77,8 @@
|
|
77
77
|
}
|
78
78
|
|
79
79
|
|
80
|
-
private _helper:
|
81
|
-
private _color:
|
80
|
+
private _helper: LineSegments | null = null;
|
81
|
+
private _color: Color | null = null;
|
82
82
|
|
83
83
|
awake(): void {
|
84
84
|
this._helper = null;
|
@@ -86,7 +86,7 @@
|
|
86
86
|
this.box = null;
|
87
87
|
}
|
88
88
|
|
89
|
-
public showHelper(col:
|
89
|
+
public showHelper(col: ColorRepresentation | null = null, force: boolean = false) {
|
90
90
|
if (!gizmos && !force) return;
|
91
91
|
if (this._helper) {
|
92
92
|
if (col)
|
@@ -1,15 +1,14 @@
|
|
1
|
-
import * as THREE from "three";
|
2
1
|
import { Mathf } from "../engine/engine_math";
|
3
2
|
import * as threeutils from "../engine/engine_three_utils";
|
4
3
|
import { activeInHierarchyFieldName } from "../engine/engine_constants";
|
5
4
|
import { Context, FrameEvent } from "../engine/engine_setup";
|
6
5
|
import * as main from "../engine/engine_mainloop_utils";
|
7
|
-
import { Object3D } from "three";
|
8
6
|
import { syncDestroy, syncInstantiate } from "../engine/engine_networking_instantiate";
|
9
|
-
import { ConstructorConcrete, SourceIdentifier, IComponent, IGameObject, Constructor, GuidsMap,
|
7
|
+
import { ConstructorConcrete, SourceIdentifier, IComponent, IGameObject, Constructor, GuidsMap, Collision, ICollider } from "../engine/engine_types";
|
10
8
|
import { addNewComponent, destroyComponentInstance, findObjectOfType, findObjectsOfType, getComponent, getComponentInChildren, getComponentInParent, getComponents, getComponentsInChildren, getComponentsInParent, getOrAddComponent, moveComponentInstance, removeComponent } from "../engine/engine_components";
|
11
9
|
import { findByGuid, destroy, InstantiateOptions, instantiate, HideFlags, foreachComponent, markAsInstancedRendered, isActiveInHierarchy, isActiveSelf, isUsingInstancing, setActive, isDestroyed } from "../engine/engine_gameobject";
|
12
10
|
|
11
|
+
import { Euler, Object3D, Quaternion, Scene, Vector3 } from "three";
|
13
12
|
|
14
13
|
// export interface ISerializationCallbackReceiver {
|
15
14
|
// onBeforeSerialize?(): object | void;
|
@@ -19,7 +18,7 @@
|
|
19
18
|
// onDeserialize?(key: string, value: any): any | void;
|
20
19
|
// }
|
21
20
|
|
22
|
-
abstract class GameObject extends
|
21
|
+
abstract class GameObject extends Object3D implements Object3D, IGameObject {
|
23
22
|
|
24
23
|
guid: string | undefined;
|
25
24
|
|
@@ -27,13 +26,13 @@
|
|
27
26
|
abstract destroy();
|
28
27
|
|
29
28
|
// The actual implementation / prototype of threejs is modified in js-extensions/Object3D
|
30
|
-
abstract get transform():
|
29
|
+
abstract get transform(): Object3D;
|
31
30
|
|
32
|
-
public static isDestroyed(go:
|
31
|
+
public static isDestroyed(go: Object3D): boolean {
|
33
32
|
return isDestroyed(go);
|
34
33
|
}
|
35
34
|
|
36
|
-
public static setActive(go:
|
35
|
+
public static setActive(go: Object3D, active: boolean, processStart: boolean = true) {
|
37
36
|
if (!go) return;
|
38
37
|
setActive(go, active);
|
39
38
|
|
@@ -44,29 +43,29 @@
|
|
44
43
|
}
|
45
44
|
|
46
45
|
/** If the object is active (same as go.visible) */
|
47
|
-
public static isActiveSelf(go:
|
46
|
+
public static isActiveSelf(go: Object3D): boolean {
|
48
47
|
return isActiveSelf(go);
|
49
48
|
}
|
50
49
|
|
51
50
|
/** If the object is active in the hierarchy (e.g. if any parent is invisible or not in the scene it will be false)
|
52
51
|
* @param go object to check
|
53
52
|
*/
|
54
|
-
public static isActiveInHierarchy(go:
|
53
|
+
public static isActiveInHierarchy(go: Object3D): boolean {
|
55
54
|
return isActiveInHierarchy(go);
|
56
55
|
}
|
57
56
|
|
58
|
-
public static markAsInstancedRendered(go:
|
57
|
+
public static markAsInstancedRendered(go: Object3D, instanced: boolean) {
|
59
58
|
markAsInstancedRendered(go, instanced);
|
60
59
|
}
|
61
60
|
|
62
|
-
public static isUsingInstancing(instance:
|
61
|
+
public static isUsingInstancing(instance: Object3D): boolean { return isUsingInstancing(instance); }
|
63
62
|
|
64
63
|
/** Run a callback for all components of the provided type on the provided object and its children (if recursive is true)
|
65
64
|
* @param instance object to run the method on
|
66
65
|
* @param cb callback to run on each component
|
67
66
|
* @param recursive if true, the method will be run on all children as well
|
68
67
|
*/
|
69
|
-
public static foreachComponent(instance:
|
68
|
+
public static foreachComponent(instance: Object3D, cb: (comp: Component) => any, recursive: boolean = true): any {
|
70
69
|
return foreachComponent(instance, cb as (comp: IComponent) => any, recursive);
|
71
70
|
}
|
72
71
|
|
@@ -90,7 +89,7 @@
|
|
90
89
|
/** Destroys a object on all connected clients (if you are in a networked session)
|
91
90
|
* @param instance object to destroy
|
92
91
|
*/
|
93
|
-
public static destroySynced(instance:
|
92
|
+
public static destroySynced(instance: Object3D | Component, context?: Context, recursive: boolean = true) {
|
94
93
|
if (!instance) return;
|
95
94
|
const go = instance as GameObject;
|
96
95
|
context = context ?? Context.Current;
|
@@ -101,14 +100,14 @@
|
|
101
100
|
* @param instance object to destroy
|
102
101
|
* @param recursive if true, all children will be destroyed as well
|
103
102
|
*/
|
104
|
-
public static destroy(instance:
|
103
|
+
public static destroy(instance: Object3D | Component, recursive: boolean = true, isRoot: boolean = true) {
|
105
104
|
return destroy(instance, recursive, isRoot);
|
106
105
|
}
|
107
106
|
|
108
107
|
/**
|
109
108
|
* Add an object to parent and also ensure all components are being registered
|
110
109
|
*/
|
111
|
-
public static add(instance:
|
110
|
+
public static add(instance: Object3D | null | undefined, parent: Object3D, context?: Context) {
|
112
111
|
if (!instance || !parent) return;
|
113
112
|
if (instance === parent) {
|
114
113
|
console.warn("Can not add object to self", instance);
|
@@ -137,7 +136,7 @@
|
|
137
136
|
/**
|
138
137
|
* Removes the object from its parent and deactivates all of its components
|
139
138
|
*/
|
140
|
-
public static remove(instance:
|
139
|
+
public static remove(instance: Object3D | null | undefined) {
|
141
140
|
if (!instance) return;
|
142
141
|
instance.parent?.remove(instance);
|
143
142
|
setActive(instance, false);
|
@@ -148,7 +147,7 @@
|
|
148
147
|
}
|
149
148
|
|
150
149
|
/** Invokes a method on all components including children (if a method with that name exists) */
|
151
|
-
public static invokeOnChildren(go:
|
150
|
+
public static invokeOnChildren(go: Object3D | null | undefined, functionName: string, ...args: any) {
|
152
151
|
this.invoke(go, functionName, true, args);
|
153
152
|
}
|
154
153
|
|
@@ -156,7 +155,7 @@
|
|
156
155
|
* @param go object to invoke the method on all components
|
157
156
|
* @param functionName name of the method to invoke
|
158
157
|
*/
|
159
|
-
public static invoke(go:
|
158
|
+
public static invoke(go: Object3D | null | undefined, functionName: string, children: boolean = false, ...args: any) {
|
160
159
|
if (!go) return;
|
161
160
|
this.foreachComponent(go, c => {
|
162
161
|
const fn = c[functionName];
|
@@ -172,7 +171,7 @@
|
|
172
171
|
* @param type type of the component to add
|
173
172
|
* @param callAwake if true, the component will be added and awake will be called immediately
|
174
173
|
*/
|
175
|
-
public static addNewComponent<T>(go:
|
174
|
+
public static addNewComponent<T>(go: IGameObject | Object3D, type: ConstructorConcrete<T>, callAwake: boolean = true): T {
|
176
175
|
const instance = new type();
|
177
176
|
//@ts-ignore
|
178
177
|
addNewComponent(go, instance, callAwake);
|
@@ -185,7 +184,7 @@
|
|
185
184
|
* @param go component to move the component to
|
186
185
|
* @param instance component to move to the GO
|
187
186
|
*/
|
188
|
-
public static addComponent(go:
|
187
|
+
public static addComponent(go: IGameObject, instance: Component): void {
|
189
188
|
return this.moveComponent(go, instance);
|
190
189
|
}
|
191
190
|
|
@@ -194,7 +193,7 @@
|
|
194
193
|
* @param go component to move the component to
|
195
194
|
* @param instance component to move to the GO
|
196
195
|
*/
|
197
|
-
public static moveComponent(go:
|
196
|
+
public static moveComponent(go: IGameObject, instance: Component): void {
|
198
197
|
if (instance.gameObject == null) {
|
199
198
|
throw new Error("Did you mean to create a new component? Use addNewComponent");
|
200
199
|
}
|
@@ -209,12 +208,12 @@
|
|
209
208
|
return instance;
|
210
209
|
}
|
211
210
|
|
212
|
-
public static getOrAddComponent<T>(go:
|
211
|
+
public static getOrAddComponent<T>(go: IGameObject | Object3D, typeName: ConstructorConcrete<T>): T {
|
213
212
|
return getOrAddComponent<any>(go, typeName);
|
214
213
|
}
|
215
214
|
|
216
215
|
/** Gets a component on the provided object */
|
217
|
-
public static getComponent<T>(go:
|
216
|
+
public static getComponent<T>(go: IGameObject | Object3D | null, typeName: Constructor<T> | null): T | null {
|
218
217
|
if (go === null) return null;
|
219
218
|
// if names are minified we could also use the type store and work with strings everywhere
|
220
219
|
// not ideal, but I dont know a good/sane way to do this otherwise
|
@@ -223,49 +222,49 @@
|
|
223
222
|
return getComponent(go, typeName as any);
|
224
223
|
}
|
225
224
|
|
226
|
-
public static getComponents<T>(go:
|
225
|
+
public static getComponents<T>(go: IGameObject | Object3D | null, typeName: Constructor<T>, arr: T[] | null = null): T[] {
|
227
226
|
if (go === null) return arr ?? [];
|
228
227
|
return getComponents(go, typeName, arr);
|
229
228
|
}
|
230
229
|
|
231
|
-
public static findByGuid(guid: string, hierarchy:
|
230
|
+
public static findByGuid(guid: string, hierarchy: Object3D): GameObject | Component | null | undefined {
|
232
231
|
const res = findByGuid(guid, hierarchy);
|
233
232
|
return res as GameObject | Component | null | undefined;
|
234
233
|
}
|
235
234
|
|
236
|
-
public static findObjectOfType<T>(typeName: Constructor<T>, context?: Context |
|
235
|
+
public static findObjectOfType<T>(typeName: Constructor<T>, context?: Context | Object3D, includeInactive: boolean = true): T | null {
|
237
236
|
return findObjectOfType(typeName, context ?? Context.Current, includeInactive);
|
238
237
|
}
|
239
238
|
|
240
|
-
public static findObjectsOfType<T>(typeName: Constructor<T>, context?: Context |
|
239
|
+
public static findObjectsOfType<T>(typeName: Constructor<T>, context?: Context | Object3D): Array<T> {
|
241
240
|
const arr = [];
|
242
241
|
findObjectsOfType(typeName, arr, context);
|
243
242
|
return arr;
|
244
243
|
}
|
245
244
|
|
246
|
-
public static getComponentInChildren<T>(go:
|
245
|
+
public static getComponentInChildren<T>(go: IGameObject | Object3D, typeName: Constructor<T>): T | null {
|
247
246
|
return getComponentInChildren(go, typeName);
|
248
247
|
}
|
249
248
|
|
250
|
-
public static getComponentsInChildren<T>(go:
|
249
|
+
public static getComponentsInChildren<T>(go: IGameObject | Object3D, typeName: Constructor<T>, arr: T[] | null = null): Array<T> {
|
251
250
|
return getComponentsInChildren<T>(go, typeName, arr ?? undefined) as T[]
|
252
251
|
}
|
253
252
|
|
254
|
-
public static getComponentInParent<T>(go:
|
253
|
+
public static getComponentInParent<T>(go: IGameObject | Object3D, typeName: Constructor<T>): T | null {
|
255
254
|
return getComponentInParent(go, typeName);
|
256
255
|
}
|
257
256
|
|
258
|
-
public static getComponentsInParent<T>(go:
|
257
|
+
public static getComponentsInParent<T>(go: IGameObject | Object3D, typeName: Constructor<T>, arr: Array<T> | null = null): Array<T> {
|
259
258
|
return getComponentsInParent(go, typeName, arr);
|
260
259
|
}
|
261
260
|
|
262
|
-
public static getAllComponents(go:
|
261
|
+
public static getAllComponents(go: IGameObject | Object3D): Behaviour[] {
|
263
262
|
const componentsList = go.userData?.components;
|
264
263
|
const newList = [...componentsList];
|
265
264
|
return newList;
|
266
265
|
}
|
267
266
|
|
268
|
-
public static *iterateComponents(go:
|
267
|
+
public static *iterateComponents(go: IGameObject | Object3D) {
|
269
268
|
const list = go?.userData?.components;
|
270
269
|
if (list && Array.isArray(list)) {
|
271
270
|
for (let i = 0; i < list.length; i++) {
|
@@ -300,7 +299,7 @@
|
|
300
299
|
set context(context: Context) {
|
301
300
|
this.__context = context;
|
302
301
|
}
|
303
|
-
get scene():
|
302
|
+
get scene(): Scene { return this.context.scene; }
|
304
303
|
|
305
304
|
get layer(): number {
|
306
305
|
return this.gameObject?.userData?.layer;
|
@@ -367,7 +366,7 @@
|
|
367
366
|
gameObject!: GameObject;
|
368
367
|
guid: string = "invalid";
|
369
368
|
sourceId?: SourceIdentifier;
|
370
|
-
// transform:
|
369
|
+
// transform: Object3D = nullObject;
|
371
370
|
|
372
371
|
/** called on a component with a map of old to new guids (e.g. when instantiate generated new guids and e.g. timeline track bindings needs to remape them) */
|
373
372
|
resolveGuids?(guidsMap: GuidsMap): void;
|
@@ -521,24 +520,24 @@
|
|
521
520
|
|
522
521
|
// TODO move this to threeutils
|
523
522
|
// we need a copy for modifying the values to local space
|
524
|
-
private static _worldPositionBuffer:
|
525
|
-
private static _worldQuaternionBuffer:
|
526
|
-
private static _worldEulerBuffer:
|
523
|
+
private static _worldPositionBuffer: Vector3 = new Vector3();
|
524
|
+
private static _worldQuaternionBuffer: Quaternion = new Quaternion();
|
525
|
+
private static _worldEulerBuffer: Euler = new Euler();
|
527
526
|
|
528
|
-
private _worldPosition:
|
529
|
-
private _worldQuaternion:
|
530
|
-
private static _tempQuaternionBuffer2:
|
531
|
-
private _worldEuler:
|
532
|
-
private _worldRotation:
|
527
|
+
private _worldPosition: Vector3 | undefined = undefined;
|
528
|
+
private _worldQuaternion: Quaternion | undefined = undefined;
|
529
|
+
private static _tempQuaternionBuffer2: Quaternion = new Quaternion();
|
530
|
+
private _worldEuler: Euler | undefined = undefined;
|
531
|
+
private _worldRotation: Vector3 | undefined = undefined;
|
533
532
|
|
534
|
-
get worldPosition():
|
535
|
-
if (!this._worldPosition) this._worldPosition = new
|
533
|
+
get worldPosition(): Vector3 {
|
534
|
+
if (!this._worldPosition) this._worldPosition = new Vector3();
|
536
535
|
threeutils.getWorldPosition(this.gameObject, this._worldPosition);
|
537
536
|
// this.gameObject.getWorldPosition(this._worldPosition);
|
538
537
|
return this._worldPosition;
|
539
538
|
}
|
540
539
|
|
541
|
-
set worldPosition(val:
|
540
|
+
set worldPosition(val: Vector3) {
|
542
541
|
threeutils.setWorldPosition(this.gameObject, val);
|
543
542
|
}
|
544
543
|
|
@@ -548,11 +547,11 @@
|
|
548
547
|
}
|
549
548
|
|
550
549
|
|
551
|
-
get worldQuaternion():
|
552
|
-
if (!this._worldQuaternion) this._worldQuaternion = new
|
550
|
+
get worldQuaternion(): Quaternion {
|
551
|
+
if (!this._worldQuaternion) this._worldQuaternion = new Quaternion();
|
553
552
|
return threeutils.getWorldQuaternion(this.gameObject, this._worldQuaternion);
|
554
553
|
}
|
555
|
-
set worldQuaternion(val:
|
554
|
+
set worldQuaternion(val: Quaternion) {
|
556
555
|
threeutils.setWorldQuaternion(this.gameObject, val);
|
557
556
|
}
|
558
557
|
setWorldQuaternion(x: number, y: number, z: number, w: number) {
|
@@ -562,23 +561,23 @@
|
|
562
561
|
|
563
562
|
|
564
563
|
// world euler (in radians)
|
565
|
-
get worldEuler():
|
566
|
-
if (!this._worldEuler) this._worldEuler = new
|
564
|
+
get worldEuler(): Euler {
|
565
|
+
if (!this._worldEuler) this._worldEuler = new Euler();
|
567
566
|
this._worldEuler.setFromQuaternion(this.worldQuaternion);
|
568
567
|
return this._worldEuler;
|
569
568
|
}
|
570
569
|
|
571
570
|
// world euler (in radians)
|
572
|
-
set worldEuler(val:
|
573
|
-
if (!this._worldQuaternion) this._worldQuaternion = new
|
571
|
+
set worldEuler(val: Euler) {
|
572
|
+
if (!this._worldQuaternion) this._worldQuaternion = new Quaternion();
|
574
573
|
this._worldQuaternion?.setFromEuler(val);
|
575
574
|
this.worldQuaternion = this._worldQuaternion;
|
576
575
|
}
|
577
576
|
|
578
577
|
// returns rotation in degrees
|
579
|
-
get worldRotation():
|
578
|
+
get worldRotation(): Vector3 {
|
580
579
|
const rot = this.worldEuler;
|
581
|
-
if (!this._worldRotation) this._worldRotation = new
|
580
|
+
if (!this._worldRotation) this._worldRotation = new Vector3();
|
582
581
|
const wr = this._worldRotation;
|
583
582
|
wr.set(rot.x, rot.y, rot.z);
|
584
583
|
wr.x = Mathf.toDegrees(wr.x);
|
@@ -587,7 +586,7 @@
|
|
587
586
|
return wr;
|
588
587
|
}
|
589
588
|
|
590
|
-
set worldRotation(val:
|
589
|
+
set worldRotation(val: Vector3) {
|
591
590
|
this.setWorldRotation(val.x, val.y, val.z, true);
|
592
591
|
}
|
593
592
|
|
@@ -602,16 +601,16 @@
|
|
602
601
|
this.worldQuaternion = Component._worldQuaternionBuffer;
|
603
602
|
}
|
604
603
|
|
605
|
-
private static _forward:
|
606
|
-
public get forward():
|
604
|
+
private static _forward: Vector3 = new Vector3();
|
605
|
+
public get forward(): Vector3 {
|
607
606
|
return Component._forward.set(0, 0, -1).applyQuaternion(this.worldQuaternion);
|
608
607
|
}
|
609
|
-
private static _right:
|
610
|
-
public get right():
|
608
|
+
private static _right: Vector3 = new Vector3();
|
609
|
+
public get right(): Vector3 {
|
611
610
|
return Component._right.set(1, 0, 0).applyQuaternion(this.worldQuaternion);
|
612
611
|
}
|
613
|
-
private static _up:
|
614
|
-
public get up():
|
612
|
+
private static _up: Vector3 = new Vector3();
|
613
|
+
public get up(): Vector3 {
|
615
614
|
return Component._up.set(0, 1, 0).applyQuaternion(this.worldQuaternion);
|
616
615
|
}
|
617
616
|
|
@@ -1,19 +1,18 @@
|
|
1
|
-
import {
|
2
|
-
// import { DragControls as Control } from "../include/three/DragControls";
|
1
|
+
import { GameObject } from "./Component";
|
3
2
|
import { SyncedTransform } from "./SyncedTransform";
|
4
|
-
import
|
5
|
-
import { IPointerClickHandler, IPointerDownHandler, IPointerEnterHandler, IPointerExitHandler, IPointerUpHandler, PointerEventData } from "./ui/PointerEvents";
|
3
|
+
import { IPointerDownHandler, IPointerEnterHandler, IPointerExitHandler, IPointerUpHandler, PointerEventData } from "./ui/PointerEvents";
|
6
4
|
import { Context } from "../engine/engine_setup";
|
7
5
|
import { Interactable, UsageMarker } from "./Interactable";
|
8
6
|
import { Rigidbody } from "./RigidBody";
|
9
7
|
import { WebXR } from "./WebXR";
|
10
8
|
import { Avatar_POI } from "./avatar/Avatar_Brain_LookAt";
|
11
9
|
import { RaycastOptions } from "../engine/engine_physics";
|
12
|
-
import { getWorldPosition,
|
10
|
+
import { getWorldPosition, setWorldPosition } from "../engine/engine_three_utils";
|
13
11
|
import { KeyCode } from "../engine/engine_input";
|
14
12
|
import { nameofFactory } from "../engine/engine_utils";
|
15
13
|
import { InstancingUtil } from "../engine/engine_instancing";
|
16
14
|
import { OrbitControls } from "./OrbitControls";
|
15
|
+
import { BufferGeometry, Camera, Color, Line, LineBasicMaterial, Matrix4, Mesh, MeshBasicMaterial, Object3D, Plane, Ray, Raycaster, SphereGeometry, Vector2, Vector3 } from "three";
|
17
16
|
|
18
17
|
const debug = false;
|
19
18
|
|
@@ -23,8 +22,8 @@
|
|
23
22
|
}
|
24
23
|
|
25
24
|
interface SelectArgs {
|
26
|
-
selected:
|
27
|
-
attached:
|
25
|
+
selected: Object3D;
|
26
|
+
attached: Object3D | GameObject | null;
|
28
27
|
}
|
29
28
|
|
30
29
|
|
@@ -41,7 +40,7 @@
|
|
41
40
|
|
42
41
|
public transformSelf: boolean = true;
|
43
42
|
// public transformGroup: boolean = true;
|
44
|
-
// public targets:
|
43
|
+
// public targets: Object3D[] | null = null;
|
45
44
|
|
46
45
|
// private controls: Control | null = null;
|
47
46
|
private orbit: OrbitControls | null = null;
|
@@ -53,7 +52,7 @@
|
|
53
52
|
super();
|
54
53
|
this.selectStartEventListener = [];
|
55
54
|
this.selectEndEventListener = [];
|
56
|
-
this._dragDelta = new
|
55
|
+
this._dragDelta = new Vector2();
|
57
56
|
}
|
58
57
|
|
59
58
|
addDragEventListener(type: DragEvents, cb: (ctrls: DragControls, args: SelectArgs) => void | Function) {
|
@@ -74,10 +73,10 @@
|
|
74
73
|
this.orbit = GameObject.findObjectOfType(OrbitControls, this.context);
|
75
74
|
}
|
76
75
|
|
77
|
-
private static lastHovered:
|
76
|
+
private static lastHovered: Object3D;
|
78
77
|
private _draggingRigidbodies: Rigidbody[] = [];
|
79
78
|
|
80
|
-
private allowEdit(_obj:
|
79
|
+
private allowEdit(_obj: Object3D | null = null) {
|
81
80
|
return this.context.connection.allowEditing;
|
82
81
|
}
|
83
82
|
|
@@ -160,7 +159,7 @@
|
|
160
159
|
|
161
160
|
private _isDragging: boolean = false;
|
162
161
|
private _marker: UsageMarker | null = null;
|
163
|
-
private _dragDelta!:
|
162
|
+
private _dragDelta!: Vector2;
|
164
163
|
private _didDrag: boolean = false;
|
165
164
|
private _activePointerId?: number;
|
166
165
|
|
@@ -177,14 +176,14 @@
|
|
177
176
|
if (!dc || dc !== this) return;
|
178
177
|
|
179
178
|
|
180
|
-
let object:
|
179
|
+
let object: Object3D = evt.object;
|
181
180
|
|
182
181
|
if (this.transformSelf) {
|
183
182
|
object = this.gameObject;
|
184
183
|
}
|
185
184
|
|
186
185
|
// raise event
|
187
|
-
const args: { selected:
|
186
|
+
const args: { selected: Object3D, attached: Object3D | null } = { selected: object, attached: object };
|
188
187
|
for (const listener of this.selectStartEventListener) {
|
189
188
|
listener(this, args);
|
190
189
|
}
|
@@ -285,54 +284,54 @@
|
|
285
284
|
return this._selected !== null && this._selected !== undefined;
|
286
285
|
}
|
287
286
|
|
288
|
-
public get selected():
|
287
|
+
public get selected(): Object3D | null {
|
289
288
|
return this._selected;
|
290
289
|
}
|
291
290
|
|
292
|
-
private _selected:
|
291
|
+
private _selected: Object3D | null = null;
|
293
292
|
private _context: Context | null = null;
|
294
|
-
private _camera:
|
295
|
-
private _cameraPlane:
|
293
|
+
private _camera: Camera;
|
294
|
+
private _cameraPlane: Plane = new Plane();
|
296
295
|
|
297
296
|
private _hasGroundPlane: boolean = false;
|
298
|
-
private _groundPlane:
|
299
|
-
private _groundOffset:
|
297
|
+
private _groundPlane: Plane = new Plane();
|
298
|
+
private _groundOffset: Vector3 = new Vector3();
|
300
299
|
private _groundOffsetFactor: number = 0;
|
301
300
|
private _groundDistance: number = 0;
|
302
|
-
private _groundPlanePoint:
|
301
|
+
private _groundPlanePoint: Vector3 = new Vector3();
|
303
302
|
|
304
|
-
private _raycaster = new
|
305
|
-
private _cameraPlaneOffset = new
|
306
|
-
private _intersection = new
|
307
|
-
private _worldPosition = new
|
308
|
-
private _inverseMatrix = new
|
303
|
+
private _raycaster = new Raycaster();
|
304
|
+
private _cameraPlaneOffset = new Vector3();
|
305
|
+
private _intersection = new Vector3();
|
306
|
+
private _worldPosition = new Vector3();
|
307
|
+
private _inverseMatrix = new Matrix4();
|
309
308
|
private _rbs: Rigidbody[] = [];
|
310
309
|
|
311
|
-
private _groundLine:
|
312
|
-
private _groundMarker:
|
313
|
-
private static geometry = new
|
310
|
+
private _groundLine: Line;
|
311
|
+
private _groundMarker: Object3D;
|
312
|
+
private static geometry = new BufferGeometry().setFromPoints([new Vector3(0, 0, 0), new Vector3(0, -1, 0)]);
|
314
313
|
|
315
|
-
constructor(camera:
|
314
|
+
constructor(camera: Camera) {
|
316
315
|
this._camera = camera;
|
317
316
|
|
318
|
-
const line = new
|
319
|
-
const mat = line.material as
|
320
|
-
mat.color = new
|
317
|
+
const line = new Line(DragHelper.geometry);
|
318
|
+
const mat = line.material as LineBasicMaterial;
|
319
|
+
mat.color = new Color(.4, .4, .4);
|
321
320
|
line.layers.set(2);
|
322
321
|
line.name = 'line';
|
323
322
|
line.scale.y = 1;
|
324
323
|
// line.matrixAutoUpdate = false;
|
325
324
|
this._groundLine = line;
|
326
325
|
|
327
|
-
const geometry = new
|
328
|
-
const material = new
|
329
|
-
const sphere = new
|
326
|
+
const geometry = new SphereGeometry(.5, 22, 22);
|
327
|
+
const material = new MeshBasicMaterial({ color: mat.color });
|
328
|
+
const sphere = new Mesh(geometry, material);
|
330
329
|
sphere.visible = false;
|
331
330
|
sphere.layers.set(2);
|
332
331
|
this._groundMarker = sphere;
|
333
332
|
}
|
334
333
|
|
335
|
-
setSelected(newSelected:
|
334
|
+
setSelected(newSelected: Object3D | null, context: Context) {
|
336
335
|
if (this._selected && context) {
|
337
336
|
for (const rb of this._rbs) {
|
338
337
|
rb.wakeUp();
|
@@ -376,7 +375,7 @@
|
|
376
375
|
}
|
377
376
|
}
|
378
377
|
|
379
|
-
private _groundOffsetVector = new
|
378
|
+
private _groundOffsetVector = new Vector3(0, 1, 0);
|
380
379
|
private _requireUpdateGroundPlane = true;
|
381
380
|
private _didDragOnGroundPlaneLastFrame: boolean = false;
|
382
381
|
|
@@ -429,7 +428,7 @@
|
|
429
428
|
this._requireUpdateGroundPlane = false;
|
430
429
|
if (this._hasGroundPlane) {
|
431
430
|
// const wp = getWorldPosition(this._selected);
|
432
|
-
// const ray = new
|
431
|
+
// const ray = new Ray(wp, new Vector3(0, -1, 0));
|
433
432
|
|
434
433
|
if (this._raycaster.ray.intersectPlane(this._groundPlane, this._intersection)) {
|
435
434
|
const y = this._intersection.y;
|
@@ -466,7 +465,7 @@
|
|
466
465
|
}
|
467
466
|
}
|
468
467
|
|
469
|
-
private onUpdateWorldPosition(wp:
|
468
|
+
private onUpdateWorldPosition(wp: Vector3, pointOnPlane: Vector3 | null, heightOnly: boolean) {
|
470
469
|
if (!this._selected) return;
|
471
470
|
if (heightOnly) {
|
472
471
|
const cur = getWorldPosition(this._selected);
|
@@ -503,7 +502,7 @@
|
|
503
502
|
private onUpdateGroundPlane() {
|
504
503
|
if (!this._selected || !this._context) return;
|
505
504
|
const wp = getWorldPosition(this._selected);
|
506
|
-
const ray = new
|
505
|
+
const ray = new Ray(new Vector3(0, .1, 0).add(wp), new Vector3(0, -1, 0));
|
507
506
|
const opts = new RaycastOptions();
|
508
507
|
opts.ignore = [this._selected];
|
509
508
|
const hits = this._context.physics.raycastFromRay(ray, opts);
|
@@ -512,7 +511,7 @@
|
|
512
511
|
if (!hit.face || this.contains(this._selected, hit.object)) {
|
513
512
|
continue;
|
514
513
|
}
|
515
|
-
const normal = new
|
514
|
+
const normal = new Vector3(0, 1, 0); // hit.face.normal
|
516
515
|
this._groundPlane.setFromNormalAndCoplanarPoint(normal, hit.point);
|
517
516
|
break;
|
518
517
|
}
|
@@ -536,7 +535,7 @@
|
|
536
535
|
}
|
537
536
|
}
|
538
537
|
|
539
|
-
private contains(obj:
|
538
|
+
private contains(obj: Object3D, toSearch: Object3D): boolean {
|
540
539
|
if (obj === toSearch) return true;
|
541
540
|
if (obj.children) {
|
542
541
|
for (const child of obj.children) {
|
@@ -1,11 +1,10 @@
|
|
1
1
|
import { getParam, resolveUrl } from "../engine/engine_utils";
|
2
|
-
// import { loadSync, parseSync } from "./engine_scenetools";
|
3
2
|
import { SerializationContext, TypeSerializer } from "./engine_serialization_core";
|
4
3
|
import { Context } from "./engine_setup";
|
5
|
-
import { Group, Object3D,
|
4
|
+
import { Group, Object3D, Texture } from "three";
|
6
5
|
import { processNewScripts } from "./engine_mainloop_utils";
|
7
6
|
import { registerPrefabProvider, syncInstantiate } from "./engine_networking_instantiate";
|
8
|
-
import { download
|
7
|
+
import { download } from "./engine_web_api";
|
9
8
|
import { getLoader } from "./engine_gltf";
|
10
9
|
import { SourceIdentifier } from "./engine_types";
|
11
10
|
import { destroy, instantiate, InstantiateOptions, isDestroyed } from "./engine_gameobject";
|
@@ -185,11 +184,11 @@
|
|
185
184
|
}
|
186
185
|
}
|
187
186
|
|
188
|
-
async instantiate(parent?:
|
187
|
+
async instantiate(parent?: Object3D | InstantiateOptions) {
|
189
188
|
return this.onInstantiate(parent, false);
|
190
189
|
}
|
191
190
|
|
192
|
-
async instantiateSynced(parent?:
|
191
|
+
async instantiateSynced(parent?: Object3D | InstantiateOptions, saveOnServer: boolean = true) {
|
193
192
|
return this.onInstantiate(parent, true, saveOnServer);
|
194
193
|
}
|
195
194
|
|
@@ -211,7 +210,7 @@
|
|
211
210
|
}
|
212
211
|
}
|
213
212
|
|
214
|
-
private async onInstantiate(parent?:
|
213
|
+
private async onInstantiate(parent?: Object3D | InstantiateOptions, networked: boolean = false, saveOnServer?: boolean) {
|
215
214
|
const context = Context.Current;
|
216
215
|
if (!parent) parent = context.scene;
|
217
216
|
if (this.mustLoad) {
|
@@ -282,7 +281,7 @@
|
|
282
281
|
* and call destroy on the player marker root
|
283
282
|
* @returns the scene root object if the asset was a glb/gltf
|
284
283
|
*/
|
285
|
-
private tryGetActualGameObjectRoot(asset: any):
|
284
|
+
private tryGetActualGameObjectRoot(asset: any): Object3D | null {
|
286
285
|
if (asset && asset.scene) {
|
287
286
|
// some exporters produce additional root objects
|
288
287
|
const scene = asset.scene as Group;
|
@@ -1,5 +1,8 @@
|
|
1
|
-
import { Camera, Clock,
|
2
|
-
|
1
|
+
import { BufferGeometry, Camera, Clock, Color, DepthTexture, Group,
|
2
|
+
Material, NearestFilter, NoToneMapping, Object3D, PCFSoftShadowMap,
|
3
|
+
PerspectiveCamera, RGBAFormat, Scene, sRGBEncoding,
|
4
|
+
Texture, WebGLRenderer, WebGLRenderTarget
|
5
|
+
} from 'three'
|
3
6
|
import { Input } from './engine_input';
|
4
7
|
import { Physics } from './engine_physics';
|
5
8
|
import { Time } from './engine_time';
|
@@ -50,7 +53,7 @@
|
|
50
53
|
name?: string;
|
51
54
|
alias?: string;
|
52
55
|
domElement: HTMLElement | null;
|
53
|
-
renderer?:
|
56
|
+
renderer?: WebGLRenderer = undefined;
|
54
57
|
hash?: string;
|
55
58
|
|
56
59
|
constructor(domElement: HTMLElement | null) {
|
@@ -74,7 +77,7 @@
|
|
74
77
|
ImmersiveAR = "immersive-ar",
|
75
78
|
}
|
76
79
|
|
77
|
-
export declare type OnBeforeRenderCallback = (renderer:
|
80
|
+
export declare type OnBeforeRenderCallback = (renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry, material: Material, group: Group) => void
|
78
81
|
|
79
82
|
|
80
83
|
export function registerComponent(script: IComponent, context?: Context) {
|
@@ -175,8 +178,8 @@
|
|
175
178
|
}
|
176
179
|
private _currentFrameEvent: FrameEvent = FrameEvent.Undefined;
|
177
180
|
|
178
|
-
scene:
|
179
|
-
renderer:
|
181
|
+
scene: Scene;
|
182
|
+
renderer: WebGLRenderer;
|
180
183
|
composer: EffectComposer | null = null;
|
181
184
|
|
182
185
|
// all scripts
|
@@ -191,7 +194,7 @@
|
|
191
194
|
scripts_WithCorroutines: IComponent[] = [];
|
192
195
|
coroutines: { [FrameEvent: number]: Array<CoroutineData> } = {}
|
193
196
|
|
194
|
-
get mainCamera():
|
197
|
+
get mainCamera(): Camera | null {
|
195
198
|
if (this.mainCameraComponent) {
|
196
199
|
const cam = this.mainCameraComponent as ICamera;
|
197
200
|
if (!cam.cam)
|
@@ -251,21 +254,21 @@
|
|
251
254
|
|
252
255
|
// some tonemapping other than "NONE" is required for adjusting exposure with EXR environments
|
253
256
|
this.renderer.toneMappingExposure = 1; // range [0...inf] instead of the usual -15..15
|
254
|
-
this.renderer.toneMapping =
|
257
|
+
this.renderer.toneMapping = NoToneMapping; // could also set to LinearToneMapping, ACESFilmicToneMapping
|
255
258
|
|
256
|
-
this.renderer.setClearColor(new
|
259
|
+
this.renderer.setClearColor(new Color('lightgrey'), 0);
|
257
260
|
// @ts-ignore
|
258
261
|
this.renderer.antialias = true;
|
259
262
|
// @ts-ignore
|
260
263
|
this.renderer.alpha = false;
|
261
264
|
this.renderer.shadowMap.enabled = true;
|
262
|
-
this.renderer.shadowMap.type =
|
265
|
+
this.renderer.shadowMap.type = PCFSoftShadowMap;
|
263
266
|
this.renderer.setSize(this.domWidth, this.domHeight);
|
264
|
-
this.renderer.outputEncoding =
|
267
|
+
this.renderer.outputEncoding = sRGBEncoding;
|
265
268
|
this.renderer.physicallyCorrectLights = true;
|
266
269
|
}
|
267
270
|
|
268
|
-
this.scene = new
|
271
|
+
this.scene = new Scene();
|
269
272
|
|
270
273
|
ContextRegistry.register(this);
|
271
274
|
|
@@ -328,7 +331,7 @@
|
|
328
331
|
}
|
329
332
|
}
|
330
333
|
|
331
|
-
updateAspect(camera:
|
334
|
+
updateAspect(camera: PerspectiveCamera, width?: number, height?: number) {
|
332
335
|
if (!camera) return;
|
333
336
|
if (width === undefined)
|
334
337
|
width = this.domWidth;
|
@@ -410,7 +413,7 @@
|
|
410
413
|
if (index >= 0) this._cameraStack.splice(index, 1);
|
411
414
|
this._cameraStack.push(cam);
|
412
415
|
this.mainCameraComponent = cam;
|
413
|
-
const camera = cam.cam as
|
416
|
+
const camera = cam.cam as PerspectiveCamera;
|
414
417
|
if (camera.isPerspectiveCamera)
|
415
418
|
this.updateAspect(camera);
|
416
419
|
(this.mainCameraComponent as ICamera)?.applyClearFlagsIfIsActiveCamera();
|
@@ -434,7 +437,7 @@
|
|
434
437
|
private _onBeforeRenderListeners: { [key: string]: OnBeforeRenderCallback[] } = {};
|
435
438
|
|
436
439
|
/** use this to subscribe to onBeforeRender events on threejs objects */
|
437
|
-
addBeforeRenderListener(target:
|
440
|
+
addBeforeRenderListener(target: Object3D, callback: OnBeforeRenderCallback) {
|
438
441
|
if (!this._onBeforeRenderListeners[target.uuid]) {
|
439
442
|
this._onBeforeRenderListeners[target.uuid] = [];
|
440
443
|
const onBeforeRenderCallback = (renderer, scene, camera, geometry, material, group) => {
|
@@ -450,7 +453,7 @@
|
|
450
453
|
this._onBeforeRenderListeners[target.uuid].push(callback);
|
451
454
|
}
|
452
455
|
|
453
|
-
removeBeforeRenderListener(target:
|
456
|
+
removeBeforeRenderListener(target: Object3D, callback: OnBeforeRenderCallback) {
|
454
457
|
if (this._onBeforeRenderListeners[target.uuid]) {
|
455
458
|
const arr = this._onBeforeRenderListeners[target.uuid];
|
456
459
|
const idx = arr.indexOf(callback);
|
@@ -473,11 +476,11 @@
|
|
473
476
|
this._requireColorTexture = val;
|
474
477
|
}
|
475
478
|
|
476
|
-
get depthTexture():
|
479
|
+
get depthTexture(): DepthTexture | null {
|
477
480
|
return this._renderTarget?.depthTexture || null;
|
478
481
|
}
|
479
482
|
|
480
|
-
get opaqueColorTexture():
|
483
|
+
get opaqueColorTexture(): Texture | null {
|
481
484
|
return this._renderTarget?.texture || null;
|
482
485
|
}
|
483
486
|
|
@@ -822,17 +825,17 @@
|
|
822
825
|
if (!this.mainCamera) return;
|
823
826
|
if (!this._requireDepthTexture && !this._requireColorTexture) return;
|
824
827
|
if (!this._renderTarget) {
|
825
|
-
this._renderTarget = new
|
828
|
+
this._renderTarget = new WebGLRenderTarget(this.domWidth, this.domHeight);
|
826
829
|
if (this._requireDepthTexture) {
|
827
830
|
const dt = new DepthTexture(this.domWidth, this.domHeight);;
|
828
831
|
this._renderTarget.depthTexture = dt;
|
829
832
|
}
|
830
833
|
if (this._requireColorTexture) {
|
831
|
-
this._renderTarget.texture = new
|
834
|
+
this._renderTarget.texture = new Texture();
|
832
835
|
this._renderTarget.texture.generateMipmaps = false;
|
833
|
-
this._renderTarget.texture.minFilter =
|
834
|
-
this._renderTarget.texture.magFilter =
|
835
|
-
this._renderTarget.texture.format =
|
836
|
+
this._renderTarget.texture.minFilter = NearestFilter;
|
837
|
+
this._renderTarget.texture.magFilter = NearestFilter;
|
838
|
+
this._renderTarget.texture.format = RGBAFormat;
|
836
839
|
}
|
837
840
|
}
|
838
841
|
const rt = this._renderTarget;
|
@@ -909,24 +912,24 @@
|
|
909
912
|
}
|
910
913
|
|
911
914
|
|
912
|
-
// const scene = new
|
915
|
+
// const scene = new Scene();
|
913
916
|
// const useComposer = utils.getParam("postfx");
|
914
917
|
// const renderer = new WebGLRenderer({ antialias: true });
|
915
918
|
// const composer = useComposer ? new EffectComposer(renderer) : undefined;
|
916
919
|
|
917
|
-
// renderer.setClearColor(new
|
920
|
+
// renderer.setClearColor(new Color('lightgrey'), 0)
|
918
921
|
// renderer.antialias = true;
|
919
922
|
// renderer.alpha = false;
|
920
923
|
// renderer.shadowMap.enabled = true;
|
921
|
-
// renderer.shadowMap.type =
|
924
|
+
// renderer.shadowMap.type = PCFSoftShadowMap;
|
922
925
|
// renderer.setSize(window.innerWidth, window.innerHeight);
|
923
|
-
// renderer.outputEncoding =
|
926
|
+
// renderer.outputEncoding = sRGBEncoding;
|
924
927
|
// renderer.physicallyCorrectLights = true;
|
925
928
|
// document.body.appendChild(renderer.domElement);
|
926
929
|
|
927
930
|
// // generation pushes loading requests in this array
|
928
931
|
// const sceneData: {
|
929
|
-
// mainCamera:
|
932
|
+
// mainCamera: Camera | undefined
|
930
933
|
// } = {
|
931
934
|
// preparing: [],
|
932
935
|
// resolving: [],
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import { Bone, Object3D, Quaternion, SkinnedMesh, Vector3 } from "three";
|
2
2
|
import { processNewScripts } from "./engine_mainloop_utils";
|
3
3
|
import { InstantiateIdProvider } from "./engine_networking_instantiate";
|
4
4
|
import { Context, registerComponent } from "./engine_setup";
|
@@ -36,9 +36,9 @@
|
|
36
36
|
parent?: string | undefined | Object3D;
|
37
37
|
/** for duplicatable parenting */
|
38
38
|
keepWorldPosition?: boolean
|
39
|
-
position?:
|
40
|
-
rotation?:
|
41
|
-
scale?:
|
39
|
+
position?: Vector3 | undefined;
|
40
|
+
rotation?: Quaternion | undefined;
|
41
|
+
scale?: Vector3 | undefined;
|
42
42
|
|
43
43
|
visible?: boolean | undefined;
|
44
44
|
|
@@ -88,14 +88,14 @@
|
|
88
88
|
return go[activeInHierarchyFieldName] || isUsingInstancing(go);
|
89
89
|
}
|
90
90
|
|
91
|
-
export function markAsInstancedRendered(go:
|
91
|
+
export function markAsInstancedRendered(go: Object3D, instanced: boolean) {
|
92
92
|
go[$isUsingInstancing] = instanced;
|
93
93
|
}
|
94
94
|
|
95
|
-
export function isUsingInstancing(instance:
|
95
|
+
export function isUsingInstancing(instance: Object3D): boolean { return InstancingUtil.isUsingInstancing(instance); }
|
96
96
|
|
97
97
|
|
98
|
-
export function findByGuid(guid: string, hierarchy:
|
98
|
+
export function findByGuid(guid: string, hierarchy: Object3D): GameObject | IComponent | null | undefined {
|
99
99
|
return tryFindObject(guid, hierarchy, true, true);
|
100
100
|
}
|
101
101
|
|
@@ -159,7 +159,7 @@
|
|
159
159
|
|
160
160
|
declare type ForEachComponentCallback = (comp: Component) => any;
|
161
161
|
|
162
|
-
export function foreachComponent(instance:
|
162
|
+
export function foreachComponent(instance: Object3D, cb: ForEachComponentCallback, recursive: boolean = true): any {
|
163
163
|
return internalForEachComponent(instance, cb, recursive);
|
164
164
|
}
|
165
165
|
|
@@ -198,8 +198,8 @@
|
|
198
198
|
}
|
199
199
|
|
200
200
|
declare class NewGameObjectReferenceInfo {
|
201
|
-
original:
|
202
|
-
clone:
|
201
|
+
original: Object3D;
|
202
|
+
clone: Object3D;
|
203
203
|
}
|
204
204
|
|
205
205
|
export function instantiate(instance: GameObject | Object3D | null, opts: InstantiateOptions | null = null): GameObject | null {
|
@@ -210,7 +210,7 @@
|
|
210
210
|
// if x is defined assume this is a vec3 - this is just to not break everything at once and stay a little bit backwards compatible
|
211
211
|
if (opts["x"] !== undefined) {
|
212
212
|
options = new InstantiateOptions();
|
213
|
-
options.position = opts as unknown as
|
213
|
+
options.position = opts as unknown as Vector3;
|
214
214
|
}
|
215
215
|
else {
|
216
216
|
// if (opts instanceof InstantiateOptions)
|
@@ -276,12 +276,12 @@
|
|
276
276
|
|
277
277
|
|
278
278
|
function internalInstantiate(
|
279
|
-
context: Context, instance: GameObject |
|
279
|
+
context: Context, instance: GameObject | Object3D, opts: InstantiateOptions | null,
|
280
280
|
componentsList: Array<Component>,
|
281
281
|
newGameObjectsMap: { [key: string]: NewGameObjectReferenceInfo },
|
282
282
|
skinnedMeshesMap: { [key: string]: NewGameObjectReferenceInfo }
|
283
283
|
)
|
284
|
-
: GameObject |
|
284
|
+
: GameObject | Object3D | null {
|
285
285
|
if (!instance) return null;
|
286
286
|
// prepare, remove things that dont work out of the box
|
287
287
|
// e.g. user data we want to manually clone
|
@@ -290,7 +290,7 @@
|
|
290
290
|
instance.userData = {};
|
291
291
|
const children = instance.children;
|
292
292
|
instance.children = [];
|
293
|
-
let clone:
|
293
|
+
let clone: Object3D | GameObject;
|
294
294
|
clone = instance.clone(false);
|
295
295
|
apply(clone);
|
296
296
|
// if(instance[$originalGuid])
|
@@ -408,9 +408,9 @@
|
|
408
408
|
) {
|
409
409
|
for (const key in skinnedMeshes) {
|
410
410
|
const val = skinnedMeshes[key];
|
411
|
-
const original = val.original as
|
411
|
+
const original = val.original as SkinnedMesh;
|
412
412
|
const originalSkeleton = original.skeleton;
|
413
|
-
const clone = val.clone as
|
413
|
+
const clone = val.clone as SkinnedMesh;
|
414
414
|
// clone.updateWorldMatrix(true, true);
|
415
415
|
if (!originalSkeleton) {
|
416
416
|
console.warn("Skinned mesh has no skeleton?", val);
|
@@ -426,16 +426,16 @@
|
|
426
426
|
// clone.bindMatrix.multiplyScalar(.025);
|
427
427
|
// console.assert(originalSkeleton.uuid !== clonedSkeleton.uuid);
|
428
428
|
// console.assert(originalBones.length === clonedSkeleton.bones.length);
|
429
|
-
const bones: Array<
|
429
|
+
const bones: Array<Bone> = [];
|
430
430
|
clonedSkeleton.bones = bones;
|
431
431
|
for (let i = 0; i < originalBones.length; i++) {
|
432
432
|
const bone = originalBones[i];
|
433
433
|
const newBoneInfo = newObjectsMap[bone.uuid];
|
434
|
-
const clonedBone = newBoneInfo.clone as
|
434
|
+
const clonedBone = newBoneInfo.clone as Bone;
|
435
435
|
// console.log("NEW BONE: ", clonedBone, "BEFORE", newBoneInfo.original);
|
436
436
|
bones.push(clonedBone);
|
437
437
|
}
|
438
|
-
// clone.skeleton = new
|
438
|
+
// clone.skeleton = new Skeleton(bones);
|
439
439
|
// clone.skeleton.update();
|
440
440
|
// clone.pose();
|
441
441
|
// clone.scale.set(1,1,1);
|
@@ -443,7 +443,7 @@
|
|
443
443
|
// console.log("ORIG", original, "CLONE", clone);
|
444
444
|
}
|
445
445
|
for (const key in skinnedMeshes) {
|
446
|
-
const clone = skinnedMeshes[key].clone as
|
446
|
+
const clone = skinnedMeshes[key].clone as SkinnedMesh;
|
447
447
|
clone.skeleton.update();
|
448
448
|
// clone.skeleton.calculateInverses();
|
449
449
|
clone.bind(clone.skeleton, clone.bindMatrix);
|
@@ -532,7 +532,7 @@
|
|
532
532
|
|
533
533
|
}
|
534
534
|
|
535
|
-
function postProcessNewInstance(copy:
|
535
|
+
function postProcessNewInstance(copy: Object3D, key: string, value: IComponent | Object3D | any, newObjectsMap: { [key: string]: NewGameObjectReferenceInfo }) {
|
536
536
|
if (value === null || value === undefined) return;
|
537
537
|
if ((value as IComponent).isComponent === true) {
|
538
538
|
const originalGameObjectReference = value["gameObject"];
|
@@ -1,7 +1,6 @@
|
|
1
|
-
import * as THREE from 'three';
|
2
1
|
import { BufferAttribute, Line, BoxGeometry, EdgesGeometry, Color, LineSegments, LineBasicMaterial, Object3D, Mesh, SphereGeometry, ColorRepresentation, Vector3, Box3, Quaternion, CylinderGeometry } from 'three';
|
3
2
|
import { Context } from './engine_setup';
|
4
|
-
import {
|
3
|
+
import { setWorldPositionXYZ } from './engine_three_utils';
|
5
4
|
import { Vec3, Vec4 } from './engine_types';
|
6
5
|
|
7
6
|
const _tmp = new Vector3();
|
@@ -109,12 +108,12 @@
|
|
109
108
|
}
|
110
109
|
|
111
110
|
const box: BoxGeometry = new BoxGeometry(1, 1, 1);
|
112
|
-
export function CreateWireCube(col:
|
111
|
+
export function CreateWireCube(col: ColorRepresentation | null = null): LineSegments {
|
113
112
|
const color = new Color(col ?? 0xdddddd);
|
114
|
-
// const material = new
|
115
|
-
// material.color = new
|
113
|
+
// const material = new MeshBasicMaterial();
|
114
|
+
// material.color = new Color(col ?? 0xdddddd);
|
116
115
|
// material.wireframe = true;
|
117
|
-
// const box = new
|
116
|
+
// const box = new Mesh(box, material);
|
118
117
|
// box.name = "BOX_GIZMO";
|
119
118
|
const edges = new EdgesGeometry(box);
|
120
119
|
const line = new LineSegments(edges, new LineBasicMaterial({ color: color }));
|
@@ -1,7 +1,5 @@
|
|
1
1
|
import "./codegen/register_types";
|
2
2
|
import { TypeStore } from "./engine_typestore";
|
3
|
-
import * as THREE from "three";
|
4
|
-
// import { GameObject } from "../engine-components/Component";
|
5
3
|
import { InstantiateIdProvider } from "./engine_networking_instantiate"
|
6
4
|
import { Context } from "./engine_setup";
|
7
5
|
import { deserializeObject, serializeObject } from "./engine_serialization";
|
@@ -15,6 +13,7 @@
|
|
15
13
|
import { getParam } from "./engine_utils";
|
16
14
|
import { LogType, showBalloonMessage } from "./debug/debug";
|
17
15
|
import { isLocalNetwork } from "./engine_networking_utils";
|
16
|
+
import { Object3D } from "three";
|
18
17
|
|
19
18
|
|
20
19
|
const debug = debugExtension;
|
@@ -43,7 +42,7 @@
|
|
43
42
|
|
44
43
|
export async function createBuiltinComponents(context: Context, gltfId: SourceIdentifier, gltf, seed: number | null | UIDProvider = null, extension?: NEEDLE_components) {
|
45
44
|
if (!gltf) return;
|
46
|
-
const lateResolve: Array<(gltf:
|
45
|
+
const lateResolve: Array<(gltf: Object3D) => {}> = [];
|
47
46
|
|
48
47
|
let idProvider: UIDProvider | null = seed as UIDProvider;
|
49
48
|
if (typeof idProvider === "number") {
|
@@ -145,15 +144,15 @@
|
|
145
144
|
declare class DeserializeData {
|
146
145
|
instance: any;
|
147
146
|
compData: IGltfbuiltinComponent;
|
148
|
-
obj:
|
147
|
+
obj: Object3D;
|
149
148
|
}
|
150
149
|
|
151
|
-
declare type LateResolveCallback = (gltf:
|
150
|
+
declare type LateResolveCallback = (gltf: Object3D) => void;
|
152
151
|
|
153
152
|
const unknownComponentsBuffer: Array<string> = [];
|
154
153
|
|
155
154
|
|
156
|
-
async function onCreateBuiltinComponents(context: SerializationContext, obj:
|
155
|
+
async function onCreateBuiltinComponents(context: SerializationContext, obj: Object3D,
|
157
156
|
deserialize: DeserializeData[], lateResolve: LateResolveCallback[]) {
|
158
157
|
if (!obj) return;
|
159
158
|
|
@@ -324,13 +323,13 @@
|
|
324
323
|
// function tryResolveType(type, entry): any | undefined {
|
325
324
|
// switch (type) {
|
326
325
|
// case "Vector2":
|
327
|
-
// return new
|
326
|
+
// return new Vector2(entry.x, entry.y);
|
328
327
|
// case "Vector3":
|
329
|
-
// return new
|
328
|
+
// return new Vector3(entry.x, entry.y, entry.z);
|
330
329
|
// case "Vector4":
|
331
|
-
// return new
|
330
|
+
// return new Vector4(entry.x, entry.y, entry.z, entry.w);
|
332
331
|
// case "Quaternion":
|
333
|
-
// return new
|
332
|
+
// return new Quaternion(entry.x, entry.y, entry.z, entry.w);
|
334
333
|
// }
|
335
334
|
// return undefined;
|
336
335
|
// }
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import * as THREE from 'three';
|
2
1
|
import { Vector2 } from 'three';
|
3
2
|
import { showBalloonMessage, showBalloonWarning } from './debug/debug';
|
4
3
|
import { assign } from './engine_serialization_core';
|
@@ -58,8 +57,8 @@
|
|
58
57
|
_doubleClickTimeThreshold = .2;
|
59
58
|
_longPressTimeThreshold = 1;
|
60
59
|
|
61
|
-
get mousePosition():
|
62
|
-
get mousePositionRC():
|
60
|
+
get mousePosition(): Vector2 { return this._pointerPositions[0]; };
|
61
|
+
get mousePositionRC(): Vector2 { return this._pointerPositionsRC[0]; }
|
63
62
|
get mouseDown(): boolean { return this._pointerDown[0]; }
|
64
63
|
get mouseUp(): boolean { return this._pointerUp[0]; }
|
65
64
|
get mouseClick(): boolean { return this._pointerClick[0]; }
|
@@ -91,19 +90,19 @@
|
|
91
90
|
return count;
|
92
91
|
}
|
93
92
|
|
94
|
-
getPointerPosition(i: number):
|
93
|
+
getPointerPosition(i: number): Vector2 | null {
|
95
94
|
if (i >= this._pointerPositions.length) return null;
|
96
95
|
return this._pointerPositions[i];
|
97
96
|
}
|
98
|
-
getPointerPositionLastFrame(i: number):
|
97
|
+
getPointerPositionLastFrame(i: number): Vector2 | null {
|
99
98
|
if (i >= this._pointerPositionsLastFrame.length) return null;
|
100
99
|
return this._pointerPositionsLastFrame[i];
|
101
100
|
}
|
102
|
-
getPointerPositionDelta(i: number):
|
101
|
+
getPointerPositionDelta(i: number): Vector2 | null {
|
103
102
|
if (i >= this._pointerPositionsDelta.length) return null;
|
104
103
|
return this._pointerPositionsDelta[i];
|
105
104
|
}
|
106
|
-
getPointerPositionRC(i: number):
|
105
|
+
getPointerPositionRC(i: number): Vector2 | null {
|
107
106
|
if (i >= this._pointerPositionsRC.length) return null;
|
108
107
|
return this._pointerPositionsRC[i];
|
109
108
|
}
|
@@ -213,11 +212,11 @@
|
|
213
212
|
private _pointerClick: boolean[] = [false];
|
214
213
|
private _pointerDoubleClick: boolean[] = [false];
|
215
214
|
private _pointerPressed: boolean[] = [false];
|
216
|
-
private _pointerPositions:
|
217
|
-
private _pointerPositionsLastFrame:
|
218
|
-
private _pointerPositionsDelta:
|
219
|
-
private _pointerPositionsRC:
|
220
|
-
private _pointerPositionDown:
|
215
|
+
private _pointerPositions: Vector2[] = [new Vector2()];
|
216
|
+
private _pointerPositionsLastFrame: Vector2[] = [new Vector2()];
|
217
|
+
private _pointerPositionsDelta: Vector2[] = [new Vector2()];
|
218
|
+
private _pointerPositionsRC: Vector2[] = [new Vector2()];
|
219
|
+
private _pointerPositionDown: Vector2[] = [new Vector2()];
|
221
220
|
private _pointerDownTime: number[] = [];
|
222
221
|
private _pointerUpTime: number[] = [];
|
223
222
|
private _pointerUpTimestamp: number[] = [];
|
@@ -505,9 +504,9 @@
|
|
505
504
|
while (evt.button >= this._pointerTypes.length) this._pointerTypes.push(evt.pointerType);
|
506
505
|
this._pointerTypes[evt.button] = evt.pointerType;
|
507
506
|
|
508
|
-
while (evt.button >= this._pointerPositionDown.length) this._pointerPositionDown.push(new
|
507
|
+
while (evt.button >= this._pointerPositionDown.length) this._pointerPositionDown.push(new Vector2());
|
509
508
|
this._pointerPositionDown[evt.button].set(evt.clientX, evt.clientY);
|
510
|
-
while (evt.button >= this._pointerPositions.length) this._pointerPositions.push(new
|
509
|
+
while (evt.button >= this._pointerPositions.length) this._pointerPositions.push(new Vector2());
|
511
510
|
this._pointerPositions[evt.button].set(evt.clientX, evt.clientY);
|
512
511
|
|
513
512
|
if (evt.button >= this._pointerDownTime.length) this._pointerDownTime.push(0);
|
@@ -577,9 +576,9 @@
|
|
577
576
|
|
578
577
|
private updatePointerPosition(evt: PointerEventArgs) {
|
579
578
|
// console.log("MOVE");
|
580
|
-
while (evt.button >= this._pointerPositions.length) this._pointerPositions.push(new
|
581
|
-
while (evt.button >= this._pointerPositionsLastFrame.length) this._pointerPositionsLastFrame.push(new
|
582
|
-
while (evt.button >= this._pointerPositionsDelta.length) this._pointerPositionsDelta.push(new
|
579
|
+
while (evt.button >= this._pointerPositions.length) this._pointerPositions.push(new Vector2());
|
580
|
+
while (evt.button >= this._pointerPositionsLastFrame.length) this._pointerPositionsLastFrame.push(new Vector2());
|
581
|
+
while (evt.button >= this._pointerPositionsDelta.length) this._pointerPositionsDelta.push(new Vector2());
|
583
582
|
|
584
583
|
const lf = this._pointerPositionsLastFrame[evt.button];
|
585
584
|
lf.copy(this._pointerPositions[evt.button]);
|
@@ -593,7 +592,7 @@
|
|
593
592
|
// we want to have the position 01 on the canvas for raycasting
|
594
593
|
const px = evt.clientX;
|
595
594
|
const py = evt.clientY;
|
596
|
-
while (evt.button >= this._pointerPositionsRC.length) this._pointerPositionsRC.push(new
|
595
|
+
while (evt.button >= this._pointerPositionsRC.length) this._pointerPositionsRC.push(new Vector2());
|
597
596
|
const rc = this._pointerPositionsRC[evt.button];
|
598
597
|
rc.set(px, py);
|
599
598
|
this.convertScreenspaceToRaycastSpace(rc);
|
@@ -7,10 +7,10 @@
|
|
7
7
|
|
8
8
|
// This is modified by a bundler (e.g. vite)
|
9
9
|
// Do not edit manually
|
10
|
-
const
|
10
|
+
const NEEDLE_ENGINE_COMMERCIAL_USE_LICENSE = false;
|
11
11
|
|
12
12
|
export function hasProLicense() {
|
13
|
-
return
|
13
|
+
return NEEDLE_ENGINE_COMMERCIAL_USE_LICENSE;
|
14
14
|
}
|
15
15
|
|
16
16
|
|
@@ -230,7 +230,7 @@
|
|
230
230
|
}
|
231
231
|
}
|
232
232
|
|
233
|
-
function updateIsActiveInHierarchyRecursiveRuntime(go:
|
233
|
+
function updateIsActiveInHierarchyRecursiveRuntime(go: Object3D, activeInHierarchy: boolean, allowEventCall: boolean, level: number = 0) {
|
234
234
|
if (level > 1000) {
|
235
235
|
console.warn("Hierarchy is too deep (> 1000 level) - will abort updating active state");
|
236
236
|
return false;
|
@@ -307,7 +307,7 @@
|
|
307
307
|
|
308
308
|
// let isRunning = false;
|
309
309
|
// // Prevent: https://github.com/needle-tools/needle-tiny/issues/641
|
310
|
-
// const temporyChildArrayBuffer: Array<Array<
|
310
|
+
// const temporyChildArrayBuffer: Array<Array<Object3D>> = [];
|
311
311
|
// export function* iterateChildrenSafe(obj: Object3D) {
|
312
312
|
// if (!obj || !obj.children) yield null;
|
313
313
|
// // if(isRunning) return;
|
@@ -322,9 +322,9 @@
|
|
322
322
|
// temporyChildArrayBuffer.push(arr);
|
323
323
|
// }
|
324
324
|
|
325
|
-
export function updateActiveInHierarchyWithoutEventCall(go:
|
325
|
+
export function updateActiveInHierarchyWithoutEventCall(go: Object3D) {
|
326
326
|
let activeInHierarchy = true;
|
327
|
-
let current:
|
327
|
+
let current: Object3D | null = go;
|
328
328
|
let foundScene: boolean = false;
|
329
329
|
while (current) {
|
330
330
|
if (!current) break;
|
@@ -342,7 +342,7 @@
|
|
342
342
|
go[constants.activeInHierarchyFieldName] = activeInHierarchy && foundScene;
|
343
343
|
}
|
344
344
|
|
345
|
-
function perComponent(go:
|
345
|
+
function perComponent(go: Object3D, evt: (comp: IComponent) => void) {
|
346
346
|
if (go.userData?.components) {
|
347
347
|
for (const comp of go.userData.components) {
|
348
348
|
evt(comp);
|
@@ -210,7 +210,7 @@
|
|
210
210
|
* (for example a networked color is sent as a number and may be converted to a color in the receiver again)
|
211
211
|
* Parameters: (newValue, previousValue)
|
212
212
|
*/
|
213
|
-
export const syncField = function(onFieldChanged
|
213
|
+
export const syncField = function(onFieldChanged?: string | FieldChangedCallbackFn) {
|
214
214
|
|
215
215
|
return function (target: any, propertyKey: string) {
|
216
216
|
|
@@ -1,6 +1,4 @@
|
|
1
1
|
import { Context } from "../engine/engine_setup";
|
2
|
-
// import { loadSync, parseSync } from "../engine/engine_scenetools";
|
3
|
-
import * as THREE from "three";
|
4
2
|
import * as web from "../engine/engine_web_api";
|
5
3
|
import { NetworkConnection } from "../engine/engine_networking";
|
6
4
|
import { generateSeed, InstantiateIdProvider } from "../engine/engine_networking_instantiate";
|
@@ -11,6 +9,7 @@
|
|
11
9
|
import { IGameObject } from "./engine_types";
|
12
10
|
import { findByGuid } from "./engine_gameobject";
|
13
11
|
import { ContextEvent, ContextRegistry } from "./engine_context_registry";
|
12
|
+
import { BoxGeometry, BoxHelper, Mesh, MeshBasicMaterial, Object3D, Vector3 } from "three";
|
14
13
|
|
15
14
|
export enum File_Event {
|
16
15
|
File_Spawned = "file-spawned",
|
@@ -21,15 +20,15 @@
|
|
21
20
|
file_name: string;
|
22
21
|
file_hash: string;
|
23
22
|
file_size: number;
|
24
|
-
position:
|
23
|
+
position: Vector3 | null;
|
25
24
|
seed: number;
|
26
25
|
sender: string;
|
27
26
|
serverUrl: string;
|
28
27
|
parentGuid?: string;
|
29
28
|
|
30
|
-
boundsSize?:
|
29
|
+
boundsSize?: Vector3;
|
31
30
|
|
32
|
-
constructor(connectionId: string, seed: number, guid: string, name: string, hash: string, size: number, position:
|
31
|
+
constructor(connectionId: string, seed: number, guid: string, name: string, hash: string, size: number, position: Vector3 | null, serverUrl: string) {
|
33
32
|
this.seed = seed;
|
34
33
|
this.guid = guid;
|
35
34
|
this.file_name = name;
|
@@ -129,7 +128,7 @@
|
|
129
128
|
|
130
129
|
// add object to proper parent
|
131
130
|
if (evt.parentGuid) {
|
132
|
-
const parent = findByGuid(evt.parentGuid, context.scene) as
|
131
|
+
const parent = findByGuid(evt.parentGuid, context.scene) as Object3D;
|
133
132
|
if ("add" in parent) parent.add(obj);
|
134
133
|
}
|
135
134
|
if (!obj.parent)
|
@@ -182,16 +181,16 @@
|
|
182
181
|
}
|
183
182
|
|
184
183
|
|
185
|
-
const previews: { [key: string]:
|
184
|
+
const previews: { [key: string]: Object3D } = {};
|
186
185
|
|
187
186
|
function addPreview(evt: FileSpawnModel, context: Context) {
|
188
|
-
const sphere = new
|
189
|
-
const object = new
|
190
|
-
const box = new
|
187
|
+
const sphere = new BoxGeometry();
|
188
|
+
const object = new Mesh(sphere, new MeshBasicMaterial({ color: 0x00ff00 }));
|
189
|
+
const box = new BoxHelper(object, 0x555555);
|
191
190
|
previews[evt.guid] = box;
|
192
191
|
context.scene.add(box);
|
193
192
|
if (evt.parentGuid) {
|
194
|
-
const parent = findByGuid(evt.parentGuid, context.scene) as
|
193
|
+
const parent = findByGuid(evt.parentGuid, context.scene) as Object3D;
|
195
194
|
if (parent)
|
196
195
|
parent.add(box);
|
197
196
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import * as THREE from "three";
|
2
2
|
import { Mathf } from "./engine_math"
|
3
|
-
import { WebGLRenderer, Vector3, Quaternion, Uniform, Texture, Material, ShaderMaterial, CanvasTexture, AnimationAction, Camera, PerspectiveCamera } from "three";
|
3
|
+
import { WebGLRenderer, Vector3, Quaternion, Uniform, Texture, Material, ShaderMaterial, CanvasTexture, AnimationAction, Camera, PerspectiveCamera, Object3D, Euler, PlaneGeometry, Scene, Mesh } from "three";
|
4
4
|
import { CircularBuffer } from "./engine_utils";
|
5
5
|
|
6
6
|
|
@@ -12,16 +12,16 @@
|
|
12
12
|
}
|
13
13
|
|
14
14
|
const flipYQuat: Quaternion = new Quaternion().setFromAxisAngle(new Vector3(0, 1, 0), Math.PI);
|
15
|
-
export function lookAtInverse(obj:
|
15
|
+
export function lookAtInverse(obj: Object3D, target: Vector3) {
|
16
16
|
|
17
17
|
obj.lookAt(target);
|
18
18
|
obj.quaternion.multiply(flipYQuat);
|
19
19
|
}
|
20
20
|
|
21
21
|
|
22
|
-
const _worldPositions = new CircularBuffer(() => new
|
22
|
+
const _worldPositions = new CircularBuffer(() => new Vector3(), 100);
|
23
23
|
|
24
|
-
export function getWorldPosition(obj:
|
24
|
+
export function getWorldPosition(obj: Object3D, vec: Vector3 | null = null, updateParents: boolean = true): Vector3 {
|
25
25
|
const wp = vec ?? _worldPositions.get();
|
26
26
|
if (!obj) return wp.set(0, 0, 0);
|
27
27
|
if (!obj.parent) return wp.copy(obj.position);
|
@@ -33,7 +33,7 @@
|
|
33
33
|
return wp;
|
34
34
|
}
|
35
35
|
|
36
|
-
export function setWorldPosition(obj:
|
36
|
+
export function setWorldPosition(obj: Object3D, val: Vector3) {
|
37
37
|
if (!obj) return;
|
38
38
|
const wp = _worldPositions.get();
|
39
39
|
if (val !== wp)
|
@@ -43,25 +43,25 @@
|
|
43
43
|
obj.position.set(wp.x, wp.y, wp.z);
|
44
44
|
}
|
45
45
|
|
46
|
-
export function setWorldPositionXYZ(obj:
|
46
|
+
export function setWorldPositionXYZ(obj: Object3D, x: number, y: number, z: number) {
|
47
47
|
const wp = _worldPositions.get();
|
48
48
|
wp.set(x, y, z);
|
49
49
|
setWorldPosition(obj, wp);
|
50
50
|
}
|
51
51
|
|
52
52
|
|
53
|
-
const _worldQuaternionBuffer:
|
54
|
-
const _worldQuaternion:
|
55
|
-
const _tempQuaternionBuffer2:
|
53
|
+
const _worldQuaternionBuffer: Quaternion = new Quaternion();
|
54
|
+
const _worldQuaternion: Quaternion = new Quaternion();
|
55
|
+
const _tempQuaternionBuffer2: Quaternion = new Quaternion();
|
56
56
|
|
57
|
-
export function getWorldQuaternion(obj:
|
57
|
+
export function getWorldQuaternion(obj: Object3D, target: Quaternion | null = null): Quaternion {
|
58
58
|
if (!obj) return _worldQuaternion.set(0, 0, 0, 1);
|
59
59
|
const quat = target ?? _worldQuaternion;
|
60
60
|
if (!obj.parent) return quat.copy(obj.quaternion);
|
61
61
|
obj.getWorldQuaternion(quat);
|
62
62
|
return quat;
|
63
63
|
}
|
64
|
-
export function setWorldQuaternion(obj:
|
64
|
+
export function setWorldQuaternion(obj: Object3D, val: Quaternion) {
|
65
65
|
if (!obj) return;
|
66
66
|
if (val !== _worldQuaternionBuffer)
|
67
67
|
_worldQuaternionBuffer.copy(val);
|
@@ -74,22 +74,22 @@
|
|
74
74
|
obj.quaternion.set(q.x, q.y, q.z, q.w);
|
75
75
|
// console.error("quaternion world to local is not yet implemented");
|
76
76
|
}
|
77
|
-
export function setWorldQuaternionXYZW(obj:
|
77
|
+
export function setWorldQuaternionXYZW(obj: Object3D, x: number, y: number, z: number, w: number) {
|
78
78
|
_worldQuaternionBuffer.set(x, y, z, w);
|
79
79
|
setWorldQuaternion(obj, _worldQuaternionBuffer);
|
80
80
|
}
|
81
81
|
|
82
|
-
const _worldScale:
|
83
|
-
const _worldScale2:
|
82
|
+
const _worldScale: Vector3 = new Vector3();
|
83
|
+
const _worldScale2: Vector3 = new Vector3();
|
84
84
|
|
85
|
-
export function getWorldScale(obj:
|
85
|
+
export function getWorldScale(obj: Object3D, vec: Vector3 | null = null): Vector3 {
|
86
86
|
if (!obj) return _worldScale.set(0, 0, 0);
|
87
87
|
if (!obj.parent) return _worldScale.copy(obj.scale);
|
88
88
|
obj.getWorldScale(vec ?? _worldScale);
|
89
89
|
return vec ?? _worldScale;
|
90
90
|
}
|
91
91
|
|
92
|
-
export function setWorldScale(obj:
|
92
|
+
export function setWorldScale(obj: Object3D, vec: Vector3) {
|
93
93
|
if (!obj) return;
|
94
94
|
if (!obj.parent) {
|
95
95
|
obj.scale.copy(vec);
|
@@ -102,35 +102,35 @@
|
|
102
102
|
obj.scale.copy(tempVec);
|
103
103
|
}
|
104
104
|
|
105
|
-
const _forward = new
|
106
|
-
const _forwardQuat = new
|
107
|
-
export function forward(obj:
|
105
|
+
const _forward = new Vector3();
|
106
|
+
const _forwardQuat = new Quaternion();
|
107
|
+
export function forward(obj: Object3D): Vector3 {
|
108
108
|
getWorldQuaternion(obj, _forwardQuat);
|
109
109
|
return _forward.set(0, 0, 1).applyQuaternion(_forwardQuat);
|
110
110
|
}
|
111
111
|
|
112
112
|
|
113
113
|
|
114
|
-
const _worldEulerBuffer:
|
115
|
-
const _worldEuler:
|
116
|
-
const _worldRotation:
|
114
|
+
const _worldEulerBuffer: Euler = new Euler();
|
115
|
+
const _worldEuler: Euler = new Euler();
|
116
|
+
const _worldRotation: Vector3 = new Vector3();
|
117
117
|
|
118
118
|
|
119
119
|
|
120
120
|
// world euler (in radians)
|
121
|
-
export function getWorldEuler(obj:
|
121
|
+
export function getWorldEuler(obj: Object3D): Euler {
|
122
122
|
obj.getWorldQuaternion(_worldQuaternion);
|
123
123
|
_worldEuler.setFromQuaternion(_worldQuaternion);
|
124
124
|
return _worldEuler;
|
125
125
|
}
|
126
126
|
|
127
127
|
// world euler (in radians)
|
128
|
-
export function setWorldEuler(obj:
|
128
|
+
export function setWorldEuler(obj: Object3D, val: Euler) {
|
129
129
|
setWorldQuaternion(obj, _worldQuaternion.setFromEuler(val));;
|
130
130
|
}
|
131
131
|
|
132
132
|
// returns rotation in degrees
|
133
|
-
export function getWorldRotation(obj:
|
133
|
+
export function getWorldRotation(obj: Object3D): Vector3 {
|
134
134
|
const rot = getWorldEuler(obj);
|
135
135
|
const wr = _worldRotation;
|
136
136
|
wr.set(rot.x, rot.y, rot.z);
|
@@ -140,11 +140,11 @@
|
|
140
140
|
return wr;
|
141
141
|
}
|
142
142
|
|
143
|
-
export function setWorldRotation(obj:
|
143
|
+
export function setWorldRotation(obj: Object3D, val: Vector3) {
|
144
144
|
setWorldRotationXYZ(obj, val.x, val.y, val.z, true);
|
145
145
|
}
|
146
146
|
|
147
|
-
export function setWorldRotationXYZ(obj:
|
147
|
+
export function setWorldRotationXYZ(obj: Object3D, x: number, y: number, z: number, degrees: boolean = true) {
|
148
148
|
if (degrees) {
|
149
149
|
x = Mathf.toRadians(x);
|
150
150
|
y = Mathf.toRadians(y);
|
@@ -159,18 +159,18 @@
|
|
159
159
|
|
160
160
|
|
161
161
|
|
162
|
-
// from https://github.com/mrdoob/
|
163
|
-
export function logHierarchy(root:
|
162
|
+
// from https://github.com/mrdoob/js/pull/10995#issuecomment-287614722
|
163
|
+
export function logHierarchy(root: Object3D | null | undefined, collapsible: boolean = true) {
|
164
164
|
if (!root) return;
|
165
165
|
if (collapsible) {
|
166
|
-
(function printGraph(obj:
|
166
|
+
(function printGraph(obj: Object3D) {
|
167
167
|
console.groupCollapsed((obj.name ? obj.name : '(no name : ' + obj.type + ')') + ' %o', obj);
|
168
168
|
obj.children.forEach(printGraph);
|
169
169
|
console.groupEnd();
|
170
170
|
}(root));
|
171
171
|
|
172
172
|
} else {
|
173
|
-
root.traverse(function (obj:
|
173
|
+
root.traverse(function (obj: Object3D) {
|
174
174
|
var s = '|___';
|
175
175
|
var obj2 = obj;
|
176
176
|
while (obj2.parent !== null) {
|
@@ -198,10 +198,10 @@
|
|
198
198
|
|
199
199
|
|
200
200
|
export class Graphics {
|
201
|
-
private static planeGeometry = new
|
201
|
+
private static planeGeometry = new PlaneGeometry(2, 2, 1, 1);
|
202
202
|
private static renderer = new WebGLRenderer({ antialias: false });
|
203
|
-
private static perspectiveCam = new
|
204
|
-
private static scene = new
|
203
|
+
private static perspectiveCam = new PerspectiveCamera();
|
204
|
+
private static scene = new Scene();
|
205
205
|
private static readonly vertex = `
|
206
206
|
varying vec2 vUv;
|
207
207
|
void main(){
|
@@ -230,7 +230,7 @@
|
|
230
230
|
fragmentShader: fragment
|
231
231
|
});
|
232
232
|
}
|
233
|
-
private static readonly mesh = new
|
233
|
+
private static readonly mesh = new Mesh(this.planeGeometry, this.blipMaterial);
|
234
234
|
|
235
235
|
static copyTexture(texture: Texture, blitMaterial?: ShaderMaterial) {
|
236
236
|
const material = blitMaterial ?? this.blipMaterial;
|
@@ -292,12 +292,12 @@
|
|
292
292
|
}
|
293
293
|
|
294
294
|
/**@obsolete use Graphics.copyTexture */
|
295
|
-
export function copyTexture(texture:
|
295
|
+
export function copyTexture(texture: Texture): Texture {
|
296
296
|
return Graphics.copyTexture(texture);
|
297
297
|
}
|
298
298
|
|
299
299
|
/**@obsolete use Graphics.textureToCanvas */
|
300
|
-
export function textureToCanvas(texture:
|
300
|
+
export function textureToCanvas(texture: Texture, force: boolean = false): HTMLCanvasElement | null {
|
301
301
|
return Graphics.textureToCanvas(texture, force);
|
302
302
|
}
|
303
303
|
|
@@ -6,6 +6,7 @@
|
|
6
6
|
import { resolveReferences } from "./extension_utils";
|
7
7
|
import { apply } from "../../engine-components/js-extensions/Object3D";
|
8
8
|
import { getLoader } from "../engine_gltf";
|
9
|
+
import { Object3D } from "three";
|
9
10
|
|
10
11
|
export const debug = debugExtension
|
11
12
|
const componentsArrayExportKey = "$___Export_Components";
|
@@ -17,11 +18,11 @@
|
|
17
18
|
}
|
18
19
|
|
19
20
|
class ExportData {
|
20
|
-
node:
|
21
|
+
node: Object3D;
|
21
22
|
nodeIndex: number;
|
22
23
|
nodeDef: any;
|
23
24
|
|
24
|
-
constructor(node:
|
25
|
+
constructor(node: Object3D, nodeIndex: number, nodeDef: any) {
|
25
26
|
this.node = node;
|
26
27
|
this.nodeIndex = nodeIndex;
|
27
28
|
this.nodeDef = nodeDef;
|
@@ -78,7 +79,7 @@
|
|
78
79
|
}
|
79
80
|
|
80
81
|
// https://github.com/mrdoob/three.js/blob/efbfc67edc7f65cfcc61a389ffc5fd43ea702bc6/examples/jsm/exporters/GLTFExporter.js#L532
|
81
|
-
serializeUserData(node:
|
82
|
+
serializeUserData(node: Object3D, _nodeDef: any) {
|
82
83
|
const components = node.userData?.components;
|
83
84
|
if (!components || components.length <= 0) return;
|
84
85
|
// delete components before serializing user data to avoid circular references
|
@@ -86,7 +87,7 @@
|
|
86
87
|
node[componentsArrayExportKey] = components;
|
87
88
|
}
|
88
89
|
|
89
|
-
afterSerializeUserData(node:
|
90
|
+
afterSerializeUserData(node: Object3D, _nodeDef) {
|
90
91
|
if (node.type === "Scene") {
|
91
92
|
if (debug)
|
92
93
|
console.log("DONE", JSON.stringify(_nodeDef));
|
@@ -102,7 +103,7 @@
|
|
102
103
|
// console.log(_nodeDef, _nodeDef.mesh);
|
103
104
|
}
|
104
105
|
|
105
|
-
writeNode(node:
|
106
|
+
writeNode(node: Object3D, nodeDef) {
|
106
107
|
let nodeIndex = this.writer.json.nodes.length;
|
107
108
|
console.log(node.name, nodeIndex, node.uuid);
|
108
109
|
const context = new ExportData(node, nodeIndex, nodeDef);
|
@@ -198,7 +199,7 @@
|
|
198
199
|
await Promise.all(loadComponents);
|
199
200
|
}
|
200
201
|
|
201
|
-
private async createComponents(obj:
|
202
|
+
private async createComponents(obj: Object3D, data: ExtensionData) {
|
202
203
|
if (!data) return;
|
203
204
|
const componentData = data[builtinComponentKeyName];
|
204
205
|
if (componentData) {
|
@@ -43,11 +43,20 @@
|
|
43
43
|
if (ext) {
|
44
44
|
if (debug)
|
45
45
|
console.log("Apply \"" + this.name + "\", src: \"" + this.sourceId + "\"", ext);
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
46
|
+
let settings: SceneLightSettings | undefined = undefined;
|
47
|
+
// If the result scene has only one child we add the LightingSettingsComponent to that child
|
48
|
+
if (_result.scene.children.length === 1) {
|
49
|
+
// add a component to the root of the scene
|
50
|
+
settings = GameObject.addNewComponent(_result.scene.children[0], SceneLightSettings, false);
|
51
|
+
}
|
52
|
+
// if the scene already has multiple children we add it as a new object
|
53
|
+
else
|
54
|
+
{
|
55
|
+
const lightSettings = new Object3D();
|
56
|
+
lightSettings.name = "Needle LightSettings";
|
57
|
+
_result.scene.add(lightSettings);
|
58
|
+
settings = GameObject.addNewComponent(lightSettings, SceneLightSettings, false);
|
59
|
+
}
|
51
60
|
settings.sourceId = this.sourceId;
|
52
61
|
settings.ambientIntensity = ext.ambientIntensity;
|
53
62
|
settings.ambientLight = new Color().fromArray(ext.ambientLight);
|
@@ -109,7 +118,7 @@
|
|
109
118
|
}
|
110
119
|
if (this.ambientMode == AmbientMode.Flat) {
|
111
120
|
if (this.ambientLight && !this._ambientLightObj) {
|
112
|
-
this._ambientLightObj = new AmbientLight(this.ambientLight,
|
121
|
+
this._ambientLightObj = new AmbientLight(this.ambientLight, this.ambientIntensity);
|
113
122
|
}
|
114
123
|
if (this._ambientLightObj) {
|
115
124
|
this.gameObject.add(this._ambientLightObj)
|
@@ -1,7 +1,6 @@
|
|
1
1
|
import { GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader";
|
2
|
-
import * as THREE from 'three';
|
3
2
|
import { FindShaderTechniques, whiteDefaultTexture, ToUnityMatrixArray, SetUnitySphericalHarmonics } from '../engine_shaders';
|
4
|
-
import { IUniform, RawShaderMaterial, Vector4 } from 'three';
|
3
|
+
import { AlwaysDepth, BackSide, Camera, DoubleSide, EqualDepth, FrontSide, GreaterDepth, GreaterEqualDepth, IUniform, LessDepth, LessEqualDepth, LinearEncoding, Material, Matrix4, NotEqualDepth, Object3D, RawShaderMaterial, Vector3, Vector4 } from 'three';
|
5
4
|
import { Context } from '../engine_setup';
|
6
5
|
import { getParam } from "../engine_utils";
|
7
6
|
import * as SHADERDATA from "../shaders/shaderData"
|
@@ -37,13 +36,13 @@
|
|
37
36
|
}
|
38
37
|
|
39
38
|
class ObjectRendererData {
|
40
|
-
objectToWorldMatrix:
|
41
|
-
worldToObjectMatrix:
|
39
|
+
objectToWorldMatrix: Matrix4 = new Matrix4();
|
40
|
+
worldToObjectMatrix: Matrix4 = new Matrix4();
|
42
41
|
|
43
42
|
objectToWorld: Array<Vector4> = new Array<Vector4>();
|
44
43
|
worldToObject: Array<Vector4> = new Array<Vector4>();
|
45
44
|
|
46
|
-
updateFrom(obj:
|
45
|
+
updateFrom(obj: Object3D) {
|
47
46
|
this.objectToWorldMatrix.copy(obj.matrixWorld);
|
48
47
|
ToUnityMatrixArray(this.objectToWorldMatrix, this.objectToWorld);
|
49
48
|
|
@@ -132,7 +131,7 @@
|
|
132
131
|
this.uniforms["unity_SpecCube0"] = { value: envTexture };
|
133
132
|
SetUnitySphericalHarmonics(this.uniforms, array);
|
134
133
|
const hdr = Math.sqrt(Math.PI * .5);
|
135
|
-
this.uniforms["unity_SpecCube0_HDR"] = { value: new
|
134
|
+
this.uniforms["unity_SpecCube0_HDR"] = { value: new Vector4(hdr, hdr, hdr, hdr) };
|
136
135
|
// this.needsUpdate = true;
|
137
136
|
// this.uniformsNeedUpdate = true;
|
138
137
|
if (debug) console.log("Set environment lighting", this.uniforms);
|
@@ -143,20 +142,20 @@
|
|
143
142
|
private _objToWorldName = "hlslcc_mtx4x4unity_ObjectToWorld";
|
144
143
|
private _worldToObjectName = "hlslcc_mtx4x4unity_WorldToObject";
|
145
144
|
|
146
|
-
private static viewProjection:
|
145
|
+
private static viewProjection: Matrix4 = new Matrix4();
|
147
146
|
private static _viewProjectionValues: Array<Vector4> = [];
|
148
147
|
private _viewProjectionName = "hlslcc_mtx4x4unity_MatrixVP";
|
149
148
|
|
150
|
-
private static viewMatrix:
|
149
|
+
private static viewMatrix: Matrix4 = new Matrix4();
|
151
150
|
private static _viewMatrixValues: Array<Vector4> = [];
|
152
151
|
private _viewMatrixName = "hlslcc_mtx4x4unity_MatrixV";
|
153
152
|
|
154
153
|
private static _worldSpaceCameraPosName = "_WorldSpaceCameraPos";
|
155
|
-
private static _worldSpaceCameraPos:
|
154
|
+
private static _worldSpaceCameraPos: Vector3 = new Vector3();
|
156
155
|
|
157
|
-
private static _mainLightColor:
|
158
|
-
private static _mainLightPosition:
|
159
|
-
private static _lightData:
|
156
|
+
private static _mainLightColor: Vector4 = new Vector4();
|
157
|
+
private static _mainLightPosition: Vector3 = new Vector3();
|
158
|
+
private static _lightData: Vector4 = new Vector4();
|
160
159
|
|
161
160
|
private _rendererData = new ObjectRendererData();
|
162
161
|
|
@@ -184,7 +183,7 @@
|
|
184
183
|
this.onUpdateUniforms(camera, obj);
|
185
184
|
}
|
186
185
|
|
187
|
-
onUpdateUniforms(camera?:
|
186
|
+
onUpdateUniforms(camera?: Camera, obj?: any) {
|
188
187
|
|
189
188
|
const context = Context.Current;
|
190
189
|
|
@@ -309,7 +308,7 @@
|
|
309
308
|
this.identifier = identifier;
|
310
309
|
}
|
311
310
|
|
312
|
-
loadMaterial(index: number): Promise<
|
311
|
+
loadMaterial(index: number): Promise<Material> | null {
|
313
312
|
|
314
313
|
const mat = this.parser.json.materials[index];
|
315
314
|
if (!mat) {
|
@@ -328,7 +327,7 @@
|
|
328
327
|
const technique: SHADERDATA.Technique = shaders.techniques[techniqueIndex];
|
329
328
|
if (!technique) return null;
|
330
329
|
|
331
|
-
return new Promise<
|
330
|
+
return new Promise<Material>(async (resolve, reject) => {
|
332
331
|
const bundle = await FindShaderTechniques(shaders, technique.program!);
|
333
332
|
const frag = bundle?.fragmentShader;
|
334
333
|
const vert = bundle?.vertexShader;
|
@@ -342,7 +341,7 @@
|
|
342
341
|
const techniqueUniforms = technique.uniforms;
|
343
342
|
|
344
343
|
if (vert.includes("_Time"))
|
345
|
-
uniforms["_Time"] = { value: new
|
344
|
+
uniforms["_Time"] = { value: new Vector4(0, 0, 0, 0) };
|
346
345
|
|
347
346
|
for (const u in techniqueUniforms) {
|
348
347
|
const uniformName = u;
|
@@ -350,7 +349,7 @@
|
|
350
349
|
// const typeName = UniformType[uniformValues.type];
|
351
350
|
switch (uniformName) {
|
352
351
|
case "_TimeParameters":
|
353
|
-
const timeUniform = new
|
352
|
+
const timeUniform = new Vector4();
|
354
353
|
uniforms[uniformName] = { value: timeUniform };
|
355
354
|
break;
|
356
355
|
|
@@ -422,7 +421,7 @@
|
|
422
421
|
if (texIndex >= 0) {
|
423
422
|
const tex = await this.parser.getDependency("texture", texIndex);
|
424
423
|
if (tex) {
|
425
|
-
tex.encoding =
|
424
|
+
tex.encoding = LinearEncoding;
|
426
425
|
tex.needsUpdate = true;
|
427
426
|
}
|
428
427
|
uniforms[key] = { value: tex };
|
@@ -436,7 +435,7 @@
|
|
436
435
|
}
|
437
436
|
}
|
438
437
|
if (Array.isArray(val) && val.length === 4) {
|
439
|
-
uniforms[key] = { value: new
|
438
|
+
uniforms[key] = { value: new Vector4(val[0], val[1], val[2], val[3]) };
|
440
439
|
continue;
|
441
440
|
}
|
442
441
|
uniforms[key] = { value: val };
|
@@ -460,16 +459,16 @@
|
|
460
459
|
const culling = uniforms["_Cull"]?.value;
|
461
460
|
switch (culling) {
|
462
461
|
case CullMode.Off:
|
463
|
-
material.side =
|
462
|
+
material.side = DoubleSide;
|
464
463
|
break;
|
465
464
|
case CullMode.Front:
|
466
|
-
material.side =
|
465
|
+
material.side = BackSide;
|
467
466
|
break;
|
468
467
|
case CullMode.Back:
|
469
|
-
material.side =
|
468
|
+
material.side = FrontSide;
|
470
469
|
break;
|
471
470
|
default:
|
472
|
-
material.side =
|
471
|
+
material.side = FrontSide;
|
473
472
|
break;
|
474
473
|
}
|
475
474
|
|
@@ -477,31 +476,31 @@
|
|
477
476
|
switch (zTest) {
|
478
477
|
case ZTestMode.Equal:
|
479
478
|
material.depthTest = true;
|
480
|
-
material.depthFunc =
|
479
|
+
material.depthFunc = EqualDepth;
|
481
480
|
break;
|
482
481
|
case ZTestMode.NotEqual:
|
483
482
|
material.depthTest = true;
|
484
|
-
material.depthFunc =
|
483
|
+
material.depthFunc = NotEqualDepth;
|
485
484
|
break;
|
486
485
|
case ZTestMode.Less:
|
487
486
|
material.depthTest = true;
|
488
|
-
material.depthFunc =
|
487
|
+
material.depthFunc = LessDepth;
|
489
488
|
break;
|
490
489
|
case ZTestMode.LEqual:
|
491
490
|
material.depthTest = true;
|
492
|
-
material.depthFunc =
|
491
|
+
material.depthFunc = LessEqualDepth;
|
493
492
|
break;
|
494
493
|
case ZTestMode.Greater:
|
495
494
|
material.depthTest = true;
|
496
|
-
material.depthFunc =
|
495
|
+
material.depthFunc = GreaterDepth;
|
497
496
|
break;
|
498
497
|
case ZTestMode.GEqual:
|
499
498
|
material.depthTest = true;
|
500
|
-
material.depthFunc =
|
499
|
+
material.depthFunc = GreaterEqualDepth;
|
501
500
|
break;
|
502
501
|
case ZTestMode.Always:
|
503
502
|
material.depthTest = false;
|
504
|
-
material.depthFunc =
|
503
|
+
material.depthFunc = AlwaysDepth;
|
505
504
|
break;
|
506
505
|
}
|
507
506
|
|
@@ -6,19 +6,16 @@
|
|
6
6
|
|
7
7
|
import "./engine-components/CameraUtils"
|
8
8
|
|
9
|
-
|
10
|
-
export { GameObject, Behaviour } from "./engine-components/Component";
|
11
|
-
export { serializable, serializeable } from "./engine/engine_serialization_decorator";
|
12
|
-
export { Collision } from "./engine/engine_types";
|
13
9
|
export * from "./engine/api";
|
14
10
|
export * from "./engine-components/api";
|
15
|
-
export * from "./engine-components/
|
16
|
-
export * from "./engine-components/js-extensions/Object3D";
|
11
|
+
export * from "./engine-components-experimental/api";
|
17
12
|
|
18
|
-
|
19
13
|
// make accessible for external javascript
|
20
14
|
import { Context } from "./engine/engine_setup";
|
21
15
|
const Needle = { Context: Context };
|
16
|
+
if (globalThis["Needle"] !== undefined) {
|
17
|
+
console.warn("Needle Engine is already imported");
|
18
|
+
}
|
22
19
|
globalThis["Needle"] = Needle;
|
23
20
|
function registerGlobal(obj: object) {
|
24
21
|
for (const key in obj) {
|
@@ -47,7 +44,7 @@
|
|
47
44
|
|
48
45
|
// make three accessible
|
49
46
|
import * as THREE from "three";
|
50
|
-
if(!globalThis["THREE"]) {
|
47
|
+
if (!globalThis["THREE"]) {
|
51
48
|
globalThis["THREE"] = THREE;
|
52
49
|
}
|
53
50
|
else console.warn("Threejs is already imported");
|
@@ -1,1484 +1,1484 @@
|
|
1
|
-
import { Color, Matrix4, Object3D, PointLightShadow, Quaternion, Vector3, Vector2, Euler, Vector4, DirectionalLightHelper } from "three";
|
2
|
-
import { Mathf } from "../engine/engine_math";
|
3
|
-
import { serializable } from "../engine/engine_serialization";
|
4
|
-
import { RGBAColor } from "./js-extensions/RGBAColor";
|
5
|
-
import { AnimationCurve } from "./AnimationCurve";
|
6
|
-
import { Vec2, Vec3 } from "../engine/engine_types";
|
7
|
-
import { Context } from "../engine/engine_setup";
|
8
|
-
import { EmitterShape, FrameOverLife, Particle, ShapeJSON } from "three.quarks";
|
9
|
-
import { createNoise4D, NoiseFunction4D } from 'simplex-noise';
|
10
|
-
import { Gizmos } from "../engine/engine_gizmos";
|
11
|
-
import { getParam } from "../engine/engine_utils";
|
12
|
-
|
13
|
-
const debug = getParam("debugparticles");
|
14
|
-
|
15
|
-
declare type Color4 = { r: number, g: number, b: number, a: number };
|
16
|
-
declare type ColorKey = { time: number, color: Color4 };
|
17
|
-
declare type AlphaKey = { time: number, alpha: number };
|
18
|
-
|
19
|
-
export interface IParticleSystem {
|
20
|
-
get currentParticles(): number;
|
21
|
-
get maxParticles(): number;
|
22
|
-
get time(): number;
|
23
|
-
get deltaTime(): number;
|
24
|
-
get duration(): number;
|
25
|
-
readonly main: MainModule;
|
26
|
-
get container(): Object3D;
|
27
|
-
get worldspace(): boolean;
|
28
|
-
get worldPos(): Vector3;
|
29
|
-
get worldQuaternion(): Quaternion;
|
30
|
-
get worldQuaternionInverted(): Quaternion;
|
31
|
-
get worldScale(): Vector3;
|
32
|
-
get matrixWorld(): Matrix4;
|
33
|
-
}
|
34
|
-
|
35
|
-
|
36
|
-
export enum ParticleSystemRenderMode {
|
37
|
-
Billboard = 0,
|
38
|
-
Stretch = 1,
|
39
|
-
HorizontalBillboard = 2,
|
40
|
-
VerticalBillboard = 3,
|
41
|
-
Mesh = 4,
|
42
|
-
// None = 5,
|
43
|
-
}
|
44
|
-
|
45
|
-
|
46
|
-
export class Gradient {
|
47
|
-
@serializable()
|
48
|
-
alphaKeys!: Array<AlphaKey>;
|
49
|
-
@serializable()
|
50
|
-
colorKeys!: Array<ColorKey>;
|
51
|
-
|
52
|
-
get duration(): number {
|
53
|
-
return 1;
|
54
|
-
}
|
55
|
-
|
56
|
-
evaluate(time: number, target: RGBAColor) {
|
57
|
-
|
58
|
-
// target.r = this.colorKeys[0].color.r;
|
59
|
-
// target.g = this.colorKeys[0].color.g;
|
60
|
-
// target.b = this.colorKeys[0].color.b;
|
61
|
-
// target.alpha = this.alphaKeys[0].alpha;
|
62
|
-
// return;
|
63
|
-
|
64
|
-
let closestAlpha: AlphaKey | undefined = undefined;
|
65
|
-
let closestAlphaIndex = 0;
|
66
|
-
let closestColor: ColorKey | null = null;
|
67
|
-
let closestColorIndex = 0;
|
68
|
-
for (let i = 0; i < this.alphaKeys.length; i++) {
|
69
|
-
const key = this.alphaKeys[i];
|
70
|
-
if (key.time < time || !closestAlpha) {
|
71
|
-
closestAlpha = key;
|
72
|
-
closestAlphaIndex = i;
|
73
|
-
}
|
74
|
-
}
|
75
|
-
for (let i = 0; i < this.colorKeys.length; i++) {
|
76
|
-
const key = this.colorKeys[i];
|
77
|
-
if (key.time < time || !closestColor) {
|
78
|
-
closestColor = key;
|
79
|
-
closestColorIndex = i;
|
80
|
-
}
|
81
|
-
}
|
82
|
-
if (closestColor) {
|
83
|
-
const hasNextColor = closestColorIndex + 1 < this.colorKeys.length;
|
84
|
-
if (hasNextColor) {
|
85
|
-
const nextColor = this.colorKeys[closestColorIndex + 1];
|
86
|
-
const t = Mathf.remap(time, closestColor.time, nextColor.time, 0, 1);
|
87
|
-
target.r = Mathf.lerp(closestColor.color.r, nextColor.color.r, t);
|
88
|
-
target.g = Mathf.lerp(closestColor.color.g, nextColor.color.g, t);
|
89
|
-
target.b = Mathf.lerp(closestColor.color.b, nextColor.color.b, t);
|
90
|
-
}
|
91
|
-
else {
|
92
|
-
target.r = closestColor.color.r;
|
93
|
-
target.g = closestColor.color.g;
|
94
|
-
target.b = closestColor.color.b;
|
95
|
-
}
|
96
|
-
}
|
97
|
-
if (closestAlpha) {
|
98
|
-
const hasNextAlpha = closestAlphaIndex + 1 < this.alphaKeys.length;
|
99
|
-
if (hasNextAlpha) {
|
100
|
-
const nextAlpha = this.alphaKeys[closestAlphaIndex + 1];
|
101
|
-
const t = Mathf.remap(time, closestAlpha.time, nextAlpha.time, 0, 1);
|
102
|
-
target.alpha = Mathf.lerp(closestAlpha.alpha, nextAlpha.alpha, t);
|
103
|
-
}
|
104
|
-
else {
|
105
|
-
target.alpha = closestAlpha.alpha;
|
106
|
-
}
|
107
|
-
}
|
108
|
-
return target;
|
109
|
-
}
|
110
|
-
}
|
111
|
-
|
112
|
-
export enum ParticleSystemCurveMode {
|
113
|
-
Constant = 0,
|
114
|
-
Curve = 1,
|
115
|
-
TwoCurves = 2,
|
116
|
-
TwoConstants = 3
|
117
|
-
}
|
118
|
-
|
119
|
-
export enum ParticleSystemGradientMode {
|
120
|
-
Color = 0,
|
121
|
-
Gradient = 1,
|
122
|
-
TwoColors = 2,
|
123
|
-
TwoGradients = 3,
|
124
|
-
RandomColor = 4,
|
125
|
-
}
|
126
|
-
|
127
|
-
export enum ParticleSystemSimulationSpace {
|
128
|
-
Local = 0,
|
129
|
-
World = 1,
|
130
|
-
Custom = 2
|
131
|
-
}
|
132
|
-
|
133
|
-
export enum ParticleSystemShapeType {
|
134
|
-
Sphere = 0,
|
135
|
-
SphereShell = 1,
|
136
|
-
Hemisphere = 2,
|
137
|
-
HemisphereShell = 3,
|
138
|
-
Cone = 4,
|
139
|
-
Box = 5,
|
140
|
-
Mesh = 6,
|
141
|
-
ConeShell = 7,
|
142
|
-
ConeVolume = 8,
|
143
|
-
ConeVolumeShell = 9,
|
144
|
-
Circle = 10,
|
145
|
-
CircleEdge = 11,
|
146
|
-
SingleSidedEdge = 12,
|
147
|
-
MeshRenderer = 13,
|
148
|
-
SkinnedMeshRenderer = 14,
|
149
|
-
BoxShell = 15,
|
150
|
-
BoxEdge = 16,
|
151
|
-
Donut = 17,
|
152
|
-
Rectangle = 18,
|
153
|
-
Sprite = 19,
|
154
|
-
SpriteRenderer = 20
|
155
|
-
}
|
156
|
-
|
157
|
-
export enum ParticleSystemShapeMultiModeValue {
|
158
|
-
Random = 0,
|
159
|
-
Loop = 1,
|
160
|
-
PingPong = 2,
|
161
|
-
BurstSpread = 3,
|
162
|
-
}
|
163
|
-
|
164
|
-
export class MinMaxCurve {
|
165
|
-
@serializable()
|
166
|
-
mode!: ParticleSystemCurveMode;
|
167
|
-
@serializable()
|
168
|
-
constant!: number;
|
169
|
-
@serializable()
|
170
|
-
constantMin!: number;
|
171
|
-
@serializable()
|
172
|
-
constantMax!: number;
|
173
|
-
@serializable(AnimationCurve)
|
174
|
-
curve?: AnimationCurve;
|
175
|
-
@serializable(AnimationCurve)
|
176
|
-
curveMin?: AnimationCurve;
|
177
|
-
@serializable(AnimationCurve)
|
178
|
-
curveMax?: AnimationCurve;
|
179
|
-
@serializable()
|
180
|
-
curveMultiplier?: number;
|
181
|
-
|
182
|
-
evaluate(t01: number, lerpFactor?: number): number {
|
183
|
-
const t = lerpFactor === undefined ? Math.random() : lerpFactor;
|
184
|
-
switch (this.mode) {
|
185
|
-
case ParticleSystemCurveMode.Constant:
|
186
|
-
return this.constant;
|
187
|
-
case ParticleSystemCurveMode.Curve:
|
188
|
-
t01 = Mathf.clamp01(t01);
|
189
|
-
return this.curve!.evaluate(t01) * this.curveMultiplier!;
|
190
|
-
case ParticleSystemCurveMode.TwoCurves:
|
191
|
-
const t1 = t01 * this.curveMin!.duration;
|
192
|
-
const t2 = t01 * this.curveMax!.duration;
|
193
|
-
return Mathf.lerp(this.curveMin!.evaluate(t1), this.curveMax!.evaluate(t2), t % 1) * this.curveMultiplier!;
|
194
|
-
case ParticleSystemCurveMode.TwoConstants:
|
195
|
-
return Mathf.lerp(this.constantMin, this.constantMax, t % 1)
|
196
|
-
default:
|
197
|
-
this.curveMax!.evaluate(t01) * this.curveMultiplier!;
|
198
|
-
break;
|
199
|
-
}
|
200
|
-
return 0;
|
201
|
-
}
|
202
|
-
|
203
|
-
getMax(): number {
|
204
|
-
switch (this.mode) {
|
205
|
-
case ParticleSystemCurveMode.Constant:
|
206
|
-
return this.constant;
|
207
|
-
case ParticleSystemCurveMode.Curve:
|
208
|
-
return this.getMaxFromCurve(this.curve!) * this.curveMultiplier!;
|
209
|
-
case ParticleSystemCurveMode.TwoCurves:
|
210
|
-
return Math.max(this.getMaxFromCurve(this.curveMin), this.getMaxFromCurve(this.curveMax)) * this.curveMultiplier!;
|
211
|
-
case ParticleSystemCurveMode.TwoConstants:
|
212
|
-
return Math.max(this.constantMin, this.constantMax);
|
213
|
-
default:
|
214
|
-
return 0;
|
215
|
-
}
|
216
|
-
}
|
217
|
-
|
218
|
-
private getMaxFromCurve(curve?: AnimationCurve) {
|
219
|
-
if (!curve) return 0;
|
220
|
-
let maxNumber = Number.MIN_VALUE;
|
221
|
-
for (let i = 0; i < curve!.keys.length; i++) {
|
222
|
-
const key = curve!.keys[i];
|
223
|
-
if (key.value > maxNumber) {
|
224
|
-
maxNumber = key.value;
|
225
|
-
}
|
226
|
-
}
|
227
|
-
return maxNumber;
|
228
|
-
}
|
229
|
-
}
|
230
|
-
|
231
|
-
export class MinMaxGradient {
|
232
|
-
mode!: ParticleSystemGradientMode;
|
233
|
-
@serializable(RGBAColor)
|
234
|
-
color!: RGBAColor;
|
235
|
-
@serializable(RGBAColor)
|
236
|
-
colorMin!: RGBAColor;
|
237
|
-
@serializable(RGBAColor)
|
238
|
-
colorMax!: RGBAColor;
|
239
|
-
@serializable(Gradient)
|
240
|
-
gradient!: Gradient;
|
241
|
-
@serializable(Gradient)
|
242
|
-
gradientMin!: Gradient;
|
243
|
-
@serializable(Gradient)
|
244
|
-
gradientMax!: Gradient;
|
245
|
-
|
246
|
-
private static _temp: RGBAColor = new RGBAColor(0, 0, 0, 1);
|
247
|
-
private static _temp2: RGBAColor = new RGBAColor(0, 0, 0, 1);
|
248
|
-
|
249
|
-
evaluate(t01: number, lerpFactor?: number): RGBAColor {
|
250
|
-
const t = lerpFactor === undefined ? Math.random() : lerpFactor;
|
251
|
-
switch (this.mode) {
|
252
|
-
case ParticleSystemGradientMode.Color:
|
253
|
-
return this.color;
|
254
|
-
case ParticleSystemGradientMode.Gradient:
|
255
|
-
this.gradient.evaluate(t01, MinMaxGradient._temp);
|
256
|
-
return MinMaxGradient._temp
|
257
|
-
case ParticleSystemGradientMode.TwoColors:
|
258
|
-
const col1 = MinMaxGradient._temp.lerpColors(this.colorMin, this.colorMax, t);
|
259
|
-
return col1;
|
260
|
-
case ParticleSystemGradientMode.TwoGradients:
|
261
|
-
this.gradientMin.evaluate(t01, MinMaxGradient._temp);
|
262
|
-
this.gradientMax.evaluate(t01, MinMaxGradient._temp2);
|
263
|
-
return MinMaxGradient._temp.lerp(MinMaxGradient._temp2, t);
|
264
|
-
|
265
|
-
}
|
266
|
-
// console.warn("Not implemented", ParticleSystemGradientMode[this.mode]);
|
267
|
-
MinMaxGradient._temp.set(0xff00ff)
|
268
|
-
MinMaxGradient._temp.alpha = 1;
|
269
|
-
return MinMaxGradient._temp;
|
270
|
-
}
|
271
|
-
}
|
272
|
-
|
273
|
-
declare type ParticleSystemScalingMode = {
|
274
|
-
Hierarchy: number;
|