@shopware-ag/dive 1.4.1 → 1.5.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shopware-ag/dive",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "description": "Shopware Spatial Framework",
5
5
  "type": "module",
6
6
  "main": "./build/dive.cjs",
@@ -144,6 +144,10 @@ export default class DIVECommunication {
144
144
  returnValue = this.setGizmoMode(payload as Actions['SET_GIZMO_MODE']['PAYLOAD']);
145
145
  break;
146
146
  }
147
+ case 'SET_GIZMO_VISIBILITY': {
148
+ returnValue = this.setGizmoVisibility(payload as Actions['SET_GIZMO_VISIBILITY']['PAYLOAD']);
149
+ break;
150
+ }
147
151
  case 'MODEL_LOADED': {
148
152
  returnValue = this.modelLoaded(payload as Actions['MODEL_LOADED']['PAYLOAD']);
149
153
  break;
@@ -380,6 +384,11 @@ export default class DIVECommunication {
380
384
  return true;
381
385
  }
382
386
 
387
+ private setGizmoVisibility(payload: Actions['SET_GIZMO_VISIBILITY']['PAYLOAD']): Actions['SET_GIZMO_VISIBILITY']['RETURN'] {
388
+ this.toolbox.SetGizmoVisibility(payload);
389
+ return payload;
390
+ }
391
+
383
392
  private modelLoaded(payload: Actions['MODEL_LOADED']['PAYLOAD']): Actions['MODEL_LOADED']['RETURN'] {
384
393
  (this.registered.get(payload.id) as COMModel).loaded = true;
385
394
  return true;
@@ -23,6 +23,7 @@ import '../actions/scene/getallscenedata';
23
23
  import '../actions/scene/setbackground';
24
24
  import '../actions/scene/updatescene';
25
25
  import '../actions/toolbox/select/setgizmomode';
26
+ import '../actions/toolbox/transform/setgizmovisible';
26
27
  import '../actions/camera/getcameratransform';
27
28
  import DIVEOrbitControls from '../../controls/OrbitControls';
28
29
  import { COMLight, COMModel, COMPov } from '../types';
@@ -122,6 +123,7 @@ const mockToolBox = {
122
123
  DetachGizmo: mockDetach,
123
124
  }),
124
125
  SetGizmoMode: jest.fn(),
126
+ SetGizmoVisibility: jest.fn(),
125
127
  } as unknown as DIVEToolbox;
126
128
 
