6 changed files with 106 additions and 40 deletions
@ -0,0 +1,76 @@ |
|||||
|
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 |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue