diff --git a/src/controllers/base.ts b/src/controllers/base.ts index 09f9f30..02dd93e 100644 --- a/src/controllers/base.ts +++ b/src/controllers/base.ts @@ -19,6 +19,7 @@ import {reparent} from "./functions/reparent"; import {snapGridVal} from "../util/functions/snapGridVal"; import {snapRotateVal} from "../util/functions/snapRotateVal"; import {grabAndClone} from "./functions/grab"; +import {isDiagramEntity} from "../diagram/functions/isDiagramEntity"; export class Base { static stickVector = Vector3.Zero(); @@ -113,8 +114,8 @@ export class Base { return; } let player = false; - const template = mesh?.metadata?.template; - if (!template) { + + if (!isDiagramEntity(mesh)) { if (mesh?.metadata?.handle == true) { mesh && mesh.setParent(this.controller.motionController.rootMesh); this.grabbedMesh = mesh; @@ -131,7 +132,8 @@ export class Base { } } else { - if (template == '#connection-template') { + + if (mesh?.metadata?.template == '#connection-template') { return; } } @@ -165,7 +167,7 @@ export class Base { } private toolboxHandleWasGrabbed(mesh: AbstractMesh): boolean { - if (!mesh?.metadata?.template + if (isDiagramEntity(mesh) && mesh?.metadata?.handle == true) { this.grabbedMesh = null; this.previousParentId = null; @@ -196,7 +198,7 @@ export class Base { this.previousRotation = null; this.previousPosition = null; this.grabbedMesh = null; - if (mesh?.metadata?.template && (mesh?.metadata?.template.indexOf('#') == -1)) { + if (isDiagramEntity(mesh) && (mesh?.metadata?.template.indexOf('#') == -1)) { return; } const entity = toDiagramEntity(mesh); diff --git a/src/controllers/functions/buildRig.ts b/src/controllers/functions/buildRig.ts index eb8d57a..ce2ba16 100644 --- a/src/controllers/functions/buildRig.ts +++ b/src/controllers/functions/buildRig.ts @@ -1,16 +1,15 @@ import { - Color3, Mesh, MeshBuilder, PhysicsAggregate, PhysicsMotionType, PhysicsShapeType, Scene, - StandardMaterial, TransformNode, Vector3 } from "@babylonjs/core"; import {AppConfig} from "../../util/appConfig"; +import {buildStandardMaterial} from "../../materials/functions/buildStandardMaterial"; export function buildRig(scene: Scene, appConfig: AppConfig): Mesh { const rigMesh = MeshBuilder.CreateCylinder("platform", {diameter: .5, height: 1.6}, scene); @@ -24,10 +23,7 @@ export function buildRig(scene: Scene, appConfig: AppConfig): Mesh { scene.onActiveCameraChanged.add((s) => { s.activeCamera.parent = cameratransform; }); - - const rigMaterial = new StandardMaterial("rigMaterial", scene); - rigMaterial.diffuseColor = Color3.Blue(); - rigMesh.material = rigMaterial; + rigMesh.material = buildStandardMaterial("rigMaterial", scene, "#2222ff"); rigMesh.setAbsolutePosition(new Vector3(0, .01, -3)); rigMesh.visibility = 0; const rigAggregate = diff --git a/src/controllers/right.ts b/src/controllers/right.ts index bc946b5..fd8e508 100644 --- a/src/controllers/right.ts +++ b/src/controllers/right.ts @@ -42,7 +42,7 @@ export class Right extends Base { controllers: Controllers, ) { super(controller, scene, xr, controllers, diagramManager); - this.listingMenu = new DiagramListingMenu(this.scene, xr, this.controllers); + this.listingMenu = new DiagramListingMenu(this.scene, xr, this.controllers, diagramManager); this.controller.onMotionControllerInitObservable.add((init) => { this.initTrigger(init.components['xr-standard-trigger']); if (init.components['a-button']) { diff --git a/src/controllers/rigplatform.ts b/src/controllers/rigplatform.ts index 3e36739..8c95181 100644 --- a/src/controllers/rigplatform.ts +++ b/src/controllers/rigplatform.ts @@ -30,7 +30,10 @@ export class Rigplatform { private readonly controllers: Controllers; private registered = false; - constructor(scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager, controllers: Controllers) { + constructor(scene: Scene, xr: WebXRDefaultExperience, + diagramManager: DiagramManager, + controllers: Controllers, + ) { this.scene = scene; this.diagramManager = diagramManager; this.controllers = controllers; diff --git a/src/controllers/webController.ts b/src/controllers/webController.ts index 796aaca..54a88ed 100644 --- a/src/controllers/webController.ts +++ b/src/controllers/webController.ts @@ -5,9 +5,12 @@ import {DiagramManager} from "../diagram/diagramManager"; import {GridMaterial} from "@babylonjs/materials"; import {setMenuPosition} from "../util/functions/setMenuPosition"; import {wheelHandler} from "./functions/wheelHandler"; +import log, {Logger} from "loglevel"; +import {isDiagramEntity} from "../diagram/functions/isDiagramEntity"; export class WebController { private readonly scene: Scene; + private readonly logger: Logger = log.getLogger('WebController'); private speed: number = 1; private readonly referencePlane: AbstractMesh; private pickedMesh: AbstractMesh; @@ -35,7 +38,7 @@ export class WebController { this.scene.onKeyboardObservable.add((kbInfo) => { - console.log(kbInfo); + this.logger.debug(kbInfo); if (kbInfo.type == 1) { switch (kbInfo.event.key) { case "ArrowUp": @@ -66,7 +69,7 @@ export class WebController { } break; default: - console.log(kbInfo.event); + this.logger.debug(kbInfo.event); } } else { @@ -138,7 +141,7 @@ export class WebController { this.rig.turn(evt.movementX); } const meshPickInfo = scene.pick(this.scene.pointerX, this.scene.pointerY, (mesh) => { - return mesh.metadata?.template != undefined; + return isDiagramEntity(mesh); }); const planePickInfo = scene.pick(this.scene.pointerX, this.scene.pointerY, (mesh) => { return mesh.id == this.referencePlane.id; @@ -178,9 +181,4 @@ export class WebController { } this._mesh = mesh; } - - private handlePointer(info, state) { - console.log(info); - console.log(state); - } } \ No newline at end of file diff --git a/src/diagram/diagramConnection.ts b/src/diagram/diagramConnection.ts index 09a0218..770a05b 100644 --- a/src/diagram/diagramConnection.ts +++ b/src/diagram/diagramConnection.ts @@ -1,15 +1,7 @@ -import { - AbstractMesh, - Color3, - MeshBuilder, - PointerInfo, - Scene, - StandardMaterial, - TransformNode, - Vector3 -} from "@babylonjs/core"; +import {AbstractMesh, MeshBuilder, PointerInfo, Scene, TransformNode, Vector3} from "@babylonjs/core"; import {v4 as uuidv4} from 'uuid'; import log, {Logger} from "loglevel"; +import {buildStandardMaterial} from "../materials/functions/buildStandardMaterial"; export class DiagramConnection { @@ -112,10 +104,8 @@ export class DiagramConnection { private buildConnection() { this.logger.debug(`buildConnection from ${this._from} to ${this._to}`); - this._mesh = MeshBuilder.CreateCylinder(this.id + "_cylinder", {diameter: .02, height: 1}, this.scene); - const material = new StandardMaterial(this.id + "_material", this.scene); - material.diffuseColor = new Color3(0, 0, 0); - this._mesh.material = material; + this._mesh = MeshBuilder.CreateCylinder(this.id + "_connection", {diameter: .02, height: 1}, this.scene); + this._mesh.material = buildStandardMaterial(this.id + "_material", this.scene, "#000000"); this.transformNode = new TransformNode(this.id + "_transform", this.scene); this._mesh.setParent(this.transformNode); this.recalculate(); diff --git a/src/diagram/diagramManager.ts b/src/diagram/diagramManager.ts index a8c5b5d..1151e81 100644 --- a/src/diagram/diagramManager.ts +++ b/src/diagram/diagramManager.ts @@ -13,10 +13,13 @@ 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"; +import {DiagramListingEvent} from "./types/diagramListing"; export class DiagramManager { public readonly onDiagramEventObservable: Observable = new Observable(); + public readonly onDiagramEventListingObservable: Observable = new Observable(); private readonly logger = log.getLogger('DiagramManager'); private readonly toolbox: Toolbox; private readonly scene: Scene; @@ -49,7 +52,7 @@ export class DiagramManager { this.logger.debug("DiagramManager constructed"); scene.onMeshRemovedObservable.add((mesh) => { - if (mesh?.metadata?.template) { + if (isDiagramEntity(mesh)) { if (mesh.metadata.template != '#connection-template') { scene.meshes.forEach((m) => { if (m?.metadata?.to == mesh.id || m?.metadata?.from == mesh.id) { diff --git a/src/diagram/functions/buildEntityActionManager.ts b/src/diagram/functions/buildEntityActionManager.ts index 21879eb..f86e1a3 100644 --- a/src/diagram/functions/buildEntityActionManager.ts +++ b/src/diagram/functions/buildEntityActionManager.ts @@ -1,8 +1,10 @@ import {ActionManager, ExecuteCodeAction, PlaySoundAction, Scene} from "@babylonjs/core"; import {ControllerEventType, Controllers} from "../../controllers/controllers"; import {DiaSounds} from "../../util/diaSounds"; +import log from "loglevel"; export function buildEntityActionManager(scene: Scene, sounds: DiaSounds, controllers: Controllers) { + const logger = log.getLogger('buildEntityActionManager'); const actionManager = new ActionManager(scene); actionManager.registerAction( new PlaySoundAction(ActionManager.OnPointerOverTrigger, sounds.tick)); @@ -12,7 +14,7 @@ export function buildEntityActionManager(scene: Scene, sounds: DiaSounds, contro type: ControllerEventType.PULSE, gripId: evt?.additionalData?.pickResult?.gripTransform?.id }) - this.logger.debug(evt); + logger.debug(evt); }) ); return actionManager; diff --git a/src/diagram/functions/diagramEventHandler.ts b/src/diagram/functions/diagramEventHandler.ts index 6c4242d..02ce094 100644 --- a/src/diagram/functions/diagramEventHandler.ts +++ b/src/diagram/functions/diagramEventHandler.ts @@ -7,6 +7,7 @@ import {Toolbox} from "../../toolbox/toolbox"; import {DiaSounds} from "../../util/diaSounds"; import {fromDiagramEntity} from "./fromDiagramEntity"; +import {isDiagramEntity} from "./isDiagramEntity"; export function diagramEventHandler(event: DiagramEvent, @@ -37,12 +38,19 @@ export function diagramEventHandler(event: DiagramEvent, } switch (event.type) { + case DiagramEventType.RESET: + this.scene.getAllMeshes().forEach((m) => { + if (m?.metadata?.template && !m?.metadata?.tool) { + m.dispose(); + } + }); + break; case DiagramEventType.CLEAR: break; case DiagramEventType.DROPPED: break; case DiagramEventType.DROP: - if (mesh?.metadata?.template && (mesh.metadata.template.indexOf('#') > -1)) { + if (isDiagramEntity(mesh) && (mesh.metadata.template.indexOf('#') > -1)) { TextLabel.updateTextNode(mesh, entity.text); } break; @@ -71,7 +79,6 @@ export function diagramEventHandler(event: DiagramEvent, } else { mesh.dispose(); } - sounds.exit.play(); } break; diff --git a/src/diagram/functions/diagramShapePhysics.ts b/src/diagram/functions/diagramShapePhysics.ts index 3567eae..0c142ea 100644 --- a/src/diagram/functions/diagramShapePhysics.ts +++ b/src/diagram/functions/diagramShapePhysics.ts @@ -1,6 +1,7 @@ import {DiaSounds} from "../../util/diaSounds"; import {AbstractMesh, PhysicsAggregate, PhysicsBody, PhysicsMotionType, PhysicsShapeType, Scene} from "@babylonjs/core"; import log from "loglevel"; +import {isDiagramEntity} from "./isDiagramEntity"; const logger = log.getLogger('DiagramShapePhysics'); const MASS_FACTOR = 10; @@ -9,7 +10,7 @@ export function applyPhysics(sounds: DiaSounds, mesh: AbstractMesh, scene: Scene, motionType?: PhysicsMotionType) { - if (!mesh?.metadata?.template) { + if (!isDiagramEntity(mesh)) { logger.error("applyPhysics: mesh.metadata.template is null", mesh); return; } diff --git a/src/diagram/functions/fromDiagramEntity.ts b/src/diagram/functions/fromDiagramEntity.ts index 6fc8e32..8f21bf2 100644 --- a/src/diagram/functions/fromDiagramEntity.ts +++ b/src/diagram/functions/fromDiagramEntity.ts @@ -1,9 +1,10 @@ import {DiagramEntity} from "../types/diagramEntity"; -import {AbstractMesh, Color3, InstancedMesh, Mesh, Quaternion, Scene, StandardMaterial, Vector3} from "@babylonjs/core"; +import {AbstractMesh, InstancedMesh, Mesh, Quaternion, Scene, Vector3} from "@babylonjs/core"; import {DiagramConnection} from "../diagramConnection"; import {TextLabel} from "../../objects/textLabel"; import log from "loglevel"; import {v4 as uuidv4} from 'uuid'; +import {buildStandardMaterial} from "../../materials/functions/buildStandardMaterial"; const logger = log.getLogger('fromDiagramEntity'); @@ -54,9 +55,8 @@ export function fromDiagramEntity(entity: DiagramEntity, scene: Scene): Abstract newMesh.scaling = xyztovec(entity.scale); } if (!newMesh.material) { - const material = new StandardMaterial("material-" + entity.id, scene); - material.diffuseColor = Color3.FromHexString(entity.color); - newMesh.material = material; + this.logger.warn("new material created, this shouldn't happen"); + newMesh.material = buildStandardMaterial("material-" + entity.id, scene, entity.color); } if (entity.text) { newMesh.metadata.text = entity.text; diff --git a/src/diagram/functions/isDiagramEntity.ts b/src/diagram/functions/isDiagramEntity.ts new file mode 100644 index 0000000..b01f371 --- /dev/null +++ b/src/diagram/functions/isDiagramEntity.ts @@ -0,0 +1,9 @@ +import {AbstractMesh} from "@babylonjs/core"; + +export function isDiagramEntity(mesh: AbstractMesh): boolean { + if (mesh?.metadata?.template != undefined) { + return true; + } else { + return false; + } +} \ No newline at end of file diff --git a/src/diagram/presentationManager.ts b/src/diagram/presentationManager.ts index 02b2367..48c35cd 100644 --- a/src/diagram/presentationManager.ts +++ b/src/diagram/presentationManager.ts @@ -1,6 +1,7 @@ import {PresentationStep} from "./presentationStep"; import log, {Logger} from "loglevel"; import {Scene} from "@babylonjs/core"; +import {isDiagramEntity} from "./functions/isDiagramEntity"; export class PresentationManager { _currentStep: PresentationStep = null; @@ -24,7 +25,7 @@ export class PresentationManager { this._steps[this._steps.length - 1].next = step; } else { this.scene.getActiveMeshes().forEach((mesh) => { - if (mesh.metadata?.template) { + if (isDiagramEntity(mesh)) { step.entities.push({ entity: mesh, endPosition: mesh.position.clone(), diff --git a/src/diagram/types/diagramEntity.ts b/src/diagram/types/diagramEntity.ts index e72992b..7cab1ba 100644 --- a/src/diagram/types/diagramEntity.ts +++ b/src/diagram/types/diagramEntity.ts @@ -9,7 +9,8 @@ export enum DiagramEventType { DROPPED, CLEAR, CHANGECOLOR, - SYNC + SYNC, + RESET } export enum DiagramEventMask { diff --git a/src/diagram/types/diagramListing.ts b/src/diagram/types/diagramListing.ts index ac78f6d..38d9f22 100644 --- a/src/diagram/types/diagramListing.ts +++ b/src/diagram/types/diagramListing.ts @@ -2,15 +2,15 @@ export enum DiagramListingEventType { GET, ADD, REMOVE, - MODIFY + MODIFY, + GETALL, } export type DiagramListingEvent = { type: DiagramListingEventType; - listing: DiagramListing; + listing?: DiagramListing; } export type DiagramListing = { - type: DiagramListingEvent; id: string; name: string; description?: string; diff --git a/src/integration/pouchdbPersistenceManager.ts b/src/integration/pouchdbPersistenceManager.ts index 5644c2b..34e4d17 100644 --- a/src/integration/pouchdbPersistenceManager.ts +++ b/src/integration/pouchdbPersistenceManager.ts @@ -6,11 +6,11 @@ import {v4 as uuidv4} from 'uuid'; import axios from "axios"; import {DiagramManager} from "../diagram/diagramManager"; import log, {Logger} from "loglevel"; -import {DiagramListing, DiagramListingEvent} from "../diagram/types/diagramListing"; +import {DiagramListing, DiagramListingEventType} from "../diagram/types/diagramListing"; + export class PouchdbPersistenceManager { configObserver: Observable = new Observable(); - diagramListingObserver: Observable = new Observable(); updateObserver: Observable = new Observable(); removeObserver: Observable = new Observable(); //implement IPersistenceManager interface with pouchdb apis @@ -25,6 +25,18 @@ export class PouchdbPersistenceManager { } public setDiagramManager(diagramManager: DiagramManager) { + diagramManager.onDiagramEventListingObservable.add((evt) => { + if (evt.type == DiagramListingEventType.GETALL) { + this.diagramListings.allDocs({include_docs: true}).then((all) => { + for (const entity of all.rows) { + diagramManager.onDiagramEventListingObservable.notifyObservers({ + type: DiagramListingEventType.ADD, + listing: {id: entity.doc._id, name: entity.doc.name} + }, -1, false, this); + } + }); + } + }, -1, false, this); diagramManager.onDiagramEventObservable.add((evt) => { switch (evt.type) { case DiagramEventType.CHANGECOLOR: diff --git a/src/materials/functions/buildStandardMaterial.ts b/src/materials/functions/buildStandardMaterial.ts index d4c8e5d..d1fca7f 100644 --- a/src/materials/functions/buildStandardMaterial.ts +++ b/src/materials/functions/buildStandardMaterial.ts @@ -5,9 +5,9 @@ export function buildStandardMaterial(name: string, scene: Scene, color: string) if (existingMaterial) { return (existingMaterial as StandardMaterial); } - const handleMaterial = new StandardMaterial(name, scene); - handleMaterial.id = name; - handleMaterial.diffuseColor = Color3.FromHexString(color); - handleMaterial.alpha = 1; - return handleMaterial; + const newMaterial = new StandardMaterial(name, scene); + newMaterial.id = name; + newMaterial.diffuseColor = Color3.FromHexString(color); + newMaterial.alpha = 1; + return newMaterial; } \ No newline at end of file diff --git a/src/menus/cameraMenu.ts b/src/menus/cameraMenu.ts index 3869945..3356506 100644 --- a/src/menus/cameraMenu.ts +++ b/src/menus/cameraMenu.ts @@ -1,9 +1,11 @@ import {Color3, DynamicTexture, Mesh, MeshBuilder, Scene, StandardMaterial, Vector3} from "@babylonjs/core"; +import log, {Logger} from "loglevel"; export class CameraMenu { private readonly scene: Scene; private xr; private controllers; + private readonly logger: Logger = log.getLogger('CameraMenu'); constructor(scene, xr, controllers) { this.scene = scene; @@ -22,23 +24,11 @@ export class CameraMenu { slice: .5, sideOrientation: Mesh.DOUBLESIDE }, this.scene); - //const camerasphere = MeshBuilder.CreatePlane("camerasphere", {width: 1.6, height: .6, sideOrientation: Mesh.DOUBLESIDE }, this.scene); camerasphere.position = position; const material = new StandardMaterial("cameramaterial", this.scene); material.emissiveColor = new Color3(1, 1, 1); - //camerasphere.rotation.z = Math.PI; - /*const texture = new VideoTexture("video", - 'https://local.immersiveidea.com/', - this.scene); -*/ - //const texture = new DynamicTexture("dynamic texture", {width: 512, height: 256}, this.scene, false); const texture = new DynamicTexture('texture', {width: 1600, height: 1600}, this.scene); - //const img = document.createElement('img'); - //document.body.append(img); - //img.width=2592; - //img.height=1944; - material.diffuseTexture = texture; const img = new Image(); img.src = 'https://cameras.immersiveidea.com/mjpg/video.mjpg?camera=' + camnum + '×tamp=1698497537140'; @@ -47,34 +37,15 @@ export class CameraMenu { ctx.drawImage(img, 250, 0, 2112, 1940, 0, 0, 1600, 1600); texture.update(); window.setInterval((texture, img, ctx) => { - //const start = new Date(); ctx.drawImage(img, 250, 0, 2112, 1940, 0, 0, 1600, 1600); texture.update(); - //console.log(new Date() - start); }, 60, texture, img, ctx); } - //https://cameras.immersiveidea.com/mjpg/video.mjpg?camera=1×tamp=1698497537140'); - - //texture.getContext().drawImage(img, 0,0); - texture.onLoadObservable.add(() => { - console.log('texture loaded'); + this.logger.debug('texture loaded'); }); - this.scene.onAfterRenderObservable.add(() => { - // texture._rebuild(); - }, 1, true, this); camerasphere.material = material; - /*texture.video.play().then(() => { - console.log('video playing'); - }).catch((err) => { - console.log(err); - console.log("here"); - }); - */ - console.log('video loaded'); - //Material.diffuseColor = new Color3(0, 0, 0); - - //https://cameras.immersiveidea.com/mjpg/video.mjpg?camera=1&resolution=2592x1944&compression=30&mirror=0&rotation=0&textsize=medium&textposition=top&textbackgroundcolor=black&textcolor=white&text=0&clock=0&date=0&overlayimage=0&fps=0&videokeyframeinterval=13&videobitrate=0&maxframesize=0×tamp=1698491710423 + this.logger.info('camera built'); } } \ No newline at end of file diff --git a/src/menus/diagramListingMenu.ts b/src/menus/diagramListingMenu.ts index 3a607c8..d5af3d3 100644 --- a/src/menus/diagramListingMenu.ts +++ b/src/menus/diagramListingMenu.ts @@ -3,14 +3,24 @@ import {AbstractMenu} from "./abstractMenu"; import {ControllerEventType, Controllers} from "../controllers/controllers"; import {AdvancedDynamicTexture, Button, Control, ScrollViewer, StackPanel, TextBlock} from "@babylonjs/gui"; import {setMenuPosition} from "../util/functions/setMenuPosition"; +import {DiagramManager} from "../diagram/diagramManager"; +import {DiagramListingEvent, DiagramListingEventType} from "../diagram/types/diagramListing"; + export class DiagramListingMenu extends AbstractMenu { private mesh: AbstractMesh; - constructor(scene: Scene, xr: WebXRDefaultExperience, controllers: Controllers) { + private panel: StackPanel; + private readonly diagramManager: DiagramManager; + + constructor(scene: Scene, xr: WebXRDefaultExperience, controllers: Controllers, diagramManager: DiagramManager) { super(scene, xr, controllers); + this.diagramManager = diagramManager; + + this.buildMenu(); this.controllers.controllerObserver.add((event) => { if (event.type == ControllerEventType.B_BUTTON) { + this.toggle(); } }); @@ -19,9 +29,15 @@ export class DiagramListingMenu extends AbstractMenu { public toggle() { setMenuPosition(this.handle.mesh, this.scene, new Vector3(0, .4, 0)); this.mesh.isVisible = !this.mesh.isVisible; + this.populateData(); (this.mesh.parent as AbstractMesh).isVisible = this.mesh.isVisible; } + public populateData() { + this.panel.clearControls(); + this.diagramManager.onDiagramEventListingObservable.notifyObservers({type: DiagramListingEventType.GETALL}, -1); + } + private buildMenu() { const configPlane = MeshBuilder .CreatePlane("gridSizePlane", @@ -35,37 +51,44 @@ export class DiagramListingMenu extends AbstractMenu { configTexture.background = "white"; const scrollViewer = new ScrollViewer('diagramListingScroll'); configTexture.addControl(scrollViewer); - const stackpanel = new StackPanel('diagramListingStack'); - scrollViewer.addControl(stackpanel); - for (let i = 0; i < 100; i++) { - const row = new StackPanel('diagramListingRow ' + i); - row.isVertical = false; - row.height = "68px"; - row.width = 1; - stackpanel.addControl(row); - const selectButton = Button.CreateSimpleButton('diagramListingText ' + i, 'Select'); - selectButton.height = "64px"; - selectButton.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT; - selectButton.width = "220px"; - selectButton.color = "white"; - selectButton.fontSize = "48px"; - selectButton.background = "#333333"; - selectButton.onPointerClickObservable.add(() => { + this.panel = new StackPanel('diagramListingStack'); + scrollViewer.addControl(this.panel); - }); - const textBlock = new TextBlock('diagramListingText ' + i, 'Diagram ' + i); - textBlock.width = "1000px"; - textBlock.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT; - textBlock.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT; - textBlock.fontSize = "48px"; - row.addControl(selectButton); - row.addControl(textBlock); - - } this.createHandle(configPlane); configPlane.position.y = .5; setMenuPosition(this.handle.mesh, this.scene, new Vector3(0, .4, 0)); this.mesh.isVisible = false; (this.mesh.parent as AbstractMesh).isVisible = false; + this.diagramManager.onDiagramEventListingObservable.add((event: DiagramListingEvent) => { + if (event.type == DiagramListingEventType.ADD) { + this.addRow(event.listing.id, event.listing.name); + } + }, -1, false, this); + + } + + private addRow(id: string, name: string) { + const row = new StackPanel('diagramListingRow ' + id); + row.isVertical = false; + row.height = "68px"; + row.width = 1; + this.panel.addControl(row); + const selectButton = Button.CreateSimpleButton('diagramListingText ' + id, id); + selectButton.height = "64px"; + selectButton.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT; + selectButton.width = "220px"; + selectButton.color = "white"; + selectButton.fontSize = "48px"; + selectButton.background = "#333333"; + selectButton.onPointerClickObservable.add(() => { + console.log(id); + }, -1, false, this); + const textBlock = new TextBlock('diagramListingText ' + name, 'Diagram ' + name); + textBlock.width = "1000px"; + textBlock.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT; + textBlock.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT; + textBlock.fontSize = "48px"; + row.addControl(selectButton); + row.addControl(textBlock); } } \ No newline at end of file diff --git a/src/menus/editMenu.ts b/src/menus/editMenu.ts index b0880bb..aa4988a 100644 --- a/src/menus/editMenu.ts +++ b/src/menus/editMenu.ts @@ -28,6 +28,7 @@ import {setMenuPosition} from "../util/functions/setMenuPosition"; import {SoccerMenu} from "../soccer/soccerMenu"; import {CameraMenu} from "./cameraMenu"; import {exportGltf} from "../util/functions/exportGltf"; +import {isDiagramEntity} from "../diagram/functions/isDiagramEntity"; export class EditMenu extends AbstractMenu { private state: EditMenuState = EditMenuState.NONE; @@ -160,23 +161,63 @@ export class EditMenu extends AbstractMenu { this.diagramManager.onDiagramEventObservable.notifyObservers(event, -1); } - private modifyMesh(mesh: AbstractMesh) { - if (mesh.metadata?.template && - mesh.parent?.parent?.id != "toolbox") { - if (this.gizmoManager.gizmos.boundingBoxGizmo.attachedMesh?.id == mesh.id) { - this.gizmoManager.gizmos.boundingBoxGizmo.attachedMesh = null; - } else { - this.gizmoManager.attachToMesh(mesh); - this.gizmoManager.gizmos.boundingBoxGizmo.onScaleBoxDragObservable.add(() => { - this.diagramManager.onDiagramEventObservable.notifyObservers({ - type: DiagramEventType.MODIFY, - entity: toDiagramEntity(mesh), - }, -1 - ) - this.logger.debug(mesh.scaling); - }); + constructor(scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager, controllers: Controllers) { + super(scene, xr, controllers); + this.sounds = new DiaSounds(scene); + this.diagramManager = diagramManager; + this.gizmoManager = new GizmoManager(scene); + this.gizmoManager.boundingBoxGizmoEnabled = true; + this.gizmoManager.gizmos.boundingBoxGizmo.scaleBoxSize = .020; + this.gizmoManager.gizmos.boundingBoxGizmo.rotationSphereSize = .020; + this.gizmoManager.gizmos.boundingBoxGizmo.scaleDragSpeed = 2; + this.gizmoManager.clearGizmoOnEmptyPointerEvent = true; + this.gizmoManager.usePointerToAttachGizmos = false; + this.manager = new GUI3DManager(this.scene); + const panel = new PlanePanel(); + + panel.columns = 4; + this.manager.addControl(panel); + panel.addControl(this.makeButton("Cameras", "camera")); + panel.addControl(this.makeButton("Modify", "modify")); + panel.addControl(this.makeButton("Remove", "remove")); + panel.addControl(this.makeButton("Add Label", "label")); + panel.addControl(this.makeButton("Copy", "copy")); + panel.addControl(this.makeButton("Connect", "connect")); + panel.addControl(this.makeButton("Export GLTF", "exportgltf")); + panel.addControl(this.makeButton("Recolor", "recolor")); + panel.addControl(this.makeButton("New Relic", "newrelic")); + panel.addControl(this.makeButton("Soccer", "soccer")); + //panel.addControl(this.makeButton("Add Ring Cameras", "addRingCameras")); + this.manager.controlScaling = .1; + this.scene.onPointerObservable.add((pointerInfo) => { + switch (pointerInfo.type) { + case PointerEventTypes.POINTERPICK: + const pickedMesh = pointerInfo.pickInfo?.pickedMesh; + if (isDiagramEntity(pickedMesh) && + pickedMesh?.parent?.parent?.id != "toolbox") { + this.diagramEntityPicked(pointerInfo).then(() => { + this.logger.debug("handled"); + }).catch((e) => { + this.logger.error(e); + }); + break; + } else { + const tool = pickedMesh?.metadata?.tool; + if (tool) { + this.logger.debug("tool type", tool); + this.paintColor = (pickedMesh.material as StandardMaterial).diffuseColor.toHexString(); + this.logger.debug((pickedMesh.material as StandardMaterial).diffuseColor.toHexString()); + this.logger.debug(pickedMesh.id); + } + + } } - } + }); + this.panel = panel; + this.createHandle(this.manager.rootContainer.children[0].node); + this.manager.rootContainer.children[0].node.position.y = .2; + this.isVisible = false; + } private copyMesh(mesh: AbstractMesh) { @@ -223,63 +264,23 @@ export class EditMenu extends AbstractMenu { } - constructor(scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager, controllers: Controllers) { - super(scene, xr, controllers); - this.sounds = new DiaSounds(scene); - this.diagramManager = diagramManager; - this.gizmoManager = new GizmoManager(scene); - this.gizmoManager.boundingBoxGizmoEnabled = true; - this.gizmoManager.gizmos.boundingBoxGizmo.scaleBoxSize = .020; - this.gizmoManager.gizmos.boundingBoxGizmo.rotationSphereSize = .020; - this.gizmoManager.gizmos.boundingBoxGizmo.scaleDragSpeed = 2; - this.gizmoManager.clearGizmoOnEmptyPointerEvent = true; - this.gizmoManager.usePointerToAttachGizmos = false; - this.manager = new GUI3DManager(this.scene); - const panel = new PlanePanel(); - - panel.columns = 4; - this.manager.addControl(panel); - panel.addControl(this.makeButton("Cameras", "camera")); - panel.addControl(this.makeButton("Modify", "modify")); - panel.addControl(this.makeButton("Remove", "remove")); - panel.addControl(this.makeButton("Add Label", "label")); - panel.addControl(this.makeButton("Copy", "copy")); - panel.addControl(this.makeButton("Connect", "connect")); - panel.addControl(this.makeButton("Export GLTF", "exportgltf")); - panel.addControl(this.makeButton("Recolor", "recolor")); - panel.addControl(this.makeButton("New Relic", "newrelic")); - panel.addControl(this.makeButton("Soccer", "soccer")); - //panel.addControl(this.makeButton("Add Ring Cameras", "addRingCameras")); - this.manager.controlScaling = .1; - this.scene.onPointerObservable.add((pointerInfo) => { - switch (pointerInfo.type) { - case PointerEventTypes.POINTERPICK: - const pickedMesh = pointerInfo.pickInfo?.pickedMesh; - if (pickedMesh.metadata?.template && - pickedMesh?.parent?.parent?.id != "toolbox") { - this.diagramEntityPicked(pointerInfo).then(() => { - this.logger.debug("handled"); - }).catch((e) => { - this.logger.error(e); - }); - break; - } else { - const tool = pickedMesh?.metadata?.tool; - if (tool) { - this.logger.debug("tool type", tool); - this.paintColor = (pickedMesh.material as StandardMaterial).diffuseColor.toHexString(); - this.logger.debug((pickedMesh.material as StandardMaterial).diffuseColor.toHexString()); - this.logger.debug(pickedMesh.id); - } - - } + private modifyMesh(mesh: AbstractMesh) { + if (isDiagramEntity(mesh) && + mesh.parent?.parent?.id != "toolbox") { + if (this.gizmoManager.gizmos.boundingBoxGizmo.attachedMesh?.id == mesh.id) { + this.gizmoManager.gizmos.boundingBoxGizmo.attachedMesh = null; + } else { + this.gizmoManager.attachToMesh(mesh); + this.gizmoManager.gizmos.boundingBoxGizmo.onScaleBoxDragObservable.add(() => { + this.diagramManager.onDiagramEventObservable.notifyObservers({ + type: DiagramEventType.MODIFY, + entity: toDiagramEntity(mesh), + }, -1 + ) + this.logger.debug(mesh.scaling); + }); } - }); - this.panel = panel; - this.createHandle(this.manager.rootContainer.children[0].node); - this.manager.rootContainer.children[0].node.position.y = .2; - this.isVisible = false; - + } } private handleClick(_info, state) { diff --git a/src/toolbox/functions/buildTool.ts b/src/toolbox/functions/buildTool.ts index 5c110c1..321303f 100644 --- a/src/toolbox/functions/buildTool.ts +++ b/src/toolbox/functions/buildTool.ts @@ -19,9 +19,9 @@ export function buildTool(tool: ToolType, parent: AbstractMesh) { WIDGET_SIZE, WIDGET_SIZE); newItem.parent = parent; - newItem.metadata = {template: tool}; + newItem.metadata = {template: tool, tool: true}; const instance = new InstancedMesh("instance-" + id, newItem); - instance.metadata = {template: tool}; + instance.metadata = {template: tool, tool: true}; instance.parent = parent; newItem.setEnabled(false); newItem.onEnabledStateChangedObservable.add(() => { diff --git a/src/tutorial/introduction.ts b/src/tutorial/introduction.ts index a3db6ec..d49a200 100644 --- a/src/tutorial/introduction.ts +++ b/src/tutorial/introduction.ts @@ -15,6 +15,7 @@ import {Button3D, GUI3DManager, TextBlock} from "@babylonjs/gui"; import {DiaSounds} from "../util/diaSounds"; import {AppConfig} from "../util/appConfig"; import Hls from "hls.js"; +import log, {Logger} from "loglevel"; export class Introduction { @@ -27,6 +28,7 @@ export class Introduction { private advance: Button3D; private sounds: DiaSounds; private config: AppConfig; + private logger: Logger = log.getLogger('Introduction'); private videoElement: HTMLVideoElement; @@ -90,7 +92,7 @@ export class Introduction { hls.attachMedia(vid); hls.on(Hls.Events.MANIFEST_PARSED, function () { vid.play().then(() => { - console.log("Video Playing"); + this.logger.debug("Video Playing"); }); }); } else if (vid.canPlayType('application/vnd.apple.mpegurl')) { diff --git a/src/util/customPhysics.ts b/src/util/customPhysics.ts index 5dedf8c..d9e49ae 100644 --- a/src/util/customPhysics.ts +++ b/src/util/customPhysics.ts @@ -3,6 +3,7 @@ import HavokPhysics from "@babylonjs/havok"; import {AppConfig} from "./appConfig"; import {snapGridVal} from "./functions/snapGridVal"; import {snapRotateVal} from "./functions/snapRotateVal"; +import {isDiagramEntity} from "../diagram/functions/isDiagramEntity"; export class CustomPhysics { private readonly scene: Scene; @@ -21,7 +22,7 @@ export class CustomPhysics { scene.collisionsEnabled = true; scene.onAfterPhysicsObservable.add(() => { scene.meshes.forEach((mesh) => { - if (mesh?.metadata?.template && mesh.physicsBody) { + if (isDiagramEntity(mesh) && mesh.physicsBody) { const body = mesh.physicsBody; const linearVelocity = new Vector3(); body.getLinearVelocityToRef(linearVelocity); diff --git a/src/util/spinner.ts b/src/util/spinner.ts index 732acfe..e6c532f 100644 --- a/src/util/spinner.ts +++ b/src/util/spinner.ts @@ -54,14 +54,7 @@ export class Spinner { rotate.setKeys(keys); spinner.animations.push(rotate); this.scene.beginAnimation(spinner, 0, 30, true); - //material.indexOfRefraction = Math.PI/4; - //material.indexOfRefraction = 1; - /*material.reflectionFresnelParameters = new FresnelParameters(); - material.reflectionFresnelParameters.leftColor = Color3.Black(); - material.reflectionFresnelParameters.rightColor = Color3.White(); - material.reflectionFresnelParameters.power = 1; -*/ material.alpha = .9; spinner.material = material; let particleSystem; @@ -92,7 +85,5 @@ export class Spinner { this.spinner = spinner; this.spinner.setEnabled(false); this.particleSystem = particleSystem; - - } } \ No newline at end of file