|
|
|
@ -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<string, ItemJson>() |
|
|
|
private readonly ___entityMap = new Map<string, ItemJson>() |
|
|
|
|
|
|
|
// 关系索引
|
|
|
|
private readonly relationIndex = new Map<string, Relation>() |
|
|
|
@ -26,7 +27,9 @@ export default class EntityManager { |
|
|
|
private readonly objects = new Map<string, THREE.Object3D[]>() |
|
|
|
|
|
|
|
// 所有 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<string, THREE.Object3D[]>() |
|
|
|
@ -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<string, ItemJson> { |
|
|
|
const entities = new Map<string, ItemJson>() |
|
|
|
const result = new Map<string, ItemJson>() |
|
|
|
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[] { |
|
|
|
|