@shopware-ag/dive 1.19.0 → 1.19.1-beta.1

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.
Files changed (197) hide show
  1. package/build/dive.cjs +388 -220
  2. package/build/dive.cjs.map +1 -1
  3. package/build/dive.js +395 -21946
  4. package/build/dive.js.map +1 -1
  5. package/build/dive.mjs +28206 -0
  6. package/build/dive.mjs.map +1 -0
  7. package/build/src/ar/AR.d.ts +37 -14
  8. package/build/src/ar/arquicklook/ARQuickLook.d.ts +5 -6
  9. package/build/src/ar/sceneviewer/SceneViewer.d.ts +42 -6
  10. package/build/src/com/actions/scene/launchar.d.ts +5 -2
  11. package/build/src/converter/Converter.d.ts +21 -0
  12. package/build/src/dive.d.ts +3 -2
  13. package/build/src/exporter/Exporter.d.ts +11 -0
  14. package/build/src/helper/applyMixins/applyMixins.d.ts +22 -6
  15. package/build/src/info/Info.d.ts +37 -13
  16. package/build/src/interface/Movable.d.ts +5 -5
  17. package/build/src/interface/Selectable.d.ts +4 -4
  18. package/build/src/loader/Loader.d.ts +11 -0
  19. package/build/src/model/Model.d.ts +2 -2
  20. package/build/src/node/Node.d.ts +3 -3
  21. package/build/src/scene/root/Root.d.ts +1 -1
  22. package/build/src/types/ExporterOptions.d.ts +15 -0
  23. package/build/src/types/FileTypes.d.ts +27 -0
  24. package/build/src/types/index.d.ts +4 -0
  25. package/build/src/types/info/index.d.ts +66 -0
  26. package/package.json +17 -3
  27. package/build/src/exporters/usdz/USDZExporter.d.ts +0 -15
  28. package/build/src/loadingmanager/LoadingManager.d.ts +0 -14
  29. package/src/__test__/DIVE.test.ts +0 -274
  30. package/src/animation/AnimationSystem.ts +0 -34
  31. package/src/animation/__test__/AnimationSystem.test.ts +0 -40
  32. package/src/ar/AR.ts +0 -98
  33. package/src/ar/__test__/AR.test.ts +0 -187
  34. package/src/ar/arquicklook/ARQuickLook.ts +0 -93
  35. package/src/ar/arquicklook/__test__/ARQuickLook.test.ts +0 -93
  36. package/src/ar/sceneviewer/SceneViewer.ts +0 -74
  37. package/src/ar/sceneviewer/__test__/SceneViewer.test.ts +0 -93
  38. package/src/ar/webxr/WebXR.ts +0 -176
  39. package/src/ar/webxr/controller/WebXRController.ts +0 -340
  40. package/src/ar/webxr/crosshair/WebXRCrosshair.ts +0 -35
  41. package/src/ar/webxr/origin/WebXROrigin.ts +0 -192
  42. package/src/ar/webxr/overlay/Overlay.ts +0 -50
  43. package/src/ar/webxr/raycaster/WebXRRaycaster.ts +0 -131
  44. package/src/ar/webxr/raycaster/ar/WebXRRaycasterAR.ts +0 -102
  45. package/src/ar/webxr/raycaster/three/WebXRRaycasterTHREE.ts +0 -49
  46. package/src/ar/webxr/touchscreencontrols/WebXRTouchscreenControls.ts +0 -356
  47. package/src/axiscamera/AxisCamera.ts +0 -108
  48. package/src/axiscamera/__test__/AxisCamera.test.ts +0 -150
  49. package/src/camera/PerspectiveCamera.ts +0 -63
  50. package/src/camera/__test__/PerspectiveCamera.test.ts +0 -36
  51. package/src/com/Communication.ts +0 -808
  52. package/src/com/__test__/Communication.test.ts +0 -1024
  53. package/src/com/actions/camera/computeencompassingview.ts +0 -10
  54. package/src/com/actions/camera/getcameratransform.ts +0 -10
  55. package/src/com/actions/camera/movecamera.ts +0 -18
  56. package/src/com/actions/camera/resetcamera.ts +0 -5
  57. package/src/com/actions/camera/setcameralayer.ts +0 -5
  58. package/src/com/actions/camera/setcameratransform.ts +0 -10
  59. package/src/com/actions/camera/zoomcamera.ts +0 -5
  60. package/src/com/actions/index.ts +0 -61
  61. package/src/com/actions/media/generatemedia.ts +0 -18
  62. package/src/com/actions/object/addobject.ts +0 -7
  63. package/src/com/actions/object/deleteobject.ts +0 -7
  64. package/src/com/actions/object/deselectobject.ts +0 -7
  65. package/src/com/actions/object/getallobjects.ts +0 -7
  66. package/src/com/actions/object/getobjects.ts +0 -7
  67. package/src/com/actions/object/model/dropit.ts +0 -5
  68. package/src/com/actions/object/model/modelloaded.ts +0 -5
  69. package/src/com/actions/object/model/placeonfloor.ts +0 -5
  70. package/src/com/actions/object/selectobject.ts +0 -7
  71. package/src/com/actions/object/setparent.ts +0 -10
  72. package/src/com/actions/object/updateobject.ts +0 -7
  73. package/src/com/actions/renderer/startrender.ts +0 -5
  74. package/src/com/actions/scene/exportscene.ts +0 -7
  75. package/src/com/actions/scene/getallscenedata.ts +0 -7
  76. package/src/com/actions/scene/launchar.ts +0 -7
  77. package/src/com/actions/scene/setbackground.ts +0 -5
  78. package/src/com/actions/scene/updatescene.ts +0 -11
  79. package/src/com/actions/toolbox/select/setgizmomode.ts +0 -5
  80. package/src/com/actions/toolbox/transform/setgizmoscalelinked.ts +0 -5
  81. package/src/com/actions/toolbox/transform/setgizmovisible.ts +0 -5
  82. package/src/com/actions/toolbox/usetool.ts +0 -7
  83. package/src/com/types/COMBaseEntity.ts +0 -9
  84. package/src/com/types/COMEntity.ts +0 -7
  85. package/src/com/types/COMEntityType.ts +0 -1
  86. package/src/com/types/COMGeometry.ts +0 -8
  87. package/src/com/types/COMGeometryType.ts +0 -9
  88. package/src/com/types/COMGroup.ts +0 -9
  89. package/src/com/types/COMLight.ts +0 -11
  90. package/src/com/types/COMMaterial.ts +0 -12
  91. package/src/com/types/COMModel.ts +0 -12
  92. package/src/com/types/COMPov.ts +0 -8
  93. package/src/com/types/COMPrimitive.ts +0 -12
  94. package/src/com/types/index.ts +0 -23
  95. package/src/constant/AxisHelperColors.ts +0 -7
  96. package/src/constant/GridColors.ts +0 -2
  97. package/src/constant/VisibilityLayerMask.ts +0 -5
  98. package/src/controls/OrbitControls.ts +0 -211
  99. package/src/controls/__test__/OrbitControls.test.ts +0 -256
  100. package/src/dive.ts +0 -363
  101. package/src/events/EventExecutor.ts +0 -35
  102. package/src/exporters/usdz/USDZExporter.ts +0 -21
  103. package/src/exporters/usdz/__test__/USDZExporter.test.ts +0 -57
  104. package/src/gizmo/Gizmo.ts +0 -144
  105. package/src/gizmo/handles/AxisHandle.ts +0 -153
  106. package/src/gizmo/handles/RadialHandle.ts +0 -149
  107. package/src/gizmo/handles/ScaleHandle.ts +0 -195
  108. package/src/gizmo/plane/GizmoPlane.ts +0 -84
  109. package/src/gizmo/rotate/RotateGizmo.ts +0 -143
  110. package/src/gizmo/scale/ScaleGizmo.ts +0 -125
  111. package/src/gizmo/translate/TranslateGizmo.ts +0 -114
  112. package/src/grid/Grid.ts +0 -34
  113. package/src/grid/__test__/Grid.test.ts +0 -28
  114. package/src/group/Group.ts +0 -184
  115. package/src/group/__test__/Group.test.ts +0 -212
  116. package/src/helper/applyMixins/__test__/applyMixins.test.ts +0 -30
  117. package/src/helper/applyMixins/applyMixins.ts +0 -18
  118. package/src/helper/findInterface/__test__/findInterface.test.ts +0 -63
  119. package/src/helper/findInterface/findInterface.ts +0 -13
  120. package/src/helper/findSceneRecursive/__test__/findSceneRecursive.test.ts +0 -40
  121. package/src/helper/findSceneRecursive/findSceneRecursive.ts +0 -16
  122. package/src/helper/getObjectDelta/__test__/getObjectDelta.test.ts +0 -186
  123. package/src/helper/getObjectDelta/getObjectDelta.ts +0 -105
  124. package/src/helper/isInterface/__test__/implementsInterface.test.ts +0 -19
  125. package/src/helper/isInterface/implementsInterface.ts +0 -9
  126. package/src/info/Info.ts +0 -154
  127. package/src/info/__test__/Info.test.ts +0 -338
  128. package/src/interface/Draggable.ts +0 -14
  129. package/src/interface/Hoverable.ts +0 -14
  130. package/src/interface/Movable.ts +0 -12
  131. package/src/interface/Rotatable.ts +0 -10
  132. package/src/interface/Scalable.ts +0 -10
  133. package/src/interface/Selectable.ts +0 -11
  134. package/src/io/IO.ts +0 -62
  135. package/src/io/__test__/IO.test.ts +0 -116
  136. package/src/io/gltf/GLTFIO.ts +0 -56
  137. package/src/io/gltf/__test__/GLTFIO.test.ts +0 -108
  138. package/src/light/AmbientLight.ts +0 -39
  139. package/src/light/PointLight.ts +0 -115
  140. package/src/light/SceneLight.ts +0 -63
  141. package/src/light/__test__/AmbientLight.test.ts +0 -29
  142. package/src/light/__test__/PointLight.test.ts +0 -74
  143. package/src/light/__test__/SceneLight.test.ts +0 -47
  144. package/src/loadingmanager/LoadingManager.ts +0 -50
  145. package/src/loadingmanager/__test__/LoadingManager.test.ts +0 -27
  146. package/src/math/__test__/DIVEMath.test.ts +0 -12
  147. package/src/math/ceil/__test__/ceilExp.test.ts +0 -12
  148. package/src/math/ceil/ceilExp.ts +0 -6
  149. package/src/math/degToRad/__test__/degToRad.test.ts +0 -172
  150. package/src/math/degToRad/degToRad.ts +0 -5
  151. package/src/math/floor/__test__/floorExp.test.ts +0 -14
  152. package/src/math/floor/floorExp.ts +0 -6
  153. package/src/math/helper/__test__/shift.test.ts +0 -12
  154. package/src/math/helper/shift.ts +0 -4
  155. package/src/math/index.ts +0 -28
  156. package/src/math/radToDeg/__test__/radToDeg.test.ts +0 -155
  157. package/src/math/radToDeg/radToDeg.ts +0 -5
  158. package/src/math/round/__test__/roundExp.test.ts +0 -14
  159. package/src/math/round/roundExp.ts +0 -10
  160. package/src/math/signedAngleTo/__test__/signedAngleTo.test.ts +0 -20
  161. package/src/math/signedAngleTo/signedAngleTo.ts +0 -20
  162. package/src/math/toFixed/__test__/toFixedExp.test.ts +0 -14
  163. package/src/math/toFixed/toFixedExp.ts +0 -9
  164. package/src/math/truncate/__test__/truncateExp.test.ts +0 -14
  165. package/src/math/truncate/truncateExp.ts +0 -9
  166. package/src/mediacreator/MediaCreator.ts +0 -75
  167. package/src/mediacreator/__test__/MediaCreator.test.ts +0 -155
  168. package/src/model/Model.ts +0 -185
  169. package/src/model/__test__/Model.test.ts +0 -222
  170. package/src/module/Module.ts +0 -45
  171. package/src/module/__test__/Module.test.ts +0 -54
  172. package/src/node/Node.ts +0 -98
  173. package/src/node/__test__/Node.test.ts +0 -120
  174. package/src/primitive/Primitive.ts +0 -299
  175. package/src/primitive/__test__/Primitive.test.ts +0 -281
  176. package/src/primitive/floor/Floor.ts +0 -45
  177. package/src/primitive/floor/__test__/Floor.test.ts +0 -24
  178. package/src/renderer/Renderer.ts +0 -215
  179. package/src/renderer/__test__/Renderer.test.ts +0 -228
  180. package/src/scene/Scene.ts +0 -106
  181. package/src/scene/__test__/Scene.test.ts +0 -124
  182. package/src/scene/root/Root.ts +0 -426
  183. package/src/scene/root/__test__/Root.test.ts +0 -903
  184. package/src/scene/xrroot/XRRoot.ts +0 -56
  185. package/src/scene/xrroot/xrlightroot/XRLightRoot.ts +0 -80
  186. package/src/toolbox/BaseTool.ts +0 -319
  187. package/src/toolbox/Toolbox.ts +0 -129
  188. package/src/toolbox/__test__/BaseTool.test.ts +0 -627
  189. package/src/toolbox/__test__/Toolbox.test.ts +0 -143
  190. package/src/toolbox/select/SelectTool.ts +0 -92
  191. package/src/toolbox/select/__test__/SelectTool.test.ts +0 -237
  192. package/src/toolbox/transform/TransformTool.ts +0 -166
  193. package/src/toolbox/transform/__test__/TransformTool.test.ts +0 -147
  194. package/src/types/SceneData.ts +0 -26
  195. package/src/types/SceneObjects.ts +0 -14
  196. package/src/types/SceneType.ts +0 -14
  197. package/src/types/index.ts +0 -5
