diff --git a/public/Big Dripper_1.wav b/public/Big Dripper_1.wav new file mode 100644 index 0000000..3c15ee2 Binary files /dev/null and b/public/Big Dripper_1.wav differ diff --git a/public/sounds.mp3 b/public/sounds.mp3 new file mode 100644 index 0000000..aaf4dd5 Binary files /dev/null and b/public/sounds.mp3 differ diff --git a/src/app.ts b/src/app.ts index 41dd6fa..372bb91 100644 --- a/src/app.ts +++ b/src/app.ts @@ -27,6 +27,7 @@ import {DualshockEventMapper} from "./util/dualshockEventMapper"; import log from "loglevel"; import {AppConfig} from "./util/appConfig"; import {IndexdbPersistenceManager} from "./diagram/indexdbPersistenceManager"; +import {DiaSounds} from "./util/diaSounds"; export class App { //preTasks = [havokModule]; @@ -64,6 +65,8 @@ export class App { const scene = new Scene(engine); this.scene = scene; + const sounds = new DiaSounds(scene); + sounds.enter.autoplay = true; const havokInstance = await HavokPhysics(); @@ -95,8 +98,12 @@ export class App { } }); + this.xr.baseExperience.onStateChangedObservable.add((state) => { if (state == WebXRState.IN_XR) { + this.scene.audioEnabled = true; + + this.xr.baseExperience.camera.position = new Vector3(0, 1.6, 0); window.addEventListener(('pa-button-state-change'), (event: any) => { if (event.detail) { diff --git a/src/controllers/base.ts b/src/controllers/base.ts index dff3c27..e4f663f 100644 --- a/src/controllers/base.ts +++ b/src/controllers/base.ts @@ -51,8 +51,8 @@ export class Base { Controllers.controllerObserver.add((event) => { if (event.type == 'pulse') { this.logger.debug(event); - if (event.gripId == this.controller.grip.id) { - this.controller.motionController.pulse(.25, 30); + if (event.gripId == this?.controller?.grip?.id) { + this.controller?.motionController?.pulse(.25, 30); } } }); diff --git a/src/diagram/diagramManager.ts b/src/diagram/diagramManager.ts index e301b51..796dd2d 100644 --- a/src/diagram/diagramManager.ts +++ b/src/diagram/diagramManager.ts @@ -8,7 +8,6 @@ import { Observable, PlaySoundAction, Scene, - Sound, WebXRExperienceHelper } from "@babylonjs/core"; import {DiagramEntity, DiagramEvent, DiagramEventType} from "./diagramEntity"; @@ -16,6 +15,7 @@ import {IPersistenceManager} from "./persistenceManager"; import {MeshConverter} from "./meshConverter"; import log from "loglevel"; import {Controllers} from "../controllers/controllers"; +import {DiaSounds} from "../util/diaSounds"; export class DiagramManager { public readonly onDiagramEventObservable: Observable = new Observable(); @@ -24,7 +24,6 @@ export class DiagramManager { private readonly scene: Scene; private xr: WebXRExperienceHelper; - private readonly tick: Sound; public setPersistenceManager(persistenceManager: IPersistenceManager) { this.persistenceManager = persistenceManager; @@ -43,11 +42,9 @@ export class DiagramManager { constructor(scene: Scene, xr: WebXRExperienceHelper) { this.scene = scene; this.xr = xr; - this.tick = new Sound("tick", './tick.mp3', this.scene); - this.tick.setVolume(.3); this.actionManager = new ActionManager(this.scene); this.actionManager.registerAction( - new PlaySoundAction(ActionManager.OnPointerOverTrigger, this.tick)); + new PlaySoundAction(ActionManager.OnPointerOverTrigger, DiaSounds.instance.tick)); this.actionManager.registerAction( new ExecuteCodeAction(ActionManager.OnPointerOverTrigger, (evt) => { Controllers.controllerObserver.notifyObservers({ diff --git a/src/diagram/meshConverter.ts b/src/diagram/meshConverter.ts index f8ac1b8..1515b7c 100644 --- a/src/diagram/meshConverter.ts +++ b/src/diagram/meshConverter.ts @@ -15,6 +15,7 @@ import log from "loglevel"; export class MeshConverter { private static logger = log.getLogger('MeshConverter'); + public static toDiagramEntity(mesh: AbstractMesh): DiagramEntity { if (!mesh) { this.logger.error("toDiagramEntity: mesh is null"); @@ -57,6 +58,7 @@ export class MeshConverter { log.debug('error: mesh is an instance'); } else { mesh = new InstancedMesh(entity.id, (mesh as Mesh)); + } } else { log.debug('no mesh found for ' + entity.template + "-" + entity.color); @@ -68,7 +70,10 @@ export class MeshConverter { mesh.metadata = {template: entity.template}; if (entity.position) { + mesh.position = entity.position; + + } if (entity.rotation) { mesh.rotation = entity.rotation; @@ -88,6 +93,15 @@ export class MeshConverter { mesh.metadata.text = entity.text; this.updateTextNode(mesh, entity.text); } + /* + const sphereAggregate = new PhysicsAggregate(mesh, PhysicsShapeType.BOX, { + + mass: 10, + restitution: 0.1, + startAsleep: false + }, scene); + + */ } else { this.logger.error("fromDiagramEntity: mesh is null after it should have been created"); } diff --git a/src/menus/configMenu.ts b/src/menus/configMenu.ts index 2d31aab..0169afc 100644 --- a/src/menus/configMenu.ts +++ b/src/menus/configMenu.ts @@ -4,6 +4,7 @@ import {CameraHelper} from "../util/cameraHelper"; import log from "loglevel"; import {AppConfig} from "../util/appConfig"; import {Controllers} from "../controllers/controllers"; +import {DiaSounds} from "../util/diaSounds"; export class ConfigMenu { private readonly scene: Scene; @@ -22,10 +23,12 @@ export class ConfigMenu { public toggle() { if (this.configPlane) { + DiaSounds.instance.exit.play(); this.configPlane.dispose(); this.configPlane = null; return; } + DiaSounds.instance.enter.play(); const width = .25; const height = .55; const res = 256; diff --git a/src/util/diaSounds.ts b/src/util/diaSounds.ts new file mode 100644 index 0000000..ef4a84e --- /dev/null +++ b/src/util/diaSounds.ts @@ -0,0 +1,66 @@ +import {Scene, Sound} from "@babylonjs/core"; + + +export class DiaSounds { + public static instance: DiaSounds; + private scene: Scene; + + constructor(scene: Scene) { + this.scene = scene; + this._enter = new Sound("enter", "./sounds.mp3", this.scene, null, { + autoplay: false, + loop: false, + offset: 0, + length: 1.0 + }); + this._exit = new Sound("exit", "./sounds.mp3", this.scene, null, { + autoplay: false, + loop: false, + offset: 1, + length: 1.0 + }); + this._high = new Sound("high", "./sounds.mp3", this.scene, null, { + autoplay: false, + loop: false, + offset: 2, + length: 1.0 + }); + this._low = new Sound("low", "./sounds.mp3", this.scene, null, { + autoplay: false, + loop: false, + offset: 2, + length: 1.0 + }); + + + DiaSounds.instance = this; + } + + public get tick() { + return new Sound("tick", './tick.mp3', this.scene); + } + + private _enter: Sound; + + public get enter() { + return this._enter; + } + + private _exit: Sound; + + public get exit() { + return this._exit; + } + + private _high: Sound; + + public get high() { + return this._high; + } + + private _low: Sound; + + public get low() { + return this._low; + } +}