@shopware-ag/dive
Version:
Shopware Spatial Framework
145 lines (116 loc) • 3.91 kB
text/typescript
import { Euler, Object3D, Vector3 } from 'three';
import { DIVERotateGizmo } from './rotate/RotateGizmo';
import { DIVETranslateGizmo } from './translate/TranslateGizmo';
import DIVEOrbitControls from '../controls/OrbitControls';
import { DIVEScaleGizmo } from './scale/ScaleGizmo';
import { DIVEGizmoPlane as DIVEGizmoPlane } from './plane/GizmoPlane';
import { DIVESelectable } from '../interface/Selectable';
export type DIVEGizmoMode = 'translate' | 'rotate' | 'scale';
export type DIVEGizmoAxis = 'x' | 'y' | 'z';
export class DIVEGizmo extends Object3D {
private _mode: DIVEGizmoMode;
public get mode(): DIVEGizmoMode {
return this._mode;
}
public set mode(value: DIVEGizmoMode) {
this._mode = value;
this.assemble();
}
public set debug(value: boolean) {
this._translateGizmo.debug = value;
this._rotateGizmo.debug = value;
this._scaleGizmo.debug = value;
}
private _gizmoNode: Object3D;
public get gizmoNode(): Object3D {
return this._gizmoNode;
}
private _translateGizmo: DIVETranslateGizmo;
private _rotateGizmo: DIVERotateGizmo;
private _scaleGizmo: DIVEScaleGizmo;
private _gizmoPlane: DIVEGizmoPlane;
public get gizmoPlane(): DIVEGizmoPlane {
return this._gizmoPlane;
}
// attachment stuff
private _object: (Object3D & DIVESelectable) | null;
public get object(): (Object3D & DIVESelectable) | null {
return this._object;
}
constructor(controller: DIVEOrbitControls) {
super();
this.name = 'DIVEGizmo';
controller.addEventListener('change', () => {
const size = controller.getDistance() / 2.5;
this.scale.set(size, size, size);
});
this._mode = 'translate';
this._gizmoNode = new Object3D();
this.add(this._gizmoNode);
this._translateGizmo = new DIVETranslateGizmo(controller);
this._rotateGizmo = new DIVERotateGizmo(controller);
this._scaleGizmo = new DIVEScaleGizmo(controller);
this._gizmoPlane = new DIVEGizmoPlane();
this._gizmoPlane.visible = false;
this._object = null;
}
public attach(object: Object3D & DIVESelectable): this {
this._object = object;
this.assemble();
return this;
}
public detach(): this {
this._object = null;
this.assemble();
return this;
}
public onHover(
mode: DIVEGizmoMode,
axis: DIVEGizmoAxis,
value: boolean,
): void {
if (!value) return;
this._gizmoPlane.assemble(mode, axis);
}
public onChange(
position?: Vector3,
rotation?: Euler,
scale?: Vector3,
): void {
if (this.object === null) return;
if (position) {
this.position.copy(position);
this.object.position.copy(position);
}
if (rotation) {
this.object.rotation.copy(rotation);
}
if (scale) {
this.object.scale.copy(scale);
this._scaleGizmo.update(scale);
}
}
private assemble(): void {
// clear all children
this._gizmoNode.clear();
this._gizmoPlane.clear();
// reset all gizmos
this._translateGizmo.reset();
this._rotateGizmo.reset();
this._scaleGizmo.reset();
// check for object
if (this.object === null) return;
// add gizmos
if (this._mode === 'translate') {
this._gizmoNode.add(this._translateGizmo);
}
if (this._mode === 'rotate') {
this._gizmoNode.add(this._rotateGizmo);
}
if (this._mode === 'scale') {
this._gizmoNode.add(this._scaleGizmo);
}
// add plane for raycasting properly while dragging
this.add(this._gizmoPlane);
}
}