import * as THREE from 'three' import type { ITool } from './ITool.ts' import { watch } from 'vue' import type Viewport from '@/designer/Viewport.ts' import { Line2 } from 'three/examples/jsm/lines/Line2.js' import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry.js' import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js' /** * 选择工具,用于在设计器中显示选中对象的包围盒 */ export default class SelectInspect implements ITool { viewport: any material: LineMaterial selectionBox: Line2 constructor() { // 颜色变成黄 const color = 0xffff00 // 0xff0000 const lineWidth = 2 this.material = new LineMaterial({ color, linewidth: lineWidth }) } init(viewport: Viewport) { this.viewport = viewport this.viewport.watchList.push(watch(() => this.viewport.state.selectedObject, (selectedObject) => { if (this.selectionBox) { viewport.scene.remove(this.selectionBox) this.selectionBox.geometry.dispose() this.selectionBox = null } const expandAmount = 0.2 // 扩展包围盒的大小 if (selectedObject !== null) { // 避免某些蒙皮网格的帧延迟效应(e.g. Michelle.glb) selectedObject.updateWorldMatrix(false, true) const box = new THREE.Box3().setFromObject(selectedObject) box.expandByScalar(expandAmount) const size = new THREE.Vector3() box.getSize(size) const center = new THREE.Vector3() box.getCenter(center) // 创建包围盒几何体 const helperGeometry = new THREE.BoxGeometry(size.x, size.y, size.z) const edgesGeometry = new THREE.EdgesGeometry(helperGeometry) // 使用 LineGeometry 包装 edgesGeometry const lineGeom = new LineGeometry() //@ts-ignore lineGeom.setPositions(edgesGeometry.attributes.position.array) const selectionBox = new Line2(lineGeom, this.material) selectionBox.computeLineDistances() selectionBox.position.copy(center) selectionBox.name = 'selectionBox' this.selectionBox = selectionBox this.viewport.scene.add(selectionBox) } })) } destory() { // 销毁选择工具 if (this.selectionBox) { this.viewport.scene.remove(this.selectionBox) this.selectionBox.geometry.dispose() this.selectionBox = null } } }