diff --git a/src/designer/menus/EditMenu.ts b/src/designer/menus/EditMenu.ts index 1f4b5ff..d8e84f0 100644 --- a/src/designer/menus/EditMenu.ts +++ b/src/designer/menus/EditMenu.ts @@ -1,7 +1,7 @@ import { renderIcon } from '@/utils/webutils.ts' import { defineMenu } from '@/runtime/DefineMenu.ts' import SvgCode from '@/components/icons/SvgCode' -import { escByKey, quickCopyByMouse } from '@/model/ModelUtils.ts' +import { escByKeyboard, quickCopyByMouse, deletePointByKeyboard } from '@/model/ModelUtils.ts' export default defineMenu((menus) => { menus.insertChildren('modelFile', @@ -57,7 +57,7 @@ export default defineMenu((menus) => { { name: 'delete', label: '删除', icon: SvgCode.delete, order: 7, tip: 'key-delete', divided: true, click() { - system.msg('删除') + deletePointByKeyboard() } }, { @@ -66,7 +66,7 @@ export default defineMenu((menus) => { { name: 'edit_property_esc', label: '取消', order: 1, tip: 'key-esc', click() { - escByKey() + escByKeyboard() } }, { diff --git a/src/model/ModelUtils.ts b/src/model/ModelUtils.ts index b0d3e24..4bd21f5 100644 --- a/src/model/ModelUtils.ts +++ b/src/model/ModelUtils.ts @@ -7,10 +7,45 @@ import { computeBoundsTree, disposeBoundsTree } from 'three-mesh-bvh' import { Vector2 } from 'three/src/math/Vector2' import type Toolbox from '@/model/itemType/Toolbox.ts' -export function escByKey() { +export function deletePointByKeyboard() { + const viewport: Viewport = window['viewport'] + if (!viewport) { + system.msg('没有找到当前视图') + return + } + + // 按下 Delete 键,删除当前选中的点 + if (!viewport.state.selectedObject) { + system.msg('没有选中任何点') + return + } + + const selectedObject = viewport.state.selectedObject + if (!(selectedObject instanceof THREE.Object3D)) { + system.msg('选中的对象不是有效的点') + return + } + + if(!selectedObject.userData?.type){ + system.msg('选中的对象没有类型信息') + return + } + + const toolbox: Toolbox = viewport.toolbox[selectedObject.userData.type] + if (!toolbox) { + system.msg('没有找到对应的工具箱') + return + } + + viewport.state.cursorMode = 'normal' + toolbox.deletePoint(selectedObject) +} + +export function escByKeyboard() { // 按下 ESC 键,取消当前操作 const viewport: Viewport = window['viewport'] if (!viewport) { + system.msg('没有找到当前视图') return } diff --git a/src/model/itemType/Toolbox.ts b/src/model/itemType/Toolbox.ts index 7b67120..caae638 100644 --- a/src/model/itemType/Toolbox.ts +++ b/src/model/itemType/Toolbox.ts @@ -64,7 +64,7 @@ export default abstract class Toolbox { return this._itemType } - mode: CursorMode + mode: string static TMP_TYPE = '_TMP' @@ -77,6 +77,30 @@ export default abstract class Toolbox { this.viewport.scene.add(object) } + deletePoint(point: THREE.Object3D): void { + const deletedPoints = _.remove(this.itemType.pointArray, (p) => p.uuid === point.uuid) + if (!deletedPoints || deletedPoints.length !== 1) { + console.warn('没有找到要删除的点:', point.uuid) + return + } + + // 删除点 + this.removeFromScene(point) + + // 如果是起始点,则清除起始点 + if (this.startPoint === point) { + this.startPoint = undefined + } + } + + removeFromScene(object: THREE.Object3D) { + if (object?.parent) { + object.parent.remove(object) + } else { + this.viewport.scene.remove(object) + } + } + /** * 单元工具初始化 */ diff --git a/src/model/itemType/ToolboxLine.ts b/src/model/itemType/ToolboxLine.ts index 7d5d9cc..60857d3 100644 --- a/src/model/itemType/ToolboxLine.ts +++ b/src/model/itemType/ToolboxLine.ts @@ -1,6 +1,8 @@ import * as THREE from 'three' import Toolbox from '@/model/itemType/Toolbox.ts' import type ItemTypeLine from '@/model/itemType/ItemTypeLine.ts' +import { findObject3DById } from '@/model/ModelUtils.ts' +import EventBus from '@/runtime/EventBus' /** * 线条工具箱 @@ -22,6 +24,9 @@ export default class ToolboxLine extends Toolbox { afterMoveTemplateLine(line: THREE.Mesh, startPoint: THREE.Object3D, endPoint: THREE.Object3D) { } + afterDeleteLine(line: THREE.Object3D, point: THREE.Object3D, relationPointIds: string[]) { + } + stop() { super.stop() @@ -35,6 +40,57 @@ export default class ToolboxLine extends Toolbox { this.itemType.createLine(this.viewport, this.viewport.scene, this.startPoint, point) } + /** + * 删除点 + */ + deletePoint(point: THREE.Object3D) { + const relationPointIds = [] + + const deletedPoints = _.remove(this.itemType.pointArray, (p) => p.uuid === point.uuid) + if (!deletedPoints || deletedPoints.length !== 1) { + console.warn('没有找到要删除的点:', point.uuid) + return + } + + if (this.viewport.state.selectedObject === point) { + // 如果当前选中的对象是要删除的点,则清除选中状态 + this.viewport.state.selectedObject = undefined + EventBus.$emit('objectChanged', { + viewport: this, + object: null + }) + } + + // 找出与这个点相关的其他点 + this.itemType.pointArray.forEach(p => { + if (p.userData.center) { + relationPointIds.push(..._.filter(p.userData.center, i => i === point.uuid)) + _.remove(p.userData.center, i => i === point.uuid) + + relationPointIds.push(..._.filter(p.userData.in, i => i === point.uuid)) + _.remove(p.userData.in, i => i === point.uuid) + + relationPointIds.push(..._.filter(p.userData.out, i => i === point.uuid)) + _.remove(p.userData.out, i => i === point.uuid) + } + }) + + // 找出与点相关的所有线 + _.forEach(point.userData.lines, (line) => { + const lineObject = findObject3DById(this.viewport.scene, line) + this.removeFromScene(lineObject) + this.afterDeleteLine(lineObject, point, relationPointIds) + }) + + // 从场景中删除点 + this.removeFromScene(point) + + // 如果是起始点,则清除起始点 + if (this.startPoint === point) { + this.startPoint = undefined + } + } + mousemove(e: MouseEvent): THREE.Vector3 | undefined { const point = super.mousemove(e) if (!point) { diff --git a/src/model/itemType/measure/MeasureToolbox.ts b/src/model/itemType/measure/MeasureToolbox.ts index 6f1b3f1..f68fe44 100644 --- a/src/model/itemType/measure/MeasureToolbox.ts +++ b/src/model/itemType/measure/MeasureToolbox.ts @@ -4,6 +4,7 @@ import { numberToString } from '@/utils/webutils.ts' import type Measure from './Measure.ts' import type { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer' import Toolbox from '@/model/itemType/Toolbox.ts' +import { findObject3DById } from '@/model/ModelUtils.ts' /** * 测量工具箱,用于处理测量相关的操作 @@ -50,6 +51,10 @@ export default class MeasureToolbox extends ToolboxLine { this.measure.group.add(object) } + removeFromScene(object: THREE.Object3D) { + this.measure.group.remove(object) + } + afterMoveTemplateLine(line: THREE.Mesh, startPoint: THREE.Object3D, endPoint: THREE.Object3D) { super.afterMoveTemplateLine(line, startPoint, endPoint) @@ -59,21 +64,33 @@ export default class MeasureToolbox extends ToolboxLine { const dist = p0.distanceTo(point) const label = `${numberToString(dist)} m` const position = new THREE.Vector3().addVectors(p0, point).multiplyScalar(0.5) - this.addOrUpdateTempLabel(label, position) + this.addOrUpdateTempLabel(line, label, position) + } + + afterDeleteLine(line: THREE.Object3D, point: THREE.Object3D, relationPointIds: string[]) { + super.afterDeleteLine(line, point, relationPointIds) + + // 删除临时标签 + if (line?.userData?.labelId) { + const label = findObject3DById(this.measure.group, line.userData.labelId) + this.removeFromScene(label) + } } /** * 添加或更新临时标签和位置 */ - addOrUpdateTempLabel(label: string, position: THREE.Vector3) { + addOrUpdateTempLabel(line: THREE.Mesh, label: string, position: THREE.Vector3) { if (!this.tempLabel) { this.tempLabel = this.measure.createLabel(label) this.tempLabel.name = MeasureToolbox.TMP_LABEL_NAME + this.tempLabel.uuid = THREE.MathUtils.generateUUID() this.tempLabel.userData = { mode: this.mode, type: Toolbox.TMP_TYPE } - this.viewport.scene.add(this.tempLabel) + line.userData.labelId = this.tempLabel.uuid + this.addToScene(this.tempLabel) } this.tempLabel.position.set(position.x, position.y, position.z) this.tempLabel.element.innerHTML = label