@shopware-ag/dive 1.16.24 → 1.16.26-beta.0
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/build/dive.cjs +1652 -203
- package/build/dive.cjs.map +1 -1
- package/build/dive.d.cts +50 -8
- package/build/dive.d.ts +50 -8
- package/build/dive.js +1619 -159
- package/build/dive.js.map +1 -1
- package/package.json +1 -1
- package/src/ar/AR.ts +164 -0
- package/src/ar/arquicklook/ARQuickLook.ts +42 -0
- package/src/ar/webxr/WebXR.ts +176 -0
- package/src/ar/webxr/controller/WebXRController.ts +334 -0
- package/src/ar/webxr/crosshair/WebXRCrosshair.ts +35 -0
- package/src/ar/webxr/origin/WebXROrigin.ts +191 -0
- package/src/ar/webxr/overlay/Overlay.ts +50 -0
- package/src/ar/webxr/raycaster/WebXRRaycaster.ts +131 -0
- package/src/ar/webxr/raycaster/ar/WebXRRaycasterAR.ts +102 -0
- package/src/ar/webxr/raycaster/three/WebXRRaycasterTHREE.ts +49 -0
- package/src/ar/webxr/touchscreencontrols/WebXRTouchscreenControls.ts +356 -0
- package/src/axiscamera/AxisCamera.ts +4 -4
- package/src/axiscamera/__test__/AxisCamera.test.ts +4 -0
- package/src/com/Communication.ts +17 -0
- package/src/com/__test__/Communication.test.ts +1 -1
- package/src/com/actions/index.ts +2 -0
- package/src/dive.ts +51 -9
- package/src/events/EventExecutor.ts +35 -0
- package/src/helper/findSceneRecursive/findSceneRecursive.ts +2 -2
- package/src/info/Info.ts +37 -1
- package/src/info/__test__/Info.test.ts +45 -5
- package/src/mediacreator/MediaCreator.ts +4 -4
- package/src/mediacreator/__test__/MediaCreator.test.ts +7 -2
- package/src/renderer/Renderer.ts +21 -11
- package/src/renderer/__test__/Renderer.test.ts +19 -1
- package/src/scene/Scene.ts +35 -12
- package/src/scene/__test__/Scene.test.ts +39 -5
- package/src/scene/root/Root.ts +1 -0
- package/src/scene/xrroot/XRRoot.ts +56 -0
- package/src/scene/xrroot/xrlightroot/XRLightRoot.ts +80 -0
- package/src/toolbox/BaseTool.ts +9 -3
- package/src/toolbox/Toolbox.ts +1 -1
- package/src/toolbox/__test__/Toolbox.test.ts +1 -1
- package/src/toolbox/select/SelectTool.ts +1 -1
- package/src/toolbox/select/__test__/SelectTool.test.ts +1 -1
- package/src/toolbox/transform/TransformTool.ts +4 -4
- package/src/toolbox/transform/__test__/TransformTool.test.ts +2 -4
package/src/com/Communication.ts
CHANGED
|
@@ -21,6 +21,7 @@ import { type DIVEMediaCreator } from '../mediacreator/MediaCreator.ts';
|
|
|
21
21
|
import { type DIVERenderer } from '../renderer/Renderer.ts';
|
|
22
22
|
import { type DIVESelectable } from '../interface/Selectable.ts';
|
|
23
23
|
import { type DIVEIO } from '../io/IO.ts';
|
|
24
|
+
import { type DIVEAR } from '../ar/AR.ts';
|
|
24
25
|
|
|
25
26
|
type EventListener<Action extends keyof Actions> = (
|
|
26
27
|
payload: Actions[Action]['PAYLOAD'],
|
|
@@ -97,6 +98,16 @@ export class DIVECommunication {
|
|
|
97
98
|
return this._io;
|
|
98
99
|
}
|
|
99
100
|
|
|
101
|
+
private _ar: DIVEAR | null;
|
|
102
|
+
private get ar(): DIVEAR {
|
|
103
|
+
if (!this._ar) {
|
|
104
|
+
const DIVEAR = require('../ar/AR.ts')
|
|
105
|
+
.DIVEAR as typeof import('../ar/AR.ts').DIVEAR;
|
|
106
|
+
this._ar = new DIVEAR(this.renderer, this.scene, this.controller);
|
|
107
|
+
}
|
|
108
|
+
return this._ar;
|
|
109
|
+
}
|
|
110
|
+
|
|
100
111
|
private registered: Map<string, COMEntity> = new Map();
|
|
101
112
|
|
|
102
113
|
// private listeners: { [key: string]: EventListener[] } = {};
|
|
@@ -116,6 +127,7 @@ export class DIVECommunication {
|
|
|
116
127
|
this.toolbox = toolbox;
|
|
117
128
|
this._mediaGenerator = null;
|
|
118
129
|
this._io = null;
|
|
130
|
+
this._ar = null;
|
|
119
131
|
|
|
120
132
|
DIVECommunication.__instances.push(this);
|
|
121
133
|
}
|
|
@@ -292,6 +304,11 @@ export class DIVECommunication {
|
|
|
292
304
|
);
|
|
293
305
|
break;
|
|
294
306
|
}
|
|
307
|
+
case 'LAUNCH_AR': {
|
|
308
|
+
this.ar.Launch();
|
|
309
|
+
returnValue = true;
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
295
312
|
default: {
|
|
296
313
|
console.warn(
|
|
297
314
|
`DIVECommunication.PerformAction: has been executed with unknown Action type ${action}`,
|
|
@@ -21,7 +21,7 @@ import '../actions/scene/updatescene';
|
|
|
21
21
|
import '../actions/toolbox/select/setgizmomode';
|
|
22
22
|
import '../actions/toolbox/transform/setgizmovisible';
|
|
23
23
|
import '../actions/camera/getcameratransform';
|
|
24
|
-
import type
|
|
24
|
+
import { type DIVEScene } from '../../scene/Scene';
|
|
25
25
|
import type DIVEToolbox from '../../toolbox/Toolbox';
|
|
26
26
|
import type DIVEOrbitControls from '../../controls/OrbitControls';
|
|
27
27
|
import { type DIVERenderer } from '../../renderer/Renderer';
|
package/src/com/actions/index.ts
CHANGED
package/src/dive.ts
CHANGED
|
@@ -17,7 +17,6 @@ import { DIVECommunication } from './com/Communication.ts';
|
|
|
17
17
|
import { DIVEAnimationSystem } from './animation/AnimationSystem.ts';
|
|
18
18
|
import DIVEAxisCamera from './axiscamera/AxisCamera.ts';
|
|
19
19
|
import { getObjectDelta } from './helper/getObjectDelta/getObjectDelta.ts';
|
|
20
|
-
|
|
21
20
|
import { generateUUID } from 'three/src/math/MathUtils';
|
|
22
21
|
import { DIVEInfo } from './info/Info.ts';
|
|
23
22
|
import pkgjson from '../package.json';
|
|
@@ -63,8 +62,11 @@ export const DIVEDefaultSettings: DIVESettings = {
|
|
|
63
62
|
|
|
64
63
|
export default class DIVE {
|
|
65
64
|
// static members
|
|
66
|
-
public static QuickView(
|
|
67
|
-
|
|
65
|
+
public static QuickView(
|
|
66
|
+
uri: string,
|
|
67
|
+
settings?: Partial<DIVESettings>,
|
|
68
|
+
): DIVE {
|
|
69
|
+
const dive = new DIVE(settings);
|
|
68
70
|
|
|
69
71
|
dive.Communication.PerformAction('SET_CAMERA_TRANSFORM', {
|
|
70
72
|
position: { x: 0, y: 2, z: 2 },
|
|
@@ -92,9 +94,22 @@ export default class DIVE {
|
|
|
92
94
|
// add loaded listener
|
|
93
95
|
dive.Communication.Subscribe('MODEL_LOADED', (data) => {
|
|
94
96
|
if (data.id !== modelid) return;
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
|
|
98
|
+
// console.log(
|
|
99
|
+
// dive.Communication.PerformAction('GET_OBJECTS', {
|
|
100
|
+
// ids: [modelid],
|
|
101
|
+
// })[0].position,
|
|
102
|
+
// );
|
|
103
|
+
|
|
104
|
+
// dive.Communication.PerformAction('PLACE_ON_FLOOR', {
|
|
105
|
+
// id: modelid,
|
|
106
|
+
// });
|
|
107
|
+
|
|
108
|
+
// console.log(
|
|
109
|
+
// dive.Communication.PerformAction('GET_OBJECTS', {
|
|
110
|
+
// ids: [modelid],
|
|
111
|
+
// }),
|
|
112
|
+
// );
|
|
98
113
|
|
|
99
114
|
const transform = dive.Communication.PerformAction(
|
|
100
115
|
'COMPUTE_ENCOMPASSING_VIEW',
|
|
@@ -277,9 +292,36 @@ export default class DIVE {
|
|
|
277
292
|
},
|
|
278
293
|
};
|
|
279
294
|
|
|
280
|
-
console.log(
|
|
281
|
-
|
|
282
|
-
|
|
295
|
+
console.log(`
|
|
296
|
+
@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@
|
|
297
|
+
@@@@+-:::::::---------------------==------------------------------=#@@@@
|
|
298
|
+
@@%=::::.......::---------------------------------------------------------+@@
|
|
299
|
+
@@+:::...........::-----------------------------------------------------------#@@
|
|
300
|
+
@@=:::.........::::::--------------${' DIVE ' + pkgjson.version.padStart(7, ' ') + ' '}---------------------------------%@
|
|
301
|
+
@%:::.......:::::::-------------------${process.env.DIVE_NODE_ENV === 'development' ? ' DEV MODE ' : '--------------'}------------------------------------#@
|
|
302
|
+
@*:::.....:::::-----------------------------------------------------------------------*@
|
|
303
|
+
@%::::::.::::---------------------------------------------------------------------------@@
|
|
304
|
+
@@-:::::::::-----------------------------------------------------------------------------=@
|
|
305
|
+
@%::::::::--------------------------------------------------------------------------------%@
|
|
306
|
+
@+::::::::--------------------------------=@@@@@%-----------------------------------------%@
|
|
307
|
+
@=:::::::--------------------------------*@@ @@+---------------------------------------#@
|
|
308
|
+
@+:::::::-------------------------------*@ @*--------------------------------------%@
|
|
309
|
+
@#::::::::-----------------------------=@@ @@=-------------------------------------%@
|
|
310
|
+
@@-::::::::----------------------------@@ @@------------------------------------=@
|
|
311
|
+
@%:::::::::--------------------------*@ @*-----------------------------------@@
|
|
312
|
+
@*:::::::::-------------------------@@ @@----------------------------------%@
|
|
313
|
+
@#::::::::::----------------------%@ @%--------------------------------%@
|
|
314
|
+
@#:::::::::::-------------------=@@ @@=------------------------------%@
|
|
315
|
+
@@-::::::::::::----------------%@ @%----------------------------=@@
|
|
316
|
+
@@#::::::::::::::------------*@ @*--------------------------#@@
|
|
317
|
+
@@+::::::::::::::::--------@@ @@------------------------+@@
|
|
318
|
+
@@*:::::::::::::::::----@@ @@---------------------+@@
|
|
319
|
+
@@@-:::::::::::::::--#@ @#-----------------=%@@
|
|
320
|
+
@@%-::::::::::::-%@ @%-------------=%@@
|
|
321
|
+
@@@@+:::::::#@@ @@*-------*@@@@
|
|
322
|
+
@@@@@@@ @@@@@@
|
|
323
|
+
|
|
324
|
+
`);
|
|
283
325
|
}
|
|
284
326
|
|
|
285
327
|
public Dispose(): void {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export class DIVEEventExecutor<T> {
|
|
2
|
+
private _listeners: Map<keyof T, ((payload: T[keyof T]) => void)[]> =
|
|
3
|
+
new Map();
|
|
4
|
+
|
|
5
|
+
public Subscribe<S extends keyof T>(
|
|
6
|
+
type: S,
|
|
7
|
+
listener: (payload: T[S]) => void,
|
|
8
|
+
): () => boolean {
|
|
9
|
+
if (!this._listeners.get(type)) this._listeners.set(type, []);
|
|
10
|
+
|
|
11
|
+
this._listeners
|
|
12
|
+
.get(type)!
|
|
13
|
+
.push(listener as (payload: T[keyof T]) => void);
|
|
14
|
+
|
|
15
|
+
return () => {
|
|
16
|
+
const listenerArray = this._listeners.get(type);
|
|
17
|
+
if (!listenerArray) return false;
|
|
18
|
+
|
|
19
|
+
const existingIndex = listenerArray.findIndex(
|
|
20
|
+
(entry) => entry === listener,
|
|
21
|
+
);
|
|
22
|
+
if (existingIndex === -1) return false;
|
|
23
|
+
|
|
24
|
+
listenerArray.splice(existingIndex, 1);
|
|
25
|
+
return true;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
protected dispatch<S extends keyof T>(type: S, payload?: T[S]): void {
|
|
30
|
+
const listenerArray = this._listeners.get(type);
|
|
31
|
+
if (!listenerArray) return;
|
|
32
|
+
|
|
33
|
+
listenerArray.forEach((listener) => listener(payload as T[S]));
|
|
34
|
+
}
|
|
35
|
+
}
|
package/src/info/Info.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
|
+
export enum WebXRUnsupportedReason {
|
|
2
|
+
'UNKNWON_ERROR' = 0,
|
|
3
|
+
'NO_HTTPS' = 1,
|
|
4
|
+
'IMMERSIVE_AR_NOT_SUPPORTED_BY_DEVICE' = 2,
|
|
5
|
+
'AR_SESSION_NOT_ALLOWED' = 3,
|
|
6
|
+
}
|
|
7
|
+
|
|
1
8
|
export class DIVEInfo {
|
|
2
9
|
private static _supportsWebXR: boolean | null = null;
|
|
10
|
+
private static _webXRUnsupportedReason: WebXRUnsupportedReason | null =
|
|
11
|
+
null;
|
|
3
12
|
|
|
4
13
|
/**
|
|
5
14
|
*
|
|
@@ -30,21 +39,48 @@ export class DIVEInfo {
|
|
|
30
39
|
return this._supportsWebXR;
|
|
31
40
|
}
|
|
32
41
|
|
|
42
|
+
// check if XRSystem is available && if https enabled
|
|
33
43
|
if (!navigator.xr) {
|
|
34
44
|
this._supportsWebXR = false;
|
|
45
|
+
|
|
46
|
+
if (window.isSecureContext === false) {
|
|
47
|
+
this._webXRUnsupportedReason = WebXRUnsupportedReason.NO_HTTPS;
|
|
48
|
+
} else {
|
|
49
|
+
this._webXRUnsupportedReason =
|
|
50
|
+
WebXRUnsupportedReason.UNKNWON_ERROR;
|
|
51
|
+
}
|
|
52
|
+
|
|
35
53
|
return this._supportsWebXR;
|
|
36
54
|
}
|
|
55
|
+
|
|
37
56
|
// Check if immersive-vr session mode is supported
|
|
38
57
|
try {
|
|
39
58
|
const supported =
|
|
40
|
-
await navigator.xr
|
|
59
|
+
await navigator.xr!.isSessionSupported('immersive-ar');
|
|
60
|
+
if (!supported) {
|
|
61
|
+
this._webXRUnsupportedReason =
|
|
62
|
+
WebXRUnsupportedReason.IMMERSIVE_AR_NOT_SUPPORTED_BY_DEVICE;
|
|
63
|
+
}
|
|
41
64
|
this._supportsWebXR = supported;
|
|
42
65
|
} catch (error) {
|
|
43
66
|
this._supportsWebXR = false;
|
|
67
|
+
this._webXRUnsupportedReason =
|
|
68
|
+
WebXRUnsupportedReason.AR_SESSION_NOT_ALLOWED;
|
|
44
69
|
}
|
|
45
70
|
return this._supportsWebXR;
|
|
46
71
|
}
|
|
47
72
|
|
|
73
|
+
/**
|
|
74
|
+
* @returns The reason why WebXR is not supported on the user's device. Returns null if WebXR is supported nor not has been checked yet.
|
|
75
|
+
*/
|
|
76
|
+
public static GetWebXRUnsupportedReason(): WebXRUnsupportedReason | null {
|
|
77
|
+
if (this._supportsWebXR === null) {
|
|
78
|
+
console.log('WebXR support has not been checked yet.');
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
return this._webXRUnsupportedReason;
|
|
82
|
+
}
|
|
83
|
+
|
|
48
84
|
/**
|
|
49
85
|
* @returns A boolean indicating whether the user's device supports AR Quick Look.
|
|
50
86
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DIVEInfo } from '../Info';
|
|
1
|
+
import { DIVEInfo, WebXRUnsupportedReason } from '../Info';
|
|
2
2
|
|
|
3
3
|
const mockNavigator = (navigator: any) => {
|
|
4
4
|
Object.defineProperty(global, 'navigator', {
|
|
@@ -60,7 +60,6 @@ describe('dive/info/DIVEInfo', () => {
|
|
|
60
60
|
});
|
|
61
61
|
|
|
62
62
|
it('should support webXR', async () => {
|
|
63
|
-
DIVEInfo['_supportsWebXR'] = null;
|
|
64
63
|
mockNavigator({
|
|
65
64
|
xr: {
|
|
66
65
|
isSessionSupported: jest.fn().mockResolvedValue(true),
|
|
@@ -71,16 +70,50 @@ describe('dive/info/DIVEInfo', () => {
|
|
|
71
70
|
});
|
|
72
71
|
|
|
73
72
|
it('should not support webXR (xr undefined)', async () => {
|
|
74
|
-
DIVEInfo['_supportsWebXR'] = null;
|
|
75
73
|
mockNavigator({
|
|
76
74
|
xr: undefined,
|
|
77
75
|
});
|
|
78
76
|
const supports = await DIVEInfo.GetSupportsWebXR();
|
|
79
77
|
expect(supports).toBe(false);
|
|
78
|
+
|
|
79
|
+
const reason = DIVEInfo.GetWebXRUnsupportedReason();
|
|
80
|
+
expect(reason).toBe(WebXRUnsupportedReason.UNKNWON_ERROR);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('should not support webXR (xr undefined & isSecureContext false)', async () => {
|
|
84
|
+
window.isSecureContext = false;
|
|
85
|
+
mockNavigator({
|
|
86
|
+
xr: undefined,
|
|
87
|
+
});
|
|
88
|
+
const supports = await DIVEInfo.GetSupportsWebXR();
|
|
89
|
+
expect(supports).toBe(false);
|
|
90
|
+
|
|
91
|
+
const reason = DIVEInfo.GetWebXRUnsupportedReason();
|
|
92
|
+
expect(reason).toBe(WebXRUnsupportedReason.NO_HTTPS);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('should get empty reason (not checked)', async () => {
|
|
96
|
+
mockNavigator({
|
|
97
|
+
xr: {
|
|
98
|
+
isSessionSupported: jest.fn().mockResolvedValue(true),
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
console.log = jest.fn();
|
|
102
|
+
const reason = DIVEInfo.GetWebXRUnsupportedReason();
|
|
103
|
+
expect(reason).toBe(null);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should get empty reason (webXR supported)', async () => {
|
|
107
|
+
mockNavigator({
|
|
108
|
+
xr: {
|
|
109
|
+
isSessionSupported: jest.fn().mockResolvedValue(true),
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
const reason = DIVEInfo.GetWebXRUnsupportedReason();
|
|
113
|
+
expect(reason).toBe(null);
|
|
80
114
|
});
|
|
81
115
|
|
|
82
116
|
it('should not support webXR', async () => {
|
|
83
|
-
DIVEInfo['_supportsWebXR'] = null;
|
|
84
117
|
mockNavigator({
|
|
85
118
|
xr: {
|
|
86
119
|
isSessionSupported: jest.fn().mockResolvedValue(false),
|
|
@@ -88,10 +121,14 @@ describe('dive/info/DIVEInfo', () => {
|
|
|
88
121
|
});
|
|
89
122
|
const supports = await DIVEInfo.GetSupportsWebXR();
|
|
90
123
|
expect(supports).toBe(false);
|
|
124
|
+
|
|
125
|
+
const reason = DIVEInfo.GetWebXRUnsupportedReason();
|
|
126
|
+
expect(reason).toBe(
|
|
127
|
+
WebXRUnsupportedReason.IMMERSIVE_AR_NOT_SUPPORTED_BY_DEVICE,
|
|
128
|
+
);
|
|
91
129
|
});
|
|
92
130
|
|
|
93
131
|
it('should not support webXR on error', async () => {
|
|
94
|
-
DIVEInfo['_supportsWebXR'] = null;
|
|
95
132
|
mockNavigator({
|
|
96
133
|
xr: {
|
|
97
134
|
isSessionSupported: jest.fn().mockRejectedValue('error'),
|
|
@@ -99,6 +136,9 @@ describe('dive/info/DIVEInfo', () => {
|
|
|
99
136
|
});
|
|
100
137
|
const supports = await DIVEInfo.GetSupportsWebXR();
|
|
101
138
|
expect(supports).toBe(false);
|
|
139
|
+
|
|
140
|
+
const reason = DIVEInfo.GetWebXRUnsupportedReason();
|
|
141
|
+
expect(reason).toBe(WebXRUnsupportedReason.AR_SESSION_NOT_ALLOWED);
|
|
102
142
|
});
|
|
103
143
|
|
|
104
144
|
it('should return cached value', async () => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import DIVEPerspectiveCamera from '../camera/PerspectiveCamera.ts';
|
|
2
|
-
import { DIVEScene } from '../scene/Scene.ts';
|
|
3
|
-
import { DIVERenderer } from '../renderer/Renderer.ts';
|
|
4
|
-
import DIVEOrbitControls from '../controls/OrbitControls.ts';
|
|
5
|
-
import { Vector3Like } from 'three';
|
|
2
|
+
import { type DIVEScene } from '../scene/Scene.ts';
|
|
3
|
+
import { type DIVERenderer } from '../renderer/Renderer.ts';
|
|
4
|
+
import type DIVEOrbitControls from '../controls/OrbitControls.ts';
|
|
5
|
+
import { type Vector3Like } from 'three';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Creates renderings of the current scene
|
|
@@ -17,8 +17,13 @@ const mock_toDataURL = jest.fn();
|
|
|
17
17
|
|
|
18
18
|
jest.mock('../../scene/Scene', () => {
|
|
19
19
|
return {
|
|
20
|
-
DIVEScene: jest.fn(()
|
|
21
|
-
|
|
20
|
+
DIVEScene: jest.fn(function () {
|
|
21
|
+
this.add = jest.fn();
|
|
22
|
+
this.children = [];
|
|
23
|
+
this.Root = {
|
|
24
|
+
children: [],
|
|
25
|
+
};
|
|
26
|
+
return this;
|
|
22
27
|
}),
|
|
23
28
|
};
|
|
24
29
|
});
|
package/src/renderer/Renderer.ts
CHANGED
|
@@ -29,6 +29,11 @@ export const DIVERendererDefaultSettings: DIVERendererSettings = {
|
|
|
29
29
|
canvas: undefined,
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
+
export type DIVERenderCallback = (
|
|
33
|
+
time: DOMHighResTimeStamp,
|
|
34
|
+
frame: XRFrame,
|
|
35
|
+
) => void;
|
|
36
|
+
|
|
32
37
|
/**
|
|
33
38
|
* A changed version of the WebGLRenderer.
|
|
34
39
|
*
|
|
@@ -44,13 +49,13 @@ export class DIVERenderer extends WebGLRenderer {
|
|
|
44
49
|
private force: boolean = false;
|
|
45
50
|
|
|
46
51
|
// pre- and post-render callbacks
|
|
47
|
-
private preRenderCallbacks: Map<string,
|
|
52
|
+
private preRenderCallbacks: Map<string, DIVERenderCallback> = new Map<
|
|
48
53
|
string,
|
|
49
|
-
|
|
54
|
+
DIVERenderCallback
|
|
50
55
|
>();
|
|
51
|
-
private postRenderCallbacks: Map<string,
|
|
56
|
+
private postRenderCallbacks: Map<string, DIVERenderCallback> = new Map<
|
|
52
57
|
string,
|
|
53
|
-
|
|
58
|
+
DIVERenderCallback
|
|
54
59
|
>();
|
|
55
60
|
|
|
56
61
|
constructor(
|
|
@@ -88,8 +93,8 @@ export class DIVERenderer extends WebGLRenderer {
|
|
|
88
93
|
|
|
89
94
|
// Starts the renderer with the given scene and camera.
|
|
90
95
|
public StartRenderer(scene: Scene, cam: Camera): void {
|
|
91
|
-
this.setAnimationLoop(() => {
|
|
92
|
-
this.internal_render(scene, cam);
|
|
96
|
+
this.setAnimationLoop((time: DOMHighResTimeStamp, frame: XRFrame) => {
|
|
97
|
+
this.internal_render(scene, cam, time, frame);
|
|
93
98
|
});
|
|
94
99
|
this.running = true;
|
|
95
100
|
}
|
|
@@ -120,7 +125,7 @@ export class DIVERenderer extends WebGLRenderer {
|
|
|
120
125
|
* @param callback Executed before rendering.
|
|
121
126
|
* @returns uuid to remove the callback.
|
|
122
127
|
*/
|
|
123
|
-
public AddPreRenderCallback(callback:
|
|
128
|
+
public AddPreRenderCallback(callback: DIVERenderCallback): string {
|
|
124
129
|
// add callback to renderloop
|
|
125
130
|
const newUUID = MathUtils.generateUUID();
|
|
126
131
|
this.preRenderCallbacks.set(newUUID, callback);
|
|
@@ -148,7 +153,7 @@ export class DIVERenderer extends WebGLRenderer {
|
|
|
148
153
|
* @param callback Executed after rendering.
|
|
149
154
|
* @returns uuid to remove the callback.
|
|
150
155
|
*/
|
|
151
|
-
public AddPostRenderCallback(callback:
|
|
156
|
+
public AddPostRenderCallback(callback: DIVERenderCallback): string {
|
|
152
157
|
// add callback to renderloop
|
|
153
158
|
const newUUID = MathUtils.generateUUID();
|
|
154
159
|
this.postRenderCallbacks.set(newUUID, callback);
|
|
@@ -185,19 +190,24 @@ export class DIVERenderer extends WebGLRenderer {
|
|
|
185
190
|
* @param scene Scene to render.
|
|
186
191
|
* @param cam Camera to render with.
|
|
187
192
|
*/
|
|
188
|
-
private internal_render(
|
|
193
|
+
private internal_render(
|
|
194
|
+
scene: Scene,
|
|
195
|
+
cam: Camera,
|
|
196
|
+
time: DOMHighResTimeStamp,
|
|
197
|
+
frame: XRFrame,
|
|
198
|
+
): void {
|
|
189
199
|
// execute background render loop callbacks
|
|
190
200
|
if ((this.paused || !this.running) && !this.force) return;
|
|
191
201
|
|
|
192
202
|
// execute render loop callbacks
|
|
193
203
|
this.preRenderCallbacks.forEach((callback) => {
|
|
194
|
-
callback();
|
|
204
|
+
callback(time, frame);
|
|
195
205
|
});
|
|
196
206
|
|
|
197
207
|
this.render(scene, cam);
|
|
198
208
|
|
|
199
209
|
this.postRenderCallbacks.forEach((callback) => {
|
|
200
|
-
callback();
|
|
210
|
+
callback(time, frame);
|
|
201
211
|
});
|
|
202
212
|
|
|
203
213
|
this.force = false;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type DIVEPerspectiveCamera from '../../camera/PerspectiveCamera';
|
|
2
|
-
import type
|
|
2
|
+
import { type DIVEScene } from '../../scene/Scene';
|
|
3
3
|
import { DIVERenderer, DIVERendererDefaultSettings } from '../Renderer';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -123,6 +123,8 @@ describe('dive/renderer/DIVERenderer', () => {
|
|
|
123
123
|
renderer['internal_render'](
|
|
124
124
|
{} as DIVEScene,
|
|
125
125
|
{} as DIVEPerspectiveCamera,
|
|
126
|
+
0.016,
|
|
127
|
+
{} as XRFrame,
|
|
126
128
|
);
|
|
127
129
|
}).not.toThrow();
|
|
128
130
|
expect(mock_render).toHaveBeenCalledTimes(1);
|
|
@@ -139,6 +141,8 @@ describe('dive/renderer/DIVERenderer', () => {
|
|
|
139
141
|
renderer['internal_render'](
|
|
140
142
|
{} as DIVEScene,
|
|
141
143
|
{} as DIVEPerspectiveCamera,
|
|
144
|
+
0.016,
|
|
145
|
+
{} as XRFrame,
|
|
142
146
|
);
|
|
143
147
|
expect(mock_render).toHaveBeenCalledTimes(0);
|
|
144
148
|
});
|
|
@@ -148,6 +152,8 @@ describe('dive/renderer/DIVERenderer', () => {
|
|
|
148
152
|
renderer['internal_render'](
|
|
149
153
|
{} as DIVEScene,
|
|
150
154
|
{} as DIVEPerspectiveCamera,
|
|
155
|
+
0.016,
|
|
156
|
+
{} as XRFrame,
|
|
151
157
|
);
|
|
152
158
|
expect(mock_render).toHaveBeenCalledTimes(1);
|
|
153
159
|
|
|
@@ -155,6 +161,8 @@ describe('dive/renderer/DIVERenderer', () => {
|
|
|
155
161
|
renderer['internal_render'](
|
|
156
162
|
{} as DIVEScene,
|
|
157
163
|
{} as DIVEPerspectiveCamera,
|
|
164
|
+
0.016,
|
|
165
|
+
{} as XRFrame,
|
|
158
166
|
);
|
|
159
167
|
expect(mock_render).toHaveBeenCalledTimes(1);
|
|
160
168
|
});
|
|
@@ -164,6 +172,8 @@ describe('dive/renderer/DIVERenderer', () => {
|
|
|
164
172
|
renderer['internal_render'](
|
|
165
173
|
{} as DIVEScene,
|
|
166
174
|
{} as DIVEPerspectiveCamera,
|
|
175
|
+
0.016,
|
|
176
|
+
{} as XRFrame,
|
|
167
177
|
);
|
|
168
178
|
expect(mock_render).toHaveBeenCalledTimes(1);
|
|
169
179
|
|
|
@@ -171,6 +181,8 @@ describe('dive/renderer/DIVERenderer', () => {
|
|
|
171
181
|
renderer['internal_render'](
|
|
172
182
|
{} as DIVEScene,
|
|
173
183
|
{} as DIVEPerspectiveCamera,
|
|
184
|
+
0.016,
|
|
185
|
+
{} as XRFrame,
|
|
174
186
|
);
|
|
175
187
|
expect(mock_render).toHaveBeenCalledTimes(1);
|
|
176
188
|
});
|
|
@@ -181,6 +193,8 @@ describe('dive/renderer/DIVERenderer', () => {
|
|
|
181
193
|
renderer['internal_render'](
|
|
182
194
|
{} as DIVEScene,
|
|
183
195
|
{} as DIVEPerspectiveCamera,
|
|
196
|
+
0.016,
|
|
197
|
+
{} as XRFrame,
|
|
184
198
|
);
|
|
185
199
|
expect(mock_render).toHaveBeenCalledTimes(0);
|
|
186
200
|
|
|
@@ -188,6 +202,8 @@ describe('dive/renderer/DIVERenderer', () => {
|
|
|
188
202
|
renderer['internal_render'](
|
|
189
203
|
{} as DIVEScene,
|
|
190
204
|
{} as DIVEPerspectiveCamera,
|
|
205
|
+
0.016,
|
|
206
|
+
{} as XRFrame,
|
|
191
207
|
);
|
|
192
208
|
expect(mock_render).toHaveBeenCalledTimes(1);
|
|
193
209
|
});
|
|
@@ -233,6 +249,8 @@ describe('dive/renderer/DIVERenderer', () => {
|
|
|
233
249
|
renderer['internal_render'](
|
|
234
250
|
{} as DIVEScene,
|
|
235
251
|
{} as DIVEPerspectiveCamera,
|
|
252
|
+
0.016,
|
|
253
|
+
{} as XRFrame,
|
|
236
254
|
);
|
|
237
255
|
expect(precallback).toHaveBeenCalledTimes(1);
|
|
238
256
|
expect(postcallback).toHaveBeenCalledTimes(1);
|
package/src/scene/Scene.ts
CHANGED
|
@@ -4,6 +4,8 @@ import { DIVERoot } from './root/Root';
|
|
|
4
4
|
import { DIVEGrid } from '../grid/Grid';
|
|
5
5
|
import { DIVEFloor } from '../primitive/floor/Floor';
|
|
6
6
|
import { type DIVESceneObject } from '../types';
|
|
7
|
+
import { DIVEXRRoot } from './xrroot/XRRoot';
|
|
8
|
+
import { type DIVERenderer } from '../renderer/Renderer';
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* A basic scene class.
|
|
@@ -14,20 +16,25 @@ import { type DIVESceneObject } from '../types';
|
|
|
14
16
|
*/
|
|
15
17
|
|
|
16
18
|
export class DIVEScene extends Scene {
|
|
17
|
-
private
|
|
18
|
-
private
|
|
19
|
-
private
|
|
19
|
+
private _root: DIVERoot;
|
|
20
|
+
private _floor: DIVEFloor;
|
|
21
|
+
private _grid: DIVEGrid;
|
|
20
22
|
|
|
21
23
|
public get Root(): DIVERoot {
|
|
22
|
-
return this.
|
|
24
|
+
return this._root;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
private _xrRoot: DIVEXRRoot;
|
|
28
|
+
public get XRRoot(): DIVEXRRoot {
|
|
29
|
+
return this._xrRoot;
|
|
23
30
|
}
|
|
24
31
|
|
|
25
32
|
public get Floor(): DIVEFloor {
|
|
26
|
-
return this.
|
|
33
|
+
return this._floor;
|
|
27
34
|
}
|
|
28
35
|
|
|
29
36
|
public get Grid(): DIVEGrid {
|
|
30
|
-
return this.
|
|
37
|
+
return this._grid;
|
|
31
38
|
}
|
|
32
39
|
|
|
33
40
|
constructor() {
|
|
@@ -35,14 +42,30 @@ export class DIVEScene extends Scene {
|
|
|
35
42
|
|
|
36
43
|
this.background = new Color(0xffffff);
|
|
37
44
|
|
|
38
|
-
this.
|
|
39
|
-
this.add(this.
|
|
45
|
+
this._root = new DIVERoot();
|
|
46
|
+
this.add(this._root);
|
|
47
|
+
|
|
48
|
+
this._floor = new DIVEFloor();
|
|
49
|
+
this.add(this._floor);
|
|
50
|
+
|
|
51
|
+
this._grid = new DIVEGrid();
|
|
52
|
+
this.add(this._grid);
|
|
40
53
|
|
|
41
|
-
this.
|
|
42
|
-
this.
|
|
54
|
+
this._xrRoot = new DIVEXRRoot(this);
|
|
55
|
+
this._xrRoot.visible = false;
|
|
56
|
+
this.add(this._xrRoot);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public InitXR(renderer: DIVERenderer): void {
|
|
60
|
+
this._root.visible = false;
|
|
61
|
+
this._xrRoot.visible = true;
|
|
62
|
+
this._xrRoot.InitLightEstimation(renderer);
|
|
63
|
+
}
|
|
43
64
|
|
|
44
|
-
|
|
45
|
-
this.
|
|
65
|
+
public DisposeXR(): void {
|
|
66
|
+
this._root.visible = true;
|
|
67
|
+
this._xrRoot.visible = false;
|
|
68
|
+
this._xrRoot.DisposeLightEstimation();
|
|
46
69
|
}
|
|
47
70
|
|
|
48
71
|
public SetBackground(color: ColorRepresentation): void {
|