@needle-tools/engine 2.28.0-pre → 2.30.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 +19 -0
- package/dist/needle-engine.d.ts +232 -139
- package/dist/needle-engine.js +349 -345
- package/dist/needle-engine.js.map +4 -4
- package/dist/needle-engine.min.js +24 -20
- package/dist/needle-engine.min.js.map +4 -4
- package/lib/engine/engine.d.ts +1 -0
- 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_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.d.ts +1 -0
- package/lib/engine/engine_serialization.js +1 -0
- package/lib/engine/engine_serialization.js.map +1 -1
- 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 -0
- package/lib/engine/engine_setup.js +23 -0
- package/lib/engine/engine_setup.js.map +1 -1
- package/lib/engine/engine_utils.d.ts +1 -1
- package/lib/engine/engine_utils.js +25 -8
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_deferred_texture.d.ts +1 -1
- package/lib/engine/extensions/NEEDLE_deferred_texture.js +26 -14
- package/lib/engine/extensions/NEEDLE_deferred_texture.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/extension_utils.js +24 -13
- package/lib/engine/extensions/extension_utils.js.map +1 -1
- package/lib/engine/extensions/extensions.js +3 -1
- package/lib/engine/extensions/extensions.js.map +1 -1
- package/lib/engine-components/Camera.js +7 -0
- package/lib/engine-components/Camera.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 +3 -3
- 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/Renderer.d.ts +1 -0
- package/lib/engine-components/Renderer.js +10 -3
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/ScreenCapture.d.ts +1 -0
- package/lib/engine-components/ScreenCapture.js +265 -1
- package/lib/engine-components/ScreenCapture.js.map +1 -1
- package/lib/engine-components/SpectatorCamera.d.ts +24 -17
- package/lib/engine-components/SpectatorCamera.js +435 -182
- 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/SyncedRoom.js +2 -0
- package/lib/engine-components/SyncedRoom.js.map +1 -1
- package/lib/engine-components/VideoPlayer.d.ts +10 -1
- package/lib/engine-components/VideoPlayer.js +64 -15
- package/lib/engine-components/VideoPlayer.js.map +1 -1
- package/lib/engine-components/Volume.d.ts +4 -0
- package/lib/engine-components/Volume.js +44 -3
- package/lib/engine-components/Volume.js.map +1 -1
- package/lib/engine-components/WebARSessionRoot.d.ts +9 -2
- package/lib/engine-components/WebARSessionRoot.js +69 -24
- package/lib/engine-components/WebARSessionRoot.js.map +1 -1
- package/lib/engine-components/WebXR.d.ts +6 -3
- package/lib/engine-components/WebXR.js +43 -7
- package/lib/engine-components/WebXR.js.map +1 -1
- package/lib/engine-components/WebXRAvatar.d.ts +3 -0
- package/lib/engine-components/WebXRAvatar.js +20 -0
- package/lib/engine-components/WebXRAvatar.js.map +1 -1
- package/lib/engine-components/WebXRController.js +14 -8
- 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/CanvasGroup.d.ts +1 -0
- package/lib/engine-components/ui/CanvasGroup.js +1 -0
- package/lib/engine-components/ui/CanvasGroup.js.map +1 -1
- package/lib/engine-components/ui/EventSystem.js +13 -4
- package/lib/engine-components/ui/EventSystem.js.map +1 -1
- package/lib/engine-components/ui/Graphic.d.ts +1 -0
- package/lib/engine-components/ui/Graphic.js +2 -0
- package/lib/engine-components/ui/Graphic.js.map +1 -1
- package/lib/engine-components/ui/Interfaces.d.ts +2 -0
- package/package.json +2 -2
- package/src/engine/engine_components.js +16 -0
- package/src/engine/engine_input.ts +62 -20
- package/src/engine/engine_physics.ts +2 -1
- package/src/engine/engine_playerview.ts +80 -0
- package/src/engine/engine_serialization.ts +3 -1
- package/src/engine/engine_serialization_core.ts +8 -0
- package/src/engine/engine_setup.ts +24 -0
- package/src/engine/engine_utils.ts +34 -8
- package/src/engine/extensions/NEEDLE_deferred_texture.ts +25 -19
- package/src/engine/extensions/NEEDLE_lighting_settings.ts +4 -2
- package/src/engine/extensions/extension_utils.ts +24 -12
- package/src/engine/extensions/extensions.ts +3 -2
- package/src/engine-components/Camera.ts +9 -1
- package/src/engine-components/Component.ts +1 -1
- package/src/engine-components/Light.ts +3 -0
- package/src/engine-components/OrbitControls.ts +3 -3
- package/src/engine-components/ParticleSystem.ts +25 -26
- package/src/engine-components/PlayerColor.ts +1 -1
- package/src/engine-components/Renderer.ts +11 -3
- package/src/engine-components/ScreenCapture.ts +312 -2
- package/src/engine-components/SpectatorCamera.ts +490 -195
- package/src/engine-components/SyncedCamera.ts +23 -22
- package/src/engine-components/SyncedRoom.ts +1 -0
- package/src/engine-components/VideoPlayer.ts +97 -21
- package/src/engine-components/Volume.ts +47 -4
- package/src/engine-components/WebARSessionRoot.ts +78 -28
- package/src/engine-components/WebXR.ts +51 -15
- package/src/engine-components/WebXRAvatar.ts +27 -2
- package/src/engine-components/WebXRController.ts +21 -15
- package/src/engine-components/WebXRSync.ts +3 -3
- package/src/engine-components/XRFlag.ts +1 -0
- package/src/engine-components/ui/CanvasGroup.ts +2 -0
- package/src/engine-components/ui/EventSystem.ts +21 -15
- package/src/engine-components/ui/Graphic.ts +3 -0
- package/src/engine-components/ui/Interfaces.ts +2 -0
|
@@ -4,7 +4,7 @@ import { ARButton } from '../include/three/ARButton.js';
|
|
|
4
4
|
import { VRButton } from '../include/three/VRButton.js';
|
|
5
5
|
|
|
6
6
|
import * as THREE from 'three'
|
|
7
|
-
import { ArrayCamera, XRHitTestSource } from 'three';
|
|
7
|
+
import { ArrayCamera, Matrix4, Vector3, XRHitTestSource } from 'three';
|
|
8
8
|
|
|
9
9
|
import * as utils from "../engine/engine_utils";
|
|
10
10
|
import { noVoip } from "./Voip";
|
|
@@ -17,6 +17,7 @@ import { EngineElement } from "../engine/engine_element";
|
|
|
17
17
|
import { AssetReference } from "../engine/engine_addressables";
|
|
18
18
|
import { serializeable } from "../engine/engine_serialization_decorator";
|
|
19
19
|
import { WebXRSync } from "./WebXRSync";
|
|
20
|
+
import { XRSessionMode } from "../engine/engine_setup";
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
export async function detectARSupport() {
|
|
@@ -73,7 +74,7 @@ export class WebXR extends Behaviour {
|
|
|
73
74
|
this.events.addEventListener(type, listener);
|
|
74
75
|
return listener;
|
|
75
76
|
}
|
|
76
|
-
public static removeEventListener(type: string, listener: any)
|
|
77
|
+
public static removeEventListener(type: string, listener: any): any {
|
|
77
78
|
this.events.removeEventListener(type, listener);
|
|
78
79
|
return listener;
|
|
79
80
|
}
|
|
@@ -94,10 +95,10 @@ export class WebXR extends Behaviour {
|
|
|
94
95
|
|
|
95
96
|
public static createARButton(webXR: WebXR, opts?: CreateButtonOptions): HTMLButtonElement {
|
|
96
97
|
const domOverlayRoot = webXR.webAR?.getAROverlayContainer();
|
|
97
|
-
const features: any = {
|
|
98
|
+
const features: any = {};
|
|
98
99
|
if (domOverlayRoot) {
|
|
99
100
|
features.domOverlay = { root: domOverlayRoot };
|
|
100
|
-
features.optionalFeatures = ['dom-overlay'];
|
|
101
|
+
features.optionalFeatures = ['hit-test', 'dom-overlay'];
|
|
101
102
|
}
|
|
102
103
|
const arButton = ARButton.createButton(webXR.context.renderer, features);
|
|
103
104
|
arButton.classList.add('webxr-ar-button');
|
|
@@ -120,7 +121,8 @@ export class WebXR extends Behaviour {
|
|
|
120
121
|
if (session) session.end();
|
|
121
122
|
}
|
|
122
123
|
|
|
123
|
-
public get Rig(): THREE.Object3D
|
|
124
|
+
public get Rig(): THREE.Object3D {
|
|
125
|
+
if(!this.rig) this.ensureRig();
|
|
124
126
|
return this.rig;
|
|
125
127
|
}
|
|
126
128
|
|
|
@@ -256,8 +258,6 @@ export class WebXR extends Behaviour {
|
|
|
256
258
|
WebXR.events.dispatchEvent({ type: WebXREvent.XRUpdate, frame: frame, xr: this.context.renderer.xr, rig: this.rig });
|
|
257
259
|
}
|
|
258
260
|
|
|
259
|
-
|
|
260
|
-
|
|
261
261
|
private onClickedARButton() {
|
|
262
262
|
if (!this._isInAR) {
|
|
263
263
|
this._requestedAR = true;
|
|
@@ -313,6 +313,7 @@ export class WebXR extends Behaviour {
|
|
|
313
313
|
}
|
|
314
314
|
else {
|
|
315
315
|
this.rig = new THREE.Group();
|
|
316
|
+
this.rig.rotateY(Math.PI);
|
|
316
317
|
this.rig.name = "XRRig";
|
|
317
318
|
this.context.scene.add(this.rig);
|
|
318
319
|
}
|
|
@@ -360,10 +361,12 @@ export class WebXR extends Behaviour {
|
|
|
360
361
|
|
|
361
362
|
switch (flag) {
|
|
362
363
|
case XRStateFlag.AR:
|
|
364
|
+
this.context.xrSessionMode = XRSessionMode.ImmersiveAR;
|
|
363
365
|
this._isInAR = true;
|
|
364
366
|
this.webAR?.onBegin(session);
|
|
365
367
|
break;
|
|
366
368
|
case XRStateFlag.VR:
|
|
369
|
+
this.context.xrSessionMode = XRSessionMode.ImmersiveVR;
|
|
367
370
|
this._isInVR = true;
|
|
368
371
|
this.onEnterVR(session);
|
|
369
372
|
break;
|
|
@@ -390,6 +393,7 @@ export class WebXR extends Behaviour {
|
|
|
390
393
|
this._isInVR = false;
|
|
391
394
|
this._requestedAR = false;
|
|
392
395
|
this._requestedVR = false;
|
|
396
|
+
this.context.xrSessionMode = undefined;
|
|
393
397
|
|
|
394
398
|
if (this.xrMirrorWindow) {
|
|
395
399
|
this.xrMirrorWindow.close();
|
|
@@ -447,7 +451,10 @@ export class WebXR extends Behaviour {
|
|
|
447
451
|
// not sure if this should be a behaviour.
|
|
448
452
|
// for now we dont really need it to go through the usual update loop
|
|
449
453
|
export class WebAR {
|
|
450
|
-
|
|
454
|
+
|
|
455
|
+
get webxr(): WebXR { return this._webxr; }
|
|
456
|
+
|
|
457
|
+
private _webxr: WebXR;
|
|
451
458
|
|
|
452
459
|
private reticle: THREE.Object3D | null = null;
|
|
453
460
|
private hitTestSource: XRHitTestSource | null = null;
|
|
@@ -467,11 +474,13 @@ export class WebAR {
|
|
|
467
474
|
private get context() { return this.webxr.context; }
|
|
468
475
|
|
|
469
476
|
constructor(webxr: WebXR) {
|
|
470
|
-
this.
|
|
477
|
+
this._webxr = webxr;
|
|
471
478
|
}
|
|
472
479
|
|
|
473
480
|
private arDomOverlay: EngineElement | null = null;
|
|
474
481
|
private arOverlayElement: HTMLElement | null = null;
|
|
482
|
+
private noHitTestAvailable: boolean = false;
|
|
483
|
+
private didPlaceARSessionRoot: boolean = false;
|
|
475
484
|
|
|
476
485
|
getAROverlayContainer(): HTMLElement | null {
|
|
477
486
|
this.arDomOverlay = this.webxr.context.domElement as EngineElement;
|
|
@@ -483,12 +492,14 @@ export class WebAR {
|
|
|
483
492
|
this.reticleActive = active;
|
|
484
493
|
}
|
|
485
494
|
|
|
486
|
-
onBegin(session: THREE.XRSession) {
|
|
495
|
+
async onBegin(session: THREE.XRSession) {
|
|
487
496
|
const context = this.webxr.context;
|
|
488
497
|
this.reticleActive = true;
|
|
498
|
+
this.didPlaceARSessionRoot = false;
|
|
489
499
|
|
|
500
|
+
const deviceType = navigator.userAgent?.includes("OculusBrowser") ? ControllerType.PhysicalDevice : ControllerType.Touch;
|
|
490
501
|
for (let i = 0; i < 4; i++) {
|
|
491
|
-
WebXRController.Create(this.webxr, i, this.webxr.gameObject,
|
|
502
|
+
WebXRController.Create(this.webxr, i, this.webxr.gameObject, deviceType)
|
|
492
503
|
}
|
|
493
504
|
|
|
494
505
|
if (!this.sessionRoot || this.sessionRoot.destroyed || !this.sessionRoot.activeAndEnabled)
|
|
@@ -501,6 +512,9 @@ export class WebAR {
|
|
|
501
512
|
session.requestReferenceSpace('viewer').then((referenceSpace) => {
|
|
502
513
|
session.requestHitTestSource({ space: referenceSpace }).then((source) => {
|
|
503
514
|
this.hitTestSource = source;
|
|
515
|
+
}).catch((_) => {
|
|
516
|
+
this.noHitTestAvailable = true;
|
|
517
|
+
console.warn("WebXR: Hit test not supported");
|
|
504
518
|
});
|
|
505
519
|
});
|
|
506
520
|
|
|
@@ -533,7 +547,7 @@ export class WebAR {
|
|
|
533
547
|
if (this.arDomOverlay && this.arOverlayElement) {
|
|
534
548
|
this.arDomOverlay.onEnterAR(session, this.arOverlayElement);
|
|
535
549
|
}
|
|
536
|
-
|
|
550
|
+
|
|
537
551
|
this.context.mainCameraComponent?.applyClearFlagsIfIsActiveCamera();
|
|
538
552
|
}
|
|
539
553
|
|
|
@@ -551,11 +565,29 @@ export class WebAR {
|
|
|
551
565
|
this.sessionRoot.onEnd(this.webxr.Rig, _session);
|
|
552
566
|
}
|
|
553
567
|
if (this.arDomOverlay) this.arDomOverlay.onExitAR(_session);
|
|
554
|
-
|
|
568
|
+
|
|
555
569
|
this.context.mainCameraComponent?.applyClearFlagsIfIsActiveCamera();
|
|
556
570
|
}
|
|
557
571
|
|
|
558
572
|
onUpdate(session: THREE.XRSession, frame: THREE.XRFrame) {
|
|
573
|
+
|
|
574
|
+
if (this.noHitTestAvailable === true) {
|
|
575
|
+
if (this.reticle)
|
|
576
|
+
this.reticle.visible = false;
|
|
577
|
+
if (!this.didPlaceARSessionRoot) {
|
|
578
|
+
this.didPlaceARSessionRoot = true;
|
|
579
|
+
const rig = this.webxr.Rig;
|
|
580
|
+
const placementMatrix = arPlacementWithoutHitTestMatrix.clone();
|
|
581
|
+
if (rig) {
|
|
582
|
+
const positionFromRig = new Vector3(0, 0, 0).add(rig.position).divideScalar(this.sessionRoot?.arScale ?? 1);
|
|
583
|
+
placementMatrix.multiply(new Matrix4().makeTranslation(positionFromRig.x, positionFromRig.y, positionFromRig.z));
|
|
584
|
+
// placementMatrix.setPosition(positionFromRig);
|
|
585
|
+
}
|
|
586
|
+
this.sessionRoot?.placeAt(rig, placementMatrix);
|
|
587
|
+
}
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
|
|
559
591
|
if (!this.hitTestSource) return;
|
|
560
592
|
const hitTestResults = frame.getHitTestResults(this.hitTestSource);
|
|
561
593
|
if (hitTestResults.length) {
|
|
@@ -563,7 +595,11 @@ export class WebAR {
|
|
|
563
595
|
const referenceSpace = this.webxr.context.renderer.xr.getReferenceSpace();
|
|
564
596
|
if (referenceSpace) {
|
|
565
597
|
const pose = hit.getPose(referenceSpace);
|
|
566
|
-
|
|
598
|
+
|
|
599
|
+
if (this.sessionRoot) {
|
|
600
|
+
const didPlace = this.sessionRoot.onUpdate(this.webxr.Rig, session, pose);
|
|
601
|
+
this.didPlaceARSessionRoot = didPlace;
|
|
602
|
+
}
|
|
567
603
|
|
|
568
604
|
if (this.reticle) {
|
|
569
605
|
this.reticle.visible = this.reticleActive;
|
|
@@ -586,4 +622,4 @@ export class WebAR {
|
|
|
586
622
|
}
|
|
587
623
|
}
|
|
588
624
|
|
|
589
|
-
|
|
625
|
+
const arPlacementWithoutHitTestMatrix = new THREE.Matrix4().identity().makeTranslation(0, -0.5, 0);
|
|
@@ -10,6 +10,8 @@ import { Object3D } from "three";
|
|
|
10
10
|
import { VRUserState } from "./WebXRSync";
|
|
11
11
|
import { getParam } from "../engine/engine_utils";
|
|
12
12
|
import { serializeable } from "../engine/engine_serialization_decorator";
|
|
13
|
+
import { ViewDevice } from "../engine/engine_playerview";
|
|
14
|
+
import { InstancingUtil } from "./Renderer";
|
|
13
15
|
|
|
14
16
|
export const debug = getParam("debugavatar");
|
|
15
17
|
|
|
@@ -18,8 +20,14 @@ export type AvatarMarkerEventArgs = {
|
|
|
18
20
|
gameObject: Object3D;
|
|
19
21
|
}
|
|
20
22
|
|
|
21
|
-
|
|
22
23
|
export class AvatarMarker extends Behaviour {
|
|
24
|
+
|
|
25
|
+
public static getAvatar(index: number): AvatarMarker | null {
|
|
26
|
+
if (index >= 0 && index < AvatarMarker.instances.length)
|
|
27
|
+
return AvatarMarker.instances[index];
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
23
31
|
public static instances: AvatarMarker[] = [];
|
|
24
32
|
|
|
25
33
|
public static onAvatarMarkerCreated(cb: (args: AvatarMarkerEventArgs) => void): Function {
|
|
@@ -55,7 +63,7 @@ export class AvatarMarker extends Behaviour {
|
|
|
55
63
|
cb({ avatarMarker: this, gameObject: this.gameObject });
|
|
56
64
|
}
|
|
57
65
|
|
|
58
|
-
isLocalAvatar(){
|
|
66
|
+
isLocalAvatar() {
|
|
59
67
|
return this.connectionId === this.context.connection.connectionId;
|
|
60
68
|
}
|
|
61
69
|
|
|
@@ -80,7 +88,10 @@ export class WebXRAvatar {
|
|
|
80
88
|
this.updateVisibility();
|
|
81
89
|
}
|
|
82
90
|
|
|
91
|
+
get isWebXRAvatar() { return true; }
|
|
92
|
+
|
|
83
93
|
// TODO: set layers on all avatars
|
|
94
|
+
/** the user id */
|
|
84
95
|
public guid: string;
|
|
85
96
|
|
|
86
97
|
private root: THREE.Object3D | null = null;
|
|
@@ -148,6 +159,18 @@ export class WebXRAvatar {
|
|
|
148
159
|
|
|
149
160
|
this.lastUpdate = state.time;
|
|
150
161
|
if (this.head) {
|
|
162
|
+
|
|
163
|
+
const device = this.webxr.IsInAR ? ViewDevice.Handheld : ViewDevice.Headset;
|
|
164
|
+
let viewObj = this.head;
|
|
165
|
+
// if (this.isLocalAvatar) {
|
|
166
|
+
// if (this.context.mainCamera && this.context.isInXR) {
|
|
167
|
+
// viewObj = this.context.renderer.xr.getCamera(this.context.mainCamera);
|
|
168
|
+
// }
|
|
169
|
+
// }
|
|
170
|
+
this.context.players.setPlayerView(state.guid, viewObj, device);
|
|
171
|
+
|
|
172
|
+
InstancingUtil.markDirty(this.head);
|
|
173
|
+
|
|
151
174
|
this._canInterpolate = true;
|
|
152
175
|
const ht = this.isLocalAvatar ? this.head : this._headTarget;
|
|
153
176
|
ht.position.set(state.position.x, state.position.y, state.position.z);
|
|
@@ -163,6 +186,7 @@ export class WebXRAvatar {
|
|
|
163
186
|
ht.quaternion.multiply(WebXRAvatar.invertRotation);
|
|
164
187
|
ht.scale.set(state.scale, state.scale, state.scale);
|
|
165
188
|
ht.scale.multiply(this.handLeftScale);
|
|
189
|
+
InstancingUtil.markDirty(this.handLeft);
|
|
166
190
|
}
|
|
167
191
|
|
|
168
192
|
if (this.handRight) {
|
|
@@ -172,6 +196,7 @@ export class WebXRAvatar {
|
|
|
172
196
|
ht.quaternion.multiply(WebXRAvatar.invertRotation);
|
|
173
197
|
ht.scale.set(state.scale, state.scale, state.scale);
|
|
174
198
|
ht.scale.multiply(this.handRightScale);
|
|
199
|
+
InstancingUtil.markDirty(this.handRight);
|
|
175
200
|
}
|
|
176
201
|
}
|
|
177
202
|
}
|
|
@@ -13,6 +13,9 @@ import * as utils from "../engine/engine_three_utils"
|
|
|
13
13
|
import { Interactable, UsageMarker } from "./Interactable";
|
|
14
14
|
import { InstancingUtil } from "./Renderer";
|
|
15
15
|
import { Rigidbody } from "./RigidBody";
|
|
16
|
+
import { getParam } from "../engine/engine_utils";
|
|
17
|
+
|
|
18
|
+
const debug = getParam("debugwebxrcontroller");
|
|
16
19
|
|
|
17
20
|
export enum ControllerType {
|
|
18
21
|
PhysicalDevice = 0,
|
|
@@ -103,10 +106,10 @@ export class WebXRController extends Behaviour {
|
|
|
103
106
|
// this is a workaround to fix that temporarely
|
|
104
107
|
// see https://github.com/needle-tools/needle-tiny-playground/issues/123
|
|
105
108
|
const jnts = ctrl.hand["joints"];
|
|
106
|
-
if(jnts){
|
|
107
|
-
for(const key of Object.keys(jnts)){
|
|
109
|
+
if (jnts) {
|
|
110
|
+
for (const key of Object.keys(jnts)) {
|
|
108
111
|
const joint = jnts[key];
|
|
109
|
-
if(joint.parent) continue;
|
|
112
|
+
if (joint.parent) continue;
|
|
110
113
|
ctrl.hand.add(joint);
|
|
111
114
|
}
|
|
112
115
|
}
|
|
@@ -189,7 +192,7 @@ export class WebXRController extends Behaviour {
|
|
|
189
192
|
private _useSmoothing: boolean = true;
|
|
190
193
|
|
|
191
194
|
awake(): void {
|
|
192
|
-
if(!this.controller){
|
|
195
|
+
if (!this.controller) {
|
|
193
196
|
console.warn("Missing Controller!!!", this);
|
|
194
197
|
return;
|
|
195
198
|
}
|
|
@@ -251,7 +254,8 @@ export class WebXRController extends Behaviour {
|
|
|
251
254
|
this.raycastLine?.add(this._raycastHitPoint);
|
|
252
255
|
this._raycastHitPoint.visible = false;
|
|
253
256
|
this.hand.add(this.handPointerModel);
|
|
254
|
-
|
|
257
|
+
if (debug)
|
|
258
|
+
console.log("ADDED TO RIG", this.webXR.Rig);
|
|
255
259
|
|
|
256
260
|
// // console.log("enable", this.index, this.controllerGrip.uuid)
|
|
257
261
|
}
|
|
@@ -427,7 +431,8 @@ export class WebXRController extends Behaviour {
|
|
|
427
431
|
this.movementVector.applyQuaternion(this.webXR.TransformOrientation);
|
|
428
432
|
this.movementVector.y = 0;
|
|
429
433
|
this.movementVector.applyQuaternion(this.worldRot);
|
|
430
|
-
|
|
434
|
+
this.movementVector.multiplyScalar(speedFactor * this.context.time.deltaTime);
|
|
435
|
+
rig.position.add(this.movementVector);
|
|
431
436
|
|
|
432
437
|
if (this.isUsingHands)
|
|
433
438
|
this.runTeleport(rig, buttons);
|
|
@@ -472,7 +477,7 @@ export class WebXRController extends Behaviour {
|
|
|
472
477
|
}
|
|
473
478
|
else this._pinchStartTime = undefined;
|
|
474
479
|
|
|
475
|
-
let doTeleport = teleport > .5;
|
|
480
|
+
let doTeleport = teleport > .5 && this.webXR.IsInVR;
|
|
476
481
|
let isInMiniatureMode = this.webXR.Rig ? this.webXR.Rig?.scale?.x < .999 : false;
|
|
477
482
|
let newRigScale: number | null = null;
|
|
478
483
|
|
|
@@ -482,7 +487,7 @@ export class WebXRController extends Behaviour {
|
|
|
482
487
|
// button[4] seems to be the A button if it exists. On hololens it's randomly pressed though for hands
|
|
483
488
|
// see https://www.w3.org/TR/webxr-gamepads-module-1/#xr-standard-gamepad-mapping
|
|
484
489
|
if (i === 4) {
|
|
485
|
-
if (btn.pressed && !this.didChangeScale) {
|
|
490
|
+
if (btn.pressed && !this.didChangeScale && this.webXR.IsInVR) {
|
|
486
491
|
this.didChangeScale = true;
|
|
487
492
|
const rig = this.webXR.Rig;
|
|
488
493
|
if (rig) {
|
|
@@ -566,7 +571,7 @@ export class WebXRController extends Behaviour {
|
|
|
566
571
|
const scale = Mathf.clamp(this.lastHit.distance * .01 * factor, .015, .1);
|
|
567
572
|
this._raycastHitPoint.scale.set(scale, scale, scale);
|
|
568
573
|
}
|
|
569
|
-
this._raycastHitPoint.visible = this.lastHit !== null;
|
|
574
|
+
this._raycastHitPoint.visible = this.lastHit !== null && this.lastHit !== undefined;
|
|
570
575
|
}
|
|
571
576
|
return hit;
|
|
572
577
|
}
|
|
@@ -583,7 +588,7 @@ export class WebXRController extends Behaviour {
|
|
|
583
588
|
}
|
|
584
589
|
|
|
585
590
|
private selectStartCallback: Function | null = null;
|
|
586
|
-
private lastSelectStartObject
|
|
591
|
+
private lastSelectStartObject: THREE.Object3D | null = null;;
|
|
587
592
|
|
|
588
593
|
private onHandleSelectStart() {
|
|
589
594
|
this.selectStartCallback = null;
|
|
@@ -611,7 +616,8 @@ export class WebXRController extends Behaviour {
|
|
|
611
616
|
for (const intersection of intersections) {
|
|
612
617
|
const object = intersection.object;
|
|
613
618
|
if (!this.testIsVisible(object)) {
|
|
614
|
-
|
|
619
|
+
if (debug)
|
|
620
|
+
console.log("not visible");
|
|
615
621
|
continue;
|
|
616
622
|
}
|
|
617
623
|
this.lastSelectStartObject = object;
|
|
@@ -622,7 +628,7 @@ export class WebXRController extends Behaviour {
|
|
|
622
628
|
sub(this, args);
|
|
623
629
|
}
|
|
624
630
|
}
|
|
625
|
-
if (args.grab !== object)
|
|
631
|
+
if (args.grab !== object && debug)
|
|
626
632
|
console.log("Grabbed object changed", "original", object, "new", args.grab);
|
|
627
633
|
if (args.grab) {
|
|
628
634
|
this.grabbed = AttachedObject.TryTake(this, args.grab, intersection, closeGrab);
|
|
@@ -630,8 +636,7 @@ export class WebXRController extends Behaviour {
|
|
|
630
636
|
break;
|
|
631
637
|
}
|
|
632
638
|
}
|
|
633
|
-
else
|
|
634
|
-
{
|
|
639
|
+
else {
|
|
635
640
|
const subs = WebXRController.eventSubs[ControllerEvents.SelectStart];
|
|
636
641
|
const args = { selected: null, grab: null };
|
|
637
642
|
if (subs && subs.length > 0) {
|
|
@@ -761,7 +766,8 @@ export class AttachedObject {
|
|
|
761
766
|
public static TryTake(controller: WebXRController, candidate: THREE.Object3D, intersection: THREE.Intersection, closeGrab: boolean): AttachedObject | null {
|
|
762
767
|
const interactable = GameObject.getComponentInParent(candidate, Interactable);
|
|
763
768
|
if (!interactable) {
|
|
764
|
-
|
|
769
|
+
if (debug)
|
|
770
|
+
console.warn("Prevented taking object that is not interactable", candidate);
|
|
765
771
|
return null;
|
|
766
772
|
}
|
|
767
773
|
|
|
@@ -346,8 +346,8 @@ export class WebXRSync extends Behaviour {
|
|
|
346
346
|
|
|
347
347
|
private buildLocalAvatar() {
|
|
348
348
|
if (this.localAvatar) return;
|
|
349
|
-
const
|
|
350
|
-
this.localAvatar = new WebXRAvatar(this.context,
|
|
349
|
+
const connectionId = this.context.connection?.connectionId ?? this.k_LocalAvatarNoNetworkingGuid;
|
|
350
|
+
this.localAvatar = new WebXRAvatar(this.context, connectionId, this.webXR!);
|
|
351
351
|
this.localAvatar.isLocalAvatar = true;
|
|
352
352
|
this.localAvatar.setAvatarOverride(this.getAvatarId());
|
|
353
353
|
this.avatars[this.localAvatar.guid] = this.localAvatar;
|
|
@@ -452,7 +452,7 @@ export class WebXRSync extends Behaviour {
|
|
|
452
452
|
|
|
453
453
|
private getAvatarId() {
|
|
454
454
|
const urlAvatar = utils.getParam("avatar") as string;
|
|
455
|
-
const avatarId = urlAvatar;
|
|
455
|
+
const avatarId = urlAvatar ?? null;
|
|
456
456
|
return avatarId;
|
|
457
457
|
}
|
|
458
458
|
}
|
|
@@ -9,9 +9,8 @@ import { PointerEventData } from "./PointerEvents";
|
|
|
9
9
|
import { Raycaster } from "./Raycaster";
|
|
10
10
|
import { InputEvents, KeyCode } from "../../engine/engine_input";
|
|
11
11
|
import { Object3D } from "three";
|
|
12
|
-
import { ICanvasGroup } from "./Interfaces";
|
|
12
|
+
import { ICanvasGroup, IGraphic } from "./Interfaces";
|
|
13
13
|
import { getParam } from "../../engine/engine_utils";
|
|
14
|
-
import { off } from "process";
|
|
15
14
|
|
|
16
15
|
const debug = getParam("debugeventsystem");
|
|
17
16
|
|
|
@@ -135,7 +134,7 @@ export class EventSystem extends Behaviour {
|
|
|
135
134
|
private objectsHoveredLastFrame: THREE.Object3D[] = [];
|
|
136
135
|
// todo: these should be listed by input source (e.g. per controller, mouse, touch)
|
|
137
136
|
private raisedPointerDownEvents: any[] = [];
|
|
138
|
-
private _didMove
|
|
137
|
+
private _didMove: boolean = false;
|
|
139
138
|
|
|
140
139
|
onBeforeUpdate() {
|
|
141
140
|
this.objectsHoveredThisFrame.length = 0;
|
|
@@ -147,9 +146,9 @@ export class EventSystem extends Behaviour {
|
|
|
147
146
|
// console.log("alt pressed");
|
|
148
147
|
return;
|
|
149
148
|
}
|
|
150
|
-
if(!this._didMove){
|
|
149
|
+
if (!this._didMove) {
|
|
151
150
|
const pos = this.context.input.getPointerPositionRC(0);
|
|
152
|
-
if(pos && pos.x === 0 && pos.y === 0) return;
|
|
151
|
+
if (pos && pos.x === 0 && pos.y === 0) return;
|
|
153
152
|
this._didMove = true;
|
|
154
153
|
}
|
|
155
154
|
|
|
@@ -166,10 +165,10 @@ export class EventSystem extends Behaviour {
|
|
|
166
165
|
// handle orbit control before handling input events
|
|
167
166
|
// this is just so button events that modify OrbitControls.enabled work
|
|
168
167
|
let orbitControlComponent: OrbitControls | null = null;
|
|
169
|
-
let previousOrbitControlState
|
|
168
|
+
let previousOrbitControlState: boolean | null = null;
|
|
170
169
|
if (this.context.input.mouseDown && this.currentActiveMeshUIComponents.length > 0 && this.context.mainCameraComponent) {
|
|
171
170
|
orbitControlComponent = GameObject.getComponent(this.context.mainCameraComponent.gameObject, OrbitControls) ?? null;
|
|
172
|
-
if(orbitControlComponent){
|
|
171
|
+
if (orbitControlComponent) {
|
|
173
172
|
previousOrbitControlState = orbitControlComponent.enabled;
|
|
174
173
|
orbitControlComponent.enabled = false;
|
|
175
174
|
}
|
|
@@ -274,16 +273,16 @@ export class EventSystem extends Behaviour {
|
|
|
274
273
|
this._noDepthTestingResults.length = 0;
|
|
275
274
|
for (let i = 0; i < hits.length; i++) {
|
|
276
275
|
const hit = hits[i];
|
|
277
|
-
const object = hit.object as THREE.Mesh;
|
|
278
|
-
if(object.material){
|
|
279
|
-
if(object.material["depthTest"] === false){
|
|
276
|
+
const object = hit.object as THREE.Mesh;
|
|
277
|
+
if (object.material) {
|
|
278
|
+
if (object.material["depthTest"] === false) {
|
|
280
279
|
this._noDepthTestingResults.push(hit);
|
|
281
280
|
continue;
|
|
282
281
|
}
|
|
283
282
|
}
|
|
284
283
|
this._sortingBuffer.push(hit);
|
|
285
284
|
}
|
|
286
|
-
for(const obj of this._sortingBuffer){
|
|
285
|
+
for (const obj of this._sortingBuffer) {
|
|
287
286
|
this._noDepthTestingResults.push(obj);
|
|
288
287
|
}
|
|
289
288
|
return this._noDepthTestingResults;
|
|
@@ -294,7 +293,7 @@ export class EventSystem extends Behaviour {
|
|
|
294
293
|
|
|
295
294
|
if (!this.testIsVisible(object)) {
|
|
296
295
|
if (args.isClicked && debug)
|
|
297
|
-
console.log("not allowed", object);
|
|
296
|
+
console.log("not allowed", object);
|
|
298
297
|
return false;
|
|
299
298
|
}
|
|
300
299
|
|
|
@@ -314,10 +313,17 @@ export class EventSystem extends Behaviour {
|
|
|
314
313
|
const actualGo = parent.shadowComponentOwner.gameObject;
|
|
315
314
|
if (actualGo) {
|
|
316
315
|
canvasGroup = this.tryFindCanvasGroup(actualGo);
|
|
317
|
-
if (canvasGroup?.
|
|
318
|
-
|
|
319
|
-
return true;
|
|
316
|
+
if (canvasGroup?.isCanvasGroup === true) {
|
|
317
|
+
if (canvasGroup.blocksRaycasts === false) return false;
|
|
318
|
+
if (canvasGroup.interactable === false) return true;
|
|
320
319
|
}
|
|
320
|
+
// handle Graphic Raycast target
|
|
321
|
+
const graphic = GameObject.foreachComponent(actualGo, c => {
|
|
322
|
+
if (typeof (c as unknown as IGraphic).raycastTarget === "boolean") return c;
|
|
323
|
+
return undefined;
|
|
324
|
+
}, false);
|
|
325
|
+
if (graphic?.raycastTarget === false) return false;
|
|
326
|
+
|
|
321
327
|
const handled = this.handleMeshUIIntersection(object, pressedOrClicked);
|
|
322
328
|
if (!clicked && handled) {
|
|
323
329
|
// return true;
|
|
@@ -10,6 +10,8 @@ import { onChange, scheduleAction } from "./Utils"
|
|
|
10
10
|
|
|
11
11
|
export class Graphic extends BaseUIComponent implements IGraphic {
|
|
12
12
|
|
|
13
|
+
get isGraphic() { return true; }
|
|
14
|
+
|
|
13
15
|
@serializeable(RGBAColor)
|
|
14
16
|
get color(): RGBAColor {
|
|
15
17
|
if (!this._color) this._color = new RGBAColor(1, 1, 1, 1);
|
|
@@ -132,6 +134,7 @@ export class Graphic extends BaseUIComponent implements IGraphic {
|
|
|
132
134
|
}
|
|
133
135
|
|
|
134
136
|
protected onAfterAddedToScene(): void {
|
|
137
|
+
super.onAfterAddedToScene();
|
|
135
138
|
if (this.shadowComponent) {
|
|
136
139
|
//@ts-ignore
|
|
137
140
|
this.shadowComponent.offset = this.shadowComponent.position.z;
|