|
|
@ -4,6 +4,34 @@ import type BaseRenderer from '@/core/base/BaseRenderer' |
|
|
import { getRenderer } from './ModuleManager' |
|
|
import { getRenderer } from './ModuleManager' |
|
|
import { getLineId, parseLineId } from '@/core/ModelUtils' |
|
|
import { getLineId, parseLineId } from '@/core/ModelUtils' |
|
|
|
|
|
|
|
|
|
|
|
export class Relation { |
|
|
|
|
|
center = new Set<string>() |
|
|
|
|
|
input = new Set<string>() |
|
|
|
|
|
output = new Set<string>() |
|
|
|
|
|
|
|
|
|
|
|
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}`) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 实体管理器 |
|
|
* 实体管理器 |
|
|
* 缓存所有 数据(ItemJson)和他们的关系, 以及渲染对象 THREE.Object3D |
|
|
* 缓存所有 数据(ItemJson)和他们的关系, 以及渲染对象 THREE.Object3D |
|
|
@ -112,11 +140,28 @@ export default class EntityManager { |
|
|
|
|
|
|
|
|
option.originEntity = _.cloneDeep(entity) |
|
|
option.originEntity = _.cloneDeep(entity) |
|
|
|
|
|
|
|
|
this.entities.delete(id) |
|
|
// 先生成线差量,再清理关系
|
|
|
this.removeRelations(id) |
|
|
this.generateLineDiffsForDelete(id) |
|
|
|
|
|
this.removeRelations(id) // 清理关系
|
|
|
|
|
|
this.entities.delete(id) // 删除实体
|
|
|
|
|
|
|
|
|
this.getDiffRenderer(entity.t).deletePoint(id, option) |
|
|
this.getDiffRenderer(entity.t).deletePoint(id, option) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
generateLineDiffsForDelete(id: string): void { |
|
|
|
|
|
const relations = this.relationIndex.get(id) |
|
|
|
|
|
if (!relations) return |
|
|
|
|
|
|
|
|
|
|
|
const removeLine = (relatedId: string, type: LinkType) => { |
|
|
|
|
|
const lineId = getLineId(id, relatedId, type) |
|
|
|
|
|
this.lineDiffs.delete.set(lineId, { startId: id, endId: relatedId, type }) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
relations.center.forEach(relatedId => removeLine(relatedId, 'center')) |
|
|
|
|
|
relations.input.forEach(relatedId => removeLine(relatedId, 'in')) |
|
|
|
|
|
relations.output.forEach(relatedId => removeLine(relatedId, 'out')) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 批量更新结束, 结束后会触发视窗的渲染 |
|
|
* 批量更新结束, 结束后会触发视窗的渲染 |
|
|
* 这个方法最重要的是进行连线逻辑的处理 |
|
|
* 这个方法最重要的是进行连线逻辑的处理 |
|
|
@ -127,9 +172,17 @@ export default class EntityManager { |
|
|
*/ |
|
|
*/ |
|
|
endEntityUpdate(): void { |
|
|
endEntityUpdate(): void { |
|
|
for (const [itemTypeName, renderer] of this.diffRenderer.entries()) { |
|
|
for (const [itemTypeName, renderer] of this.diffRenderer.entries()) { |
|
|
|
|
|
// "线"创建
|
|
|
for (const [lineId, lineDiffItem] of this.lineDiffs.create.entries()) { |
|
|
for (const [lineId, lineDiffItem] of this.lineDiffs.create.entries()) { |
|
|
const start = this.entities.get(lineDiffItem.startId) |
|
|
const start = this.entities.get(lineDiffItem.startId) |
|
|
const end = this.entities.get(lineDiffItem.endId) |
|
|
const end = this.entities.get(lineDiffItem.endId) |
|
|
|
|
|
|
|
|
|
|
|
// 添加存在性检查
|
|
|
|
|
|
if (!start || !end) { |
|
|
|
|
|
console.warn(`无法创建线 ${lineId}, 起点或终点不存在`) |
|
|
|
|
|
continue |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (start.t !== itemTypeName) { |
|
|
if (start.t !== itemTypeName) { |
|
|
// 只通知起点对应的渲染器
|
|
|
// 只通知起点对应的渲染器
|
|
|
continue |
|
|
continue |
|
|
@ -137,9 +190,17 @@ export default class EntityManager { |
|
|
renderer.createLine(start, end, lineDiffItem.type) |
|
|
renderer.createLine(start, end, lineDiffItem.type) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// "线"更新
|
|
|
for (const [lineId, lineDiffItem] of this.lineDiffs.update.entries()) { |
|
|
for (const [lineId, lineDiffItem] of this.lineDiffs.update.entries()) { |
|
|
const start = this.entities.get(lineDiffItem.startId) |
|
|
const start = this.entities.get(lineDiffItem.startId) |
|
|
const end = this.entities.get(lineDiffItem.endId) |
|
|
const end = this.entities.get(lineDiffItem.endId) |
|
|
|
|
|
|
|
|
|
|
|
// 添加存在性检查
|
|
|
|
|
|
if (!start || !end) { |
|
|
|
|
|
console.warn(`无法更新线 ${lineId}, 起点或终点不存在`) |
|
|
|
|
|
continue |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (start.t !== itemTypeName) { |
|
|
if (start.t !== itemTypeName) { |
|
|
// 只通知起点对应的渲染器
|
|
|
// 只通知起点对应的渲染器
|
|
|
continue |
|
|
continue |
|
|
@ -147,13 +208,26 @@ export default class EntityManager { |
|
|
renderer.updateLine(start, end, lineDiffItem.type) |
|
|
renderer.updateLine(start, end, lineDiffItem.type) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// "线"删除
|
|
|
for (const [lineId, lineDiffItem] of this.lineDiffs.delete.entries()) { |
|
|
for (const [lineId, lineDiffItem] of this.lineDiffs.delete.entries()) { |
|
|
const start = this.entities.get(lineDiffItem.startId) |
|
|
const start = this.entities.get(lineDiffItem.startId) |
|
|
const end = this.entities.get(lineDiffItem.endId) |
|
|
const end = this.entities.get(lineDiffItem.endId) |
|
|
|
|
|
|
|
|
|
|
|
if (!start || !end) { |
|
|
|
|
|
// 即使实体不存在也要处理删除
|
|
|
|
|
|
renderer.deleteLine( |
|
|
|
|
|
start || { id: lineDiffItem.startId, t: 'unknown' } as ItemJson, |
|
|
|
|
|
end || { id: lineDiffItem.endId, t: 'unknown' } as ItemJson, |
|
|
|
|
|
lineDiffItem.type) |
|
|
|
|
|
continue |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (start.t !== itemTypeName) { |
|
|
if (start.t !== itemTypeName) { |
|
|
// 只通知起点对应的渲染器
|
|
|
// 只通知起点对应的渲染器
|
|
|
continue |
|
|
continue |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 使用安全删除方法, 即使实体不存在也要处理删除
|
|
|
renderer.deleteLine(start, end, lineDiffItem.type) |
|
|
renderer.deleteLine(start, end, lineDiffItem.type) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -197,6 +271,11 @@ export default class EntityManager { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private updateReverseRelations(id: string, oldIds: Set<string>, newIds: Set<string>, relationType: LinkType) { |
|
|
private updateReverseRelations(id: string, oldIds: Set<string>, newIds: Set<string>, relationType: LinkType) { |
|
|
|
|
|
// 确保关系索引存在
|
|
|
|
|
|
if (!this.relationIndex.has(id)) { |
|
|
|
|
|
this.relationIndex.set(id, new Relation()) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 移除旧关系
|
|
|
// 移除旧关系
|
|
|
for (const relatedId of oldIds) { |
|
|
for (const relatedId of oldIds) { |
|
|
if (!newIds.has(relatedId)) { |
|
|
if (!newIds.has(relatedId)) { |
|
|
@ -219,6 +298,9 @@ export default class EntityManager { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private calculateLineDiffs(id: string, oldIds: Set<string>, newIds: Set<string>, lineType: LinkType) { |
|
|
private calculateLineDiffs(id: string, oldIds: Set<string>, newIds: Set<string>, lineType: LinkType) { |
|
|
|
|
|
// 确保关系索引存在
|
|
|
|
|
|
if (!this.relationIndex.has(id)) return |
|
|
|
|
|
|
|
|
// 删除被移除的线
|
|
|
// 删除被移除的线
|
|
|
for (const relatedId of oldIds) { |
|
|
for (const relatedId of oldIds) { |
|
|
if (!newIds.has(relatedId)) { |
|
|
if (!newIds.has(relatedId)) { |
|
|
@ -236,6 +318,43 @@ export default class EntityManager { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 删除关系关系网, 计算出差值, 可以临时放在 diffRenderer 中, 等待 commitUpdate 时统一处理 |
|
|
|
|
|
*/ |
|
|
|
|
|
private removeRelations(id: string): void { |
|
|
|
|
|
const relations = this.relationIndex.get(id) |
|
|
|
|
|
if (!relations) return |
|
|
|
|
|
|
|
|
|
|
|
relations.center.forEach(relatedId => { |
|
|
|
|
|
const rev = this.relationIndex.get(relatedId) |
|
|
|
|
|
if (rev) rev.center.delete(id) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
relations.input.forEach(relatedId => { |
|
|
|
|
|
const rev = this.relationIndex.get(relatedId) |
|
|
|
|
|
if (rev) rev.output.delete(id) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
relations.output.forEach(relatedId => { |
|
|
|
|
|
const rev = this.relationIndex.get(relatedId) |
|
|
|
|
|
if (rev) rev.input.delete(id) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
this.relationIndex.delete(id) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private getDiffRenderer(type: string) { |
|
|
|
|
|
let renderer = this.diffRenderer.get(type) |
|
|
|
|
|
if (typeof renderer === 'undefined') { |
|
|
|
|
|
renderer = getRenderer(type) |
|
|
|
|
|
renderer.beginRendererUpdate(this.viewport) |
|
|
|
|
|
this.diffRenderer.set(type, renderer) |
|
|
|
|
|
} |
|
|
|
|
|
return renderer |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* 重命名一个点 |
|
|
* 重命名一个点 |
|
|
* 注意, 不能在更新时刻改名. 所有的关系节点都应该改名 |
|
|
* 注意, 不能在更新时刻改名. 所有的关系节点都应该改名 |
|
|
@ -301,46 +420,6 @@ export default class EntityManager { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* 删除关系关系网, 计算出差值, 可以临时放在 diffRenderer 中, 等待 commitUpdate 时统一处理 |
|
|
|
|
|
*/ |
|
|
|
|
|
private removeRelations(id: string): void { |
|
|
|
|
|
const relations = this.relationIndex.get(id) |
|
|
|
|
|
if (!relations) return |
|
|
|
|
|
|
|
|
|
|
|
const removeLine = (relatedId: string, type: LinkType) => { |
|
|
|
|
|
const lineId = getLineId(id, relatedId, type) |
|
|
|
|
|
this.lineDiffs.delete.set(lineId, { startId: id, endId: relatedId, type }) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
relations.center.forEach((relatedId) => { |
|
|
|
|
|
this.relationIndex.get(relatedId)?.center.delete(id) |
|
|
|
|
|
removeLine(relatedId, 'center') |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
relations.input.forEach((relatedId) => { |
|
|
|
|
|
this.relationIndex.get(relatedId)?.output.delete(id) |
|
|
|
|
|
removeLine(relatedId, 'in') |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
relations.output.forEach((relatedId) => { |
|
|
|
|
|
this.relationIndex.get(relatedId)?.input.delete(id) |
|
|
|
|
|
removeLine(relatedId, 'out') |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
this.relationIndex.delete(id) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private getDiffRenderer(type: string) { |
|
|
|
|
|
let renderer = this.diffRenderer.get(type) |
|
|
|
|
|
if (typeof renderer === 'undefined') { |
|
|
|
|
|
renderer = getRenderer(type) |
|
|
|
|
|
renderer.beginRendererUpdate(this.viewport) |
|
|
|
|
|
this.diffRenderer.set(type, renderer) |
|
|
|
|
|
} |
|
|
|
|
|
return renderer |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
deleteEntityOnly(id: string) { |
|
|
deleteEntityOnly(id: string) { |
|
|
return this.entities.delete(id) |
|
|
return this.entities.delete(id) |
|
|
} |
|
|
} |
|
|
@ -376,30 +455,3 @@ interface LineDiffItem { |
|
|
type: LinkType |
|
|
type: LinkType |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
export class Relation { |
|
|
|
|
|
center = new Set<string>() |
|
|
|
|
|
input = new Set<string>() |
|
|
|
|
|
output = new Set<string>() |
|
|
|
|
|
|
|
|
|
|
|
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}`) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|