UNPKG

@shopware-ag/dive

Version:

Shopware Spatial Framework

167 lines (138 loc) 5.33 kB
import { DIVEBaseTool } from '../BaseTool.ts'; import { type DIVEScene } from '../../scene/Scene.ts'; import type DIVEOrbitControls from '../../controls/OrbitControls.ts'; import { TransformControls } from 'three/examples/jsm/controls/TransformControls'; import { type DIVEMovable } from '../../interface/Movable.ts'; import { implementsInterface } from '../../helper/isInterface/implementsInterface.ts'; import { DIVEGizmo } from '../../gizmo/Gizmo.ts'; import { type Mesh, type MeshBasicMaterial } from 'three'; import { AxesColorBlue, AxesColorGreen, AxesColorRed, } from '../../constant/AxisHelperColors.ts'; export const isTransformTool = ( tool: DIVEBaseTool, ): tool is DIVETransformTool => { return (tool as DIVETransformTool).isTransformTool !== undefined; }; export interface DIVEObjectEventMap { select: object; } /** * A Tool to select and move objects in the scene. * * Objects have to implement the DIVESelectable interface to be selectable and DIVEMovable to be movable. * * @module */ export default class DIVETransformTool extends DIVEBaseTool { readonly isTransformTool: boolean = true; private _scaleLinked: boolean; protected _gizmo: TransformControls | DIVEGizmo; constructor(scene: DIVEScene, controller: DIVEOrbitControls) { super(scene, controller); this.name = 'DIVETransformTool'; this._scaleLinked = false; this._gizmo = this.initGizmo() as TransformControls; this._scene.add(this._gizmo); } public Activate(): void {} public SetGizmoMode(mode: 'translate' | 'rotate' | 'scale'): void { this._gizmo.mode = mode; } public SetGizmoVisibility(active: boolean): void { const contains = this._scene.children.includes(this._gizmo); if (active && !contains) { this._scene.add(this._gizmo); if ('isTransformControls' in this._gizmo) { (this._gizmo as TransformControls) .getRaycaster() .layers.enableAll(); } } else if (!active && contains) { this._scene.remove(this._gizmo); if ('isTransformControls' in this._gizmo) { (this._gizmo as TransformControls) .getRaycaster() .layers.disableAll(); } } } public SetGizmoScaleLinked(linked: boolean): void { this._scaleLinked = linked; } // only used for optimizing pointer events with DIVEGizmo // public onPointerDown(e: PointerEvent): void { // super.onPointerDown(e); // if (this._hovered) { // this._dragRaycastOnObjects = ( // this._gizmo as DIVEGizmo // ).gizmoPlane?.children; // } // } // only used for optimizing pointer events with DIVEGizmo // protected raycast(): Intersection[] { // return super.raycast((this._gizmo as DIVEGizmo).gizmoNode.children); // } private initGizmo(): TransformControls | DIVEGizmo { const g = new TransformControls( // this._controller, this._controller.object, this._controller.domElement, ); // g.debug = true; g.mode = 'translate'; g.traverse((child) => { if (!('isMesh' in child)) return; const material = (child as Mesh).material as MeshBasicMaterial; if (child.name === 'X') { material.color.set(AxesColorRed); } if (child.name === 'Y') { material.color.set(AxesColorGreen); } if (child.name === 'Z') { material.color.set(AxesColorBlue); } if (child.name === 'XY') { material.color.set(AxesColorBlue); } if (child.name === 'YZ') { material.color.set(AxesColorRed); } if (child.name === 'XZ') { material.color.set(AxesColorGreen); } }); // happens when pointerDown event is called on gizmo g.addEventListener('mouseDown', () => { this._controller.enabled = false; if (!implementsInterface<DIVEMovable>(g.object, 'isMovable')) return; if (!g.object.onMoveStart) return; g.object.onMoveStart(); }); // happens when pointerMove event is called on gizmo g.addEventListener('objectChange', () => { if (!implementsInterface<DIVEMovable>(g.object, 'isMovable')) return; if (!g.object.onMove) return; g.object.onMove(); if (this._scaleLinked) { const scale = g.object.scale; const averageScale = (scale.x + scale.y + scale.z) / 3; g.object.scale.set(averageScale, averageScale, averageScale); } }); // happens when pointerUp event is called on gizmo g.addEventListener('mouseUp', () => { this._controller.enabled = true; if (!implementsInterface<DIVEMovable>(g.object, 'isMovable')) return; if (!g.object.onMoveEnd) return; g.object.onMoveEnd(); }); return g; } }