|
|
@ -9,7 +9,9 @@ import { getSetter } from '@/core/manager/ModuleManager.ts' |
|
|
import Constract from '@/core/Constract.ts' |
|
|
import Constract from '@/core/Constract.ts' |
|
|
import type { Object3DLike } from '@/types/ModelTypes.ts' |
|
|
import type { Object3DLike } from '@/types/ModelTypes.ts' |
|
|
import { PointManageWrap } from '@/core/manager/InstancePointManager.ts' |
|
|
import { PointManageWrap } from '@/core/manager/InstancePointManager.ts' |
|
|
import { drawOBBox, getAABBox, getOBBox } from '@/core/ModelUtils.ts' |
|
|
import { drawOBBox, drawOBBoxUseLineManager, getAABBox, getOBBox } from '@/core/ModelUtils.ts' |
|
|
|
|
|
import InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts' |
|
|
|
|
|
import LineSegmentManager from '@/core/manager/LineSegmentManager.ts' |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 选择工具,用于在设计器中显示选中对象的包围盒 |
|
|
* 选择工具,用于在设计器中显示选中对象的包围盒 |
|
|
@ -75,22 +77,26 @@ export default class SelectManager { |
|
|
// EventBus.on('multiselectedObjectChanged', this.updateMultiSelectionBoxes)
|
|
|
// EventBus.on('multiselectedObjectChanged', this.updateMultiSelectionBoxes)
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
redSelectionGroup = new THREE.Group() |
|
|
|
|
|
|
|
|
|
|
|
updateMultiSelectionBoxes = () => { |
|
|
updateMultiSelectionBoxes = () => { |
|
|
const multiSelectedObjects = this.viewport.state.multiSelectedObjects |
|
|
const multiSelectedItems = this.viewport.state.multiSelectedItems |
|
|
// 为所有多选对象创建包围盒线框
|
|
|
// 为所有多选对象创建包围盒线框
|
|
|
this.clearRedSelectionBoxes() |
|
|
this.redSelectionBoxManager.clear() |
|
|
|
|
|
|
|
|
if (!multiSelectedObjects || multiSelectedObjects.length === 0) { |
|
|
if (!multiSelectedItems || multiSelectedItems.length === 0) { |
|
|
return |
|
|
return |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
for (const object of multiSelectedObjects) { |
|
|
console.log('drawRedSelection', multiSelectedItems.length) |
|
|
if (object.userData.entityId) { |
|
|
for (const item of multiSelectedItems) { |
|
|
this.createRedSelectionBox(object) |
|
|
drawOBBoxUseLineManager(item.id + '_red', this.redSelectionBoxManager, item) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
get redSelectionBoxManager(): LineSegmentManager { |
|
|
|
|
|
const name = 'redSelectionBoxManager' |
|
|
|
|
|
return this.viewport.getOrCreateLineManager(name, () => |
|
|
|
|
|
new LineSegmentManager(name, this.viewport, this.redMaterial) |
|
|
|
|
|
) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 取消红选
|
|
|
// 取消红选
|
|
|
@ -185,62 +191,6 @@ export default class SelectManager { |
|
|
}) |
|
|
}) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 清除之前的红色包围盒线框
|
|
|
|
|
|
private clearRedSelectionBoxes() { |
|
|
|
|
|
if (this.redSelectionGroup.children.length > 0) { |
|
|
|
|
|
for (const child of this.redSelectionGroup.children) { |
|
|
|
|
|
this.redSelectionGroup.remove(child) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
this.viewport.scene.remove(this.redSelectionGroup) |
|
|
|
|
|
this.redSelectionGroup = new THREE.Group() |
|
|
|
|
|
this.viewport.scene.add(this.redSelectionGroup) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 创建红选包围盒
|
|
|
|
|
|
private createRedSelectionBox(object: Object3DLike) { |
|
|
|
|
|
// 如果对象没有 entityId,则不创建包围盒线框
|
|
|
|
|
|
if (!object.userData.entityId) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
let box: THREE.Box3 |
|
|
|
|
|
if (object instanceof PointManageWrap) { |
|
|
|
|
|
box = object.createBox3() |
|
|
|
|
|
|
|
|
|
|
|
} else if (object instanceof THREE.Object3D) { |
|
|
|
|
|
box = new THREE.Box3().setFromObject(object) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const min = box.min |
|
|
|
|
|
const max = box.max |
|
|
|
|
|
|
|
|
|
|
|
const corners = [ |
|
|
|
|
|
new THREE.Vector3(min.x - Constract.RED_EXPAND_AMOUNT, max.y + Constract.RED_EXPAND_AMOUNT, min.z - Constract.RED_EXPAND_AMOUNT), |
|
|
|
|
|
new THREE.Vector3(max.x + Constract.RED_EXPAND_AMOUNT, max.y + Constract.RED_EXPAND_AMOUNT, min.z - Constract.RED_EXPAND_AMOUNT), |
|
|
|
|
|
new THREE.Vector3(max.x + Constract.RED_EXPAND_AMOUNT, max.y + Constract.RED_EXPAND_AMOUNT, max.z + Constract.RED_EXPAND_AMOUNT), |
|
|
|
|
|
new THREE.Vector3(min.x - Constract.RED_EXPAND_AMOUNT, max.y + Constract.RED_EXPAND_AMOUNT, max.z + Constract.RED_EXPAND_AMOUNT) |
|
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
// 构建矩形边框(4 条边)
|
|
|
|
|
|
const positions = [] |
|
|
|
|
|
for (let i = 0; i < 4; i++) { |
|
|
|
|
|
const p1 = corners[i] |
|
|
|
|
|
const p2 = corners[(i + 1) % 4] |
|
|
|
|
|
positions.push(p1.x, p1.y, p1.z) |
|
|
|
|
|
positions.push(p2.x, p2.y, p2.z) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 创建几何体
|
|
|
|
|
|
const lineGeom = new LineGeometry() |
|
|
|
|
|
const vertices = new Float32Array(positions) |
|
|
|
|
|
lineGeom.setPositions(vertices) |
|
|
|
|
|
|
|
|
|
|
|
const selectionBox = new Line2(lineGeom, this.redMaterial) |
|
|
|
|
|
selectionBox.computeLineDistances() |
|
|
|
|
|
|
|
|
|
|
|
this.redSelectionGroup.add(selectionBox) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 更新选中对象的包围盒线框
|
|
|
// 更新选中对象的包围盒线框
|
|
|
private updateSelectionBox = () => { |
|
|
private updateSelectionBox = () => { |
|
|
this.clearSelectionBox() |
|
|
this.clearSelectionBox() |
|
|
@ -263,8 +213,7 @@ export default class SelectManager { |
|
|
|
|
|
|
|
|
// 销毁选择工具
|
|
|
// 销毁选择工具
|
|
|
this.clearSelectionBox() |
|
|
this.clearSelectionBox() |
|
|
this.disposeRect() |
|
|
this.calcSelectionRectAndDispose() |
|
|
this.clearRedSelectionBoxes() |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 清除当前选中对象的包围盒线框
|
|
|
// 清除当前选中对象的包围盒线框
|
|
|
@ -278,7 +227,7 @@ export default class SelectManager { |
|
|
|
|
|
|
|
|
private createRectangle = () => { |
|
|
private createRectangle = () => { |
|
|
if (this.rectangle !== null) { |
|
|
if (this.rectangle !== null) { |
|
|
this.disposeRect() |
|
|
this.calcSelectionRectAndDispose() |
|
|
} |
|
|
} |
|
|
if (this.recStartPos) { |
|
|
if (this.recStartPos) { |
|
|
// 创建矩形
|
|
|
// 创建矩形
|
|
|
@ -334,7 +283,7 @@ export default class SelectManager { |
|
|
|
|
|
|
|
|
private onMouseMove = (event: MouseEvent) => { |
|
|
private onMouseMove = (event: MouseEvent) => { |
|
|
if (!this.recStartPos) { |
|
|
if (!this.recStartPos) { |
|
|
this.disposeRect() |
|
|
this.calcSelectionRectAndDispose() |
|
|
} |
|
|
} |
|
|
// 更新矩形大小或重新生成矩形
|
|
|
// 更新矩形大小或重新生成矩形
|
|
|
const position = this.viewport.getClosestIntersection(event) |
|
|
const position = this.viewport.getClosestIntersection(event) |
|
|
@ -344,7 +293,7 @@ export default class SelectManager { |
|
|
|
|
|
|
|
|
private onMouseUp = (event: MouseEvent) => { |
|
|
private onMouseUp = (event: MouseEvent) => { |
|
|
if (event.button !== 0) return |
|
|
if (event.button !== 0) return |
|
|
this.disposeRect() |
|
|
this.calcSelectionRectAndDispose(event) |
|
|
const clickTime = this.clickTime |
|
|
const clickTime = this.clickTime |
|
|
this.clickTime = null |
|
|
this.clickTime = null |
|
|
if (Date.now() - clickTime < Constract.MOUSE_CLICK_DELAY) { |
|
|
if (Date.now() - clickTime < Constract.MOUSE_CLICK_DELAY) { |
|
|
@ -352,8 +301,15 @@ export default class SelectManager { |
|
|
const objects: Object3DLike[] = this.viewport.entityManager.getObjectByCanvasMouse(event) |
|
|
const objects: Object3DLike[] = this.viewport.entityManager.getObjectByCanvasMouse(event) |
|
|
if (objects.length > 0 && objects[0]?.userData?.entityId && objects[0]?.userData?.createType !== 'line') { |
|
|
if (objects.length > 0 && objects[0]?.userData?.entityId && objects[0]?.userData?.createType !== 'line') { |
|
|
console.log('mouseClick', objects) |
|
|
console.log('mouseClick', objects) |
|
|
|
|
|
|
|
|
|
|
|
if (event.ctrlKey) { |
|
|
|
|
|
// 按住 ctrl 键, 就是添加红选内容
|
|
|
|
|
|
this.appendOrRemoveRedSelection(objects[0]?.userData?.entityId) |
|
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
const object = objects[0] |
|
|
const object = objects[0] |
|
|
this.selectById(object.userData.entityId) |
|
|
this.selectById(object.userData.entityId) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
} else { |
|
|
} else { |
|
|
// 如果没有选中任何对象,清除选中状态
|
|
|
// 如果没有选中任何对象,清除选中状态
|
|
|
@ -362,21 +318,9 @@ export default class SelectManager { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private disposeRect = () => { |
|
|
private calcSelectionRectAndDispose = (evt?: MouseEvent) => { |
|
|
if (this.rectangle !== null) { |
|
|
if (this.rectangle !== null && evt) { |
|
|
// 查找在这个矩形内的所有有效业务对象,并将他们添加进 viewport.state.multiSelectedObjects
|
|
|
// 查找在这个矩形内的所有有效业务对象,并将他们添加进 viewport.state.multiSelectedObjects
|
|
|
this.calcRectangleObjectToState() |
|
|
|
|
|
this.viewport.scene.remove(this.rectangle) |
|
|
|
|
|
this.rectangle.geometry.dispose() |
|
|
|
|
|
this.rectangle = null |
|
|
|
|
|
} |
|
|
|
|
|
this.recStartPos = null |
|
|
|
|
|
this.viewport.controls.enabled = true // 启用控制器
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private calcRectangleObjectToState = () => { |
|
|
|
|
|
if (!this.rectangle || !this.recStartPos) return |
|
|
|
|
|
|
|
|
|
|
|
// 获取矩形的包围盒
|
|
|
// 获取矩形的包围盒
|
|
|
const box = new THREE.Box3().setFromObject(this.rectangle) |
|
|
const box = new THREE.Box3().setFromObject(this.rectangle) |
|
|
|
|
|
|
|
|
@ -385,39 +329,38 @@ export default class SelectManager { |
|
|
const startZ = box.min.z |
|
|
const startZ = box.min.z |
|
|
const endX = box.max.x |
|
|
const endX = box.max.x |
|
|
const endZ = box.max.z |
|
|
const endZ = box.max.z |
|
|
|
|
|
_.defer(() => { |
|
|
|
|
|
this.calcRedSelection(startX, startZ, endX, endZ, evt.ctrlKey) |
|
|
|
|
|
}) |
|
|
|
|
|
this.viewport.scene.remove(this.rectangle) |
|
|
|
|
|
this.rectangle.geometry.dispose() |
|
|
|
|
|
this.rectangle = null |
|
|
|
|
|
} |
|
|
|
|
|
this.recStartPos = null |
|
|
|
|
|
this.viewport.controls.enabled = true // 启用控制器
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 查找所有在矩形内的对象
|
|
|
private appendOrRemoveRedSelection(id: string) { |
|
|
const ids = this.viewport.itemFindManager.getItemsByRect(startX, startZ, endX, endZ) |
|
|
// 如果 id 包含在 this.viewport.state.multiSelectedEntityIds 中,则移除它, 否则 添加它
|
|
|
|
|
|
const multiSelectedEntityIds = this.viewport.state.multiSelectedEntityIds |
|
|
// 清空之前的多选对象
|
|
|
const index = _.indexOf(multiSelectedEntityIds, id) |
|
|
this.viewport.state.multiSelectedObjects = [] |
|
|
if (index > -1) { |
|
|
|
|
|
// 如果已经存在,则移除
|
|
|
// 遍历找到的对象,添加到多选对象中
|
|
|
multiSelectedEntityIds.splice(index, 1) |
|
|
const multiSelectedObjects = [] |
|
|
} else { |
|
|
const multiSelectedItems = [] |
|
|
// 否则添加
|
|
|
const multiSelectedEntityIds = [] |
|
|
|
|
|
for (const id of ids) { |
|
|
|
|
|
const object = this.viewport.entityManager.findObjectById(id) |
|
|
|
|
|
if (object.userData.entityId && object.userData.t) { |
|
|
|
|
|
const item = this.viewport.entityManager.findItemById(object.userData.entityId) |
|
|
|
|
|
if (item && item.dt.protected !== true) { |
|
|
|
|
|
multiSelectedObjects.push(object) |
|
|
|
|
|
multiSelectedItems.push(item) |
|
|
|
|
|
multiSelectedEntityIds.push(id) |
|
|
multiSelectedEntityIds.push(id) |
|
|
} |
|
|
} |
|
|
} |
|
|
this.multiSelectByIds(multiSelectedEntityIds) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 触发多选对象更新事件
|
|
|
private calcRedSelection = (startX, startZ, endX, endZ, isAppend: boolean = false) => { |
|
|
this.viewport.state.multiSelectedObjects = markRaw(multiSelectedObjects) |
|
|
// 查找所有在矩形内的对象
|
|
|
this.viewport.state.multiSelectedItems = markRaw(multiSelectedItems) |
|
|
const ids = this.viewport.itemFindManager.getItemsByRect(startX, startZ, endX, endZ) |
|
|
this.viewport.state.multiSelectedEntityIds = multiSelectedEntityIds |
|
|
|
|
|
EventBus.dispatch('multiSelectedObjectsChanged', { |
|
|
// 清空之前的多选对象
|
|
|
viewport: markRaw(this.viewport), |
|
|
const idsOrigin = isAppend ? this.viewport.state.multiSelectedEntityIds : [] |
|
|
multiSelectedObjects: this.viewport.state.multiSelectedObjects, |
|
|
this.multiSelectByIds(_.uniq(idsOrigin.concat(ids))) |
|
|
multiSelectedItems: this.viewport.state.multiSelectedItems, |
|
|
|
|
|
multiSelectedEntityIds: this.viewport.state.multiSelectedEntityIds |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|