170 lines
5.9 KiB
TypeScript
170 lines
5.9 KiB
TypeScript
import {
|
|
AbstractMesh,
|
|
Angle,
|
|
Color3,
|
|
Mesh,
|
|
MeshBuilder,
|
|
Observable, Scene,
|
|
StandardMaterial,
|
|
Vector3, WebXRExperienceHelper
|
|
} from "@babylonjs/core";
|
|
import {v4 as uuidv4} from 'uuid';
|
|
import {DiagramEntity, DiagramEvent, DiagramEventType} from "./diagramEntity";
|
|
import {PersistenceManager} from "./persistenceManager";
|
|
|
|
export class DiagramManager {
|
|
private persistenceManager: PersistenceManager = new PersistenceManager();
|
|
static onDiagramEventObservable = new Observable();
|
|
private scene: Scene;
|
|
private xr: WebXRExperienceHelper;
|
|
static currentMesh: AbstractMesh;
|
|
|
|
constructor(scene: Scene, xr: WebXRExperienceHelper) {
|
|
this.scene = scene;
|
|
this.xr = xr;
|
|
this.persistenceManager.updateObserver.add(this.#onRemoteEvent, -1, true, this);
|
|
this.persistenceManager.initialize();
|
|
if (!DiagramManager.onDiagramEventObservable) {
|
|
DiagramManager.onDiagramEventObservable = new Observable();
|
|
}
|
|
if (DiagramManager.onDiagramEventObservable.hasObservers()) {
|
|
|
|
} else {
|
|
DiagramManager.onDiagramEventObservable.add(this.#onDiagramEvent, -1, true, this);
|
|
}
|
|
}
|
|
#onRemoteEvent(event: DiagramEntity) {
|
|
const mesh = this.#createMesh(event);
|
|
const material = new StandardMaterial("material-" + event.id, this.scene);
|
|
material.diffuseColor = Color3.FromHexString(event.color);
|
|
mesh.material = material;
|
|
}
|
|
|
|
#onDiagramEvent(event: DiagramEvent) {
|
|
const entity = event.entity;
|
|
let mesh;
|
|
let material
|
|
if (entity) {
|
|
mesh = this.scene.getMeshByName(entity.id);
|
|
if (mesh) {
|
|
material = mesh.material;
|
|
}
|
|
}
|
|
|
|
switch (event.type) {
|
|
case DiagramEventType.CLEAR:
|
|
DiagramManager.currentMesh.dispose();
|
|
DiagramManager.currentMesh = null;
|
|
break;
|
|
case DiagramEventType.DROPPED:
|
|
break;
|
|
case DiagramEventType.DROP:
|
|
if (DiagramManager.currentMesh) {
|
|
this.persistenceManager.add(DiagramManager.currentMesh);
|
|
const newName = uuidv4();
|
|
const newMesh = DiagramManager.currentMesh.clone("id"+newName, DiagramManager.currentMesh.parent);
|
|
const newMaterial = DiagramManager.currentMesh.material.clone("material"+newName);
|
|
newMesh.material=newMaterial;
|
|
DiagramManager.currentMesh.setParent(null);
|
|
DiagramManager.currentMesh = newMesh;
|
|
DiagramManager.onDiagramEventObservable.notifyObservers({
|
|
type: DiagramEventType.DROPPED,
|
|
entity: entity
|
|
});
|
|
}
|
|
break;
|
|
case DiagramEventType.ADD:
|
|
if (DiagramManager.currentMesh) {
|
|
DiagramManager.currentMesh.dispose();
|
|
}
|
|
if (mesh) {
|
|
return;
|
|
} else {
|
|
mesh = this.#createMesh(entity);
|
|
if (!material) {
|
|
material = new StandardMaterial("material-" + event.entity.id, this.scene);
|
|
material.diffuseColor = Color3.FromHexString(event.entity.color);
|
|
mesh.material = material;
|
|
|
|
}
|
|
if (!mesh) {
|
|
return;
|
|
}
|
|
}
|
|
DiagramManager.currentMesh = mesh;
|
|
break;
|
|
case DiagramEventType.MODIFY:
|
|
if (!mesh) {
|
|
|
|
} else {
|
|
if (!material) {
|
|
material = new StandardMaterial("material-" + event.entity.id, this.scene);
|
|
material.diffuseColor = Color3.FromHexString(event.entity.color);
|
|
if (mesh) {
|
|
mesh.material = material;
|
|
}
|
|
|
|
}
|
|
mesh.material = material;
|
|
mesh.position = entity.position;
|
|
mesh.rotation = entity.rotation;
|
|
if (entity.parent) {
|
|
mesh.parent = this.scene.getMeshByName(entity.parent);
|
|
} else {
|
|
|
|
}
|
|
}
|
|
DiagramManager.currentMesh = mesh;
|
|
break;
|
|
case DiagramEventType.REMOVE:
|
|
break;
|
|
}
|
|
}
|
|
|
|
#createMesh(entity: DiagramEntity) {
|
|
if (!entity.id) {
|
|
entity.id = "id" + uuidv4();
|
|
}
|
|
let mesh: Mesh;
|
|
switch (entity.template) {
|
|
case "#box-template":
|
|
mesh = MeshBuilder.CreateBox(entity.id,
|
|
{
|
|
width: 1,
|
|
height: 1,
|
|
depth: 1
|
|
}, this.scene);
|
|
|
|
break;
|
|
case "#sphere-template":
|
|
mesh = MeshBuilder.CreateSphere(entity.id, {diameter: 1}, this.scene);
|
|
break
|
|
case "#cylinder-template":
|
|
mesh = MeshBuilder.CreateCylinder(entity.id, {
|
|
diameter: 1,
|
|
height: 1
|
|
}, this.scene);
|
|
break;
|
|
default:
|
|
mesh = null;
|
|
}
|
|
if (mesh) {
|
|
mesh.metadata = {template: entity.template};
|
|
|
|
if (entity.position) {
|
|
mesh.position = entity.position;
|
|
}
|
|
if (entity.rotation) {
|
|
mesh.rotation = entity.rotation;
|
|
}
|
|
if (entity.parent) {
|
|
mesh.parent = this.scene.getMeshByName(entity.parent);
|
|
}
|
|
if (entity.scale) {
|
|
mesh.scaling = entity.scale;
|
|
}
|
|
}
|
|
|
|
return mesh;
|
|
}
|
|
} |