Browse Source

读取 / 写入 bug

master
修宁 6 months ago
parent
commit
00a9b524f8
  1. 3
      src/core/Constract.ts
  2. 9
      src/core/ModelUtils.ts
  3. 32
      src/core/base/BaseRenderer.ts
  4. 10
      src/core/engine/SceneHelp.ts
  5. 98
      src/core/engine/Viewport.ts
  6. 11
      src/core/manager/DragManager.ts
  7. 8
      src/core/manager/EntityManager.ts
  8. 33
      src/core/manager/InstanceMeshManager.ts
  9. 1
      src/core/manager/InstancePointManager.ts
  10. 4
      src/core/manager/InteractionManager.ts
  11. 62
      src/core/manager/LabelManager.ts
  12. 142
      src/core/manager/LineSegmentManager.ts
  13. 4
      src/core/manager/SelectManager.ts
  14. 66
      src/core/manager/StateManager.ts
  15. 181
      src/core/manager/WorldModel.ts
  16. 170
      src/editor/Model2DEditor.vue
  17. 17
      src/editor/ModelMain.vue
  18. 4
      src/editor/menus/FileMenu.ts
  19. 3
      src/editor/widgets/modeltree/ModeltreeViewJs.js
  20. 142
      src/example/example1.js
  21. 12
      src/modules/carton/CartonRenderer.ts
  22. 11
      src/modules/gstore/GstoreRenderer.ts
  23. 45
      src/modules/measure/MeasureRenderer.ts
  24. 10
      src/modules/pallet/PalletRenderer.ts
  25. 9
      src/modules/tote/ToteRenderer.ts
  26. 21
      src/modules/way/WayRenderer.ts
  27. 1
      src/runtime/EventBus.ts
  28. 3
      src/runtime/System.ts
  29. 17
      src/types/ModelTypes.ts
  30. 15
      src/types/Types.d.ts

3
src/core/Constract.ts

@ -32,5 +32,8 @@ const Constract = Object.freeze({
HEIGHT_WAY: 0.01,
HEIGHT_WAY_LABEL: 0.03,
HEIGHT_WAY_LINE: 0.02,
// 鼠标点击延迟
MOUSE_CLICK_DELAY: 200
})
export default Constract

9
src/core/ModelUtils.ts