127
129
  const mockMediaCreator = {
@@ -614,6 +616,14 @@ describe('dive/communication/DIVECommunication', () => {
614
616
  expect(success).toBe(true);
615
617
  });
616
618
 
619
+ it('should perform action SET_GIZMO_VISIBILITY', () => {
620
+ let visibility = testCom.PerformAction('SET_GIZMO_VISIBILITY', true);
621
+ expect(visibility).toBe(true);
622
+
623
+ visibility = testCom.PerformAction('SET_GIZMO_VISIBILITY', false);
624
+ expect(visibility).toBe(false);
625
+ });
626
+
617
627
  it('should perform action MODEL_LOADED', () => {
618
628
  const payload = {
619
629
  entityType: "model",
@@ -19,6 +19,7 @@ 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";
22
23
 
23
24
  export type Actions = {
24
25
  GET_ALL_SCENE_DATA: GET_ALL_SCENE_DATA,
@@ -39,6 +40,7 @@ export type Actions = {
39
40
  SET_CAMERA_LAYER: SET_CAMERA_LAYER,
40
41
  ZOOM_CAMERA: ZOOM_CAMERA,
41
42
  SET_GIZMO_MODE: SET_GIZMO_MODE,
43
+ SET_GIZMO_VISIBILITY: SET_GIZMO_VISIBILITY,
42
44
  MODEL_LOADED: MODEL_LOADED,
43
45
  UPDATE_SCENE: UPDATE_SCENE,
44
46
  GENERATE_MEDIA: GENERATE_MEDIA,
@@ -0,0 +1,4 @@
1
+ export default interface SET_GIZMO_VISIBILITY {
2
+ 'PAYLOAD': boolean,
3
+ 'RETURN': boolean,
4
+ }
@@ -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 });
@@ -64,6 +64,7 @@ jest.mock('three', () => {
64
64
  }
65
65
  this.add = jest.fn();
66
66
  this.children = [{
67
+ visible: true,
67
68
  material: {
68
69
  color: {},
69
70
  },
@@ -86,6 +87,9 @@ jest.mock('three', () => {
86
87
  return vec3;
87
88
  };
88
89
  this.mesh = new Mesh();
90
+ this.traverse = jest.fn((callback) => {
91
+ callback(this.children[0])
92
+ });
89
93
  return this;
90
94
  }),
91
95
  Box3: jest.fn(function () {
@@ -196,6 +200,11 @@ describe('dive/model/DIVEModel', () => {
196
200
  expect(() => model.SetScale({ x: 1, y: 1, z: 1 })).not.toThrow();
197
201
  });
198
202
 
203
+ it('should set visibility', () => {
204
+ const model = new Model();
205
+ expect(() => model.SetVisibility(true)).not.toThrow();
206
+ });
207
+
199
208
  it('should set to world origin', () => {
200
209
  const model = new Model();
201
210
  model.userData.id = 'something';
@@ -51,7 +51,7 @@ export default class DIVEModelRoot extends Object3D {
51
51
  if (object.position !== undefined) (sceneObject as Model).SetPosition(object.position);
52
52
  if (object.rotation !== undefined) (sceneObject as Model).SetRotation(object.rotation);
53
53
  if (object.scale !== undefined) (sceneObject as Model).SetScale(object.scale);
54
- if (object.visible !== undefined) (sceneObject as Model).visible = object.visible;
54
+ if (object.visible !== undefined) (sceneObject as Model).SetVisibility(object.visible);
55
55
  }
56
56
 
57
57
  public DeleteModel(object: Partial<COMModel>): void {
@@ -45,6 +45,7 @@ jest.mock('../../../../model/Model.ts', () => {
45
45
  this.SetPosition = mock_SetPosition;
46
46
  this.SetRotation = mock_SetRotation;
47
47
  this.SetScale = mock_SetScale;
48
+ this.SetVisibility = jest.fn();
48
49
  this.PlaceOnFloor = mock_PlaceOnFloor;
49
50
  this.removeFromParent = jest.fn();
50
51
  return this;
@@ -258,8 +258,8 @@ export default abstract class DIVEBaseTool {
258
258
  public onWheel(e: WheelEvent): void { }
259
259
 
260
260
  protected raycast(objects?: Object3D[]): Intersection[] {
261
- if (objects !== undefined) return this._raycaster.intersectObjects(objects, true);
262
- return this._raycaster.intersectObjects(this._scene.children, true);
261
+ if (objects !== undefined) return this._raycaster.intersectObjects(objects, true).filter(i => i.object.visible);
262
+ return this._raycaster.intersectObjects(this._scene.children, true).filter(i => i.object.visible);
263
263
  }
264
264
 
265
265
  private pointerWasDragged(): boolean {
@@ -69,6 +69,10 @@ export default class DIVEToolbox {
69
69
  this.selectTool.SetGizmoMode(mode);
70
70
  }
71
71
 
72
+ public SetGizmoVisibility(active: boolean): void {
73
+ this.selectTool.SetGizmoVisibility(active);
74
+ }
75
+
72
76
  public onPointerMove(e: PointerEvent): void {
73
77
  this.activeTool.onPointerMove(e);
74
78
  }
@@ -134,6 +134,7 @@ describe('dive/toolbox/DIVEBaseTool', () => {
134
134
  object: {
135
135
  uuid: 'uuid',
136
136
  isHoverable: true,
137
+ visible: true,
137
138
  } as Object3D & DIVEHoverable
138
139
  }
139
140
  ]
@@ -158,6 +159,7 @@ describe('dive/toolbox/DIVEBaseTool', () => {
158
159
  object: {
159
160
  uuid: 'uuid',
160
161
  isHoverable: true,
162
+ visible: true,
161
163
  onPointerEnter() {
162
164
  return;
163
165
  },
@@ -183,6 +185,7 @@ describe('dive/toolbox/DIVEBaseTool', () => {
183
185
  object: {
184
186
  uuid: 'uuid',
185
187
  isHoverable: true,
188
+ visible: true,
186
189
  onPointerOver() {
187
190
  return;
188
191
  }
@@ -193,6 +196,7 @@ describe('dive/toolbox/DIVEBaseTool', () => {
193
196
 
194
197
  toolBox['_hovered'] = {
195
198
  uuid: 'uuid',
199
+ visible: true,
196
200
  onPointerLeave() {
197
201
  return;
198
202
  },
@@ -215,6 +219,7 @@ describe('dive/toolbox/DIVEBaseTool', () => {
215
219
  object: {
216
220
  uuid: 'uuid2',
217
221
  isHoverable: true,
222
+ visible: true,
218
223
  onPointerEnter() {
219
224
  return;
220
225
  },
@@ -225,6 +230,7 @@ describe('dive/toolbox/DIVEBaseTool', () => {
225
230
 
226
231
  toolBox['_hovered'] = {
227
232
  uuid: 'uuid',
233
+ visible: true,
228
234
  onPointerLeave() {
229
235
  return;
230
236
  },
@@ -28,6 +28,7 @@ const mock_onPointerMove = jest.fn();
28
28
  const mock_onPointerUp = jest.fn();
29
29
  const mock_onWheel = jest.fn();
30
30
  const mock_SetGizmoMode = jest.fn();
31
+ const mock_SetGizmoVisibility = jest.fn();
31
32
 
32
33
  jest.mock('../select/SelectTool.ts', () => {
33
34
  return jest.fn(function () {
@@ -38,6 +39,7 @@ jest.mock('../select/SelectTool.ts', () => {
38
39
  this.onPointerUp = mock_onPointerUp;
39
40
  this.onWheel = mock_onWheel;
40
41
  this.SetGizmoMode = mock_SetGizmoMode;
42
+ this.SetGizmoVisibility = mock_SetGizmoVisibility;
41
43
  return this;
42
44
  });
43
45
  });
@@ -114,4 +116,10 @@ describe('dive/toolbox/DIVEToolBox', () => {
114
116
  toolBox.SetGizmoMode('translate');
115
117
  expect(mock_SetGizmoMode).toHaveBeenCalledTimes(1);
116
118
  });
119
+
120
+ it('should set gizmo active', () => {
121
+ const toolBox = new DIVEToolbox({} as DIVEScene, mockController);
122
+ toolBox.SetGizmoVisibility(true);
123
+ expect(mock_SetGizmoVisibility).toHaveBeenCalledTimes(1);
124
+ });
117
125
  });
@@ -47,13 +47,14 @@ export default class DIVESelectTool extends DIVETransformTool {
47
47
  if ('isMoveable' in selectable) {
48
48
  const movable = selectable as (Object3D & DIVESelectable & DIVEMoveable);
49
49
  this._gizmo.attach(movable);
50
+ this.SetGizmoVisibility(movable.visible);
50
51
  }
51
52
  }
52
53
 
53
54
  public onClick(e: PointerEvent): void {
54
55
  super.onClick(e);
55
56
 
56
- const first = this._raycaster.intersectObjects(this._scene.Root.children, true)[0];
57
+ const first = this._raycaster.intersectObjects(this._scene.Root.children, true).filter((intersect) => intersect.object.visible )[0];
57
58
  const selectable = this.findSelectableInterface(first?.object);
58
59
 
59
60
  // if nothing is hit
@@ -41,6 +41,7 @@ jest.mock('../../../controls/OrbitControls', () => {
41
41
  jest.mock('../../../scene/Scene', () => {
42
42
  return jest.fn(function () {
43
43
  this.add = jest.fn();
44
+ this.children = [];
44
45
  this.Root = {
45
46
  children: [],
46
47
  }
@@ -130,7 +131,15 @@ describe('dive/toolbox/select/DIVESelectTool', () => {
130
131
  });
131
132
 
132
133
  it('should execute onClick with hit', () => {
133
- mock_intersectObjects.mockReturnValueOnce([{ object: { uuid: 'test', parent: { name: 'this is the test scene root!!!', parent: null } } }]);
134
+ mock_intersectObjects.mockReturnValueOnce(
135
+ [{
136
+ object: {
137
+ uuid: 'test',
138
+ visible: true,
139
+ parent: { name: 'this is the test scene root!!!', parent: null }
140
+ }
141
+ }]
142
+ );
134
143
  const selectTool = new DIVESelectTool(mockScene, mockController);
135
144
  expect(() => selectTool.onClick({ offsetX: 0, offsetY: 0 } as PointerEvent)).not.toThrow();
136
145
  });
@@ -139,10 +148,10 @@ describe('dive/toolbox/select/DIVESelectTool', () => {
139
148
  const mock_onSelect = jest.fn();
140
149
 
141
150
  mock_intersectObjects.mockReturnValueOnce([{
142
-
143
151
  object: {
144
152
  isSelectable: true,
145
153
  onSelect: mock_onSelect,
154
+ visible: true,
146
155
  parent: {
147
156
  name: 'this is the test scene root!!!',
148
157
  parent: null,
@@ -152,6 +161,7 @@ describe('dive/toolbox/select/DIVESelectTool', () => {
152
161
  }]);
153
162
  const selectTool = new DIVESelectTool(mockScene, mockController);
154
163
  selectTool['_gizmo'].object = {
164
+ visible: true,
155
165
  isSelectable: true,
156
166
  uuid: 'test0',
157
167
  } as unknown as Object3D & DIVESelectable;
@@ -162,10 +172,10 @@ describe('dive/toolbox/select/DIVESelectTool', () => {
162
172
  const mock_onSelect = jest.fn();
163
173
 
164
174
  mock_intersectObjects.mockReturnValueOnce([{
165
-
166
175
  object: {
167
176
  isSelectable: true,
168
177
  onSelect: mock_onSelect,
178
+ visible: true,
169
179
  parent: {
170
180
  name: 'this is the test scene root!!!',
171
181
  parent: null,
@@ -50,6 +50,15 @@ export default class DIVETransformTool extends DIVEBaseTool {
50
50
  this._gizmo.mode = mode;
51
51
  }
52
52
 
53
+ public SetGizmoVisibility(active: boolean): void {
54
+ const contains = this._scene.children.includes(this._gizmo);
55
+ if (active && !contains) {
56
+ this._scene.add(this._gizmo);
57
+ } else if (!active && contains) {
58
+ this._scene.remove(this._gizmo);
59
+ }
60
+ }
61
+
53
62
  // public onPointerDown(e: PointerEvent): void {
54
63
  // super.onPointerDown(e);
55
64
 
@@ -41,9 +41,11 @@ jest.mock('../../../controls/OrbitControls', () => {
41
41
  jest.mock('../../../scene/Scene', () => {
42
42
  return jest.fn(function () {
43
43
  this.add = jest.fn();
44
+ this.remove = jest.fn();
44
45
  this.Root = {
45
46
  children: [],
46
47
  }
48
+ this.children = [];
47
49
  return this;
48
50
  });
49
51
  });
@@ -129,4 +131,14 @@ describe('dive/toolbox/select/DIVETransformTool', () => {
129
131
  const transformTool = new DIVETransformTool(mockScene, mockController);
130
132
  expect(() => transformTool.SetGizmoMode('translate')).not.toThrow();
131
133
  });
134
+
135
+ it('should set gizmo active', () => {
136
+ const transformTool = new DIVETransformTool(mockScene, mockController);
137
+ expect(() => transformTool.SetGizmoVisibility(true)).not.toThrow();
138
+
139
+ expect(mockScene.add).toBeCalled();
140
+
141
+ mockScene.children.includes = jest.fn().mockReturnValue(true);
142
+ expect(() => transformTool.SetGizmoVisibility(false)).not.toThrow();
143
+ });
132
144
  });