@shopware-ag/dive
Version:
Shopware Spatial Framework
126 lines (101 loc) • 3.69 kB
text/typescript
import { Object3D, Vector3 } from 'three';
import {
AxesColorBlue,
AxesColorGreen,
AxesColorRed,
} from '../../constant/AxisHelperColors';
import { DIVEHoverable } from '../../interface/Hoverable';
import DIVEOrbitControls from '../../controls/OrbitControls';
import { DIVEScaleHandle } from '../handles/ScaleHandle';
import { DraggableEvent } from '../../toolbox/BaseTool';
import { DIVEGizmoAxis, DIVEGizmo } from '../Gizmo';
export class DIVEScaleGizmo extends Object3D implements DIVEHoverable {
readonly isHoverable: true = true;
public children: DIVEScaleHandle[];
private _controller: DIVEOrbitControls;
public set debug(value: boolean) {
this.children.forEach((child) => {
child.debug = value;
});
}
private _startScale: Vector3 | null;
constructor(controller: DIVEOrbitControls) {
super();
this.name = 'DIVEScaleGizmo';
this.children = [];
this._startScale = null;
this._controller = controller;
this.add(
new DIVEScaleHandle('x', 1, new Vector3(1, 0, 0), AxesColorRed),
);
this.add(
new DIVEScaleHandle('y', 1, new Vector3(0, 1, 0), AxesColorGreen),
);
this.add(
new DIVEScaleHandle('z', 1, new Vector3(0, 0, 1), AxesColorBlue),
);
}
public reset(): void {
this.children.forEach((child) => {
child.reset();
});
}
public update(scale: Vector3): void {
this.children.forEach((child) => {
child.update(scale);
});
}
private handleHighlight(
axis: DIVEGizmoAxis,
value: boolean,
dragged: boolean,
): void {
// Set highlight state for all handles.
this.children.forEach((child) => {
if (dragged) {
// Dragging has priority when it comes to highlighting.
child.highlight = child.axis === axis && dragged;
} else {
// If nothing is dragged, decide on hovered state.
child.highlight = child.axis === axis && value;
}
});
}
public onHoverAxis(handle: DIVEScaleHandle, value: boolean): void {
// If _startScale is set, it means there is a drag operation in progress.
// While dragging, we don't want to change the hover state.
if (this._startScale) return;
if (!this.parent) return;
if (!this.parent.parent) return;
(this.parent.parent as DIVEGizmo).onHover(
'translate',
handle.axis,
value,
);
this.handleHighlight(handle.axis, value, false);
}
public onAxisDragStart(handle: DIVEScaleHandle): void {
if (!this.parent) return;
if (!this.parent.parent) return;
const object = (this.parent.parent as DIVEGizmo).object;
if (!object) return;
this._startScale = object.scale.clone();
this.handleHighlight(handle.axis, true, true);
}
public onAxisDrag(axis: DIVEScaleHandle, e: DraggableEvent): void {
if (!this._startScale) return;
if (!this.parent) return;
if (!this.parent.parent) return;
if (!('onChange' in this.parent.parent)) return;
const delta = e.dragDelta.clone().projectOnVector(axis.forwardVector);
(this.parent.parent as DIVEGizmo).onChange(
undefined,
undefined,
this._startScale.clone().add(delta),
);
}
public onAxisDragEnd(handle: DIVEScaleHandle): void {
this._startScale = null;
this.handleHighlight(handle.axis, false, false);
}
}