import {AbstractActionManager, AbstractMesh, ActionManager, Observable, Scene, WebXRDefaultExperience} from "@babylonjs/core"; import {DiagramEntity, DiagramEntityType, DiagramEvent, DiagramEventType} from "./types/diagramEntity"; import log from "loglevel"; import {AppConfig} from "../util/appConfig"; import {buildEntityActionManager} from "./functions/buildEntityActionManager"; import {DefaultScene} from "../defaultScene"; import {DiagramMenuManager} from "./diagramMenuManager"; import {DiagramEventObserverMask} from "./types/diagramEventObserverMask"; import {DiagramObject} from "./diagramObject"; import {getMe} from "../util/me"; import {UserModelType} from "../users/userTypes"; import {vectoxys} from "./functions/vectorConversion"; import {controllerObservable} from "../controllers/controllers"; import {ControllerEvent} from "../controllers/types/controllerEvent"; export class DiagramManager { private readonly _logger = log.getLogger('DiagramManager'); public readonly _config: AppConfig; private readonly _controllerObservable: Observable; private readonly _diagramEntityActionManager: ActionManager; public readonly onDiagramEventObservable: Observable = new Observable(); public readonly onUserEventObservable: Observable = new Observable(); private readonly _diagramMenuManager: DiagramMenuManager; private readonly _scene: Scene; private readonly _diagramObjects: Map = new Map(); private readonly _me: string; private _moving: number = 10; private _i: number = 0; public get diagramMenuManager(): DiagramMenuManager { return this._diagramMenuManager; } public setXR(xr: WebXRDefaultExperience): void { this._diagramMenuManager.setXR(xr); } constructor(readyObservable: Observable) { this._me = getMe(); this._scene = DefaultScene.Scene; this._config = new AppConfig(); this._diagramMenuManager = new DiagramMenuManager(this.onDiagramEventObservable, controllerObservable, readyObservable); this._diagramEntityActionManager = buildEntityActionManager(controllerObservable); this.onDiagramEventObservable.add(this.onDiagramEvent, DiagramEventObserverMask.FROM_DB, true, this); this.onUserEventObservable.add((user) => { if (user.id != this._me) { this._logger.debug('user event', user); } }); window.setInterval(() => { this._i++; const platform = this._scene.getMeshByName('platform'); if (!platform || !platform.physicsBody) { return; } if (platform.physicsBody) { if ((this._i % this._moving) == 0) { this.onUserEventObservable.notifyObservers( { id: this._me, name: 'me', type: 'user', base: { position: vectoxys(platform.absolutePosition), rotation: vectoxys(platform.absoluteRotationQuaternion.toEulerAngles()), velocity: vectoxys(platform.physicsBody.getLinearVelocity()) }, } ); } if (platform.physicsBody.getLinearVelocity().length() > 0.01) { this._moving = 1; } else { this._moving = 10; } } }, 100); document.addEventListener('uploadImage', (event: CustomEvent) => { const diagramEntity: DiagramEntity = { template: '#image-template', image: event.detail.data, text: event.detail.name, type: DiagramEntityType.ENTITY, position: {x: 0, y: 1.6, z: 0}, rotation: {x: 0, y: Math.PI, z: 0}, scale: {x: 1, y: 1, z: 1}, } const object = new DiagramObject(this._scene, this.onDiagramEventObservable, {diagramEntity: diagramEntity}); this._diagramObjects.set(diagramEntity.id, object); //const newMesh = buildMeshFromDiagramEntity(diagramEntity, this._scene); if (this.onDiagramEventObservable) { this.onDiagramEventObservable.notifyObservers({ type: DiagramEventType.ADD, entity: diagramEntity }, DiagramEventObserverMask.TO_DB); } }); this._logger.debug("DiagramManager constructed"); } public get actionManager(): AbstractActionManager { return this._diagramEntityActionManager; } public getDiagramObject(id: string) { return this._diagramObjects.get(id); } public isDiagramObject(mesh: AbstractMesh) { return this._diagramObjects.has(mesh?.id) } public createCopy(id: string): DiagramObject { const diagramObject = this._diagramObjects.get(id); if (!diagramObject) { this._logger.warn('createCopy called with invalid diagram object', id); return null; } const obj = diagramObject.clone(); return obj; } public addObject(diagramObject: DiagramObject) { this._diagramObjects.set(diagramObject.diagramEntity.id, diagramObject); } public get config(): AppConfig { return this._config; } private onDiagramEvent(event: DiagramEvent) { let diagramObject = this._diagramObjects.get(event?.entity?.id); switch (event.type) { case DiagramEventType.CLEAR: this._diagramObjects.forEach((value) => { value.dispose(); }); this._diagramObjects.clear(); break; case DiagramEventType.ADD: if (diagramObject) { diagramObject.fromDiagramEntity(event.entity); } else { diagramObject = DiagramObject.CreateObject(this._scene, this.onDiagramEventObservable, {diagramEntity: event.entity, actionManager: this._diagramEntityActionManager}); } if (diagramObject) { this._diagramObjects.set(event.entity.id, diagramObject); } else { this._logger.error('failed to create diagram object for ', event.entity); } break; case DiagramEventType.REMOVE: if (diagramObject) { diagramObject.dispose(); } this._diagramObjects.delete(event?.entity?.id); break; case DiagramEventType.MODIFY: this._logger.debug(event); //diagramObject = this._diagramObjects.get(event.entity.id); if (diagramObject && event.entity.text && event.entity.text != diagramObject.text) { diagramObject.text = event.entity.text; } else { this._logger.warn('Skipping text update for', event); } if (event.entity.position) { //diagramObject.position = event.entity.position; } break; } } }