@shopware-ag/dive 1.2.0 → 1.3.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/build/dive.cjs +288 -60
- package/build/dive.cjs.map +1 -1
- package/build/dive.d.cts +64 -6
- package/build/dive.d.ts +64 -6
- package/build/dive.js +289 -61
- package/build/dive.js.map +1 -1
- package/package.json +1 -1
- package/src/__test__/DIVE.test.ts +2 -0
- package/src/com/Communication.ts +6 -3
- package/src/com/__test__/Communication.test.ts +3 -6
- package/src/com/actions/object/getobjects.ts +2 -2
- package/src/dive.ts +7 -0
- package/src/gizmo/Gizmo.ts +130 -0
- package/src/gizmo/handles/AxisHandle.ts +124 -0
- package/src/gizmo/handles/RadialHandle.ts +119 -0
- package/src/gizmo/handles/ScaleHandle.ts +152 -0
- package/src/gizmo/plane/GizmoPlane.ts +85 -0
- package/src/gizmo/rotate/RotateGizmo.ts +95 -0
- package/src/gizmo/scale/ScaleGizmo.ts +97 -0
- package/src/gizmo/translate/TranslateGizmo.ts +88 -0
- package/src/interface/Draggable.ts +34 -0
- package/src/interface/Hoverable.ts +33 -0
- package/src/interface/Moveable.ts +0 -2
- package/src/interface/Selectable.ts +6 -0
- package/src/interface/__test__/Interfaces.test.ts +56 -0
- package/src/math/index.ts +3 -0
- package/src/math/signedAngleTo/__test__/signedAngleTo.test.ts +14 -0
- package/src/math/signedAngleTo/signedAngleTo.ts +13 -0
- package/src/scene/root/lightroot/LightRoot.ts +17 -3
- package/src/scene/root/lightroot/__test__/LightRoot.test.ts +12 -3
- package/src/scene/root/modelroot/ModelRoot.ts +17 -3
- package/src/scene/root/modelroot/__test__/ModelRoot.test.ts +13 -14
- package/src/toolbox/BaseTool.ts +254 -4
- package/src/toolbox/Toolbox.ts +6 -0
- package/src/toolbox/__test__/BaseTool.test.ts +389 -0
- package/src/toolbox/__test__/Toolbox.test.ts +8 -0
- package/src/toolbox/select/SelectTool.ts +29 -65
- package/src/toolbox/select/__test__/SelectTool.test.ts +57 -25
- package/src/toolbox/transform/TransformTool.ts +48 -0
|
@@ -160,6 +160,8 @@ describe('dive/DIVE', () => {
|
|
|
160
160
|
it('should instantiate', () => {
|
|
161
161
|
const dive = new DIVE();
|
|
162
162
|
expect(dive).toBeDefined();
|
|
163
|
+
expect((window as any).DIVE.PrintScene).toBeDefined();
|
|
164
|
+
expect(() => (window as any).DIVE.PrintScene()).not.toThrow();
|
|
163
165
|
});
|
|
164
166
|
|
|
165
167
|
it('should instantiate with settings', () => {
|
package/src/com/Communication.ts
CHANGED
|
@@ -210,12 +210,15 @@ export default class DIVECommunication {
|
|
|
210
210
|
}
|
|
211
211
|
|
|
212
212
|
private getObjects(payload: Actions['GET_OBJECTS']['PAYLOAD']): Actions['GET_OBJECTS']['RETURN'] {
|
|
213
|
+
if (payload.ids.length === 0) return [];
|
|
214
|
+
|
|
215
|
+
const objects: COMEntity[] = [];
|
|
213
216
|
this.registered.forEach((object) => {
|
|
214
|
-
if (
|
|
215
|
-
|
|
217
|
+
if (!payload.ids.includes(object.id)) return;
|
|
218
|
+
objects.push(object);
|
|
216
219
|
});
|
|
217
220
|
|
|
218
|
-
return
|
|
221
|
+
return objects;
|
|
219
222
|
}
|
|
220
223
|
|
|
221
224
|
private addObject(payload: Actions['ADD_OBJECT']['PAYLOAD']): Actions['ADD_OBJECT']['RETURN'] {
|
|
@@ -510,13 +510,10 @@ describe('dive/communication/DIVECommunication', () => {
|
|
|
510
510
|
} as COMPov;
|
|
511
511
|
testCom.PerformAction('ADD_OBJECT', mock1);
|
|
512
512
|
|
|
513
|
-
|
|
513
|
+
const successWithoutIds = testCom.PerformAction('GET_OBJECTS', { ids: [] });
|
|
514
|
+
expect(Array.from(successWithoutIds.values())).toStrictEqual([]);
|
|
514
515
|
|
|
515
|
-
const
|
|
516
|
-
expect(successWithoutIds).toStrictEqual(map);
|
|
517
|
-
|
|
518
|
-
map = new Map();
|
|
519
|
-
const successWithIds = testCom.PerformAction('GET_OBJECTS', { map, ids: ['test1'] });
|
|
516
|
+
const successWithIds = testCom.PerformAction('GET_OBJECTS', { ids: ['test1'] });
|
|
520
517
|
expect(Array.from(successWithIds.values())).toStrictEqual([{ entityType: "pov", id: "test1", position: { x: 0, y: 0, z: 0 }, target: { x: 0, y: 0, z: 0 } }]);
|
|
521
518
|
});
|
|
522
519
|
|
package/src/dive.ts
CHANGED
|
@@ -163,6 +163,13 @@ export default class DIVE {
|
|
|
163
163
|
|
|
164
164
|
// whene everything is done, start the renderer
|
|
165
165
|
this.renderer.StartRenderer(this.scene, this.perspectiveCamera);
|
|
166
|
+
|
|
167
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
168
|
+
(window as any).DIVE = {
|
|
169
|
+
PrintScene: () => {
|
|
170
|
+
console.log(this.scene);
|
|
171
|
+
},
|
|
172
|
+
}
|
|
166
173
|
}
|
|
167
174
|
|
|
168
175
|
// methods
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Euler, Object3D, Vector3 } from "three";
|
|
2
|
+
import { DIVERotateGizmo } from "./rotate/RotateGizmo";
|
|
3
|
+
import { DIVETranslateGizmo } from "./translate/TranslateGizmo";
|
|
4
|
+
import DIVEOrbitControls from "../controls/OrbitControls";
|
|
5
|
+
import { DIVEScaleGizmo } from "./scale/ScaleGizmo";
|
|
6
|
+
import { DIVEGizmoPlane as DIVEGizmoPlane } from "./plane/GizmoPlane";
|
|
7
|
+
import { DIVESelectable } from "../interface/Selectable";
|
|
8
|
+
|
|
9
|
+
export type DIVEGizmoMode = ('translate' | 'rotate' | 'scale');
|
|
10
|
+
|
|
11
|
+
export type DIVEGizmoAxis = 'x' | 'y' | 'z';
|
|
12
|
+
|
|
13
|
+
export class DIVEGizmo extends Object3D {
|
|
14
|
+
private _mode: DIVEGizmoMode;
|
|
15
|
+
public get mode(): DIVEGizmoMode {
|
|
16
|
+
return this._mode;
|
|
17
|
+
}
|
|
18
|
+
public set mode(value: DIVEGizmoMode) {
|
|
19
|
+
this._mode = value;
|
|
20
|
+
this.assemble();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private _gizmoNode: Object3D;
|
|
24
|
+
public get gizmoNode(): Object3D {
|
|
25
|
+
return this._gizmoNode;
|
|
26
|
+
}
|
|
27
|
+
private _translateGizmo: DIVETranslateGizmo;
|
|
28
|
+
private _rotateGizmo: DIVERotateGizmo;
|
|
29
|
+
private _scaleGizmo: DIVEScaleGizmo;
|
|
30
|
+
|
|
31
|
+
private _gizmoPlane: DIVEGizmoPlane;
|
|
32
|
+
public get gizmoPlane(): DIVEGizmoPlane {
|
|
33
|
+
return this._gizmoPlane;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// attachment stuff
|
|
37
|
+
private _object: (Object3D & DIVESelectable) | null;
|
|
38
|
+
public get object(): (Object3D & DIVESelectable) | null {
|
|
39
|
+
return this._object;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
constructor(controller: DIVEOrbitControls) {
|
|
43
|
+
super();
|
|
44
|
+
this.name = "DIVEGizmo";
|
|
45
|
+
|
|
46
|
+
controller.addEventListener('change', () => {
|
|
47
|
+
const size = controller.getDistance() / 2.5;
|
|
48
|
+
this.scale.set(size, size, size);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
this._mode = 'translate';
|
|
52
|
+
|
|
53
|
+
this._gizmoNode = new Object3D();
|
|
54
|
+
this.add(this._gizmoNode);
|
|
55
|
+
|
|
56
|
+
this._translateGizmo = new DIVETranslateGizmo(controller);
|
|
57
|
+
this._rotateGizmo = new DIVERotateGizmo(controller);
|
|
58
|
+
this._scaleGizmo = new DIVEScaleGizmo(controller);
|
|
59
|
+
|
|
60
|
+
this._gizmoPlane = new DIVEGizmoPlane();
|
|
61
|
+
this._gizmoPlane.visible = false;
|
|
62
|
+
|
|
63
|
+
this._object = null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public attach(object: (Object3D & DIVESelectable)): this {
|
|
67
|
+
this._object = object;
|
|
68
|
+
this.assemble();
|
|
69
|
+
return this;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
public detach(): this {
|
|
73
|
+
this._object = null;
|
|
74
|
+
this.assemble();
|
|
75
|
+
return this;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public onHover(mode: DIVEGizmoMode, axis: DIVEGizmoAxis, value: boolean): void {
|
|
79
|
+
if (!value) return;
|
|
80
|
+
this._gizmoPlane.assemble(mode, axis);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public onChange(position?: Vector3, rotation?: Euler, scale?: Vector3): void {
|
|
84
|
+
if (this.object === null) return;
|
|
85
|
+
|
|
86
|
+
if (position) {
|
|
87
|
+
this.position.copy(position);
|
|
88
|
+
this.object.position.copy(position);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (rotation) {
|
|
92
|
+
this.object.rotation.copy(rotation);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (scale) {
|
|
96
|
+
this.object.scale.copy(scale);
|
|
97
|
+
this._scaleGizmo.update(scale);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private assemble(): void {
|
|
102
|
+
// clear all children
|
|
103
|
+
this._gizmoNode.clear();
|
|
104
|
+
this._gizmoPlane.clear();
|
|
105
|
+
|
|
106
|
+
// reset all gizmos
|
|
107
|
+
this._translateGizmo.reset();
|
|
108
|
+
this._rotateGizmo.reset();
|
|
109
|
+
this._scaleGizmo.reset();
|
|
110
|
+
|
|
111
|
+
// check for object
|
|
112
|
+
if (this.object === null) return;
|
|
113
|
+
|
|
114
|
+
// add gizmos
|
|
115
|
+
if (this._mode === 'translate') {
|
|
116
|
+
this._gizmoNode.add(this._translateGizmo);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (this._mode === 'rotate') {
|
|
120
|
+
this._gizmoNode.add(this._rotateGizmo);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (this._mode === 'scale') {
|
|
124
|
+
this._gizmoNode.add(this._scaleGizmo);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// add plane for raycasting properly while dragging
|
|
128
|
+
this.add(this._gizmoPlane);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { Color, ColorRepresentation, CylinderGeometry, Mesh, MeshBasicMaterial, Object3D, Vector3 } from "three";
|
|
2
|
+
import { UI_LAYER_MASK } from "../../constant/VisibilityLayerMask";
|
|
3
|
+
import { DIVEHoverable } from "../../interface/Hoverable";
|
|
4
|
+
import { DIVETranslateGizmo } from "../translate/TranslateGizmo";
|
|
5
|
+
import { DIVEDraggable } from "../../interface/Draggable";
|
|
6
|
+
import { DraggableEvent } from "../../toolbox/BaseTool";
|
|
7
|
+
|
|
8
|
+
export class DIVEAxisHandle extends Object3D implements DIVEHoverable, DIVEDraggable {
|
|
9
|
+
readonly isHoverable: true = true;
|
|
10
|
+
readonly isDraggable: true = true;
|
|
11
|
+
|
|
12
|
+
public parent: DIVETranslateGizmo | null = null;
|
|
13
|
+
|
|
14
|
+
public axis: 'x' | 'y' | 'z';
|
|
15
|
+
|
|
16
|
+
private _color: Color = new Color(0xff00ff);
|
|
17
|
+
private _colorHover: Color;
|
|
18
|
+
private _hovered: boolean;
|
|
19
|
+
private _highlight: boolean;
|
|
20
|
+
public get highlight(): boolean {
|
|
21
|
+
return this._highlight;
|
|
22
|
+
}
|
|
23
|
+
public set highlight(highlight: boolean) {
|
|
24
|
+
this._highlight = highlight;
|
|
25
|
+
this._lineMaterial.color = this._highlight || this._hovered ? this._colorHover : this._color;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private _lineMaterial: MeshBasicMaterial;
|
|
29
|
+
|
|
30
|
+
public get forwardVector(): Vector3 {
|
|
31
|
+
return new Vector3(0, 0, 1).applyQuaternion(this.quaternion).normalize();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public get rightVector(): Vector3 {
|
|
35
|
+
return new Vector3(1, 0, 0).applyQuaternion(this.quaternion).normalize();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public get upVector(): Vector3 {
|
|
39
|
+
return new Vector3(0, 1, 0).applyQuaternion(this.quaternion).normalize();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
constructor(axis: 'x' | 'y' | 'z', length: number, direction: Vector3, color: ColorRepresentation) {
|
|
43
|
+
super();
|
|
44
|
+
|
|
45
|
+
this.name = "DIVEAxisHandle";
|
|
46
|
+
this.axis = axis;
|
|
47
|
+
|
|
48
|
+
this._color.set(color);
|
|
49
|
+
this._colorHover = this._color.clone().multiplyScalar(2);
|
|
50
|
+
|
|
51
|
+
this._highlight = false;
|
|
52
|
+
this._hovered = false;
|
|
53
|
+
|
|
54
|
+
// create line
|
|
55
|
+
const lineGeo = new CylinderGeometry(0.01, 0.01, length, 13);
|
|
56
|
+
this._lineMaterial = new MeshBasicMaterial({
|
|
57
|
+
color: color,
|
|
58
|
+
depthTest: false,
|
|
59
|
+
depthWrite: false,
|
|
60
|
+
});
|
|
61
|
+
const lineMesh = new Mesh(lineGeo, this._lineMaterial);
|
|
62
|
+
lineMesh.layers.mask = UI_LAYER_MASK;
|
|
63
|
+
lineMesh.renderOrder = Infinity;
|
|
64
|
+
lineMesh.rotateX(Math.PI / 2);
|
|
65
|
+
lineMesh.translateY(length / 2);
|
|
66
|
+
this.add(lineMesh);
|
|
67
|
+
|
|
68
|
+
// create collider
|
|
69
|
+
const collider = new CylinderGeometry(0.1, 0.1, length, 3);
|
|
70
|
+
const colliderMaterial = new MeshBasicMaterial({
|
|
71
|
+
color: 0xff00ff,
|
|
72
|
+
transparent: true,
|
|
73
|
+
opacity: 0.15,
|
|
74
|
+
depthTest: false,
|
|
75
|
+
depthWrite: false,
|
|
76
|
+
});
|
|
77
|
+
const colliderMesh = new Mesh(collider, colliderMaterial);
|
|
78
|
+
colliderMesh.visible = false;
|
|
79
|
+
colliderMesh.layers.mask = UI_LAYER_MASK;
|
|
80
|
+
colliderMesh.renderOrder = Infinity;
|
|
81
|
+
colliderMesh.rotateX(Math.PI / 2);
|
|
82
|
+
colliderMesh.translateY(length / 2);
|
|
83
|
+
this.add(colliderMesh);
|
|
84
|
+
|
|
85
|
+
this.rotateX(direction.y * -Math.PI / 2);
|
|
86
|
+
this.rotateY(direction.x * Math.PI / 2);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public reset(): void {
|
|
90
|
+
this._lineMaterial.color = this._color;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public onPointerEnter(): void {
|
|
94
|
+
this._hovered = true;
|
|
95
|
+
if (this.parent) {
|
|
96
|
+
this.parent.onHandleHover(this, true);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
public onPointerLeave(): void {
|
|
101
|
+
this._hovered = false;
|
|
102
|
+
if (this.parent) {
|
|
103
|
+
this.parent.onHandleHover(this, false);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public onDragStart(): void {
|
|
108
|
+
if (this.parent) {
|
|
109
|
+
this.parent.onHandleDragStart(this);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public onDrag(e: DraggableEvent): void {
|
|
114
|
+
if (this.parent) {
|
|
115
|
+
this.parent.onHandleDrag(this, e);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public onDragEnd(): void {
|
|
120
|
+
if (this.parent) {
|
|
121
|
+
this.parent.onHandleDragEnd(this);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { Color, ColorRepresentation, Mesh, MeshBasicMaterial, Object3D, TorusGeometry, Vector3 } from "three";
|
|
2
|
+
import { UI_LAYER_MASK } from "../../constant/VisibilityLayerMask";
|
|
3
|
+
import { DIVEHoverable } from "../../interface/Hoverable";
|
|
4
|
+
import { DraggableEvent } from "../../toolbox/BaseTool";
|
|
5
|
+
import { DIVERotateGizmo } from "../rotate/RotateGizmo";
|
|
6
|
+
import { DIVEDraggable } from "../../interface/Draggable";
|
|
7
|
+
|
|
8
|
+
export class DIVERadialHandle extends Object3D implements DIVEHoverable, DIVEDraggable {
|
|
9
|
+
readonly isHoverable: true = true;
|
|
10
|
+
readonly isDraggable: true = true;
|
|
11
|
+
|
|
12
|
+
public parent: DIVERotateGizmo | null = null;
|
|
13
|
+
|
|
14
|
+
public axis: 'x' | 'y' | 'z';
|
|
15
|
+
|
|
16
|
+
private _color: Color = new Color(0xff00ff);
|
|
17
|
+
private _colorHover: Color;
|
|
18
|
+
private _hovered: boolean;
|
|
19
|
+
private _highlight: boolean;
|
|
20
|
+
public get highlight(): boolean {
|
|
21
|
+
return this._highlight;
|
|
22
|
+
}
|
|
23
|
+
public set highlight(highlight: boolean) {
|
|
24
|
+
this._highlight = highlight;
|
|
25
|
+
this._lineMaterial.color = this._highlight || this._hovered ? this._colorHover : this._color;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private _lineMaterial: MeshBasicMaterial;
|
|
29
|
+
|
|
30
|
+
public get forwardVector(): Vector3 {
|
|
31
|
+
return new Vector3(0, 0, 1).applyQuaternion(this.quaternion).normalize();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public get rightVector(): Vector3 {
|
|
35
|
+
return new Vector3(1, 0, 0).applyQuaternion(this.quaternion).normalize();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public get upVector(): Vector3 {
|
|
39
|
+
return new Vector3(0, 1, 0).applyQuaternion(this.quaternion).normalize();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
constructor(axis: 'x' | 'y' | 'z', radius: number, arc: number, direction: Vector3, color: ColorRepresentation) {
|
|
43
|
+
super();
|
|
44
|
+
|
|
45
|
+
this.name = "DIVERadialHandle";
|
|
46
|
+
this.axis = axis;
|
|
47
|
+
|
|
48
|
+
this._color.set(color);
|
|
49
|
+
this._colorHover = this._color.clone().multiplyScalar(2);
|
|
50
|
+
this._hovered = false;
|
|
51
|
+
this._highlight = false;
|
|
52
|
+
|
|
53
|
+
// create line
|
|
54
|
+
const lineGeo = new TorusGeometry(radius, 0.01, 13, 48, arc);
|
|
55
|
+
this._lineMaterial = new MeshBasicMaterial({
|
|
56
|
+
color: color,
|
|
57
|
+
depthTest: false,
|
|
58
|
+
depthWrite: false,
|
|
59
|
+
});
|
|
60
|
+
const lineMesh = new Mesh(lineGeo, this._lineMaterial);
|
|
61
|
+
lineMesh.layers.mask = UI_LAYER_MASK;
|
|
62
|
+
lineMesh.renderOrder = Infinity;
|
|
63
|
+
this.add(lineMesh);
|
|
64
|
+
|
|
65
|
+
// create collider
|
|
66
|
+
const collider = new TorusGeometry(radius, 0.1, 3, 48, arc);
|
|
67
|
+
const colliderMaterial = new MeshBasicMaterial({
|
|
68
|
+
color: 0xff00ff,
|
|
69
|
+
transparent: true,
|
|
70
|
+
opacity: 0.15,
|
|
71
|
+
depthTest: false,
|
|
72
|
+
depthWrite: false,
|
|
73
|
+
});
|
|
74
|
+
const colliderMesh = new Mesh(collider, colliderMaterial);
|
|
75
|
+
colliderMesh.visible = false;
|
|
76
|
+
colliderMesh.layers.mask = UI_LAYER_MASK;
|
|
77
|
+
colliderMesh.renderOrder = Infinity;
|
|
78
|
+
|
|
79
|
+
this.add(colliderMesh);
|
|
80
|
+
|
|
81
|
+
this.lookAt(direction);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
public reset(): void {
|
|
85
|
+
this._lineMaterial.color = this._color;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
public onPointerEnter(): void {
|
|
89
|
+
this._hovered = true;
|
|
90
|
+
if (this.parent) {
|
|
91
|
+
this.parent.onHandleHover(this, true);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
public onPointerLeave(): void {
|
|
96
|
+
this._hovered = false;
|
|
97
|
+
if (this.parent) {
|
|
98
|
+
this.parent.onHandleHover(this, false);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
public onDragStart(): void {
|
|
103
|
+
if (this.parent) {
|
|
104
|
+
this.parent.onHandleDragStart(this);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public onDrag(e: DraggableEvent): void {
|
|
109
|
+
if (this.parent) {
|
|
110
|
+
this.parent.onHandleDrag(this, e);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
public onDragEnd(): void {
|
|
115
|
+
if (this.parent) {
|
|
116
|
+
this.parent.onHandleDragEnd(this);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { BoxGeometry, Color, ColorRepresentation, CylinderGeometry, Mesh, MeshBasicMaterial, Object3D, Vector3 } from "three";
|
|
2
|
+
import { UI_LAYER_MASK } from "../../constant/VisibilityLayerMask";
|
|
3
|
+
import { DIVEHoverable } from "../../interface/Hoverable";
|
|
4
|
+
import { DIVEScaleGizmo } from "../scale/ScaleGizmo";
|
|
5
|
+
import { DIVEDraggable } from "../../interface/Draggable";
|
|
6
|
+
import { DraggableEvent } from "../../toolbox/BaseTool";
|
|
7
|
+
|
|
8
|
+
export class DIVEScaleHandle extends Object3D implements DIVEHoverable, DIVEDraggable {
|
|
9
|
+
readonly isHoverable: true = true;
|
|
10
|
+
readonly isDraggable: true = true;
|
|
11
|
+
|
|
12
|
+
public parent: DIVEScaleGizmo | null = null;
|
|
13
|
+
|
|
14
|
+
public axis: 'x' | 'y' | 'z';
|
|
15
|
+
|
|
16
|
+
private _color: Color = new Color(0xff00ff);
|
|
17
|
+
private _colorHover: Color;
|
|
18
|
+
private _hovered: boolean;
|
|
19
|
+
private _highlight: boolean;
|
|
20
|
+
public get highlight(): boolean {
|
|
21
|
+
return this._highlight;
|
|
22
|
+
}
|
|
23
|
+
public set highlight(highlight: boolean) {
|
|
24
|
+
this._highlight = highlight;
|
|
25
|
+
this._lineMaterial.color = this._highlight || this._hovered ? this._colorHover : this._color;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private _lineMaterial: MeshBasicMaterial;
|
|
29
|
+
|
|
30
|
+
private _box: Mesh;
|
|
31
|
+
private _boxSize: number;
|
|
32
|
+
|
|
33
|
+
public get forwardVector(): Vector3 {
|
|
34
|
+
return new Vector3(0, 0, 1).applyQuaternion(this.quaternion).normalize();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public get rightVector(): Vector3 {
|
|
38
|
+
return new Vector3(1, 0, 0).applyQuaternion(this.quaternion).normalize();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public get upVector(): Vector3 {
|
|
42
|
+
return new Vector3(0, 1, 0).applyQuaternion(this.quaternion).normalize();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
constructor(axis: 'x' | 'y' | 'z', length: number, direction: Vector3, color: ColorRepresentation, boxSize: number = 0.05) {
|
|
46
|
+
super();
|
|
47
|
+
|
|
48
|
+
this.name = "DIVEScaleHandle";
|
|
49
|
+
this.axis = axis;
|
|
50
|
+
|
|
51
|
+
this._color.set(color);
|
|
52
|
+
this._colorHover = this._color.clone().multiplyScalar(2);
|
|
53
|
+
this._hovered = false;
|
|
54
|
+
this._highlight = false;
|
|
55
|
+
|
|
56
|
+
this._boxSize = boxSize;
|
|
57
|
+
|
|
58
|
+
// create line
|
|
59
|
+
const lineGeo = new CylinderGeometry(0.01, 0.01, length - boxSize / 2, 13);
|
|
60
|
+
this._lineMaterial = new MeshBasicMaterial({
|
|
61
|
+
color: color,
|
|
62
|
+
depthTest: false,
|
|
63
|
+
depthWrite: false,
|
|
64
|
+
});
|
|
65
|
+
const lineMesh = new Mesh(lineGeo, this._lineMaterial);
|
|
66
|
+
lineMesh.layers.mask = UI_LAYER_MASK;
|
|
67
|
+
lineMesh.renderOrder = Infinity;
|
|
68
|
+
lineMesh.rotateX(Math.PI / 2);
|
|
69
|
+
lineMesh.translateY(length / 2 - boxSize / 4);
|
|
70
|
+
this.add(lineMesh);
|
|
71
|
+
|
|
72
|
+
// create box
|
|
73
|
+
this._box = new Mesh(
|
|
74
|
+
new BoxGeometry(boxSize, boxSize, boxSize),
|
|
75
|
+
this._lineMaterial,
|
|
76
|
+
);
|
|
77
|
+
this._box.layers.mask = UI_LAYER_MASK;
|
|
78
|
+
this._box.renderOrder = Infinity;
|
|
79
|
+
this._box.rotateX(Math.PI / 2);
|
|
80
|
+
this._box.translateY(length - boxSize / 2);
|
|
81
|
+
this._box.rotateZ(direction.x * Math.PI / 2);
|
|
82
|
+
this._box.rotateX(direction.z * Math.PI / 2);
|
|
83
|
+
this.add(this._box);
|
|
84
|
+
|
|
85
|
+
// create collider
|
|
86
|
+
const collider = new CylinderGeometry(0.1, 0.1, length + boxSize / 2, 3);
|
|
87
|
+
const colliderMaterial = new MeshBasicMaterial({
|
|
88
|
+
color: 0xff00ff,
|
|
89
|
+
transparent: true,
|
|
90
|
+
opacity: 0.15,
|
|
91
|
+
depthTest: false,
|
|
92
|
+
depthWrite: false,
|
|
93
|
+
});
|
|
94
|
+
const colliderMesh = new Mesh(collider, colliderMaterial);
|
|
95
|
+
colliderMesh.visible = false;
|
|
96
|
+
colliderMesh.layers.mask = UI_LAYER_MASK;
|
|
97
|
+
colliderMesh.renderOrder = Infinity;
|
|
98
|
+
colliderMesh.rotateX(Math.PI / 2);
|
|
99
|
+
colliderMesh.translateY(length / 2);
|
|
100
|
+
this.add(colliderMesh);
|
|
101
|
+
|
|
102
|
+
this.rotateX(direction.y * -Math.PI / 2);
|
|
103
|
+
this.rotateY(direction.x * Math.PI / 2);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
public reset(): void {
|
|
107
|
+
this._lineMaterial.color = this._color;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
public update(scale: Vector3): void {
|
|
111
|
+
this._box.scale.copy(
|
|
112
|
+
new Vector3(1, 1, 1) // identity scale ...
|
|
113
|
+
.sub(this.forwardVector) // subtracted the forward vector ...
|
|
114
|
+
.add( // to then add ...
|
|
115
|
+
scale.clone() // the scale ...
|
|
116
|
+
.multiply(this.forwardVector) // that is scaled by the forward vector again to get the forward vector as the only direction
|
|
117
|
+
)
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
public onPointerEnter(): void {
|
|
122
|
+
this._hovered = true;
|
|
123
|
+
if (this.parent) {
|
|
124
|
+
this.parent.onHoverAxis(this, true);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public onPointerLeave(): void {
|
|
129
|
+
this._hovered = false;
|
|
130
|
+
if (this.parent) {
|
|
131
|
+
this.parent.onHoverAxis(this, false);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public onDragStart(): void {
|
|
136
|
+
if (this.parent) {
|
|
137
|
+
this.parent.onAxisDragStart(this);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
public onDrag(e: DraggableEvent): void {
|
|
142
|
+
if (this.parent) {
|
|
143
|
+
this.parent.onAxisDrag(this, e);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
public onDragEnd(): void {
|
|
148
|
+
if (this.parent) {
|
|
149
|
+
this.parent.onAxisDragEnd(this);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Mesh, MeshBasicMaterial, Object3D, PlaneGeometry } from "three";
|
|
2
|
+
import { UI_LAYER_MASK } from "../../constant/VisibilityLayerMask";
|
|
3
|
+
import { DIVEGizmoAxis, DIVEGizmoMode } from "../Gizmo";
|
|
4
|
+
|
|
5
|
+
export class DIVEGizmoPlane extends Object3D {
|
|
6
|
+
private _meshX: Mesh;
|
|
7
|
+
public get XPlane(): Mesh {
|
|
8
|
+
return this._meshX;
|
|
9
|
+
}
|
|
10
|
+
private _meshY: Mesh;
|
|
11
|
+
public get YPlane(): Mesh {
|
|
12
|
+
return this._meshY;
|
|
13
|
+
}
|
|
14
|
+
private _meshZ: Mesh;
|
|
15
|
+
public get ZPlane(): Mesh {
|
|
16
|
+
return this._meshZ;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
constructor() {
|
|
20
|
+
super();
|
|
21
|
+
this.name = "DIVEGizmoPlane";
|
|
22
|
+
|
|
23
|
+
const material = new MeshBasicMaterial({
|
|
24
|
+
transparent: true,
|
|
25
|
+
opacity: 0.15,
|
|
26
|
+
depthTest: false,
|
|
27
|
+
depthWrite: false,
|
|
28
|
+
side: 2,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const geoX = new PlaneGeometry(100, 100, 2, 2);
|
|
32
|
+
const matX = material.clone();
|
|
33
|
+
matX.color.set(0xff0000);
|
|
34
|
+
this._meshX = new Mesh(geoX, matX);
|
|
35
|
+
this._meshX.layers.mask = UI_LAYER_MASK;
|
|
36
|
+
this._meshX.rotateY(Math.PI / 2);
|
|
37
|
+
|
|
38
|
+
const geoY = new PlaneGeometry(100, 100, 2, 2);
|
|
39
|
+
const matY = material.clone();
|
|
40
|
+
matY.color.set(0x00ff00);
|
|
41
|
+
this._meshY = new Mesh(geoY, matY);
|
|
42
|
+
this._meshY.layers.mask = UI_LAYER_MASK;
|
|
43
|
+
this._meshY.rotateX(-Math.PI / 2);
|
|
44
|
+
|
|
45
|
+
const geoZ = new PlaneGeometry(100, 100, 2, 2);
|
|
46
|
+
const matZ = material.clone();
|
|
47
|
+
matZ.color.set(0x0000ff);
|
|
48
|
+
this._meshZ = new Mesh(geoZ, matZ);
|
|
49
|
+
this._meshZ.layers.mask = UI_LAYER_MASK;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public assemble(mode: DIVEGizmoMode, axis: DIVEGizmoAxis): void {
|
|
53
|
+
this.clear();
|
|
54
|
+
|
|
55
|
+
if (mode === 'translate' || mode === 'scale') {
|
|
56
|
+
switch (axis) {
|
|
57
|
+
case 'x':
|
|
58
|
+
this.add(this._meshY);
|
|
59
|
+
this.add(this._meshZ);
|
|
60
|
+
break;
|
|
61
|
+
case 'y':
|
|
62
|
+
this.add(this._meshX);
|
|
63
|
+
this.add(this._meshZ);
|
|
64
|
+
break;
|
|
65
|
+
case 'z':
|
|
66
|
+
this.add(this._meshX);
|
|
67
|
+
this.add(this._meshY);
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
} else if (mode === 'rotate') {
|
|
71
|
+
switch (axis) {
|
|
72
|
+
case 'x':
|
|
73
|
+
this.add(this._meshX);
|
|
74
|
+
break;
|
|
75
|
+
case 'y':
|
|
76
|
+
this.add(this._meshY);
|
|
77
|
+
break;
|
|
78
|
+
case 'z':
|
|
79
|
+
this.add(this._meshZ);
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
}
|
|
85
|
+
}
|