@ -3,7 +3,7 @@ import type Viewport from '@/core/engine/Viewport'
import { Vector2 } from 'three/src/math/Vector2'
import EventBus from '@/runtime/EventBus.ts'
import Decimal from 'decimal.js'
import type { Object3DLike } from '@/types/ModelTypes.ts'
import type { LineLike, Object3DLike } from '@/types/ModelTypes.ts'
import axios from 'axios'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader'
@ -127,12 +127,9 @@ export function setUserDataForItem(item: ItemJson, object: Object3DLike) {
}
}
export function setUserDataForLine(start: ItemJson, end: ItemJson, type: LinkType, object: Object3DLike) {
export function setUserDataForLine(start: ItemJson, end: ItemJson, type: LinkType, object: LineLike) {
const id = getLineId(start.id, end.id, type)
if (!object.name) {
object.name = id
}
object.userData = {
...object.userData,
createType: 'line',
@ -248,7 +245,7 @@ export function getClosestObject(viewport: Viewport, object: THREE.Object3D, ins
if (object.userData && object.userData.t && object.userData.entityId) {
// 找到第一个有效的业务 Object3D
if (object instanceof THREE.InstancedMesh && instanceId >= 0) {
const manager = viewport.pointManagerMap.get(object.userData.t)
const manager = viewport.meshManager.get(object.userData.t)
if (manager) {
return manager.findByMeshInstanceId(object.userData.blockIndex, instanceId)
}

32
src/core/base/BaseRenderer.ts

@ -2,11 +2,10 @@ import type Viewport from '@/core/engine/Viewport'
import * as THREE from 'three'
import { getLineId, getMatrixFromTf, setUserDataForItem, setUserDataForLine } from '@/core/ModelUtils.ts'
import { Line2 } from 'three/examples/jsm/lines/Line2'
import InstancePointManager, { PointManageWrap } from '@/core/manager/InstancePointManager.ts'
import Constract from '@/core/Constract.ts'
import LineSegmentManager, { LineManageWrap } from '@/core/manager/LineSegmentManager.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts'
import { InstanceMeshWrap } from '@/core/manager/InstanceMeshManager.ts'
import { PointManageWrap } from '@/core/manager/InstancePointManager.ts'
import { LineWrap } from '@/core/manager/LineSegmentManager.ts'
import type { LineLike, Object3DLike } from '@/types/ModelTypes.ts'
import { MeshWrap } from '@/core/manager/InstanceMeshManager.ts'
/**
*
@ -59,7 +58,7 @@ export default abstract class BaseRenderer {
/**
* 线
*/
createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): Object3DLike {
createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): LineLike {
throw new Error('createLineBasic method must be implemented in derived class.')
}
@ -72,7 +71,7 @@ export default abstract class BaseRenderer {
/**
* 线
*/
afterCreateOrUpdateLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: Object3DLike) {
afterCreateOrUpdateLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: LineLike) {
}
/**
@ -98,7 +97,7 @@ export default abstract class BaseRenderer {
this.tempViewport.scene.add(...objects)
// const dragObjects = objects.filter(obj => !!obj.userData.draggable)
//this.tempViewport.dragControl.setDragObjects(dragObjects, 'push')
//this.tempViewport.dragManager.setDragObjects(dragObjects, 'push')
}
removeFromScene(...objects: THREE.Object3D[]) {
@ -107,7 +106,7 @@ export default abstract class BaseRenderer {
return
}
this.tempViewport.scene.remove(...objects)
//this.tempViewport.dragControl.setDragObjects(objects, 'remove')
//this.tempViewport.dragManager.setDragObjects(objects, 'remove')
}
createPointForEntity(item: ItemJson, option?: RendererCudOption): Object3DLike {
@ -156,17 +155,12 @@ export default abstract class BaseRenderer {
if (object instanceof THREE.Object3D) {
this.removeFromScene(object)
} else if (object instanceof PointManageWrap) {
// 如果是 PointManageWrap, 则需要调用管理器的删除方法
object.manager.deletePoint(id)
} else if (object instanceof InstanceMeshWrap) {
} else if (object instanceof MeshWrap) {
// 如果是 PointManageWrap, 则需要调用管理器的删除方法
object.manager.delete(id)
} else if (object instanceof LineManageWrap) {
// 如果是 PointManageWrap, 则需要调用管理器的删除方法
object.manager.deleteLine(id)
} else {
throw new Error('unkown Point type', object)
}
this.tempViewport.entityManager.deleteEntityOnly(id)
@ -240,8 +234,6 @@ export default abstract class BaseRenderer {
if (line instanceof THREE.Object3D) {
this.appendToScene(line)
} else if (line instanceof PointManageWrap) {
line.manager.syncMeshObject3D(line)
}
this.afterCreateOrUpdateLine(start, end, type, option, line)
@ -274,7 +266,7 @@ export default abstract class BaseRenderer {
const geom = line.geometry
geom.setFromPoints([startPoint.position, endPoint.position])
} else if (line instanceof LineManageWrap) {
} else if (line instanceof LineWrap) {
line.manager.updateLine(lineId, startPoint.position, endPoint.position, line.color)
}
}

10
src/core/engine/SceneHelp.ts

@ -4,8 +4,7 @@ import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry'
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial'
import { Line2 } from 'three/examples/jsm/lines/Line2'
import type { Object3DLike } from '@/types/ModelTypes.ts'
import { LineManageWrap } from '@/core/manager/LineSegmentManager.ts'
import { PointManageWrap } from '@/core/manager/InstancePointManager.ts'
import { LineWrap } from '@/core/manager/LineSegmentManager.ts'
/**
*
@ -86,6 +85,7 @@ export default class SceneHelp {
//
// const hemisphereLight = new THREE.HemisphereLight(0xffffff, 0x444444, 1)
// this.scene.add(hemisphereLight)
window['scene'] = this.scene
}
// /**
@ -114,9 +114,6 @@ export default class SceneHelp {
if (obj instanceof THREE.Object3D) {
this.scene.add(obj)
} else if (obj instanceof LineManageWrap) {
// 默认会合并到 LineSegmentManager 中
}
}
}
@ -163,7 +160,8 @@ export default class SceneHelp {
// 清空场景
this.scene.children = []
this.scene = null
// this.scene = null
delete window['scene']
}
}

98
src/core/engine/Viewport.ts

@ -4,7 +4,7 @@ import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import Stats from 'three/examples/jsm/libs/stats.module'
import type WorldModel from '../manager/WorldModel'
import $ from 'jquery'
import { markRaw, reactive, toRaw, watch } from 'vue'
import { markRaw, reactive, watch } from 'vue'
import { CSS3DRenderer } from 'three/examples/jsm/renderers/CSS3DRenderer'
import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer'
@ -15,12 +15,10 @@ import EntityManager from '../manager/EntityManager'
import InteractionManager from '@/core/manager/InteractionManager'
import { calcPositionUseSnap } from '@/core/ModelUtils'
import StateManager from '@/core/manager/StateManager.ts'
import EventBus from '@/runtime/EventBus.ts'
import Constract from '@/core/Constract.ts'
import DragManager from '@/core/manager/DragManager.ts'
import type { PropertySetter } from '@/core/base/PropertyTypes.ts'
import LabelManager from '@/core/manager/LabelManager.ts'
import type InstancePointManager from '@/core/manager/InstancePointManager.ts'
import type LineSegmentManager from '@/core/manager/LineSegmentManager.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts'
import type InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts'
@ -62,9 +60,6 @@ export default class Viewport {
markRaw(this.interactionManager)
]
// 点实例管理器 moduleName -> InstancePointManager
pointManagerMap: Map<string, InstancePointManager> = new Map()
// 对象实例管理器 moduleName -> InstanceMeshManager
meshManager: Map<string, InstanceMeshManager> = new Map()
@ -106,13 +101,14 @@ export default class Viewport {
}
})
constructor(sceneHelp: SceneHelp, viewerDom: HTMLElement) {
constructor(sceneHelp: SceneHelp, viewerDom: HTMLElement, stateManager) {
this.scene = sceneHelp
this.viewerDom = viewerDom
this.stateManager = stateManager
}
/**
*
*
* @param typeName
* @param createFn
*/
@ -128,22 +124,6 @@ export default class Viewport {
}
/**
*
* @param typeName
* @param createFn
*/
getOrCreatePointManager(typeName: string, createFn: () => InstancePointManager): InstancePointManager {
let pointManager = this.pointManagerMap.get(typeName)
if (!pointManager) {
pointManager = createFn()
if (pointManager) {
this.pointManagerMap.set(typeName, pointManager)
}
}
return pointManager
}
/**
* 线
* @param typeName 线
* @param createFn 线
@ -166,8 +146,8 @@ export default class Viewport {
console.log('viewport on catelogCode: ' + this.scene.catalogCode)
const viewerDom = this.viewerDom
// 管理器
this.stateManager = new StateManager(option.stateManagerId, this)
// 状态管理器初始化
this.stateManager.init(this)
// 渲染器
const renderer = new THREE.WebGLRenderer({
@ -264,27 +244,13 @@ export default class Viewport {
this.animate()
try {
if (worldModel.state.isDraft) {
await this.stateManager.loadFromLocalstore()
EventBus.dispatch('dataLoadComplete', {})
} else {
// 不是从草稿读的数据, 就找服务器捞数据
const vdata = await this.worldModel.getCatalogData(this.scene.catalogCode)
if (!vdata) {
return
}
if (!vdata.catalog) {
vdata.catalog = toRaw(this.worldModel.state.catalog)
}
await this.stateManager.load(vdata)
EventBus.dispatch('dataLoadComplete', {})
}
} finally {
this.state.isReady = true
}
window['viewport'] = this
window['stateManager'] = this.stateManager
window['entityManager'] = this.entityManager
window['renderer'] = this.renderer
window['camera'] = this.camera
window['renderer'] = this.renderer
window['controls'] = this.controls
}
/**
@ -294,6 +260,10 @@ export default class Viewport {
if (this.camera) {
this.scene.remove(this.camera)
}
if (this.controls) {
this.controls.dispose()
this.controls = null
}
// ============================ 创建透视相机
const viewerDom = this.viewerDom
@ -323,6 +293,9 @@ export default class Viewport {
// this.renderer.render(this.scene, this.camera);
// });
this.controls = controls
window['camera'] = this.camera
window['controls'] = this.controls
}
/**
@ -332,6 +305,10 @@ export default class Viewport {
if (this.camera) {
this.scene.remove(this.camera)
}
if (this.controls) {
this.controls.dispose()
this.controls = null
}
// ============================ 创建正交相机
const viewerDom = this.viewerDom
@ -370,6 +347,9 @@ export default class Viewport {
cameraNew.updateProjectionMatrix()
window['camera'] = this.camera
window['controls'] = this.controls
this.syncCameraState()
}
@ -527,13 +507,18 @@ export default class Viewport {
dispose() {
this.state.isReady = false
if (this.pointManagerMap.size > 0) {
this.pointManagerMap.forEach((manager) => {
if (this.animationFrameId !== null) {
cancelAnimationFrame(this.animationFrameId)
this.animationFrameId = null
}
if (this.meshManager.size > 0) {
this.meshManager.forEach((manager) => {
if (manager.dispose) {
manager.dispose()
}
})
this.pointManagerMap.clear()
this.meshManager.clear()
}
if (this.lineSegmentManagerMap.size > 0) {
this.lineSegmentManagerMap.forEach((manager) => {
@ -553,11 +538,6 @@ export default class Viewport {
this.tools = []
}
if (this.animationFrameId !== null) {
cancelAnimationFrame(this.animationFrameId)
this.animationFrameId = null
}
if (this.watchList) {
_.forEach(this.watchList, (unWatchFn => {
if (typeof unWatchFn === 'function') {
@ -594,6 +574,14 @@ export default class Viewport {
this.controls.dispose()
this.controls = null
}
delete window['viewport']
delete window['stateManager']
delete window['entityManager']
delete window['renderer']
delete window['camera']
delete window['renderer']
delete window['controls']
}
getIntersects(point: THREE.Vector2) {

11
src/core/manager/DragManager.ts

@ -1,10 +1,9 @@
import * as THREE from 'three'
import type Viewport from '@/core/engine/Viewport.ts'
import { getClosestObject } from '@/core/ModelUtils.ts'
import EventBus from '@/runtime/EventBus.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts'
import InstancePointManager, { PointManageWrap } from '@/core/manager/InstancePointManager.ts'
import { LineManageWrap } from '@/core/manager/LineSegmentManager.ts'
import { PointManageWrap } from '@/core/manager/InstancePointManager.ts'
import Constract from '@/core/Constract.ts'
/**
* ThreeJS X/Z
@ -64,6 +63,7 @@ export default class DragControl {
*/
private onPointerDown = (event: PointerEvent): void => {
if (!this.enabled) return
if (event.button !== 0) return
const mouse = this.getMousePosition(event.clientX, event.clientY)
const intersected = this.getIntersectedDraggableObject(mouse)
@ -91,7 +91,7 @@ export default class DragControl {
}
}, 100) // 每100毫秒检查一次状态, 鼠标移出要主动清理
}, 100) // 0.1秒延迟抓取
}, Constract.MOUSE_CLICK_DELAY) // 0.1秒延迟抓取
}
@ -112,7 +112,7 @@ export default class DragControl {
const intersected = this.getIntersectedDraggableObject(mouse)
// =====================================
// const ids = this.viewport.itemFindManager.getItemsByPosition(CurrentMouseInfo.x, CurrentMouseInfo.z)
this.domElement.style.cursor = intersected ? 'grab' : 'auto'
this.domElement.style.cursor = intersected ? 'pointer' : 'auto'
}
}
@ -120,6 +120,7 @@ export default class DragControl {
* pointerup
*/
private onPointerUp = (event: PointerEvent): void => {
if (event.button !== 0) return
if (this.isDragging) {
const startPos = this.dragStartMouse.clone()
const targetPos = new THREE.Vector2(CurrentMouseInfo.x, CurrentMouseInfo.z)

8
src/core/manager/EntityManager.ts

@ -5,7 +5,7 @@ import { getRenderer } from './ModuleManager'
import { getClosestObject, getLineId, parseLineId } from '@/core/ModelUtils'
import { Vector2 } from 'three'
import { getFreezeDeep } from '@/utils/webutils.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts'
import type { LineLike, Object3DLike } from '@/types/ModelTypes.ts'
/**
*
@ -33,7 +33,7 @@ export default class EntityManager {
readonly _draggableObjects: THREE.Object3D[] = []
// 所有 THREEJS "线"对象, 检索值是"线实体"的 id, 取值方式是 {type}${startId}${endId}, 值是 THREE.Object3D 数组
private readonly __lineMap = new Map<string, Object3DLike>()
private readonly __lineMap = new Map<string, LineLike>()
// 差量渲染器
private readonly diffRenderer = new Map<string, BaseRenderer>()
@ -468,11 +468,11 @@ export default class EntityManager {
}
}
appendLineObject(id: string, lines: Object3DLike) {
appendLineObject(id: string, lines: LineLike) {
this.__lineMap.set(id, lines)
}
findLineObjectById(lineId: string): Object3DLike | undefined {
findLineObjectById(lineId: string): LineLike | undefined {
return this.__lineMap.get(lineId)
}

33
src/core/manager/InstanceMeshManager.ts

@ -5,7 +5,7 @@ import { PointManageWrap } from '@/core/manager/InstancePointManager.ts'
import { Matrix4 } from 'three/src/math/Matrix4'
export default class InstanceMeshManager {
private __uuidMap = new Map<string, InstanceMeshWrap>()
private __uuidMap = new Map<string, MeshWrap>()
public readonly name: string
public readonly viewport: Viewport
@ -34,7 +34,7 @@ export default class InstanceMeshManager {
/**
*
*/
findByMeshInstanceId(blockIndex: number, instanceId: number): InstanceMeshWrap {
findByMeshInstanceId(blockIndex: number, instanceId: number): MeshWrap {
if (!this.blocks[blockIndex]) {
console.error('InstancePointManager: Invalid blockIndex', blockIndex)
return null
@ -44,7 +44,14 @@ export default class InstanceMeshManager {
return this.__uuidMap.get(uuid)
}
create(entityId: string, userData?: any): InstanceMeshWrap {
createByItem(item: ItemJson): MeshWrap {
return this.create(item.id, {
t: item.t,
entityId: item.id
})
}
create(entityId: string, userData?: any): MeshWrap {
// 如果 entityId 存在,就替换
if (this.__uuidMap.has(entityId)) {
const existingWrap = this.__uuidMap.get(entityId)
@ -76,11 +83,11 @@ export default class InstanceMeshManager {
return null
}
return new InstanceMeshWrap(entityId, this, blockIndex, meshIndex, userData)
return new MeshWrap(entityId, this, blockIndex, meshIndex, userData)
}
delete(wrapOrId: InstanceMeshWrap | string) {
let wrap: InstanceMeshWrap
delete(wrapOrId: MeshWrap | string) {
let wrap: MeshWrap
if (typeof wrapOrId === 'string') {
wrap = this.__uuidMap.get(wrapOrId)
if (!wrap) return
@ -123,7 +130,7 @@ export default class InstanceMeshManager {
return block
}
setBlockMatrixAt(wrap: InstanceMeshWrap, matrix: THREE.Matrix4) {
setBlockMatrixAt(wrap: MeshWrap, matrix: THREE.Matrix4) {
const block = this.blocks[wrap.blockIndex]
if (!block) {
console.warn(`InstanceMeshManager: Block ${wrap.blockIndex} not found!`)
@ -132,6 +139,7 @@ export default class InstanceMeshManager {
if (!block.__indexIdMap.has(wrap.meshIndex)) {
this.__uuidMap.set(wrap.uuid, wrap)
block.__indexIdMap.set(wrap.meshIndex, wrap.uuid)
wrap.parent = block.instancedMesh
}
block.instancedMesh.setMatrixAt(wrap.meshIndex, matrix)
@ -143,13 +151,12 @@ export default class InstanceMeshManager {
block.dispose()
}
this.blocks.length = 0 // 清空 blocks 数组
this.geometry.dispose() // 释放几何体资源
this.material.dispose() // 释放材质资源
console.log(`InstanceMeshManager ${this.name} disposed.`)
this.geometry?.dispose() // 释放几何体资源
this.material?.dispose() // 释放材质资源
}
}
export class InstanceMeshWrap {
export class MeshWrap {
readonly entityId: string
readonly manager: InstanceMeshManager
readonly blockIndex: number
@ -180,7 +187,7 @@ export class InstanceMeshWrap {
this.userData = userData
}
setMatrix4(matrix: THREE.Matrix4): InstanceMeshWrap {
setMatrix4(matrix: THREE.Matrix4): MeshWrap {
this.manager.setBlockMatrixAt(this, matrix)
return this
}
@ -196,7 +203,7 @@ export class InstanceMeshWrap {
return matrix
}
applyMatrix4(targetMatrix: THREE.Matrix4): InstanceMeshWrap {
applyMatrix4(targetMatrix: THREE.Matrix4): MeshWrap {
const matrix = this.matrix
const newMatrix = matrix.multiplyMatrices(targetMatrix, matrix)
this.setMatrix4(newMatrix)

1
src/core/manager/InstancePointManager.ts

@ -3,7 +3,6 @@ import type Viewport from '@/core/engine/Viewport.ts'
import { Vector3 } from 'three/src/math/Vector3'
import InstanceMeshBlock from '@/core/manager/InstanceMeshBlock.ts'
import { getMatrixFromTf } from '@/core/ModelUtils.ts'
import { InstanceMeshWrap } from '@/core/manager/InstanceMeshManager.ts'
/**
*

4
src/core/manager/InteractionManager.ts

@ -53,7 +53,7 @@ export default class InteractionManager implements IControls {
}
this.viewport.state.cursorMode = 'normal'
this.viewport.dragControl.enabled = true
this.viewport.dragManager.enabled = true
this.viewport.viewerDom.style.cursor = ''
this.option = undefined
@ -90,7 +90,7 @@ export default class InteractionManager implements IControls {
// 初始化交互
this.currentTool = interaction
this.viewport.dragControl.enabled = false
this.viewport.dragManager.enabled = false
this.currentTool.start(this.viewport, this.option)

62
src/core/manager/LabelManager.ts

@ -1,41 +1,15 @@
import * as THREE from 'three'
import type IControls from '@/core/controls/IControls.ts'
import type Viewport from '@/core/engine/Viewport.ts'
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'
import { Text } from 'troika-three-text'
import SimSunTTF from '@/assets/fonts/simsunb.ttf'
import type { Object3DLike } from '@/types/ModelTypes.ts'
import type { LineLike, Object3DLike } from '@/types/ModelTypes.ts'
export interface LabelOption {
/**
*
*/
name?: string
/**
* 使 HTML
*/
useHtmlLabel: boolean
/**
* ex: css='14px', text=0.4
*/
fontSize: number | string
/**
* ex: '#ffffff'
*/
color: string
/**
* ex: css='5px 8px', text=0.2
*/
padding?: number | string
text?: string
format?: (distance: number) => string
}
/**
*
*/
export default class LabelManager implements IControls {
export default class LabelManager {
viewport: Viewport
private labelMap: Map<string, Text | CSS2DObject> = new Map()
private labelGroup: THREE.Group
@ -47,7 +21,7 @@ export default class LabelManager implements IControls {
this.viewport.scene.add(this.labelGroup)
}
createOrUpdateLabelByDistance(lineRef: Object3DLike, startPos: THREE.Vector3, endPos: THREE.Vector3, option: LabelOption): Text | CSS2DObject {
createOrUpdateLabelByDistance(lineRef: LineLike, startPos: THREE.Vector3, endPos: THREE.Vector3, option: LabelOption): Text | CSS2DObject {
let labelObj = this.labelMap.get(lineRef.userData.labelObjectId)
// 线段不存在
@ -69,7 +43,7 @@ export default class LabelManager implements IControls {
return labelObj
}
createLabel(parentObj: Object3DLike, option: LabelOption): Text | CSS2DObject {
createLabel(parentObj: Object3DLike | LineLike, option: LabelOption): Text | CSS2DObject {
const labelObj = this.createLabelObject(option)
parentObj.userData.labelObjectId = labelObj.uuid
@ -89,7 +63,7 @@ export default class LabelManager implements IControls {
}
updateLabel(parentObj: Object3DLike, text: string) {
updateLabel(parentObj: Object3DLike | LineLike, text: string) {
const labelObj = this.labelMap.get(parentObj.userData.labelObjectId)
if (labelObj) {
if (labelObj instanceof CSS2DObject) {
@ -219,3 +193,29 @@ export default class LabelManager implements IControls {
// }
}
export interface LabelOption {
/**
*
*/
name?: string
/**
* 使 HTML
*/
useHtmlLabel: boolean
/**
* ex: css='14px', text=0.4
*/
fontSize: number | string
/**
* ex: '#ffffff'
*/
color: string
/**
* ex: css='5px 8px', text=0.2
*/
padding?: number | string
text?: string
format?: (distance: number) => string
}

142
src/core/manager/LineSegmentManager.ts

@ -1,24 +1,36 @@
import * as THREE from 'three'
import type Viewport from '@/core/engine/Viewport.ts'
import { LineSegmentsGeometry } from 'three/examples/jsm/lines/LineSegmentsGeometry'
import { LineSegments2 } from 'three/examples/jsm/lines/LineSegments2'
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial'
import type { Object3DLike, Vector3Like } from '@/types/ModelTypes.ts'
import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry'
import type { Vector3Like } from '@/types/ModelTypes.ts'
import { LineSegmentsGeometry } from 'three/examples/jsm/lines/LineSegmentsGeometry'
/**
* 线
*/
export default class LineSegmentManager {
private readonly viewport: Viewport
private readonly lineGeometry: LineGeometry // LineSegmentsGeometry
private readonly lineGeometry: LineSegmentsGeometry
private readonly lineMaterial: LineMaterial
private readonly lineSegments: LineSegments2
private readonly segments: Map<string, LineManageWrap> = new Map()
private readonly segments: Map<string, LineWrap> = new Map()
public needsUpdate: boolean = false
private colorArray: Float32Array | null = null
private positionArray: Float32Array | null = null
constructor(name: string, viewport: Viewport, lineMaterial: LineMaterial) {
this.viewport = viewport
this.lineMaterial = lineMaterial
this.lineGeometry = new LineSegmentsGeometry() // new LineSegmentsGeometry()
// 创建线段的渲染对象
this.lineSegments = new LineSegments2(this.lineGeometry, this.lineMaterial)
this.lineSegments.name = name
this.lineSegments.frustumCulled = false
this.viewport.scene.add(this.lineSegments)
}
/**
* 线
* @param lineId 线
@ -26,8 +38,9 @@ export default class LineSegmentManager {
* @param end
* @param color 线 ()
* @param userData ()
* @param visible
*/
createLine(lineId: string, start: Vector3Like, end: Vector3Like, color?: THREE.Color | number | string, userData: Partial<UserData> = {}): LineManageWrap {
createOrUpdateLine(lineId: string, start: Vector3Like, end: Vector3Like, color?: THREE.Color | number | string, userData: Partial<UserData> = {}, visible: boolean = true): LineWrap {
const segment = this.segments.get(lineId)
if (segment) {
// console.error(`LineSegmentManager: Line with id ${lineId} already exists.`)
@ -52,15 +65,7 @@ export default class LineSegmentManager {
colorObj = new THREE.Color(color)
}
const result = new LineManageWrap(this, {
uuid: lineId,
visible: true,
userData: {
entityId: lineId,
createType: 'line',
...userData
}
}, startVec, endVec, colorObj)
const result = new LineWrap(this, lineId, startVec, endVec, colorObj, visible)
this.segments.set(lineId, result)
result.parent = this.lineSegments
@ -68,7 +73,7 @@ export default class LineSegmentManager {
return result
}
updateLine(lineId: string, start?: Vector3Like, end?: Vector3Like, color?: THREE.Color | number | string): LineManageWrap {
updateLine(lineId: string, start?: Vector3Like, end?: Vector3Like, color?: THREE.Color | number | string, visible: boolean = true): LineWrap {
const wrap = this.segments.get(lineId)
if (!wrap) return
@ -94,66 +99,6 @@ export default class LineSegmentManager {
return wrap
}
// /**
// * 更新线段位置
// * @param lineId 线段唯一标识
// * @param start 新起点
// * @param end 新终点
// */
// updateLinePosition(lineId: string, start: THREE.Vector3Like, end: THREE.Vector3Like): void {
// const segment = this.segments.get(lineId)
// if (!segment) return
//
// if (start instanceof THREE.Vector3) {
// segment.start.copy(start)
// } else {
// segment.start.set(start[0], start[1], start[2])
// }
//
// if (end instanceof THREE.Vector3) {
// segment.end.copy(end)
// } else {
// segment.end.set(end[0], end[1], end[2])
// }
//
// this.needsUpdate = true
// }
//
// /**
// * 更新线段颜色
// * @param lineId 线段唯一标识
// * @param color 新颜色
// */
// updateLineColor(lineId: string, color: THREE.Color | number | string): void {
// const segment = this.segments.get(lineId)
// if (!segment) return
//
// if (color instanceof THREE.Color) {
// segment.color = color
// } else if (typeof color === 'number') {
// segment.color = new THREE.Color(color)
// } else if (typeof color === 'string') {
// segment.color = new THREE.Color(color)
// } else {
// segment.color = undefined
// }
//
// this.needsUpdate = true
// }
//
// /**
// * 设置线段可见性
// * @param lineId 线段唯一标识
// * @param visible 是否可见
// */
// setLineVisible(lineId: string, visible: boolean): void {
// const segment = this.segments.get(lineId)
// if (segment && segment.visible !== visible) {
// segment.visible = visible
// this.needsUpdate = true
// }
// }
/**
* 线
* @param lineId 线
@ -167,14 +112,6 @@ export default class LineSegmentManager {
}
/**
* 线
* @param lineId 线
*/
getObject3DLike(lineId: string): Object3DLike {
return this.segments.get(lineId)
}
/**
* ()
*/
updateGeometry(): void {
@ -247,26 +184,6 @@ export default class LineSegmentManager {
this.needsUpdate = false
}
/**
* 线
*/
public static create(name: string, viewport: Viewport, lineMaterial: LineMaterial): LineSegmentManager {
return new LineSegmentManager(name, viewport, lineMaterial)
}
private constructor(name: string, viewport: Viewport, lineMaterial: LineMaterial) {
this.viewport = viewport
this.lineMaterial = lineMaterial
this.lineGeometry = new LineGeometry() // new LineSegmentsGeometry()
// 创建线段的渲染对象
this.lineSegments = new LineSegments2(this.lineGeometry, this.lineMaterial)
this.lineSegments.name = name
this.lineSegments.frustumCulled = false
this.viewport.scene.add(this.lineSegments)
}
dispose() {
this.viewport.scene.remove(this.lineSegments)
this.lineGeometry.dispose()
@ -287,25 +204,21 @@ export default class LineSegmentManager {
}
export class LineManageWrap {
export class LineWrap {
readonly manager: LineSegmentManager
parent: THREE.Object3D | null = null
uuid: string
start: THREE.Vector3
end: THREE.Vector3
color: THREE.Color
uuid: string
name: string
visible: boolean
readonly position = new THREE.Vector3()
readonly rotation = new THREE.Euler()
readonly scale = new THREE.Vector3(1, 1, 1)
//@ts-ignore
userData: UserData = {}
get type() {
return 'LineManageWrap'
return 'LineWrap'
}
get isObject3D() {
@ -315,12 +228,13 @@ export class LineManageWrap {
updateWorldMatrix() {
}
constructor(lineManager: LineSegmentManager, data: any, start: THREE.Vector3, end: THREE.Vector3, color: THREE.Color) {
constructor(lineManager: LineSegmentManager, uuid: string, start: THREE.Vector3, end: THREE.Vector3, color: THREE.Color, visible: boolean = true) {
this.manager = lineManager
_.extend(this, data)
this.uuid = uuid
this.start = start
this.end = end
this.color = color
this.visible = visible
}
dispose() {

4
src/core/manager/SelectManager.ts

@ -318,6 +318,7 @@ export default class SelectManager {
}
private onMouseDown = (event: MouseEvent) => {
if (event.button !== 0) return
if (event.shiftKey) {
// 记录鼠标按下位置
this.recStartPos = this.viewport.getClosestIntersection(event)
@ -342,10 +343,11 @@ export default class SelectManager {
}
private onMouseUp = (event: MouseEvent) => {
if (event.button !== 0) return
this.disposeRect()
const clickTime = this.clickTime
this.clickTime = null
if (Date.now() - clickTime < 200) {
if (Date.now() - clickTime < Constract.MOUSE_CLICK_DELAY) {
// 如果是点击事件,触发选中逻辑
const objects: Object3DLike[] = this.viewport.entityManager.getObjectByCanvasMouse(event)
if (objects.length > 0 && objects[0]?.userData?.entityId && objects[0]?.userData?.createType !== 'line') {

66
src/core/manager/StateManager.ts

@ -53,9 +53,9 @@ export default class StateManager {
/**
* ,
*/
readonly entityManager: EntityManager
entityManager: EntityManager
readonly viewport: Viewport
viewport: Viewport
/**
*
@ -96,22 +96,26 @@ export default class StateManager {
/**
* @param id , key
* @param viewport ,
* @param maxHistorySteps 20
*/
constructor(id: string, viewport: Viewport, maxHistorySteps = 20) {
constructor(id: string, maxHistorySteps = 20) {
this.id = id
this.storeKey = `-tmp-yvan-lcc-${this.id}`
this.entityManager = viewport.entityManager
this.viewport = viewport
this.maxHistorySteps = maxHistorySteps
this.historySteps = []
this.pendingChanges = false
this.isAutoSavingPaused = false
}
init(viewport: Viewport) {
this.viewport = viewport
this.entityManager = viewport.entityManager
_.defer(() => {
this.fullSync(false)
})
}
// 差异反转方法
private invertDiff(diff: DataDiff): DataDiff {
return {
@ -331,7 +335,7 @@ export default class StateManager {
/**
*
*/
async load(data: Partial<VData>) {
async load(data: VData) {
this.isLoading.value = true
this.historySteps = Array.from({ length: this.maxHistorySteps }, () => null)
this.historyIndex = -1
@ -340,16 +344,10 @@ export default class StateManager {
// 停止自动保存,避免在加载过程中触发
this.stopAutoSave()
// 直接替换数组引用(避免响应式开销)
//@ts-ignore
this.___vdata = {
id: this.id,
isChanged: false,
...data
}
this.___vdata = data
// 同步到视口
this.fullSync()
// this.fullSync()
this.isChanged.value = false
console.log('[StateManager] 加载完成,共', data.items.length, '个对象')
@ -358,6 +356,9 @@ export default class StateManager {
await this.saveToLocalstore()
} finally {
EventBus.dispatch('dataLoadComplete', {
stateManager: this
})
this.isLoading.value = false
}
}
@ -437,8 +438,8 @@ export default class StateManager {
}
this.isChanged.value = saved.isChanged || false
this.fullSync(false) // 同步到视口
console.log('[StateManager] 从本地存储恢复', this.___vdata.items.length, '个对象')
// this.fullSync(false) // 同步到视口
console.log('[StateManager] 从本地存储 [' + this.storeKey + '] 恢复', this.___vdata.items.length, '个对象')
return true
}
@ -450,6 +451,9 @@ export default class StateManager {
} finally {
this.isLoading.value = false
EventBus.dispatch('dataLoadComplete', {
stateManager: this
})
}
}
@ -477,34 +481,18 @@ export default class StateManager {
/**
* 稿
*/
static async tryLoadCatalogFromLocalstore(): Promise<{
success: boolean,
catalogCode?: string,
catalog?: Catalog,
stateManagerId?: string
}> {
static async tryLoadCatalogFromLocalstore(stateManagerId: string): Promise<VData | null> {
// 获取 url 中的 stateManagerId
// 从 localforage 中读取草稿数据
const stateManagerId = getQueryParams()?.get('store')
if (stateManagerId) {
const storeKey = `-tmp-yvan-lcc-${stateManagerId}`
const saved: VData = await localforage.getItem(storeKey)
if (saved && saved.catalog) {
const catalogCode = saved.catalogCode || ''
if (catalogCode) {
return {
success: true,
catalogCode,
catalog: saved.catalog,
stateManagerId
}
}
if (saved && saved.catalog && saved.catalogCode && saved.worldData) {
return saved
}
}
return {
success: false
}
return null
}
/**

181
src/core/manager/WorldModel.ts

@ -1,4 +1,4 @@
import _ from 'lodash'
import _, { cloneDeep } from 'lodash'
import { reactive, watch } from 'vue'
import EventBus from '@/runtime/EventBus'
import Measure from '@/modules/measure'
@ -6,42 +6,58 @@ import Way from '@/modules/way'
import Gstore from '@/modules/gstore'
import Rack from '@/modules/rack'
import ShuttleRack from '@/modules/shuttle_rack'
import Pallet from "@/modules/pallet"
import Tote from "@/modules/tote"
import Agv1 from "@/modules/agv1"
import Carton from "@/modules/carton"
import Ptr from "@/modules/ptr"
import Clx from "@/modules/clx"
import Charger from "@/modules/charger"
import Pallet from '@/modules/pallet'
import Tote from '@/modules/tote'
import Agv1 from '@/modules/agv1'
import Carton from '@/modules/carton'
import Ptr from '@/modules/ptr'
import Clx from '@/modules/clx'
import Charger from '@/modules/charger'
import StateManager from '@/core/manager/StateManager.ts'
import { getQueryParams, setQueryParam } from '@/utils/webutils.ts'
import localforage from 'localforage'
export interface WorldModelState {
isOpened: boolean // 是否已打开世界模型
catalog: Catalog // 世界模型目录数据
isDraft: boolean // 是否是草稿数据, 如果是草稿数据, 则不需要再从服务器加载数据
worldData: any // 世界模型数据, 包含排除 items 楼层数据之外的所有数据
infos: any // 当前楼层的其他数据
isChanged: boolean // 当前楼层数据是否被修改
catalog: Catalog // 当前世界模型目录数据
server: string // 当前楼层服务器地址
project_uuid: string // 当前楼层所在项目ID
catalogCode: string // 当前楼层的目录代码
stateManagerId: string // 当前楼层的状态管理器id
isDraft: boolean // 是否是草稿数据
}
/**
*
*/
export default class WorldModel {
data: any = null
currentStateManager: StateManager
/**
*
*/
state: WorldModelState = reactive({
isOpened: false, // 是否已打开世界模型
worldData: null, // 世界模型数据, 包含排除 items 楼层数据之外的所有数据
infos: {} as any, // 楼层的其他数据
isChanged: false,
catalog: [] as Catalog, // 世界模型目录
server: '',
project_uuid: '', // 项目ID
catalogCode: '', // 当前楼层的目录代码
isDraft: false, // 是否是草稿数据, 如果是草稿数据, 则不需要再从服务器加载数据
stateManagerId: '', // 当前楼层的状态管理器id, 一般是 项目ID+目录项ID
catalog: [] as Catalog // 世界模型目录
isDraft: false // 是否是草稿数据, 如果是草稿数据, 则不需要再从服务器加载数据
})
get gridOption(): IGridHelper {
const data = _.get(this.data, 'Tool.gridHelper')
const data = _.get(this.state.worldData, 'Tool.gridHelper')
return _.defaultsDeep(data, {
axesEnabled: true,
axesSize: 5,
@ -68,8 +84,6 @@ export default class WorldModel {
*/
init() {
// 观察 this.state.catalogCode 的变化, 如果变化就调用 catalogCodeChange 方法
watch(() => this.state.catalogCode, this.onCatalogCodeChanged.bind(this))
return Promise.all([
Measure,
Way,
@ -88,84 +102,111 @@ export default class WorldModel {
console.log('世界模型初始化完成')
// 尝试从草稿中加载数据
StateManager.tryLoadCatalogFromLocalstore().then(data => {
if (data.success) {
this.state.catalog = data.catalog
const stateManagerId = getQueryParams()?.get('store')
StateManager.tryLoadCatalogFromLocalstore(stateManagerId).then(data => {
if (data) {
this.state.isOpened = true
this.state.catalogCode = data.catalogCode
this.state.stateManagerId = data.stateManagerId
this.state.worldData = data.worldData
this.state.infos = data.infos
this.state.isChanged = data.isChanged
this.state.catalog = data.catalog
this.state.server = data.server
this.state.project_uuid = data.project_uuid
this.state.isDraft = true
this.tryOpenCatelog(data.catalogCode, true).then(() => {
this.state.catalogCode = data.catalogCode
this.state.stateManagerId = data.project_uuid + '_' + data.catalogCode
})
}
})
})
}
/**
*
*/
loadCatalog(data: any) {
this.data = data
this.state.catalog = data.catalog
this.state.isOpened = true
}
/**
* ,
*/
onCatalogCodeChanged(catalogCode: string) {
if (this.state.isDraft) {
// 草稿数据, 不需要再从服务器加载数据, 放行
EventBus.dispatch('catalogChanged', {
catalogCode: this.state.catalogCode,
stateManagerId: this.state.stateManagerId
})
return
}
async tryOpenCatelog(catalogCode: string, isDraft: boolean = false) {
if (!catalogCode) {
this.state.stateManagerId = ''
EventBus.dispatch('catalogChanged', {
catalogCode: this.state.catalogCode,
stateManagerId: this.state.stateManagerId
})
// 没有地图
this.clear()
return
}
const floor = _.find(this.data.items, r => r.catalogCode === catalogCode && r.t === 'floor')
if (!floor) {
system.msg('楼层不存在: ' + catalogCode)
if (!this.state.project_uuid) {
system.showErrorDialog('项目未初始化, 请先打开一个项目!')
this.state.catalogCode = ''
this.state.stateManagerId = null
return
}
this.state.stateManagerId = this.data.project_uuid + '_' + catalogCode
EventBus.dispatch('catalogChanged', {
catalogCode: this.state.catalogCode,
stateManagerId: this.state.stateManagerId
})
this.state.catalogCode = catalogCode
this.state.isDraft = isDraft
this.state.stateManagerId = this.state.project_uuid + '_' + catalogCode
const stateManager = new StateManager(this.state.stateManagerId)
if (isDraft) {
// 从草稿捞数据
await stateManager.loadFromLocalstore()
} else {
// 从服务器捞数据
const vdata = await worldModel.getCatalogData(catalogCode)
await stateManager.load(vdata)
}
this.currentStateManager = stateManager
}
/**
*
*/
async loadWorldFromRemoting(veryBigData) {
const worldData = veryBigData
const catalog = veryBigData.catalog
const items = veryBigData.items
delete veryBigData.catalog
delete veryBigData.items
this.state.isOpened = true
this.state.worldData = worldData
// 没有打开楼层,不加载 this.state.infos
// 没有打开楼层,不加载 this.state.isChanged
this.state.catalog = catalog
this.state.server = veryBigData.server
this.state.project_uuid = veryBigData.project_uuid
// 没有打开楼层,不加载 this.state.catalogCode
this.state.isDraft = false
await localforage.setItem('_____veryBigItemsData', items)
}
/**
*
*/
async getCatalogData(catalogCode: string): Promise<Partial<VData>> {
if (!this.data || !this.data.items) {
async getCatalogData(catalogCode: string): Promise<VData> {
const _____veryBigItemsData: any = await localforage.getItem('_____veryBigItemsData')
if (!_____veryBigItemsData) {
return Promise.reject('楼层数据未加载, catalogCode=' + catalogCode)
}
const floor = _.find(this.data.items, r => r.catalogCode === this.state.catalogCode && r.t === 'floor')
const floor = _.find(_____veryBigItemsData, r => r.catalogCode === this.state.catalogCode && r.t === 'floor')
if (floor) {
if (!floor.items) {
floor.items = []
}
const vdata: Partial<VData> = {
items: _.cloneDeep(floor.items) as ItemJson[],
const items = _.cloneDeep(floor.items)
delete floor.items
const vdata: VData = {
items: items as ItemJson[],
infos: floor,
isChanged: false,
server: '',
projectId: '',
catalogCode: catalogCode
catalog: _.cloneDeep(this.state.catalog),
server: this.state.server,
project_uuid: this.state.project_uuid,
catalogCode: catalogCode,
worldData: _.cloneDeep(this.state.worldData)
}
console.log('从服务器返回数据, 一共' + vdata.items.length + '个')
@ -173,4 +214,14 @@ export default class WorldModel {
}
return Promise.reject('楼层不存在, catalogCode=' + catalogCode)
}
clear() {
this.currentStateManager = null
this.state.catalogCode = ''
this.state.stateManagerId = null
setQueryParam('store', '')
EventBus.dispatch('dataLoadComplete', {
stateManager: null
})
}
}

170
src/editor/Model2DEditor.vue

@ -4,10 +4,6 @@
<span class="section-toolbar-line" style="margin-left: 85px;"></span>
<el-button :icon="renderIcon('antd ClusterOutlined')" link></el-button>
<span class="section-toolbar-line"></span>
<el-cascader placeholder="选择楼层" size="small" v-model="currentLevel"
:options="calcCatalog" filterable :show-all-levels="false" clearable
:props="{emitPath:false}" />
<span class="section-toolbar-line"></span>
<el-button-group>
<el-button :icon="renderIcon('antd CameraFilled')" link
:type="state?.view3DMode===Constract.Mode2D?'primary':''"
@ -22,7 +18,7 @@
</el-button>
<el-upload :on-change="addCADDxf"
:show-file-list="false" accept=".dxf" action="" :auto-upload="false">
<el-button :icon="renderIcon('element Files')" link >
<el-button :icon="renderIcon('element Files')" link>
添加CAD图纸
</el-button>
</el-upload>
@ -30,9 +26,9 @@
</el-button-group>
</div>
<div class="section-content">
<div v-if="currentStateManagerId" :key="currentStateManagerId || getRandom()"
:StateManagerId="currentStateManagerId"
class="canvas-container" ref="canvasContainer" tabindex="1" />
<div v-if="currentStateManagerId" :key="currentStateManagerVersion"
class="canvas-container" ref="canvasContainer" tabindex="1"
/>
</div>
<div class="section-bottom-toolbar section-toolbar" v-if="!!state">
<div class="section-toolbar-left">
@ -109,9 +105,10 @@ import Constract from '@/core/Constract'
import EventBus from '@/runtime/EventBus'
import SceneHelp from '@/core/engine/SceneHelp'
import BulkCopy from './BulkCopy.vue'
import lodash from "lodash";
import { DXFViewer } from 'three-dxf-viewer';
import cadFont from "@/assets/fonts/helvetiker_regular.typeface.json?url"
import lodash from 'lodash'
import { DXFViewer } from 'three-dxf-viewer'
import cadFont from '@/assets/fonts/helvetiker_regular.typeface.json?url'
import StateManager from '@/core/manager/StateManager.js'
export default defineComponent({
@ -124,17 +121,13 @@ export default defineComponent({
scene: null,
viewport: null,
currentStateManagerId: null,
currentStateManagerVersion: 0,
searchKeyword: ''
}
},
mounted() {
if (worldModel.state.isDraft) {
// 稿,
this.initByFloor()
}
EventBus.on('catalogChanged', (floor) => {
// ,
this.initByFloor()
this.$nextTick(() => {
this.initByFloor(worldModel.currentStateManager)
})
},
beforeUnmount() {
@ -142,20 +135,18 @@ export default defineComponent({
},
methods: {
renderIcon,
getRandom() {
return Math.random().toString(36).substring(2, 15)
},
destroyScene() {
if (this.viewport) {
this.viewport.dispose()
this.viewport = null
delete window['viewport']
}
if (this.scene) {
this.scene.dispose()
this.scene = null
delete window['scene']
}
if (this.viewport) {
this.viewport.dispose()
this.viewport = null
}
this.currentStateManagerId = null
this.currentStateManagerVersion++
this.isReady = false
},
toFixed(num) {
@ -167,28 +158,21 @@ export default defineComponent({
}
return parseFloat(num).toFixed(2)
},
initByFloor() {
initByFloor(stateManager) {
this.destroyScene()
if (!this.$el || this.$.isUnmounted) {
// ,
console.warn('Model2DEditor component is unmounted, skipping initialization.')
return
}
delete window['editor']
delete window['viewport']
delete window['scene']
delete window['stateManager']
delete window['entityManager']
delete window['renderer']
delete window['camera']
delete window['renderer']
delete window['controls']
const id = worldModel.state.stateManagerId
const id = this.worldModelState.stateManagerId
this.currentStateManagerId = id
this.currentStateManagerVersion++
if (!worldModel.state.catalogCode || !worldModel.state.isOpened || !id) {
if (!this.worldModelState.catalogCode || !this.worldModelState.isOpened || !id) {
//
setQueryParam('store', '')
return
@ -212,7 +196,7 @@ export default defineComponent({
}
const sceneHelp = new SceneHelp(worldModel, worldModel.state.catalogCode)
const viewport = new Viewport(sceneHelp, viewerDom)
const viewport = new Viewport(sceneHelp, viewerDom, stateManager)
this.scene = markRaw(sceneHelp)
this.viewport = markRaw(viewport)
@ -222,15 +206,7 @@ export default defineComponent({
setQueryParam('store', id)
// window.history.replaceState({}, '', window.location.href + '?store=' + id)
window['viewport'] = viewport
window['THREE'] = THREE
window['scene'] = sceneHelp.scene
window['stateManager'] = viewport.stateManager
window['entityManager'] = viewport.entityManager
window['renderer'] = viewport.renderer
window['camera'] = viewport.camera
window['renderer'] = viewport.renderer
window['controls'] = viewport.controls
//@ts-ignore
viewerDom.focus()
@ -249,6 +225,7 @@ export default defineComponent({
} else {
console.error('Canvas container not found after retries')
this.currentStateManagerId = ''
this.currentStateManagerVersion++
}
}
@ -258,18 +235,18 @@ export default defineComponent({
},
showBulkCopy() {
const viewport = this.viewport;
const selectedItem = viewport?.state?.selectedItem;
if(!viewport || !selectedItem) return;
const viewport = this.viewport
const selectedItem = viewport?.state?.selectedItem
if (!viewport || !selectedItem) return
const config = {
numberOfRows: 1,
numberOfColumns: 1,
rowSpace: 0,
columnSpacing: 0,
doubleRow: false,
};
doubleRow: false
}
system.showDialog(createVNode(BulkCopy, {
config,
config
}), {
title: '批量复制',
width: 520,
@ -277,83 +254,64 @@ export default defineComponent({
showClose: true,
showMax: true,
showCancelButton: false,
showOkButton: true,
showOkButton: true
}).then(() => {
if(!config.numberOfRows || !config.numberOfColumns) return;
if (!config.numberOfRows || !config.numberOfColumns) return
viewport.stateManager.update(({ getEntity, addEntity }) => {
const xAxle = selectedItem.tf[0][0];
const zAxle = selectedItem.tf[0][2];
const xSize = selectedItem.tf[2][0];
const zSize = selectedItem.tf[2][2];
console.log("item", JSON.stringify(selectedItem.tf));
for (let rCount = 0; rCount < config.numberOfRows; rCount++) {
for (let cCount = 0; cCount < config.numberOfColumns; cCount++) {
if(rCount===0 && cCount===0) continue;
const item = lodash.cloneDeep(selectedItem);
item.id = system.createUUID();
item.tf[0][0] = xAxle + cCount * (xSize + config.columnSpacing);
item.tf[0][2] = zAxle + rCount * (zSize + config.rowSpace);
addEntity(item);
console.log("item", JSON.stringify(item.tf));
}
const xAxle = selectedItem.tf[0][0]
const zAxle = selectedItem.tf[0][2]
const xSize = selectedItem.tf[2][0]
const zSize = selectedItem.tf[2][2]
console.log('item', JSON.stringify(selectedItem.tf))
for (let rCount = 0; rCount < config.numberOfRows; rCount++) {
for (let cCount = 0; cCount < config.numberOfColumns; cCount++) {
if (rCount === 0 && cCount === 0) continue
const item = lodash.cloneDeep(selectedItem)
item.id = system.createUUID()
item.tf[0][0] = xAxle + cCount * (xSize + config.columnSpacing)
item.tf[0][2] = zAxle + rCount * (zSize + config.rowSpace)
addEntity(item)
console.log('item', JSON.stringify(item.tf))
}
});
console.log("config", config, selectedItem);
}).finally();
}
})
console.log('config', config, selectedItem)
}).finally()
},
async addCADDxf(file) {
// 1
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const cube = new THREE.Mesh(geometry, material);
const geometry = new THREE.BoxGeometry(1, 1, 1)
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 })
const cube = new THREE.Mesh(geometry, material)
console.log('file', file)
if (!file) return
file = file.raw
const viewer = new DXFViewer();
let dxf = await viewer.getFromFile(file, cadFont);
const viewer = new DXFViewer()
let dxf = await viewer.getFromFile(file, cadFont)
dxf.scale.set(0.001, 0.001, 0.001)
dxf.rotation.x = -Math.PI / 2
// Add the geometry to the scene
const group = new THREE.Group();
group.add(dxf);
this.scene.add(group);
const group = new THREE.Group()
group.add(dxf)
this.scene.add(group)
}
},
computed: {
worldModelState() {
return worldModel.state
},
state() {
return this.viewport?.state
},
currentLevel: {
get() {
return worldModel.state.catalogCode
},
set(newVal) {
worldModel.state.catalogCode = newVal
}
},
calcCatalog() {
if (!worldModel.state.catalog || !worldModel.state.isOpened) {
return []
}
return worldModel.state.catalog.map(group => ({
value: group.label,
label: group.label,
children: group.items.map(item => ({
value: item.catalogCode,
label: item.label
}))
}))
},
selectedObject() {
return this.state?.selectedObject;
},
return this.state?.selectedObject
}
}
})
</script>

17
src/editor/ModelMain.vue

@ -51,7 +51,8 @@
</div>
</SplitArea>
<SplitArea class="section-center" :class="{'hidden-split':hideRight}" :size="calcCenterSize">
<el-tabs type="card" class="section-tabs" v-model="centerActiveName" @tab-click="handleCenterTabClick">
<el-tabs type="card" class="section-tabs" v-model="centerActiveName" @tab-click="handleCenterTabClick"
v-if="isShowEditor" :key="editorHash">
<el-tab-pane label="2D视图" name="ModelEditor" lazy>
<Model2DEditor @viewportChanged="setCurrentViewport" />
</el-tab-pane>
@ -115,6 +116,7 @@ import { normalizeShortKey } from '@/utils/webutils.ts'
import Logo from '@/assets/images/logo.png'
import './ModelMain.less'
import EventBus from '@/runtime/EventBus.js'
export default {
components: { Model2DEditor, Model3DViewer, Split, SplitArea },
@ -152,6 +154,15 @@ export default {
}
})
})
EventBus.on('dataLoadComplete', (data) => {
const { stateManager } = data
if (stateManager) {
this.isShowEditor = true
} else {
this.isShowEditor = false
}
this.editorHash += 1 //
})
},
unmounted() {
ModelMainUnmounted()
@ -159,6 +170,8 @@ export default {
data() {
return {
Logo,
isShowEditor: false,
editorHash: 0,
currentViewport: null,
calcRootMenu: getRootMenu(),
bottomSize: 30,
@ -304,4 +317,4 @@ export default {
}
}
}
</script>
</script>

4
src/editor/menus/FileMenu.ts

@ -26,7 +26,7 @@ export default defineMenu((menus) => {
const res = await import('@/example/example1')
worldModel.state.isDraft = false
worldModel.loadCatalog(res.default)
await worldModel.loadWorldFromRemoting(res.default)
} finally {
system.clearLoading()
@ -49,4 +49,4 @@ export default defineMenu((menus) => {
}
]
)
})
})

3
src/editor/widgets/modeltree/ModeltreeViewJs.js

@ -45,7 +45,8 @@ export default defineComponent({
return worldModel.state.catalogCode
},
set(newVal) {
worldModel.state.catalogCode = newVal
// worldModel.state.catalogCode = newVal
worldModel.tryOpenCatelog(newVal)
}
},
calcCatalog() {

142
src/example/example1.js

@ -2,6 +2,7 @@ import { buildAgvPerformanceData, buildCenterLinkPerformanceData, buildPointPerf
export default {
project_uuid: 'example1',
server: 'demo',
Tool: {
Group: [], // 分组
GlobalVariables: [], // 全局变量
@ -325,13 +326,61 @@ export default {
{
catalogCode: 'f3', t: 'floor',
items: [
// {
// id: 'node1',
// // t: 'gstore',
// // t: 'carton',
// t: 'measure',
// v: true,
// tf: [[0, 0, 0], [0, 0, 0], [2, 0.05, 1]],
// dt: { in: [], out: [], center: [] }
// },
// 双向连接路径
{
id: 'gstore1',
t: 'gstore',
// t: 'carton',
id: 'way11',
t: 'way',
v: true,
tf: [[0, 0, 0], [0, 0, 0], [2, 0.05, 1]],
dt: { in: [], out: [], center: [] }
tf: [[2, 0.1, 1], [0, 0, 0], [1.0, 1.0, 1.0]],
dt: { in: ['way12'], out: ['way12'], center: [] }
},
{
id: 'way12',
t: 'way',
v: true,
tf: [[5, 0.1, 1], [0, 0, 0], [1.0, 1.0, 1.0]],
dt: { in: ['way11'], out: ['way11'], center: [] }
},
// 21->22 单向连接路径
{
id: 'way21',
t: 'way',
v: true,
tf: [[2, 0.1, 3], [0, 0, 0], [1.0, 1.0, 1.0]],
dt: { in: [], out: ['way22'], center: [] }
},
{
id: 'way22',
t: 'way',
v: true,
tf: [[5, 0.1, 3], [0, 0, 0], [1.0, 1.0, 1.0]],
dt: { in: ['way21'], out: [], center: [] }
},
// 32->31 单向连接路径
{
id: 'way31',
t: 'way',
v: true,
tf: [[2, 0.1, 5], [0, 0, 0], [1.0, 1.0, 1.0]],
dt: { in: ['way32'], out: [], center: [] }
},
{
id: 'way32',
t: 'way',
v: true,
tf: [[5, 0.1, 5], [0, 0, 0], [1.0, 1.0, 1.0]],
dt: { in: [], out: ['way31'], center: [] }
}
]
},
@ -403,6 +452,29 @@ export default {
v: true,
tf: [[5, 0, 5], [0, 0, 0], [2, 1, 1]],
dt: { in: [], out: [], center: [] }
},
// 尺
{
id: 'measure11',
t: 'measure',
v: true,
tf: [[2, 0.1, 1], [0, 0, 0], [1.0, 1.0, 1.0]],
dt: { in: [], out: [], center: ['measure12', 'measure13'] }
},
{
id: 'measure12',
t: 'measure',
v: true,
tf: [[5, 0.1, 1], [0, 0, 0], [1.0, 1.0, 1.0]],
dt: { in: [], out: [], center: ['measure11'] }
},
{
id: 'measure13',
t: 'measure',
v: true,
tf: [[2, 0.1, 3], [0, 0, 0], [1.0, 1.0, 1.0]],
dt: { in: [], out: [], center: ['measure22', 'measure11'] }
}
]
},
@ -846,36 +918,36 @@ export default {
}
]
},
{
catalogCode: 'flash1', t: 'floor',
items: [
{
id: 'flash_rack1',
t: 'flash_rack',
dt: async () => import('./flash.js')
}
]
},
{
catalogCode: 'flash2', t: 'floor',
items: [
{
id: 'flash_rack1',
t: 'flash_rack',
dt: async () => import('./flash.js')
}
]
},
{
catalogCode: 'flash3', t: 'floor',
items: [
{
id: 'flash_rack1',
t: 'flash_rack',
dt: async () => import('./flash.js')
}
]
},
// {
// catalogCode: 'flash1', t: 'floor',
// items: [
// {
// id: 'flash_rack1',
// t: 'flash_rack',
// dt: async () => import('./flash.js')
// }
// ]
// },
// {
// catalogCode: 'flash2', t: 'floor',
// items: [
// {
// id: 'flash_rack1',
// t: 'flash_rack',
// dt: async () => import('./flash.js')
// }
// ]
// },
// {
// catalogCode: 'flash3', t: 'floor',
// items: [
// {
// id: 'flash_rack1',
// t: 'flash_rack',
// dt: async () => import('./flash.js')
// }
// ]
// },
{
catalogCode: 'de1', t: 'side',
floorHeight: [ // 侧面视图的各层面高度

12
src/modules/carton/CartonRenderer.ts

@ -1,11 +1,11 @@
import * as THREE from 'three'
import BaseRenderer from '@/core/base/BaseRenderer.ts'
import Constract from '@/core/Constract.ts'
import InstancePointManager from '@/core/manager/InstancePointManager.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts'
import MODULE_GLB_File from '@/assets/Models/carton.glb?url'
import MODULE_3DS_TEX from '@/assets/Models/carton.jpg?url'
import { loadGlbModule, loadTexture, processModel } from '@/core/ModelUtils.ts'
import InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts'
/**
*
@ -58,21 +58,21 @@ export default class PalletRenderer extends BaseRenderer {
}
createPointBasic(item: ItemJson, option?: RendererCudOption): Object3DLike {
return this.pointManager.createPoint(item)
return this.pointManager.createByItem(item)
}
get pointManager(): InstancePointManager {
get pointManager(): InstanceMeshManager {
if (!this.tempViewport) {
throw new Error('tempViewport is not set.')
}
return this.tempViewport.getOrCreatePointManager(this.itemTypeName, () =>
return this.tempViewport.getOrCreateMeshManager(this.itemTypeName, () => {
// 构建 InstanceMesh 代理对象
InstancePointManager.create(this.itemTypeName,
return new InstanceMeshManager(this.itemTypeName,
this.tempViewport,
this.cartonGeometry,
this.cartonMaterial,
true, true)
)
})
}
dispose() {

11
src/modules/gstore/GstoreRenderer.ts

@ -2,11 +2,8 @@ import * as THREE from 'three'
import BaseRenderer from '@/core/base/BaseRenderer.ts'
import Constract from '@/core/Constract.ts'
import { type Object3DLike } from '@/types/ModelTypes.ts'
import InstancePointManager from '@/core/manager/InstancePointManager.ts'
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial'
import { getMatrixFromTf } from '@/core/ModelUtils.ts'
import InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts'
import { translate } from 'element-plus'
/**
*
@ -49,7 +46,7 @@ export default class GstoreRenderer extends BaseRenderer {
strokeGeometry = new THREE.BoxGeometry(1, 1, 1)
createPointBasic(item: ItemJson, option?: RendererCudOption): Object3DLike {
return this.pointManager.createPoint(item)
return this.pointManager.createByItem(item)
}
createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): THREE.Object3D {
@ -137,13 +134,13 @@ export default class GstoreRenderer extends BaseRenderer {
// this.strokeMaterial.dispose()
}
get pointManager(): InstancePointManager {
get pointManager(): InstanceMeshManager {
if (!this.tempViewport) {
throw new Error('tempViewport is not set.')
}
return this.tempViewport.getOrCreatePointManager(this.itemTypeName, () =>
return this.tempViewport.getOrCreateMeshManager(this.itemTypeName, () =>
// 构建 InstanceMesh 代理对象
InstancePointManager.create(this.itemTypeName,
new InstanceMeshManager(this.itemTypeName,
this.tempViewport,
this.pointGeometry,
this.pointMaterial,

45
src/modules/measure/MeasureRenderer.ts

@ -3,9 +3,9 @@ import BaseRenderer from '@/core/base/BaseRenderer.ts'
import { getLineId } from '@/core/ModelUtils.ts'
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js'
import Constract from '@/core/Constract.ts'
import InstancePointManager from '@/core/manager/InstancePointManager.ts'
import LineSegmentManager from '@/core/manager/LineSegmentManager.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts'
import LineSegmentManager, { LineWrap } from '@/core/manager/LineSegmentManager.ts'
import type { LineLike, Object3DLike } from '@/types/ModelTypes.ts'
import InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts'
/**
*
@ -27,29 +27,13 @@ export default class MeasureRenderer extends BaseRenderer {
lineMaterial: LineMaterial = new LineMaterial({
color: 0xFF8C00,
linewidth: 1,
vertexColors: false,
vertexColors: true,
dashed: false
})
readonly defulePositionY = Constract.HEIGHT_MEASURE
readonly defaultScale: THREE.Vector3 = new THREE.Vector3(0.25, 0.25, 0.1)
readonly defaultRotation: THREE.Vector3 = new THREE.Vector3(90, 0, 0)
/**
* 使,
*/
override afterCreateOrUpdatePoint(item: ItemJson, option: RendererCudOption, object: Object3DLike) {
super.afterCreateOrUpdatePoint(item, option, object)
const point = object
point.scale.set(this.defaultScale.x, this.defaultScale.y, this.defaultScale.z)
point.rotation.set(
THREE.MathUtils.degToRad(this.defaultRotation.x),
THREE.MathUtils.degToRad(this.defaultRotation.y),
THREE.MathUtils.degToRad(this.defaultRotation.z)
)
}
createPointBasic(item: ItemJson, option?: RendererCudOption): Object3DLike {
// 不允许改变高度/角度/大小
item.tf = [
@ -57,15 +41,16 @@ export default class MeasureRenderer extends BaseRenderer {
[this.defaultRotation.x, this.defaultRotation.y, this.defaultRotation.z],
[this.defaultScale.x, this.defaultScale.y, this.defaultScale.z]
]
return this.pointManager.createPoint(item)
const lm = this.lineSegmentManager
return this.pointManager.createByItem(item)
}
createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): Object3DLike {
createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): LineLike {
const lineId = getLineId(start.id, end.id, type)
return this.lineSegmentManager.createLine(lineId, start.tf[0], end.tf[0], this.lineMaterial.color)
return this.lineSegmentManager.createOrUpdateLine(lineId, start.tf[0], end.tf[0], this.lineMaterial.color)
}
afterCreateOrUpdateLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: Object3DLike) {
afterCreateOrUpdateLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: LineLike) {
super.afterCreateOrUpdateLine(start, end, type, option, object)
const startPoint = this.tempViewport?.entityManager.findObjectById(start.id)
@ -81,16 +66,16 @@ export default class MeasureRenderer extends BaseRenderer {
afterDeleteLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption) {
const lineId = getLineId(start.id, end.id, type)
const object = this.tempViewport.entityManager.findLineObjectById(lineId)
this.tempViewport.labelManager.removeLabel(object)
// this.tempViewport.labelManager.removeLabel(object)
}
get pointManager(): InstancePointManager {
get pointManager(): InstanceMeshManager {
if (!this.tempViewport) {
throw new Error('tempViewport is not set.')
}
return this.tempViewport.getOrCreatePointManager(this.itemTypeName, () =>
return this.tempViewport.getOrCreateMeshManager(this.itemTypeName, () =>
// 构建 InstanceMesh 代理对象
InstancePointManager.create(this.itemTypeName,
new InstanceMeshManager(this.itemTypeName,
this.tempViewport,
this.pointGeometry,
this.pointMaterial,
@ -104,9 +89,7 @@ export default class MeasureRenderer extends BaseRenderer {
}
return this.tempViewport.getOrCreateLineManager(this.itemTypeName, () =>
// 构建 LineSegment.points 代理对象
LineSegmentManager.create(this.itemTypeName,
this.tempViewport,
this.lineMaterial)
new LineSegmentManager(this.itemTypeName, this.tempViewport, this.lineMaterial)
)
}

10
src/modules/pallet/PalletRenderer.ts

@ -6,6 +6,7 @@ import type { Object3DLike } from '@/types/ModelTypes.ts'
import MODULE_GLB_File from '@/assets/Models/Pallet.glb?url'
import MODULE_3DS_TEX from '@/assets/Models/Pallet.jpg?url'
import { load3DModule, loadByUrl, loadGlbModule, loadTexture, processModel } from '@/core/ModelUtils.ts'
import InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts'
/**
*
@ -27,7 +28,6 @@ export default class PalletRenderer extends BaseRenderer {
palletMaterial: THREE.Material
init() {
return Promise.all([
super.init(),
@ -53,16 +53,16 @@ export default class PalletRenderer extends BaseRenderer {
}
createPointBasic(item: ItemJson, option?: RendererCudOption): Object3DLike {
return this.pointManager.createPoint(item)
return this.pointManager.createByItem(item)
}
get pointManager(): InstancePointManager {
get pointManager(): InstanceMeshManager {
if (!this.tempViewport) {
throw new Error('tempViewport is not set.')
}
return this.tempViewport.getOrCreatePointManager(this.itemTypeName, () =>
return this.tempViewport.getOrCreateMeshManager(this.itemTypeName, () =>
// 构建 InstanceMesh 代理对象
InstancePointManager.create(this.itemTypeName,
new InstanceMeshManager(this.itemTypeName,
this.tempViewport,
this.palletGeometry,
this.palletMaterial,

9
src/modules/tote/ToteRenderer.ts

@ -6,6 +6,7 @@ import type { Object3DLike } from '@/types/ModelTypes.ts'
import MODULE_3DS_File from '@/assets/Models/Tote.3ds?url'
import MODULE_3DS_TEX from '@/assets/Models/ToteTex.png?url'
import { load3DModule, loadByUrl, loadTexture, processModel } from '@/core/ModelUtils.ts'
import InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts'
/**
*
@ -96,16 +97,16 @@ export default class PalletRenderer extends BaseRenderer {
}
createPointBasic(item: ItemJson, option?: RendererCudOption): Object3DLike {
return this.pointManager.createPoint(item)
return this.pointManager.createByItem(item)
}
get pointManager(): InstancePointManager {
get pointManager(): InstanceMeshManager {
if (!this.tempViewport) {
throw new Error('tempViewport is not set.')
}
return this.tempViewport.getOrCreatePointManager(this.itemTypeName, () =>
return this.tempViewport.getOrCreateMeshManager(this.itemTypeName, () =>
// 构建 InstanceMesh 代理对象
InstancePointManager.create(this.itemTypeName,
new InstanceMeshManager(this.itemTypeName,
this.tempViewport,
this.toteGeometry,
this.toteMaterial,

21
src/modules/way/WayRenderer.ts

@ -1,7 +1,7 @@
import * as THREE from 'three'
import BaseRenderer from '@/core/base/BaseRenderer.ts'
import MoveLinePointPng from '@/assets/images/moveline_point.png'
import { createLinkPlaneMatrix4, getCargoLineId, getLinkDirection } from '@/core/ModelUtils.ts'
import { createLinkPlaneMatrix4, getCargoLineId, getLinkDirection, getMatrixFromTf } from '@/core/ModelUtils.ts'
import Constract from '@/core/Constract.ts'
import InstancePointManager from '@/core/manager/InstancePointManager.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts'
@ -99,7 +99,7 @@ export default class WayRenderer extends BaseRenderer {
[this.defaultRotation.x, this.defaultRotation.y, this.defaultRotation.z],
[this.defaultScale.x, this.defaultScale.y, this.defaultScale.z]
]
return this.pointManager.createPoint(item)
return this.pointManager.createByItem(item)
}
createLine(start: ItemJson, end: ItemJson, type: LinkType): Object3DLike {
@ -128,14 +128,19 @@ export default class WayRenderer extends BaseRenderer {
return
}
const startPosition = new THREE.Vector3(start.tf[0][0], this.defulePositionY, start.tf[0][2])
const endPosition = new THREE.Vector3(end.tf[0][0], this.defulePositionY, end.tf[0][2])
const startMatrix = getMatrixFromTf(start.tf) // new THREE.Vector3(start.tf[0][0], this.defulePositionY, start.tf[0][2])
const endMatrix = getMatrixFromTf(end.tf) // new THREE.Vector3(end.tf[0][0], this.defulePositionY, end.tf[0][2])
const startPosition = new THREE.Vector3()
const endPosition = new THREE.Vector3()
startMatrix.decompose(startPosition, new THREE.Quaternion(), new THREE.Vector3())
endMatrix.decompose(endPosition, new THREE.Quaternion(), new THREE.Vector3())
const wrap = this.guidewayManager.create(lineId, {})
wrap.uuid = lineId
const matrix = createLinkPlaneMatrix4(startPosition, endPosition, this.rendererOption.lineWidth)
wrap.setMatrix4(matrix)
const length = startPosition.distanceTo(endPosition)
if (length < 0.1) {
// 如果两点距离小于 0.1m,则不添加方向指示器
@ -322,13 +327,13 @@ export default class WayRenderer extends BaseRenderer {
})
}
get pointManager(): InstancePointManager {
get pointManager(): InstanceMeshManager {
if (!this.tempViewport) {
throw new Error('tempViewport is not set.')
}
return this.tempViewport.getOrCreatePointManager(this.itemTypeName, () =>
return this.tempViewport.getOrCreateMeshManager(this.itemTypeName, () =>
// 构建 InstanceMesh 代理对象
InstancePointManager.create(this.itemTypeName,
new InstanceMeshManager(this.itemTypeName,
this.tempViewport,
this.pointGeometry,
this.pointMaterial,

1
src/runtime/EventBus.ts

@ -3,7 +3,6 @@ import mitt from 'mitt'
const instance = mitt()
export type DispatchNames = 'selectedObjectChanged' |
'catalogChanged' |
'dataLoadComplete' |
'selectedObjectPropertyChanged' |
'multiSelectedObjectsChanged'

3
src/runtime/System.ts

@ -250,8 +250,6 @@ export default class System {
const _insId = _.uniqueId('_dlg')
console.trace()
console.time('showLoading')
system.rootElementList.push({
cmp: markRaw(LoadingDialog),
props: {
@ -269,7 +267,6 @@ export default class System {
* ...
*/
public clearLoading(): void {
console.timeEnd('showLoading')
if (typeof this.globalLoadingHandle === 'function') {
this.globalLoadingHandle()
}

17
src/types/ModelTypes.ts

@ -1,8 +1,7 @@
import { Object3D } from 'three'
import LineSegmentManager, { LineManageWrap } from '@/core/manager/LineSegmentManager.ts'
import InstancePointManager, { PointManageWrap } from '@/core/manager/InstancePointManager.ts'
import * as THREE from 'three'
import { InstanceMeshWrap } from '@/core/manager/InstanceMeshManager.ts'
import { MeshWrap } from '@/core/manager/InstanceMeshManager.ts'
import type { LineWrap } from '@/core/manager/LineSegmentManager.ts'
//
// /**
// * 点数据接口, 用于平衡 Object3D 一致的取数方式
@ -57,17 +56,9 @@ export const BasePlane = {
}
}
export interface LineManageReference {
manager: LineSegmentManager
id: string
}
export interface PointManagerReference {
manager: InstancePointManager
id: string
}
export type Object3DLike = Object3D | MeshWrap
export type Object3DLike = Object3D | PointManageWrap | InstanceMeshWrap
export type LineLike = Object3D | LineWrap
/**
* , THREE.Vector3

15
src/types/Types.d.ts

@ -19,14 +19,14 @@ interface VData {
items: ItemJson[]
/**
*
*
*/
isChanged: boolean
infos: any
/**
* id
*
*/
id: string
isChanged: boolean
/**
*
@ -41,12 +41,17 @@ interface VData {
/**
* ID
*/
projectId?: string
project_uuid?: string
/**
*
*/
catalogCode: string
/**
*
*/
worldData: any
}
interface CatalogItem {

Loading…
Cancel
Save