@shopware-ag/dive 1.17.0 → 1.17.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/build/dive.cjs +90 -45
- package/build/dive.cjs.map +1 -1
- package/build/dive.d.cts +38 -2
- package/build/dive.d.ts +38 -2
- package/build/dive.js +90 -45
- package/build/dive.js.map +1 -1
- package/package.json +2 -1
- package/src/com/Communication.ts +41 -0
- package/src/gizmo/Gizmo.ts +6 -0
- package/src/gizmo/handles/AxisHandle.ts +14 -8
- package/src/gizmo/handles/RadialHandle.ts +12 -6
- package/src/gizmo/handles/ScaleHandle.ts +14 -8
- package/src/gizmo/rotate/RotateGizmo.ts +6 -0
- package/src/gizmo/scale/ScaleGizmo.ts +6 -0
- package/src/gizmo/translate/TranslateGizmo.ts +6 -0
- package/src/model/Model.ts +7 -2
- package/src/model/__test__/Model.test.ts +48 -73
- package/src/primitive/Primitive.ts +7 -2
- package/src/primitive/__test__/Primitive.test.ts +25 -18
- package/src/toolbox/select/__test__/SelectTool.test.ts +32 -27
- package/src/toolbox/transform/TransformTool.ts +61 -53
- package/src/toolbox/transform/__test__/TransformTool.test.ts +27 -25
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shopware-ag/dive",
|
|
3
|
-
"version": "1.17.
|
|
3
|
+
"version": "1.17.2",
|
|
4
4
|
"description": "Shopware Spatial Framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./build/dive.cjs",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"globals": "^15.0.0",
|
|
45
45
|
"jest": "^29.7.0",
|
|
46
46
|
"jest-environment-jsdom": "^29.7.0",
|
|
47
|
+
"jest-junit": "^16.0.0",
|
|
47
48
|
"jsdom": "^24.0.0",
|
|
48
49
|
"prettier": "^3.3.3",
|
|
49
50
|
"prettier-plugin-multiline-arrays": "^3.0.6",
|
package/src/com/Communication.ts
CHANGED
|
@@ -457,6 +457,27 @@ export class DIVECommunication {
|
|
|
457
457
|
const deletedObject = this.registered.get(payload.id);
|
|
458
458
|
if (!deletedObject) return false;
|
|
459
459
|
|
|
460
|
+
// If the object has a parent, detach it first
|
|
461
|
+
if (deletedObject.parentId) {
|
|
462
|
+
// First detach from parent group
|
|
463
|
+
this.setParent({
|
|
464
|
+
object: { id: deletedObject.id },
|
|
465
|
+
parent: null,
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// If deleting a group, update all children to have no parent
|
|
470
|
+
if (deletedObject.entityType === 'group') {
|
|
471
|
+
this.registered.forEach((object) => {
|
|
472
|
+
if (object.parentId === deletedObject.id) {
|
|
473
|
+
this.updateObject({
|
|
474
|
+
id: object.id,
|
|
475
|
+
parentId: null,
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
|
|
460
481
|
// copy object to payload to use later
|
|
461
482
|
Object.assign(payload, deletedObject);
|
|
462
483
|
|
|
@@ -723,6 +744,11 @@ export class DIVECommunication {
|
|
|
723
744
|
if (payload.parent === null) {
|
|
724
745
|
// detach from current parent
|
|
725
746
|
this.scene.Root.attach(sceneObject);
|
|
747
|
+
// Update registration to reflect no parent
|
|
748
|
+
this.updateObject({
|
|
749
|
+
id: object.id,
|
|
750
|
+
parentId: null,
|
|
751
|
+
});
|
|
726
752
|
return true;
|
|
727
753
|
}
|
|
728
754
|
|
|
@@ -735,6 +761,11 @@ export class DIVECommunication {
|
|
|
735
761
|
if (!parent) {
|
|
736
762
|
// detach from current parent
|
|
737
763
|
this.scene.Root.attach(sceneObject);
|
|
764
|
+
// Update registration to reflect no parent
|
|
765
|
+
this.updateObject({
|
|
766
|
+
id: object.id,
|
|
767
|
+
parentId: null,
|
|
768
|
+
});
|
|
738
769
|
return true;
|
|
739
770
|
}
|
|
740
771
|
|
|
@@ -743,11 +774,21 @@ export class DIVECommunication {
|
|
|
743
774
|
if (!parentObject) {
|
|
744
775
|
// detach from current parent
|
|
745
776
|
this.scene.Root.attach(sceneObject);
|
|
777
|
+
// Update registration to reflect no parent
|
|
778
|
+
this.updateObject({
|
|
779
|
+
id: object.id,
|
|
780
|
+
parentId: null,
|
|
781
|
+
});
|
|
746
782
|
return true;
|
|
747
783
|
}
|
|
748
784
|
|
|
749
785
|
// attach to new parent
|
|
750
786
|
parentObject.attach(sceneObject);
|
|
787
|
+
// Update registration to reflect new parent
|
|
788
|
+
this.updateObject({
|
|
789
|
+
id: object.id,
|
|
790
|
+
parentId: parent.id,
|
|
791
|
+
});
|
|
751
792
|
return true;
|
|
752
793
|
}
|
|
753
794
|
|
package/src/gizmo/Gizmo.ts
CHANGED
|
@@ -20,6 +20,12 @@ export class DIVEGizmo extends Object3D {
|
|
|
20
20
|
this.assemble();
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
public set debug(value: boolean) {
|
|
24
|
+
this._translateGizmo.debug = value;
|
|
25
|
+
this._rotateGizmo.debug = value;
|
|
26
|
+
this._scaleGizmo.debug = value;
|
|
27
|
+
}
|
|
28
|
+
|
|
23
29
|
private _gizmoNode: Object3D;
|
|
24
30
|
public get gizmoNode(): Object3D {
|
|
25
31
|
return this._gizmoNode;
|
|
@@ -20,6 +20,10 @@ export class DIVEAxisHandle
|
|
|
20
20
|
readonly isHoverable: true = true;
|
|
21
21
|
readonly isDraggable: true = true;
|
|
22
22
|
|
|
23
|
+
public set debug(value: boolean) {
|
|
24
|
+
this._colliderMesh.visible = value;
|
|
25
|
+
}
|
|
26
|
+
|
|
23
27
|
public parent: DIVETranslateGizmo | null = null;
|
|
24
28
|
|
|
25
29
|
public axis: 'x' | 'y' | 'z';
|
|
@@ -39,6 +43,8 @@ export class DIVEAxisHandle
|
|
|
39
43
|
|
|
40
44
|
private _lineMaterial: MeshBasicMaterial;
|
|
41
45
|
|
|
46
|
+
private _colliderMesh: Mesh;
|
|
47
|
+
|
|
42
48
|
public get forwardVector(): Vector3 {
|
|
43
49
|
return new Vector3(0, 0, 1)
|
|
44
50
|
.applyQuaternion(this.quaternion)
|
|
@@ -89,7 +95,7 @@ export class DIVEAxisHandle
|
|
|
89
95
|
this.add(lineMesh);
|
|
90
96
|
|
|
91
97
|
// create collider
|
|
92
|
-
const
|
|
98
|
+
const colliderGeo = new CylinderGeometry(0.1, 0.1, length, 3);
|
|
93
99
|
const colliderMaterial = new MeshBasicMaterial({
|
|
94
100
|
color: 0xff00ff,
|
|
95
101
|
transparent: true,
|
|
@@ -97,13 +103,13 @@ export class DIVEAxisHandle
|
|
|
97
103
|
depthTest: false,
|
|
98
104
|
depthWrite: false,
|
|
99
105
|
});
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
this.add(
|
|
106
|
+
this._colliderMesh = new Mesh(colliderGeo, colliderMaterial);
|
|
107
|
+
this._colliderMesh.visible = false;
|
|
108
|
+
this._colliderMesh.layers.mask = UI_LAYER_MASK;
|
|
109
|
+
this._colliderMesh.renderOrder = Infinity;
|
|
110
|
+
this._colliderMesh.rotateX(Math.PI / 2);
|
|
111
|
+
this._colliderMesh.translateY(length / 2);
|
|
112
|
+
this.add(this._colliderMesh);
|
|
107
113
|
|
|
108
114
|
this.rotateX((direction.y * -Math.PI) / 2);
|
|
109
115
|
this.rotateY((direction.x * Math.PI) / 2);
|
|
@@ -20,6 +20,10 @@ export class DIVERadialHandle
|
|
|
20
20
|
readonly isHoverable: true = true;
|
|
21
21
|
readonly isDraggable: true = true;
|
|
22
22
|
|
|
23
|
+
public set debug(value: boolean) {
|
|
24
|
+
this._colliderMesh.visible = value;
|
|
25
|
+
}
|
|
26
|
+
|
|
23
27
|
public parent: DIVERotateGizmo | null = null;
|
|
24
28
|
|
|
25
29
|
public axis: 'x' | 'y' | 'z';
|
|
@@ -39,6 +43,8 @@ export class DIVERadialHandle
|
|
|
39
43
|
|
|
40
44
|
private _lineMaterial: MeshBasicMaterial;
|
|
41
45
|
|
|
46
|
+
private _colliderMesh: Mesh;
|
|
47
|
+
|
|
42
48
|
public get forwardVector(): Vector3 {
|
|
43
49
|
return new Vector3(0, 0, 1)
|
|
44
50
|
.applyQuaternion(this.quaternion)
|
|
@@ -87,7 +93,7 @@ export class DIVERadialHandle
|
|
|
87
93
|
this.add(lineMesh);
|
|
88
94
|
|
|
89
95
|
// create collider
|
|
90
|
-
const
|
|
96
|
+
const colliderGeo = new TorusGeometry(radius, 0.1, 3, 48, arc);
|
|
91
97
|
const colliderMaterial = new MeshBasicMaterial({
|
|
92
98
|
color: 0xff00ff,
|
|
93
99
|
transparent: true,
|
|
@@ -95,12 +101,12 @@ export class DIVERadialHandle
|
|
|
95
101
|
depthTest: false,
|
|
96
102
|
depthWrite: false,
|
|
97
103
|
});
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
104
|
+
this._colliderMesh = new Mesh(colliderGeo, colliderMaterial);
|
|
105
|
+
this._colliderMesh.visible = false;
|
|
106
|
+
this._colliderMesh.layers.mask = UI_LAYER_MASK;
|
|
107
|
+
this._colliderMesh.renderOrder = Infinity;
|
|
102
108
|
|
|
103
|
-
this.add(
|
|
109
|
+
this.add(this._colliderMesh);
|
|
104
110
|
|
|
105
111
|
this.lookAt(direction);
|
|
106
112
|
}
|
|
@@ -21,6 +21,10 @@ export class DIVEScaleHandle
|
|
|
21
21
|
readonly isHoverable: true = true;
|
|
22
22
|
readonly isDraggable: true = true;
|
|
23
23
|
|
|
24
|
+
public set debug(value: boolean) {
|
|
25
|
+
this._colliderMesh.visible = value;
|
|
26
|
+
}
|
|
27
|
+
|
|
24
28
|
public parent: DIVEScaleGizmo | null = null;
|
|
25
29
|
|
|
26
30
|
public axis: 'x' | 'y' | 'z';
|
|
@@ -40,6 +44,8 @@ export class DIVEScaleHandle
|
|
|
40
44
|
|
|
41
45
|
private _lineMaterial: MeshBasicMaterial;
|
|
42
46
|
|
|
47
|
+
private _colliderMesh: Mesh;
|
|
48
|
+
|
|
43
49
|
private _box: Mesh;
|
|
44
50
|
private _boxSize: number;
|
|
45
51
|
|
|
@@ -113,7 +119,7 @@ export class DIVEScaleHandle
|
|
|
113
119
|
this.add(this._box);
|
|
114
120
|
|
|
115
121
|
// create collider
|
|
116
|
-
const
|
|
122
|
+
const colliderGeo = new CylinderGeometry(
|
|
117
123
|
0.1,
|
|
118
124
|
0.1,
|
|
119
125
|
length + boxSize / 2,
|
|
@@ -126,13 +132,13 @@ export class DIVEScaleHandle
|
|
|
126
132
|
depthTest: false,
|
|
127
133
|
depthWrite: false,
|
|
128
134
|
});
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
this.add(
|
|
135
|
+
this._colliderMesh = new Mesh(colliderGeo, colliderMaterial);
|
|
136
|
+
this._colliderMesh.visible = false;
|
|
137
|
+
this._colliderMesh.layers.mask = UI_LAYER_MASK;
|
|
138
|
+
this._colliderMesh.renderOrder = Infinity;
|
|
139
|
+
this._colliderMesh.rotateX(Math.PI / 2);
|
|
140
|
+
this._colliderMesh.translateY(length / 2);
|
|
141
|
+
this.add(this._colliderMesh);
|
|
136
142
|
|
|
137
143
|
this.rotateX((direction.y * -Math.PI) / 2);
|
|
138
144
|
this.rotateY((direction.x * Math.PI) / 2);
|
|
@@ -15,6 +15,12 @@ export class DIVERotateGizmo extends Object3D {
|
|
|
15
15
|
|
|
16
16
|
private _controller: DIVEOrbitControls;
|
|
17
17
|
|
|
18
|
+
public set debug(value: boolean) {
|
|
19
|
+
this.children.forEach((child) => {
|
|
20
|
+
child.debug = value;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
18
24
|
private _startRot: Euler | null;
|
|
19
25
|
|
|
20
26
|
constructor(controller: DIVEOrbitControls) {
|
|
@@ -17,6 +17,12 @@ export class DIVEScaleGizmo extends Object3D implements DIVEHoverable {
|
|
|
17
17
|
|
|
18
18
|
private _controller: DIVEOrbitControls;
|
|
19
19
|
|
|
20
|
+
public set debug(value: boolean) {
|
|
21
|
+
this.children.forEach((child) => {
|
|
22
|
+
child.debug = value;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
20
26
|
private _startScale: Vector3 | null;
|
|
21
27
|
|
|
22
28
|
constructor(controller: DIVEOrbitControls) {
|
|
@@ -12,6 +12,12 @@ import { DraggableEvent } from '../../toolbox/BaseTool';
|
|
|
12
12
|
export class DIVETranslateGizmo extends Object3D {
|
|
13
13
|
private _controller: DIVEOrbitControls;
|
|
14
14
|
|
|
15
|
+
public set debug(value: boolean) {
|
|
16
|
+
this.children.forEach((child) => {
|
|
17
|
+
child.debug = value;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
15
21
|
public children: DIVEAxisHandle[];
|
|
16
22
|
|
|
17
23
|
private _startPos: Vector3 | null;
|
package/src/model/Model.ts
CHANGED
|
@@ -116,8 +116,13 @@ export class DIVEModel extends DIVENode {
|
|
|
116
116
|
const worldPos = this.getWorldPosition(this._positionWorldBuffer);
|
|
117
117
|
const oldWorldPos = worldPos.clone();
|
|
118
118
|
|
|
119
|
-
//
|
|
120
|
-
|
|
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;
|
|
121
126
|
|
|
122
127
|
// skip any action when the position did not change
|
|
123
128
|
if (worldPos.y === oldWorldPos.y) return;
|
|
@@ -9,9 +9,9 @@ import {
|
|
|
9
9
|
MeshStandardMaterial,
|
|
10
10
|
type Texture,
|
|
11
11
|
Color,
|
|
12
|
+
Object3D,
|
|
12
13
|
} from 'three';
|
|
13
14
|
import { type COMMaterial } from '../../com/types';
|
|
14
|
-
import { isTypeOnlyImportOrExportDeclaration } from 'typescript';
|
|
15
15
|
|
|
16
16
|
const intersectObjectsMock = jest.fn();
|
|
17
17
|
|
|
@@ -25,43 +25,43 @@ jest.mock('three', () => {
|
|
|
25
25
|
this.x = x;
|
|
26
26
|
this.y = y;
|
|
27
27
|
this.z = z;
|
|
28
|
-
this.copy = (vec3: Vector3) => {
|
|
28
|
+
this.copy = jest.fn((vec3: Vector3) => {
|
|
29
29
|
this.x = vec3.x;
|
|
30
30
|
this.y = vec3.y;
|
|
31
31
|
this.z = vec3.z;
|
|
32
32
|
return this;
|
|
33
|
-
};
|
|
34
|
-
this.set = (x: number, y: number, z: number) => {
|
|
33
|
+
});
|
|
34
|
+
this.set = jest.fn((x: number, y: number, z: number) => {
|
|
35
35
|
this.x = x;
|
|
36
36
|
this.y = y;
|
|
37
37
|
this.z = z;
|
|
38
38
|
return this;
|
|
39
|
-
};
|
|
40
|
-
this.multiply = (vec3: Vector3) => {
|
|
39
|
+
});
|
|
40
|
+
this.multiply = jest.fn((vec3: Vector3) => {
|
|
41
41
|
this.x *= vec3.x;
|
|
42
42
|
this.y *= vec3.y;
|
|
43
43
|
this.z *= vec3.z;
|
|
44
44
|
return this;
|
|
45
|
-
};
|
|
46
|
-
this.clone = () => {
|
|
45
|
+
});
|
|
46
|
+
this.clone = jest.fn(() => {
|
|
47
47
|
return new Vector3(this.x, this.y, this.z);
|
|
48
|
-
};
|
|
49
|
-
this.setY = (y: number) => {
|
|
48
|
+
});
|
|
49
|
+
this.setY = jest.fn((y: number) => {
|
|
50
50
|
this.y = y;
|
|
51
51
|
return this;
|
|
52
|
-
};
|
|
53
|
-
this.add = (vec3: Vector3) => {
|
|
52
|
+
});
|
|
53
|
+
this.add = jest.fn((vec3: Vector3) => {
|
|
54
54
|
this.x += vec3.x;
|
|
55
55
|
this.y += vec3.y;
|
|
56
56
|
this.z += vec3.z;
|
|
57
57
|
return this;
|
|
58
|
-
};
|
|
59
|
-
this.sub = (vec3: Vector3) => {
|
|
58
|
+
});
|
|
59
|
+
this.sub = jest.fn((vec3: Vector3) => {
|
|
60
60
|
this.x -= vec3.x;
|
|
61
61
|
this.y -= vec3.y;
|
|
62
62
|
this.z -= vec3.z;
|
|
63
63
|
return this;
|
|
64
|
-
};
|
|
64
|
+
});
|
|
65
65
|
return this;
|
|
66
66
|
}),
|
|
67
67
|
Object3D: jest.fn(function () {
|
|
@@ -83,14 +83,7 @@ jest.mock('three', () => {
|
|
|
83
83
|
};
|
|
84
84
|
this.add = jest.fn();
|
|
85
85
|
this.sub = jest.fn();
|
|
86
|
-
this.children = [
|
|
87
|
-
{
|
|
88
|
-
visible: true,
|
|
89
|
-
material: {
|
|
90
|
-
color: {},
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
];
|
|
86
|
+
this.children = [];
|
|
94
87
|
this.userData = {};
|
|
95
88
|
this.position = new Vector3();
|
|
96
89
|
this.rotation = {
|
|
@@ -105,12 +98,14 @@ jest.mock('three', () => {
|
|
|
105
98
|
z: 1,
|
|
106
99
|
set: jest.fn(),
|
|
107
100
|
};
|
|
108
|
-
this.localToWorld = (vec3: Vector3) => {
|
|
101
|
+
this.localToWorld = jest.fn((vec3: Vector3) => {
|
|
109
102
|
return vec3;
|
|
110
|
-
};
|
|
111
|
-
this.mesh = new Mesh();
|
|
103
|
+
});
|
|
112
104
|
this.traverse = jest.fn((callback) => {
|
|
113
|
-
callback(this
|
|
105
|
+
callback(this);
|
|
106
|
+
this.children.forEach((child: Object3D) => {
|
|
107
|
+
callback(child);
|
|
108
|
+
});
|
|
114
109
|
});
|
|
115
110
|
this.getWorldPosition = jest.fn(() => {
|
|
116
111
|
return this.position.clone();
|
|
@@ -136,11 +131,12 @@ jest.mock('three', () => {
|
|
|
136
131
|
return this;
|
|
137
132
|
}),
|
|
138
133
|
Mesh: jest.fn(function () {
|
|
134
|
+
this.isMesh = true;
|
|
139
135
|
this.geometry = {
|
|
140
136
|
computeBoundingBox: jest.fn(),
|
|
141
137
|
boundingBox: new Box3(),
|
|
142
138
|
};
|
|
143
|
-
this.material =
|
|
139
|
+
this.material = new MeshStandardMaterial();
|
|
144
140
|
this.castShadow = true;
|
|
145
141
|
this.receiveShadow = true;
|
|
146
142
|
this.layers = {
|
|
@@ -149,9 +145,9 @@ jest.mock('three', () => {
|
|
|
149
145
|
this.updateWorldMatrix = jest.fn();
|
|
150
146
|
this.traverse = jest.fn();
|
|
151
147
|
this.removeFromParent = jest.fn();
|
|
152
|
-
this.localToWorld = (vec3: Vector3) => {
|
|
148
|
+
this.localToWorld = jest.fn((vec3: Vector3) => {
|
|
153
149
|
return vec3;
|
|
154
|
-
};
|
|
150
|
+
});
|
|
155
151
|
return this;
|
|
156
152
|
}),
|
|
157
153
|
MeshStandardMaterial: jest.fn(function () {
|
|
@@ -181,33 +177,12 @@ jest.mock('../../com/Communication.ts', () => {
|
|
|
181
177
|
};
|
|
182
178
|
});
|
|
183
179
|
|
|
180
|
+
const object = new Object3D();
|
|
181
|
+
object.children.push(new Mesh());
|
|
182
|
+
|
|
184
183
|
const gltf = {
|
|
185
184
|
scene: {
|
|
186
|
-
|
|
187
|
-
isObject3D: true,
|
|
188
|
-
parent: null,
|
|
189
|
-
dispatchEvent: jest.fn(),
|
|
190
|
-
layers: {
|
|
191
|
-
mask: 0,
|
|
192
|
-
},
|
|
193
|
-
material: {},
|
|
194
|
-
updateWorldMatrix: jest.fn(),
|
|
195
|
-
children: [
|
|
196
|
-
{
|
|
197
|
-
castShadow: false,
|
|
198
|
-
receiveShadow: false,
|
|
199
|
-
layers: {
|
|
200
|
-
mask: 0,
|
|
201
|
-
},
|
|
202
|
-
children: [],
|
|
203
|
-
updateWorldMatrix: jest.fn(),
|
|
204
|
-
isMesh: true,
|
|
205
|
-
},
|
|
206
|
-
],
|
|
207
|
-
traverse: function (callback: (object: object) => void) {
|
|
208
|
-
callback(this);
|
|
209
|
-
},
|
|
210
|
-
removeFromParent: jest.fn(),
|
|
185
|
+
...object,
|
|
211
186
|
},
|
|
212
187
|
} as unknown as GLTF;
|
|
213
188
|
|
|
@@ -236,38 +211,38 @@ describe('dive/model/DIVEModel', () => {
|
|
|
236
211
|
});
|
|
237
212
|
|
|
238
213
|
it('should place on floor', () => {
|
|
214
|
+
model.SetModel(gltf);
|
|
215
|
+
|
|
239
216
|
const com = DIVECommunication.get('id')!;
|
|
240
217
|
const spyPerformAction = jest.spyOn(com, 'PerformAction');
|
|
241
218
|
|
|
242
219
|
model.userData.id = 'something';
|
|
220
|
+
model.position.set(0, 4, 0);
|
|
243
221
|
|
|
244
|
-
model['
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
222
|
+
jest.spyOn(model['_mesh']!, 'localToWorld').mockReturnValueOnce(
|
|
223
|
+
new Vector3(0, 2, 0),
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
const scene = {
|
|
227
|
+
parent: null,
|
|
228
|
+
Root: {
|
|
229
|
+
children: [
|
|
230
|
+
model,
|
|
231
|
+
],
|
|
232
|
+
},
|
|
233
|
+
} as unknown as DIVEScene;
|
|
234
|
+
scene.Root.parent = scene;
|
|
235
|
+
model.parent = scene.Root;
|
|
248
236
|
|
|
249
237
|
expect(() => model.PlaceOnFloor()).not.toThrow();
|
|
250
238
|
expect(spyPerformAction).toHaveBeenCalledWith(
|
|
251
239
|
'UPDATE_OBJECT',
|
|
252
240
|
expect.objectContaining({
|
|
253
241
|
position: expect.objectContaining({
|
|
254
|
-
y:
|
|
242
|
+
y: 2,
|
|
255
243
|
}),
|
|
256
244
|
}),
|
|
257
245
|
);
|
|
258
|
-
|
|
259
|
-
// skip any action when the position did not change
|
|
260
|
-
spyPerformAction.mockClear();
|
|
261
|
-
model.position.y = 1.5;
|
|
262
|
-
expect(() => model.PlaceOnFloor()).not.toThrow();
|
|
263
|
-
expect(spyPerformAction).not.toHaveBeenCalled();
|
|
264
|
-
|
|
265
|
-
// mock that the communication is not available
|
|
266
|
-
spyPerformAction.mockClear();
|
|
267
|
-
jest.spyOn(DIVECommunication, 'get').mockReturnValueOnce(undefined);
|
|
268
|
-
model.position.y = 0;
|
|
269
|
-
expect(() => model.PlaceOnFloor()).not.toThrow();
|
|
270
|
-
expect(spyPerformAction).not.toHaveBeenCalled();
|
|
271
246
|
});
|
|
272
247
|
|
|
273
248
|
it('should drop it', () => {
|
|
@@ -111,8 +111,13 @@ export class DIVEPrimitive extends DIVENode {
|
|
|
111
111
|
const worldPos = this.getWorldPosition(this._positionWorldBuffer);
|
|
112
112
|
const oldWorldPos = worldPos.clone();
|
|
113
113
|
|
|
114
|
-
//
|
|
115
|
-
|
|
114
|
+
// compute the bounding box
|
|
115
|
+
this._mesh?.geometry?.computeBoundingBox();
|
|
116
|
+
const meshBB = this._mesh?.geometry?.boundingBox;
|
|
117
|
+
|
|
118
|
+
// subtract the bounding box min y axis value from the world position y value
|
|
119
|
+
if (!meshBB || !this._mesh) return;
|
|
120
|
+
worldPos.y = worldPos.y - this._mesh.localToWorld(meshBB.min.clone()).y;
|
|
116
121
|
|
|
117
122
|
// skip any action when the position did not change
|
|
118
123
|
if (worldPos.y === oldWorldPos.y) return;
|
|
@@ -139,7 +139,15 @@ jest.mock('three', () => {
|
|
|
139
139
|
Mesh: jest.fn(function () {
|
|
140
140
|
this.geometry = {
|
|
141
141
|
computeBoundingBox: jest.fn(),
|
|
142
|
-
boundingBox:
|
|
142
|
+
boundingBox: {
|
|
143
|
+
min: new Vector3(0, 2, 0),
|
|
144
|
+
max: new Vector3(2, 4, 2),
|
|
145
|
+
getCenter: jest.fn(() => {
|
|
146
|
+
return new Vector3(0, 0, 0);
|
|
147
|
+
}),
|
|
148
|
+
expandByObject: jest.fn(),
|
|
149
|
+
setFromObject: jest.fn(),
|
|
150
|
+
},
|
|
143
151
|
};
|
|
144
152
|
this.material = {};
|
|
145
153
|
this.castShadow = true;
|
|
@@ -258,34 +266,33 @@ describe('dive/primitive/DIVEPrimitive', () => {
|
|
|
258
266
|
const spyPerformAction = jest.spyOn(com, 'PerformAction');
|
|
259
267
|
|
|
260
268
|
primitive.userData.id = 'something';
|
|
261
|
-
|
|
269
|
+
primitive.position.set(0, 2, 0);
|
|
262
270
|
primitive['_boundingBox'] = {
|
|
263
|
-
min: new Vector3(0,
|
|
264
|
-
|
|
271
|
+
min: new Vector3(0, -2, 0),
|
|
272
|
+
setFromObject: jest.fn(),
|
|
265
273
|
} as unknown as Box3;
|
|
266
274
|
|
|
275
|
+
const scene = {
|
|
276
|
+
parent: null,
|
|
277
|
+
Root: {
|
|
278
|
+
children: [
|
|
279
|
+
primitive,
|
|
280
|
+
],
|
|
281
|
+
},
|
|
282
|
+
} as unknown as DIVEScene;
|
|
283
|
+
scene.Root.parent = scene;
|
|
284
|
+
|
|
285
|
+
primitive.parent = scene.Root;
|
|
286
|
+
|
|
267
287
|
expect(() => primitive.PlaceOnFloor()).not.toThrow();
|
|
268
288
|
expect(spyPerformAction).toHaveBeenCalledWith(
|
|
269
289
|
'UPDATE_OBJECT',
|
|
270
290
|
expect.objectContaining({
|
|
271
291
|
position: expect.objectContaining({
|
|
272
|
-
y:
|
|
292
|
+
y: 0,
|
|
273
293
|
}),
|
|
274
294
|
}),
|
|
275
295
|
);
|
|
276
|
-
|
|
277
|
-
// skip any action when the position did not change
|
|
278
|
-
spyPerformAction.mockClear();
|
|
279
|
-
primitive.position.y = 1.5;
|
|
280
|
-
expect(() => primitive.PlaceOnFloor()).not.toThrow();
|
|
281
|
-
expect(spyPerformAction).not.toHaveBeenCalled();
|
|
282
|
-
|
|
283
|
-
// mock that the communication is not available
|
|
284
|
-
spyPerformAction.mockClear();
|
|
285
|
-
jest.spyOn(DIVECommunication, 'get').mockReturnValueOnce(undefined);
|
|
286
|
-
primitive.position.y = 0;
|
|
287
|
-
expect(() => primitive.PlaceOnFloor()).not.toThrow();
|
|
288
|
-
expect(spyPerformAction).not.toHaveBeenCalled();
|
|
289
296
|
});
|
|
290
297
|
|
|
291
298
|
it('should drop it', () => {
|