Refactor how controllers are initialized.

This commit is contained in:
Michael Mainguy 2023-08-14 15:51:48 -05:00
parent 64060ef573
commit f554a09474
15 changed files with 182 additions and 147 deletions

View File

@ -15,9 +15,9 @@ import log from "loglevel";
import {AppConfig} from "./util/appConfig";
import {GamepadManager} from "./controllers/gamepadManager";
import {CustomEnvironment} from "./util/customEnvironment";
import {DrawioManager} from "./integration/drawioManager";
import {VoiceManager} from "./integration/voiceManager";
import {TranscriptType} from "./integration/voiceTranscript";
import {Controllers} from "./controllers/controllers";
export class App {
@ -25,17 +25,17 @@ export class App {
constructor() {
const config = AppConfig.config;
const logger = log.getLogger('App');
log.enableAll(true);
log.setDefaultLevel('debug');
log.setDefaultLevel('info');
log.getLogger('App').setLevel('info');
//log.getLogger('App').setLevel('info');
//log.getLogger('IndexdbPersistenceManager').setLevel('info');
//log.getLogger('DiagramManager').setLevel('info');
//log.getLogger('DiagramConnection').setLevel('debug');
log.getLogger('DrawioManager').setLevel('warn');
log.getLogger('VoiceManager').setLevel('debug');
log.getLogger('EntityTree').setLevel('warn');
log.getLogger('EditMenu').setLevel('warn');
//log.getLogger('DrawioManager').setLevel('warn');
//log.getLogger('VoiceManager').setLevel('debug');
//log.getLogger('EntityTree').setLevel('warn');
//log.getLogger('EditMenu').setLevel('warn');
const canvas = document.createElement("canvas");
canvas.style.width = "100%";
canvas.style.height = "100%";
@ -92,9 +92,10 @@ export class App {
}
});
const diagramManager = new DiagramManager(scene, xr.baseExperience);
const rig = new Rigplatform(scene, xr, diagramManager);
const toolbox = new Toolbox(scene, xr.baseExperience, diagramManager);
const controllers = new Controllers();
const diagramManager = new DiagramManager(scene, xr.baseExperience, controllers);
const rig = new Rigplatform(scene, xr, diagramManager, controllers);
const toolbox = new Toolbox(scene, xr.baseExperience, diagramManager, controllers);
//const dioManager = new DrawioManager(scene, diagramManager);
import ('./integration/indexdbPersistenceManager').then((module) => {
const persistenceManager = new module.IndexdbPersistenceManager("diagram");

View File

@ -32,13 +32,15 @@ export class Base {
protected readonly diagramManager: DiagramManager;
private logger: log.Logger;
private lastPosition: Vector3 = null;
protected controllers: Controllers;
constructor(controller: WebXRInputSource,
scene: Scene,
xr: WebXRDefaultExperience,
controllers: Controllers,
diagramManager: DiagramManager) {
this.logger = log.getLogger('Base');
this.controller = controller;
this.controllers = controllers;
this.scene = scene;
@ -79,7 +81,7 @@ export class Base {
this.initGrip(init.components['xr-standard-squeeze'])
}
});
Controllers.controllerObserver.add((event) => {
this.controllers.controllerObserver.add((event) => {
if (event.type == 'pulse') {
this.logger.debug(event);
if (event.gripId == this?.controller?.grip?.id) {

View File

@ -6,6 +6,6 @@ export type ControllerEventType = {
gripId?: string;
}
export class Controllers {
public static movable: TransformNode | AbstractMesh;
public static controllerObserver: Observable<ControllerEventType> = new Observable();
public movable: TransformNode | AbstractMesh;
public readonly controllerObserver: Observable<ControllerEventType> = new Observable();
}

View File

@ -11,17 +11,17 @@ export class Left extends Base {
public configMenu: ConfigMenu;
constructor(controller:
WebXRInputSource, scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager) {
WebXRInputSource, scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager, controllers: Controllers) {
super(controller, scene, xr, diagramManager);
this.configMenu = new ConfigMenu(this.scene, xr.baseExperience);
super(controller, scene, xr, controllers, diagramManager);
this.configMenu = new ConfigMenu(this.scene, xr.baseExperience, this.controllers);
Left.instance = this;
this.controller.onMotionControllerInitObservable.add((init) => {
if (init.components['xr-standard-thumbstick']) {
init.components['xr-standard-thumbstick']
.onAxisValueChangedObservable.add((value) => {
log.trace('Left', `thumbstick moved ${value.x}, ${value.y}`);
if (!Controllers.movable) {
if (!this.controllers.movable) {
this.moveRig(value);
} else {
this.moveMovable(value);
@ -32,19 +32,21 @@ export class Left extends Base {
init.components['xr-standard-thumbstick'].onButtonStateChangedObservable.add((value) => {
if (value.pressed) {
log.trace('Left', 'thumbstick changed');
Controllers.controllerObserver.notifyObservers({type: 'decreaseVelocity', value: value.value});
this.controllers.controllerObserver.notifyObservers({
type: 'decreaseVelocity',
value: value.value
});
}
});
}
});
}
private initXButton(xbutton: WebXRControllerComponent) {
if (xbutton) {
xbutton.onButtonStateChangedObservable.add((button) => {
if (button.pressed) {
Controllers.controllerObserver.notifyObservers({type: 'x-button', value: button.value});
this.controllers.controllerObserver.notifyObservers({type: 'x-button', value: button.value});
}
});
}
@ -54,7 +56,7 @@ export class Left extends Base {
if (ybutton) {
ybutton.onButtonStateChangedObservable.add((button) => {
if (button.pressed) {
Controllers.controllerObserver.notifyObservers({type: 'y-button', value: button.value});
this.controllers.controllerObserver.notifyObservers({type: 'y-button', value: button.value});
}
});
}
@ -62,12 +64,12 @@ export class Left extends Base {
private moveMovable(value: { x: number, y: number }) {
if (Math.abs(value.x) > .1) {
Controllers.movable.position.x += .005 * Math.sign(value.x);
this.controllers.movable.position.x += .005 * Math.sign(value.x);
} else {
}
if (Math.abs(value.y) > .1) {
Controllers.movable.position.y += -.005 * Math.sign(value.y);
this.controllers.movable.position.y += -.005 * Math.sign(value.y);
} else {
}
@ -75,21 +77,24 @@ export class Left extends Base {
private moveRig(value: { x: number, y: number }) {
if (Math.abs(value.x) > .1) {
Controllers.controllerObserver.notifyObservers({type: 'leftright', value: value.x * this.speedFactor});
this.controllers.controllerObserver.notifyObservers({type: 'leftright', value: value.x * this.speedFactor});
Base.stickVector.x = 1;
} else {
Base.stickVector.x = 0;
}
if (Math.abs(value.y) > .1) {
Controllers.controllerObserver.notifyObservers({type: 'forwardback', value: value.y * this.speedFactor});
this.controllers.controllerObserver.notifyObservers({
type: 'forwardback',
value: value.y * this.speedFactor
});
Base.stickVector.y = 1;
} else {
Base.stickVector.y = 0;
}
if (Base.stickVector.equals(Vector3.Zero())) {
Controllers.controllerObserver.notifyObservers({type: 'leftright', value: 0});
Controllers.controllerObserver.notifyObservers({type: 'forwardback', value: 0});
this.controllers.controllerObserver.notifyObservers({type: 'leftright', value: 0});
this.controllers.controllerObserver.notifyObservers({type: 'forwardback', value: 0});
} else {
}

View File

@ -8,9 +8,9 @@ export class Right extends Base {
public static instance: Right;
constructor(controller:
WebXRInputSource, scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager
WebXRInputSource, scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager, controllers: Controllers,
) {
super(controller, scene, xr, diagramManager);
super(controller, scene, xr, controllers, diagramManager);
Right.instance = this;
this.controller.onMotionControllerInitObservable.add((init) => {
this.initTrigger(init.components['xr-standard-trigger']);
@ -24,7 +24,7 @@ export class Right extends Base {
if (bbutton) {
bbutton.onButtonStateChangedObservable.add((button) => {
if (button.pressed) {
Controllers.controllerObserver.notifyObservers({type: 'b-button', value: button.value});
this.controllers.controllerObserver.notifyObservers({type: 'b-button', value: button.value});
}
});
}
@ -36,7 +36,7 @@ export class Right extends Base {
.onButtonStateChangedObservable
.add((button) => {
if (button.pressed) {
Controllers.controllerObserver.notifyObservers({type: 'trigger', value: button.value});
this.controllers.controllerObserver.notifyObservers({type: 'trigger', value: button.value});
}
});
}
@ -47,7 +47,7 @@ export class Right extends Base {
abutton.onButtonStateChangedObservable.add((value) => {
if (value.pressed) {
log.getLogger("right").debug("a-button pressed");
Controllers.controllerObserver.notifyObservers({type: 'menu'});
this.controllers.controllerObserver.notifyObservers({type: 'menu'});
}
});
}
@ -62,7 +62,7 @@ export class Right extends Base {
thumbstick.onButtonStateChangedObservable.add((value) => {
if (value.pressed) {
log.trace('Right', `thumbstick changed ${value.value}`);
Controllers.controllerObserver.notifyObservers({type: 'increaseVelocity', value: value.value});
this.controllers.controllerObserver.notifyObservers({type: 'increaseVelocity', value: value.value});
}
});
}
@ -70,19 +70,19 @@ export class Right extends Base {
private moveRig(value) {
if (Math.abs(value.x) > .1) {
Controllers.controllerObserver.notifyObservers({type: 'turn', value: value.x});
this.controllers.controllerObserver.notifyObservers({type: 'turn', value: value.x});
} else {
Controllers.controllerObserver.notifyObservers({type: 'turn', value: 0});
this.controllers.controllerObserver.notifyObservers({type: 'turn', value: 0});
}
if (Math.abs(value.y) > .1) {
Controllers.controllerObserver.notifyObservers({type: 'updown', value: value.y * this.speedFactor});
this.controllers.controllerObserver.notifyObservers({type: 'updown', value: value.y * this.speedFactor});
Base.stickVector.z = 1;
} else {
Controllers.controllerObserver.notifyObservers({type: 'updown', value: 0});
this.controllers.controllerObserver.notifyObservers({type: 'updown', value: 0});
Base.stickVector.z = 0;
}
if (Base.stickVector.equals(Vector3.Zero())) {
Controllers.controllerObserver.notifyObservers({type: 'updown', value: 0});
this.controllers.controllerObserver.notifyObservers({type: 'updown', value: 0});
}
}
}

View File

@ -39,44 +39,8 @@ export class Rigplatform {
private turnVelocity: number = 0;
private logger = log.getLogger('Rigplatform');
private readonly diagramManager: DiagramManager;
constructor(scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager) {
this.scene = scene;
this.diagramManager = diagramManager;
Rigplatform.xr = xr;
Rigplatform.instance = this;
this.bMenu = new EditMenu(scene, xr.baseExperience, this.diagramManager);
this.camera = scene.activeCamera;
this.rigMesh = MeshBuilder.CreateBox("platform", {width: 2, height: .02, depth: 2}, scene);
for (const cam of scene.cameras) {
cam.parent = this.rigMesh;
}
const rigMaterial = new StandardMaterial("rigMaterial", scene);
rigMaterial.diffuseColor = Color3.Blue();
this.rigMesh.material = rigMaterial;
this.rigMesh.setAbsolutePosition(new Vector3(0, .1, -3));
this.rigMesh.visibility = 0;
const rigAggregate =
new PhysicsAggregate(
this.rigMesh,
PhysicsShapeType.CYLINDER,
{friction: 1, center: Vector3.Zero(), radius: .5, mass: 10, restitution: .01},
scene);
rigAggregate.body.setMotionType(PhysicsMotionType.DYNAMIC);
rigAggregate.body.setGravityFactor(.001);
this.fixRotation();
this.body = rigAggregate.body;
this.initializeControllers();
scene.onActiveCameraChanged.add((s) => {
this.camera = s.activeCamera;
this.camera.parent = this.rigMesh;
});
this.registerVelocityObserver();
}
private readonly controllers: Controllers;
private registered = false;
private registerVelocityObserver() {
this.scene.onBeforeRenderObservable.add(() => {
const vel = this.velocity.applyRotationQuaternion(this.scene.activeCamera.absoluteRotation);
@ -118,51 +82,103 @@ export class Rigplatform {
}
}
constructor(scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager, controllers: Controllers) {
this.scene = scene;
this.diagramManager = diagramManager;
this.controllers = controllers;
Rigplatform.xr = xr;
Rigplatform.instance = this;
this.bMenu = new EditMenu(scene, xr.baseExperience, this.diagramManager);
this.camera = scene.activeCamera;
this.rigMesh = MeshBuilder.CreateBox("platform", {width: 2, height: .02, depth: 2}, scene);
for (const cam of scene.cameras) {
cam.parent = this.rigMesh;
}
const rigMaterial = new StandardMaterial("rigMaterial", scene);
rigMaterial.diffuseColor = Color3.Blue();
this.rigMesh.material = rigMaterial;
this.rigMesh.setAbsolutePosition(new Vector3(0, .1, -3));
this.rigMesh.visibility = 0;
const rigAggregate =
new PhysicsAggregate(
this.rigMesh,
PhysicsShapeType.CYLINDER,
{friction: 1, center: Vector3.Zero(), radius: .5, mass: 10, restitution: .01},
scene);
rigAggregate.body.setMotionType(PhysicsMotionType.DYNAMIC);
rigAggregate.body.setGravityFactor(.001);
this.fixRotation();
this.body = rigAggregate.body;
this.initializeControllers();
scene.onActiveCameraChanged.add((s) => {
this.camera = s.activeCamera;
this.camera.parent = this.rigMesh;
});
this.registerVelocityObserver();
}
private registerObserver() {
if (!this.registered) {
this.registered = true;
this.controllers.controllerObserver.add((event: { type: string, value: number }) => {
switch (event.type) {
case "increaseVelocity":
if (this.velocityIndex < this.velocityArray.length - 1) {
this.velocityIndex++;
} else {
this.velocityIndex = 0;
}
break;
case "decreaseVelocity":
if (this.velocityIndex > 0) {
this.velocityIndex--;
} else {
this.velocityIndex = this.velocityArray.length - 1;
}
break;
case "turn":
this.turn(event.value);
break;
case "forwardback":
this.forwardback(event.value);
break;
case "leftright":
this.leftright(event.value);
break;
case "updown":
this.updown(event.value);
break;
case "stop":
log.warn("Rigplatform", "stop is no longer implemented");
break;
case "menu":
this.bMenu.toggle();
break;
}
});
}
}
private initializeControllers() {
Rigplatform.xr.input.onControllerAddedObservable.add((source) => {
this.registerObserver();
let controller;
switch (source.inputSource.handedness) {
case "right":
Right.instance = new Right(source, this.scene, Rigplatform.xr, this.diagramManager);
Controllers.controllerObserver.add((event: { type: string, value: number }) => {
switch (event.type) {
case "increaseVelocity":
if (this.velocityIndex < this.velocityArray.length - 1) {
this.velocityIndex++;
} else {
this.velocityIndex = 0;
}
break;
case "decreaseVelocity":
if (this.velocityIndex > 0) {
this.velocityIndex--;
} else {
this.velocityIndex = this.velocityArray.length-1;
}
break;
case "turn":
this.turn(event.value);
break;
case "forwardback":
this.forwardback(event.value);
break;
case "leftright":
this.leftright(event.value);
break;
case "updown":
this.updown(event.value);
break;
case "stop":
log.warn("Rigplatform", "stop is no longer implemented");
break;
case "menu":
this.bMenu.toggle();
break;
}
});
if (!Right.instance) {
Right.instance = new Right(source, this.scene, Rigplatform.xr, this.diagramManager, this.controllers);
}
break;
case "left":
Left.instance = new Left(source, this.scene, Rigplatform.xr, this.diagramManager);
if (!Left.instance) {
Left.instance = new Left(source, this.scene, Rigplatform.xr, this.diagramManager, this.controllers);
}
break;
}

View File

@ -135,6 +135,8 @@ export class DiagramConnection {
private removeConnection = () => {
this.logger.debug("removeConnection");
this.scene.onBeforeRenderObservable.removeCallback(this.beforeRender);
this._mesh.onDisposeObservable.removeCallback(this.removeConnection);
this.removeObserver();
if (this.toAnchor) {
this.toAnchor = null;

View File

@ -1,5 +1,5 @@
import {Color3, Vector3} from "@babylonjs/core";
import {EditMenuState} from "../menus/MenuState";
import {EditMenuState} from "../menus/editMenuState";
export enum DiagramEventType {
ADD,

View File

@ -45,16 +45,18 @@ export class DiagramManager {
private readonly actionManager: ActionManager;
private config: AppConfig;
private controllers: Controllers;
constructor(scene: Scene, xr: WebXRExperienceHelper) {
constructor(scene: Scene, xr: WebXRExperienceHelper, controllers: Controllers) {
this.scene = scene;
this.xr = xr;
this.controllers = controllers;
this.actionManager = new ActionManager(this.scene);
this.actionManager.registerAction(
new PlaySoundAction(ActionManager.OnPointerOverTrigger, DiaSounds.instance.tick));
this.actionManager.registerAction(
new ExecuteCodeAction(ActionManager.OnPointerOverTrigger, (evt) => {
Controllers.controllerObserver.notifyObservers({
this.controllers.controllerObserver.notifyObservers({
type: 'pulse',
gripId: evt?.additionalData?.pickResult?.gripTransform?.id
})

View File

@ -1,6 +1,5 @@
import {AbstractMesh, Color3, MeshBuilder, Scene, Vector3} from "@babylonjs/core";
import {AdvancedDynamicTexture, StackPanel, TextBlock} from "@babylonjs/gui";
import {Controllers} from "../controllers/controllers";
export class Hud {
private scene: Scene;
@ -32,12 +31,7 @@ export class Hud {
stackPanel.addControl(textPosition);
stackPanel.addControl(textRotation);
this.scene.onBeforeRenderObservable.add(() => {
if (Controllers.movable) {
textPosition.text = 'position: '+ this.formatVector3(Controllers.movable.position);
textRotation.text = 'rotation: '+ this.formatVector3(Controllers.movable.rotation);
}
});
}
createTextBlock(): TextBlock {
const text = new TextBlock();

View File

@ -11,14 +11,21 @@ export class ConfigMenu {
private readonly xr: WebXRExperienceHelper;
private configPlane: AbstractMesh = null;
constructor(scene: Scene, xr: WebXRExperienceHelper) {
private controllers: Controllers;
private yObserver;
constructor(scene: Scene, xr: WebXRExperienceHelper, controllers: Controllers) {
this.scene = scene;
this.xr = xr;
Controllers.controllerObserver.add((event) => {
if (event.type == 'x-button') {
this.toggle();
}
});
this.controllers = controllers;
if (!this.yObserver) {
this.controllers.controllerObserver.add((event) => {
if (event.type == 'y-button') {
this.toggle();
}
});
}
}
public toggle() {

View File

@ -13,7 +13,7 @@ import {
} from "@babylonjs/core";
import {Button3D, GUI3DManager, StackPanel3D, TextBlock} from "@babylonjs/gui";
import {DiagramManager} from "../diagram/diagramManager";
import {EditMenuState} from "./MenuState";
import {EditMenuState} from "./editMenuState";
import {DiagramEvent, DiagramEventType} from "../diagram/diagramEntity";
import {MeshConverter} from "../diagram/meshConverter";
import log from "loglevel";
@ -60,7 +60,7 @@ export class EditMenu {
panel.addControl(this.makeButton("Recolor", "recolor"));
//panel.addControl(this.makeButton("Add Ring Cameras", "addRingCameras"));
this.manager.controlScaling = .5;
this.manager.controlScaling = .1;
this.scene.onPointerObservable.add((pointerInfo) => {
switch (pointerInfo.type) {
case PointerEventTypes.POINTERPICK:

View File

@ -36,11 +36,13 @@ export class Toolbox {
private readonly manager: GUI3DManager;
private readonly gridsize = 5;
private readonly addPanel: StackPanel3D;
private readonly controllers: Controllers;
private xObserver;
constructor(scene: Scene, xr: WebXRExperienceHelper, diagramManager: DiagramManager) {
constructor(scene: Scene, xr: WebXRExperienceHelper, diagramManager: DiagramManager, controllers: Controllers) {
this.scene = scene;
this.controllers = controllers;
this.diagramManager = diagramManager;
this.diagramManager.onDiagramEventObservable.add((evt) => {
if (evt?.entity?.color && evt.type == DiagramEventType.CHANGECOLOR) {
this.updateToolbox(evt.entity.color);
@ -71,15 +73,17 @@ export class Toolbox {
}
Toolbox.instance = this;
Controllers.controllerObserver.add((evt) => {
if (evt.type == 'y-button') {
if (evt.value == 1) {
this.node.parent.setEnabled(!this.node.parent.isEnabled(false));
CameraHelper.setMenuPosition(this.node.parent as Mesh, this.scene,
new Vector3(0, -.5, 0));
if (!this.xObserver) {
this.xObserver = this.controllers.controllerObserver.add((evt) => {
if (evt.type == 'x-button') {
if (evt.value == 1) {
this.node.parent.setEnabled(!this.node.parent.isEnabled(false));
CameraHelper.setMenuPosition(this.node.parent as Mesh, this.scene,
new Vector3(0, 0, 0));
}
}
}
});
});
}
}
public buildTool(tool: ToolType, parent: AbstractMesh) {

View File

@ -8,12 +8,14 @@ export class CameraHelper {
}
public static setMenuPosition(node: TransformNode, scene: Scene, offset: Vector3 = Vector3.Zero()) {
node.position =
CameraHelper.getFrontPosition(2, scene);
const front = CameraHelper.getFrontPosition(.8, scene);
front.y = scene.activeCamera.globalPosition.y;
node.position = front;
node.position.addInPlace(offset);
node.lookAt(scene.activeCamera.globalPosition);
node.rotation.y = node.rotation.y + Math.PI;
node.position.y += .2;
node.position.y -= .5;
}
}