@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
|
@@ -25,13 +25,15 @@ jest.mock('three', () => {
|
|
|
25
25
|
far: 0,
|
|
26
26
|
fov: 0,
|
|
27
27
|
},
|
|
28
|
-
}
|
|
28
|
+
};
|
|
29
29
|
this.add = mockAdd;
|
|
30
|
-
this.children = [
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
this.children = [
|
|
31
|
+
{
|
|
32
|
+
material: {
|
|
33
|
+
color: {},
|
|
34
|
+
},
|
|
33
35
|
},
|
|
34
|
-
|
|
36
|
+
];
|
|
35
37
|
return this;
|
|
36
38
|
}),
|
|
37
39
|
SphereGeometry: jest.fn(function () {
|
|
@@ -58,7 +60,7 @@ jest.mock('three', () => {
|
|
|
58
60
|
this.userData = {};
|
|
59
61
|
return this;
|
|
60
62
|
}),
|
|
61
|
-
}
|
|
63
|
+
};
|
|
62
64
|
});
|
|
63
65
|
|
|
64
66
|
jest.mock('../../com/Communication.ts', () => {
|
|
@@ -67,10 +69,10 @@ jest.mock('../../com/Communication.ts', () => {
|
|
|
67
69
|
get: jest.fn(() => {
|
|
68
70
|
return {
|
|
69
71
|
PerformAction: jest.fn(),
|
|
70
|
-
}
|
|
72
|
+
};
|
|
71
73
|
}),
|
|
72
74
|
},
|
|
73
|
-
}
|
|
75
|
+
};
|
|
74
76
|
});
|
|
75
77
|
|
|
76
78
|
describe('dive/light/DIVEPointLight', () => {
|
|
@@ -93,7 +95,9 @@ describe('dive/light/DIVEPointLight', () => {
|
|
|
93
95
|
it('should set color', () => {
|
|
94
96
|
const testLight = new DIVEPointLight();
|
|
95
97
|
testLight.SetColor({ test: true } as unknown as Color);
|
|
96
|
-
expect((testLight.children[0] as PointLight).color).toEqual({
|
|
98
|
+
expect((testLight.children[0] as PointLight).color).toEqual({
|
|
99
|
+
test: true,
|
|
100
|
+
});
|
|
97
101
|
});
|
|
98
102
|
|
|
99
103
|
it('should set enabled', () => {
|
|
@@ -128,4 +132,4 @@ describe('dive/light/DIVEPointLight', () => {
|
|
|
128
132
|
jest.spyOn(DIVECommunication, 'get').mockReturnValueOnce(undefined);
|
|
129
133
|
expect(() => testLight.onDeselect()).not.toThrow();
|
|
130
134
|
});
|
|
131
|
-
});
|
|
135
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import DIVESceneLight from '../SceneLight';
|
|
2
2
|
import { DIVECommunication } from '../../com/Communication';
|
|
3
|
-
import { Color,
|
|
3
|
+
import { Color, Object3D } from 'three';
|
|
4
4
|
|
|
5
5
|
jest.mock('../../com/Communication.ts', () => {
|
|
6
6
|
return {
|
|
@@ -8,10 +8,10 @@ jest.mock('../../com/Communication.ts', () => {
|
|
|
8
8
|
get: jest.fn(() => {
|
|
9
9
|
return {
|
|
10
10
|
PerformAction: jest.fn(),
|
|
11
|
-
}
|
|
11
|
+
};
|
|
12
12
|
}),
|
|
13
13
|
},
|
|
14
|
-
}
|
|
14
|
+
};
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
const mockAdd = jest.fn();
|
|
@@ -36,13 +36,15 @@ jest.mock('three', () => {
|
|
|
36
36
|
far: 0,
|
|
37
37
|
fov: 0,
|
|
38
38
|
},
|
|
39
|
-
}
|
|
39
|
+
};
|
|
40
40
|
this.add = mockAdd;
|
|
41
|
-
this.children = [
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
this.children = [
|
|
42
|
+
{
|
|
43
|
+
material: {
|
|
44
|
+
color: {},
|
|
45
|
+
},
|
|
44
46
|
},
|
|
45
|
-
|
|
47
|
+
];
|
|
46
48
|
this.userData = {};
|
|
47
49
|
return this;
|
|
48
50
|
}),
|
|
@@ -94,14 +96,16 @@ jest.mock('three', () => {
|
|
|
94
96
|
far: 0,
|
|
95
97
|
fov: 0,
|
|
96
98
|
},
|
|
97
|
-
}
|
|
99
|
+
};
|
|
98
100
|
this.removeFromParent = mockAdd;
|
|
99
101
|
return this;
|
|
100
102
|
}),
|
|
101
|
-
}
|
|
103
|
+
};
|
|
102
104
|
});
|
|
103
105
|
|
|
104
|
-
jest.spyOn(DIVECommunication, 'get').mockReturnValue({
|
|
106
|
+
jest.spyOn(DIVECommunication, 'get').mockReturnValue({
|
|
107
|
+
PerformAction: jest.fn(),
|
|
108
|
+
} as unknown as DIVECommunication);
|
|
105
109
|
|
|
106
110
|
describe('dive/light/DIVESceneLight', () => {
|
|
107
111
|
it('should instantiate', () => {
|
|
@@ -118,7 +122,9 @@ describe('dive/light/DIVESceneLight', () => {
|
|
|
118
122
|
|
|
119
123
|
it('should set color', () => {
|
|
120
124
|
const testLight = new DIVESceneLight();
|
|
121
|
-
expect(() =>
|
|
125
|
+
expect(() =>
|
|
126
|
+
testLight.SetColor({ test: true } as unknown as Color),
|
|
127
|
+
).not.toThrow();
|
|
122
128
|
});
|
|
123
129
|
|
|
124
130
|
it('should set enabled', () => {
|
|
@@ -127,4 +133,4 @@ describe('dive/light/DIVESceneLight', () => {
|
|
|
127
133
|
expect(testLight.children[0].visible).toBe(false);
|
|
128
134
|
expect(testLight.children[1].visible).toBe(false);
|
|
129
135
|
});
|
|
130
|
-
});
|
|
136
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DRACOLoader, GLTF, GLTFLoader } from
|
|
1
|
+
import { DRACOLoader, GLTF, GLTFLoader } from 'three/examples/jsm/Addons.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* A basic loading manager.
|
|
@@ -14,7 +14,9 @@ export class DIVELoadingManager {
|
|
|
14
14
|
constructor() {
|
|
15
15
|
this.gltfloader = new GLTFLoader();
|
|
16
16
|
this.dracoloader = new DRACOLoader();
|
|
17
|
-
this.dracoloader.setDecoderPath(
|
|
17
|
+
this.dracoloader.setDecoderPath(
|
|
18
|
+
'https://www.gstatic.com/draco/v1/decoders/',
|
|
19
|
+
);
|
|
18
20
|
this.gltfloader.setDRACOLoader(this.dracoloader);
|
|
19
21
|
}
|
|
20
22
|
|
|
@@ -23,13 +25,16 @@ export class DIVELoadingManager {
|
|
|
23
25
|
public async LoadGLTF(uri: string): Promise<GLTF> {
|
|
24
26
|
const progEvent = (p: ProgressEvent<EventTarget>): void => {
|
|
25
27
|
this.progress.set(uri, p.loaded / p.total);
|
|
26
|
-
}
|
|
28
|
+
};
|
|
27
29
|
|
|
28
30
|
this.progress.set(uri, 0);
|
|
29
31
|
|
|
30
32
|
return new Promise<GLTF>((resolve, reject) => {
|
|
31
|
-
this.gltfloader
|
|
32
|
-
|
|
33
|
+
this.gltfloader
|
|
34
|
+
.loadAsync(uri, progEvent)
|
|
35
|
+
.then(resolve)
|
|
36
|
+
.catch(reject);
|
|
37
|
+
});
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
public PollProgress(): number {
|
|
@@ -41,4 +46,4 @@ export class DIVELoadingManager {
|
|
|
41
46
|
if (this.progress.size === 0) return 1;
|
|
42
47
|
return total / this.progress.size;
|
|
43
48
|
}
|
|
44
|
-
}
|
|
49
|
+
}
|
|
@@ -6,20 +6,26 @@ const mock_setDecoderPath = jest.fn();
|
|
|
6
6
|
jest.mock('three/examples/jsm/Addons.js', () => {
|
|
7
7
|
return {
|
|
8
8
|
GLTFLoader: jest.fn(function () {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
progEvent
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
this.loadAsync = (
|
|
10
|
+
uri: string,
|
|
11
|
+
progEvent: (p: ProgressEvent<EventTarget>) => void,
|
|
12
|
+
) =>
|
|
13
|
+
new Promise<void>((resolve) => {
|
|
14
|
+
progEvent({
|
|
15
|
+
loaded: 0,
|
|
16
|
+
total: 1,
|
|
17
|
+
} as ProgressEvent<EventTarget>);
|
|
18
|
+
resolve();
|
|
19
|
+
});
|
|
14
20
|
this.setDRACOLoader = mock_setDRACOLoader;
|
|
15
21
|
return this;
|
|
16
22
|
}),
|
|
17
23
|
DRACOLoader: jest.fn(() => {
|
|
18
24
|
return {
|
|
19
25
|
setDecoderPath: mock_setDecoderPath,
|
|
20
|
-
}
|
|
26
|
+
};
|
|
21
27
|
}),
|
|
22
|
-
}
|
|
28
|
+
};
|
|
23
29
|
});
|
|
24
30
|
|
|
25
31
|
describe('dive/loadingmanager/DIVELoadingManager', () => {
|
|
@@ -48,5 +54,4 @@ describe('dive/loadingmanager/DIVELoadingManager', () => {
|
|
|
48
54
|
const progress = testLight.PollProgress();
|
|
49
55
|
expect(progress).toBe(1);
|
|
50
56
|
});
|
|
51
|
-
|
|
52
|
-
});
|
|
57
|
+
});
|
package/src/math/ceil/ceilExp.ts
CHANGED
package/src/math/helper/shift.ts
CHANGED
package/src/math/index.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import ceilExp from
|
|
2
|
-
import floorExp from
|
|
3
|
-
import roundExp from
|
|
4
|
-
import signedAngleTo from
|
|
5
|
-
import toFixedExp from
|
|
6
|
-
import truncateExp from
|
|
1
|
+
import ceilExp from './ceil/ceilExp.ts';
|
|
2
|
+
import floorExp from './floor/floorExp.ts';
|
|
3
|
+
import roundExp from './round/roundExp.ts';
|
|
4
|
+
import signedAngleTo from './signedAngleTo/signedAngleTo.ts';
|
|
5
|
+
import toFixedExp from './toFixed/toFixedExp.ts';
|
|
6
|
+
import truncateExp from './truncate/truncateExp.ts';
|
|
7
7
|
|
|
8
8
|
export const DIVEMath: {
|
|
9
9
|
ceilExp: typeof ceilExp;
|
|
@@ -19,4 +19,4 @@ export const DIVEMath: {
|
|
|
19
19
|
toFixedExp,
|
|
20
20
|
truncateExp,
|
|
21
21
|
signedAngleTo,
|
|
22
|
-
}
|
|
22
|
+
};
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import shift from
|
|
1
|
+
import shift from '../helper/shift.ts';
|
|
2
2
|
|
|
3
|
-
export default function roundExponential(
|
|
3
|
+
export default function roundExponential(
|
|
4
|
+
number: number,
|
|
5
|
+
decimals: number = 0,
|
|
6
|
+
): number {
|
|
4
7
|
if (number < 0) return -roundExponential(-number, decimals);
|
|
5
8
|
const n = shift(number, +decimals);
|
|
6
9
|
return shift(Math.round(n), -decimals);
|
|
7
|
-
}
|
|
10
|
+
}
|
|
@@ -6,9 +6,15 @@ describe('dive/math/signedAngleTo', () => {
|
|
|
6
6
|
const planeNormal = new Vector3(0, 0, 1);
|
|
7
7
|
const a = new Vector3(1, 0, 0);
|
|
8
8
|
expect(signedAngleTo(a, new Vector3(1, 0, 0), planeNormal)).toBe(0);
|
|
9
|
-
expect(signedAngleTo(a, new Vector3(0, 1, 0), planeNormal)).toBe(
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
expect(signedAngleTo(a, new Vector3(0, 1, 0), planeNormal)).toBe(
|
|
10
|
+
Math.PI / 2,
|
|
11
|
+
);
|
|
12
|
+
expect(signedAngleTo(a, new Vector3(-1, 0, 0), planeNormal)).toBe(
|
|
13
|
+
Math.PI,
|
|
14
|
+
);
|
|
15
|
+
expect(signedAngleTo(a, new Vector3(0, -1, 0), planeNormal)).toBe(
|
|
16
|
+
-Math.PI / 2,
|
|
17
|
+
);
|
|
12
18
|
expect(signedAngleTo(a, planeNormal, planeNormal)).toBe(0);
|
|
13
19
|
});
|
|
14
|
-
});
|
|
20
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Vector3 } from
|
|
1
|
+
import { Vector3 } from 'three';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Calculate the signed angle between two vectors. Only works when the vectors are on the same plane.
|
|
@@ -8,6 +8,13 @@ import { Vector3 } from "three";
|
|
|
8
8
|
* @returns Signed angle in radians
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
export default function signedAngleTo(
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
export default function signedAngleTo(
|
|
12
|
+
vecA: Vector3,
|
|
13
|
+
vecB: Vector3,
|
|
14
|
+
planeNormal: Vector3,
|
|
15
|
+
): number {
|
|
16
|
+
return Math.atan2(
|
|
17
|
+
vecA.clone().cross(vecB).dot(planeNormal),
|
|
18
|
+
vecB.clone().dot(vecA),
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -2,13 +2,13 @@ import toFixedExp from '../toFixedExp';
|
|
|
2
2
|
|
|
3
3
|
describe('dive/math/toFixed/toFixedExp', () => {
|
|
4
4
|
it('should toFixedExp', () => {
|
|
5
|
-
expect(toFixedExp(-0.5)).toBe(
|
|
6
|
-
expect(toFixedExp(0.5)).toBe(
|
|
7
|
-
expect(toFixedExp(0.55)).toBe(
|
|
8
|
-
expect(toFixedExp(0.49)).toBe(
|
|
9
|
-
expect(toFixedExp(1.49)).toBe(
|
|
10
|
-
expect(toFixedExp(0.49, 2)).toBe(
|
|
11
|
-
expect(toFixedExp(1.49, 2)).toBe(
|
|
12
|
-
expect(toFixedExp(-1.49, 2)).toBe(
|
|
5
|
+
expect(toFixedExp(-0.5)).toBe('0');
|
|
6
|
+
expect(toFixedExp(0.5)).toBe('1');
|
|
7
|
+
expect(toFixedExp(0.55)).toBe('1');
|
|
8
|
+
expect(toFixedExp(0.49)).toBe('0');
|
|
9
|
+
expect(toFixedExp(1.49)).toBe('1');
|
|
10
|
+
expect(toFixedExp(0.49, 2)).toBe('0.49');
|
|
11
|
+
expect(toFixedExp(1.49, 2)).toBe('1.49');
|
|
12
|
+
expect(toFixedExp(-1.49, 2)).toBe('-1.49');
|
|
13
13
|
});
|
|
14
|
-
});
|
|
14
|
+
});
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import shift from
|
|
1
|
+
import shift from '../helper/shift.ts';
|
|
2
2
|
|
|
3
|
-
export default function toFixedExp(
|
|
3
|
+
export default function toFixedExp(
|
|
4
|
+
number: number,
|
|
5
|
+
decimals: number = 0,
|
|
6
|
+
): string {
|
|
4
7
|
const n = shift(number, +decimals);
|
|
5
8
|
return shift(Math.round(n), -decimals).toFixed(decimals);
|
|
6
|
-
}
|
|
9
|
+
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import shift from
|
|
1
|
+
import shift from '../helper/shift.ts';
|
|
2
2
|
|
|
3
|
-
export default function truncateExp(
|
|
3
|
+
export default function truncateExp(
|
|
4
|
+
number: number,
|
|
5
|
+
decimals: number = 0,
|
|
6
|
+
): number {
|
|
4
7
|
const n = shift(number, +decimals);
|
|
5
8
|
return shift(Math.trunc(n), -decimals);
|
|
6
|
-
}
|
|
9
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import DIVEPerspectiveCamera from
|
|
2
|
-
import { DIVEScene } from
|
|
3
|
-
import { DIVERenderer } from
|
|
4
|
-
import DIVEOrbitControls from
|
|
5
|
-
import { Vector3Like } from
|
|
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';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Creates renderings of the current scene
|
|
@@ -15,13 +15,22 @@ export class DIVEMediaCreator {
|
|
|
15
15
|
private scene: DIVEScene;
|
|
16
16
|
private controller: DIVEOrbitControls;
|
|
17
17
|
|
|
18
|
-
constructor(
|
|
18
|
+
constructor(
|
|
19
|
+
renderer: DIVERenderer,
|
|
20
|
+
scene: DIVEScene,
|
|
21
|
+
controller: DIVEOrbitControls,
|
|
22
|
+
) {
|
|
19
23
|
this.renderer = renderer;
|
|
20
24
|
this.scene = scene;
|
|
21
25
|
this.controller = controller;
|
|
22
26
|
}
|
|
23
27
|
|
|
24
|
-
public GenerateMedia(
|
|
28
|
+
public GenerateMedia(
|
|
29
|
+
position: Vector3Like,
|
|
30
|
+
target: Vector3Like,
|
|
31
|
+
width: number,
|
|
32
|
+
height: number,
|
|
33
|
+
): string {
|
|
25
34
|
const resetPosition = this.controller.object.position.clone();
|
|
26
35
|
const resetRotation = this.controller.object.quaternion.clone();
|
|
27
36
|
|
|
@@ -32,7 +41,6 @@ export class DIVEMediaCreator {
|
|
|
32
41
|
this.controller.target.copy(target);
|
|
33
42
|
this.controller.update();
|
|
34
43
|
|
|
35
|
-
|
|
36
44
|
const dataUri = this.DrawCanvas().toDataURL();
|
|
37
45
|
|
|
38
46
|
this.controller.object.position.copy(resetPosition);
|
|
@@ -49,9 +57,11 @@ export class DIVEMediaCreator {
|
|
|
49
57
|
}
|
|
50
58
|
|
|
51
59
|
// draw canvas
|
|
52
|
-
this.controller.object.layers.mask =
|
|
60
|
+
this.controller.object.layers.mask =
|
|
61
|
+
DIVEPerspectiveCamera.LIVE_VIEW_LAYER_MASK;
|
|
53
62
|
this.renderer.render(this.scene, this.controller.object);
|
|
54
|
-
this.controller.object.layers.mask =
|
|
63
|
+
this.controller.object.layers.mask =
|
|
64
|
+
DIVEPerspectiveCamera.EDITOR_VIEW_LAYER_MASK;
|
|
55
65
|
|
|
56
66
|
const returnCanvas = this.renderer.domElement;
|
|
57
67
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { DIVEMediaCreator } from '../MediaCreator';
|
|
2
2
|
import { DIVERenderer } from '../../renderer/Renderer';
|
|
3
3
|
import { DIVEScene } from '../../scene/Scene';
|
|
4
|
-
import DIVEPerspectiveCamera, {
|
|
4
|
+
import DIVEPerspectiveCamera, {
|
|
5
|
+
DIVEPerspectiveCameraDefaultSettings,
|
|
6
|
+
} from '../../camera/PerspectiveCamera';
|
|
5
7
|
import { type COMPov } from '../../com/types';
|
|
6
8
|
import DIVEOrbitControls from '../../controls/OrbitControls';
|
|
7
9
|
import { DIVEAnimationSystem } from '../../animation/AnimationSystem';
|
|
@@ -17,7 +19,7 @@ jest.mock('../../scene/Scene', () => {
|
|
|
17
19
|
return {
|
|
18
20
|
DIVEScene: jest.fn(() => {
|
|
19
21
|
return {};
|
|
20
|
-
})
|
|
22
|
+
}),
|
|
21
23
|
};
|
|
22
24
|
});
|
|
23
25
|
|
|
@@ -40,7 +42,7 @@ jest.mock('../../camera/PerspectiveCamera', () => {
|
|
|
40
42
|
};
|
|
41
43
|
this.layers = {
|
|
42
44
|
mask: 0,
|
|
43
|
-
}
|
|
45
|
+
};
|
|
44
46
|
return this;
|
|
45
47
|
});
|
|
46
48
|
});
|
|
@@ -78,12 +80,12 @@ jest.mock('../../renderer/Renderer', () => {
|
|
|
78
80
|
DIVERenderer: jest.fn(function () {
|
|
79
81
|
this.domElement = {
|
|
80
82
|
toDataURL: mock_toDataURL,
|
|
81
|
-
}
|
|
83
|
+
};
|
|
82
84
|
this.render = mock_render;
|
|
83
85
|
this.OnResize = jest.fn();
|
|
84
86
|
return this;
|
|
85
|
-
})
|
|
86
|
-
}
|
|
87
|
+
}),
|
|
88
|
+
};
|
|
87
89
|
});
|
|
88
90
|
|
|
89
91
|
jest.mock('../../animation/AnimationSystem', () => {
|
|
@@ -91,7 +93,7 @@ jest.mock('../../animation/AnimationSystem', () => {
|
|
|
91
93
|
DIVEAnimationSystem: jest.fn(function () {
|
|
92
94
|
this.domElement = {
|
|
93
95
|
toDataURL: mock_toDataURL,
|
|
94
|
-
}
|
|
96
|
+
};
|
|
95
97
|
this.render = mock_render;
|
|
96
98
|
this.OnResize = jest.fn();
|
|
97
99
|
this.AddPreRenderCallback = jest.fn((callback) => {
|
|
@@ -99,8 +101,8 @@ jest.mock('../../animation/AnimationSystem', () => {
|
|
|
99
101
|
return 'id';
|
|
100
102
|
});
|
|
101
103
|
return this;
|
|
102
|
-
})
|
|
103
|
-
}
|
|
104
|
+
}),
|
|
105
|
+
};
|
|
104
106
|
});
|
|
105
107
|
|
|
106
108
|
let mediaCreator: DIVEMediaCreator;
|
|
@@ -108,7 +110,15 @@ let mediaCreator: DIVEMediaCreator;
|
|
|
108
110
|
describe('dive/mediacreator/DIVEMediaCreator', () => {
|
|
109
111
|
beforeEach(() => {
|
|
110
112
|
jest.clearAllMocks();
|
|
111
|
-
mediaCreator = new DIVEMediaCreator(
|
|
113
|
+
mediaCreator = new DIVEMediaCreator(
|
|
114
|
+
new DIVERenderer(),
|
|
115
|
+
new DIVEScene(),
|
|
116
|
+
new DIVEOrbitControls(
|
|
117
|
+
new DIVEPerspectiveCamera(DIVEPerspectiveCameraDefaultSettings),
|
|
118
|
+
new DIVERenderer(),
|
|
119
|
+
new DIVEAnimationSystem(new DIVERenderer()),
|
|
120
|
+
),
|
|
121
|
+
);
|
|
112
122
|
});
|
|
113
123
|
|
|
114
124
|
it('should instantiate', () => {
|
|
@@ -118,10 +128,15 @@ describe('dive/mediacreator/DIVEMediaCreator', () => {
|
|
|
118
128
|
it('should generate media', () => {
|
|
119
129
|
const mock_POV = {
|
|
120
130
|
position: { x: 0, y: 0, z: 0 },
|
|
121
|
-
target: { x: 0, y: 0, z: 0 }
|
|
131
|
+
target: { x: 0, y: 0, z: 0 },
|
|
122
132
|
} as COMPov;
|
|
123
133
|
expect(() => {
|
|
124
|
-
mediaCreator.GenerateMedia(
|
|
134
|
+
mediaCreator.GenerateMedia(
|
|
135
|
+
mock_POV.position,
|
|
136
|
+
mock_POV.target,
|
|
137
|
+
800,
|
|
138
|
+
600,
|
|
139
|
+
);
|
|
125
140
|
}).not.toThrow();
|
|
126
141
|
expect(mock_render).toHaveBeenCalledTimes(1);
|
|
127
142
|
expect(mock_toDataURL).toHaveBeenCalledTimes(1);
|
package/src/model/Model.ts
CHANGED
|
@@ -40,7 +40,8 @@ export class DIVEModel extends DIVENode {
|
|
|
40
40
|
if (this._material) {
|
|
41
41
|
this._mesh.material = this._material;
|
|
42
42
|
} else {
|
|
43
|
-
this._material = (child as Mesh)
|
|
43
|
+
this._material = (child as Mesh)
|
|
44
|
+
.material as MeshStandardMaterial;
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
});
|
|
@@ -111,24 +112,40 @@ export class DIVEModel extends DIVENode {
|
|
|
111
112
|
|
|
112
113
|
public PlaceOnFloor(): void {
|
|
113
114
|
this.position.y = -this._boundingBox.min.y * this.scale.y;
|
|
114
|
-
DIVECommunication.get(this.userData.id)?.PerformAction(
|
|
115
|
+
DIVECommunication.get(this.userData.id)?.PerformAction(
|
|
116
|
+
'UPDATE_OBJECT',
|
|
117
|
+
{
|
|
118
|
+
id: this.userData.id,
|
|
119
|
+
position: this.position,
|
|
120
|
+
rotation: this.rotation,
|
|
121
|
+
scale: this.scale,
|
|
122
|
+
},
|
|
123
|
+
);
|
|
115
124
|
}
|
|
116
125
|
|
|
117
126
|
public DropIt(): void {
|
|
118
127
|
if (!this.parent) {
|
|
119
|
-
console.warn(
|
|
128
|
+
console.warn(
|
|
129
|
+
'DIVEModel: DropIt() called on a model that is not in the scene.',
|
|
130
|
+
this,
|
|
131
|
+
);
|
|
120
132
|
return;
|
|
121
133
|
}
|
|
122
134
|
|
|
123
135
|
// calculate the bottom center of the bounding box
|
|
124
136
|
const bottomY = this._boundingBox.min.y * this.scale.y;
|
|
125
|
-
const bbBottomCenter = this.localToWorld(
|
|
137
|
+
const bbBottomCenter = this.localToWorld(
|
|
138
|
+
this._boundingBox.getCenter(new Vector3()).multiply(this.scale),
|
|
139
|
+
);
|
|
126
140
|
bbBottomCenter.y = bottomY + this.position.y;
|
|
127
141
|
|
|
128
142
|
// set up raycaster and raycast all scene objects (product layer)
|
|
129
143
|
const raycaster = new Raycaster(bbBottomCenter, new Vector3(0, -1, 0));
|
|
130
144
|
raycaster.layers.mask = PRODUCT_LAYER_MASK;
|
|
131
|
-
const intersections = raycaster.intersectObjects(
|
|
145
|
+
const intersections = raycaster.intersectObjects(
|
|
146
|
+
findSceneRecursive(this).Root.children,
|
|
147
|
+
true,
|
|
148
|
+
);
|
|
132
149
|
|
|
133
150
|
// if we hit something, move the model to the top on the hit object's bounding box
|
|
134
151
|
if (intersections.length > 0) {
|
|
@@ -138,12 +155,23 @@ export class DIVEModel extends DIVENode {
|
|
|
138
155
|
const worldPos = mesh.localToWorld(meshBB.max.clone());
|
|
139
156
|
|
|
140
157
|
const oldPos = this.position.clone();
|
|
141
|
-
const newPos = this.position
|
|
158
|
+
const newPos = this.position
|
|
159
|
+
.clone()
|
|
160
|
+
.setY(worldPos.y)
|
|
161
|
+
.sub(new Vector3(0, bottomY, 0));
|
|
142
162
|
this.position.copy(newPos);
|
|
143
163
|
|
|
144
164
|
// if the position changed, update the object in communication
|
|
145
165
|
if (this.position.y === oldPos.y) return;
|
|
146
|
-
DIVECommunication.get(this.userData.id)?.PerformAction(
|
|
166
|
+
DIVECommunication.get(this.userData.id)?.PerformAction(
|
|
167
|
+
'UPDATE_OBJECT',
|
|
168
|
+
{
|
|
169
|
+
id: this.userData.id,
|
|
170
|
+
position: this.position,
|
|
171
|
+
rotation: this.rotation,
|
|
172
|
+
scale: this.scale,
|
|
173
|
+
},
|
|
174
|
+
);
|
|
147
175
|
}
|
|
148
176
|
}
|
|
149
177
|
}
|