Added tick sound
This commit is contained in:
parent
14363bc1ca
commit
4c52d7b1d7
@ -39,11 +39,7 @@ export class App {
|
||||
|
||||
constructor() {
|
||||
const config = AppConfig.config;
|
||||
|
||||
log.setLevel('info');
|
||||
log.getLogger('AppConfig').setLevel('debug');
|
||||
log.getLogger('IndexdbPersistenceManager').setLevel('debug');
|
||||
|
||||
log.setLevel('debug');
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.style.width = "100%";
|
||||
canvas.style.height = "100%";
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
import {
|
||||
AbstractMesh,
|
||||
InstancedMesh,
|
||||
Mesh,
|
||||
Scene,
|
||||
Vector3,
|
||||
WebXRControllerComponent,
|
||||
@ -13,6 +11,7 @@ import {DiagramManager} from "../diagram/diagramManager";
|
||||
import {DiagramEvent, DiagramEventType} from "../diagram/diagramEntity";
|
||||
import log from "loglevel";
|
||||
import {AppConfig} from "../util/appConfig";
|
||||
import {Controllers} from "./controllers";
|
||||
|
||||
|
||||
export class Base {
|
||||
@ -28,12 +27,14 @@ export class Base {
|
||||
|
||||
protected readonly xr: WebXRDefaultExperience;
|
||||
protected readonly diagramManager: DiagramManager;
|
||||
|
||||
private logger: log.Logger;
|
||||
constructor(controller: WebXRInputSource,
|
||||
scene: Scene,
|
||||
xr: WebXRDefaultExperience,
|
||||
diagramManager: DiagramManager) {
|
||||
this.logger = log.getLogger('Base');
|
||||
this.controller = controller;
|
||||
|
||||
this.scene = scene;
|
||||
this.xr = xr;
|
||||
this.diagramManager = diagramManager;
|
||||
@ -47,6 +48,15 @@ export class Base {
|
||||
}
|
||||
this.initGrip(init.components['xr-standard-squeeze']);
|
||||
});
|
||||
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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public disable() {
|
||||
@ -59,15 +69,6 @@ export class Base {
|
||||
this.controller.pointer.setEnabled(true);
|
||||
}
|
||||
|
||||
private createCopy(mesh: AbstractMesh) {
|
||||
if (!mesh.isAnInstance) {
|
||||
return new InstancedMesh("new", (mesh as Mesh));
|
||||
} else {
|
||||
return new InstancedMesh("new", (mesh as InstancedMesh).sourceMesh);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private initGrip(grip: WebXRControllerComponent) {
|
||||
grip.onButtonStateChangedObservable.add(() => {
|
||||
if (grip.changes.pressed) {
|
||||
@ -98,7 +99,7 @@ export class Base {
|
||||
this.grabbedMesh = mesh;
|
||||
} else {
|
||||
const config = AppConfig.config;
|
||||
const newMesh = this.createCopy(mesh);
|
||||
const newMesh = this.diagramManager.createCopy(mesh);
|
||||
newMesh.position = mesh.absolutePosition.clone();
|
||||
newMesh.rotation = mesh.absoluteRotationQuaternion.toEulerAngles().clone();
|
||||
newMesh.scaling = config.createSnapVal;
|
||||
|
||||
@ -2,7 +2,8 @@ import {AbstractMesh, Observable, TransformNode} from "@babylonjs/core";
|
||||
|
||||
export type ControllerEventType = {
|
||||
type: string,
|
||||
value?: number
|
||||
value?: number,
|
||||
gripId?: string;
|
||||
}
|
||||
export class Controllers {
|
||||
public static movable: TransformNode | AbstractMesh;
|
||||
|
||||
@ -1,8 +1,21 @@
|
||||
import {Observable, Scene, WebXRExperienceHelper} from "@babylonjs/core";
|
||||
import {
|
||||
AbstractMesh,
|
||||
ActionManager,
|
||||
Color3,
|
||||
ExecuteCodeAction,
|
||||
InstancedMesh,
|
||||
Mesh,
|
||||
Observable,
|
||||
PlaySoundAction,
|
||||
Scene,
|
||||
Sound,
|
||||
WebXRExperienceHelper
|
||||
} from "@babylonjs/core";
|
||||
import {DiagramEntity, DiagramEvent, DiagramEventType} from "./diagramEntity";
|
||||
import {IPersistenceManager} from "./persistenceManager";
|
||||
import {MeshConverter} from "./meshConverter";
|
||||
import log from "loglevel";
|
||||
import {Controllers} from "../controllers/controllers";
|
||||
|
||||
export class DiagramManager {
|
||||
public readonly onDiagramEventObservable: Observable<DiagramEvent> = new Observable();
|
||||
@ -11,15 +24,7 @@ export class DiagramManager {
|
||||
private readonly scene: Scene;
|
||||
private xr: WebXRExperienceHelper;
|
||||
|
||||
constructor(scene: Scene, xr: WebXRExperienceHelper) {
|
||||
this.scene = scene;
|
||||
this.xr = xr;
|
||||
if (this.onDiagramEventObservable.hasObservers()) {
|
||||
this.logger.warn("onDiagramEventObservable already has Observers, you should be careful");
|
||||
}
|
||||
this.onDiagramEventObservable.add(this.onDiagramEvent, -1, true, this);
|
||||
this.logger.debug("DiagramManager constructed");
|
||||
}
|
||||
private readonly tick: Sound;
|
||||
|
||||
public setPersistenceManager(persistenceManager: IPersistenceManager) {
|
||||
this.persistenceManager = persistenceManager;
|
||||
@ -33,11 +38,56 @@ export class DiagramManager {
|
||||
}
|
||||
return this.persistenceManager;
|
||||
}
|
||||
private readonly actionManager: ActionManager;
|
||||
|
||||
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));
|
||||
this.actionManager.registerAction(
|
||||
new ExecuteCodeAction(ActionManager.OnPointerOverTrigger, (evt) => {
|
||||
Controllers.controllerObserver.notifyObservers({
|
||||
type: 'pulse',
|
||||
gripId: evt?.additionalData?.pickResult?.gripTransform?.id
|
||||
})
|
||||
this.logger.debug(evt);
|
||||
})
|
||||
);
|
||||
if (this.onDiagramEventObservable.hasObservers()) {
|
||||
this.logger.warn("onDiagramEventObservable already has Observers, you should be careful");
|
||||
}
|
||||
this.onDiagramEventObservable.add(this.onDiagramEvent, -1, true, this);
|
||||
this.logger.debug("DiagramManager constructed");
|
||||
}
|
||||
|
||||
public createCopy(mesh: AbstractMesh): AbstractMesh {
|
||||
let newMesh;
|
||||
if (!mesh.isAnInstance) {
|
||||
newMesh = new InstancedMesh("new", (mesh as Mesh));
|
||||
} else {
|
||||
newMesh = new InstancedMesh("new", (mesh as InstancedMesh).sourceMesh);
|
||||
}
|
||||
newMesh.actionManager = this.actionManager;
|
||||
return newMesh;
|
||||
|
||||
}
|
||||
|
||||
private onRemoteEvent(event: DiagramEntity) {
|
||||
//const mesh = Toolbox.instance.newMesh(ToolType[Object.entries(ToolType).find(e => e[1] == event.template)[0]], event.id);
|
||||
this.logger.debug(event);
|
||||
const toolMesh = this.scene.getMeshById("tool-" + event.template + "-" + event.color);
|
||||
if (!toolMesh) {
|
||||
log.debug('no mesh found for ' + event.template + "-" + event.color, 'adding it');
|
||||
this.onDiagramEventObservable.notifyObservers({
|
||||
type: DiagramEventType.CHANGECOLOR,
|
||||
entity: event
|
||||
});
|
||||
}
|
||||
const mesh = MeshConverter.fromDiagramEntity(event, this.scene);
|
||||
mesh.actionManager = this.actionManager;
|
||||
if (event.parent) {
|
||||
mesh.parent = this.scene.getMeshById(event.parent);
|
||||
}
|
||||
@ -66,7 +116,23 @@ export class DiagramManager {
|
||||
this.getPersistenceManager()?.modify(mesh);
|
||||
break;
|
||||
case DiagramEventType.CHANGECOLOR:
|
||||
if (!event.oldColor) {
|
||||
if (!event.newColor) {
|
||||
this.getPersistenceManager()?.changeColor(null, Color3.FromHexString(event.entity.color));
|
||||
this.logger.info("Recieved color change event, sending entity color as new color");
|
||||
} else {
|
||||
this.logger.info("Recieved color change event, no old color, sending new color");
|
||||
this.getPersistenceManager()?.changeColor(null, event.newColor);
|
||||
}
|
||||
} else {
|
||||
if (event.newColor) {
|
||||
this.logger.info("changing color from " + event.oldColor + " to " + event.newColor);
|
||||
this.getPersistenceManager()?.changeColor(event.oldColor, event.newColor);
|
||||
} else {
|
||||
this.logger.error("changing color from " + event.oldColor + ", but no new color found");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case DiagramEventType.REMOVE:
|
||||
if (mesh) {
|
||||
|
||||
@ -4,7 +4,7 @@ import {DiagramEntity} from "./diagramEntity";
|
||||
import Dexie from "dexie";
|
||||
import {MeshConverter} from "./meshConverter";
|
||||
import log from "loglevel";
|
||||
import {AppConfigType} from "../util/appConfig";
|
||||
import {AppConfigType} from "../util/appConfigType";
|
||||
|
||||
|
||||
export class IndexdbPersistenceManager implements IPersistenceManager {
|
||||
@ -16,8 +16,8 @@ export class IndexdbPersistenceManager implements IPersistenceManager {
|
||||
constructor(name: string) {
|
||||
this.db = new Dexie(name);
|
||||
const version = 2;
|
||||
this.db.version(2).stores({config: "id,gridSnap,rotateSnap,createSnap"});
|
||||
this.db.version(2).stores({entities: "id,position,rotation,last_seen,template,text,scale,color"});
|
||||
this.db.version(version).stores({config: "id,gridSnap,rotateSnap,createSnap"});
|
||||
this.db.version(version).stores({entities: "id,position,rotation,last_seen,template,text,scale,color"});
|
||||
this.logger.debug("IndexdbPersistenceManager constructed");
|
||||
|
||||
}
|
||||
@ -83,8 +83,12 @@ export class IndexdbPersistenceManager implements IPersistenceManager {
|
||||
}
|
||||
|
||||
public changeColor(oldColor, newColor) {
|
||||
if (!oldColor || !newColor) {
|
||||
this.logger.error("changeColor called with null color, early return");
|
||||
if (!oldColor) {
|
||||
if (!newColor) {
|
||||
this.logger.error("changeColor called with no new color, early return");
|
||||
} else {
|
||||
this.logger.info("changeColor called with no old Color, new color added to diagram, early return");
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.logger.debug(`changeColor ${oldColor.toHexString()} to ${newColor.toHexString()}`);
|
||||
|
||||
@ -10,7 +10,6 @@ import {
|
||||
StandardMaterial
|
||||
} from "@babylonjs/core";
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
import {Toolbox} from "../toolbox/toolbox";
|
||||
import log from "loglevel";
|
||||
|
||||
|
||||
@ -61,14 +60,6 @@ export class MeshConverter {
|
||||
}
|
||||
} else {
|
||||
log.debug('no mesh found for ' + entity.template + "-" + entity.color);
|
||||
Toolbox.instance.updateToolbox(entity.color);
|
||||
mesh = scene.getMeshById("tool-" + entity.template + "-" + entity.color);
|
||||
if (!mesh) {
|
||||
log.debug('no mesh found for ' + entity.template + "-" + entity.color);
|
||||
} else {
|
||||
mesh = new InstancedMesh(entity.id, (mesh as Mesh));
|
||||
}
|
||||
//Toolbox.instance.buildTool(Toolbox.getToolTypeFromString(entity.template), entity.color);
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,9 +142,14 @@ export class MeshConverter {
|
||||
const plane = MeshBuilder.CreatePlane("text", {width: planeWidth, height: height}, mesh.getScene());
|
||||
plane.material = mat;
|
||||
plane.billboardMode = Mesh.BILLBOARDMODE_ALL;
|
||||
//textNode = this.updateTextNode(mesh, entity.text);
|
||||
|
||||
|
||||
const yOffset = mesh.getBoundingInfo().boundingSphere.radius;
|
||||
plane.parent = mesh;
|
||||
plane.position.y = .5 + (.125 / 2);
|
||||
plane.position.y = yOffset;
|
||||
plane.scaling.y = 1 / mesh.scaling.y;
|
||||
plane.scaling.x = 1 / mesh.scaling.x;
|
||||
plane.scaling.z = 1 / mesh.scaling.z;
|
||||
return plane;
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
import {AbstractMesh, Color3, Observable} from "@babylonjs/core";
|
||||
import {DiagramEntity} from "./diagramEntity";
|
||||
import {AppConfigType} from "../util/appConfig";
|
||||
import {AppConfigType} from "../util/appConfigType";
|
||||
|
||||
|
||||
export interface IPersistenceManager {
|
||||
add(mesh: AbstractMesh);
|
||||
|
||||
@ -40,6 +40,12 @@ export class Toolbox {
|
||||
constructor(scene: Scene, xr: WebXRExperienceHelper, diagramManager: DiagramManager) {
|
||||
this.scene = scene;
|
||||
this.diagramManager = diagramManager;
|
||||
|
||||
this.diagramManager.onDiagramEventObservable.add((evt) => {
|
||||
if (evt?.entity?.color && evt.type == DiagramEventType.CHANGECOLOR) {
|
||||
this.updateToolbox(evt.entity.color);
|
||||
}
|
||||
}, -1, true, this);
|
||||
this.addPanel = new StackPanel3D();
|
||||
this.manager = new GUI3DManager(scene);
|
||||
this.manager.addControl(this.addPanel);
|
||||
@ -62,8 +68,10 @@ export class Toolbox {
|
||||
} else {
|
||||
this.buildToolbox();
|
||||
}
|
||||
|
||||
Toolbox.instance = this;
|
||||
}
|
||||
|
||||
private buildToolbox() {
|
||||
this.node.position.y = -.2;
|
||||
this.node.scaling= new Vector3(0.5, 0.5, 0.5);
|
||||
|
||||
@ -2,17 +2,13 @@ import {Angle, Vector3} from "@babylonjs/core";
|
||||
import round from "round";
|
||||
import log from "loglevel";
|
||||
import {IPersistenceManager} from "../diagram/persistenceManager";
|
||||
import {AppConfigType} from "./appConfigType";
|
||||
|
||||
export type SnapValue = {
|
||||
value: number,
|
||||
label: string
|
||||
}
|
||||
export type AppConfigType = {
|
||||
id?: number,
|
||||
gridSnap: number,
|
||||
rotateSnap: number,
|
||||
createSnap: number
|
||||
}
|
||||
|
||||
|
||||
export class AppConfig {
|
||||
private readonly logger = log.getLogger('AppConfig');
|
||||
|
||||
6
src/util/appConfigType.ts
Normal file
6
src/util/appConfigType.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export type AppConfigType = {
|
||||
id?: number,
|
||||
gridSnap: number,
|
||||
rotateSnap: number,
|
||||
createSnap: number
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user