Browse Source

Merge remote-tracking branch 'origin/master'

master
liupeng 7 months ago
parent
commit
aa02163d5d
  1. 48
      src/designer/Viewport.ts
  2. 4
      src/designer/model2DEditor/EsDragControls.ts
  3. 2
      src/designer/model2DEditor/tools/ITool.ts
  4. 3
      src/designer/model2DEditor/tools/MouseMoveInspect.ts
  5. 195
      src/designer/model2DEditor/tools/SelectInspect.ts
  6. 11
      src/model/itemType/ItemTypeLine.ts

48
src/designer/Viewport.ts

@ -6,18 +6,16 @@ import Stats from 'three/examples/jsm/libs/stats.module'
import type WorldModel from '@/model/WorldModel.ts'
import $ from 'jquery'
import { reactive, watch } from 'vue'
import MouseMoveInspect from '@/designer/model2DEditor/tools/MouseMoveInspect.ts'
import type { ITool } from '@/designer/model2DEditor/tools/ITool.ts'
import { CSS3DRenderer } from 'three/examples/jsm/renderers/CSS3DRenderer'
import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer'
import { getAllItemTypes } from '@/runtime/DefineItemType.ts'
import type { ItemTypeDefineOption } from '@/model/itemType/ItemTypeDefine.ts'
import type Toolbox from '@/model/itemType/Toolbox.ts'
import { calcPositionUseSnap } from '@/model/ModelUtils.ts'
import textureUrl from '@/assets/images/conveyor/shapes/Belt1.png'
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'
import SelectInspect from '@/designer/model2DEditor/tools/SelectInspect.ts'
import MouseMoveInspect from '@/designer/model2DEditor/tools/MouseMoveInspect.ts'
/**
*
@ -41,7 +39,8 @@ export default class Viewport {
toolStartObject: THREE.Object3D | null = null
currentTool: Toolbox | null = null
tools: ITool[] = [
new MouseMoveInspect()
new MouseMoveInspect(),
new SelectInspect()
]
toolbox: Record<string, Toolbox> = {}
@ -63,6 +62,7 @@ export default class Viewport {
currentFloor: '',
isReady: false,
cursorMode: 'normal',
selectedObject: null,
camera: {
position: { x: 0, y: 0, z: 0 },
rotation: { x: 0, y: 0, z: 0 }
@ -209,35 +209,8 @@ export default class Viewport {
}
this.updateGridVisibility()
}))
this.watchList.push(watch(() => this.state.cursorMode, (newVal: CursorMode) => {
if (!this.state.isReady) {
return
}
if (this.currentTool) {
this.currentTool.stop()
this.currentTool = null
}
if (newVal === 'normal' || !newVal) {
this.dragControl.dragControls.enabled = true
return
}
const currentTool = this.toolbox[newVal]
if (currentTool) {
// 选择标尺工具
this.currentTool = currentTool
this.dragControl.dragControls.enabled = false
} else {
system.showErrorDialog(`当前鼠标模式 ${newVal} 不支持`)
}
if (this.currentTool) {
this.currentTool.start(this.toolStartObject)
this.toolStartObject = null
}
}))
// 监听窗口大小变化
if (this.resizeObserver) {
this.resizeObserver.unobserve(this.viewerDom)
}
@ -252,7 +225,7 @@ export default class Viewport {
tool.init(this)
}
// 触发所有物品类型的 afterAddViewport 方法
_.forEach(getAllItemTypes(), (itemType: ItemTypeDefineOption) => {
itemType.clazz.afterAddViewport(this)
})
@ -495,6 +468,11 @@ export interface ViewportState {
cursorMode: CursorMode,
/**
*
*/
selectedObject: THREE.Object3D | null
/**
*
*/
camera: {

4
src/designer/model2DEditor/EsDragControls.ts

@ -4,6 +4,7 @@ import type Viewport from '@/designer/Viewport.ts'
import Constract from '@/designer/Constract.ts'
import { getItemTypeByName } from '@/runtime/DefineItemType.ts'
import type { ItemTypeDefineOption } from '@/model/itemType/ItemTypeDefine.ts'
import { markRaw } from 'vue'
// dragControls 绑定函数
let dragStartFn, dragFn, dragEndFn, clickblankFn
@ -114,6 +115,9 @@ export default class EsDragControls {
if (e.object.userData.onClick) {
e.object.userData.onClick(e)
}
if (e.object.userData.selectable) {
this.viewport.state.selectedObject = markRaw(e.object)
}
}
if (e.object.userData?.type) {

2
src/designer/model2DEditor/tools/ITool.ts

@ -2,4 +2,6 @@ export interface ITool {
init(viewport: any): void
destory(): void
animate?: () => void;
}

3
src/designer/model2DEditor/tools/MouseMoveInspect.ts

@ -70,4 +70,7 @@ export default class MouseMoveInspect implements ITool {
}
}, 1)
animate(): void {
}
}

