diff --git a/src/core/base/BaseInteraction.ts b/src/core/base/BaseInteraction.ts index 29e31e5..a00fb92 100644 --- a/src/core/base/BaseInteraction.ts +++ b/src/core/base/BaseInteraction.ts @@ -98,8 +98,6 @@ export default abstract class BaseInteraction { } // 提交状态管理器 - console.log('drag from ', [this.dragItem.tf[0][0], this.dragItem.tf[0][2]], 'to', [CurrentMouseInfo.x, CurrentMouseInfo.z]) - const stateManager = this.viewport.stateManager stateManager.beginStateUpdate({ createFromInteraction: true }) this.dragItem.tf[0][0] = CurrentMouseInfo.x diff --git a/src/core/base/BaseRenderer.ts b/src/core/base/BaseRenderer.ts index b11cf95..ca89a9e 100644 --- a/src/core/base/BaseRenderer.ts +++ b/src/core/base/BaseRenderer.ts @@ -229,6 +229,7 @@ export default abstract class BaseRenderer { */ updateLine(start: ItemJson, end: ItemJson, type: LinkType, option?: RendererCudOption) { const lineId = getLineId(start.id, end.id, type) + console.log('updateline ', lineId) const lines = this.tempViewport.entityManager.findLineObjectsById(lineId) _.forEach(lines, (line: THREE.Object3D) => { @@ -251,15 +252,20 @@ export default abstract class BaseRenderer { * @param option 渲染选项 */ deleteLine(start: ItemJson, end: ItemJson, type: LinkType, option?: RendererCudOption) { - const id = getLineId(start.id, end.id, type) - const lines = this.tempViewport.entityManager.findLineObjectsById(id) + const lineId = getLineId(start.id, end.id, type) + console.log('deleteline ', lineId) + const lines = this.tempViewport.entityManager.findLineObjectsById(lineId) if (lines) { this.removeFromScene(...lines) } - this.tempViewport.entityManager.deleteLineObjectOnly(id) + this.tempViewport.entityManager.deleteLineObjectOnly(lineId) this.afterDeleteLine(start, end, type, option, lines) } + dispose() { + // 清理资源 + this.isUpdating = false + } } diff --git a/src/core/base/IMeta.ts b/src/core/base/IMeta.ts index b9bb8d3..680d003 100644 --- a/src/core/base/IMeta.ts +++ b/src/core/base/IMeta.ts @@ -35,11 +35,7 @@ export const BASIC_META_OF_LINE2: ItemTypeMeta = [] /** * 属性面板元数据声明, 第一级 category, 第二级 tabName, 第三级 MetaItem */ -export interface IMeta { - [key: string]: { - [tabName: string]: MetaItem[] - } -} +export type IMeta = MetaItem[] /** * PropertyPanelConfig interface @@ -50,6 +46,7 @@ export interface MetaItem { editor: string; label?: string; readonly?: boolean; + category?: string; [key: string]: any; } \ No newline at end of file diff --git a/src/core/controls/EsDragControls.ts b/src/core/controls/EsDragControls.ts index 5005dbd..1911383 100644 --- a/src/core/controls/EsDragControls.ts +++ b/src/core/controls/EsDragControls.ts @@ -5,7 +5,7 @@ import { getItemTypeByName } from '@/model/itemType/ItemTypeDefine' import type { ItemTypeDefineOption } from '@/model/itemType/ItemTypeDefine' import { markRaw } from 'vue' import EventBus from '@/runtime/EventBus' -import { getInteraction } from '@/core/manager/ModuleManager.ts' +import { getInteraction, getMeta } from '@/core/manager/ModuleManager.ts' import type BaseInteraction from '@/core/base/BaseInteraction.ts' // dragControls 绑定函数 @@ -114,10 +114,6 @@ export default class EsDragControls { // 拖拽中 drag(e) { this.currentInteraction?.dragPointMove(this.viewport, e) - EventBus.dispatch('objectChanged', { - viewport: this, - object: e.object - }) } // 拖拽结束 @@ -131,12 +127,24 @@ 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) - EventBus.dispatch('objectChanged', { - viewport: this, - object: e.object - }) + if (e.object.userData?.entityId) { + const entityId = e.object.userData.entityId + const item = this.viewport.entityManager.findItemById(entityId) + const itemTypeName = e.object.userData.t + if (item.dt.protected !== true) { + this.viewport.state.selectedObject = markRaw(e.object) + this.viewport.state.selectedItem = markRaw(item) + this.viewport.state.selectedEntityId = entityId + this.viewport.state.selectedObjectMeta = getMeta(itemTypeName) + + EventBus.dispatch('selectedObjectChanged', { + viewport: this, + selectedObject: this.viewport.state.selectedObject, + selectedItem: this.viewport.state.selectedItem, + selectedEntityId: this.viewport.state.selectedEntityId, + selectedObjectMeta: this.viewport.state.selectedObjectMeta + }) + } } } diff --git a/src/core/controls/IControls.ts b/src/core/controls/IControls.ts index 2476375..ab341c7 100644 --- a/src/core/controls/IControls.ts +++ b/src/core/controls/IControls.ts @@ -1,7 +1,7 @@ export default interface IControls { init(viewport: any): void - destory(): void + dispose(): void animate?: () => void; } \ No newline at end of file diff --git a/src/core/controls/MouseMoveInspect.ts b/src/core/controls/MouseMoveInspect.ts index 27ea283..8ed262e 100644 --- a/src/core/controls/MouseMoveInspect.ts +++ b/src/core/controls/MouseMoveInspect.ts @@ -26,7 +26,7 @@ export default class MouseMoveInspect implements IControls { this.canvas.addEventListener('mouseleave', lvFn) } - destory() { + dispose() { this.canvas.removeEventListener('pointermove', pmFn) pmFn = undefined this.canvas.removeEventListener('pointerout', otFn) diff --git a/src/core/controls/SelectInspect.ts b/src/core/controls/SelectInspect.ts index 9024857..49feb42 100644 --- a/src/core/controls/SelectInspect.ts +++ b/src/core/controls/SelectInspect.ts @@ -63,8 +63,7 @@ export default class SelectInspect implements IControls { puFn = this.onMouseUp.bind(this) this.canvas.addEventListener('pointerup', puFn) - this.viewport.watchList.push(watch(() => this.viewport.state.selectedObject, this.updateSelectionBox.bind(this))) - EventBus.on('objectChanged', (data) => { + EventBus.on('selectedObjectChanged', (data) => { this.updateSelectionBox(this.viewport.state.selectedObject) }) } @@ -74,50 +73,41 @@ export default class SelectInspect implements IControls { */ updateSelectionBox(selectedObject: THREE.Object3D) { this.disposeSelectionBox() - this.viewport.state.selectedObjectMeta = null // 清除之前的元数据 - if (selectedObject?.userData?.type) { - const type = selectedObject.userData.type - const itemTypeDefine = getItemTypeByName(type) - if (itemTypeDefine) { - this.viewport.state.selectedObjectMeta = itemTypeDefine.getMeta(selectedObject) + const expandAmount = 0.2 // 扩展包围盒的大小 + // 避免某些蒙皮网格的帧延迟效应(e.g. Michelle.glb) + selectedObject.updateWorldMatrix(false, true) - const expandAmount = 0.2 // 扩展包围盒的大小 - // 避免某些蒙皮网格的帧延迟效应(e.g. Michelle.glb) - selectedObject.updateWorldMatrix(false, true) + const box = new THREE.Box3().setFromObject(selectedObject) + box.expandByScalar(expandAmount) - const box = new THREE.Box3().setFromObject(selectedObject) - box.expandByScalar(expandAmount) + const size = new THREE.Vector3() + box.getSize(size) - const size = new THREE.Vector3() - box.getSize(size) + const center = new THREE.Vector3() + box.getCenter(center) - 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) - // 创建包围盒几何体 - 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) - // 使用 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 - const selectionBox = new Line2(lineGeom, this.material) - selectionBox.computeLineDistances() - selectionBox.position.copy(center) - selectionBox.name = 'selectionBox' - this.selectionBox = selectionBox + console.log('selectedItem', this.viewport.state.selectedItem) - this.viewport.scene.add(selectionBox) - - } - } + this.viewport.scene.add(selectionBox) } - destory() { - + dispose() { this.canvas.removeEventListener('pointerdown', pdFn) pdFn = undefined this.canvas.removeEventListener('pointermove', pmFn) diff --git a/src/core/engine/SceneHelp.ts b/src/core/engine/SceneHelp.ts index 03c60ef..6ca655d 100644 --- a/src/core/engine/SceneHelp.ts +++ b/src/core/engine/SceneHelp.ts @@ -95,7 +95,7 @@ export default class SceneHelp { /** * 销毁场景, 释放全部 WebGL 资源 */ - destory() { + dispose() { // 移除旧模型 if (!this.scene) { return diff --git a/src/core/engine/Viewport.ts b/src/core/engine/Viewport.ts index d2cac25..5aade39 100644 --- a/src/core/engine/Viewport.ts +++ b/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 { reactive, toRaw, watch } from 'vue' +import { markRaw, reactive, toRaw, watch } from 'vue' import type IControls from '../controls/IControls' import { CSS3DRenderer } from 'three/examples/jsm/renderers/CSS3DRenderer' import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer' @@ -20,6 +20,7 @@ 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 type { IMeta } from '@/core/base/IMeta.ts' /** * 视窗对象 @@ -376,7 +377,7 @@ export default class Viewport { this.gridHelper.visible = opacity > 0 } - destroy() { + dispose() { this.state.isReady = false if (this.animationFrameId !== null) { @@ -395,8 +396,8 @@ export default class Viewport { if (this.tools) { for (const tool of this.tools) { - if (tool.destory) { - tool.destory() + if (tool.dispose) { + tool.dispose() } } this.tools = [] @@ -418,6 +419,31 @@ export default class Viewport { console.log('WebGL disposed, memory:', this.renderer.info.memory) this.renderer.domElement = null } + + if (this.controls) { + this.controls.dispose() + this.controls = null + } + + if (this.dragControl) { + this.dragControl.dispose() + this.dragControl = null + } + + if (this.interactionManager) { + this.interactionManager.dispose() + this.interactionManager = null + } + + if (this.stateManager) { + this.stateManager.dispose() + this.stateManager = null + } + + if (this.entityManager) { + this.entityManager.dispose() + this.entityManager = null + } } getIntersects(point: THREE.Vector2) { @@ -461,12 +487,16 @@ export interface ViewportState { /** * 选中的对象 */ - selectedObject: THREE.Object3D | null + selectedObject: THREE.Object3D | undefined + + selectedItem: ItemJson | undefined + + selectedEntityId: string | undefined /** * 选中的对象的元数据 */ - selectedObjectMeta: ItemTypeMeta | null + selectedObjectMeta: IMeta | undefined /** * 是否正在更新中 diff --git a/src/core/manager/EntityManager.ts b/src/core/manager/EntityManager.ts index a51ec4f..44d1ff9 100644 --- a/src/core/manager/EntityManager.ts +++ b/src/core/manager/EntityManager.ts @@ -4,36 +4,6 @@ import type BaseRenderer from '@/core/base/BaseRenderer' import { getRenderer } from './ModuleManager' import { getLineId, parseLineId } from '@/core/ModelUtils' -/** - * 关系详情 - */ -export class Relation { - center = new Set() - input = new Set() - output = new Set() - - add(type: LinkType, id: string) { - if (type === 'in') - return this.input.add(id) - else if (type === 'out') - return this.output.add(id) - else if (type === 'center') - return this.center.add(id) - else - throw new Error(`Unknown link type: ${type}`) - } - - delete(type: LinkType, id: string) { - if (type === 'in') - return this.input.delete(id) - else if (type === 'out') - return this.output.delete(id) - else if (type === 'center') - return this.center.delete(id) - else - throw new Error(`Unknown link type: ${type}`) - } -} /** * 实体管理器 @@ -66,10 +36,37 @@ export default class EntityManager { update: new Map(), delete: new Map() } + // 记录所有发生过变化的实体, 用于在 endEntityUpdate 时进行写回给 StateManager + private readonly writeBackEntities = new Set() isUpdating = false - getAllEntities(): Map { - return this.entities + dispose() { + // 清理所有差量渲染器 + for (const renderer of this.diffRenderer.values()) { + renderer.dispose() + } + this.diffRenderer.clear() + + // 清理所有实体和关系索引 + this.entities.clear() + this.relationIndex.clear() + this.objects.clear() + this.lines.clear() + this.writeBackEntities.clear() + } + + /** + * 克隆需要回写的实体集合 + */ + cloneWriteBackEntities(): Map { + const entities = new Map() + for (const id of this.writeBackEntities) { + const entity = this.entities.get(id) + if (!entity) continue + entities.set(id, _.cloneDeep(entity)) + } + console.log('需要回写', entities.size, '行数据') + return entities } init(viewport: Viewport) { @@ -82,6 +79,7 @@ export default class EntityManager { beginEntityUpdate(): void { this.isUpdating = true this.viewport.beginViewUpdate() + this.writeBackEntities.clear() this.diffRenderer.clear() this.lineDiffs.create.clear() this.lineDiffs.update.clear() @@ -96,34 +94,36 @@ export default class EntityManager { throw new Error('Entity must have an id') } const entity = _.cloneDeep(entityRaw) as ItemJson + const originEntity = this.entities.get(entity.id) // 找到这个数据的渲染器 const renderer = this.getDiffRenderer(entity.t) - const originEntity = this.entities.get(entity.id) + // 先判断坐标是否变化 + const coordinateChanged = originEntity?.tf && entity?.tf && !_.isEqual(originEntity.tf[0], entity.tf[0]) + this.entities.set(entity.id, entity) // 更新关系网 this.updateRelations(entity, originEntity) - // 判断坐标是否变化 - - if (originEntity?.tf && entity?.tf && !_.isEqual(originEntity.tf[0], entity.tf[0])) { + if (coordinateChanged) { + this.writeBackEntities.add(entity.id) // 点的坐标发生变化, 要通知所有关联线更新 - const relations = this.relationIndex.get(entity.id) - if (!relations) return - - for (const type of (['center', 'in', 'out'] as LinkType[])) { - const relatedIds = relations[type] - if (!relatedIds) continue - - for (const relatedId of relatedIds) { - const lineId = getLineId(entity.id, relatedId, type) - this.lineDiffs.update.set(lineId, { startId: entity.id, endId: relatedId, type }) - - // 如果是双向线(比如 center),也要反向加一次 - if (type === 'center') { - this.lineDiffs.update.set(lineId, { startId: relatedId, endId: entity.id, type }) + const relation = this.relationIndex.get(entity.id) + if (relation) { + for (const type of (['center', 'in', 'out'] as LinkType[])) { + const relatedIds = relation[type] + if (!relatedIds) continue + + for (const relatedId of relatedIds) { + const lineId = getLineId(entity.id, relatedId, type) + this.lineDiffs.update.set(lineId, { startId: entity.id, endId: relatedId, type }) + + // 如果是双向线(比如 center),也要反向加一次 + if (type === 'center') { + this.lineDiffs.update.set(lineId, { startId: relatedId, endId: entity.id, type }) + } } } } @@ -146,6 +146,7 @@ export default class EntityManager { if (!entity) return option.originEntity = _.cloneDeep(entity) + this.writeBackEntities.add(entity.id) // 先生成线差量,再清理关系 this.generateLineDiffsForDelete(id) @@ -210,6 +211,7 @@ export default class EntityManager { if (start.t !== itemTypeName) { // 只通知起点对应的渲染器 + console.error(`Line ${lineId} start point type mismatch: expected ${itemTypeName}, got ${start.t}`) continue } renderer.updateLine(start, end, lineDiffItem.type) @@ -312,6 +314,7 @@ export default class EntityManager { if (!newIds.has(relatedId)) { const rev = this.relationIndex.get(relatedId) rev.delete(relationType, id) + this.writeBackEntities.add(id) } } @@ -324,6 +327,7 @@ export default class EntityManager { this.relationIndex.set(relatedId, rev) } rev.add(relationType, id) + this.writeBackEntities.add(id) } } } @@ -360,16 +364,19 @@ export default class EntityManager { relations.center.forEach(relatedId => { const rev = this.relationIndex.get(relatedId) if (rev) rev.center.delete(id) + this.writeBackEntities.add(relatedId) }) relations.input.forEach(relatedId => { const rev = this.relationIndex.get(relatedId) if (rev) rev.output.delete(id) + this.writeBackEntities.add(relatedId) }) relations.output.forEach(relatedId => { const rev = this.relationIndex.get(relatedId) if (rev) rev.input.delete(id) + this.writeBackEntities.add(relatedId) }) this.relationIndex.delete(id) @@ -496,3 +503,34 @@ interface LineDiffItem { type: LinkType } + +/** + * 关系详情 + */ +export class Relation { + center = new Set() + input = new Set() + output = new Set() + + add(type: LinkType, id: string) { + if (type === 'in') + return this.input.add(id) + else if (type === 'out') + return this.output.add(id) + else if (type === 'center') + return this.center.add(id) + else + throw new Error(`Unknown link type: ${type}`) + } + + delete(type: LinkType, id: string) { + if (type === 'in') + return this.input.delete(id) + else if (type === 'out') + return this.output.delete(id) + else if (type === 'center') + return this.center.delete(id) + else + throw new Error(`Unknown link type: ${type}`) + } +} \ No newline at end of file diff --git a/src/core/manager/InteractionManager.ts b/src/core/manager/InteractionManager.ts index 3b4c48f..3e31109 100644 --- a/src/core/manager/InteractionManager.ts +++ b/src/core/manager/InteractionManager.ts @@ -54,7 +54,7 @@ export default class InteractionManager implements IControls { this.viewport.state.cursorMode = 'normal' this.viewport.dragControl.dragControls.enabled = true - debugger + this.viewport.viewerDom.style.cursor = '' system.msg('退出新建模式') } @@ -92,7 +92,7 @@ export default class InteractionManager implements IControls { // 初始化交互 this.currentTool = interaction this.viewport.dragControl.dragControls.enabled = false - debugger + this.currentTool.start(this.viewport, { startPoint: this.toolStartObject }) // 更新 UI 状态 @@ -101,7 +101,7 @@ export default class InteractionManager implements IControls { system.msg(`enter [${mode}] interaction`) } - destory(): void { + dispose(): void { this.exitInteraction() } } \ No newline at end of file diff --git a/src/core/manager/StateManager.ts b/src/core/manager/StateManager.ts index 8ec2864..aa7f08c 100644 --- a/src/core/manager/StateManager.ts +++ b/src/core/manager/StateManager.ts @@ -262,9 +262,14 @@ export default class StateManager { this.entityManager.endEntityUpdate() - // 从实体管理器中获取最新数据 - const updatedItems = this.entityManager.getAllEntities() - this.vdata.items = Array.from(updatedItems.values()) + // 获取被改过的数据, 覆盖之前的数据 + const writeBackMap = this.entityManager.cloneWriteBackEntities() + for (let i = 0; i < this.vdata.items.length; i++) { + const item = this.vdata.items[i] + if (writeBackMap.has(item.id)) { + this.vdata.items[i] = writeBackMap.get(item.id) + } + } } /** @@ -351,7 +356,7 @@ export default class StateManager { } await this.saveToLocalstore() - }, 5000) + }, 2500) } /** @@ -494,7 +499,7 @@ export default class StateManager { /** * 销毁资源 */ - destroy() { + dispose() { // 清理引用 delete this.vdata delete this.historySteps diff --git a/src/editor/Model2DEditor.vue b/src/editor/Model2DEditor.vue index 3d1b8ee..d2201fd 100644 --- a/src/editor/Model2DEditor.vue +++ b/src/editor/Model2DEditor.vue @@ -110,12 +110,12 @@ export default defineComponent({ }, destroyScene() { if (this.viewport) { - this.viewport.destroy() + this.viewport.dispose() this.viewport = null delete window['viewport'] } if (this.scene) { - this.scene.destory() + this.scene.dispose() this.scene = null delete window['scene'] } diff --git a/src/editor/propEditors/IMetaProp.ts b/src/editor/propEditors/IMetaProp.ts index 7d4fed2..1574505 100644 --- a/src/editor/propEditors/IMetaProp.ts +++ b/src/editor/propEditors/IMetaProp.ts @@ -1,16 +1,16 @@ import * as THREE from 'three' -import { type ItemTypeMetaItem } from '@/model/itemType/ItemTypeDefine' import { defineComponent, type PropType } from 'vue' import type Viewport from '@/core/engine/Viewport' import EventBus from '@/runtime/EventBus' +import type { MetaItem } from '@/core/base/IMeta.ts' export default defineComponent({ props: { - prop: Object as PropType, + prop: Object as PropType, viewport: Object as PropType }, mounted() { - EventBus.on('objectChanged', (data) => { + EventBus.on('selectedObjectChanged', (data) => { //@ts-ignore if (typeof this.refreshValue === 'function') { //@ts-ignore diff --git a/src/editor/widgets/property/PropertyView.vue b/src/editor/widgets/property/PropertyView.vue index 95aafd8..dd9ad6b 100644 --- a/src/editor/widgets/property/PropertyView.vue +++ b/src/editor/widgets/property/PropertyView.vue @@ -19,7 +19,7 @@ - - diff --git a/src/modules/measure/MeasureMeta.ts b/src/modules/measure/MeasureMeta.ts index b17d5bd..eb545cc 100644 --- a/src/modules/measure/MeasureMeta.ts +++ b/src/modules/measure/MeasureMeta.ts @@ -1,23 +1,15 @@ import type { IMeta } from '@/core/base/IMeta.ts' -const MeasureMeta: IMeta = { - // "点"属性面板 - point: { - // 基础面板 - basic: [ - { field: 'uuid', editor: 'UUID', label: 'uuid', readonly: true }, - { field: 'name', editor: 'TextInput', label: '名称' }, - { field: 'dt.label', editor: 'TextInput', label: '标签' }, - { editor: 'TransformEditor' }, - { field: 'dt.color', editor: 'Color', label: '颜色' }, - { editor: '-' }, - { field: 'tf', editor: 'InOutCenterEditor' }, - { field: 'dt.selectable', editor: 'Switch', label: '可选中' }, - { field: 'dt.protected', editor: 'Switch', label: '受保护' }, - { field: 'visible', editor: 'Switch', label: '可见' } - ] - }, - // "线"属性面板 - line: {} -} +const MeasureMeta: IMeta = [ + { field: 'uuid', editor: 'UUID', label: 'uuid', readonly: true, category: 'basic' }, + { field: 'name', editor: 'TextInput', label: '名称', category: 'basic' }, + { field: 'dt.label', editor: 'TextInput', label: '标签', category: 'basic' }, + { editor: 'TransformEditor', category: 'basic' }, + { field: 'dt.color', editor: 'Color', label: '颜色', category: 'basic' }, + { editor: '-', category: 'basic' }, + { field: 'tf', editor: 'InOutCenterEditor', category: 'basic' }, + { field: 'dt.selectable', editor: 'Switch', label: '可选中', category: 'basic' }, + { field: 'dt.protected', editor: 'Switch', label: '受保护', category: 'basic' }, + { field: 'visible', editor: 'Switch', label: '可见', category: 'basic' } +] export default MeasureMeta \ No newline at end of file diff --git a/src/modules/measure/MeasureRenderer.ts b/src/modules/measure/MeasureRenderer.ts index 61beff9..e9ee774 100644 --- a/src/modules/measure/MeasureRenderer.ts +++ b/src/modules/measure/MeasureRenderer.ts @@ -171,4 +171,16 @@ export default class MeasureRenderer extends BaseRenderer { getDefaultRotation(): THREE.Vector3 { return this.defaultRotation } + + dispose() { + super.dispose() + + if (this.group && this.group.parent) { + this.group.parent.remove(this.group) + } + this.group = undefined + + this.pointMaterial.dispose() + this.lineMaterial.dispose() + } } \ No newline at end of file diff --git a/src/runtime/EventBus.ts b/src/runtime/EventBus.ts index 51c822a..b64515c 100644 --- a/src/runtime/EventBus.ts +++ b/src/runtime/EventBus.ts @@ -2,7 +2,7 @@ import mitt from 'mitt' const instance = mitt() -export type DispatchNames = 'objectChanged' | 'catalogChanged' | 'dataLoadComplete' +export type DispatchNames = 'selectedObjectChanged' | 'catalogChanged' | 'dataLoadComplete' export default { dispatch(name: DispatchNames, data?: any) {