From 95871a724e327837efe1fa5038b3af3d47e8a259 Mon Sep 17 00:00:00 2001 From: luoyifan Date: Tue, 27 May 2025 19:58:04 +0800 Subject: [PATCH] =?UTF-8?q?Q=20=E5=BF=AB=E6=8D=B7=E9=94=AE=EF=BC=8C?= =?UTF-8?q?=E5=BF=AB=E9=80=9F=E6=B7=BB=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/designer/menus/EditMenu.ts | 3 +- .../model2DEditor/tools/MouseMoveInspect.ts | 25 +++++++++++++- src/model/ModelUtils.ts | 38 ++++++++++++++++++++++ src/model/itemType/Toolbox.ts | 14 +++++++- 4 files changed, 77 insertions(+), 3 deletions(-) diff --git a/src/designer/menus/EditMenu.ts b/src/designer/menus/EditMenu.ts index fa34631..e3df32f 100644 --- a/src/designer/menus/EditMenu.ts +++ b/src/designer/menus/EditMenu.ts @@ -1,6 +1,7 @@ import { renderIcon } from '@/utils/webutils.ts' import { defineMenu } from '@/runtime/DefineMenu.ts' import SvgCode from '@/components/icons/SvgCode' +import { quickCopyByMouse } from '@/model/ModelUtils.ts' export default defineMenu((menus) => { menus.insertChildren('modelFile', @@ -77,7 +78,7 @@ export default defineMenu((menus) => { { name: 'edit_append', label: '快速添加', tip: 'key-q', click() { - system.msg('快速添加') + quickCopyByMouse() } }, { diff --git a/src/designer/model2DEditor/tools/MouseMoveInspect.ts b/src/designer/model2DEditor/tools/MouseMoveInspect.ts index 6a46835..c95406d 100644 --- a/src/designer/model2DEditor/tools/MouseMoveInspect.ts +++ b/src/designer/model2DEditor/tools/MouseMoveInspect.ts @@ -1,7 +1,7 @@ import type Viewport from '@/designer/Viewport.ts' import type { ITool } from '@/designer/model2DEditor/tools/ITool.ts' -let pmFn +let pmFn, otFn, lvFn /** * 鼠标移动时,将鼠标位置的坐标转换为设计图上的坐标,并设置到 designer.mousePos 属性中 @@ -18,12 +18,29 @@ export default class MouseMoveInspect implements ITool { this.canvas = this.viewport.renderer.domElement as HTMLCanvasElement pmFn = this.mouseMove.bind(this) + otFn = this.mouseLv.bind(this) + lvFn = this.mouseLv.bind(this) this.canvas.addEventListener('pointermove', pmFn) + this.canvas.addEventListener('pointerout', otFn) + this.canvas.addEventListener('mouseleave', lvFn) } destory() { this.canvas.removeEventListener('pointermove', pmFn) pmFn = undefined + this.canvas.removeEventListener('pointerout', otFn) + otFn = undefined + this.canvas.removeEventListener('mouseleave', lvFn) + lvFn = undefined + } + + mouseLv() { + this.viewport.state.mouse.x = 0 + this.viewport.state.mouse.z = 0 + window['CurrentMouseInfo'] = { + x: 0, + z: 0 + } } mouseMove = _.throttle(function(this: MouseMoveInspect, event: MouseEvent) { @@ -36,5 +53,11 @@ export default class MouseMoveInspect implements ITool { this.viewport.state.mouse.x = point.x this.viewport.state.mouse.z = point.z + window['CurrentMouseInfo'] = { + viewport: this.viewport, + x: point.x, + z: point.z + } + }, 1) } \ No newline at end of file diff --git a/src/model/ModelUtils.ts b/src/model/ModelUtils.ts index 683f16f..40b2b39 100644 --- a/src/model/ModelUtils.ts +++ b/src/model/ModelUtils.ts @@ -2,6 +2,44 @@ import * as THREE from 'three' import type { ItemTypeDefineOption } from '@/model/itemType/ItemTypeDefine.ts' import type { ItemJson } from '@/model/WorldModelType.ts' import { getAllItemTypes, getItemTypeByName } from '@/runtime/DefineItemType.ts' +import type Viewport from '@/designer/Viewport.ts' +import type Toolbox from '@/model/itemType/Toolbox.ts' + +export function quickCopyByMouse() { + // 获取鼠标位置,查看鼠标是否在某个 viewport 的画布上,并取得该 viewport + const currentMouseInfo = window['CurrentMouseInfo'] + if (!currentMouseInfo?.viewport || !currentMouseInfo.x || !currentMouseInfo.z) { + system.msg('无法获取鼠标位置') + return + } + + // 从当前 mouse.x, mouse.z 获取地图坐标 + const viewport: Viewport = currentMouseInfo.viewport + const x = currentMouseInfo.x + const z = currentMouseInfo.z + + // 如果当前 x,y 命中在某条线上,以当前鼠标为点,插入一个这个线段的起点的相似点,连接两头的点。 + + // 如果不在线上,查找0.2米内的有效点 Object3D, 如果有,则以这个点为起点, 延伸同类型的点,并让他们相连 + findObject3DByCondition(viewport.scene, object => { + // 判断 object 是否是有效的 Object3D, 并且是当前 viewport 的对象 + if (object instanceof THREE.Object3D && object.visible && + object.userData.type && viewport.toolbox[object.userData.type]) { + + const toolbox: Toolbox = viewport.toolbox[object.userData.type] + + // 检查是否在 0.2 米内 + const distance = object.position.distanceTo(new THREE.Vector3(x, 0, z)) + if (distance < 0.2) { + // 找到一个有效点,执行复制操作 + toolbox.start(object) + system.msg('复制成功') + return true + } + } + return false + }) +} /** * 考虑吸附的情况下计算鼠标事件位置 diff --git a/src/model/itemType/Toolbox.ts b/src/model/itemType/Toolbox.ts index 00b88a2..4e59f07 100644 --- a/src/model/itemType/Toolbox.ts +++ b/src/model/itemType/Toolbox.ts @@ -182,6 +182,18 @@ export default abstract class Toolbox { return } + // 如果按下了 shift 键,则 point 的位置必须位于 startPoint 正上下方,或者正左右方 + if (this.startPoint && e.shiftKey) { + const startPos = this.startPoint.position + const dx = Math.abs(point.x - startPos.x) + const dz = Math.abs(point.z - startPos.z) + if (dx > dz) { + point.z = startPos.z + } else { + point.x = startPos.x + } + } + this.lastMovePosition = point // 在鼠标移动时绘制临时点 @@ -206,7 +218,7 @@ export default abstract class Toolbox { if (e.button === 2) { // 右键点击, 完成绘图操作 this.viewport.state.cursorMode = 'normal' - + this.stop() } else if (e.button === 0) { // 左键点击, 添加点