diff --git a/src/core/base/BaseRenderer.ts b/src/core/base/BaseRenderer.ts index 1455622..88056a1 100644 --- a/src/core/base/BaseRenderer.ts +++ b/src/core/base/BaseRenderer.ts @@ -88,6 +88,7 @@ export default abstract class BaseRenderer { createType: 'point', entityId: item.id, draggable: item.dt.protected !== true, + selectable: item.dt.selectable !== false, t: item.t } } @@ -103,6 +104,10 @@ export default abstract class BaseRenderer { ...object.userData, createType: 'line', entityId: getLineId(start.id, end.id, type), + startId: start.id, + endId: end.id, + draggable: false, + selectable: false, t: start.t } } diff --git a/src/core/controls/SelectInspect.ts b/src/core/controls/SelectInspect.ts index cd41f10..d25fb7e 100644 --- a/src/core/controls/SelectInspect.ts +++ b/src/core/controls/SelectInspect.ts @@ -312,11 +312,11 @@ export default class SelectInspect implements IControls { if (Date.now() - clickTime < 200) { // 如果是点击事件,触发选中逻辑 const objects: THREE.Object3D[] = this.viewport.entityManager.getObjectByCanvasMouse(event) - if (objects.length > 0 && objects[0]?.userData?.entityId) { + if (objects.length > 0 && objects[0]?.userData?.entityId && objects[0]?.userData?.createType !== 'line') { console.log('mouseClick', objects) const object = objects[0] const entityId = object.userData.entityId - const item = this.viewport.entityManager.findItemById(entityId) + let item = this.viewport.entityManager.findItemById(entityId) const itemTypeName = object.userData.t if (item.dt.protected !== true) { this.viewport.state.selectedObject = markRaw(object) diff --git a/src/core/manager/EntityManager.ts b/src/core/manager/EntityManager.ts index 2fa5744..f91df02 100644 --- a/src/core/manager/EntityManager.ts +++ b/src/core/manager/EntityManager.ts @@ -4,6 +4,7 @@ import type BaseRenderer from '@/core/base/BaseRenderer' import { getRenderer } from './ModuleManager' import { getClosestObject, getLineId, parseLineId } from '@/core/ModelUtils' import { Vector2 } from 'three' +import { getFreezeDeep } from '@/utils/webutils.ts' /** * 实体管理器 @@ -17,7 +18,7 @@ export default class EntityManager { viewport: Viewport // 所有数据点的实体 - private readonly entities = new Map() + private readonly ___entityMap = new Map() // 关系索引 private readonly relationIndex = new Map() @@ -26,7 +27,9 @@ export default class EntityManager { private readonly objects = new Map() // 所有 THREEJS "可选中"对象, 检索值是"点实体"的 id, 值是 THREE.Object3D 数组 - private readonly _selectableObjects: THREE.Object3D[] = [] + readonly _selectableObjects: THREE.Object3D[] = [] + + readonly _draggableObjects: THREE.Object3D[] = [] // 所有 THREEJS "线"对象, 检索值是"线实体"的 id, 取值方式是 {type}${startId}${endId}, 值是 THREE.Object3D 数组 private readonly lines = new Map() @@ -51,7 +54,7 @@ export default class EntityManager { this.diffRenderer.clear() // 清理所有实体和关系索引 - this.entities.clear() + this.___entityMap.clear() this.relationIndex.clear() this.objects.clear() this.lines.clear() @@ -62,14 +65,14 @@ export default class EntityManager { * 克隆需要回写的实体集合 */ cloneWriteBackEntities(): Map { - const entities = new Map() + const result = new Map() for (const id of this.writeBackEntities) { - const entity = this.entities.get(id) + const entity = this.___entityMap.get(id) if (!entity) continue - entities.set(id, _.cloneDeep(entity)) + result.set(id, _.cloneDeep(entity)) } - console.log('需要回写', entities.size, '行数据') - return entities + console.log('需要回写', result.size, '行数据') + return result } init(viewport: Viewport) { @@ -97,14 +100,14 @@ 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 originEntity = this.___entityMap.get(entity.id) // 找到这个数据的渲染器 const renderer = this.getDiffRenderer(entity.t) // 先判断坐标是否变化 const coordinateChanged = originEntity?.tf && entity?.tf && !_.isEqual(originEntity.tf[0], entity.tf[0]) - this.entities.set(entity.id, entity) + this.___entityMap.set(entity.id, entity) // 更新关系网 this.updateRelations(entity, originEntity) @@ -148,7 +151,7 @@ export default class EntityManager { * 删除实体, 与这个点有关的所有线都要删除, 与这个点有关系的点,都要对应的 center[] / in[] / out[] 都要断绝关系 */ deleteEntity(id: string, option: EntityCudOption = {}): void { - const entity = this.entities.get(id) + const entity = this.___entityMap.get(id) if (!entity) return option.originEntity = _.cloneDeep(entity) @@ -157,7 +160,7 @@ export default class EntityManager { // 先生成线差量,再清理关系 this.generateLineDiffsForDelete(id) this.removeRelations(id) // 清理关系 - this.entities.delete(id) // 删除实体 + this.___entityMap.delete(id) // 删除实体 this.getDiffRenderer(entity.t).deletePoint(id, option as RendererCudOption) } @@ -189,8 +192,8 @@ export default class EntityManager { for (const [itemTypeName, renderer] of this.diffRenderer.entries()) { // "线"创建 for (const [lineId, lineDiffItem] of this.lineDiffs.create.entries()) { - const start = this.entities.get(lineDiffItem.startId) - const end = this.entities.get(lineDiffItem.endId) + const start = this.___entityMap.get(lineDiffItem.startId) + const end = this.___entityMap.get(lineDiffItem.endId) // 添加存在性检查 if (!start || !end) { @@ -207,8 +210,8 @@ export default class EntityManager { // "线"更新 for (const [lineId, lineDiffItem] of this.lineDiffs.update.entries()) { - const start = this.entities.get(lineDiffItem.startId) - const end = this.entities.get(lineDiffItem.endId) + const start = this.___entityMap.get(lineDiffItem.startId) + const end = this.___entityMap.get(lineDiffItem.endId) // 添加存在性检查 if (!start || !end) { @@ -226,8 +229,8 @@ export default class EntityManager { // "线"删除 for (const [lineId, lineDiffItem] of this.lineDiffs.delete.entries()) { - const start = this.entities.get(lineDiffItem.startId) - const end = this.entities.get(lineDiffItem.endId) + const start = this.___entityMap.get(lineDiffItem.startId) + const end = this.___entityMap.get(lineDiffItem.endId) if (!start || !end) { // 即使实体不存在也要处理删除 @@ -265,7 +268,7 @@ export default class EntityManager { needUpdateIds.add(lineDiffItem.endId) } for (const id of needUpdateIds) { - const entity = this.entities.get(id) + const entity = this.___entityMap.get(id) if (entity) { entity.dt.center = Array.from(this.relationIndex.get(id)?.center || []) entity.dt.in = Array.from(this.relationIndex.get(id)?.input || []) @@ -407,115 +410,45 @@ export default class EntityManager { return renderer } - - // /** - // * 重命名一个点 - // * 注意, 不能在更新时刻改名. 所有的关系节点都应该改名 - // */ - // renamePoint(newId: string, originId: string) { - // if (this.isUpdating) { - // throw new Error('Cannot rename point during update') - // } - // const entity = this.entities.get(originId) - // if (!entity) { - // throw new Error(`Entity with id ${originId} does not exist`) - // } - // if (this.entities.has(newId)) { - // throw new Error(`Entity with id ${newId} already exists`) - // } - // entity.id = newId - // this.entities.set(newId, entity) - // this.entities.delete(originId) - // this.objects.set(newId, this.objects.get(originId) || []) - // this.objects.delete(originId) - // - // // 更新关系索引 - // const relations = this.relationIndex.get(originId) - // if (relations) { - // this.relationIndex.delete(originId) - // - // // 更新所有关系中的 id - // relations.center.forEach((relatedId) => { - // const rev = this.relationIndex.get(relatedId) - // if (rev && rev.delete('center', originId)) { - // rev.add('center', newId) - // } - // }) - // relations.input.forEach((relatedId) => { - // const rev = this.relationIndex.get(relatedId) - // if (rev && rev.delete('out', originId)) { - // rev.add('out', newId) - // } - // }) - // relations.output.forEach((relatedId) => { - // const rev = this.relationIndex.get(relatedId) - // if (rev && rev.delete('in', originId)) { - // rev.add('in', newId) - // } - // }) - // - // this.relationIndex.set(newId, relations) - // } - // - // // 更新所有线段数据 - // for (const [lineId, lineObjects] of this.lines.entries()) { - // const [type, startId, endId] = parseLineId(lineId) - // if (startId === originId) { - // const newLineId = getLineId(newId, endId, type) - // this.lines.set(newLineId, lineObjects) - // this.lines.delete(lineId) - // - // } else if (endId === originId) { - // const newLineId = getLineId(startId, newId, type) - // this.lines.set(newLineId, lineObjects) - // this.lines.delete(lineId) - // } - // } - // } - deleteEntityOnly(id: string) { - return this.entities.delete(id) + return this.___entityMap.delete(id) } findObjectsById(id: string) { return this.objects.get(id) || [] } - deleteObjectsOnly(id: string) { - // 删除对象时,也需要从 _selectableObjects 中移除 - const rel = this.objects.get(id) - if (rel) { - _.remove(this._selectableObjects, obj => !rel.includes(obj)) - } - return this.objects.delete(id) - } - appendObject(id: string, points: THREE.Object3D[]) { this.objects.set(id, points) // 如果是可选中对象,添加到 _selectableObjects 中 - if (points.some(obj => obj.userData.selectable !== false)) { - this._selectableObjects.push(...points) + for (const point of points) { + if (point.userData.selectable !== false) { + this._selectableObjects.push(point) + } + if (point.userData.draggable) { + this._draggableObjects.push(point) + } } } appendLineObject(id: string, lines: THREE.Object3D[]) { this.lines.set(id, lines) - // 如果是可选中对象,添加到 _selectableObjects 中 - if (lines.some(obj => obj.userData.selectable !== false)) { - this._selectableObjects.push(...lines) - } } findLineObjectsById(lineId: string): THREE.Object3D[] { return this.lines.get(lineId) || [] } + deleteObjectsOnly(id: string) { + _.remove(this._selectableObjects, obj => obj.userData?.entityId === id) + _.remove(this._draggableObjects, obj => obj.userData?.entityId === id) + return this.objects.delete(id) + } + deleteLineObjectOnly(id: string) { // 删除线对象时,也需要从 _selectableObjects 中移除 - const rel = this.lines.get(id) - if (rel) { - _.remove(this._selectableObjects, obj => !rel.includes(obj)) - } + _.remove(this._selectableObjects, obj => obj.userData?.entityId === id) + _.remove(this._draggableObjects, obj => obj.userData?.entityId === id) return this.lines.delete(id) } @@ -526,7 +459,7 @@ export default class EntityManager { if (!linkStartPointId) { return } - return this.entities.get(linkStartPointId) + return getFreezeDeep(this.___entityMap.get(linkStartPointId)) } getObjectByCanvasMouse(event: MouseEvent): THREE.Object3D[] { diff --git a/src/editor/widgets/property/PropertyView.vue b/src/editor/widgets/property/PropertyView.vue index d743f1f..447c0da 100644 --- a/src/editor/widgets/property/PropertyView.vue +++ b/src/editor/widgets/property/PropertyView.vue @@ -1,7 +1,8 @@