UNPKG

@pmndrs/handle

Version:

framework agnostic expandable handle implementation for threejs

87 lines (86 loc) 4 kB
import { BoxGeometry, CylinderGeometry, Euler, Group, Mesh, MeshBasicMaterial } from 'three'; import { handleXRayMaterialProperties, setupHandlesContextHoverMaterial } from '../material.js'; import { RegisteredHandle } from '../registered.js'; import { extractHandleTransformOptions } from '../utils.js'; const normalRotation = new Euler(0, 0, -Math.PI / 2); const invertedRotation = new Euler(0, 0, Math.PI / 2); export class AxisScaleHandle extends RegisteredHandle { invert; showHandleLine; constructor(context, axis, tagPrefix = '', invert = false, showHandleLine = true) { super(context, axis, tagPrefix, () => ({ scale: this.options, rotate: false, translate: 'as-scale', multitouch: false, })); this.invert = invert; this.showHandleLine = showHandleLine; } bind(defaultColor, defaultHoverColor, config) { const { options, disabled } = extractHandleTransformOptions(this.axis, config); if (options === false) { return undefined; } this.options = options; const rotation = this.invert ? invertedRotation : normalRotation; //visualization const visualizationHeadGroup = new Group(); visualizationHeadGroup.position.x = this.invert ? -0.5 : 0.5; visualizationHeadGroup.rotation.copy(rotation); this.add(visualizationHeadGroup); const material = new MeshBasicMaterial(handleXRayMaterialProperties); const cleanupHeadHover = setupHandlesContextHoverMaterial(this.context, material, this.tag, { color: defaultColor, hoverColor: defaultHoverColor, disabled, }); const visualizationHeadMesh = new Mesh(new BoxGeometry(0.08, 0.08, 0.08), material); visualizationHeadMesh.renderOrder = Infinity; visualizationHeadMesh.rotation.copy(rotation); visualizationHeadGroup.add(visualizationHeadMesh); let cleanupLineHover; let visualizationLineMesh; let visualizationLineGroup; if (this.showHandleLine) { visualizationLineGroup = new Group(); visualizationLineGroup.rotation.copy(rotation); this.add(visualizationLineGroup); const material = new MeshBasicMaterial(handleXRayMaterialProperties); cleanupLineHover = setupHandlesContextHoverMaterial(this.context, material, this.tag, { color: defaultColor, hoverColor: defaultHoverColor, disabled, }); visualizationLineMesh = new Mesh(new CylinderGeometry(0.0075, 0.0075, 0.5, 3), material); visualizationLineMesh.renderOrder = Infinity; visualizationLineMesh.position.y = 0.25; visualizationLineGroup.add(visualizationLineMesh); } //interaction const interactionGroup = new Group(); interactionGroup.visible = false; interactionGroup.rotation.copy(rotation); interactionGroup.position.x = this.invert ? -0.3 : 0.3; this.add(interactionGroup); const interactionMesh = new Mesh(new CylinderGeometry(0.2, 0, 0.5, 4)); interactionMesh.pointerEventsOrder = Infinity; interactionMesh.position.y = 0.04; interactionGroup.add(interactionMesh); const unregister = disabled ? undefined : this.context.registerHandle(this.store, interactionMesh, this.tag); return () => { material.dispose(); interactionMesh.geometry.dispose(); visualizationHeadMesh.geometry.dispose(); visualizationLineMesh?.geometry.dispose(); unregister?.(); cleanupHeadHover?.(); cleanupLineHover?.(); if (visualizationLineGroup != null) { this.remove(visualizationLineGroup); } this.remove(interactionGroup); this.remove(visualizationHeadGroup); }; } }