@shopware-ag/dive 1.8.0 → 1.9.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.
@@ -1,13 +1,10 @@
1
1
  import DIVERoot from '../Root';
2
2
  import { type Vector3, type Object3D } from 'three';
3
- import { type COMLight, type COMModel, type COMPov } from '../../../com';
4
-
5
- const mock_UpdateLight = jest.fn();
6
- const mock_UpdateModel = jest.fn();
7
- const mock_GetLight = jest.fn();
8
- const mock_GetModel = jest.fn();
9
- const mock_DeleteLight = jest.fn();
10
- const mock_DeleteModel = jest.fn();
3
+ import { type COMPrimitive, type COMLight, type COMModel, type COMPov } from '../../../com/types';
4
+
5
+ const mock_UpdateObject = jest.fn();
6
+ const mock_DeleteObject = jest.fn();
7
+ const mock_GetObject = jest.fn();
11
8
  const mock_PlaceOnFloor = jest.fn();
12
9
 
13
10
  jest.mock('three', () => {
@@ -91,9 +88,9 @@ jest.mock('../lightroot/LightRoot', () => {
91
88
  this.isObject3D = true;
92
89
  this.parent = null;
93
90
  this.dispatchEvent = jest.fn();
94
- this.UpdateLight = mock_UpdateLight;
95
- this.DeleteLight = mock_DeleteLight;
96
- this.GetLight = mock_GetLight;
91
+ this.UpdateLight = mock_UpdateObject;
92
+ this.DeleteLight = mock_DeleteObject;
93
+ this.GetLight = mock_GetObject;
97
94
  this.removeFromParent = jest.fn();
98
95
  return this;
99
96
  });
@@ -104,10 +101,10 @@ jest.mock('../modelroot/ModelRoot', () => {
104
101
  this.isObject3D = true;
105
102
  this.parent = null;
106
103
  this.dispatchEvent = jest.fn();
107
- this.UpdateModel = mock_UpdateModel;
108
- this.DeleteModel = mock_DeleteModel;
104
+ this.UpdateModel = mock_UpdateObject;
105
+ this.DeleteModel = mock_DeleteObject;
109
106
  this.PlaceOnFloor = mock_PlaceOnFloor;
110
- this.GetModel = mock_GetModel;
107
+ this.GetModel = mock_GetObject;
111
108
  this.removeFromParent = jest.fn();
112
109
  this.traverse = jest.fn((callback: (object: Object3D) => void) => {
113
110
  callback(this);
@@ -116,6 +113,25 @@ jest.mock('../modelroot/ModelRoot', () => {
116
113
  });
117
114
  });
118
115
 
116
+ jest.mock('../primitiveroot/PrimitiveRoot', () => {
117
+ return {
118
+ DIVEPrimitiveRoot: jest.fn(function () {
119
+ this.isObject3D = true;
120
+ this.parent = null;
121
+ this.dispatchEvent = jest.fn();
122
+ this.UpdatePrimitive = mock_UpdateObject;
123
+ this.DeletePrimitive = mock_DeleteObject;
124
+ this.PlaceOnFloor = mock_PlaceOnFloor;
125
+ this.GetPrimitive = mock_GetObject;
126
+ this.removeFromParent = jest.fn();
127
+ this.traverse = jest.fn((callback: (object: Object3D) => void) => {
128
+ callback(this);
129
+ });
130
+ return this;
131
+ }),
132
+ };
133
+ });
134
+
119
135
  describe('DIVE/scene/root/DIVERoot', () => {
120
136
  afterEach(() => {
121
137
  jest.clearAllMocks();
@@ -124,7 +140,7 @@ describe('DIVE/scene/root/DIVERoot', () => {
124
140
  it('should instantiate', () => {
125
141
  const root = new DIVERoot();
126
142
  expect(root).toBeDefined();
127
- expect(root.add).toHaveBeenCalledTimes(4);
143
+ expect(root.add).toHaveBeenCalledTimes(5);
128
144
  });
129
145
 
130
146
  it('should have Floor', () => {
@@ -145,51 +161,79 @@ describe('DIVE/scene/root/DIVERoot', () => {
145
161
 
146
162
  it('should add object', () => {
147
163
  const root = new DIVERoot();
164
+ expect(() => root.AddSceneObject({ entityType: 'pov' } as COMPov)).not.toThrow();
165
+ expect(mock_UpdateObject).toHaveBeenCalledTimes(0);
166
+
148
167
  root.AddSceneObject({ entityType: 'light' } as COMLight);
149
- expect(mock_UpdateLight).toHaveBeenCalledTimes(1);
168
+ expect(mock_UpdateObject).toHaveBeenCalledTimes(1);
150
169
 
151
170
  root.AddSceneObject({ entityType: 'model' } as COMModel);
152
- expect(mock_UpdateModel).toHaveBeenCalledTimes(1);
171
+ expect(mock_UpdateObject).toHaveBeenCalledTimes(2);
153
172
 
154
- expect(() => root.AddSceneObject({ entityType: 'pov' } as COMPov)).not.toThrow();
173
+ root.AddSceneObject({ entityType: 'primitive' } as COMPrimitive);
174
+ expect(mock_UpdateObject).toHaveBeenCalledTimes(3);
155
175
  });
156
176
 
157
177
  it('should update object', () => {
158
178
  const root = new DIVERoot();
159
179
 
180
+ expect(() => root.UpdateSceneObject({ entityType: 'pov' })).not.toThrow();
181
+ expect(mock_UpdateObject).toHaveBeenCalledTimes(0);
182
+
160
183
  root.UpdateSceneObject({ entityType: 'light' });
161
- expect(mock_UpdateLight).toHaveBeenCalledTimes(1);
184
+ expect(mock_UpdateObject).toHaveBeenCalledTimes(1);
162
185
 
163
186
  root.UpdateSceneObject({ entityType: 'model' });
164
- expect(mock_UpdateModel).toHaveBeenCalledTimes(1);
187
+ expect(mock_UpdateObject).toHaveBeenCalledTimes(2);
165
188
 
166
- expect(() => root.UpdateSceneObject({ entityType: 'pov' })).not.toThrow();
189
+ root.UpdateSceneObject({ entityType: 'primitive' });
190
+ expect(mock_UpdateObject).toHaveBeenCalledTimes(3);
167
191
  });
168
192
 
169
193
  it('should delete object', () => {
170
194
  const root = new DIVERoot();
171
195
 
172
196
  root.DeleteSceneObject({ entityType: 'light' });
173
- expect(mock_DeleteLight).toHaveBeenCalledTimes(1);
197
+ expect(mock_DeleteObject).toHaveBeenCalledTimes(1);
174
198
 
175
199
  root.DeleteSceneObject({ entityType: 'model' });
176
- expect(mock_DeleteModel).toHaveBeenCalledTimes(1);
200
+ expect(mock_DeleteObject).toHaveBeenCalledTimes(2);
201
+
202
+ root.DeleteSceneObject({ entityType: 'primitive' });
203
+ expect(mock_DeleteObject).toHaveBeenCalledTimes(3);
177
204
 
178
205
  expect(() => root.DeleteSceneObject({ entityType: 'pov' })).not.toThrow();
179
206
  });
180
207
 
181
208
  it('should place model on floor', () => {
182
209
  const root = new DIVERoot();
210
+
211
+ root.PlaceOnFloor({ entityType: 'pov' });
212
+ expect(mock_PlaceOnFloor).toHaveBeenCalledTimes(0);
213
+
214
+ root.PlaceOnFloor({ entityType: 'light' });
215
+ expect(mock_PlaceOnFloor).toHaveBeenCalledTimes(0);
216
+
183
217
  root.PlaceOnFloor({ entityType: 'model' });
184
218
  expect(mock_PlaceOnFloor).toHaveBeenCalledTimes(1);
219
+
220
+ root.PlaceOnFloor({ entityType: 'primitive' });
221
+ expect(mock_PlaceOnFloor).toHaveBeenCalledTimes(2);
185
222
  });
186
223
 
187
224
  it('should get scene object', () => {
188
225
  const scene = new DIVERoot();
189
- scene.GetSceneObject({ entityType: 'model' });
190
- expect(mock_GetModel).toHaveBeenCalledTimes(1);
191
- scene.GetSceneObject({ entityType: 'light' });
192
- expect(mock_GetLight).toHaveBeenCalledTimes(1);
226
+
193
227
  expect(scene.GetSceneObject({ entityType: 'pov' })).toBeUndefined();
228
+ expect(mock_GetObject).toHaveBeenCalledTimes(0);
229
+
230
+ scene.GetSceneObject({ entityType: 'light' });
231
+ expect(mock_GetObject).toHaveBeenCalledTimes(1);
232
+
233
+ scene.GetSceneObject({ entityType: 'model' });
234
+ expect(mock_GetObject).toHaveBeenCalledTimes(2);
235
+
236
+ scene.GetSceneObject({ entityType: 'primitive' });
237
+ expect(mock_GetObject).toHaveBeenCalledTimes(3);
194
238
  });
195
239
  });
@@ -1,8 +1,7 @@
1
- import { TransformControls } from 'three/examples/jsm/Addons';
2
- import { COMLight } from '../../../../com';
3
- import { DIVEMoveable } from '../../../../interface/Moveable';
4
1
  import DIVELightRoot from '../LightRoot';
5
2
  import type DIVEScene from '../../../Scene';
3
+ import { type COMLight } from '../../../../com/types';
4
+ import { type DIVEMoveable } from '../../../../interface/Moveable';
6
5
 
7
6
  const mock_SetPosition = jest.fn();
8
7
  const mock_SetIntensity = jest.fn();
@@ -0,0 +1,88 @@
1
+ import { Object3D } from "three";
2
+ import { DIVEPrimitive } from "../../../primitive/Primitive.ts";
3
+ import type DIVEScene from "../../Scene.ts";
4
+ import { type COMPrimitive } from "../../../com/types";
5
+ import { type TransformControls } from "three/examples/jsm/controls/TransformControls";
6
+
7
+ /**
8
+ * A basic scene node to hold all primitives.
9
+ *
10
+ * @module
11
+ */
12
+ export class DIVEPrimitiveRoot extends Object3D {
13
+ constructor() {
14
+ super();
15
+ this.name = "PrimitiveRoot";
16
+ }
17
+
18
+ public GetPrimitive(object: Partial<COMPrimitive>): Object3D | undefined {
19
+ if (object.id === undefined) {
20
+ console.warn('PrimitiveRoot.GetPrimitive: object.id is undefined')
21
+ return undefined;
22
+ }
23
+ return this.children.find(object3D => object3D.userData.id === object.id);
24
+ }
25
+
26
+ public UpdatePrimitive(object: Partial<COMPrimitive>): void {
27
+ if (object.id === undefined) {
28
+ console.warn('PrimitiveRoot.UpdatePrimitive: object.id is undefined')
29
+ return;
30
+ }
31
+
32
+ let sceneObject = this.children.find(object3D => object3D.userData.id === object.id);
33
+ if (!sceneObject && object.geometry !== undefined) {
34
+ const primitive = new DIVEPrimitive();
35
+ primitive.SetGeometry(object.geometry);
36
+ sceneObject = primitive;
37
+ sceneObject.userData.id = object.id;
38
+ this.add(sceneObject);
39
+ }
40
+
41
+ if (object.position !== undefined) (sceneObject as DIVEPrimitive).SetPosition(object.position);
42
+ if (object.rotation !== undefined) (sceneObject as DIVEPrimitive).SetRotation(object.rotation);
43
+ if (object.scale !== undefined) (sceneObject as DIVEPrimitive).SetScale(object.scale);
44
+ if (object.visible !== undefined) (sceneObject as DIVEPrimitive).SetVisibility(object.visible);
45
+ if (object.material !== undefined) (sceneObject as DIVEPrimitive).SetMaterial(object.material);
46
+ }
47
+
48
+ public DeletePrimitive(object: Partial<COMPrimitive>): void {
49
+ if (object.id === undefined) {
50
+ console.warn(`PrimitiveRoot.DeletePrimitive: object.id is undefined`)
51
+ return;
52
+ }
53
+
54
+ const sceneObject = this.children.find(object3D => object3D.userData.id === object.id);
55
+ if (!sceneObject) {
56
+ console.warn(`PrimitiveRoot.DeletePrimitive: Primitive with id ${object.id} not found`);
57
+ return;
58
+ }
59
+
60
+ // _______________________________________________________
61
+ // this is only neccessary due to using the old TransformControls instead of the new DIVEGizmo
62
+ const findScene = (object: Object3D): DIVEScene => {
63
+ if (object.parent !== null) {
64
+ return findScene(object.parent);
65
+ };
66
+ return object as DIVEScene;
67
+ }
68
+
69
+ const scene = findScene(sceneObject);
70
+ scene.children.find((object) => {
71
+ if ('isTransformControls' in object) {
72
+ (object as TransformControls).detach();
73
+ }
74
+ });
75
+ // _______________________________________________________
76
+
77
+ this.remove(sceneObject);
78
+ }
79
+
80
+ public PlaceOnFloor(object: Partial<COMPrimitive>): void {
81
+ if (object.id === undefined) console.warn('PrimitiveRoot.PlaceOnFloor: object.id is undefined');
82
+
83
+ const sceneObject = this.children.find(object3D => object3D.userData.id === object.id);
84
+ if (!sceneObject) return;
85
+
86
+ (sceneObject as DIVEPrimitive).PlaceOnFloor();
87
+ }
88
+ }
@@ -0,0 +1,181 @@
1
+ import DIVECommunication from '../../../../com/Communication';
2
+ import { DIVEPrimitiveRoot } from '../PrimitiveRoot';
3
+ import type DIVEScene from '../../../Scene';
4
+ import { type DIVEMoveable } from '../../../../interface/Moveable';
5
+ import { type COMMaterial, type COMGeometry } from '../../../../com/types';
6
+
7
+ const mock_SetPosition = jest.fn();
8
+ const mock_SetRotation = jest.fn();
9
+ const mock_SetScale = jest.fn();
10
+ const mock_PlaceOnFloor = jest.fn();
11
+ const mock_SetGeometry = jest.fn();
12
+ const mock_SetMaterial = jest.fn();
13
+
14
+ jest.mock('../../../../com/types.ts', () => {
15
+ return {
16
+ COMPrimitive: {},
17
+ }
18
+ });
19
+
20
+ jest.mock('../../../../com/Communication.ts', () => {
21
+ return {
22
+ get: jest.fn(() => {
23
+ return {
24
+ PerformAction: jest.fn(),
25
+ }
26
+ }),
27
+ }
28
+ });
29
+
30
+ jest.mock('../../../../primitive/Primitive.ts', () => {
31
+ return {
32
+ DIVEPrimitive: jest.fn(function () {
33
+ this.isObject3D = true;
34
+ this.parent = null;
35
+ this.dispatchEvent = jest.fn();
36
+ this.userData = {
37
+ id: undefined,
38
+ };
39
+ this.SetGeometry = mock_SetGeometry;
40
+ this.SetMaterial = mock_SetMaterial;
41
+ this.SetPosition = mock_SetPosition;
42
+ this.SetRotation = mock_SetRotation;
43
+ this.SetScale = mock_SetScale;
44
+ this.SetVisibility = jest.fn();
45
+ this.PlaceOnFloor = mock_PlaceOnFloor;
46
+ this.removeFromParent = jest.fn();
47
+ return this;
48
+ })
49
+ };
50
+ });
51
+
52
+ jest.spyOn(DIVECommunication, 'get').mockReturnValue({ PerformAction: jest.fn() } as unknown as DIVECommunication);
53
+
54
+ const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(() => { });
55
+ let primitiveRoot = new DIVEPrimitiveRoot();
56
+
57
+ describe('dive/scene/root/primitiveroot/DIVEPrimitiveRoot', () => {
58
+ beforeEach(() => {
59
+ consoleWarnSpy.mockClear();
60
+
61
+ primitiveRoot = new DIVEPrimitiveRoot();
62
+ });
63
+
64
+ it('should instantiate', () => {
65
+ expect(primitiveRoot).toBeDefined();
66
+ });
67
+
68
+ it('should not add incorrect primitive', async () => {
69
+ expect(() => primitiveRoot.UpdatePrimitive({ id: undefined })).not.toThrow();
70
+ expect(consoleWarnSpy).toHaveBeenCalled();
71
+ expect(primitiveRoot.children).toHaveLength(0);
72
+ });
73
+
74
+ it('should add basic primitive', async () => {
75
+ expect(() => primitiveRoot.UpdatePrimitive({
76
+ id: 'test_id',
77
+ geometry: {} as COMGeometry,
78
+ visible: false,
79
+ })).not.toThrow();
80
+ expect(mock_SetGeometry).toHaveBeenCalledTimes(1);
81
+ expect(primitiveRoot.children).toHaveLength(1);
82
+ expect(primitiveRoot.children[0].userData.id).toBe('test_id');
83
+ });
84
+
85
+ it('should add configured primitive', async () => {
86
+ primitiveRoot.userData.id = 'something';
87
+ expect(() => primitiveRoot.UpdatePrimitive({
88
+ id: 'test_id',
89
+ position: { x: 1, y: 2, z: 3 },
90
+ rotation: { x: 1, y: 2, z: 3 },
91
+ scale: { x: 1, y: 2, z: 3 },
92
+ geometry: {} as COMGeometry,
93
+ material: {} as COMMaterial,
94
+ })).not.toThrow();
95
+
96
+ jest.spyOn(DIVECommunication, 'get').mockReturnValueOnce(undefined);
97
+ expect(() => primitiveRoot.UpdatePrimitive({
98
+ id: 'test_id',
99
+ position: { x: 1, y: 2, z: 3 },
100
+ rotation: { x: 1, y: 2, z: 3 },
101
+ scale: { x: 1, y: 2, z: 3 },
102
+ geometry: {} as COMGeometry,
103
+ material: {} as COMMaterial,
104
+ }
105
+ )).not.toThrow();
106
+
107
+ expect(primitiveRoot.children).toHaveLength(1);
108
+ expect(mock_SetPosition).toHaveBeenCalledTimes(2);
109
+ expect(mock_SetRotation).toHaveBeenCalledTimes(2);
110
+ expect(mock_SetScale).toHaveBeenCalledTimes(2);
111
+ expect(mock_SetGeometry).toHaveBeenCalledTimes(2);
112
+ expect(mock_SetMaterial).toHaveBeenCalledTimes(2);
113
+ });
114
+
115
+ it('should not place incorrect primitive on floor', async () => {
116
+ expect(() => primitiveRoot.PlaceOnFloor({ id: undefined })).not.toThrow();
117
+ expect(consoleWarnSpy).toHaveBeenCalled();
118
+ expect(mock_PlaceOnFloor).toHaveBeenCalledTimes(0);
119
+ });
120
+
121
+ it('should not place non-existing primitive on floor', async () => {
122
+ primitiveRoot.PlaceOnFloor({ id: 'test_id' });
123
+ expect(mock_PlaceOnFloor).toHaveBeenCalledTimes(0);
124
+ });
125
+
126
+ it('should place primitive on floor', async () => {
127
+ primitiveRoot.UpdatePrimitive({
128
+ id: 'test_id',
129
+ position: { x: 1, y: 2, z: 3 },
130
+ rotation: { x: 1, y: 2, z: 3 },
131
+ scale: { x: 1, y: 2, z: 3 },
132
+ geometry: {} as COMGeometry,
133
+ });
134
+ primitiveRoot.PlaceOnFloor({ id: 'test_id' });
135
+ expect(mock_PlaceOnFloor).toHaveBeenCalledTimes(1);
136
+ });
137
+
138
+ it('should get primitive', async () => {
139
+ expect(() => primitiveRoot.GetPrimitive({ id: undefined })).not.toThrow();
140
+ expect(consoleWarnSpy).toHaveBeenCalled();
141
+ expect(primitiveRoot.GetPrimitive({ id: 'test_id' })).toBeUndefined();
142
+ expect(() => primitiveRoot.UpdatePrimitive({
143
+ id: 'test_id',
144
+ position: { x: 1, y: 2, z: 3 },
145
+ rotation: { x: 1, y: 2, z: 3 },
146
+ scale: { x: 1, y: 2, z: 3 },
147
+ geometry: {} as COMGeometry,
148
+ })).not.toThrow();
149
+ expect(primitiveRoot.GetPrimitive({ id: 'test_id' })).toBeDefined();
150
+ });
151
+
152
+ it('should delete primitive', async () => {
153
+
154
+ const sceneParent = {
155
+ parent: null,
156
+ children: [
157
+ {
158
+ isTransformControls: true,
159
+ detach: jest.fn(),
160
+ }
161
+ ],
162
+ }
163
+ primitiveRoot.parent = sceneParent as unknown as DIVEScene;
164
+
165
+ expect(() => primitiveRoot.DeletePrimitive({ id: undefined })).not.toThrow();
166
+ expect(consoleWarnSpy).toHaveBeenCalled();
167
+ consoleWarnSpy.mockClear();
168
+ expect(() => primitiveRoot.DeletePrimitive({ id: 'test_id' })).not.toThrow();
169
+ expect(consoleWarnSpy).toHaveBeenCalled();
170
+ expect(() => primitiveRoot.UpdatePrimitive({
171
+ id: 'test_id',
172
+ position: { x: 1, y: 2, z: 3 },
173
+ rotation: { x: 1, y: 2, z: 3 },
174
+ scale: { x: 1, y: 2, z: 3 },
175
+ geometry: {} as COMGeometry,
176
+ })).not.toThrow();
177
+ (primitiveRoot.children[0] as unknown as DIVEMoveable).isMoveable = true;
178
+ expect(() => primitiveRoot.DeletePrimitive({ id: 'test_id' })).not.toThrow();
179
+ expect(primitiveRoot.children).toHaveLength(0);
180
+ });
181
+ });