immersive2/src/diagram/diagramManager.ts

108 lines
4.6 KiB
TypeScript

import {AbstractMesh, ActionManager, Color3, InstancedMesh, Mesh, Observable, Scene} from "@babylonjs/core";
import {DiagramEvent, DiagramEventType} from "./types/diagramEntity";
import log from "loglevel";
import {Controllers} from "../controllers/controllers";
import {DiaSounds} from "../util/diaSounds";
import {AppConfig} from "../util/appConfig";
import {Toolbox} from "../toolbox/toolbox";
import {PresentationManager} from "./presentationManager";
import {diagramEventHandler} from "./functions/diagramEventHandler";
import {deepCopy} from "../util/functions/deepCopy";
import {applyPhysics} from "./functions/diagramShapePhysics";
import {applyScaling} from "./functions/applyScaling";
import {toDiagramEntity} from "./functions/toDiagramEntity";
import {v4 as uuidv4} from 'uuid';
import {buildEntityActionManager} from "./functions/buildEntityActionManager";
import {isDiagramEntity} from "./functions/isDiagramEntity";
export class DiagramManager {
public readonly _config: AppConfig;
private readonly _controllers: Controllers;
private readonly diagramEntityActionManager: ActionManager;
private presentationManager: PresentationManager;
public readonly onDiagramEventObservable: Observable<DiagramEvent> = new Observable();
private readonly logger = log.getLogger('DiagramManager');
private readonly toolbox: Toolbox;
private readonly scene: Scene;
private readonly sounds: DiaSounds;
constructor(scene: Scene) {
this._config = new AppConfig();
this._controllers = new Controllers();
this.sounds = new DiaSounds(scene);
this.scene = scene;
this.toolbox = new Toolbox(scene);
this.presentationManager = new PresentationManager(this.scene);
this.diagramEntityActionManager = buildEntityActionManager(this.scene, this.sounds, this._controllers);
if (this.onDiagramEventObservable.hasObservers()) {
this.logger.warn("onDiagramEventObservable already has Observers, you should be careful");
}
this.toolbox.colorChangeObservable.add((evt) => {
this.logger.debug(evt);
this.onDiagramEventObservable.notifyObservers({
type: DiagramEventType.CHANGECOLOR,
oldColor: Color3.FromHexString(evt.oldColor), newColor: Color3.FromHexString(evt.newColor)
}, 2);
}, -1, true, this, false);
this.onDiagramEventObservable.add(this.onDiagramEvent, 1, true, this);
this.logger.debug("DiagramManager constructed");
scene.onMeshRemovedObservable.add((mesh) => {
if (isDiagramEntity(mesh)) {
if (mesh.metadata.template != '#connection-template') {
scene.meshes.forEach((m) => {
if (m?.metadata?.to == mesh.id || m?.metadata?.from == mesh.id) {
this.logger.debug("removing connection", m.id);
this.onDiagramEventObservable.notifyObservers({
type: DiagramEventType.REMOVE,
entity: toDiagramEntity(m)
}, -1);
}
});
}
}
});
}
public get controllers(): Controllers {
return this._controllers;
}
public get config(): AppConfig {
return this._config;
}
public createCopy(mesh: AbstractMesh, copy: boolean = false): AbstractMesh {
let newMesh;
if (!mesh.isAnInstance) {
newMesh = new InstancedMesh('id' + uuidv4(), (mesh as Mesh));
} else {
newMesh = new InstancedMesh('id' + uuidv4(), (mesh as InstancedMesh).sourceMesh);
}
newMesh.id = 'id' + uuidv4();
newMesh.actionManager = this.diagramEntityActionManager;
newMesh.position = mesh.absolutePosition.clone();
if (mesh.absoluteRotationQuaternion) {
newMesh.rotation = mesh.absoluteRotationQuaternion.toEulerAngles().clone();
} else {
this.logger.error("no rotation quaternion");
}
applyScaling(mesh, newMesh, copy, this._config.current?.createSnap);
newMesh.material = mesh.material;
newMesh.metadata = deepCopy(mesh.metadata);
if (this._config.current?.physicsEnabled) {
applyPhysics(this.sounds, newMesh, this.scene);
}
return newMesh;
}
private onDiagramEvent(event: DiagramEvent) {
diagramEventHandler(
event, this.scene, this.toolbox, this._config.current.physicsEnabled,
this.diagramEntityActionManager, this.sounds);
}
}