@shopware-ag/dive
Version:
Shopware Spatial Framework
93 lines (74 loc) • 2.82 kB
text/typescript
import { type Object3D } from 'three';
import { type DIVEScene } from '../../scene/Scene.ts';
import DIVETransformTool from '../transform/TransformTool.ts';
import { findInterface } from '../../helper/findInterface/findInterface.ts';
import type DIVEOrbitControls from '../../controls/OrbitControls.ts';
import { type DIVESelectable } from '../../interface/Selectable.ts';
import { type DIVEMovable } from '../../interface/Movable.ts';
import { type DIVEBaseTool } from '../BaseTool.ts';
export const isSelectTool = (tool: DIVEBaseTool): tool is DIVESelectTool => {
return (tool as DIVESelectTool).isSelectTool !== 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 class DIVESelectTool extends DIVETransformTool {
readonly isSelectTool: boolean = true;
constructor(scene: DIVEScene, controller: DIVEOrbitControls) {
super(scene, controller);
this.name = 'SelectTool';
}
public Activate(): void {}
public Select(selectable: DIVESelectable): void {
this.AttachGizmo(selectable);
if (selectable.onSelect) selectable.onSelect();
}
public Deselect(selectable: DIVESelectable): void {
this.DetachGizmo();
if (selectable.onDeselect) selectable.onDeselect();
}
public AttachGizmo(selectable: DIVESelectable): void {
if ('isMovable' in selectable) {
const movable = selectable as Object3D &
DIVESelectable &
DIVEMovable;
this._gizmo.attach(movable);
this.SetGizmoVisibility(movable.visible);
}
}
public DetachGizmo(): void {
this._gizmo.detach();
}
public onClick(e: PointerEvent): void {
super.onClick(e);
const first = this._raycaster
.intersectObjects(this._scene.Root.children, true)
.filter((intersect) => intersect.object.visible)[0];
const selectable = findInterface<DIVESelectable>(
first?.object,
'isSelectable',
);
// if nothing is hit
if (!first || !selectable) {
if (this._gizmo.object) {
this.Deselect(this._gizmo.object as Object3D & DIVESelectable);
}
return;
}
if (this._gizmo.object) {
// do not reselect if the same object was clicked
if (this._gizmo.object.uuid === selectable.uuid) return;
// deselect previous object
this.Deselect(this._gizmo.object as Object3D & DIVESelectable);
}
// select clicked object
this.Select(selectable);
}
}