@needle-tools/engine 2.27.0-pre → 2.29.0-pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/dist/needle-engine.d.ts +193 -132
- package/dist/needle-engine.js +345 -345
- package/dist/needle-engine.js.map +4 -4
- package/dist/needle-engine.min.js +19 -19
- package/dist/needle-engine.min.js.map +4 -4
- package/lib/engine/engine_input.d.ts +13 -1
- package/lib/engine/engine_input.js +47 -16
- package/lib/engine/engine_input.js.map +1 -1
- package/lib/engine/engine_networking_utils.js +1 -2
- package/lib/engine/engine_networking_utils.js.map +1 -1
- package/lib/engine/engine_physics.d.ts +1 -0
- package/lib/engine/engine_physics.js +2 -1
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_playerview.d.ts +26 -0
- package/lib/engine/engine_playerview.js +65 -0
- package/lib/engine/engine_playerview.js.map +1 -0
- package/lib/engine/engine_serialization_core.js +5 -0
- package/lib/engine/engine_serialization_core.js.map +1 -1
- package/lib/engine/engine_setup.d.ts +8 -1
- package/lib/engine/engine_setup.js +38 -3
- package/lib/engine/engine_setup.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_lighting_settings.js +6 -2
- package/lib/engine/extensions/NEEDLE_lighting_settings.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js +1 -1
- package/lib/engine/extensions/NEEDLE_techniques_webgl.js.map +1 -1
- package/lib/engine-components/Component.d.ts +1 -1
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/Light.js +1 -0
- package/lib/engine-components/Light.js.map +1 -1
- package/lib/engine-components/OrbitControls.js +1 -2
- package/lib/engine-components/OrbitControls.js.map +1 -1
- package/lib/engine-components/ParticleSystem.d.ts +0 -1
- package/lib/engine-components/ParticleSystem.js +24 -27
- package/lib/engine-components/ParticleSystem.js.map +1 -1
- package/lib/engine-components/PlayerColor.js +1 -2
- package/lib/engine-components/PlayerColor.js.map +1 -1
- package/lib/engine-components/SpectatorCamera.d.ts +24 -17
- package/lib/engine-components/SpectatorCamera.js +410 -181
- package/lib/engine-components/SpectatorCamera.js.map +1 -1
- package/lib/engine-components/SyncedCamera.d.ts +8 -4
- package/lib/engine-components/SyncedCamera.js +15 -18
- package/lib/engine-components/SyncedCamera.js.map +1 -1
- package/lib/engine-components/WebXR.js +1 -0
- package/lib/engine-components/WebXR.js.map +1 -1
- package/lib/engine-components/WebXRAvatar.d.ts +3 -0
- package/lib/engine-components/WebXRAvatar.js +16 -0
- package/lib/engine-components/WebXRAvatar.js.map +1 -1
- package/lib/engine-components/WebXRController.js +1 -1
- package/lib/engine-components/WebXRController.js.map +1 -1
- package/lib/engine-components/WebXRSync.js +3 -3
- package/lib/engine-components/WebXRSync.js.map +1 -1
- package/lib/engine-components/XRFlag.d.ts +2 -1
- package/lib/engine-components/XRFlag.js +1 -0
- package/lib/engine-components/XRFlag.js.map +1 -1
- package/lib/engine-components/ui/InputField.js +2 -2
- package/package.json +1 -1
- package/src/engine/engine_components.js +16 -0
- package/src/engine/engine_input.ts +62 -20
- package/src/engine/engine_networking_utils.ts +1 -2
- package/src/engine/engine_physics.ts +2 -1
- package/src/engine/engine_playerview.ts +80 -0
- package/src/engine/engine_serialization_core.ts +8 -0
- package/src/engine/engine_setup.ts +37 -3
- package/src/engine/extensions/NEEDLE_lighting_settings.ts +4 -2
- package/src/engine/extensions/NEEDLE_techniques_webgl.ts +1 -1
- package/src/engine-components/Component.ts +1 -1
- package/src/engine-components/Light.ts +3 -0
- package/src/engine-components/OrbitControls.ts +1 -2
- package/src/engine-components/ParticleSystem.ts +25 -26
- package/src/engine-components/PlayerColor.ts +1 -1
- package/src/engine-components/SpectatorCamera.ts +466 -194
- package/src/engine-components/SyncedCamera.ts +23 -22
- package/src/engine-components/WebXR.ts +1 -0
- package/src/engine-components/WebXRAvatar.ts +22 -2
- package/src/engine-components/WebXRController.ts +1 -1
- package/src/engine-components/WebXRSync.ts +3 -3
- package/src/engine-components/XRFlag.ts +1 -0
- package/src/engine-components/ui/InputField.ts +2 -2
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { getParam } from "./engine_utils";
|
|
2
|
+
import { Object3D } from "three";
|
|
3
|
+
import { Context } from "./engine_setup";
|
|
4
|
+
|
|
5
|
+
const debug = getParam("debugplayerview");
|
|
6
|
+
|
|
7
|
+
export enum ViewDevice {
|
|
8
|
+
Browser = "browser",
|
|
9
|
+
Headset = "headset",
|
|
10
|
+
Handheld = "handheld",
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class PlayerView {
|
|
14
|
+
readonly userId: string;
|
|
15
|
+
readonly context: Context;
|
|
16
|
+
|
|
17
|
+
viewDevice: ViewDevice = ViewDevice.Browser;
|
|
18
|
+
|
|
19
|
+
get currentObject(): Object3D | undefined | null {
|
|
20
|
+
return this._object;
|
|
21
|
+
}
|
|
22
|
+
set currentObject(obj: Object3D | undefined | null) {
|
|
23
|
+
this._object = obj;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
get isConnected(): boolean {
|
|
27
|
+
return this.context.connection.userIsInRoom(this.userId);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
removed: boolean = false;
|
|
31
|
+
|
|
32
|
+
private _object: undefined | Object3D | null;
|
|
33
|
+
|
|
34
|
+
constructor(userId: string, context: Context) {
|
|
35
|
+
this.userId = userId;
|
|
36
|
+
this.context = context;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export class PlayerViewManager {
|
|
41
|
+
|
|
42
|
+
private readonly context: Context;
|
|
43
|
+
private readonly playerViews = new Map<string, PlayerView>();
|
|
44
|
+
|
|
45
|
+
constructor(context: Context) {
|
|
46
|
+
this.context = context;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
setPlayerView(id: string, obj: Object3D | undefined | null, device: ViewDevice) {
|
|
50
|
+
let view = this.playerViews.get(id);
|
|
51
|
+
if (!view) {
|
|
52
|
+
view = new PlayerView(id, this.context);
|
|
53
|
+
this.playerViews.set(id, view);
|
|
54
|
+
}
|
|
55
|
+
view.viewDevice = device;
|
|
56
|
+
view.currentObject = obj;
|
|
57
|
+
view.removed = false;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
getPlayerView(id: string | null | undefined): PlayerView | undefined {
|
|
61
|
+
if (!id) return undefined;
|
|
62
|
+
if (!this.context.connection.userIsInRoom(id)) {
|
|
63
|
+
this.playerViews.delete(id);
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
const view = this.playerViews.get(id);
|
|
67
|
+
return view;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
removePlayerView(id: string, device: ViewDevice) {
|
|
71
|
+
const view = this.playerViews.get(id);
|
|
72
|
+
if (view?.viewDevice === device) {
|
|
73
|
+
if (debug)
|
|
74
|
+
console.log("REMOVE", id);
|
|
75
|
+
view.removed = true;
|
|
76
|
+
this.playerViews.delete(id);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
}
|
|
@@ -248,6 +248,14 @@ export function deserializeObject(obj: ISerializable, serializedData: object, co
|
|
|
248
248
|
for (const key in typeInfo) {
|
|
249
249
|
const serializedEntryInfo = typeInfo[key];
|
|
250
250
|
const data = serializedData[key];
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
if (obj[key] !== undefined && data === undefined) {
|
|
254
|
+
// if a field is marked as serialized and has some default value
|
|
255
|
+
// but no data was serialized do not override the default value with undefined
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
|
|
251
259
|
context.path = key;
|
|
252
260
|
|
|
253
261
|
if (serializedEntryInfo === null) {
|
|
@@ -26,6 +26,7 @@ import { RendererData } from './engine_rendererdata';
|
|
|
26
26
|
import { Addressables } from './engine_addressables';
|
|
27
27
|
import { Application } from './engine_application';
|
|
28
28
|
import { LightDataRegistry, ILightDataRegistry } from './engine_lightdata';
|
|
29
|
+
import { PlayerViewManager } from './engine_playerview';
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
const debug = utils.getParam("debugSetup");
|
|
@@ -90,13 +91,26 @@ export class Context {
|
|
|
90
91
|
isManagedExternally: boolean = false;
|
|
91
92
|
|
|
92
93
|
domElement: HTMLElement;
|
|
94
|
+
get resolutionScaleFactor() { return this._resolutionScaleFactor; }
|
|
95
|
+
/** use to scale the resolution up or down of the renderer. default is 1 */
|
|
96
|
+
set resolutionScaleFactor(val: number) {
|
|
97
|
+
if(val === this._resolutionScaleFactor) return;
|
|
98
|
+
if(typeof val !== "number") return;
|
|
99
|
+
if(val <= 0) {
|
|
100
|
+
console.error("Invalid resolution scale factor", val);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
this._resolutionScaleFactor = val;
|
|
104
|
+
this.updateSize();
|
|
105
|
+
}
|
|
106
|
+
private _resolutionScaleFactor: number = 1;
|
|
93
107
|
get domWidth(): number { return this.domElement.clientWidth; }
|
|
94
108
|
get domHeight(): number { return this.domElement.clientHeight; }
|
|
95
109
|
get domX(): number { return this.domElement.offsetLeft; }
|
|
96
110
|
get domY(): number { return this.domElement.offsetTop; }
|
|
97
111
|
get isInXR() { return this.renderer.xr?.isPresenting || false; }
|
|
98
112
|
get xrSession() { return this.renderer.xr?.getSession(); }
|
|
99
|
-
get
|
|
113
|
+
get arOverlayElement(): HTMLElement {
|
|
100
114
|
const el = this.domElement as any;
|
|
101
115
|
if (typeof el.getAROverlayContainer === "function")
|
|
102
116
|
return el.getAROverlayContainer();
|
|
@@ -152,6 +166,7 @@ export class Context {
|
|
|
152
166
|
rendererData: RendererData;
|
|
153
167
|
addressables: Addressables;
|
|
154
168
|
lightmaps: ILightDataRegistry;
|
|
169
|
+
players : PlayerViewManager;
|
|
155
170
|
|
|
156
171
|
private _sizeChanged: boolean = false;
|
|
157
172
|
private _isCreated: boolean = false;
|
|
@@ -199,6 +214,7 @@ export class Context {
|
|
|
199
214
|
this.rendererData = new RendererData(this);
|
|
200
215
|
this.addressables = new Addressables(this);
|
|
201
216
|
this.lightmaps = new LightDataRegistry(this);
|
|
217
|
+
this.players = new PlayerViewManager(this);
|
|
202
218
|
|
|
203
219
|
window.addEventListener('resize', this.updateSize.bind(this));
|
|
204
220
|
const ro = new ResizeObserver(_ => this._sizeChanged = true);
|
|
@@ -208,12 +224,15 @@ export class Context {
|
|
|
208
224
|
private updateSize() {
|
|
209
225
|
if (!this.isManagedExternally && !this.renderer.xr.isPresenting) {
|
|
210
226
|
this._sizeChanged = false;
|
|
211
|
-
const
|
|
212
|
-
const
|
|
227
|
+
const scaleFactor = this.resolutionScaleFactor;
|
|
228
|
+
const width = this.domWidth * scaleFactor;
|
|
229
|
+
const height = this.domHeight * scaleFactor;
|
|
213
230
|
const camera = this.mainCamera as PerspectiveCamera;
|
|
214
231
|
this.updateAspect(camera);
|
|
215
232
|
this.renderer.setSize(width, height);
|
|
216
233
|
this.renderer.setPixelRatio(window.devicePixelRatio);
|
|
234
|
+
this.renderer.domElement.style.width = this.domWidth + "px";
|
|
235
|
+
this.renderer.domElement.style.height = this.domHeight + "px";
|
|
217
236
|
if (this.composer) {
|
|
218
237
|
this.composer.setSize(width, height);
|
|
219
238
|
this.composer.setPixelRatio(window.devicePixelRatio);
|
|
@@ -294,6 +313,21 @@ export class Context {
|
|
|
294
313
|
(this.mainCameraComponent as Camera)?.applyClearFlagsIfIsActiveCamera();
|
|
295
314
|
}
|
|
296
315
|
|
|
316
|
+
removeCamera(cam?: Camera | null) {
|
|
317
|
+
if(!cam) return;
|
|
318
|
+
const index = this._cameraStack.indexOf(cam);
|
|
319
|
+
if (index >= 0) this._cameraStack.splice(index, 1);
|
|
320
|
+
|
|
321
|
+
if (this.mainCameraComponent === cam) {
|
|
322
|
+
this.mainCameraComponent = undefined;
|
|
323
|
+
|
|
324
|
+
if (this._cameraStack.length > 0) {
|
|
325
|
+
const last = this._cameraStack[this._cameraStack.length - 1];
|
|
326
|
+
this.setCurrentCamera(last);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
297
331
|
private _onBeforeRenderListeners: { [key: string]: OnBeforeRenderCallback[] } = {};
|
|
298
332
|
|
|
299
333
|
/** use this to subscribe to onBeforeRender events on threejs objects */
|
|
@@ -99,13 +99,14 @@ export class SceneLightSettings extends Behaviour {
|
|
|
99
99
|
onEnable() {
|
|
100
100
|
const isActive = this.context.mainCameraComponent?.sourceId === this.sourceId;
|
|
101
101
|
if (debug)
|
|
102
|
-
console.log("
|
|
102
|
+
console.log("Enable scene lighting", this.sourceId, isActive, this, this.context.mainCameraComponent?.sourceId);
|
|
103
103
|
if (!isActive) {
|
|
104
|
+
if(debug) console.warn("This is no active?!", this.context.mainCameraComponent?.sourceId)
|
|
104
105
|
// this.enabled = false;
|
|
105
106
|
// return;
|
|
106
107
|
}
|
|
107
108
|
if (this.ambientMode == AmbientMode.Flat) {
|
|
108
|
-
if (this.ambientLight) {
|
|
109
|
+
if (this.ambientLight && !this._ambientLightObj) {
|
|
109
110
|
this._ambientLightObj = new AmbientLight(this.ambientLight, Math.PI * this.ambientIntensity);
|
|
110
111
|
}
|
|
111
112
|
if (this._ambientLightObj) {
|
|
@@ -155,6 +156,7 @@ export class SceneLightSettings extends Behaviour {
|
|
|
155
156
|
if (debug)
|
|
156
157
|
console.log("disable", this.sourceId, this);
|
|
157
158
|
if (this._lightProbeObj) this._lightProbeObj.removeFromParent();
|
|
159
|
+
if(this._ambientLightObj) this._ambientLightObj.removeFromParent();
|
|
158
160
|
if (this.sourceId)
|
|
159
161
|
this.context.rendererData.disableReflection();
|
|
160
162
|
}
|
|
@@ -393,7 +393,7 @@ export class NEEDLE_techniques_webgl implements GLTFLoaderPlugin {
|
|
|
393
393
|
const val = materialExtension.values[key];
|
|
394
394
|
if (typeof val === "string") {
|
|
395
395
|
if (val.startsWith("/textures/")) {
|
|
396
|
-
const indexString = val.substring(
|
|
396
|
+
const indexString = val.substring("/textures/".length);
|
|
397
397
|
const texIndex = Number.parseInt(indexString);
|
|
398
398
|
if (texIndex >= 0) {
|
|
399
399
|
const tex = await this.parser.getDependency("texture", texIndex);
|
|
@@ -644,7 +644,7 @@ abstract class GameObject extends THREE.Object3D implements THREE.Object3D {
|
|
|
644
644
|
return object.getComponentsInChildren(typeName, go, arr);
|
|
645
645
|
}
|
|
646
646
|
|
|
647
|
-
public static getComponentInParent<T>(go: GameObject | THREE.Object3D
|
|
647
|
+
public static getComponentInParent<T>(go: GameObject | THREE.Object3D | Array<Object3D>, typeName: Constructor<T>): T | null {
|
|
648
648
|
return object.getComponentInParent(typeName, go);
|
|
649
649
|
}
|
|
650
650
|
|
|
@@ -9,7 +9,6 @@ import { serializeable } from "../engine/engine_serialization_decorator";
|
|
|
9
9
|
import { Vector3 } from "three";
|
|
10
10
|
|
|
11
11
|
export class OrbitControls extends Behaviour {
|
|
12
|
-
|
|
13
12
|
public get controls() {
|
|
14
13
|
return this._controls;
|
|
15
14
|
}
|
|
@@ -31,7 +30,7 @@ export class OrbitControls extends Behaviour {
|
|
|
31
30
|
minZoom: number = 0;
|
|
32
31
|
maxZoom: number = Infinity;
|
|
33
32
|
enablePan: boolean = true;
|
|
34
|
-
@serializeable(
|
|
33
|
+
@serializeable()
|
|
35
34
|
lookAtConstraint: LookAtConstraint | null = null;
|
|
36
35
|
lookAtConstraint01: number = 1;
|
|
37
36
|
middleClickToFocus: boolean = true;
|
|
@@ -61,7 +61,7 @@ export class ParticleSystem extends Behaviour {
|
|
|
61
61
|
|
|
62
62
|
awake(): void {
|
|
63
63
|
this.renderer = GameObject.getComponent(this.gameObject, ParticleSystemRenderer)!;
|
|
64
|
-
if (debug)
|
|
64
|
+
// if (debug)
|
|
65
65
|
console.log(this);
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -108,31 +108,30 @@ export class ParticleSystem extends Behaviour {
|
|
|
108
108
|
this.activeCount = this.main.prewarm ? this.main.maxParticles : 0;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
update() {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
111
|
+
// update() {
|
|
112
|
+
// if (!this.geometry) return;
|
|
113
|
+
|
|
114
|
+
// const t = this.context.time.deltaTime;
|
|
115
|
+
// this.emit(t);
|
|
116
|
+
|
|
117
|
+
// for (let i = 0; i < this.activeCount; i += 1) {
|
|
118
|
+
// const ps = this.particleStates[i];
|
|
119
|
+
// if (!ps) continue;
|
|
120
|
+
// const vx = ps.velocity.x * t;
|
|
121
|
+
// const vy = ps.velocity.y * t;
|
|
122
|
+
// const vz = ps.velocity.z * t;
|
|
123
|
+
// ps.position.x += vx;
|
|
124
|
+
// ps.position.y += vy;
|
|
125
|
+
// ps.position.z += vz;
|
|
126
|
+
// this.updateOverLifetime(i, ps);
|
|
127
|
+
// this.geometry.attributes.position.setXYZ(i, ps.position.x, ps.position.y, ps.position.z);
|
|
128
|
+
// this.geometry.attributes.color.setXYZ(i, ps.color.r, ps.color.g, ps.color.b);
|
|
129
|
+
// }
|
|
130
|
+
// if (this.geometry) {
|
|
131
|
+
// this.geometry.attributes.position.needsUpdate = true;
|
|
132
|
+
// this.geometry.setDrawRange(0, this.activeCount);
|
|
133
|
+
// }
|
|
134
|
+
// }
|
|
136
135
|
|
|
137
136
|
emit(deltaTime: number) {
|
|
138
137
|
const count = this.activeCount;
|