@shopware-ag/dive 1.16.0 → 1.16.2
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/README.md +271 -40
- package/build/dive.cjs +575 -159
- package/build/dive.cjs.map +1 -1
- package/build/dive.d.cts +83 -57
- package/build/dive.d.ts +83 -57
- package/build/dive.js +614 -164
- package/build/dive.js.map +1 -1
- package/package.json +72 -60
- package/src/__test__/DIVE.test.ts +35 -31
- package/src/animation/AnimationSystem.ts +4 -4
- package/src/animation/__test__/AnimationSystem.test.ts +3 -3
- package/src/axiscamera/AxisCamera.ts +31 -11
- package/src/axiscamera/__test__/AxisCamera.test.ts +18 -10
- package/src/camera/PerspectiveCamera.ts +28 -13
- package/src/camera/__test__/PerspectiveCamera.test.ts +2 -2
- package/src/com/Communication.ts +282 -100
- package/src/com/__test__/Communication.test.ts +207 -141
- package/src/com/actions/camera/computeencompassingview.ts +8 -7
- package/src/com/actions/camera/getcameratransform.ts +8 -7
- package/src/com/actions/camera/movecamera.ts +16 -13
- package/src/com/actions/camera/resetcamera.ts +4 -3
- package/src/com/actions/camera/setcameralayer.ts +4 -3
- package/src/com/actions/camera/setcameratransform.ts +8 -7
- package/src/com/actions/camera/zoomcamera.ts +4 -3
- package/src/com/actions/index.ts +54 -54
- package/src/com/actions/media/generatemedia.ts +17 -13
- package/src/com/actions/object/addobject.ts +5 -4
- package/src/com/actions/object/deleteobject.ts +5 -4
- package/src/com/actions/object/deselectobject.ts +5 -4
- package/src/com/actions/object/getallobjects.ts +5 -4
- package/src/com/actions/object/getobjects.ts +5 -4
- package/src/com/actions/object/model/dropit.ts +4 -3
- package/src/com/actions/object/model/modelloaded.ts +4 -3
- package/src/com/actions/object/model/placeonfloor.ts +4 -3
- package/src/com/actions/object/selectobject.ts +5 -4
- package/src/com/actions/object/setparent.ts +8 -7
- package/src/com/actions/object/updateobject.ts +5 -4
- package/src/com/actions/scene/exportscene.ts +5 -4
- package/src/com/actions/scene/getallscenedata.ts +24 -18
- package/src/com/actions/scene/setbackground.ts +4 -3
- package/src/com/actions/scene/updatescene.ts +10 -9
- package/src/com/actions/toolbox/select/setgizmomode.ts +4 -3
- package/src/com/actions/toolbox/transform/setgizmovisible.ts +4 -3
- package/src/com/actions/toolbox/usetool.ts +5 -4
- package/src/com/types/COMBaseEntity.ts +2 -2
- package/src/com/types/COMEntity.ts +6 -6
- package/src/com/types/COMEntityType.ts +1 -1
- package/src/com/types/COMGeometry.ts +2 -2
- package/src/com/types/COMGroup.ts +3 -3
- package/src/com/types/COMLight.ts +3 -3
- package/src/com/types/COMMaterial.ts +2 -2
- package/src/com/types/COMModel.ts +4 -4
- package/src/com/types/COMPov.ts +3 -3
- package/src/com/types/COMPrimitive.ts +5 -5
- package/src/com/types/index.ts +10 -10
- package/src/constant/AxisHelperColors.ts +1 -1
- package/src/constant/GridColors.ts +1 -1
- package/src/controls/OrbitControls.ts +62 -29
- package/src/controls/__test__/OrbitControls.test.ts +133 -39
- package/src/dive.ts +82 -36
- package/src/gizmo/Gizmo.ts +21 -13
- package/src/gizmo/handles/AxisHandle.ts +40 -17
- package/src/gizmo/handles/RadialHandle.ts +39 -15
- package/src/gizmo/handles/ScaleHandle.ts +62 -25
- package/src/gizmo/plane/GizmoPlane.ts +5 -6
- package/src/gizmo/rotate/RotateGizmo.ts +58 -16
- package/src/gizmo/scale/ScaleGizmo.ts +37 -15
- package/src/gizmo/translate/TranslateGizmo.ts +34 -14
- package/src/grid/Grid.ts +13 -5
- package/src/grid/__test__/Grid.test.ts +5 -3
- package/src/group/Group.ts +9 -7
- package/src/group/__test__/Group.test.ts +8 -6
- package/src/helper/applyMixins/__test__/applyMixins.test.ts +9 -6
- package/src/helper/applyMixins/applyMixins.ts +6 -3
- package/src/helper/findInterface/__test__/findInterface.test.ts +28 -18
- package/src/helper/findInterface/findInterface.ts +7 -4
- package/src/helper/findSceneRecursive/__test__/findSceneRecursive.test.ts +1 -1
- package/src/helper/findSceneRecursive/findSceneRecursive.ts +1 -1
- package/src/helper/getObjectDelta/__test__/getObjectDelta.test.ts +43 -7
- package/src/helper/getObjectDelta/getObjectDelta.ts +13 -9
- package/src/helper/isInterface/__test__/implementsInterface.test.ts +1 -1
- package/src/helper/isInterface/implementsInterface.ts +6 -3
- package/src/info/Info.ts +20 -16
- package/src/info/__test__/Info.test.ts +67 -36
- package/src/interface/Draggable.ts +2 -2
- package/src/interface/Hoverable.ts +2 -2
- package/src/interface/Movable.ts +1 -1
- package/src/interface/Rotatable.ts +1 -1
- package/src/interface/Scalable.ts +1 -1
- package/src/io/IO.ts +21 -43
- package/src/io/__test__/IO.test.ts +16 -62
- package/src/io/gltf/GLTFIO.ts +34 -31
- package/src/io/gltf/__test__/GLTFIO.test.ts +88 -78
- package/src/light/PointLight.ts +42 -9
- package/src/light/SceneLight.ts +5 -5
- package/src/light/__test__/AmbientLight.test.ts +5 -4
- package/src/light/__test__/PointLight.test.ts +14 -10
- package/src/light/__test__/SceneLight.test.ts +19 -13
- package/src/loadingmanager/LoadingManager.ts +11 -6
- package/src/loadingmanager/__test__/LoadingManager.test.ts +14 -9
- package/src/math/__test__/DIVEMath.test.ts +1 -1
- package/src/math/ceil/__test__/ceilExp.test.ts +1 -1
- package/src/math/ceil/ceilExp.ts +2 -2
- package/src/math/floor/__test__/floorExp.test.ts +1 -1
- package/src/math/floor/floorExp.ts +2 -2
- package/src/math/helper/__test__/shift.test.ts +1 -1
- package/src/math/helper/shift.ts +1 -1
- package/src/math/index.ts +7 -7
- package/src/math/round/__test__/roundExp.test.ts +1 -1
- package/src/math/round/roundExp.ts +6 -3
- package/src/math/signedAngleTo/__test__/signedAngleTo.test.ts +10 -4
- package/src/math/signedAngleTo/signedAngleTo.ts +11 -4
- package/src/math/toFixed/__test__/toFixedExp.test.ts +9 -9
- package/src/math/toFixed/toFixedExp.ts +6 -3
- package/src/math/truncate/__test__/truncateExp.test.ts +1 -1
- package/src/math/truncate/truncateExp.ts +6 -3
- package/src/mediacreator/MediaCreator.ts +20 -10
- package/src/mediacreator/__test__/MediaCreator.test.ts +27 -12
- package/src/model/Model.ts +35 -7
- package/src/model/__test__/Model.test.ts +71 -44
- package/src/node/Node.ts +34 -12
- package/src/node/__test__/Node.test.ts +17 -13
- package/src/primitive/Primitive.ts +78 -13
- package/src/primitive/__test__/Primitive.test.ts +49 -38
- package/src/primitive/floor/Floor.ts +14 -3
- package/src/primitive/floor/__test__/Floor.test.ts +10 -4
- package/src/renderer/Renderer.ts +46 -15
- package/src/renderer/__test__/Renderer.test.ts +74 -24
- package/src/scene/Scene.ts +9 -3
- package/src/scene/__test__/Scene.test.ts +2 -2
- package/src/scene/root/Root.ts +142 -75
- package/src/scene/root/__test__/Root.test.ts +439 -111
- package/src/toolbox/BaseTool.ts +69 -33
- package/src/toolbox/Toolbox.ts +37 -17
- package/src/toolbox/__test__/BaseTool.test.ts +324 -160
- package/src/toolbox/__test__/Toolbox.test.ts +31 -14
- package/src/toolbox/select/SelectTool.ts +24 -19
- package/src/toolbox/select/__test__/SelectTool.test.ts +95 -59
- package/src/toolbox/transform/TransformTool.ts +40 -17
- package/src/toolbox/transform/__test__/TransformTool.test.ts +22 -15
- package/src/types/SceneObjects.ts +8 -8
- package/src/types/SceneType.ts +3 -3
- package/src/types/index.ts +3 -6
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
* Find the difference between two objects.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export const getObjectDelta = <T extends object>(
|
|
6
|
-
|
|
5
|
+
export const getObjectDelta = <T extends object>(
|
|
6
|
+
a: T,
|
|
7
|
+
b: Partial<T>,
|
|
8
|
+
): Partial<T> => {
|
|
7
9
|
// if a and b have no entries we have no delta
|
|
8
10
|
if (Object.keys(a).length === 0 && Object.keys(b).length === 0) {
|
|
9
11
|
return {};
|
|
@@ -17,7 +19,6 @@ export const getObjectDelta = <T extends object>(a: T, b: Partial<T>): Partial<T
|
|
|
17
19
|
let delta = {};
|
|
18
20
|
|
|
19
21
|
Object.keys(b).forEach((key) => {
|
|
20
|
-
|
|
21
22
|
// if key is not in a we have a delta
|
|
22
23
|
if (!Object.keys(a).includes(key)) {
|
|
23
24
|
delta = { ...delta, [key]: b[key as keyof object] };
|
|
@@ -26,7 +27,6 @@ export const getObjectDelta = <T extends object>(a: T, b: Partial<T>): Partial<T
|
|
|
26
27
|
|
|
27
28
|
// assumption: b[key] is an array
|
|
28
29
|
if (Array.isArray(b[key as keyof object])) {
|
|
29
|
-
|
|
30
30
|
// if a[key] is not an array we have a delta
|
|
31
31
|
if (!Array.isArray(a[key as keyof object])) {
|
|
32
32
|
delta = { ...delta, [key]: b[key as keyof object] };
|
|
@@ -54,7 +54,10 @@ export const getObjectDelta = <T extends object>(a: T, b: Partial<T>): Partial<T
|
|
|
54
54
|
|
|
55
55
|
bArray.forEach((entry, index) => {
|
|
56
56
|
// getObjectDelta in array
|
|
57
|
-
const inArrayDelta = getObjectDelta(
|
|
57
|
+
const inArrayDelta = getObjectDelta(
|
|
58
|
+
aArray[index],
|
|
59
|
+
bArray[index],
|
|
60
|
+
);
|
|
58
61
|
|
|
59
62
|
// if inArrayDelta has more then 0 entries we have a delta
|
|
60
63
|
if (Object.keys(inArrayDelta).length) {
|
|
@@ -68,13 +71,11 @@ export const getObjectDelta = <T extends object>(a: T, b: Partial<T>): Partial<T
|
|
|
68
71
|
return;
|
|
69
72
|
}
|
|
70
73
|
|
|
71
|
-
|
|
72
74
|
return;
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
// assumption: b[key] is an object
|
|
76
78
|
if (typeof b[key as keyof object] === 'object') {
|
|
77
|
-
|
|
78
79
|
// if a[key] is not an object we have a delta
|
|
79
80
|
if (typeof a[key as keyof object] !== 'object') {
|
|
80
81
|
delta = { ...delta, [key]: b[key as keyof object] };
|
|
@@ -82,7 +83,10 @@ export const getObjectDelta = <T extends object>(a: T, b: Partial<T>): Partial<T
|
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
// recursive: find objectDelta in a and b
|
|
85
|
-
const objectDelta = getObjectDelta(
|
|
86
|
+
const objectDelta = getObjectDelta(
|
|
87
|
+
a[key as keyof object],
|
|
88
|
+
b[key as keyof object],
|
|
89
|
+
);
|
|
86
90
|
|
|
87
91
|
// if objectDelta has more than 0 entries we have a delta
|
|
88
92
|
if (Object.keys(objectDelta).length) {
|
|
@@ -98,4 +102,4 @@ export const getObjectDelta = <T extends object>(a: T, b: Partial<T>): Partial<T
|
|
|
98
102
|
});
|
|
99
103
|
|
|
100
104
|
return delta;
|
|
101
|
-
}
|
|
105
|
+
};
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import { type Object3D } from
|
|
1
|
+
import { type Object3D } from 'three';
|
|
2
2
|
|
|
3
|
-
export function implementsInterface<T>(
|
|
3
|
+
export function implementsInterface<T>(
|
|
4
|
+
object: Object3D | null | undefined,
|
|
5
|
+
discriminator: string,
|
|
6
|
+
): object is Object3D & T {
|
|
4
7
|
if (!object) return false;
|
|
5
8
|
return discriminator in object;
|
|
6
|
-
}
|
|
9
|
+
}
|
package/src/info/Info.ts
CHANGED
|
@@ -8,17 +8,17 @@ export class DIVEInfo {
|
|
|
8
8
|
public static GetSystem(): string {
|
|
9
9
|
const platform = navigator.platform;
|
|
10
10
|
if (/Android/.test(navigator.userAgent)) {
|
|
11
|
-
return
|
|
11
|
+
return 'Android';
|
|
12
12
|
} else if (/iPhone|iPad|iPod/.test(navigator.userAgent)) {
|
|
13
|
-
return
|
|
14
|
-
} else if (platform.startsWith(
|
|
15
|
-
return
|
|
16
|
-
} else if (platform.startsWith(
|
|
17
|
-
return
|
|
18
|
-
} else if (platform.startsWith(
|
|
19
|
-
return
|
|
13
|
+
return 'iOS';
|
|
14
|
+
} else if (platform.startsWith('Win')) {
|
|
15
|
+
return 'Windows';
|
|
16
|
+
} else if (platform.startsWith('Mac')) {
|
|
17
|
+
return 'MacOS';
|
|
18
|
+
} else if (platform.startsWith('Linux')) {
|
|
19
|
+
return 'Linux';
|
|
20
20
|
} else {
|
|
21
|
-
return
|
|
21
|
+
return 'Unknown';
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -36,7 +36,8 @@ export class DIVEInfo {
|
|
|
36
36
|
}
|
|
37
37
|
// Check if immersive-vr session mode is supported
|
|
38
38
|
try {
|
|
39
|
-
const supported =
|
|
39
|
+
const supported =
|
|
40
|
+
await navigator.xr.isSessionSupported('immersive-ar');
|
|
40
41
|
this._supportsWebXR = supported;
|
|
41
42
|
} catch (error) {
|
|
42
43
|
this._supportsWebXR = false;
|
|
@@ -48,8 +49,8 @@ export class DIVEInfo {
|
|
|
48
49
|
* @returns A boolean indicating whether the user's device supports AR Quick Look.
|
|
49
50
|
*/
|
|
50
51
|
public static GetSupportsARQuickLook(): boolean {
|
|
51
|
-
const a = document.createElement(
|
|
52
|
-
if (a.relList.supports(
|
|
52
|
+
const a = document.createElement('a');
|
|
53
|
+
if (a.relList.supports('ar')) {
|
|
53
54
|
return true;
|
|
54
55
|
}
|
|
55
56
|
|
|
@@ -57,7 +58,9 @@ export class DIVEInfo {
|
|
|
57
58
|
const userAgent = navigator.userAgent;
|
|
58
59
|
|
|
59
60
|
// Check if the device is running iOS
|
|
60
|
-
const isIOS =
|
|
61
|
+
const isIOS =
|
|
62
|
+
/iPad|iPhone|iPod/.test(userAgent) &&
|
|
63
|
+
!(window as unknown as Window & { MSStream?: string }).MSStream;
|
|
61
64
|
if (!isIOS) {
|
|
62
65
|
return false;
|
|
63
66
|
}
|
|
@@ -78,7 +81,8 @@ export class DIVEInfo {
|
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
// Check for supported browser
|
|
81
|
-
const isSupportedBrowser =
|
|
84
|
+
const isSupportedBrowser =
|
|
85
|
+
/^((?!chrome|android).)*safari|CriOS|FxiOS/i.test(userAgent);
|
|
82
86
|
if (isSupportedBrowser) {
|
|
83
87
|
return true;
|
|
84
88
|
}
|
|
@@ -91,7 +95,7 @@ export class DIVEInfo {
|
|
|
91
95
|
* @returns A boolean indicating whether the user's device is a mobile device.
|
|
92
96
|
*/
|
|
93
97
|
public static get isMobile(): boolean {
|
|
94
|
-
return this.GetSystem() ===
|
|
98
|
+
return this.GetSystem() === 'Android' || this.GetSystem() === 'iOS';
|
|
95
99
|
}
|
|
96
100
|
|
|
97
101
|
/**
|
|
@@ -111,4 +115,4 @@ export class DIVEInfo {
|
|
|
111
115
|
|
|
112
116
|
return await this.GetSupportsWebXR();
|
|
113
117
|
}
|
|
114
|
-
}
|
|
118
|
+
}
|
|
@@ -3,7 +3,7 @@ import { DIVEInfo } from '../Info';
|
|
|
3
3
|
const mockNavigator = (navigator: any) => {
|
|
4
4
|
Object.defineProperty(global, 'navigator', {
|
|
5
5
|
value: navigator,
|
|
6
|
-
writable: true
|
|
6
|
+
writable: true,
|
|
7
7
|
});
|
|
8
8
|
};
|
|
9
9
|
|
|
@@ -15,44 +15,46 @@ describe('dive/info/DIVEInfo', () => {
|
|
|
15
15
|
|
|
16
16
|
it('should get system: Windows', () => {
|
|
17
17
|
mockNavigator({
|
|
18
|
-
platform: 'Win64'
|
|
18
|
+
platform: 'Win64',
|
|
19
19
|
});
|
|
20
20
|
expect(DIVEInfo.GetSystem()).toBe('Windows');
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
it('should get system: MacOS', () => {
|
|
24
24
|
mockNavigator({
|
|
25
|
-
platform: 'MacIntel'
|
|
25
|
+
platform: 'MacIntel',
|
|
26
26
|
});
|
|
27
27
|
expect(DIVEInfo.GetSystem()).toBe('MacOS');
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
it('should get system: Linux', () => {
|
|
31
31
|
mockNavigator({
|
|
32
|
-
platform: 'Linux'
|
|
32
|
+
platform: 'Linux',
|
|
33
33
|
});
|
|
34
34
|
expect(DIVEInfo.GetSystem()).toBe('Linux');
|
|
35
35
|
});
|
|
36
36
|
|
|
37
37
|
it('should get system: Android', () => {
|
|
38
38
|
mockNavigator({
|
|
39
|
-
userAgent:
|
|
40
|
-
|
|
39
|
+
userAgent:
|
|
40
|
+
'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
|
|
41
|
+
platform: 'Linux',
|
|
41
42
|
});
|
|
42
43
|
expect(DIVEInfo.GetSystem()).toBe('Android');
|
|
43
44
|
});
|
|
44
45
|
|
|
45
46
|
it('should get system: iOS', () => {
|
|
46
47
|
mockNavigator({
|
|
47
|
-
userAgent:
|
|
48
|
-
|
|
48
|
+
userAgent:
|
|
49
|
+
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0_1 like Mac OS X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3',
|
|
50
|
+
platform: 'iPhone',
|
|
49
51
|
});
|
|
50
52
|
expect(DIVEInfo.GetSystem()).toBe('iOS');
|
|
51
53
|
});
|
|
52
54
|
|
|
53
55
|
it('should get system: Unknown', () => {
|
|
54
56
|
mockNavigator({
|
|
55
|
-
platform: 'Unknown'
|
|
57
|
+
platform: 'Unknown',
|
|
56
58
|
});
|
|
57
59
|
expect(DIVEInfo.GetSystem()).toBe('Unknown');
|
|
58
60
|
});
|
|
@@ -62,7 +64,7 @@ describe('dive/info/DIVEInfo', () => {
|
|
|
62
64
|
mockNavigator({
|
|
63
65
|
xr: {
|
|
64
66
|
isSessionSupported: jest.fn().mockResolvedValue(true),
|
|
65
|
-
}
|
|
67
|
+
},
|
|
66
68
|
});
|
|
67
69
|
const supports = await DIVEInfo.GetSupportsWebXR();
|
|
68
70
|
expect(supports).toBe(true);
|
|
@@ -71,7 +73,7 @@ describe('dive/info/DIVEInfo', () => {
|
|
|
71
73
|
it('should not support webXR (xr undefined)', async () => {
|
|
72
74
|
DIVEInfo['_supportsWebXR'] = null;
|
|
73
75
|
mockNavigator({
|
|
74
|
-
xr: undefined
|
|
76
|
+
xr: undefined,
|
|
75
77
|
});
|
|
76
78
|
const supports = await DIVEInfo.GetSupportsWebXR();
|
|
77
79
|
expect(supports).toBe(false);
|
|
@@ -82,7 +84,7 @@ describe('dive/info/DIVEInfo', () => {
|
|
|
82
84
|
mockNavigator({
|
|
83
85
|
xr: {
|
|
84
86
|
isSessionSupported: jest.fn().mockResolvedValue(false),
|
|
85
|
-
}
|
|
87
|
+
},
|
|
86
88
|
});
|
|
87
89
|
const supports = await DIVEInfo.GetSupportsWebXR();
|
|
88
90
|
expect(supports).toBe(false);
|
|
@@ -93,7 +95,7 @@ describe('dive/info/DIVEInfo', () => {
|
|
|
93
95
|
mockNavigator({
|
|
94
96
|
xr: {
|
|
95
97
|
isSessionSupported: jest.fn().mockRejectedValue('error'),
|
|
96
|
-
}
|
|
98
|
+
},
|
|
97
99
|
});
|
|
98
100
|
const supports = await DIVEInfo.GetSupportsWebXR();
|
|
99
101
|
expect(supports).toBe(false);
|
|
@@ -104,7 +106,7 @@ describe('dive/info/DIVEInfo', () => {
|
|
|
104
106
|
mockNavigator({
|
|
105
107
|
xr: {
|
|
106
108
|
isSessionSupported: jest.fn().mockRejectedValue('error'),
|
|
107
|
-
}
|
|
109
|
+
},
|
|
108
110
|
});
|
|
109
111
|
const supports = await DIVEInfo.GetSupportsWebXR();
|
|
110
112
|
expect(supports).toBe(true);
|
|
@@ -115,7 +117,7 @@ describe('dive/info/DIVEInfo', () => {
|
|
|
115
117
|
mockNavigator({
|
|
116
118
|
xr: {
|
|
117
119
|
isSessionSupported: jest.fn().mockRejectedValue('error'),
|
|
118
|
-
}
|
|
120
|
+
},
|
|
119
121
|
});
|
|
120
122
|
const supports = await DIVEInfo.GetSupportsWebXR();
|
|
121
123
|
expect(supports).toBe(false);
|
|
@@ -123,90 +125,119 @@ describe('dive/info/DIVEInfo', () => {
|
|
|
123
125
|
|
|
124
126
|
it('should support ARQuickLook with feature detection', () => {
|
|
125
127
|
mockNavigator({
|
|
126
|
-
userAgent:
|
|
128
|
+
userAgent:
|
|
129
|
+
'Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Mobile/15E148 Safari/604.',
|
|
127
130
|
});
|
|
128
|
-
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
131
|
+
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
132
|
+
relList: { supports: () => true },
|
|
133
|
+
} as unknown as HTMLAnchorElement);
|
|
129
134
|
const supports = DIVEInfo.GetSupportsARQuickLook();
|
|
130
135
|
expect(supports).toBe(true);
|
|
131
136
|
});
|
|
132
137
|
|
|
133
138
|
it('should support ARQuickLook (iPhone, iOS 15, Safari)', () => {
|
|
134
139
|
mockNavigator({
|
|
135
|
-
userAgent:
|
|
140
|
+
userAgent:
|
|
141
|
+
'Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Mobile/15E148 Safari/604.',
|
|
136
142
|
});
|
|
137
|
-
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
143
|
+
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
144
|
+
relList: { supports: () => false },
|
|
145
|
+
} as unknown as HTMLAnchorElement);
|
|
138
146
|
const supports = DIVEInfo.GetSupportsARQuickLook();
|
|
139
147
|
expect(supports).toBe(true);
|
|
140
148
|
});
|
|
141
149
|
|
|
142
150
|
it('should support ARQuickLook (iPhone, iOS 17, Google)', () => {
|
|
143
151
|
mockNavigator({
|
|
144
|
-
userAgent:
|
|
152
|
+
userAgent:
|
|
153
|
+
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) GSA/277.0.555192628 Mobile/15E148 Safari/604.',
|
|
145
154
|
});
|
|
146
|
-
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
155
|
+
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
156
|
+
relList: { supports: () => false },
|
|
157
|
+
} as unknown as HTMLAnchorElement);
|
|
147
158
|
const supports = DIVEInfo.GetSupportsARQuickLook();
|
|
148
159
|
expect(supports).toBe(true);
|
|
149
160
|
});
|
|
150
161
|
|
|
151
162
|
it('should support ARQuickLook (iPhone, iOS 17, Chrome)', () => {
|
|
152
163
|
mockNavigator({
|
|
153
|
-
userAgent:
|
|
164
|
+
userAgent:
|
|
165
|
+
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/126.0.6478.153 Mobile/15E148 Safari/604.',
|
|
154
166
|
});
|
|
155
|
-
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
167
|
+
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
168
|
+
relList: { supports: () => false },
|
|
169
|
+
} as unknown as HTMLAnchorElement);
|
|
156
170
|
const supports = DIVEInfo.GetSupportsARQuickLook();
|
|
157
171
|
expect(supports).toBe(true);
|
|
158
172
|
});
|
|
159
173
|
|
|
160
174
|
it('should support ARQuickLook (iPhone, iOS 17, Chrome)', () => {
|
|
161
175
|
mockNavigator({
|
|
162
|
-
userAgent:
|
|
176
|
+
userAgent:
|
|
177
|
+
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_1 like Mac OS X) AppleWebKit/605.1.11 (KHTML, like Gecko) Version/11.1 Mobile/11E148 CriOS/604.',
|
|
163
178
|
});
|
|
164
|
-
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
179
|
+
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
180
|
+
relList: { supports: () => false },
|
|
181
|
+
} as unknown as HTMLAnchorElement);
|
|
165
182
|
const supports = DIVEInfo.GetSupportsARQuickLook();
|
|
166
183
|
expect(supports).toBe(true);
|
|
167
184
|
});
|
|
168
185
|
|
|
169
186
|
it('should support ARQuickLook (iPhone, iOS 17, Firefox)', () => {
|
|
170
187
|
mockNavigator({
|
|
171
|
-
userAgent:
|
|
188
|
+
userAgent:
|
|
189
|
+
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_1 like Mac OS X) AppleWebKit/605.1.11 (KHTML, like Gecko) Version/11.1 Mobile/11E148 FxiOS/604.',
|
|
172
190
|
});
|
|
173
|
-
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
191
|
+
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
192
|
+
relList: { supports: () => false },
|
|
193
|
+
} as unknown as HTMLAnchorElement);
|
|
174
194
|
const supports = DIVEInfo.GetSupportsARQuickLook();
|
|
175
195
|
expect(supports).toBe(true);
|
|
176
196
|
});
|
|
177
197
|
|
|
178
198
|
it('should not support ARQuickLook (Android)', () => {
|
|
179
199
|
mockNavigator({
|
|
180
|
-
userAgent:
|
|
200
|
+
userAgent:
|
|
201
|
+
'Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Mobile Safari/537.3',
|
|
181
202
|
});
|
|
182
|
-
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
203
|
+
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
204
|
+
relList: { supports: () => false },
|
|
205
|
+
} as unknown as HTMLAnchorElement);
|
|
183
206
|
const supports = DIVEInfo.GetSupportsARQuickLook();
|
|
184
207
|
expect(supports).toBe(false);
|
|
185
208
|
});
|
|
186
209
|
|
|
187
210
|
it('should not support ARQuickLook (iPhone, no iOS version)', () => {
|
|
188
211
|
mockNavigator({
|
|
189
|
-
userAgent:
|
|
212
|
+
userAgent:
|
|
213
|
+
'Mozilla/5.0 (iPhone; CPU iPhone OS like Mac OS X) AppleWebKit/605.1.11 (KHTML, like Gecko) Version/11.1 Mobile/11E148 Safari/604.',
|
|
190
214
|
});
|
|
191
|
-
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
215
|
+
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
216
|
+
relList: { supports: () => false },
|
|
217
|
+
} as unknown as HTMLAnchorElement);
|
|
192
218
|
const supports = DIVEInfo.GetSupportsARQuickLook();
|
|
193
219
|
expect(supports).toBe(false);
|
|
194
220
|
});
|
|
195
221
|
|
|
196
222
|
it('should not support ARQuickLook (iPhone, iOS 17, no browser)', () => {
|
|
197
223
|
mockNavigator({
|
|
198
|
-
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_1 like Mac OS X)'
|
|
224
|
+
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_1 like Mac OS X)',
|
|
199
225
|
});
|
|
200
|
-
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
226
|
+
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
227
|
+
relList: { supports: () => false },
|
|
228
|
+
} as unknown as HTMLAnchorElement);
|
|
201
229
|
const supports = DIVEInfo.GetSupportsARQuickLook();
|
|
202
230
|
expect(supports).toBe(false);
|
|
203
231
|
});
|
|
204
232
|
|
|
205
233
|
it('should not support ARQuickLook (iPhone, iOS <12, Safari)', () => {
|
|
206
234
|
mockNavigator({
|
|
207
|
-
userAgent:
|
|
235
|
+
userAgent:
|
|
236
|
+
'Mozilla/5.0 (iPhone; CPU iPhone OS 11_1 like Mac OS X) AppleWebKit/605.1.11 (KHTML, like Gecko) Version/11.1 Mobile/11E148 Safari/604.',
|
|
208
237
|
});
|
|
209
|
-
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
238
|
+
jest.spyOn(document, 'createElement').mockReturnValue({
|
|
239
|
+
relList: { supports: () => false },
|
|
240
|
+
} as unknown as HTMLAnchorElement);
|
|
210
241
|
const supports = DIVEInfo.GetSupportsARQuickLook();
|
|
211
242
|
expect(supports).toBe(false);
|
|
212
243
|
});
|
|
@@ -264,4 +295,4 @@ describe('dive/info/DIVEInfo', () => {
|
|
|
264
295
|
jest.spyOn(DIVEInfo, 'GetSupportsWebXR').mockResolvedValue(false);
|
|
265
296
|
expect(await DIVEInfo.GetIsARCapable()).toBe(false);
|
|
266
297
|
});
|
|
267
|
-
});
|
|
298
|
+
});
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { type DraggableEvent } from
|
|
7
|
+
import { type DraggableEvent } from '../toolbox/BaseTool';
|
|
8
8
|
|
|
9
9
|
export interface DIVEDraggable {
|
|
10
10
|
isDraggable: true;
|
|
11
11
|
onDragStart?: (e: DraggableEvent) => void;
|
|
12
12
|
onDrag?: (e: DraggableEvent) => void;
|
|
13
13
|
onDragEnd?: (e: DraggableEvent) => void;
|
|
14
|
-
}
|
|
14
|
+
}
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { type Intersection } from
|
|
7
|
+
import { type Intersection } from 'three';
|
|
8
8
|
|
|
9
9
|
export interface DIVEHoverable {
|
|
10
10
|
isHoverable: true;
|
|
11
11
|
onPointerEnter?: (i: Intersection) => void;
|
|
12
12
|
onPointerOver?: (i: Intersection) => void;
|
|
13
13
|
onPointerLeave?: () => void;
|
|
14
|
-
}
|
|
14
|
+
}
|
package/src/interface/Movable.ts
CHANGED
package/src/io/IO.ts
CHANGED
|
@@ -1,107 +1,85 @@
|
|
|
1
|
-
import { DIVEGLTFIO } from
|
|
1
|
+
import { DIVEGLTFIO } from './gltf/GLTFIO';
|
|
2
2
|
|
|
3
|
-
import { type DIVESceneFileType } from
|
|
4
|
-
import { type DIVEScene } from
|
|
3
|
+
import { type DIVESceneFileType } from '../types';
|
|
4
|
+
import { type DIVEScene } from '../scene/Scene';
|
|
5
5
|
|
|
6
6
|
export class DIVEIO {
|
|
7
|
-
|
|
8
7
|
private _scene: DIVEScene;
|
|
9
8
|
|
|
10
9
|
private _gltfIO: DIVEGLTFIO;
|
|
11
10
|
|
|
12
11
|
constructor(scene: DIVEScene) {
|
|
13
|
-
|
|
14
12
|
this._scene = scene;
|
|
15
13
|
|
|
16
14
|
this._gltfIO = new DIVEGLTFIO();
|
|
17
|
-
|
|
18
15
|
}
|
|
19
16
|
|
|
20
|
-
public Import<FileType extends keyof DIVESceneFileType>(
|
|
21
|
-
|
|
17
|
+
public Import<FileType extends keyof DIVESceneFileType>(
|
|
18
|
+
type: FileType,
|
|
19
|
+
url: string,
|
|
20
|
+
): Promise<DIVESceneFileType[FileType] | null> {
|
|
22
21
|
return this._importFromURL(type, url)
|
|
23
22
|
|
|
24
23
|
.catch((error) => {
|
|
25
|
-
|
|
26
24
|
console.error(error);
|
|
27
25
|
|
|
28
26
|
return null;
|
|
29
|
-
|
|
30
27
|
});
|
|
31
|
-
|
|
32
28
|
}
|
|
33
29
|
|
|
34
|
-
public Export<FileType extends keyof DIVESceneFileType>(
|
|
35
|
-
|
|
30
|
+
public Export<FileType extends keyof DIVESceneFileType>(
|
|
31
|
+
type: FileType,
|
|
32
|
+
): Promise<string | null> {
|
|
36
33
|
return this._exportToURL(type)
|
|
37
34
|
|
|
38
35
|
.catch((error) => {
|
|
39
|
-
|
|
40
36
|
console.error(error);
|
|
41
37
|
|
|
42
38
|
return null;
|
|
43
|
-
|
|
44
39
|
});
|
|
45
|
-
|
|
46
40
|
}
|
|
47
41
|
|
|
48
|
-
private _importFromURL<FileType extends keyof DIVESceneFileType>(
|
|
49
|
-
|
|
42
|
+
private _importFromURL<FileType extends keyof DIVESceneFileType>(
|
|
43
|
+
type: FileType,
|
|
44
|
+
url: string,
|
|
45
|
+
): Promise<DIVESceneFileType[FileType]> {
|
|
50
46
|
switch (type) {
|
|
51
|
-
|
|
52
47
|
case 'glb': {
|
|
53
|
-
|
|
54
48
|
return this._gltfIO.Import(url);
|
|
55
|
-
|
|
56
49
|
}
|
|
57
50
|
|
|
58
51
|
default: {
|
|
59
|
-
|
|
60
52
|
return Promise.reject('Unsupported file type: ' + type);
|
|
61
|
-
|
|
62
53
|
}
|
|
63
|
-
|
|
64
54
|
}
|
|
65
55
|
}
|
|
66
56
|
|
|
67
|
-
private _exportToURL<FileType extends keyof DIVESceneFileType>(
|
|
68
|
-
|
|
57
|
+
private _exportToURL<FileType extends keyof DIVESceneFileType>(
|
|
58
|
+
type: FileType,
|
|
59
|
+
): Promise<string> {
|
|
69
60
|
switch (type) {
|
|
70
|
-
|
|
71
61
|
case 'glb': {
|
|
72
|
-
|
|
73
62
|
return new Promise((resolve, reject) => {
|
|
74
|
-
|
|
75
|
-
|
|
63
|
+
this._gltfIO
|
|
64
|
+
.Export(this._scene, true, true)
|
|
76
65
|
|
|
77
66
|
.then((data) => {
|
|
78
|
-
|
|
79
|
-
resolve(this._createBlobURL(data))
|
|
80
|
-
|
|
67
|
+
resolve(this._createBlobURL(data));
|
|
81
68
|
})
|
|
82
69
|
|
|
83
70
|
.catch((error) => {
|
|
84
|
-
|
|
85
71
|
reject(error);
|
|
86
|
-
|
|
87
72
|
});
|
|
88
73
|
});
|
|
89
|
-
|
|
90
74
|
}
|
|
91
75
|
|
|
92
76
|
default: {
|
|
93
|
-
|
|
94
77
|
return Promise.reject('Unsupported file type: ' + type);
|
|
95
|
-
|
|
96
78
|
}
|
|
97
|
-
|
|
98
79
|
}
|
|
99
80
|
}
|
|
100
81
|
|
|
101
82
|
private _createBlobURL(data: ArrayBuffer): string {
|
|
102
|
-
|
|
103
83
|
return URL.createObjectURL(new Blob([data]));
|
|
104
|
-
|
|
105
84
|
}
|
|
106
|
-
|
|
107
|
-
}
|
|
85
|
+
}
|