195
src/designer/model2DEditor/tools/SelectInspect.ts

@ -0,0 +1,195 @@
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'
let pdFn, pmFn, puFn
/**
*
*/
export default class SelectInspect implements ITool {
viewport: Viewport
/**
* 线
*/
material: LineMaterial = new LineMaterial({ color: 0xffff00, linewidth: 2 })
/**
*
*/
rectMaterial: THREE.MeshBasicMaterial = new THREE.MeshBasicMaterial({
color: 0x000000,
opacity: 0.5,
transparent: true
})
/**
*
*/
rectangle: THREE.Mesh | null = null
/**
* 线
*/
selectionBox: Line2
/**
* , viewport.renderer.domElement
*/
canvas: HTMLCanvasElement
/**
*
*/
recStartPos: THREE.Vector3 | null
constructor() {
}
init(viewport: Viewport) {
this.viewport = viewport
this.canvas = this.viewport.renderer.domElement as HTMLCanvasElement
pdFn = this.onMouseDown.bind(this)
this.canvas.addEventListener('pointerdown', pdFn)
pmFn = this.onMouseMove.bind(this)
this.canvas.addEventListener('pointermove', pmFn)
puFn = this.onMouseUp.bind(this)
this.canvas.addEventListener('pointerup', puFn)
this.viewport.watchList.push(watch(() => this.viewport.state.selectedObject, (selectedObject) => {
this.disposeSelectionBox()
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() {
this.canvas.removeEventListener('pointerdown', pdFn)
pdFn = undefined
this.canvas.removeEventListener('pointermove', pmFn)
pmFn = undefined
this.canvas.removeEventListener('pointerup', puFn)
puFn = undefined
// 销毁选择工具
this.disposeSelectionBox()
this.disposeRect()
}
disposeSelectionBox() {
if (this.selectionBox) {
this.viewport.scene.remove(this.selectionBox)
this.selectionBox.geometry.dispose()
this.selectionBox = null
}
}
createRectangle() {
if (this.rectangle !== null) {
this.disposeRect()
}
if (this.recStartPos) {
// 创建矩形
this.rectangle = new THREE.Mesh(
new THREE.PlaneGeometry(1, 1),
this.rectMaterial
)
this.rectangle.name = 'selectRectangle'
this.rectangle.rotation.x = -Math.PI / 2 // 关键!让平面正对相机
this.rectangle.position.set(
this.recStartPos.x,
this.recStartPos.y,
this.recStartPos.z
)
this.viewport.scene.add(this.rectangle)
}
}
updateRectangle(position: THREE.Vector3) {
if (!this.rectangle || !this.recStartPos) return
// console.log('updateRectangle', this.recStartPos, position)
const width = position.x - this.recStartPos.x
const height = position.z - this.recStartPos.z
const newWidth = Math.abs(width)
const newHeight = Math.abs(height)
// 清理旧几何体
this.rectangle.geometry.dispose()
this.rectangle.geometry = new THREE.PlaneGeometry(newWidth, newHeight)
this.rectangle.position.set(
this.recStartPos.x + width / 2,
this.recStartPos.y,
this.recStartPos.z + height / 2
)
}
onMouseDown(event: MouseEvent) {
if (event.shiftKey) {
// 记录鼠标按下位置
this.recStartPos = this.viewport.getClosestIntersection(event)
this.createRectangle()
}
}
onMouseMove(event: MouseEvent) {
if (!this.recStartPos) {
this.disposeRect()
}
// 更新矩形大小或重新生成矩形
const position = this.viewport.getClosestIntersection(event)
if (!position) return
this.updateRectangle(position)
}
disposeRect() {
if (this.rectangle !== null) {
this.viewport.scene.remove(this.rectangle)
this.rectangle.geometry.dispose()
this.rectangle = null
}
this.recStartPos = null
}
onMouseUp(event: MouseEvent) {
this.disposeRect()
}
}

11
src/model/itemType/ItemTypeLine.ts

@ -105,10 +105,13 @@ export default abstract class ItemTypeLine extends ItemType {
point.name = item.name
point.uuid = item.id || THREE.MathUtils.generateUUID()
point.userData = _.cloneDeep(item.dt) || {}
point.userData.type = item.t
point.userData.actionType = item.a
point.userData.label = item.l
point.userData.color = item.c
_.extend(point.userData, {
type: item.t,
actionType: item.a,
label: item.l,
color: item.c,
selectable: true
})
point.rotation.set(
THREE.MathUtils.degToRad(item.tf[1][0]),

Loading…
Cancel
Save