@shopware-ag/dive 1.4.2 → 1.6.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/README.md +38 -24
- package/build/dive.cjs +734 -492
- package/build/dive.cjs.map +1 -1
- package/build/dive.d.cts +182 -113
- package/build/dive.d.ts +182 -113
- package/build/dive.js +733 -478
- package/build/dive.js.map +1 -1
- package/package.json +1 -1
- package/src/__test__/DIVE.test.ts +66 -22
- package/src/animation/AnimationSystem.ts +16 -0
- package/src/animation/__test__/AnimationSystem.test.ts +23 -2
- package/src/axiscamera/AxisCamera.ts +40 -2
- package/src/axiscamera/__test__/AxisCamera.test.ts +178 -5
- package/src/com/Communication.ts +59 -16
- package/src/com/__test__/Communication.test.ts +83 -24
- package/src/com/actions/camera/computeencompassingview.ts +9 -0
- package/src/com/actions/index.ts +4 -0
- package/src/com/actions/scene/updatescene.ts +1 -0
- package/src/com/actions/toolbox/transform/setgizmovisible.ts +4 -0
- package/src/controls/OrbitControls.ts +14 -2
- package/src/controls/__test__/OrbitControls.test.ts +31 -4
- package/src/dive.ts +93 -33
- package/src/grid/Grid.ts +4 -0
- package/src/grid/__test__/Grid.test.ts +7 -0
- package/src/interface/Selectable.ts +17 -0
- package/src/interface/__test__/Interfaces.test.ts +18 -0
- package/src/mediacreator/MediaCreator.ts +2 -2
- package/src/mediacreator/__test__/MediaCreator.test.ts +12 -10
- package/src/model/Model.ts +6 -0
- package/src/model/__test__/Model.test.ts +9 -0
- package/src/renderer/Renderer.ts +7 -1
- package/src/renderer/__test__/Renderer.test.ts +14 -5
- package/src/scene/Scene.ts +8 -2
- package/src/scene/__test__/Scene.test.ts +6 -0
- package/src/scene/root/Root.ts +11 -1
- package/src/scene/root/__test__/Root.test.ts +68 -2
- package/src/scene/root/modelroot/ModelRoot.ts +1 -1
- package/src/scene/root/modelroot/__test__/ModelRoot.test.ts +1 -0
- package/src/toolbox/BaseTool.ts +3 -3
- package/src/toolbox/Toolbox.ts +57 -37
- package/src/toolbox/__test__/BaseTool.test.ts +49 -7
- package/src/toolbox/__test__/Toolbox.test.ts +43 -40
- package/src/toolbox/select/SelectTool.ts +18 -28
- package/src/toolbox/select/__test__/SelectTool.test.ts +27 -8
- package/src/toolbox/transform/TransformTool.ts +16 -1
- package/src/toolbox/transform/__test__/TransformTool.test.ts +34 -5
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
import DIVECommunication from '../Communication';
|
|
2
|
-
import DIVEScene from '../../scene/Scene';
|
|
3
|
-
import DIVEToolbox from '../../toolbox/Toolbox';
|
|
4
|
-
import DIVEMediaCreator from '../../mediacreator/MediaCreator';
|
|
5
2
|
import '..';
|
|
6
3
|
import '../types';
|
|
7
4
|
import '../actions';
|
|
@@ -23,10 +20,15 @@ import '../actions/scene/getallscenedata';
|
|
|
23
20
|
import '../actions/scene/setbackground';
|
|
24
21
|
import '../actions/scene/updatescene';
|
|
25
22
|
import '../actions/toolbox/select/setgizmomode';
|
|
23
|
+
import '../actions/toolbox/transform/setgizmovisible';
|
|
26
24
|
import '../actions/camera/getcameratransform';
|
|
27
|
-
import
|
|
28
|
-
import
|
|
29
|
-
import
|
|
25
|
+
import type DIVEScene from '../../scene/Scene';
|
|
26
|
+
import type DIVEToolbox from '../../toolbox/Toolbox';
|
|
27
|
+
import type DIVEOrbitControls from '../../controls/OrbitControls';
|
|
28
|
+
import { type DIVERenderer } from '../../renderer/Renderer';
|
|
29
|
+
import { type COMLight, type COMModel, type COMPov } from '../types';
|
|
30
|
+
import { type Object3D } from 'three';
|
|
31
|
+
import { DIVESelectTool, isSelectTool } from '../../toolbox/select/SelectTool';
|
|
30
32
|
|
|
31
33
|
jest.mock('three/src/math/MathUtils', () => {
|
|
32
34
|
return {
|
|
@@ -34,6 +36,33 @@ jest.mock('three/src/math/MathUtils', () => {
|
|
|
34
36
|
}
|
|
35
37
|
});
|
|
36
38
|
|
|
39
|
+
jest.mock('../../mediacreator/MediaCreator', () => {
|
|
40
|
+
return {
|
|
41
|
+
default: jest.fn(function () {
|
|
42
|
+
this.GenerateMedia = jest.fn();
|
|
43
|
+
|
|
44
|
+
return this;
|
|
45
|
+
}),
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
jest.mock('../../toolbox/select/SelectTool', () => {
|
|
50
|
+
return {
|
|
51
|
+
isSelectTool: jest.fn().mockReturnValue(true),
|
|
52
|
+
DIVESelectTool: jest.fn().mockImplementation(() => {
|
|
53
|
+
return {
|
|
54
|
+
AttachGizmo: jest.fn(),
|
|
55
|
+
DetachGizmo: jest.fn(),
|
|
56
|
+
};
|
|
57
|
+
}),
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const mockRenderer = {
|
|
62
|
+
render: jest.fn(),
|
|
63
|
+
OnResize: jest.fn(),
|
|
64
|
+
} as unknown as DIVERenderer;
|
|
65
|
+
|
|
37
66
|
const mockScene = {
|
|
38
67
|
SetBackground: jest.fn(),
|
|
39
68
|
AddSceneObject: jest.fn(),
|
|
@@ -55,8 +84,12 @@ const mockScene = {
|
|
|
55
84
|
},
|
|
56
85
|
SetVisibility: jest.fn(),
|
|
57
86
|
SetColor: jest.fn(),
|
|
58
|
-
}
|
|
87
|
+
},
|
|
88
|
+
Grid: {
|
|
89
|
+
SetVisibility: jest.fn(),
|
|
90
|
+
},
|
|
59
91
|
},
|
|
92
|
+
ComputeSceneBB: jest.fn(),
|
|
60
93
|
} as unknown as DIVEScene;
|
|
61
94
|
|
|
62
95
|
const mockController = {
|
|
@@ -107,32 +140,44 @@ const mockController = {
|
|
|
107
140
|
clone: jest.fn().mockReturnValue({ x: 1, y: 2, z: 3 }),
|
|
108
141
|
copy: jest.fn(),
|
|
109
142
|
},
|
|
143
|
+
quaternion: {
|
|
144
|
+
x: 1,
|
|
145
|
+
y: 2,
|
|
146
|
+
z: 3,
|
|
147
|
+
w: 4,
|
|
148
|
+
clone: jest.fn().mockReturnValue({ x: 1, y: 2, z: 3, w: 4 }),
|
|
149
|
+
copy: jest.fn(),
|
|
150
|
+
},
|
|
110
151
|
SetCameraLayer: jest.fn(),
|
|
152
|
+
OnResize: jest.fn(),
|
|
153
|
+
layers: {
|
|
154
|
+
mask: 1,
|
|
155
|
+
},
|
|
111
156
|
},
|
|
112
157
|
MoveTo: jest.fn(),
|
|
113
158
|
RevertLast: jest.fn(),
|
|
159
|
+
ComputeEncompassingView: jest.fn().mockReturnValue({
|
|
160
|
+
position: { x: 1, y: 2, z: 3 },
|
|
161
|
+
target: { x: 4, y: 5, z: 6 }
|
|
162
|
+
}),
|
|
114
163
|
} as unknown as DIVEOrbitControls;
|
|
115
164
|
|
|
116
|
-
const mockAttach = jest.fn();
|
|
117
|
-
const mockDetach = jest.fn();
|
|
118
165
|
const mockToolBox = {
|
|
119
166
|
UseTool: jest.fn(),
|
|
120
167
|
GetActiveTool: jest.fn().mockReturnValue({
|
|
121
|
-
AttachGizmo:
|
|
122
|
-
DetachGizmo:
|
|
168
|
+
AttachGizmo: jest.fn(),
|
|
169
|
+
DetachGizmo: jest.fn(),
|
|
123
170
|
}),
|
|
124
171
|
SetGizmoMode: jest.fn(),
|
|
172
|
+
SetGizmoVisibility: jest.fn(),
|
|
125
173
|
} as unknown as DIVEToolbox;
|
|
126
174
|
|
|
127
|
-
const mockMediaCreator = {
|
|
128
|
-
GenerateMedia: jest.fn(),
|
|
129
|
-
} as unknown as DIVEMediaCreator;
|
|
130
175
|
let testCom: DIVECommunication;
|
|
131
176
|
|
|
132
177
|
|
|
133
178
|
describe('dive/communication/DIVECommunication', () => {
|
|
134
179
|
beforeEach(() => {
|
|
135
|
-
testCom = new DIVECommunication(mockScene, mockController, mockToolBox
|
|
180
|
+
testCom = new DIVECommunication(mockRenderer, mockScene, mockController, mockToolBox);
|
|
136
181
|
});
|
|
137
182
|
|
|
138
183
|
afterEach(() => {
|
|
@@ -191,13 +236,6 @@ describe('dive/communication/DIVECommunication', () => {
|
|
|
191
236
|
expect(() => testCom.PerformAction('ADD_OBJECT', payload)).not.toThrow();
|
|
192
237
|
});
|
|
193
238
|
|
|
194
|
-
// it('should not dispatch with invalid action type', () => {
|
|
195
|
-
// const listener = jest.fn();
|
|
196
|
-
// testCom.Subscribe('GET_ALL_OBJECTS', listener);
|
|
197
|
-
// testCom.dispatch('INVALID_ACTION_TYPE', {});
|
|
198
|
-
// expect(listener).toHaveBeenCalledTimes(0);
|
|
199
|
-
// });
|
|
200
|
-
|
|
201
239
|
it('should perform action ADD_OBJECT', () => {
|
|
202
240
|
const payload = {
|
|
203
241
|
entityType: "light",
|
|
@@ -432,6 +470,19 @@ describe('dive/communication/DIVECommunication', () => {
|
|
|
432
470
|
expect(successSet).toBe(true);
|
|
433
471
|
});
|
|
434
472
|
|
|
473
|
+
it('should perform action COMPUTE_ENCOMPASSING_VIEW', () => {
|
|
474
|
+
const payload = {};
|
|
475
|
+
const transform = testCom.PerformAction('COMPUTE_ENCOMPASSING_VIEW', payload);
|
|
476
|
+
expect(transform).toStrictEqual({
|
|
477
|
+
position: { x: 1, y: 2, z: 3 },
|
|
478
|
+
target: { x: 4, y: 5, z: 6 }
|
|
479
|
+
});
|
|
480
|
+
expect(payload).toStrictEqual({
|
|
481
|
+
position: { x: 1, y: 2, z: 3 },
|
|
482
|
+
target: { x: 4, y: 5, z: 6 }
|
|
483
|
+
});
|
|
484
|
+
});
|
|
485
|
+
|
|
435
486
|
it('should perform action GET_ALL_SCENE_DATA', () => {
|
|
436
487
|
testCom.PerformAction('ADD_OBJECT', {
|
|
437
488
|
entityType: "pov",
|
|
@@ -542,7 +593,6 @@ describe('dive/communication/DIVECommunication', () => {
|
|
|
542
593
|
jest.spyOn(mockScene, 'GetSceneObject').mockReturnValueOnce({ isSelectable: true } as unknown as Object3D);
|
|
543
594
|
const success3 = testCom.PerformAction('SELECT_OBJECT', { id: 'test0' });
|
|
544
595
|
expect(success3).toBe(true);
|
|
545
|
-
expect(mockAttach).toHaveBeenCalledTimes(1);
|
|
546
596
|
});
|
|
547
597
|
|
|
548
598
|
it('should perform action DESELECT_OBJECT', () => {
|
|
@@ -568,7 +618,6 @@ describe('dive/communication/DIVECommunication', () => {
|
|
|
568
618
|
jest.spyOn(mockScene, 'GetSceneObject').mockReturnValueOnce({ isSelectable: true } as unknown as Object3D);
|
|
569
619
|
const success3 = testCom.PerformAction('DESELECT_OBJECT', { id: 'test0' });
|
|
570
620
|
expect(success3).toBe(true);
|
|
571
|
-
expect(mockDetach).toHaveBeenCalledTimes(1);
|
|
572
621
|
});
|
|
573
622
|
|
|
574
623
|
it('should perform action SET_CAMERA_TRANSFORM', () => {
|
|
@@ -614,6 +663,14 @@ describe('dive/communication/DIVECommunication', () => {
|
|
|
614
663
|
expect(success).toBe(true);
|
|
615
664
|
});
|
|
616
665
|
|
|
666
|
+
it('should perform action SET_GIZMO_VISIBILITY', () => {
|
|
667
|
+
let visibility = testCom.PerformAction('SET_GIZMO_VISIBILITY', true);
|
|
668
|
+
expect(visibility).toBe(true);
|
|
669
|
+
|
|
670
|
+
visibility = testCom.PerformAction('SET_GIZMO_VISIBILITY', false);
|
|
671
|
+
expect(visibility).toBe(false);
|
|
672
|
+
});
|
|
673
|
+
|
|
617
674
|
it('should perform action MODEL_LOADED', () => {
|
|
618
675
|
const payload = {
|
|
619
676
|
entityType: "model",
|
|
@@ -637,6 +694,7 @@ describe('dive/communication/DIVECommunication', () => {
|
|
|
637
694
|
backgroundColor: 'ffffff',
|
|
638
695
|
floorEnabled: true,
|
|
639
696
|
floorColor: 'ffffff',
|
|
697
|
+
gridEnabled: true,
|
|
640
698
|
});
|
|
641
699
|
expect(success0).toBe(true);
|
|
642
700
|
|
|
@@ -645,6 +703,7 @@ describe('dive/communication/DIVECommunication', () => {
|
|
|
645
703
|
backgroundColor: undefined,
|
|
646
704
|
floorEnabled: undefined,
|
|
647
705
|
floorColor: undefined,
|
|
706
|
+
gridEnabled: undefined,
|
|
648
707
|
});
|
|
649
708
|
expect(success1).toBe(true);
|
|
650
709
|
});
|
package/src/com/actions/index.ts
CHANGED
|
@@ -19,6 +19,8 @@ import SELECT_OBJECT from "./object/selectobject.ts";
|
|
|
19
19
|
import DESELECT_OBJECT from "./object/deselectobject.ts";
|
|
20
20
|
import GET_CAMERA_TRANSFORM from "./camera/getcameratransform.ts";
|
|
21
21
|
import DROP_IT from "./object/model/dropit.ts";
|
|
22
|
+
import SET_GIZMO_VISIBILITY from "./toolbox/transform/setgizmovisible.js";
|
|
23
|
+
import COMPUTE_ENCOMPASSING_VIEW from "./camera/computeencompassingview.ts";
|
|
22
24
|
|
|
23
25
|
export type Actions = {
|
|
24
26
|
GET_ALL_SCENE_DATA: GET_ALL_SCENE_DATA,
|
|
@@ -36,9 +38,11 @@ export type Actions = {
|
|
|
36
38
|
GET_CAMERA_TRANSFORM: GET_CAMERA_TRANSFORM,
|
|
37
39
|
MOVE_CAMERA: MOVE_CAMERA,
|
|
38
40
|
RESET_CAMERA: RESET_CAMERA,
|
|
41
|
+
COMPUTE_ENCOMPASSING_VIEW: COMPUTE_ENCOMPASSING_VIEW,
|
|
39
42
|
SET_CAMERA_LAYER: SET_CAMERA_LAYER,
|
|
40
43
|
ZOOM_CAMERA: ZOOM_CAMERA,
|
|
41
44
|
SET_GIZMO_MODE: SET_GIZMO_MODE,
|
|
45
|
+
SET_GIZMO_VISIBILITY: SET_GIZMO_VISIBILITY,
|
|
42
46
|
MODEL_LOADED: MODEL_LOADED,
|
|
43
47
|
UPDATE_SCENE: UPDATE_SCENE,
|
|
44
48
|
GENERATE_MEDIA: GENERATE_MEDIA,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { OrbitControls } from "three/examples/jsm/Addons.js";
|
|
2
2
|
import DIVEPerspectiveCamera from "../camera/PerspectiveCamera.ts";
|
|
3
|
-
import DIVERenderer from "../renderer/Renderer.ts";
|
|
4
|
-
import { MathUtils, Vector3Like } from "three";
|
|
3
|
+
import { DIVERenderer } from "../renderer/Renderer.ts";
|
|
4
|
+
import { type Box3, MathUtils, Vector3, Vector3Like } from "three";
|
|
5
5
|
import { Easing, Tween } from "@tweenjs/tween.js";
|
|
6
6
|
|
|
7
7
|
export type DIVEOrbitControlsSettings = {
|
|
@@ -49,6 +49,18 @@ export default class DIVEOrbitControls extends OrbitControls {
|
|
|
49
49
|
this.dampingFactor = settings.dampingFactor;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
public ComputeEncompassingView(bb: Box3): { position: Vector3Like, target: Vector3Like } {
|
|
53
|
+
const center = bb.getCenter(new Vector3());
|
|
54
|
+
const size = bb.getSize(new Vector3());
|
|
55
|
+
const distance = Math.max(size.x, size.y, size.z) * 1.25;
|
|
56
|
+
const direction = this.object.position.clone().normalize();
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
position: direction.multiplyScalar(distance),
|
|
60
|
+
target: center,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
52
64
|
public ZoomIn(by?: number): void {
|
|
53
65
|
const zoomBy = by || DIVEOrbitControls.DEFAULT_ZOOM_FACTOR;
|
|
54
66
|
const { minDistance, maxDistance } = this;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import DIVEOrbitControls from '../OrbitControls';
|
|
2
|
-
import DIVEPerspectiveCamera from '../../camera/PerspectiveCamera';
|
|
3
|
-
import
|
|
2
|
+
import type DIVEPerspectiveCamera from '../../camera/PerspectiveCamera';
|
|
3
|
+
import { DIVERenderer } from '../../renderer/Renderer';
|
|
4
|
+
import { Box3 } from 'three';
|
|
4
5
|
|
|
5
6
|
jest.mock('three/examples/jsm/Addons.js', () => {
|
|
6
7
|
return {
|
|
@@ -88,11 +89,32 @@ const moveToDuration = 1000;
|
|
|
88
89
|
|
|
89
90
|
const mockCamera = {
|
|
90
91
|
position: {
|
|
91
|
-
clone: jest.fn()
|
|
92
|
+
clone: jest.fn(() => {
|
|
93
|
+
return mockCamera.position;
|
|
94
|
+
}),
|
|
95
|
+
normalize: jest.fn(() => {
|
|
96
|
+
return mockCamera.position;
|
|
97
|
+
}),
|
|
98
|
+
multiplyScalar: jest.fn(() => {
|
|
99
|
+
return mockCamera.position;
|
|
100
|
+
}),
|
|
92
101
|
},
|
|
93
102
|
lookAt: jest.fn(),
|
|
94
103
|
} as unknown as DIVEPerspectiveCamera;
|
|
95
|
-
const mockRenderer
|
|
104
|
+
const mockRenderer = {
|
|
105
|
+
render: jest.fn(),
|
|
106
|
+
OnResize: jest.fn(),
|
|
107
|
+
getViewport: jest.fn(),
|
|
108
|
+
setViewport: jest.fn(),
|
|
109
|
+
AddPreRenderCallback: jest.fn((callback) => {
|
|
110
|
+
callback();
|
|
111
|
+
}),
|
|
112
|
+
AddPostRenderCallback: jest.fn((callback) => {
|
|
113
|
+
callback();
|
|
114
|
+
}),
|
|
115
|
+
RemovePreRenderCallback: jest.fn(),
|
|
116
|
+
RemovePostRenderCallback: jest.fn(),
|
|
117
|
+
} as unknown as DIVERenderer;
|
|
96
118
|
|
|
97
119
|
describe('dive/controls/DIVEOrbitControls', () => {
|
|
98
120
|
afterEach(() => {
|
|
@@ -104,6 +126,11 @@ describe('dive/controls/DIVEOrbitControls', () => {
|
|
|
104
126
|
expect(controller).toBeDefined();
|
|
105
127
|
});
|
|
106
128
|
|
|
129
|
+
it('should compute encompassing view', () => {
|
|
130
|
+
const controller = new DIVEOrbitControls(mockCamera, mockRenderer);
|
|
131
|
+
expect(() => controller.ComputeEncompassingView(new Box3())).not.toThrow();
|
|
132
|
+
});
|
|
133
|
+
|
|
107
134
|
it('should zoom in with default value', () => {
|
|
108
135
|
const controller = new DIVEOrbitControls(mockCamera, mockRenderer);
|
|
109
136
|
expect(() => controller.ZoomIn()).not.toThrow();
|
package/src/dive.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import DIVERenderer, { DIVERendererDefaultSettings, DIVERendererSettings } from "./renderer/Renderer.ts";
|
|
1
|
+
import { DIVERenderer, DIVERendererDefaultSettings, DIVERendererSettings } from "./renderer/Renderer.ts";
|
|
3
2
|
import DIVEScene from "./scene/Scene.ts";
|
|
4
3
|
import DIVEPerspectiveCamera, { DIVEPerspectiveCameraDefaultSettings, DIVEPerspectiveCameraSettings } from "./camera/PerspectiveCamera.ts";
|
|
5
4
|
import DIVEOrbitControls, { DIVEOrbitControlsDefaultSettings, DIVEOrbitControlsSettings } from "./controls/OrbitControls.ts";
|
|
6
|
-
import DIVEMediaCreator from "./mediacreator/MediaCreator.ts";
|
|
7
5
|
import DIVEToolbox from "./toolbox/Toolbox.ts";
|
|
8
6
|
import DIVECommunication from "./com/Communication.ts";
|
|
9
7
|
import DIVEAnimationSystem from "./animation/AnimationSystem.ts";
|
|
@@ -13,9 +11,11 @@ import { getObjectDelta } from "./helper/getObjectDelta/getObjectDelta.ts";
|
|
|
13
11
|
import type { Actions } from './com/actions/index.ts';
|
|
14
12
|
import type { COMPov, COMLight, COMModel, COMEntity } from './com/types.ts';
|
|
15
13
|
import { DIVEMath } from './math/index.ts';
|
|
14
|
+
import { generateUUID } from "three/src/math/MathUtils";
|
|
16
15
|
|
|
17
16
|
export type DIVESettings = {
|
|
18
17
|
autoResize: boolean;
|
|
18
|
+
displayAxes: boolean;
|
|
19
19
|
renderer: DIVERendererSettings;
|
|
20
20
|
perspectiveCamera: DIVEPerspectiveCameraSettings;
|
|
21
21
|
orbitControls: DIVEOrbitControlsSettings;
|
|
@@ -23,6 +23,7 @@ export type DIVESettings = {
|
|
|
23
23
|
|
|
24
24
|
export const DIVEDefaultSettings: DIVESettings = {
|
|
25
25
|
autoResize: true,
|
|
26
|
+
displayAxes: false,
|
|
26
27
|
renderer: DIVERendererDefaultSettings,
|
|
27
28
|
perspectiveCamera: DIVEPerspectiveCameraDefaultSettings,
|
|
28
29
|
orbitControls: DIVEOrbitControlsDefaultSettings,
|
|
@@ -52,6 +53,71 @@ export const DIVEDefaultSettings: DIVESettings = {
|
|
|
52
53
|
*/
|
|
53
54
|
|
|
54
55
|
export default class DIVE {
|
|
56
|
+
// static members
|
|
57
|
+
public static QuickView(uri: string): DIVE {
|
|
58
|
+
const dive = new DIVE();
|
|
59
|
+
|
|
60
|
+
dive.Communication.PerformAction('SET_CAMERA_TRANSFORM', {
|
|
61
|
+
position: { x: 0, y: 2, z: 2 },
|
|
62
|
+
target: { x: 0, y: 0.5, z: 0 },
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// generate scene light id
|
|
66
|
+
const lightid = generateUUID();
|
|
67
|
+
|
|
68
|
+
// add scene light
|
|
69
|
+
dive.Communication.PerformAction('ADD_OBJECT', {
|
|
70
|
+
entityType: 'light',
|
|
71
|
+
type: 'scene',
|
|
72
|
+
name: 'light',
|
|
73
|
+
id: lightid,
|
|
74
|
+
enabled: true,
|
|
75
|
+
visible: true,
|
|
76
|
+
intensity: 1,
|
|
77
|
+
color: 0xffffff,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// generate model id
|
|
81
|
+
const modelid = generateUUID();
|
|
82
|
+
|
|
83
|
+
// add loaded listener
|
|
84
|
+
dive.Communication.Subscribe('MODEL_LOADED', (data) => {
|
|
85
|
+
if (data.id !== modelid) return;
|
|
86
|
+
dive.Communication.PerformAction('PLACE_ON_FLOOR', {
|
|
87
|
+
id: modelid,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const transform = dive.Communication.PerformAction('COMPUTE_ENCOMPASSING_VIEW', {});
|
|
91
|
+
|
|
92
|
+
dive.Communication.PerformAction('SET_CAMERA_TRANSFORM', {
|
|
93
|
+
position: transform.position,
|
|
94
|
+
target: transform.target,
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// instantiate model
|
|
99
|
+
dive.Communication.PerformAction('ADD_OBJECT', {
|
|
100
|
+
entityType: 'model',
|
|
101
|
+
name: 'object',
|
|
102
|
+
id: modelid,
|
|
103
|
+
position: { x: 0, y: 0, z: 0 },
|
|
104
|
+
rotation: { x: 0, y: 0, z: 0 },
|
|
105
|
+
scale: { x: 1, y: 1, z: 1 },
|
|
106
|
+
uri: uri,
|
|
107
|
+
visible: true,
|
|
108
|
+
loaded: false,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// set scene properties
|
|
112
|
+
dive.Communication.PerformAction('UPDATE_SCENE', {
|
|
113
|
+
backgroundColor: 0xffffff,
|
|
114
|
+
gridEnabled: false,
|
|
115
|
+
floorColor: 0xffffff,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
return dive;
|
|
119
|
+
}
|
|
120
|
+
|
|
55
121
|
// descriptive members
|
|
56
122
|
private _settings: DIVESettings;
|
|
57
123
|
private _resizeObserverId: string;
|
|
@@ -63,13 +129,12 @@ export default class DIVE {
|
|
|
63
129
|
private scene: DIVEScene;
|
|
64
130
|
private perspectiveCamera: DIVEPerspectiveCamera;
|
|
65
131
|
private orbitControls: DIVEOrbitControls;
|
|
66
|
-
private mediaCreator: DIVEMediaCreator;
|
|
67
132
|
private toolbox: DIVEToolbox;
|
|
68
133
|
private communication: DIVECommunication;
|
|
69
134
|
|
|
70
135
|
// additional components
|
|
71
|
-
private animationSystem: DIVEAnimationSystem;
|
|
72
|
-
private axisCamera: DIVEAxisCamera;
|
|
136
|
+
private animationSystem: DIVEAnimationSystem | null;
|
|
137
|
+
private axisCamera: DIVEAxisCamera | null;
|
|
73
138
|
|
|
74
139
|
// getters
|
|
75
140
|
public get Communication(): DIVECommunication {
|
|
@@ -108,6 +173,13 @@ export default class DIVE {
|
|
|
108
173
|
}
|
|
109
174
|
}
|
|
110
175
|
|
|
176
|
+
if (settingsDelta.displayAxes) {
|
|
177
|
+
this.axisCamera = new DIVEAxisCamera(this.renderer, this.scene, this.orbitControls);
|
|
178
|
+
} else {
|
|
179
|
+
this.axisCamera?.Dispose();
|
|
180
|
+
this.axisCamera = null;
|
|
181
|
+
}
|
|
182
|
+
|
|
111
183
|
Object.assign(this._settings, settings);
|
|
112
184
|
}
|
|
113
185
|
|
|
@@ -123,38 +195,18 @@ export default class DIVE {
|
|
|
123
195
|
this.scene = new DIVEScene();
|
|
124
196
|
this.perspectiveCamera = new DIVEPerspectiveCamera(this._settings.perspectiveCamera);
|
|
125
197
|
this.orbitControls = new DIVEOrbitControls(this.perspectiveCamera, this.renderer, this._settings.orbitControls);
|
|
126
|
-
this.mediaCreator = new DIVEMediaCreator(this.renderer, this.scene, this.orbitControls);
|
|
127
198
|
this.toolbox = new DIVEToolbox(this.scene, this.orbitControls);
|
|
128
|
-
this.communication = new DIVECommunication(this.
|
|
199
|
+
this.communication = new DIVECommunication(this.renderer, this.scene, this.orbitControls, this.toolbox);
|
|
129
200
|
|
|
130
201
|
// initialize animation system
|
|
131
|
-
this.animationSystem =
|
|
132
|
-
this.renderer.AddPreRenderCallback(() => {
|
|
133
|
-
this.animationSystem.update();
|
|
134
|
-
})
|
|
202
|
+
this.animationSystem = null;
|
|
135
203
|
|
|
136
204
|
// initialize axis camera
|
|
137
|
-
this.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const restoreBackground = this.scene.background;
|
|
143
|
-
this.scene.background = null;
|
|
144
|
-
|
|
145
|
-
this.renderer.getViewport(restoreViewport);
|
|
146
|
-
this.renderer.setViewport(0, 0, 150, 150);
|
|
147
|
-
this.renderer.autoClear = false;
|
|
148
|
-
|
|
149
|
-
this.axisCamera.SetFromCameraMatrix(this.perspectiveCamera.matrix);
|
|
150
|
-
|
|
151
|
-
this.renderer.render(this.scene, this.axisCamera);
|
|
152
|
-
|
|
153
|
-
this.renderer.setViewport(restoreViewport);
|
|
154
|
-
this.renderer.autoClear = true;
|
|
155
|
-
|
|
156
|
-
this.scene.background = restoreBackground;
|
|
157
|
-
});
|
|
205
|
+
if (this._settings.displayAxes) {
|
|
206
|
+
this.axisCamera = new DIVEAxisCamera(this.renderer, this.scene, this.orbitControls);
|
|
207
|
+
} else {
|
|
208
|
+
this.axisCamera = null;
|
|
209
|
+
}
|
|
158
210
|
|
|
159
211
|
// add resize observer if autoResize is enabled
|
|
160
212
|
if (this._settings.autoResize) {
|
|
@@ -172,6 +224,14 @@ export default class DIVE {
|
|
|
172
224
|
}
|
|
173
225
|
}
|
|
174
226
|
|
|
227
|
+
public Dispose(): void {
|
|
228
|
+
this.removeResizeObserver();
|
|
229
|
+
this.renderer.Dispose();
|
|
230
|
+
this.axisCamera?.Dispose();
|
|
231
|
+
this.toolbox.Dispose();
|
|
232
|
+
this.communication.DestroyInstance();
|
|
233
|
+
}
|
|
234
|
+
|
|
175
235
|
// methods
|
|
176
236
|
public OnResize(width: number, height: number): void {
|
|
177
237
|
// resize renderer
|
package/src/grid/Grid.ts
CHANGED
|
@@ -16,4 +16,11 @@ describe('dive/grid/DIVEGrid', () => {
|
|
|
16
16
|
expect((grid.children[0] as GridHelper).material.depthTest).toBe(false);
|
|
17
17
|
expect((grid.children[0] as GridHelper).layers.mask).toBe(HELPER_LAYER_MASK);
|
|
18
18
|
});
|
|
19
|
+
|
|
20
|
+
it('should set visibility', () => {
|
|
21
|
+
grid.SetVisibility(false);
|
|
22
|
+
expect(grid.visible).toBe(false);
|
|
23
|
+
grid.SetVisibility(true);
|
|
24
|
+
expect(grid.visible).toBe(true);
|
|
25
|
+
});
|
|
19
26
|
});
|
|
@@ -14,4 +14,21 @@ export interface DIVESelectable {
|
|
|
14
14
|
|
|
15
15
|
export function isSelectable(object: Object3D): object is Object3D & DIVESelectable {
|
|
16
16
|
return 'isSelectable' in object;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function findSelectableInterface(child: Object3D): (Object3D & DIVESelectable) | undefined {
|
|
20
|
+
if (child === undefined) return undefined;
|
|
21
|
+
|
|
22
|
+
if (child.parent === null) {
|
|
23
|
+
// in this case it is the scene itself
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (isSelectable(child)) {
|
|
28
|
+
// in this case it is the Selectable
|
|
29
|
+
return child;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// search recursively in parent
|
|
33
|
+
return findSelectableInterface(child.parent);
|
|
17
34
|
}
|
|
@@ -21,6 +21,24 @@ describe('interfaces', () => {
|
|
|
21
21
|
expect(Selectable_DEF.isSelectable(Selectable as unknown as Object3D)).toBe(true);
|
|
22
22
|
});
|
|
23
23
|
|
|
24
|
+
it('should find Selectable', () => {
|
|
25
|
+
let Selectable = {
|
|
26
|
+
isSelectable: true,
|
|
27
|
+
} as unknown as Object3D & Selectable_DEF.DIVESelectable;
|
|
28
|
+
expect(Selectable_DEF.findSelectableInterface(Selectable as unknown as Object3D)).toBe(Selectable);
|
|
29
|
+
|
|
30
|
+
let parent = {
|
|
31
|
+
isSelectable: true,
|
|
32
|
+
}
|
|
33
|
+
Selectable = {
|
|
34
|
+
parent: parent,
|
|
35
|
+
} as unknown as Object3D & Selectable_DEF.DIVESelectable;
|
|
36
|
+
expect(Selectable_DEF.findSelectableInterface(Selectable as unknown as Object3D)).toBe(parent);
|
|
37
|
+
|
|
38
|
+
Selectable = { isSelectable: true, parent: null } as unknown as Object3D & Selectable_DEF.DIVESelectable;
|
|
39
|
+
expect(Selectable_DEF.findSelectableInterface(Selectable as unknown as Object3D)).toBe(undefined);
|
|
40
|
+
});
|
|
41
|
+
|
|
24
42
|
it('should identify Draggable', () => {
|
|
25
43
|
const Draggable = { isDraggable: true };
|
|
26
44
|
expect(Draggable_DEF.isDraggable(Draggable as unknown as Object3D)).toBe(true);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import DIVEPerspectiveCamera from "../camera/PerspectiveCamera.ts";
|
|
2
2
|
import DIVEScene from "../scene/Scene.ts";
|
|
3
|
-
import DIVERenderer from "../renderer/Renderer.ts";
|
|
3
|
+
import { DIVERenderer } from "../renderer/Renderer.ts";
|
|
4
4
|
import DIVEOrbitControls from "../controls/OrbitControls.ts";
|
|
5
5
|
import { Vector3Like } from "three";
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@ import { Vector3Like } from "three";
|
|
|
10
10
|
* @module
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
export
|
|
13
|
+
export class DIVEMediaCreator {
|
|
14
14
|
private renderer: DIVERenderer;
|
|
15
15
|
private scene: DIVEScene;
|
|
16
16
|
private controller: DIVEOrbitControls;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import DIVEMediaCreator from '../MediaCreator';
|
|
2
|
-
import DIVERenderer from '../../renderer/Renderer';
|
|
1
|
+
import { DIVEMediaCreator } from '../MediaCreator';
|
|
2
|
+
import { DIVERenderer } from '../../renderer/Renderer';
|
|
3
3
|
import DIVEScene from '../../scene/Scene';
|
|
4
4
|
import DIVEPerspectiveCamera, { DIVEPerspectiveCameraDefaultSettings } from '../../camera/PerspectiveCamera';
|
|
5
5
|
import { COMPov } from '../../com';
|
|
@@ -71,14 +71,16 @@ jest.mock('../../controls/OrbitControls', () => {
|
|
|
71
71
|
});
|
|
72
72
|
|
|
73
73
|
jest.mock('../../renderer/Renderer', () => {
|
|
74
|
-
return
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
74
|
+
return {
|
|
75
|
+
DIVERenderer: jest.fn(function () {
|
|
76
|
+
this.domElement = {
|
|
77
|
+
toDataURL: mock_toDataURL,
|
|
78
|
+
}
|
|
79
|
+
this.render = mock_render;
|
|
80
|
+
this.OnResize = jest.fn();
|
|
81
|
+
return this;
|
|
82
|
+
})
|
|
83
|
+
}
|
|
82
84
|
});
|
|
83
85
|
|
|
84
86
|
let mediaCreator: DIVEMediaCreator;
|
package/src/model/Model.ts
CHANGED
|
@@ -57,6 +57,12 @@ export default class DIVEModel extends Object3D implements DIVESelectable, DIVEM
|
|
|
57
57
|
this.scale.set(scale.x, scale.y, scale.z);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
public SetVisibility(visible: boolean): void {
|
|
61
|
+
this.traverse((child) => {
|
|
62
|
+
child.visible = visible;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
60
66
|
public SetToWorldOrigin(): void {
|
|
61
67
|
this.position.set(0, 0, 0);
|
|
62
68
|
DIVECommunication.get(this.userData.id)?.PerformAction('UPDATE_OBJECT', { id: this.userData.id, position: this.position, rotation: this.rotation, scale: this.scale });
|