@@ -1,155 +0,0 @@
1
- import { DIVEMediaCreator } from '../MediaCreator';
2
- import { DIVERenderer } from '../../renderer/Renderer';
3
- import { DIVEScene } from '../../scene/Scene';
4
- import DIVEPerspectiveCamera, {
5
- DIVEPerspectiveCameraDefaultSettings,
6
- } from '../../camera/PerspectiveCamera';
7
- import { type COMPov } from '../../com/types';
8
- import DIVEOrbitControls from '../../controls/OrbitControls';
9
- import { DIVEAnimationSystem } from '../../animation/AnimationSystem';
10
-
11
- /**
12
- * @jest-environment jsdom
13
- */
14
-
15
- const mock_render = jest.fn();
16
- const mock_toDataURL = jest.fn();
17
-
18
- jest.mock('../../scene/Scene', () => {
19
- return {
20
- DIVEScene: jest.fn(function () {
21
- this.add = jest.fn();
22
- this.children = [];
23
- this.Root = {
24
- children: [],
25
- };
26
- return this;
27
- }),
28
- };
29
- });
30
-
31
- jest.mock('../../camera/PerspectiveCamera', () => {
32
- return jest.fn(function () {
33
- this.position = {
34
- clone: jest.fn(),
35
- copy: jest.fn(),
36
- };
37
- this.quaternion = {
38
- clone: jest.fn(),
39
- copy: jest.fn(),
40
- };
41
- this.orbitControls = {
42
- target: {
43
- clone: jest.fn(),
44
- copy: jest.fn(),
45
- },
46
- update: jest.fn(),
47
- };
48
- this.layers = {
49
- mask: 0,
50
- };
51
- return this;
52
- });
53
- });
54
-
55
- jest.mock('../../controls/OrbitControls', () => {
56
- return jest.fn(function () {
57
- this.object = {
58
- position: {
59
- clone: jest.fn(),
60
- copy: jest.fn(),
61
- },
62
- quaternion: {
63
- clone: jest.fn(),
64
- copy: jest.fn(),
65
- },
66
- layers: {
67
- mask: 0,
68
- },
69
- OnResize: jest.fn(),
70
- };
71
-
72
- this.target = {
73
- clone: jest.fn(),
74
- copy: jest.fn(),
75
- };
76
-
77
- this.update = jest.fn();
78
-
79
- return this;
80
- });
81
- });
82
-
83
- jest.mock('../../renderer/Renderer', () => {
84
- return {
85
- DIVERenderer: jest.fn(function () {
86
- this.domElement = {
87
- toDataURL: mock_toDataURL,
88
- };
89
- this.render = mock_render;
90
- this.OnResize = jest.fn();
91
- return this;
92
- }),
93
- };
94
- });
95
-
96
- jest.mock('../../animation/AnimationSystem', () => {
97
- return {
98
- DIVEAnimationSystem: jest.fn(function () {
99
- this.domElement = {
100
- toDataURL: mock_toDataURL,
101
- };
102
- this.render = mock_render;
103
- this.OnResize = jest.fn();
104
- this.AddPreRenderCallback = jest.fn((callback) => {
105
- callback();
106
- return 'id';
107
- });
108
- return this;
109
- }),
110
- };
111
- });
112
-
113
- let mediaCreator: DIVEMediaCreator;
114
-
115
- describe('dive/mediacreator/DIVEMediaCreator', () => {
116
- beforeEach(() => {
117
- jest.clearAllMocks();
118
- mediaCreator = new DIVEMediaCreator(
119
- new DIVERenderer(),
120
- new DIVEScene(),
121
- new DIVEOrbitControls(
122
- new DIVEPerspectiveCamera(DIVEPerspectiveCameraDefaultSettings),
123
- new DIVERenderer(),
124
- new DIVEAnimationSystem(new DIVERenderer()),
125
- ),
126
- );
127
- });
128
-
129
- it('should instantiate', () => {
130
- expect(mediaCreator).toBeDefined();
131
- });
132
-
133
- it('should generate media', () => {
134
- const mock_POV = {
135
- position: { x: 0, y: 0, z: 0 },
136
- target: { x: 0, y: 0, z: 0 },
137
- } as COMPov;
138
- expect(() => {
139
- mediaCreator.GenerateMedia(
140
- mock_POV.position,
141
- mock_POV.target,
142
- 800,
143
- 600,
144
- );
145
- }).not.toThrow();
146
- expect(mock_render).toHaveBeenCalledTimes(1);
147
- expect(mock_toDataURL).toHaveBeenCalledTimes(1);
148
- });
149
-
150
- it('should draw canvas with custom canvas', () => {
151
- const canvas = document.createElement('canvas');
152
- mediaCreator.DrawCanvas(canvas);
153
- expect(mock_render).toHaveBeenCalledTimes(1);
154
- });
155
- });
@@ -1,185 +0,0 @@
1
- import { Mesh, MeshStandardMaterial, Raycaster, Vector3 } from 'three';
2
- import { PRODUCT_LAYER_MASK } from '../constant/VisibilityLayerMask';
3
- import type { GLTF } from 'three/examples/jsm/loaders/GLTFLoader';
4
- import { findSceneRecursive } from '../helper/findSceneRecursive/findSceneRecursive';
5
- import { type COMMaterial } from '../com/types';
6
- import { DIVENode } from '../node/Node';
7
- import { DIVECommunication } from '../com/Communication';
8
-
9
- /**
10
- * A basic model class.
11
- *
12
- * It does calculate it's own bounding box which is used for positioning on the floor.
13
- *
14
- * Can be moved and selected.
15
- *
16
- * @module
17
- */
18
-
19
- export class DIVEModel extends DIVENode {
20
- readonly isDIVEModel: true = true;
21
-
22
- private _mesh: Mesh | null = null;
23
- private _material: MeshStandardMaterial | null = null;
24
-
25
- public SetModel(gltf: GLTF): void {
26
- this.clear();
27
- this._boundingBox.makeEmpty();
28
-
29
- gltf.scene.traverse((child) => {
30
- child.castShadow = true;
31
- child.receiveShadow = true;
32
-
33
- child.layers.mask = this.layers.mask;
34
- this._boundingBox.expandByObject(child);
35
-
36
- // only search for first mesh for now
37
- if (!this._mesh && 'isMesh' in child) {
38
- this._mesh = child as Mesh;
39
-
40
- // if the material is already set, use it, otherwise set it from the model's material
41
- if (this._material) {
42
- this._mesh.material = this._material;
43
- } else {
44
- this._material = (child as Mesh)
45
- .material as MeshStandardMaterial;
46
- }
47
- }
48
- });
49
-
50
- this.add(gltf.scene);
51
- }
52
-
53
- public SetMaterial(material: Partial<COMMaterial>): void {
54
- // if there is no material, create a new one
55
- if (!this._material) {
56
- this._material = new MeshStandardMaterial();
57
- }
58
-
59
- if (material.vertexColors !== undefined) {
60
- this._material.vertexColors = material.vertexColors;
61
- }
62
-
63
- // apply color if supplied
64
- if (material.color !== undefined) {
65
- this._material.color.set(material.color);
66
- }
67
-
68
- // apply albedo map if supplied
69
- if (material.map !== undefined) {
70
- this._material.map = material.map;
71
- }
72
-
73
- // apply normal map
74
- if (material.normalMap !== undefined) {
75
- this._material.normalMap = material.normalMap;
76
- }
77
-
78
- // set roughness value
79
- // if supplied, apply roughness map
80
- // if we applied a roughness map, set roughness to 1.0
81
- if (material.roughness !== undefined) {
82
- this._material.roughness = material.roughness;
83
- }
84
-
85
- if (material.roughnessMap !== undefined) {
86
- this._material.roughnessMap = material.roughnessMap;
87
-
88
- if (this._material.roughnessMap) {
89
- this._material.roughness = 1.0;
90
- }
91
- }
92
-
93
- // set metalness value
94
- // if supplied, apply metalness map
95
- // if we applied a metalness map, set metalness to 1.0
96
- if (material.metalness !== undefined) {
97
- this._material.metalness = material.metalness;
98
- }
99
-
100
- if (material.metalnessMap !== undefined) {
101
- this._material.metalnessMap = material.metalnessMap;
102
-
103
- if (this._material.metalnessMap) {
104
- this._material.metalness = 1.0;
105
- }
106
- }
107
-
108
- // if the mesh is already set, update the material
109
- if (this._mesh) {
110
- this._mesh.material = this._material;
111
- }
112
- }
113
-
114
- public PlaceOnFloor(): void {
115
- // calculate and temporary save world position
116
- const worldPos = this.getWorldPosition(this._positionWorldBuffer);
117
- const oldWorldPos = worldPos.clone();
118
-
119
- // compute the bounding box
120
- this._mesh?.geometry?.computeBoundingBox();
121
- const meshBB = this._mesh?.geometry?.boundingBox;
122
-
123
- // subtract the bounding box min y axis value from the world position y value
124
- if (!meshBB || !this._mesh) return;
125
- worldPos.y = worldPos.y - this._mesh.localToWorld(meshBB.min.clone()).y;
126
-
127
- // skip any action when the position did not change
128
- if (worldPos.y === oldWorldPos.y) return;
129
-
130
- DIVECommunication.get(this.userData.id)?.PerformAction(
131
- 'UPDATE_OBJECT',
132
- {
133
- id: this.userData.id,
134
- position: worldPos,
135
- rotation: this.rotation,
136
- scale: this.scale,
137
- },
138
- );
139
- }
140
-
141
- public DropIt(): void {
142
- if (!this.parent) {
143
- console.warn(
144
- 'DIVEModel: DropIt() called on a model that is not in the scene.',
145
- this,
146
- );
147
- return;
148
- }
149
-
150
- // calculate the bottom center of the bounding box
151
- const bottomY = this._boundingBox.min.y * this.scale.y;
152
- const bbBottomCenter = this.localToWorld(
153
- this._boundingBox.getCenter(new Vector3()).multiply(this.scale),
154
- );
155
- bbBottomCenter.y = bottomY + this.position.y;
156
-
157
- // set up raycaster and raycast all scene objects (product layer)
158
- const raycaster = new Raycaster(bbBottomCenter, new Vector3(0, -1, 0));
159
- raycaster.layers.mask = PRODUCT_LAYER_MASK;
160
- const intersections = raycaster.intersectObjects(
161
- findSceneRecursive(this).Root.children,
162
- true,
163
- );
164
-
165
- // if we hit something, move the model to the top on the hit object's bounding box
166
- if (intersections.length > 0) {
167
- const mesh = intersections[0].object as Mesh;
168
- mesh.geometry.computeBoundingBox();
169
- const meshBB = mesh.geometry.boundingBox!;
170
- const worldPos = mesh.localToWorld(meshBB.max.clone());
171
-
172
- const oldPos = this.position.clone();
173
- const newPos = this.position
174
- .clone()
175
- .setY(worldPos.y)
176
- .sub(new Vector3(0, bottomY, 0));
177
- this.position.copy(newPos);
178
-
179
- // if the position changed, update the object in communication
180
- if (this.position.y === oldPos.y) return;
181
-
182
- this.onMove();
183
- }
184
- }
185
- }
@@ -1,222 +0,0 @@
1
- import { RaycasterIntersectObjectMock } from '../../../__mocks__/three';
2
-
3
- import { DIVEModel } from '../Model';
4
- import { DIVECommunication } from '../../com/Communication';
5
- import { GLTF } from 'three/examples/jsm/loaders/GLTFLoader';
6
- import { DIVEScene } from '../../scene/Scene';
7
- import {
8
- Vector3,
9
- Box3,
10
- Mesh,
11
- MeshStandardMaterial,
12
- type Texture,
13
- Object3D,
14
- } from 'three';
15
- import { type COMMaterial } from '../../com/types';
16
-
17
- jest.mock('../../com/Communication.ts', () => {
18
- return {
19
- DIVECommunication: {
20
- get: jest.fn(() => {
21
- return {
22
- PerformAction: jest.fn(),
23
- };
24
- }),
25
- },
26
- };
27
- });
28
-
29
- const object = new Object3D();
30
- object.children.push(new Mesh());
31
-
32
- const gltf = {
33
- scene: {
34
- ...object,
35
- },
36
- } as unknown as GLTF;
37
-
38
- jest.spyOn(DIVECommunication, 'get').mockReturnValue({
39
- PerformAction: jest.fn(),
40
- } as unknown as DIVECommunication);
41
-
42
- let model: DIVEModel;
43
-
44
- describe('dive/model/DIVEModel', () => {
45
- beforeEach(() => {
46
- jest.clearAllMocks();
47
- RaycasterIntersectObjectMock.mockClear();
48
- model = new DIVEModel();
49
- });
50
-
51
- afterEach(() => {
52
- jest.clearAllMocks();
53
- });
54
-
55
- it('should instantiate', () => {
56
- expect(model).toBeDefined();
57
- });
58
-
59
- it('should set model', () => {
60
- expect(() => model.SetModel(gltf)).not.toThrow();
61
- });
62
-
63
- it('should place on floor', () => {
64
- model.SetModel(gltf);
65
-
66
- const com = DIVECommunication.get('id')!;
67
- const spyPerformAction = jest.spyOn(com, 'PerformAction');
68
-
69
- model.userData.id = 'something';
70
- model.position.set(0, 4, 0);
71
-
72
- jest.spyOn(model['_mesh']!, 'localToWorld').mockReturnValueOnce(
73
- new Vector3(0, 2, 0),
74
- );
75
-
76
- const scene = {
77
- parent: null,
78
- Root: {
79
- children: [
80
- model,
81
- ],
82
- },
83
- } as unknown as DIVEScene;
84
- scene.Root.parent = scene;
85
- model.parent = scene.Root;
86
-
87
- expect(() => model.PlaceOnFloor()).not.toThrow();
88
- expect(spyPerformAction).toHaveBeenCalledWith(
89
- 'UPDATE_OBJECT',
90
- expect.objectContaining({
91
- position: expect.objectContaining({
92
- y: 2,
93
- }),
94
- }),
95
- );
96
- });
97
-
98
- it('should drop it', () => {
99
- const comMock = {
100
- PerformAction: jest.fn(),
101
- } as unknown as DIVECommunication;
102
- jest.spyOn(DIVECommunication, 'get').mockReturnValue(comMock);
103
-
104
- const spy = jest.spyOn(model, 'onMove').mockImplementation(() => {});
105
-
106
- const size = {
107
- x: 1,
108
- y: 1,
109
- z: 1,
110
- };
111
-
112
- model.userData.id = 'something';
113
- model.position.set(0, 4, 0);
114
- model['_boundingBox'] = {
115
- min: new Vector3(-size.x / 2, -size.y / 2, -size.z / 2),
116
- max: new Vector3(size.x / 2, size.y / 2, size.z / 2),
117
- getCenter: jest.fn(() => {
118
- return new Vector3(0, 0, 0);
119
- }),
120
- } as unknown as Box3;
121
-
122
- const hitObject = new Mesh();
123
- hitObject.geometry.boundingBox = new Box3();
124
- hitObject.geometry.boundingBox.max = new Vector3(0, 2, 0);
125
- RaycasterIntersectObjectMock.mockReturnValue([
126
- {
127
- object: hitObject,
128
- },
129
- ]);
130
-
131
- const scene = {
132
- parent: null,
133
- Root: {
134
- children: [
135
- model,
136
- ],
137
- },
138
- } as unknown as DIVEScene;
139
- scene.Root.parent = scene;
140
-
141
- // test when parent is not set
142
- console.warn = jest.fn();
143
- expect(() => model.DropIt()).not.toThrow();
144
- expect(console.warn).toHaveBeenCalledTimes(1);
145
-
146
- model.parent = scene.Root;
147
-
148
- expect(() => model.DropIt()).not.toThrow();
149
- expect(model.position.y).toBe(2.5);
150
- expect(spy).toHaveBeenCalledTimes(1);
151
-
152
- expect(() => model.DropIt()).not.toThrow();
153
- expect(spy).toHaveBeenCalledTimes(1);
154
-
155
- // alter position so onMove will be called again
156
- model.position.y = 2;
157
- jest.spyOn(DIVECommunication, 'get').mockReturnValueOnce(undefined);
158
- expect(() => model.DropIt()).not.toThrow();
159
- expect(spy).toHaveBeenCalledTimes(2);
160
- });
161
-
162
- it('should set material', () => {
163
- // apply invalid material should not crash
164
- expect(() => model.SetMaterial({} as COMMaterial)).not.toThrow();
165
- expect(model['_material']).not.toBeNull();
166
-
167
- expect(() =>
168
- model.SetMaterial({
169
- color: 0xffffff,
170
- roughness: 0,
171
- metalness: 1,
172
- } as COMMaterial),
173
- ).not.toThrow();
174
- expect((model['_material'] as MeshStandardMaterial).roughness).toBe(0);
175
- expect(
176
- (model['_material'] as MeshStandardMaterial).roughnessMap,
177
- ).toBeUndefined();
178
- expect((model['_material'] as MeshStandardMaterial).metalness).toBe(1);
179
- expect(
180
- (model['_material'] as MeshStandardMaterial).metalnessMap,
181
- ).toBeUndefined();
182
-
183
- expect(() =>
184
- model.SetMaterial({
185
- color: 0xff00ff,
186
- vertexColors: true,
187
- map: 'This_Is_A_Texture' as unknown as Texture,
188
- normalMap: 'This_Is_A_Texture' as unknown as Texture,
189
- roughness: 0,
190
- roughnessMap: 'This_Is_A_Texture' as unknown as Texture,
191
- metalness: 1,
192
- metalnessMap: 'This_Is_A_Texture' as unknown as Texture,
193
- } as COMMaterial),
194
- ).not.toThrow();
195
- expect((model['_material'] as MeshStandardMaterial).roughness).toBe(1);
196
- expect(
197
- (model['_material'] as MeshStandardMaterial).roughnessMap,
198
- ).toBeDefined();
199
- expect((model['_material'] as MeshStandardMaterial).metalness).toBe(1);
200
- expect(
201
- (model['_material'] as MeshStandardMaterial).metalnessMap,
202
- ).toBeDefined();
203
- });
204
-
205
- it('should set model material when material already set before', () => {
206
- model.SetMaterial({ roughness: 0.5 } as COMMaterial);
207
- expect(() => model.SetModel(gltf)).not.toThrow();
208
- expect(
209
- (model['_mesh']?.material as MeshStandardMaterial).roughness,
210
- ).toBe(0.5);
211
- });
212
-
213
- it('should set material to model when model already set before', () => {
214
- model.SetModel(gltf);
215
- expect(() =>
216
- model.SetMaterial({ roughness: 0.5 } as COMMaterial),
217
- ).not.toThrow();
218
- expect(
219
- (model['_mesh']?.material as MeshStandardMaterial).roughness,
220
- ).toBe(0.5);
221
- });
222
- });
@@ -1,45 +0,0 @@
1
- export class DIVEModule<T> {
2
- constructor(
3
- private _path: string,
4
- private _ctor: string,
5
- ) {}
6
-
7
- private _promise: Promise<T> | null = null;
8
- private _instance: T | null = null;
9
-
10
- public async get(): Promise<T> {
11
- // if we already have an instance, return it
12
- if (this._instance) {
13
- return Promise.resolve(this._instance);
14
- }
15
-
16
- // if we already have a loading process ongoing, return the already created promise
17
- if (this._promise) {
18
- return this._promise;
19
- }
20
-
21
- // if we don't have a promise yet, it means that we are not already loading the module
22
- this._promise = (async () => {
23
- const module = await import(this._path);
24
-
25
- const ModuleConstructor = module[this._ctor];
26
-
27
- if (!ModuleConstructor) {
28
- throw new Error(
29
- `DIVE: Module class ${this._ctor} not found in ${this._path}`,
30
- );
31
- }
32
-
33
- if (typeof ModuleConstructor !== 'function') {
34
- throw new Error(
35
- `DIVE: Module at ${this._path} does not export a valid constructor (${this._ctor} wanted)`,
36
- );
37
- }
38
-
39
- this._instance = new ModuleConstructor() as T;
40
- return this._instance;
41
- })();
42
-
43
- return this._promise;
44
- }
45
- }
@@ -1,54 +0,0 @@
1
- import { DIVEModule } from '../Module';
2
-
3
- jest.mock('/mock/path', () => mockModule, { virtual: true });
4
-
5
- const mockModule: Record<string, any> = {};
6
-
7
- describe('dive/module/DIVEModule', () => {
8
- beforeEach(() => {
9
- // Reset the mock module before each test
10
- Object.keys(mockModule).forEach((key) => delete mockModule[key]);
11
- });
12
-
13
- it('should return the same instance on multiple calls to get()', async () => {
14
- mockModule.TestClass = class TestClass {};
15
- const diveModule = new DIVEModule('/mock/path', 'TestClass');
16
-
17
- const instance1 = await diveModule.get();
18
- const instance2 = await diveModule.get();
19
-
20
- expect(instance1).toBe(instance2);
21
- });
22
-
23
- it('should throw an error if the constructor is not found', async () => {
24
- const diveModule = new DIVEModule('/mock/path', 'NonExistentClass');
25
-
26
- await expect(diveModule.get()).rejects.toThrow(
27
- 'DIVE: Module class NonExistentClass not found in /mock/path',
28
- );
29
- });
30
-
31
- it('should throw an error if the constructor is not a function', async () => {
32
- mockModule.InvalidClass = {};
33
- const diveModule = new DIVEModule('/mock/path', 'InvalidClass');
34
-
35
- await expect(diveModule.get()).rejects.toThrow(
36
- 'DIVE: Module at /mock/path does not export a valid constructor (InvalidClass wanted)',
37
- );
38
- });
39
-
40
- it('should only load the module once even with concurrent calls to get()', async () => {
41
- mockModule.TestClass = class TestClass {};
42
- const diveModule = new DIVEModule('/mock/path', 'TestClass');
43
-
44
- const [
45
- instance1,
46
- instance2,
47
- ] = await Promise.all([
48
- diveModule.get(),
49
- diveModule.get(),
50
- ]);
51
-
52
- expect(instance1).toBe(instance2);
53
- });
54
- });