Removed dead code.

This commit is contained in:
Michael Mainguy 2024-08-26 07:54:18 -05:00
parent 53ca47d63e
commit 60758ed84d
49 changed files with 140 additions and 2344 deletions

View File

@ -9,7 +9,7 @@ import {
import {DiagramManager} from "../diagram/diagramManager"; import {DiagramManager} from "../diagram/diagramManager";
import {DiagramEvent, DiagramEventType} from "../diagram/types/diagramEntity"; import {DiagramEvent, DiagramEventType} from "../diagram/types/diagramEntity";
import log from "loglevel"; import log from "loglevel";
import {ControllerEventType, Controllers} from "./controllers";
import {grabAndClone} from "./functions/grabAndClone"; import {grabAndClone} from "./functions/grabAndClone";
import {ClickMenu} from "../menus/clickMenu"; import {ClickMenu} from "../menus/clickMenu";
import {motionControllerObserver} from "./functions/motionControllerObserver"; import {motionControllerObserver} from "./functions/motionControllerObserver";
@ -21,10 +21,13 @@ import {MeshTypeEnum} from "../diagram/types/meshTypeEnum";
import {getMeshType} from "./functions/getMeshType"; import {getMeshType} from "./functions/getMeshType";
import {viewOnly} from "../util/functions/getPath"; import {viewOnly} from "../util/functions/getPath";
import {ControllerEventType} from "./types/controllerEventType";
import {controllerObservable} from "./controllers";
const CLICK_TIME = 300; const CLICK_TIME = 300;
export class Base { export abstract class AbstractController {
static stickVector = Vector3.Zero(); static stickVector = Vector3.Zero();
protected readonly scene: Scene; protected readonly scene: Scene;
protected readonly xr: WebXRDefaultExperience; protected readonly xr: WebXRDefaultExperience;
@ -34,7 +37,7 @@ export class Base {
protected grabbedObject: DiagramObject = null; protected grabbedObject: DiagramObject = null;
protected grabbedMesh: AbstractMesh = null; protected grabbedMesh: AbstractMesh = null;
protected grabbedMeshType: MeshTypeEnum = null; protected grabbedMeshType: MeshTypeEnum = null;
protected controllers: Controllers;
private readonly _logger = log.getLogger('Base'); private readonly _logger = log.getLogger('Base');
private _clickStart: number = 0; private _clickStart: number = 0;
@ -48,7 +51,6 @@ export class Base {
diagramManager: DiagramManager) { diagramManager: DiagramManager) {
this._logger.debug('Base Controller Constructor called'); this._logger.debug('Base Controller Constructor called');
this.xrInputSource = controller; this.xrInputSource = controller;
this.controllers = diagramManager.controllers;
this.scene = DefaultScene.Scene; this.scene = DefaultScene.Scene;
this.xr = xr; this.xr = xr;
@ -66,7 +68,7 @@ export class Base {
//@TODO THis works, but it uses initGrip, not sure if this is the best idea //@TODO THis works, but it uses initGrip, not sure if this is the best idea
this.xrInputSource.onMotionControllerInitObservable.add(motionControllerObserver, -1, false, this); this.xrInputSource.onMotionControllerInitObservable.add(motionControllerObserver, -1, false, this);
this.controllers.controllerObservable.add((event) => { controllerObservable.add((event) => {
this._logger.debug(event); this._logger.debug(event);
switch (event.type) { switch (event.type) {
case ControllerEventType.PULSE: case ControllerEventType.PULSE:

View File

@ -1,41 +1,6 @@
import {AbstractMesh, Observable, TransformNode, Vector3, WebXRInputSource} from "@babylonjs/core"; import {AbstractMesh, Observable, TransformNode} from "@babylonjs/core";
import {ControllerEvent} from "./types/controllerEvent";
export type ControllerEvent = {
type: ControllerEventType,
value?: number,
startPosition?: Vector3,
endPosition?: Vector3,
duration?: number,
gripId?: string;
controller?: WebXRInputSource;
}
export enum ControllerEventType { export var movable: TransformNode | AbstractMesh;
GRIP = 'grip', export const controllerObservable: Observable<ControllerEvent> = new Observable();
HIDE = 'hide',
SHOW = 'show',
PULSE = 'pulse',
SQUEEZE = 'squeeze',
CLICK = 'click',
Y_BUTTON = 'y-button',
X_BUTTON = 'x-button',
A_BUTTON = 'a-button',
B_BUTTON = 'b-button',
THUMBSTICK = 'thumbstick',
THUMBSTICK_CHANGED = 'thumbstickChanged',
DECREASE_VELOCITY = 'decreaseVelocity',
INCREASE_VELOCITY = 'decreaseVelocity',
LEFT_RIGHT = 'leftright',
FORWARD_BACK = 'forwardback',
TURN = 'turn',
UP_DOWN = 'updown',
TRIGGER = 'trigger',
MENU = 'menu',
MOTION = 'motion',
GAZEPOINT = 'gazepoint',
}
export class Controllers {
public movable: TransformNode | AbstractMesh;
public readonly controllerObservable: Observable<ControllerEvent> = new Observable();
}

View File

@ -1,25 +0,0 @@
import {HavokPlugin} from "@babylonjs/core";
import {DefaultScene} from "../../defaultScene";
import log from "loglevel";
export function beforeRenderObserver() {
if (this?.grabbedMesh?.physicsBody) {
const scene = DefaultScene.Scene;
const hk = (scene.getPhysicsEngine().getPhysicsPlugin() as HavokPlugin);
this.lastPosition = this?.grabbedMesh?.physicsBody?.transformNode.absolutePosition.clone();
if (this.grabbedMeshParentId) {
const parent = scene.getTransformNodeById(this.grabbedMeshParentId);
if (parent) {
hk.setPhysicsBodyTransformation(this.grabbedMesh.physicsBody, parent);
hk.sync(this.grabbedMesh.physicsBody);
} else {
log.getLogger('beforeRenderObserver').error("parent not found for " + this.grabbedMeshParentId);
}
} else {
log.getLogger('beforeRenderObserver').warn("no parent id");
}
}
}

View File

@ -1,12 +0,0 @@
import {DiagramEvent, DiagramEventType} from "../../diagram/types/diagramEntity";
import {toDiagramEntity} from "../../diagram/functions/toDiagramEntity";
import {AbstractMesh} from "@babylonjs/core";
export function buildDrop(mesh: AbstractMesh): DiagramEvent {
const entity = toDiagramEntity(mesh);
return {
type: DiagramEventType.DROP,
entity: entity
}
}

View File

@ -35,7 +35,5 @@ export function grabAndClone(diagramManager: DiagramManager, mesh: AbstractMesh,
obj.baseTransform.setParent(parent); obj.baseTransform.setParent(parent);
diagramManager.addObject(obj); diagramManager.addObject(obj);
return obj; return obj;
} }
} }

View File

@ -8,7 +8,6 @@ export function handleWasGrabbed(mesh: AbstractMesh): boolean {
logger.debug("handleWasGrabbed: mesh is a diagram entity"); logger.debug("handleWasGrabbed: mesh is a diagram entity");
return false; return false;
} else { } else {
const result = (mesh?.metadata?.handle == true); const result = (mesh?.metadata?.handle == true);
logger.debug("handleWasGrabbed: mesh ", result); logger.debug("handleWasGrabbed: mesh ", result);
return result; return result;

View File

@ -1,24 +0,0 @@
import {AbstractMesh} from "@babylonjs/core";
import log from "loglevel";
export function reparent(mesh: AbstractMesh, previousParentId: string, grabbedMeshParentId: string) {
const logger = log.getLogger('reparent');
if (previousParentId) {
const parent = mesh.getScene().getMeshById(previousParentId);
if (parent) {
logger.warn('not yet implemented')
} else {
mesh.setParent(null);
}
} else {
const parent = mesh.getScene().getTransformNodeById(grabbedMeshParentId);
if (parent) {
logger.warn('setting parent to null', grabbedMeshParentId, parent)
mesh.setParent(null);
parent.dispose();
} else {
mesh.setParent(null);
}
}
}

View File

@ -1,10 +0,0 @@
import {AbstractMesh, TransformNode} from "@babylonjs/core";
export function setupTransformNode(mesh: TransformNode, parent: AbstractMesh) {
const transformNode = new TransformNode("grabAnchor, this.scene");
transformNode.id = "grabAnchor";
transformNode.position = mesh.position.clone();
transformNode.rotationQuaternion = mesh.rotationQuaternion.clone();
transformNode.setParent(parent);
return transformNode;
}

View File

@ -1,12 +1,13 @@
import {Vector3, WebXRControllerComponent, WebXRDefaultExperience, WebXRInputSource} from "@babylonjs/core"; import {Vector3, WebXRControllerComponent, WebXRDefaultExperience, WebXRInputSource} from "@babylonjs/core";
import {Base} from "./base"; import {AbstractController} from "./abstractController";
import {ControllerEventType} from "./controllers";
import log from "loglevel"; import log from "loglevel";
import {DiagramManager} from "../diagram/diagramManager"; import {DiagramManager} from "../diagram/diagramManager";
import {DefaultScene} from "../defaultScene"; import {DefaultScene} from "../defaultScene";
import {ControllerEventType} from "./types/controllerEventType";
import {controllerObservable, movable} from "./controllers";
export class Left extends Base { export class LeftController extends AbstractController {
private leftLogger = log.getLogger('Left'); private leftLogger = log.getLogger('Left');
constructor(controller: constructor(controller:
WebXRInputSource, xr: WebXRDefaultExperience, diagramManager: DiagramManager) { WebXRInputSource, xr: WebXRDefaultExperience, diagramManager: DiagramManager) {
@ -17,7 +18,7 @@ export class Left extends Base {
init.components['xr-standard-thumbstick'] init.components['xr-standard-thumbstick']
.onAxisValueChangedObservable.add((value) => { .onAxisValueChangedObservable.add((value) => {
this.leftLogger.trace(`thumbstick moved ${value.x}, ${value.y}`); this.leftLogger.trace(`thumbstick moved ${value.x}, ${value.y}`);
if (!this.controllers.movable) { if (!movable) {
this.moveRig(value); this.moveRig(value);
} else { } else {
this.moveMovable(value); this.moveMovable(value);
@ -29,7 +30,7 @@ export class Left extends Base {
init.components['xr-standard-thumbstick'].onButtonStateChangedObservable.add((value) => { init.components['xr-standard-thumbstick'].onButtonStateChangedObservable.add((value) => {
if (value.pressed) { if (value.pressed) {
this.leftLogger.trace('Left', 'thumbstick changed'); this.leftLogger.trace('Left', 'thumbstick changed');
this.controllers.controllerObservable.notifyObservers({ controllerObservable.notifyObservers({
type: ControllerEventType.DECREASE_VELOCITY, type: ControllerEventType.DECREASE_VELOCITY,
value: value.value value: value.value
}); });
@ -46,7 +47,7 @@ export class Left extends Base {
.onButtonStateChangedObservable .onButtonStateChangedObservable
.add((button) => { .add((button) => {
this.leftLogger.trace('trigger pressed'); this.leftLogger.trace('trigger pressed');
this.controllers.controllerObservable.notifyObservers({ controllerObservable.notifyObservers({
type: ControllerEventType.TRIGGER, type: ControllerEventType.TRIGGER,
value: button.value, value: button.value,
controller: this.xrInputSource controller: this.xrInputSource
@ -60,7 +61,7 @@ export class Left extends Base {
xbutton.onButtonStateChangedObservable.add((button) => { xbutton.onButtonStateChangedObservable.add((button) => {
if (button.pressed) { if (button.pressed) {
this.leftLogger.trace('X button pressed'); this.leftLogger.trace('X button pressed');
this.controllers.controllerObservable.notifyObservers({ controllerObservable.notifyObservers({
type: ControllerEventType.X_BUTTON, type: ControllerEventType.X_BUTTON,
value: button.value value: button.value
}); });
@ -74,7 +75,7 @@ export class Left extends Base {
ybutton.onButtonStateChangedObservable.add((button) => { ybutton.onButtonStateChangedObservable.add((button) => {
if (button.pressed) { if (button.pressed) {
this.leftLogger.trace('Y button pressed'); this.leftLogger.trace('Y button pressed');
this.controllers.controllerObservable.notifyObservers({ controllerObservable.notifyObservers({
type: ControllerEventType.Y_BUTTON, type: ControllerEventType.Y_BUTTON,
value: button.value value: button.value
}); });
@ -85,12 +86,12 @@ export class Left extends Base {
private moveMovable(value: { x: number, y: number }) { private moveMovable(value: { x: number, y: number }) {
if (Math.abs(value.x) > .1) { if (Math.abs(value.x) > .1) {
this.controllers.movable.position.x += .005 * Math.sign(value.x); movable.position.x += .005 * Math.sign(value.x);
} else { } else {
} }
if (Math.abs(value.y) > .1) { if (Math.abs(value.y) > .1) {
this.controllers.movable.position.y += -.005 * Math.sign(value.y); movable.position.y += -.005 * Math.sign(value.y);
} else { } else {
} }
@ -98,27 +99,27 @@ export class Left extends Base {
private moveRig(value: { x: number, y: number }) { private moveRig(value: { x: number, y: number }) {
if (Math.abs(value.x) > .1) { if (Math.abs(value.x) > .1) {
this.controllers.controllerObservable.notifyObservers({ controllerObservable.notifyObservers({
type: ControllerEventType.LEFT_RIGHT, type: ControllerEventType.LEFT_RIGHT,
value: value.x * this.speedFactor value: value.x * this.speedFactor
}); });
Base.stickVector.x = 1; AbstractController.stickVector.x = 1;
} else { } else {
Base.stickVector.x = 0; AbstractController.stickVector.x = 0;
} }
if (Math.abs(value.y) > .1) { if (Math.abs(value.y) > .1) {
this.controllers.controllerObservable.notifyObservers({ controllerObservable.notifyObservers({
type: ControllerEventType.FORWARD_BACK, type: ControllerEventType.FORWARD_BACK,
value: value.y * this.speedFactor value: value.y * this.speedFactor
}); });
Base.stickVector.y = 1; AbstractController.stickVector.y = 1;
} else { } else {
Base.stickVector.y = 0; AbstractController.stickVector.y = 0;
} }
if (Base.stickVector.equals(Vector3.Zero())) { if (AbstractController.stickVector.equals(Vector3.Zero())) {
this.controllers.controllerObservable.notifyObservers({type: ControllerEventType.LEFT_RIGHT, value: 0}); controllerObservable.notifyObservers({type: ControllerEventType.LEFT_RIGHT, value: 0});
this.controllers.controllerObservable.notifyObservers({type: ControllerEventType.FORWARD_BACK, value: 0}); controllerObservable.notifyObservers({type: ControllerEventType.FORWARD_BACK, value: 0});
} else { } else {
} }

View File

@ -1,19 +1,21 @@
import {Base} from "./base"; import {AbstractController} from "./abstractController";
import {Vector3, WebXRControllerComponent, WebXRDefaultExperience, WebXRInputSource} from "@babylonjs/core"; import {Vector3, WebXRControllerComponent, WebXRDefaultExperience, WebXRInputSource} from "@babylonjs/core";
import {ControllerEventType} from "./controllers";
import {DiagramManager} from "../diagram/diagramManager"; import {DiagramManager} from "../diagram/diagramManager";
import log from "loglevel"; import log from "loglevel";
import {ControllerEventType} from "./types/controllerEventType";
import {controllerObservable} from "./controllers";
export class Right extends Base { export class RightController extends AbstractController {
private rightLogger = log.getLogger("Right"); private rightLogger = log.getLogger("Right");
private initBButton(bbutton: WebXRControllerComponent) { private initBButton(bbutton: WebXRControllerComponent) {
if (bbutton) { if (bbutton) {
bbutton.onButtonStateChangedObservable.add((button) => { bbutton.onButtonStateChangedObservable.add((button) => {
if (button.pressed) { if (button.pressed) {
this.rightLogger.debug('B Button Pressed'); this.rightLogger.debug('B Button Pressed');
this.controllers.controllerObservable.notifyObservers({ controllerObservable.notifyObservers({
type: ControllerEventType.B_BUTTON, type: ControllerEventType.B_BUTTON,
value: button.value value: button.value
}); });
@ -41,7 +43,7 @@ export class Right extends Base {
.onButtonStateChangedObservable .onButtonStateChangedObservable
.add((button) => { .add((button) => {
this.rightLogger.debug("right trigger pressed"); this.rightLogger.debug("right trigger pressed");
this.controllers.controllerObservable.notifyObservers({ controllerObservable.notifyObservers({
type: ControllerEventType.TRIGGER, type: ControllerEventType.TRIGGER,
value: button.value, value: button.value,
controller: this.xrInputSource controller: this.xrInputSource
@ -55,7 +57,7 @@ export class Right extends Base {
abutton.onButtonStateChangedObservable.add((value) => { abutton.onButtonStateChangedObservable.add((value) => {
if (value.pressed) { if (value.pressed) {
this.rightLogger.debug('A button pressed'); this.rightLogger.debug('A button pressed');
this.controllers.controllerObservable.notifyObservers({type: ControllerEventType.MENU}); controllerObservable.notifyObservers({type: ControllerEventType.MENU});
} }
}); });
} }
@ -70,7 +72,7 @@ export class Right extends Base {
thumbstick.onButtonStateChangedObservable.add((value) => { thumbstick.onButtonStateChangedObservable.add((value) => {
if (value.pressed) { if (value.pressed) {
this.rightLogger.trace('Right', `thumbstick changed ${value.value}`); this.rightLogger.trace('Right', `thumbstick changed ${value.value}`);
this.controllers.controllerObservable.notifyObservers({ controllerObservable.notifyObservers({
type: ControllerEventType.INCREASE_VELOCITY, type: ControllerEventType.INCREASE_VELOCITY,
value: value.value value: value.value
}); });
@ -81,22 +83,22 @@ export class Right extends Base {
private moveRig(value) { private moveRig(value) {
if (Math.abs(value.x) > .1) { if (Math.abs(value.x) > .1) {
this.controllers.controllerObservable.notifyObservers({type: ControllerEventType.TURN, value: value.x}); controllerObservable.notifyObservers({type: ControllerEventType.TURN, value: value.x});
} else { } else {
this.controllers.controllerObservable.notifyObservers({type: ControllerEventType.TURN, value: 0}); controllerObservable.notifyObservers({type: ControllerEventType.TURN, value: 0});
} }
if (Math.abs(value.y) > .1) { if (Math.abs(value.y) > .1) {
this.controllers.controllerObservable.notifyObservers({ controllerObservable.notifyObservers({
type: ControllerEventType.UP_DOWN, type: ControllerEventType.UP_DOWN,
value: value.y * this.speedFactor value: value.y * this.speedFactor
}); });
Base.stickVector.z = 1; AbstractController.stickVector.z = 1;
} else { } else {
this.controllers.controllerObservable.notifyObservers({type: ControllerEventType.UP_DOWN, value: 0}); controllerObservable.notifyObservers({type: ControllerEventType.UP_DOWN, value: 0});
Base.stickVector.z = 0; AbstractController.stickVector.z = 0;
} }
if (Base.stickVector.equals(Vector3.Zero())) { if (AbstractController.stickVector.equals(Vector3.Zero())) {
this.controllers.controllerObservable.notifyObservers({type: ControllerEventType.UP_DOWN, value: 0}); controllerObservable.notifyObservers({type: ControllerEventType.UP_DOWN, value: 0});
} }
} }
} }

View File

@ -1,17 +1,18 @@
import {Angle, Mesh, Quaternion, Scene, Vector3, WebXRDefaultExperience} from "@babylonjs/core"; import {Angle, Mesh, Quaternion, Scene, Vector3, WebXRDefaultExperience} from "@babylonjs/core";
import {Right} from "./right"; import {RightController} from "./rightController";
import {Left} from "./left"; import {LeftController} from "./leftController";
import {ControllerEvent, ControllerEventType, Controllers} from "./controllers";
import log from "loglevel"; import log from "loglevel";
import {DiagramManager} from "../diagram/diagramManager"; import {DiagramManager} from "../diagram/diagramManager";
import {buildRig} from "./functions/buildRig"; import {buildRig} from "./functions/buildRig";
import {DefaultScene} from "../defaultScene"; import {DefaultScene} from "../defaultScene";
import {ControllerEvent} from "./types/controllerEvent";
import {ControllerEventType} from "./types/controllerEventType";
import {controllerObservable} from "./controllers";
const RIGHT = "right"; const RIGHT = "right";
const LEFT = "left"; const LEFT = "left";
export class Rigplatform { export class Rigplatform {
public static instance: Rigplatform; public static instance: Rigplatform;
@ -19,14 +20,14 @@ export class Rigplatform {
public rigMesh: Mesh; public rigMesh: Mesh;
private _logger = log.getLogger('Rigplatform'); private _logger = log.getLogger('Rigplatform');
private readonly _controllers: Controllers;
private readonly _diagramManager: DiagramManager; private readonly _diagramManager: DiagramManager;
private readonly _scene: Scene; private readonly _scene: Scene;
private readonly _velocityArray = [0.01, 0.1, 1, 2, 5]; private readonly _velocityArray = [0.01, 0.1, 1, 2, 5];
private readonly _xr: WebXRDefaultExperience; private readonly _xr: WebXRDefaultExperience;
private _rightController: Right; private _rightController: RightController;
private _leftController: Left; private _leftController: LeftController;
private _turning: boolean = false; private _turning: boolean = false;
private _velocity: Vector3 = Vector3.Zero(); private _velocity: Vector3 = Vector3.Zero();
private _velocityIndex: number = 2; private _velocityIndex: number = 2;
@ -40,7 +41,7 @@ export class Rigplatform {
) { ) {
this._scene = DefaultScene.Scene; this._scene = DefaultScene.Scene;
this._diagramManager = diagramManager; this._diagramManager = diagramManager;
this._controllers = diagramManager.controllers;
this._xr = xr; this._xr = xr;
this.rigMesh = buildRig(xr); this.rigMesh = buildRig(xr);
this._fixRotation(); this._fixRotation();
@ -112,12 +113,12 @@ export class Rigplatform {
private _registerObserver() { private _registerObserver() {
if (this._registered) { if (this._registered) {
this._logger.warn('observer already registered, clearing and re registering'); this._logger.warn('observer already registered, clearing and re registering');
this._controllers.controllerObservable.clear(); controllerObservable.clear();
this._registered = false; this._registered = false;
} }
if (!this._registered) { if (!this._registered) {
this._registered = true; this._registered = true;
this._controllers.controllerObservable.add((event: ControllerEvent) => { controllerObservable.add((event: ControllerEvent) => {
this._logger.debug(event); this._logger.debug(event);
switch (event.type) { switch (event.type) {
case ControllerEventType.INCREASE_VELOCITY: case ControllerEventType.INCREASE_VELOCITY:
@ -165,12 +166,12 @@ export class Rigplatform {
switch (source.inputSource.handedness) { switch (source.inputSource.handedness) {
case RIGHT: case RIGHT:
if (!this._rightController) { if (!this._rightController) {
this._rightController = new Right(source, this._xr, this._diagramManager); this._rightController = new RightController(source, this._xr, this._diagramManager);
} }
break; break;
case LEFT: case LEFT:
if (!this._leftController) { if (!this._leftController) {
this._leftController = new Left(source, this._xr, this._diagramManager); this._leftController = new LeftController(source, this._xr, this._diagramManager);
} }
break; break;
} }

View File

@ -0,0 +1,12 @@
import {Vector3, WebXRInputSource} from "@babylonjs/core";
import {ControllerEventType} from "./controllerEventType";
export type ControllerEvent = {
type: ControllerEventType,
value?: number,
startPosition?: Vector3,
endPosition?: Vector3,
duration?: number,
gripId?: string;
controller?: WebXRInputSource;
}

View File

@ -0,0 +1,24 @@
export enum ControllerEventType {
GRIP = 'grip',
HIDE = 'hide',
SHOW = 'show',
PULSE = 'pulse',
SQUEEZE = 'squeeze',
CLICK = 'click',
Y_BUTTON = 'y-button',
X_BUTTON = 'x-button',
A_BUTTON = 'a-button',
B_BUTTON = 'b-button',
THUMBSTICK = 'thumbstick',
THUMBSTICK_CHANGED = 'thumbstickChanged',
DECREASE_VELOCITY = 'decreaseVelocity',
INCREASE_VELOCITY = 'decreaseVelocity',
LEFT_RIGHT = 'leftright',
FORWARD_BACK = 'forwardback',
TURN = 'turn',
UP_DOWN = 'updown',
TRIGGER = 'trigger',
MENU = 'menu',
MOTION = 'motion',
GAZEPOINT = 'gazepoint',
}

View File

@ -1,6 +1,6 @@
import {AbstractMesh, KeyboardEventTypes, Scene} from "@babylonjs/core"; import {AbstractMesh, KeyboardEventTypes, Scene} from "@babylonjs/core";
import {Rigplatform} from "./rigplatform"; import {Rigplatform} from "./rigplatform";
import {Controllers} from "./controllers";
import {DiagramManager} from "../diagram/diagramManager"; import {DiagramManager} from "../diagram/diagramManager";
import {wheelHandler} from "./functions/wheelHandler"; import {wheelHandler} from "./functions/wheelHandler";
import log, {Logger} from "loglevel"; import log, {Logger} from "loglevel";
@ -12,7 +12,7 @@ export class WebController {
private rig: Rigplatform; private rig: Rigplatform;
private diagramManager: DiagramManager; private diagramManager: DiagramManager;
private mouseDown: boolean = false; private mouseDown: boolean = false;
private readonly controllers: Controllers;
private upDownWheel: boolean = false; private upDownWheel: boolean = false;
private fowardBackWheel: boolean = false; private fowardBackWheel: boolean = false;
private canvas: HTMLCanvasElement; private canvas: HTMLCanvasElement;
@ -20,11 +20,11 @@ export class WebController {
constructor(scene: Scene, constructor(scene: Scene,
rig: Rigplatform, rig: Rigplatform,
diagramManager: DiagramManager, diagramManager: DiagramManager,
controllers: Controllers) { ) {
this.scene = scene; this.scene = scene;
this.rig = rig; this.rig = rig;
this.diagramManager = diagramManager; this.diagramManager = diagramManager;
this.controllers = controllers;
this.canvas = document.querySelector('#gameCanvas'); this.canvas = document.querySelector('#gameCanvas');
//this.referencePlane = MeshBuilder.CreatePlane('referencePlane', {size: 10}, this.scene); //this.referencePlane = MeshBuilder.CreatePlane('referencePlane', {size: 10}, this.scene);
//this.referencePlane.setEnabled(false); //this.referencePlane.setEnabled(false);
@ -160,7 +160,7 @@ export class WebController {
}); });
this.scene.onPointerDown = (evt, state) => { this.scene.onPointerDown = (evt) => {
if (evt.pointerType == "mouse") { if (evt.pointerType == "mouse") {
this.mouseDown = true; this.mouseDown = true;
/*if (evt.shiftKey) { /*if (evt.shiftKey) {

View File

@ -1,7 +1,7 @@
import {AbstractActionManager, AbstractMesh, ActionManager, Observable, Scene} from "@babylonjs/core"; import {AbstractActionManager, AbstractMesh, ActionManager, Observable, Scene} from "@babylonjs/core";
import {DiagramEntity, DiagramEvent, DiagramEventType} from "./types/diagramEntity"; import {DiagramEntity, DiagramEvent, DiagramEventType} from "./types/diagramEntity";
import log from "loglevel"; import log from "loglevel";
import {Controllers} from "../controllers/controllers";
import {AppConfig} from "../util/appConfig"; import {AppConfig} from "../util/appConfig";
import {buildEntityActionManager} from "./functions/buildEntityActionManager"; import {buildEntityActionManager} from "./functions/buildEntityActionManager";
import {DefaultScene} from "../defaultScene"; import {DefaultScene} from "../defaultScene";
@ -11,12 +11,14 @@ import {DiagramObject} from "./diagramObject";
import {getMe} from "../util/me"; import {getMe} from "../util/me";
import {UserModelType} from "../users/userTypes"; import {UserModelType} from "../users/userTypes";
import {vectoxys} from "./functions/vectorConversion"; import {vectoxys} from "./functions/vectorConversion";
import {controllerObservable} from "../controllers/controllers";
import {ControllerEvent} from "../controllers/types/controllerEvent";
export class DiagramManager { export class DiagramManager {
private readonly _logger = log.getLogger('DiagramManager'); private readonly _logger = log.getLogger('DiagramManager');
public readonly _config: AppConfig; public readonly _config: AppConfig;
private readonly _controllers: Controllers; private readonly _controllerObservable: Observable<ControllerEvent>;
private readonly _diagramEntityActionManager: ActionManager; private readonly _diagramEntityActionManager: ActionManager;
public readonly onDiagramEventObservable: Observable<DiagramEvent> = new Observable(); public readonly onDiagramEventObservable: Observable<DiagramEvent> = new Observable();
public readonly onUserEventObservable: Observable<UserModelType> = new Observable(); public readonly onUserEventObservable: Observable<UserModelType> = new Observable();
@ -31,9 +33,9 @@ export class DiagramManager {
this._me = getMe(); this._me = getMe();
this._scene = DefaultScene.Scene; this._scene = DefaultScene.Scene;
this._config = new AppConfig(); this._config = new AppConfig();
this._controllers = new Controllers();
this._diagramMenuManager = new DiagramMenuManager(this.onDiagramEventObservable, this._controllers, this._config, readyObservable); this._diagramMenuManager = new DiagramMenuManager(this.onDiagramEventObservable, controllerObservable, this._config, readyObservable);
this._diagramEntityActionManager = buildEntityActionManager(this._controllers); this._diagramEntityActionManager = buildEntityActionManager(controllerObservable);
this.onDiagramEventObservable.add(this.onDiagramEvent, DiagramEventObserverMask.FROM_DB, true, this); this.onDiagramEventObservable.add(this.onDiagramEvent, DiagramEventObserverMask.FROM_DB, true, this);
@ -116,11 +118,6 @@ export class DiagramManager {
return this._diagramObjects.has(mesh?.id) return this._diagramObjects.has(mesh?.id)
} }
public get controllers(): Controllers {
return this._controllers;
}
public createCopy(id: string): DiagramObject { public createCopy(id: string): DiagramObject {
const diagramObject = this._diagramObjects.get(id); const diagramObject = this._diagramObjects.get(id);
if (!diagramObject) { if (!diagramObject) {

View File

@ -2,7 +2,6 @@ import {DiagramEvent, DiagramEventType} from "./types/diagramEntity";
import {AbstractMesh, ActionEvent, Observable, Scene, Vector3, WebXRInputSource} from "@babylonjs/core"; import {AbstractMesh, ActionEvent, Observable, Scene, Vector3, WebXRInputSource} from "@babylonjs/core";
import {InputTextView} from "../information/inputTextView"; import {InputTextView} from "../information/inputTextView";
import {DefaultScene} from "../defaultScene"; import {DefaultScene} from "../defaultScene";
import {ControllerEvent, ControllerEventType, Controllers} from "../controllers/controllers";
import log from "loglevel"; import log from "loglevel";
import {Toolbox} from "../toolbox/toolbox"; import {Toolbox} from "../toolbox/toolbox";
import {ClickMenu} from "../menus/clickMenu"; import {ClickMenu} from "../menus/clickMenu";
@ -13,6 +12,8 @@ import {ConnectionPreview} from "../menus/connectionPreview";
import {ScaleMenu2} from "../menus/ScaleMenu2"; import {ScaleMenu2} from "../menus/ScaleMenu2";
import {viewOnly} from "../util/functions/getPath"; import {viewOnly} from "../util/functions/getPath";
import {GroupMenu} from "../menus/groupMenu"; import {GroupMenu} from "../menus/groupMenu";
import {ControllerEvent} from "../controllers/types/controllerEvent";
import {ControllerEventType} from "../controllers/types/controllerEventType";
export class DiagramMenuManager { export class DiagramMenuManager {
@ -26,10 +27,10 @@ export class DiagramMenuManager {
private _logger = log.getLogger('DiagramMenuManager'); private _logger = log.getLogger('DiagramMenuManager');
private _connectionPreview: ConnectionPreview; private _connectionPreview: ConnectionPreview;
constructor(notifier: Observable<DiagramEvent>, controllers: Controllers, config: AppConfig, readyObservable: Observable<boolean>) { constructor(notifier: Observable<DiagramEvent>, controllerObservable: Observable<ControllerEvent>, config: AppConfig, readyObservable: Observable<boolean>) {
this._scene = DefaultScene.Scene; this._scene = DefaultScene.Scene;
this._notifier = notifier; this._notifier = notifier;
this._inputTextView = new InputTextView(controllers); this._inputTextView = new InputTextView(controllerObservable);
this.configMenu = new ConfigMenu(config); this.configMenu = new ConfigMenu(config);
this._inputTextView.onTextObservable.add((evt) => { this._inputTextView.onTextObservable.add((evt) => {
@ -43,7 +44,7 @@ export class DiagramMenuManager {
//this.scaleMenu.handleMesh.setEnabled(false) //this.scaleMenu.handleMesh.setEnabled(false)
this.configMenu.handleTransformNode.setEnabled(false); this.configMenu.handleTransformNode.setEnabled(false);
} }
controllers.controllerObservable.add((event: ControllerEvent) => { controllerObservable.add((event: ControllerEvent) => {
if (event.type == ControllerEventType.B_BUTTON) { if (event.type == ControllerEventType.B_BUTTON) {
if (event.value > .8) { if (event.value > .8) {
const platform = this._scene.getMeshByName("platform"); const platform = this._scene.getMeshByName("platform");

View File

@ -1,47 +0,0 @@
import {afterEach, describe, expect, it, vi} from 'vitest'
import {applyScaling} from './applyScaling'
import {Vector3} from "@babylonjs/core";
describe('applyScaling', () => {
afterEach(() => {
vi.restoreAllMocks();
})
it('should copy scaling', () => {
const oldMesh = {
scaling: {
clone: () => 'cloned'
}
}
const newMesh = {
scaling: null
}
applyScaling(oldMesh as any, newMesh as any, true, 0)
expect(newMesh.scaling).toBe('cloned')
})
it('scaling to be set to 1,1,1 if snap passed as null', () => {
const spy = vi.spyOn(Vector3, 'One');
//expect(spy).toHaveBeenCalledTimes(1);
const oldMesh = {
scaling: {}
}
const newMesh = {
scaling: null
}
applyScaling(oldMesh as any, newMesh as any, false, null)
expect(newMesh.scaling.x).toBe(1);
expect(newMesh.scaling.y).toBe(1);
expect(newMesh.scaling.z).toBe(1);
})
it('scaling to be set to 2,2,2 snap passed as Vector3(2,2,2)', () => {
const oldMesh = {
scaling: {}
}
const newMesh = {
scaling: new Vector3()
}
applyScaling(oldMesh as any, newMesh as any, false, 2)
expect(newMesh.scaling.x).toBe(2);
expect(newMesh.scaling.y).toBe(2);
expect(newMesh.scaling.z).toBe(2);
})
});

View File

@ -1,16 +0,0 @@
import {AbstractMesh, Vector3} from "@babylonjs/core";
export function applyScaling(oldMesh: AbstractMesh,
newMesh: AbstractMesh,
copy: boolean,
snap: number) {
if (copy) {
newMesh.scaling = oldMesh.scaling.clone();
} else {
if (snap) {
newMesh.scaling.set(snap, snap, snap);
} else {
newMesh.scaling = Vector3.One();
}
}
}

View File

@ -1,9 +1,17 @@
import {ActionManager, ExecuteCodeAction, HighlightLayer, InstancedMesh, StandardMaterial,} from "@babylonjs/core"; import {
import {ControllerEventType, Controllers} from "../../controllers/controllers"; ActionManager,
ExecuteCodeAction,
HighlightLayer,
InstancedMesh,
Observable,
StandardMaterial,
} from "@babylonjs/core";
import log from "loglevel"; import log from "loglevel";
import {DefaultScene} from "../../defaultScene"; import {DefaultScene} from "../../defaultScene";
import {ControllerEventType} from "../../controllers/types/controllerEventType";
import {ControllerEvent} from "../../controllers/types/controllerEvent";
export function buildEntityActionManager(controllers: Controllers) { export function buildEntityActionManager(controllerObservable: Observable<ControllerEvent>) {
const highlightLayer = new HighlightLayer('highlightLayer', DefaultScene.Scene); const highlightLayer = new HighlightLayer('highlightLayer', DefaultScene.Scene);
highlightLayer.innerGlow = false; highlightLayer.innerGlow = false;
highlightLayer.outerGlow = true; highlightLayer.outerGlow = true;
@ -37,10 +45,10 @@ export function buildEntityActionManager(controllers: Controllers) {
logger.error(e); logger.error(e);
} }
} }
controllers.controllerObservable.notifyObservers({ controllerObservable.notifyObservers({
type: ControllerEventType.PULSE, type: ControllerEventType.PULSE,
gripId: evt?.additionalData?.pickResult?.gripTransform?.id gripId: evt?.additionalData?.pickResult?.gripTransform?.id
}) });
logger.debug(evt); logger.debug(evt);
}) })
); );

View File

@ -1,73 +0,0 @@
import {afterEach, describe, expect, it, vi} from 'vitest'
import {buildMeshFromDiagramEntity} from './buildMeshFromDiagramEntity'
import {DiagramEntityType} from "../types/diagramEntity";
import {Vector3} from "@babylonjs/core";
describe('buildMeshFromDiagramEntity', () => {
afterEach(() => {
vi.restoreAllMocks();
})
it('should return null if entity is null', () => {
const scene = {
getMeshById: () => null
}
const entity = buildMeshFromDiagramEntity(null, scene as any);
expect(entity).toBe(null);
});
it('should return existing mesh if id exists in scene', () => {
const material = 'material';
const scene = {
getMeshById: (id) => {
return {
id: id,
material: material
}
}
}
const dEntity = {
type: DiagramEntityType.USER,
}
const entity = buildMeshFromDiagramEntity(dEntity, scene as any);
expect(entity.material).toBe(material);
});
it('should generate new mesh if id is missing', () => {
vi.mock('../diagramConnection', () => {
const DiagramConnection = vi.fn();
DiagramConnection.prototype.mesh =
{
id: 'id',
material: 'material',
getChildren: vi.fn(),
getScene: vi.fn()
}
return {DiagramConnection}
});
const scene = {
getMeshById: () => {
return null;
},
}
const dEntity = {
type: DiagramEntityType.USER,
template: "#connection-template",
color: "$FF00FF",
position: {x: 1, y: 2, z: 3},
rotation: {x: 4, y: 5, z: 6},
scale: {x: 7, y: 8, z: 9},
text: 'new text'
}
const entity = buildMeshFromDiagramEntity(dEntity, scene as any);
expect(entity.id).toBe('id');
expect(entity.material).toBe('material');
expect(entity.position).toEqual(new Vector3(1, 2, 3));
expect(entity.rotation).toEqual(new Vector3(4, 5, 6));
expect(entity.scaling).toEqual(new Vector3(7, 8, 9));
expect(entity.metadata.text).toEqual('new text');
});
});

View File

@ -1,54 +0,0 @@
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;
private scene: Scene;
private logger: Logger = log.getLogger("PresentationManager");
constructor(scene: Scene) {
this.scene = scene;
}
_steps: PresentationStep[] = [];
public get steps(): PresentationStep[] {
return this._steps;
}
public addStep(): PresentationStep {
const step = new PresentationStep();
this._currentStep = step;
if (this._steps.length > 0) {
this._steps[this._steps.length - 1].next = step;
} else {
this.scene.getActiveMeshes().forEach((mesh) => {
if (isDiagramEntity(mesh)) {
step.entities.push({
entity: mesh,
endPosition: mesh.position.clone(),
endRotation: mesh.rotation.clone(),
endScaling: mesh.scaling.clone()
})
step.duration = 1;
}
});
}
this._steps.push(step);
return step;
}
public play() {
this._currentStep.play();
if (this._currentStep.next) {
this._currentStep = this._currentStep.next;
}
}
public reset() {
this._currentStep = this._steps[0];
this._steps[0].play();
}
}

View File

@ -1,45 +0,0 @@
import {AbstractMesh, Animation, Vector3} from "@babylonjs/core";
export type EntityTransform = {
entity: AbstractMesh,
endPosition?: Vector3,
endRotation?: Vector3,
endScaling?: Vector3
}
export class PresentationStep {
public id: string;
public name: string;
public duration: number = 2;
public entities: Array<EntityTransform> = [];
public next: PresentationStep;
private readonly fps: number = 30;
private get endFrame(): number {
return this.fps * this.duration;
}
public play() {
this.entities.forEach((entityTransform) => {
if (entityTransform.endPosition) {
const transform = new Animation("transform", "position",
this.fps, Animation.ANIMATIONTYPE_VECTOR3, Animation.ANIMATIONLOOPMODE_CONSTANT);
const keyframes = [
{frame: 0, value: entityTransform.entity.position},
{frame: this.endFrame, value: entityTransform.endPosition}
]
transform.setKeys(keyframes);
entityTransform.entity.animations.push(transform);
entityTransform.entity.getScene().beginAnimation(entityTransform.entity, 0, this.endFrame, false);
}
if (entityTransform.endRotation) {
//entityTransform.entity.rotation = entityTransform.endRotation;
}
if (entityTransform.endScaling) {
//entityTransform.entity.scaling = entityTransform.endScaling;
}
});
}
}

View File

@ -1,9 +1,10 @@
import {AbstractMesh, MeshBuilder, Observable, Scene, TransformNode, Vector3} from "@babylonjs/core"; import {AbstractMesh, MeshBuilder, Observable, Scene, TransformNode, Vector3} from "@babylonjs/core";
import log, {Logger} from "loglevel"; import log, {Logger} from "loglevel";
import {AdvancedDynamicTexture, Control, InputText, VirtualKeyboard} from "@babylonjs/gui"; import {AdvancedDynamicTexture, Control, InputText, VirtualKeyboard} from "@babylonjs/gui";
import {ControllerEventType, Controllers} from "../controllers/controllers";
import {Handle} from "../objects/handle"; import {Handle} from "../objects/handle";
import {DefaultScene} from "../defaultScene"; import {DefaultScene} from "../defaultScene";
import {ControllerEvent} from "../controllers/types/controllerEvent";
import {ControllerEventType} from "../controllers/types/controllerEventType";
export type TextEvent = { export type TextEvent = {
id: string; id: string;
@ -16,15 +17,15 @@ export class InputTextView {
private readonly scene: Scene; private readonly scene: Scene;
private readonly inputMesh: AbstractMesh; private readonly inputMesh: AbstractMesh;
private readonly controllers: Controllers; private readonly controllerObservable: Observable<ControllerEvent>;
private readonly handle: Handle; private readonly handle: Handle;
private inputText: InputText; private inputText: InputText;
private diagramMesh: AbstractMesh; private diagramMesh: AbstractMesh;
private keyboard: VirtualKeyboard; private keyboard: VirtualKeyboard;
constructor(controllers: Controllers) { constructor(controllerObservable: Observable<ControllerEvent>) {
this.controllers = controllers; this.controllerObservable = controllerObservable;
this.scene = DefaultScene.Scene; this.scene = DefaultScene.Scene;
this.inputMesh = MeshBuilder.CreatePlane("input", {width: 1, height: .5}, this.scene); this.inputMesh = MeshBuilder.CreatePlane("input", {width: 1, height: .5}, this.scene);
this.handle = new Handle(this.inputMesh, 'Input'); this.handle = new Handle(this.inputMesh, 'Input');
@ -113,7 +114,7 @@ export class InputTextView {
this.logger.debug(eventData); this.logger.debug(eventData);
const gripId = eventState?.userInfo?.pickInfo?.gripTransform?.id; const gripId = eventState?.userInfo?.pickInfo?.gripTransform?.id;
if (gripId) { if (gripId) {
this.controllers.controllerObservable.notifyObservers({ this.controllerObservable.notifyObservers({
type: ControllerEventType.PULSE, type: ControllerEventType.PULSE,
gripId: gripId gripId: gripId
}); });

View File

@ -45,7 +45,7 @@ export class PouchdbPersistenceManager {
} }
this._logger.debug(evt); this._logger.debug(evt);
}); });
document.addEventListener('dbcreated', (evt) => { document.addEventListener('dbcreated', (evt: CustomEvent) => {
const detail = ((evt.detail as unknown) as PasswordEvent2); const detail = ((evt.detail as unknown) as PasswordEvent2);
const password = detail.password; const password = detail.password;
const id = detail.id; const id = detail.id;

View File

@ -1,305 +0,0 @@
import log from "loglevel";
import {Color3, Scene, Vector3} from "@babylonjs/core";
import {DiagramManager} from "../diagram/diagramManager";
import {DiagramEventType} from "../diagram/types/diagramEntity";
type DrawIOEntity = {
text?: string,
id?: string,
parent?: string,
parentEntity?: DrawIOEntity,
geometry?: DrawIOGeometry,
}
type DrawIOGeometry = {
zIndex?: number,
x: number,
y: number,
width: number,
height: number
}
class EntityTree {
private readonly logger = log.getLogger('EntityTree');
private root: DrawIOEntity;
private readonly nodes: Map<string, DrawIOEntity> = new Map<string, DrawIOEntity>();
private readonly unparented: Array<DrawIOEntity> = new Array<DrawIOEntity>();
constructor() {
this.root = {};
}
public getNodes(): Array<DrawIOEntity> {
this.reparent();
const output: Array<DrawIOEntity> = new Array<DrawIOEntity>();
this.nodes.forEach((node) => {
if (node.parentEntity) {
node.geometry = this.computeOffset(node);
}
output.push(node);
});
return output;
}
public reparent() {
this.unparented.forEach((node) => {
if (this.nodes.has(node.parent)) {
this.logger.debug('reparenting node: ' + node.id + ' to parent: ' + node.parent);
node.parentEntity = this.nodes.get(node.parent);
} else {
this.logger.warn('parent node does not exist for id: ' + node.id +
' parent id: ' + node.parent);
}
});
}
public addNode(node: DrawIOEntity) {
if (this.nodes.has(node.id)) {
this.logger.warn('node already exists for id: ' + node.id);
} else {
if (node.parent) {
if (this.nodes.has(node.parent)) {
node.parentEntity = this.nodes.get(node.parent);
this.nodes.set(node.id, node);
} else {
this.logger.warn('parent node does not exist for id: ' + node.id +
' parent id: ' + node.parent);
this.unparented.push(node);
}
} else {
this.logger.warn('no parent for node id: ' + node.id + 'setting as root');
this.nodes.set(node.id, node);
this.root = node;
}
}
}
private computeOffset(node: DrawIOEntity): DrawIOGeometry {
if (node.parentEntity) {
const parentgeo = this.computeOffset(node.parentEntity);
if (parentgeo) {
const parentzIndex = 1 + parentgeo.zIndex ? parentgeo.zIndex : 0;
return {
x: node.geometry.x,
y: node.geometry.y,
width: node.geometry.width,
height: node.geometry.height,
zIndex: node.geometry.zIndex ? node.geometry.zIndex + parentzIndex : parentzIndex + 1
};
} else {
return {
x: node.geometry.x,
y: node.geometry.y,
width: node.geometry.width,
height: node.geometry.height,
zIndex: node.geometry.zIndex ? node.geometry.zIndex : 0
};
}
} else {
if (node.geometry) {
if (node.geometry.zIndex === undefined) {
node.geometry.zIndex = 0;
}
return node.geometry;
} else {
return {
x: 0,
y: 0,
width: 0,
height: 0,
zIndex: 0
}
}
}
}
}
type DrawIOConnector = {
id: string,
source: string,
target: string,
text: string
}
export class DrawioManager {
private diagramManager: DiagramManager;
private connectors: Array<DrawIOConnector> = [];
private readonly scene: Scene;
private readonly logger = log.getLogger('DrawioManager');
private minY = 0;
private minX = 0;
private maxX = 0;
private maxY = 0;
private maxZ = 0;
constructor(scene: Scene, diagramManager: DiagramManager) {
this.scene = scene;
this.diagramManager = diagramManager;
this.buildGraph();
}
private async fetchData(url: string): Promise<Document> {
this.logger.debug("starting to get graph");
const graph = await fetch(url);
this.logger.debug('got graph');
const graphXml = await graph.text();
return new DOMParser().parseFromString(graphXml, 'text/html');
}
private getDiagram(doc: Document, index: number): Element {
const firstDiagram = doc.querySelectorAll('diagram')[index];
return firstDiagram.querySelector('mxGraphModel');
}
private parseDiagram(mxDiagram: Element): EntityTree {
const entityTree = new EntityTree();
mxDiagram.querySelectorAll('mxCell').forEach((cell) => {
const value = cell.getAttribute('value');
let ent = null;
if (value) {
ent = new DOMParser().parseFromString(value, 'text/html');
const errorNode = ent.querySelector("parsererror");
if (errorNode) {
this.logger.error(value);
}
}
const text = ent ? this.getText(ent, '') : '';
const id = cell.getAttribute('id');
const parent = cell.getAttribute('parent');
const source = cell.getAttribute('source');
const target = cell.getAttribute('target');
const edge = cell.getAttribute('target');
if (source && target && edge) {
this.connectors.push({id: id, source: source, target: target, text: text});
} else {
const geo = cell.querySelector('[id="' + id + '"] > mxGeometry');
let geometry;
if (geo) {
geometry = {
x: Number.parseFloat(geo.getAttribute('x')),
y: Number.parseFloat(geo.getAttribute('y')),
width: Number.parseFloat(geo.getAttribute('width')),
height: Number.parseFloat(geo.getAttribute('height')),
}
} else {
geometry = {
x: 0,
y: 0,
width: 0,
height: 0
}
}
//entities.push({text: text, id: id, parent: parent, geometry: this.fixMinMax(geometry)});
if (text) {
this.logger.debug('Text' + text);
this.logger.debug('Geometry' + JSON.stringify(geometry));
}
if (geometry) {
if (Number.isNaN(geometry.x) || Number.isNaN(geometry.y)
|| Number.isNaN(geometry.width) ||
Number.isNaN(geometry.height)) {
this.logger.warn('invalid geometry for node: ' + id, geometry);
} else {
entityTree.addNode({text: text, id: id, parent: parent, geometry: geometry});
}
}
}
});
return entityTree
}
private async buildGraph() {
const doc = await this.fetchData('/arch_demo.xml');
const mxDiagram = this.getDiagram(doc, 0);
this.logger.debug('begin parse');
const entities: EntityTree = this.parseDiagram(mxDiagram);
entities.getNodes().forEach((node) => {
if (node.geometry.x < this.minX) {
this.minX = node.geometry.x;
this.logger.debug('minX: ' + this.minX);
}
if (node.geometry.y < this.minY) {
this.minY = node.geometry.y;
this.logger.debug('minY: ' + this.minY);
}
if (node.geometry.x + node.geometry.width > this.maxX) {
this.maxX = node.geometry.x + node.geometry.width;
this.logger.debug('maxX: ' + this.maxX);
}
if (node.geometry.y + node.geometry.height > this.maxY) {
this.maxY = node.geometry.y + node.geometry.height;
this.logger.debug('maxY: ' + this.maxY);
}
if (node.geometry.zIndex > this.maxZ) {
this.maxZ = node.geometry.zIndex;
this.logger.debug('maxZ: ' + this.maxZ);
}
});
this.logger.info('minX: ' + this.minX + ' minY: ' + this.minY + ' maxX: ' + this.maxX + ' maxY: ' + this.maxY);
this.logger.debug('done parsing');
this.logger.debug(this.connectors);
this.createSceneData(entities.getNodes());
}
private createSceneData(nodes) {
const yOffset = 20;
const scale = .001;
nodes.forEach((entity) => {
this.diagramManager.onDiagramEventObservable.notifyObservers(
{
type: DiagramEventType.ADD,
entity: {
text: entity.text,
id: entity.id,
position: new Vector3(
(entity.geometry.x * scale) - (entity.geometry.width * scale / 2),
yOffset - (entity.geometry.y * scale) + (entity.geometry.height * scale / 2),
entity.geometry.zIndex * .1),
scale: new Vector3(entity.geometry.width * scale, entity.geometry.height * scale, .05),
color: Color3.Blue().toHexString(),
template: '#box-template'
}
}
);
});
}
private getText(obj: Node, text: string): string {
if (obj.nodeType == Node.TEXT_NODE) {
if (obj.textContent) {
return obj.textContent.trim();
} else {
return '';
}
} else {
if (obj.childNodes) {
let t = '';
obj.childNodes.forEach((child) => {
t += ' ' + this.getText(child, '');
});
return text.trim() + ' ' + t.trim();
} else {
return '';
}
}
}
}

View File

@ -1,48 +0,0 @@
import {Observable} from "@babylonjs/core";
export class NativeVoiceRecognition {
public readonly onTextObservable: Observable<string> = new Observable<string>();
private recognition: SpeechRecognition;
constructor() {
this.onTextObservable = new Observable<string>();
this.setup();
}
public stop() {
this.recognition.stop();
}
private setup() {
//const SpeechRecognition2 = SpeechRecognition || webkitSpeechRecognition
// const SpeechGrammarList = SpeechGrammarList || window.webkitSpeechGrammarList
//const SpeechRecognitionEvent = SpeechRecognitionEvent || webkitSpeechRecognitionEvent
try {
this.recognition = new webkitSpeechRecognition();
} catch (e) {
this.recognition = new SpeechRecognition();
}
this.recognition.continuous = false;
this.recognition.lang = 'en-US';
this.recognition.interimResults = true;
this.recognition.maxAlternatives = 1;
this.recognition.onresult = (event) => {
this.onTextObservable.notifyObservers(event.results[0][0].transcript);
}
this.recognition.onend = () => {
}
this.recognition.onstart = () => {
}
this.recognition.start();
}
}

View File

@ -1,128 +0,0 @@
import {Color3, Material, Mesh, MeshBuilder, Scene, StandardMaterial, TransformNode, Vector3} from "@babylonjs/core";
import axios from "axios";
import {AdvancedDynamicTexture, TextBlock} from "@babylonjs/gui";
export class NewRelicQuery {
private readonly scene: Scene;
private data: { name: string, point: Vector3 }[] = [];
private baseTransform: TransformNode;
private seriesNumber = 0;
private maxY = 0;
private minY = 0;
private maxZ = 0;
private minZ = 0;
constructor(scene: Scene) {
this.scene = scene;
this.baseTransform = new TransformNode("graphBase", this.scene);
}
public async getSales() {
const data = await axios.get('/data.json')
const series = data.data[0].series[0].series;
for (const s of series) {
this.buildSeries(s);
}
this.buildModel();
}
//private materials: Material[];
private buildSeries(series) {
const name = series.name;
const material = new StandardMaterial(name + 'Material', this.scene);
material.diffuseColor = new Color3(Math.random(), Math.random(), Math.random());
//material.ambientColor = new Color3(0, 0, 0);
material.specularColor = new Color3(1, 1, 1);
material.alpha = .9;
//this.materials.push(material);
const data = series.data;
for (const point in data) {
this.buildPoint(name, data[point]);
}
this.buildTextLabel(name, new Vector3(this.seriesNumber, .25, -.25));
this.seriesNumber++;
}
private buildTextLabel(text: string, position: Vector3) {
const plane = MeshBuilder.CreatePlane("plane", {width: .5, height: .25}, this.scene);
plane.billboardMode = Mesh.BILLBOARDMODE_ALL;
const advancedTexture = AdvancedDynamicTexture.CreateForMesh(plane, 1024, 512, false);
const text1 = new TextBlock();
text1.text = text;
advancedTexture.background = "#000000";
text1.color = "white";
text1.fontSize = 128;
advancedTexture.addControl(text1);
plane.position.set(position.x, position.y, position.z);
}
private buildNumericLabel(number: number, position: Vector3) {
const rounded = Math.round(number);
let shortNumber: string = '???';
if (Math.log10(rounded) < 3) {
shortNumber = rounded.toString();
}
if (Math.log10(rounded) >= 3 && Math.log10(rounded) < 6) {
shortNumber = (Math.round(rounded / 100) / 10).toString() + 'K';
}
if (Math.log10(rounded) >= 6) {
shortNumber = (Math.round(rounded / 100000) / 10).toString() + 'M';
}
this.buildTextLabel(shortNumber, position);
}
private buildModel() {
const zScale = 20 / (this.maxZ - this.minZ);
const yScale = 20 / (this.maxY - this.minY);
for (const point of this.data) {
const z = (point.point.z - this.minZ) * zScale;
const y = (point.point.y - this.minY) * yScale;
//const baseMesh = (this.scene.getMeshByName(point.name+ 'Mesh') as Mesh);
const bar = MeshBuilder.CreateBox(name + 'Mesh', {width: 1, height: 1, depth: 1}, this.scene);
bar.material = this.scene.getMaterialByName(point.name + 'Material');
//const bar = new InstancedMesh(point.name + point.point.z, baseMesh);
bar.scaling.x = .5;
bar.scaling.y = y;
bar.scaling.z = .5;
/*MeshBuilder.CreateBox(point.name + point.point.z, {width: .5,
height: y, depth: .5}, this.scene);
*/
bar.position.set(point.point.x, y / 2, z);
this.buildNumericLabel(point.point.y, new Vector3(point.point.x, y, z));
const base = MeshBuilder.CreatePlane('base', {width: 20, height: 20}, this.scene);
const material = new StandardMaterial("baseMaterial", this.scene);
material.diffuseColor = new Color3(0, 1, 0);
base.material = material;
base.position.set(10, .001, 10);
base.parent = this.baseTransform;
base.rotation.x = Math.PI / 2;
bar.parent = this.baseTransform;
// bar.material = this.scene.getMaterialByName(point.name+'Material');
}
}
private buildPoint(name, point) {
if (point[1] > this.maxY) {
this.maxY = point[1];
}
if (this.minY === 0 || point[1] < this.minY) {
this.minY = point[1];
}
if (point[0] > this.maxZ) {
this.maxZ = point[0];
}
if (this.minZ === 0 || point[0] < this.minZ) {
this.minZ = point[0];
}
this.data.push({name: name, point: new Vector3(this.seriesNumber, point[1], point[0])});
}
}

View File

@ -1,145 +0,0 @@
import RecordRTC from 'recordrtc';
import log from "loglevel";
import {Observable} from "@babylonjs/core";
import {TranscriptType, VoiceTranscript} from "./voiceTranscript";
type VoiceManagerEvent = {
audio_start?: number;
audio_end?: number;
confidence?: number;
text?: string;
words?: Array<any>;
created?: string;
message_type?: string
}
export class VoiceManager {
private socket: WebSocket;
private token: string;
public readonly transcriptionObserver: Observable<VoiceTranscript> = new Observable<VoiceTranscript>();
private recorder: RecordRTC;
private data: any[] = [];
private logger = log.getLogger('VoiceManager');
constructor() {
this.setupRecorder();
}
public startRecording() {
this.connectToVoice();
}
public stopRecording() {
this.recorder.reset();
this.socket.send('{"terminate_session": true}');
this.socket = null;
}
public async connectToVoice() {
const response = await fetch('/.netlify/functions/voice');
const data = await response.json();
this.token = data.token;
if (!this.socket) {
this.socket = new WebSocket(`wss://api.assemblyai.com/v2/realtime/ws?sample_rate=16000&token=${this.token}`);
this.socket.onmessage = this.messageRecieved;
this.socket.onopen = this.socketOpen;
this.socket.onclose = this.socketClose;
} else {
switch (this.socket.readyState) {
case 0:
this.logger.debug('socket opening');
break;
case 1:
this.logger.debug('socket already open');
//await this.recorder.startRecording();
break;
case 2:
this.logger.debug('socket is closing');
this.socket = null;
//await this.setupConnection();
break;
case 3:
this.logger.debug('Socket is closed');
this.socket = null;
//await this.setupConnection();
break
default:
this.logger.debug(`socket state is unknown: ${this.socket.readyState}`);
}
}
}
private async setupRecorder() {
if (!this.recorder) {
const stream = await navigator.mediaDevices.getUserMedia({audio: true});
this.recorder = new RecordRTC(stream, {
type: 'audio', mimeType: 'audio/webm;codecs=pcm', // endpoint requires 16bit PCM audio
recorderType: RecordRTC.StereoAudioRecorder, timeSlice: 300, // set 250 ms intervals of data that sends to AAI
desiredSampRate: 16000, numberOfAudioChannels: 1, // real-time requires only one channel
bufferSize: 4096, audioBitsPerSecond: 128000, ondataavailable: (blob) => {
const reader = new FileReader();
reader.onload = () => {
const base64data: string = (reader.result as string);
// audio data must be sent as a base64 encoded string
if (this.socket && (this.socket.readyState === 1)) {
this.socket.send(JSON.stringify({audio_data: base64data.split('base64,')[1]}));
} else {
this.logger.warn('no socket available');
}
};
reader.readAsDataURL(blob);
},
});
}
}
private messageRecieved = (message: any) => {
const res = (JSON.parse(message.data) as VoiceManagerEvent);
if (this.data) {
//this.logger.debug(`Received data: ${JSON.stringify(res)}`);
switch (res.message_type) {
case 'PartialTranscript':
if (res.words.length > 0) {
this.logger.debug(`PartialTranscript: ${res.text}`);
this.transcriptionObserver.notifyObservers(
{
text: res.text, words: res.words, confidence: res.confidence,
type: TranscriptType.PartialTranscript
});
}
break;
case 'FinalTranscript':
if (res.words.length > 0) {
this.transcriptionObserver.notifyObservers(
{
text: res.text, words: res.words, confidence: res.confidence,
type: TranscriptType.FinalTranscript
});
}
break;
case 'SessionBegins':
this.logger.debug(`SessionBegins: ${res}`);
break;
}
}
}
private socketClose = async () => {
this.logger.debug('Socket closed');
this.socket = null;
this.recorder.reset();
}
private socketOpen = async () => {
this.logger.debug('voice socket opened');
if (!this.recorder) {
this.logger.error('recorder not initialized');
} else {
this.recorder.startRecording();
}
}
}

View File

@ -1,11 +0,0 @@
export type VoiceTranscript = {
words: VoiceTranscript[];
text: string;
type: TranscriptType;
confidence: number;
}
export enum TranscriptType {
PartialTranscript = 'PartialTranscript',
FinalTranscript = 'FinalTranscript'
}

View File

@ -1,5 +1,4 @@
import {Scene, WebXRDefaultExperience} from "@babylonjs/core"; import {Scene, WebXRDefaultExperience} from "@babylonjs/core";
import {Controllers} from "../controllers/controllers";
import {Handle} from "../objects/handle"; import {Handle} from "../objects/handle";
import {DefaultScene} from "../defaultScene"; import {DefaultScene} from "../defaultScene";
@ -7,12 +6,11 @@ export abstract class AbstractMenu {
protected handle: Handle; protected handle: Handle;
protected scene: Scene; protected scene: Scene;
protected xr: WebXRDefaultExperience; protected xr: WebXRDefaultExperience;
protected controllers: Controllers;
protected constructor(xr: WebXRDefaultExperience, controllers: Controllers) {
protected constructor(xr: WebXRDefaultExperience) {
this.scene = DefaultScene.Scene; this.scene = DefaultScene.Scene;
this.xr = xr; this.xr = xr;
this.controllers = controllers;
} }
public toggle() { public toggle() {

View File

@ -1,37 +0,0 @@
import {AbstractMesh, Angle, Color3, MeshBuilder, Scene, StandardMaterial, Vector3} from "@babylonjs/core";
import log, {Logger} from "loglevel";
import {MaptilerMap} from "../maps/maptilerMap";
export class CameraMenu {
private readonly _scene: Scene;
private readonly _logger: Logger = log.getLogger('CameraMenu');
constructor(scene: Scene) {
this._scene = scene;
this.buildMap();
}
private buildMap() {
const maptilerMap = new MaptilerMap('YnvhjBiU8oCWP0GXNdHL', this._scene, 'map-node', 3);
maptilerMap.node.position.y = 3;
maptilerMap.node.position.z = -4;
maptilerMap.node.rotation.y = Math.PI;
maptilerMap.node.rotation.x = Angle.FromDegrees(10).radians()
maptilerMap.node.scaling = new Vector3(1, 1, 1);
maptilerMap.setLocation('loves park, il', 16).then(() => {
//maptilerMap.plotPoint(42.33181896128866, -88.86844896012006, this.buildPoint());
});
maptilerMap.onPickObservable.add((evt) => {
maptilerMap.plotPoint(evt.lat, evt.lon, this.buildPoint());
});
}
private buildPoint(): AbstractMesh {
const mesh = MeshBuilder.CreateIcoSphere('point', {radius: .02}, this._scene);
const material: StandardMaterial = new StandardMaterial('pointMat', this._scene);
material.diffuseColor = Color3.Red();
mesh.material = material;
mesh.isPickable = true;
return mesh;
}
}

View File

@ -1,20 +0,0 @@
import {AbstractMenu} from "./abstractMenu";
import {WebXRDefaultExperience} from "@babylonjs/core";
import {Controllers} from "../controllers/controllers";
import {makeButton} from "./functions/makeButton";
//a class called SequenceMenu that extends AbstraceMenu and has three buttons labeled '1', '2', and '3'
export class SequenceMenu extends AbstractMenu {
constructor(xr: WebXRDefaultExperience, controllers: Controllers) {
super(xr, controllers);
this.buildMenu();
}
private buildMenu() {
const button1 = makeButton("1", "1");
const button2 = makeButton("2", "1");
const button3 = makeButton("3", "1");
}
}

View File

@ -1,198 +0,0 @@
import {
AbstractMesh,
Color3,
DynamicTexture,
InstancedMesh,
MeshBuilder,
Scene,
StandardMaterial,
Vector3
} from "@babylonjs/core";
import {PouchdbPersistenceManager} from "../integration/database/pouchdbPersistenceManager";
export class NewRelicData {
private key: string;
private account: string;
private data: any[];
private readonly scene: Scene;
private persistenceManager: PouchdbPersistenceManager;
private policyLabels: AbstractMesh[] = [];
constructor(persistenceManager: PouchdbPersistenceManager, scene: Scene) {
this.persistenceManager = persistenceManager;
this.scene = scene;
this.persistenceManager.getNewRelicData()
.then((data) => {
this.data = data;
this.getNewRelicData().then(() => {
this.drawGraph();
});
});
}
public setCredentials(key: string, account: string) {
this.key = key;
this.account = account;
}
public async clearData() {
this.data = [];
await this.persistenceManager.setNewRelicData(this.data);
}
public async getNewRelicData() {
if (this.data && this.data.length > 0) {
console.warn("Already have data, early return");
return;
}
try {
const res = await fetch('https://deepdiagram.com/.netlify/functions/nerdgraph', {
method: 'POST',
credentials: 'include',
body: '{"query": "{actor { nrql(query: \\"select * from NrAiIncident \\", accounts: ' + this.account + ') { results } } }"}',
headers: {"Api-Key": this.key}
});
const data = await res.json();
if (data?.data?.actor?.nrql?.results) {
const newdata = data.data.actor.nrql.results.map((item: any) => {
item.id = item.incidentId;
item.policyName = item.policyName ? item.policyName : "No Policy";
return item
});
await this.persistenceManager.setNewRelicData(newdata);
this.data = newdata;
}
} catch (err) {
}
}
public drawGraph() {
this.data.sort((a, b) => {
return parseInt(a.openTime) - parseInt(b.openTime);
});
const duration = this.data[this.data.length - 1].openTime - this.data[0].openTime;
const interval = 10 / duration;
const first = parseInt(this.data[0].openTime);
const material = new StandardMaterial("material", this.scene);
material.diffuseColor = new Color3(0, 0, .7);
material.alpha = .3;
const baseMesh = MeshBuilder.CreateBox("baseItem", {width: 1, height: 1, depth: 1}, this.scene);
baseMesh.material = material;
const warningMaterial = new StandardMaterial("warningMaterial", this.scene);
warningMaterial.diffuseColor = new Color3(.7, .7, .2);
warningMaterial.alpha = .5;
const warningMesh = MeshBuilder.CreateBox("warningItem", {width: 1, height: 1, depth: 1}, this.scene);
warningMesh.material = warningMaterial;
const criticalMaterial = new StandardMaterial("criticalMaterial", this.scene);
criticalMaterial.diffuseColor = new Color3(.9, .2, .2);
criticalMaterial.alpha = .7;
const criticalMesh = MeshBuilder.CreateBox("criticalItem", {width: 1, height: 1, depth: 1}, this.scene);
criticalMesh.material = criticalMaterial;
const policies: Map<String, { x: number, y: number }> = new Map<string, { x: number, y: number }>();
this.data.forEach((item) => {
const policy = item.policyName ? item.policyName : "No Policy";
let x;
let y: number = 0;
if (policies.has(policy)) {
const value = policies.get(policy);
x = value.x;
y = value.y + .105;
policies.set(policy, {x, y});
} else {
policies.set(policy, {x: policies.size / 10, y: 0});
x = policies.get(policy).x;
const policyLabel = this.buildText(policy);
policyLabel.scaling = new Vector3(3, 3, 3);
policyLabel.position = new Vector3(x, .4, 0);
policyLabel.rotation.x = Math.PI / 2;
policyLabel.rotation.y = -Math.PI / 2;
this.policyLabels.push(policyLabel);
}
const start = parseInt(item.openTime) - first;
let end = duration;
if (item.closeTime) {
end = parseInt(item.closeTime) - first;
}
let box: AbstractMesh;
switch (item.priority) {
case "critical":
box = new InstancedMesh(item.id, criticalMesh);
break;
case "warning":
box = new InstancedMesh(item.id, warningMesh);
break;
default:
box = new InstancedMesh(item.id, baseMesh);
}
box.position = new Vector3(x, y + .5, (start * interval));
if (item.closeTime) {
box.scaling = new Vector3(.1, .1, (end - start) * interval);
} else {
box.scaling = new Vector3(.1, .1, .01);
}
box.position.z = box.position.z + box.scaling.z / 2;
const startLabel = this.buildText(new Date(start + first).toLocaleString());
startLabel.position = box.position.add(new Vector3(.05, .05, 0));
startLabel.position.z = (start * interval) - .01;
const endLabel = this.buildText(new Date(end + first).toLocaleString());
endLabel.position = box.position.add(new Vector3(.05, .05, 0));
endLabel.position.z = (end * interval) + .01;
});
this.scene.onBeforeRenderObservable.add(() => {
this.policyLabels.forEach((label) => {
label.position.z = this.scene.activeCamera.globalPosition.z;
});
});
}
private buildText(text: string) {
//Set font
const height = 0.03;
const font_size = 24;
const font = "bold " + font_size + "px Arial";
//Set height for dynamic texture
const DTHeight = 1.5 * font_size; //or set as wished
//Calc Ratio
const ratio = height / DTHeight;
//Use a temporary dynamic texture to calculate the length of the text on the dynamic texture canvas
const temp = new DynamicTexture("DynamicTexture", 32, this.scene);
const tmpctx = temp.getContext();
tmpctx.font = font;
const DTWidth = tmpctx.measureText(text).width + 8;
//Calculate width the plane has to be
const planeWidth = DTWidth * ratio;
//Create dynamic texture and write the text
const dynamicTexture = new DynamicTexture("DynamicTexture", {
width: DTWidth,
height: DTHeight
}, this.scene, false);
const mat = new StandardMaterial("mat", this.scene);
mat.diffuseTexture = dynamicTexture;
dynamicTexture.drawText(text, null, null, font, "#000000", "#ffffff", true);
//Create plane and set dynamic texture as material
const plane = MeshBuilder.CreatePlane("text", {width: planeWidth, height: height}, this.scene);
plane.material = mat;
return plane;
}
}

View File

@ -1,33 +0,0 @@
import {AbstractMenu} from "../menus/abstractMenu";
import {Scene, WebXRDefaultExperience} from "@babylonjs/core";
import {Controllers} from "../controllers/controllers";
import log, {Logger} from "loglevel";
import {Grid} from "@babylonjs/gui";
export class NewRelicMenu extends AbstractMenu {
private logger: Logger = log.getLogger('NewRelicMenu');
constructor(scene: Scene, xr: WebXRDefaultExperience, controllers: Controllers) {
super(scene, xr, controllers);
this.buildMenu();
}
buildMenu() {
this.logger.debug('buildMenu');
//this.makeButton("credentials", "credentials");
const grid = new Grid("grid");
grid.addColumnDefinition(.5);
grid.addColumnDefinition(.5);
grid.addRowDefinition(.5);
}
private handleClick(_info, state) {
this.logger.debug("clicked " + state.currentTarget.name);
switch (state.currentTarget.name) {
case "credentials":
break;
}
}
}

View File

@ -13,7 +13,7 @@ export function MainMenu({onClick}) {
} else { } else {
return ( return (
<div className="overlay mini" id="main"> <div className="overlay mini" id="main">
<img alte="deep diagram logo" height="120" src="/assets/ddd.svg" width="320"/> <img alt="deep diagram logo" height="120" src="/assets/ddd.svg" width="320"/>
<div id="enterXR" className="inactive"><a href="#" id="enterVRLink">Enter VR</a></div> <div id="enterXR" className="inactive"><a href="#" id="enterVRLink">Enter VR</a></div>
<QuestLink/> <QuestLink/>

View File

@ -1,72 +0,0 @@
import {
AbstractMesh,
MeshBuilder,
PhysicsAggregate,
PhysicsShapeType,
Scene,
SceneLoader,
TransformNode,
Vector3
} from "@babylonjs/core";
import {ControllerEventType, Controllers} from "../controllers/controllers";
import log, {Logger} from "loglevel";
export class Ball {
private readonly logger: Logger = log.getLogger('Ball');
private readonly scene: Scene;
private transformNode: TransformNode;
private mesh: AbstractMesh;
_position: Vector3 = new Vector3(0, .5, 0);
private parent: AbstractMesh;
private controllers: Controllers;
private physicsAggregate: PhysicsAggregate;
constructor(scene: Scene) {
this.scene = scene;
this.buildBall();
}
public setControllers(controllers: Controllers) {
this.controllers = controllers;
this.controllers.controllerObservable.add((event) => {
if (event.type == ControllerEventType.MOTION) {
}
});
}
public kick(direction: Vector3, force: number) {
this.physicsAggregate.body.applyImpulse(direction.scale(force), Vector3.Zero());
}
public get position(): Vector3 {
return this.physicsAggregate.transformNode.absolutePosition;
}
private buildBall() {
SceneLoader.ImportMesh(null, "/assets/models/", "ball.gltf", this.scene,
(meshes) => {
this.logger.debug('ball loaded');
this.mesh = meshes[0];
this.parent = MeshBuilder.CreateSphere("ballParent", {diameter: .17}, this.scene);
this.parent.isVisible = false;
this.parent.position = this._position;
this.scene.onBeforeRenderObservable.add(() => {
if (!this.physicsAggregate &&
this.scene?.getPhysicsEngine()?.getPhysicsPlugin()) {
this.logger.debug("creating physics aggregate");
this.physicsAggregate = new PhysicsAggregate(this.parent,
PhysicsShapeType.SPHERE, {mass: 1, restitution: .6, friction: .6}, this.scene);
this.physicsAggregate.body.setLinearDamping(.3);
this.physicsAggregate.body.setAngularDamping(2);
this.mesh.setParent(this.physicsAggregate.transformNode);
this.mesh.position.y = 0;
return;
}
}, -1, false, this, false);
});
}
}

View File

@ -1,141 +0,0 @@
import {
InstancedMesh,
Mesh,
MeshBuilder,
Scene,
StandardMaterial,
TransformNode,
Vector2,
Vector3
} from "@babylonjs/core";
import {Ball} from "./ball";
import {Team} from "./team";
export class Field {
private readonly scene: Scene;
public ball: Ball;
private readonly goalMesh: Mesh;
private material: StandardMaterial;
private team1: Team;
private readonly fieldCenter: TransformNode;
private team2: Team;
public gazePoint: Vector3;
constructor(scene: Scene) {
this.scene = scene;
this.fieldCenter = new TransformNode("fieldCenter", this.scene);
this.team1 = new Team(scene, 1, "one");
this.team2 = new Team(scene, -1, "two");
this.goalMesh = MeshBuilder.CreateCylinder("goalPost", {diameter: .1, height: 1}, this.scene);
this.material = new StandardMaterial("material", this.scene);
this.material.diffuseColor.set(1, 1, 1);
this.material.alpha = .5;
this.goalMesh.material = this.getMaterial();
this.goalMesh.setEnabled(false);
this.ball = new Ball(this.scene);
this.buildField();
}
private buildField() {
const width = .08;
this.buildLine(new Vector2(35, 0), new Vector2(width, 100));
this.buildLine(new Vector2(-35, 0), new Vector2(width, 100));
this.buildLine(new Vector2(-9.16, 50 - 2.75), new Vector2(width, 5.5 - width));
this.buildLine(new Vector2(9.16, 50 - 2.75), new Vector2(width, 5.5 - width));
this.buildLine(new Vector2(-9.16, -50 + 2.75), new Vector2(width, 5.5 - width));
this.buildLine(new Vector2(9.16, -50 + 2.75), new Vector2(width, 5.5 - width));
this.buildLine(new Vector2(-18.33, 50 - 8.25), new Vector2(width, 16.5 - width));
this.buildLine(new Vector2(18.33, 50 - 8.25), new Vector2(width, 16.5 - width));
this.buildLine(new Vector2(-18.33, -50 + 8.25), new Vector2(width, 16.5 - width));
this.buildLine(new Vector2(18.33, -50 + 8.25), new Vector2(width, 16.5 - width));
this.buildLine(new Vector2(0, -50), new Vector2(70 - width, width));
this.buildLine(new Vector2(0, 50), new Vector2(70 - width, width));
this.buildLine(new Vector2(0, -44.5), new Vector2(18.32 + width, width));
this.buildLine(new Vector2(0, 44.5), new Vector2(18.32 + width, width));
this.buildLine(new Vector2(0, -33.5), new Vector2(36.66 + width, width));
this.buildLine(new Vector2(0, 33.5), new Vector2(36.66 + width, width));
this.buildCircle(new Vector2(0, 50 - 11));
this.buildCircle(new Vector2(0, -50 + 11));
this.buildLine(new Vector2(0, 0), new Vector2(70 - width, width));
this.buildArc(new Vector2(0, 0));
this.buildArc(new Vector2(0, 50 - 11), Math.PI / 11, Math.PI / 1.275);
this.buildArc(new Vector2(0, -50 + 11), Math.PI / 11, (Math.PI / 1.275) - Math.PI);
this.buildGoalPost(new Vector2(3.66, -50));
this.buildGoalPost(new Vector2(-3.66, -50));
this.buildGoalPost(new Vector2(3.66, 50));
this.buildGoalPost(new Vector2(-3.66, 50));
this.buildGoalPost(new Vector2(0, 50), false, 7.32, 2.44);
this.buildGoalPost(new Vector2(0, -50), false, 7.32, 2.44);
}
private buildGoalPost(position: Vector2, vertical: boolean = true, length: number = 2.44, y: number = 0) {
const goalPost = new InstancedMesh("goalPost", this.goalMesh);
goalPost.position.x = position.x;
goalPost.position.z = position.y;
if (!vertical) {
goalPost.rotation.z = Math.PI / 2;
goalPost.position.y = y;
} else {
goalPost.position.y = length / 2;
}
goalPost.scaling.y = length;
goalPost.visibility = 1;
goalPost.setParent(this.fieldCenter);
}
private buildCircle(position: Vector2) {
const circle = MeshBuilder.CreateDisc("disc", {radius: .25, tessellation: 180}, this.scene);
circle.position.x = position.x;
circle.position.z = position.y;
circle.position.y = .01;
circle.rotation.x = Math.PI / 2;
circle.material = this.getMaterial();
circle.setParent(this.fieldCenter);
}
private buildArc(position: Vector2, arc: number = Math.PI, rotation: number = 0) {
const myShape = [
new Vector3(1, 0, 0),
new Vector3(1, 0, 1.012),
new Vector3(.975, 0, 1.012)
];
const circle = MeshBuilder.CreateLathe("lathe", {
arc: arc,
shape: myShape, radius: 9.15, tessellation: 180
}, this.scene);
circle.material = this.getMaterial();
circle.position.y = 0.01;
circle.position.x = position.x;
circle.position.z = position.y;
circle.rotation = new Vector3(0, rotation, 0);
circle.setParent(this.fieldCenter);
}
private getMaterial(): StandardMaterial {
const material = new StandardMaterial("material", this.scene);
material.diffuseColor.set(1, 1, 1);
material.alpha = .5;
return material;
}
private buildLine(position: Vector2, shape: Vector2) {
const line = MeshBuilder.CreatePlane("line", {width: shape.x, height: shape.y}, this.scene);
line.material = this.getMaterial();
line.rotation.x = Math.PI / 2;
line.position.y = .01;
line.position.x = position.x;
line.position.z = position.y;
line.setParent(this.fieldCenter);
}
}

View File

@ -1,149 +0,0 @@
import {
AbstractMesh,
AnimationGroup,
AssetContainer,
Mesh,
MeshBuilder,
Observable,
PBRMaterial,
PhysicsAggregate,
PhysicsMotionType,
PhysicsShapeType,
Scene,
SceneLoader,
Skeleton,
Texture,
Vector2,
Vector3
} from "@babylonjs/core";
import log, {Logger} from "loglevel";
export class PlayerFactory {
private readonly logger: Logger = log.getLogger('PlayerFactory')
public onReadyObservable: Observable<any> = new Observable();
private readonly scene: Scene;
private container: AssetContainer;
constructor(scene: Scene) {
this.scene = scene;
SceneLoader.LoadAssetContainer("/assets/models/",
"player2.glb",
this.scene,
(container: AssetContainer) => {
this.container = container;
this.onReadyObservable.notifyObservers(this);
this.logger.debug('Player Model Loaded');
});
}
public buildPlayer(position: Vector3, number: number, uniformTexture: Texture = null, teamName: string = "team"): Player {
this.logger.debug(`Building player #${number}, for team ${teamName}`);
return new Player(this.scene, position, this.container, number, uniformTexture, teamName);
}
}
export class Player {
private readonly logger: Logger = log.getLogger('Player');
public readonly onReadyObservable: Observable<any> = new Observable();
private readonly scene: Scene;
private readonly position: Vector3;
private mesh: Mesh;
private parent: AbstractMesh;
private animationGroup: AnimationGroup;
private physicsAggregate: PhysicsAggregate;
private skeleton: Skeleton;
private readonly number: number;
private readonly teamName: string;
private forward = true;
private destination: Vector2;
constructor(scene: Scene, position: Vector3, container: AssetContainer, number: number = 0, texture: Texture = null, teamName: string = "team") {
this.scene = scene;
this.position = position;
this.number = number;
this.teamName = teamName;
const data = container.instantiateModelsToScene(undefined, false, {doNotInstantiate: true});
this.mesh = (data.rootNodes[0] as Mesh);
if (texture) {
((this.mesh.getChildren()[0].getChildren()[2] as Mesh).material as PBRMaterial).albedoTexture = texture;
// (this.mesh.material as PBRMaterial).albedoTexture = texture;
}
this.skeleton = data.skeletons[0];
this.animationGroup = data.animationGroups[6];
this.buildPlayer();
}
public lookAt(location: Vector2) {
const body = this.physicsAggregate.body;
body.disablePreStep = false;
body.transformNode.lookAt(new Vector3(location.x, body.transformNode.position.y, location.y));
this.scene.onAfterRenderObservable.addOnce(() => {
this.physicsAggregate.body.disablePreStep = true;
this.animationGroup.stop();
this.animationGroup.onAnimationGroupEndObservable.add(() => {
if (this.forward) {
this.animationGroup.start(false, .1, 256, 267);
} else {
this.animationGroup.start(false, .1, 267, 256);
}
this.forward = !this.forward;
}, -1, false, this);
this.animationGroup.start(false, .1, 256, 267);
});
}
public runTo(location: Vector2) {
this.logger.debug(`Running to ${JSON.stringify(location)}`)
this.destination = location;
const body = this.physicsAggregate.transformNode.physicsBody;
body.setMotionType(PhysicsMotionType.ANIMATED);
body.disablePreStep = false;
body.transformNode.lookAt(new Vector3(location.x, body.transformNode.position.y, location.y));
const vel = new Vector3(location.x, body.transformNode.position.y, location.y);
this.scene.onBeforeRenderObservable.addOnce(() => {
body.setLinearVelocity(vel.subtract(body.transformNode.position).normalize().scale(2));
});
this.scene.onAfterRenderObservable.addOnce(() => {
this.physicsAggregate.body.disablePreStep = true;
this.animationGroup.stop();
this.animationGroup.start(true, 1.0, 0, 250);
});
this.scene.onAfterPhysicsObservable.add(() => {
if (body.getLinearVelocity().length() > .1) {
if (this.destination.subtract(new Vector2(body.transformNode.position.x,
body.transformNode.position.z)).length() < .1) {
body.setLinearVelocity(Vector3.Zero());
body.setMotionType(PhysicsMotionType.DYNAMIC);
this.animationGroup.stop();
this.animationGroup.start(false, .1, 256, 267);
}
}
});
}
private buildPlayer() {
this.parent = MeshBuilder.CreateCylinder(`team${this.teamName}player${this.number}`, {
diameter: .5,
height: 1.6
}, this.scene);
this.parent.position = this.position;
this.parent.isVisible = false;
this.physicsAggregate = new PhysicsAggregate(this.parent,
PhysicsShapeType.CYLINDER, {mass: 100, restitution: .02, friction: .3}, this.scene);
this.physicsAggregate.body.setAngularDamping(.5);
this.mesh.parent = this.physicsAggregate.transformNode;
this.mesh.metadata = {type: "player", grabbable: true};
this.mesh.position.x = 3;
this.mesh.position.y = -.84;
}
}

View File

@ -1,201 +0,0 @@
import {Color3, MeshBuilder, Vector3, WebXRDefaultExperience} from "@babylonjs/core";
import {AbstractMenu} from "../menus/abstractMenu";
import {ControllerEvent, ControllerEventType, Controllers} from "../controllers/controllers";
import {Control3D, GUI3DManager, PlanePanel, Slider3D} from "@babylonjs/gui";
import log, {Logger} from "loglevel";
import {Field} from "./field";
import {makeButton} from "../menus/functions/makeButton";
enum SoccerMenuState {
PLAY,
PLAN,
TRAIN,
NONE
}
export class SoccerMenu extends AbstractMenu {
private manager: GUI3DManager;
private state: SoccerMenuState = SoccerMenuState.NONE;
private readonly field: Field;
private readonly logger: Logger = log.getLogger('SoccerMenu')
private startTime: number;
private startPosition: Vector3;
constructor(xr: WebXRDefaultExperience, controllers: Controllers) {
super(xr, controllers);
this.field = new Field(this.scene);
this.manager = new GUI3DManager(this.scene);
this.controllers.controllerObservable.add(this.controllerEventHandler, -1, false, this);
this.buildMenu();
}
private controllerEventHandler(event: ControllerEvent) {
switch (this.state) {
case SoccerMenuState.PLAY:
this.playControllerEventHandler(event);
break;
case SoccerMenuState.PLAN:
break;
case SoccerMenuState.TRAIN:
break;
case SoccerMenuState.NONE:
break
}
}
private forceFactor: number = 10;
private buildKickLine(direction: Vector3, force: number) {
const start = this.field.ball.position.clone();
const line = MeshBuilder.CreateLines("kickLine", {points: [start, start.add(direction.scale(force))]}, this.scene);
line.color = new Color3(1, 1, .5);
line.isPickable = false;
setTimeout(() => {
line.dispose();
}, 2000);
}
makeSlider(name: string): Control3D {
const slider = new Slider3D(name, false);
slider.scaling.x = 2;
slider.minimum = 10;
slider.maximum = 30;
slider.value = this.forceFactor;
slider.onValueChangedObservable.add((value) => {
this.logger.debug(`slider value ${value}`);
this.forceFactor = value;
});
return slider;
}
private playControllerEventHandler(event: ControllerEvent) {
switch (event.type) {
case ControllerEventType.TRIGGER:
if (event.value > .8) {
if (!this.startTime) {
this.startTime = new Date().getTime();
const start = event.controller.grip.absolutePosition.clone();
//transform start to this.xr.baseExperience.camera space
start.subtractInPlace(this.xr.baseExperience.camera.globalPosition);
//const e = this.xr.baseExperience.camera.absoluteRotation.toEulerAngles();
//start.applyRotationQuaternionInPlace(Quaternion.FromEulerAngles(0, e.y, 0));
this.startPosition = start;
}
} else {
if (this.startTime) {
const end = event.controller.grip.absolutePosition.clone();
//transform start to this.xr.baseExperience.camera space
end.subtractInPlace(this.xr.baseExperience.camera.globalPosition);
//const e = this.xr.baseExperience.camera.absoluteRotation.toEulerAngles();
//end.applyRotationQuaternionInPlace(Quaternion.FromEulerAngles(0, e.y, 0));
if (this.startTime && this.startPosition) {
const duration = new Date().getTime() - this.startTime;
this.controllers.controllerObservable.notifyObservers({
type: ControllerEventType.MOTION,
startPosition: this.startPosition,
endPosition: end,
duration: duration
});
this.startTime = null;
this.startPosition = null;
}
}
}
const worldRay = this.scene.activeCamera.getForwardRay();
worldRay.origin = this.scene.activeCamera.globalPosition;
const pickInfo = this.scene.pickWithRay(worldRay, function (mesh) {
return mesh.name != 'platform';
});
if (pickInfo?.hit) {
const circle = MeshBuilder.CreateDisc("circle", {radius: .04}, this.scene);
const normal = pickInfo.getNormal(true, false).scale(-1);
circle.position = pickInfo.pickedPoint.add(normal.scale(-.01));
circle.lookAt(pickInfo.pickedPoint.add(normal));
setTimeout(() => {
circle.dispose();
}, 1500);
if (pickInfo?.pickedMesh?.name == 'Football Ball.001') {
this.controllers.controllerObservable.notifyObservers({
type: ControllerEventType.GAZEPOINT,
endPosition: pickInfo.pickedPoint,
startPosition: this.xr.baseExperience.camera.globalPosition
})
}
}
const mesh = this.scene.getPointerOverMesh();
if (mesh) {
const meta = mesh?.parent?.parent?.parent
if (meta) {
this.logger.debug(meta.id);
}
}
break;
case ControllerEventType.MOTION:
const start = event.startPosition.clone();
const direction = start.subtract(event.endPosition);
const force = direction.length() * this.forceFactor;
const dir = direction.normalize();
//const e = this.xr.baseExperience.camera.absoluteRotation.toEulerAngles();
//direction.applyRotationQuaternionInPlace(Quaternion.FromEulerAngles(0, e.y, 0));
this.buildKickLine(dir, force);
this.field.ball.kick(dir, force);
break;
case ControllerEventType.GAZEPOINT:
if (event.endPosition) {
this.field.gazePoint = event.endPosition.clone();
}
break;
}
}
makeButton(name: string, id: string) {
const button = makeButton(name, id);
button.onPointerClickObservable.add(this.handleClick, -1, false, this);
return button;
}
private buildMenu() {
const panel = new PlanePanel();
this.manager.addControl(panel);
panel.columns = 10;
panel.addControl(makeButton("Play", "play"));
panel.addControl(makeButton("Plan", "plan"));
panel.addControl(makeButton("Train", "Train"));
panel.addControl(makeButton("Modify", "modify"));
const slider = panel.addControl(this.makeSlider("force"));
this.manager.rootContainer.children[0].node.position.y = .2;
this.manager.controlScaling = .2;
//panel.updateLayout();
//slider.position.x = 1;
//this.createHandle(this.manager.rootContainer.children[0].node);
//this.handle.mesh.position = getFrontPosition(3, this.scene).add(new Vector3(0, .5, 0));
}
private handleClick(_info, state) {
this.logger.debug("clicked " + state.currentTarget.name);
switch (state.currentTarget.name) {
case "play":
this.state = SoccerMenuState.PLAY;
break;
case "plan":
this.state = SoccerMenuState.PLAN;
break;
case "train":
this.state = SoccerMenuState.TRAIN;
break;
}
}
}

View File

@ -1,49 +0,0 @@
import {Player, PlayerFactory} from "./player";
import {Scene, Texture, Vector2, Vector3} from "@babylonjs/core";
export class Team {
private readonly scene: Scene;
private players: Player[] = [];
private readonly goalSide: number = -1;
private playerFactory: PlayerFactory;
private positions: Vector2[] = [
new Vector2(3, 1),
new Vector2(-3, 1),
new Vector2(5, 2),
new Vector2(15, 5),
new Vector2(-15, 5),
new Vector2(2, 10),
new Vector2(-2, 15),
new Vector2(15, 20),
new Vector2(-15, 20),
new Vector2(0, 35),
new Vector2(0, 47),
];
private readonly name: string;
private uniforms: Texture[] = [];
constructor(scene: Scene, side: number = 1, name: string = "team") {
this.scene = scene;
this.goalSide = side;
this.name = name;
this.uniforms.push(new Texture("/assets/textures/team1.png", this.scene))
this.uniforms.push(new Texture("/assets/textures/team2.png", this.scene))
this.playerFactory = new PlayerFactory(this.scene);
this.playerFactory.onReadyObservable.add(() => {
this.buildTeam();
});
}
private buildTeam() {
for (let i = 0; i < 11; i++) {
const player = this.playerFactory
.buildPlayer(new Vector3(this.positions[i].x * this.goalSide, 1, this.positions[i].y * this.goalSide), i,
this.uniforms[this.goalSide == 1 ? 0 : 1],
this.name);
player.lookAt(new Vector2(0, -50 * this.goalSide))
this.players.push(player);
}
}
}

View File

@ -7,24 +7,12 @@ export class AnimatedLineTexture {
public static Texture() { public static Texture() {
if (!AnimatedLineTexture._texture) { if (!AnimatedLineTexture._texture) {
/*this._texture = new RawTexture(
this._textureColors,
this._textureColors.length / 3,
1,
Engine.TEXTUREFORMAT_RGB,
DefaultScene.Scene,
false,
true,
Engine.TEXTURE_NEAREST_NEAREST
)*/
this._texture = new Texture('/assets/textures/arrow.png', DefaultScene.Scene); this._texture = new Texture('/assets/textures/arrow.png', DefaultScene.Scene);
//this._texture.wrapU = RawTexture.WRAP_ADDRESSMODE this._texture.name = 'connection-texture';
this._texture.name = 'blue-white-texture';
this._texture.uScale = 30; this._texture.uScale = 30;
DefaultScene.Scene.onBeforeRenderObservable.add(() => { DefaultScene.Scene.onBeforeRenderObservable.add(() => {
this._texture.uOffset -= 0.01 * DefaultScene.Scene.getAnimationRatio() this._texture.uOffset -= 0.01 * DefaultScene.Scene.getAnimationRatio()
}); });
} }
return this._texture; return this._texture;
} }

View File

@ -1,111 +0,0 @@
import {Scene, Sound} from "@babylonjs/core";
export class DiaSounds {
private readonly scene: Scene;
private readonly _tick: Sound;
constructor(scene: Scene) {
this.scene = scene;
const soundSprite = [
{obj: "_enter", name: "enter", url: "/assets/sounds/sounds.mp3"},
{obj: "_exit", name: "exit", url: "/assets/sounds/sounds.mp3"},
{obj: "_high", name: "high", url: "/assets/sounds/sounds.mp3"},
{obj: "_low", name: "low", url: "/assets/sounds/sounds.mp3"},
];
soundSprite.forEach((item: { obj: any, name: string, url: string }, idx) => {
this[item.obj] = new Sound(item.name, item.url, this.scene, null, {
autoplay: false,
loop: false,
volume: this.volume,
offset: idx,
length: 1.0
});
});
this._tick = new Sound("tick", '/assets/sounds/tick.mp3', this.scene);
this._bounce = new Sound("bounce", "/assets/sounds/drumsprite.mp3", this.scene, null, {
autoplay: false,
loop: false,
offset: 0,
length: 0.990
});
this._background = new Sound("brown", "/assets/sounds/brown.mp3", this.scene, null, {
autoplay: false,
volume: 1,
loop: true
});
const spatialOptions = {
spatialSound: true,
autoplay: false,
volume: .5,
loop: false
}
this._backgroundEffects.push(this.buildSpatialSound("warbler2", "/assets/sounds/warbler2.mp3"));
this._backgroundEffects.push(this.buildSpatialSound("warbler3", "/assets/sounds/warbler3.mp3"));
this._backgroundEffects.push(this.buildSpatialSound("crickets", "/assets/sounds/crickets.mp3"));
this._backgroundEffects.push(this.buildSpatialSound("dove", "/assets/sounds/dove.mp3"))
}
private volume: number = 0.8;
private readonly _bounce: Sound;
private readonly _background: Sound;
private readonly _enter: Sound;
public get enter() {
return this._enter;
}
public get tick() {
return this._tick;
}
_backgroundEffects: Array<Sound> = [];
public get backgroundEffects(): Array<Sound> {
return this._backgroundEffects;
}
private buildSpatialSound(name: string, url: string) {
const spatialOptions = {
spatialSound: true,
autoplay: false,
volume: .5,
loop: false
}
const sound = new Sound(name, url, this.scene, null, spatialOptions);
sound.switchPanningModelToHRTF();
sound.maxDistance = 40;
return sound;
}
public get background(): Sound {
return this._background;
}
private readonly _exit: Sound;
public get exit() {
return this._exit;
}
private readonly _high: Sound;
public get high() {
return this._high;
}
private readonly _low: Sound;
public get low() {
return this._low;
}
public get bounce() {
const bounce = this._bounce.clone();
bounce.updateOptions({offset: 0, volume: this.volume, length: .990});
bounce.onEndedObservable.add(() => {
bounce.dispose();
});
return bounce;
}
}

View File

@ -1,22 +0,0 @@
import {Scene} from "@babylonjs/core";
export class DiagramExporter {
private scene: Scene;
constructor(scene: Scene) {
this.scene = scene;
}
public exportgltf() {
import("@babylonjs/serializers").then((serializers) => {
serializers.GLTF2Export.GLBAsync(this.scene, 'diagram.glb', {
shouldExportNode: function (node) {
return (node?.metadata?.exportable as boolean);
}
}).then((gltf) => {
gltf.downloadFiles();
});
});
}
}

View File

@ -1,22 +0,0 @@
import {TransformNode} from "@babylonjs/core";
const debug = true;
export function displayDebug(text: string[]) {
if (debug) {
drawDebugText(text);
}
}
function drawDebugText(text: string[]) {
const transform = new TransformNode("debugTransform");
transform.parent = transform.getScene().activeCamera;
transform.getScene().onActiveCameraChanged.add(() => {
transform.parent = transform.getScene().activeCamera;
});
console.log(text);
transform.position.z = 1;
transform.position.y = .2;
}

View File

@ -94,6 +94,6 @@ export async function groundMeshObserver(ground: AbstractMesh,
rig.turnSnap = config.turnSnap; rig.turnSnap = config.turnSnap;
}, -1, false, this); }, -1, false, this);
const webController = new WebController(ground.getScene(), rig, diagramManager, diagramManager.controllers); const webController = new WebController(ground.getScene(), rig, diagramManager);
} }

View File

@ -1,17 +1,8 @@
import {DefaultScene} from "../../defaultScene"; import {DefaultScene} from "../../defaultScene";
export function addSceneInspector() { export function addSceneInspector() {
const scene = DefaultScene.Scene;
window.addEventListener("keydown", (ev) => { window.addEventListener("keydown", (ev) => {
if (ev.key == "z") {
//voiceManager.startRecording();
}
if (ev.key == "x") {
//voiceManager.stopRecording();
}
if (ev.shiftKey && ev.ctrlKey && ev.altKey && ev.keyCode === 73) { if (ev.shiftKey && ev.ctrlKey && ev.altKey && ev.keyCode === 73) {
const web = document.querySelector('#webApp'); const web = document.querySelector('#webApp');
(web as HTMLDivElement).style.display = 'none'; (web as HTMLDivElement).style.display = 'none';

View File

@ -1,78 +0,0 @@
import {
Color3,
DynamicTexture,
InstancedMesh,
Mesh,
MeshBuilder,
Scene,
StandardMaterial,
TransformNode
} from "@babylonjs/core";
import {DefaultScene} from "../defaultScene";
export class TextMeshGenerator {
private _scene: Scene;
private _textMeshes: Map<string, Mesh> = new Map<string, Mesh>();
constructor() {
this._scene = DefaultScene.Scene;
this.initialize();
}
public getMesh(input: string): TransformNode {
const transformNode = new TransformNode("textMesh-" + input, this._scene);
let x = 0;
for (const char of input) {
const mesh = new InstancedMesh("instance_" + input, this._textMeshes.get(char));
mesh.parent = transformNode;
x = x + Math.abs(mesh.getBoundingInfo().boundingBox.minimum.x);
mesh.position.x = x;
x = x + mesh.getBoundingInfo().boundingBox.maximum.x;
}
return transformNode;
}
public generateCharMesh(input: string): Mesh {
console.log("Generating text mesh for: " + input);
//Set font
const height = 0.05;
const font_size = 28;
const font = "bold " + font_size + "px Arial";
//Set height for dynamic texture
const DTHeight = 1.5 * font_size; //or set as wished
//Calc Ratio
const ratio = height / DTHeight;
//Use a temporary dynamic texture to calculate the length of the text on the dynamic texture canvas
const temp = new DynamicTexture("DynamicTexture", 32, this._scene);
const tmpctx = temp.getContext();
tmpctx.font = font;
const DTWidth = tmpctx.measureText(input).width + 8;
//Calculate width the plane has to be
const planeWidth = DTWidth * ratio;
const dynamicTexture = new DynamicTexture("DynamicTexture", {
width: DTWidth,
height: DTHeight
}, this._scene, false);
dynamicTexture.drawText(input, null, null, font, "#ffffff", "#000000", true);
temp.dispose();
const mat = new StandardMaterial("mat", this._scene);
mat.diffuseColor = Color3.Black();
mat.disableLighting = true;
mat.backFaceCulling = true;
mat.emissiveTexture = dynamicTexture;
const plane = MeshBuilder.CreatePlane("character" + input, {width: planeWidth, height: height}, this._scene);
plane.material = mat;
return plane;
}
private initialize() {
for (let i = 32; i < 127; ++i) {
const mesh = this.generateCharMesh(String.fromCharCode(i));
this._textMeshes.set(String.fromCharCode(i), mesh);
}
}
}

View File

@ -1,92 +0,0 @@
import {VuMeterEngine, WebVoiceProcessor} from "@picovoice/web-voice-processor";
import {EagleProfilerWorker, EagleWorker} from "@picovoice/eagle-web";
import {PvEngine} from "@picovoice/web-voice-processor/dist/types/types";
import {base64} from "rfc4648";
import {CobraWorker} from "@picovoice/cobra-web";
export class VoiceRecognizer {
private readonly profile = 'TT4GLAFik3sHYasWTbmNc7CX2xmJifp897E6xyJDwcD8rHA1ZgJTdLaLQ0Z1zJP3Lzv61JMJpuNsgSSxraWf62RECXJHA4SJ5RCSv3/MHXcnKlaGzcQ4gJD/vcl8tL45j02me6lNf1TtbI81qv/GBSH9u3p5V/p7fD1j/tZ8P3kzM40FG1QxP330Sp/dvSwU6oEc5iH7+D3Zsy4GEtD3iqGdAex4200elW753eXlKli92qLlaplDxCZZIwNG0/ER51NhVzg/D+ieZLE/rUjZAl+z4a9c7AurnQDTZ1fKyzwMzjiQsb8h6rIco+IlblAuE8dmVfFxZXrpfw8tViK5KwnpbHrnR8ebLA0Zd/G5l0yjXeCEh8Y26qkGZk43MolBgQ044KNNsJbDrm1o2sYGvo/BgEronFuBB+wNw0pVFqp1nrIqfT8IsH42q4rj7ByzxH+4QVr1uQVx7c89GTp1yYyqk+q9B+f0cG063KwnUofddkx0tmot3d8kPCZGL1H88qMm2NdNeCU6AFi1qhP1Ssd3jOsyzd4O3U9JMJIUruySzf6Qx3/JI4aSKJm0To/xEszrm028s1qD8I0+Kh3GxgtiW+toCzJrAIoRkxmIgV2HbOStjerTQDK2t1MMHpHEr7NfNaJxxripR2xDlw/r1Sh2sf58AhIYBk1b/U54PCsm7tWKc0YroWgO5qSpASdkIq2UX7AgQ6nWtcZPk5d5xdfRkhIy3Yf6yushwEz/+v3aa/fshkh9lbKnz2wt4MhmbMJv7WYenHQr0RvEDQFchNHUyx8D7fBLpKwrmHVDi0meG7pl0Q9DrFzykeBZi0m22T6xF5OUBqvUZWdcqa5ZoYvPZS5Uk0d3COhAGjgFEAL7IMK9rZei24mM98+vqyfD1RRK29rQFljHxO9lJ0N3NINW2PfZulPPqn0OtEhxU829W1k1JjOUgOucJUpI9D0H1vrcqTYq0F4mj3YTqJ0CNbqXEan+XlbjB6kGKDuO1V/YkLbShJRnmKVtaCS2m4zDCJ5Rc7x8J7E/Cx6AnVK7UWM9CLnnLoaJ6sib9UnBV1uSTK2BIp1mO8b+BjP2yJ2/l1xbYUPZQa/ECRarwDP9PY9lHym6WGf35BjuWBwxT6obifw9JyYaqFZxwNbKviqKshSW8wmh5euYu3s0hY/MhCD+ZCYZiJAXADArcv8z8Wlk1x/KmZwLOAKJfgDUcs+9Q8aKGq5/jTPcd6MuM5pAVwfoFMR9QD8uKmyrPuBdJMRZFULX0uqliyna2CTmsAJ+6B47AA61q1/50Vj8OTUBLi+fhIaw3Ch1ofMYopIqc+QT81ekH8b9/+pXaUi+moA6C53Mnch9hB/uKoJELPSNDpIy1fP08Ujv/K0Foft4X43w9dImveOEhw==';
public constructor() {
this.start();
}
public async start() {
let voicePresent = false;
const eagleProfiler = await EagleProfilerWorker.create(
'qQG03oXEGQRfPbX7H1VTZHLy/zelmMxcWXSy14/pskqri4LTJvBWmQ==',
{publicPath: '/voice/eagle_params.pv'}
)
const bytes = base64.parse(this.profile);
const eagle = await EagleWorker.create('qQG03oXEGQRfPbX7H1VTZHLy/zelmMxcWXSy14/pskqri4LTJvBWmQ=='
, {publicPath: '/voice/eagle_params.pv'},
[{bytes: bytes}]);
let data: Int16Array = null;
const engine: PvEngine = {
onmessage: async (e: MessageEvent) => {
if (!voicePresent) {
return;
}
switch (e.data.command) {
case 'process':
const inputData = e.data.inputFrame;
const validation = await eagle.process(inputData);
if (validation && validation[0] > .99) {
}
if (data == null) {
data = inputData;
} else {
data = new Int16Array(data.length + inputData.length);
data.set(data, 0);
data.set(inputData, data.length - inputData.length);
}
if (data.length > eagleProfiler.minEnrollSamples) {
const result = await eagleProfiler.enroll(data);
if (result.percentage >= 100) {
const profile = await eagleProfiler.export();
//WebVoiceProcessor.unsubscribe(engine);
//WebVoiceProcessor.unsubscribe(engine);
//eagleProfiler.release();
}
}
break;
}
}
}
const devices = await navigator.mediaDevices.enumerateDevices();
devices.forEach((device) => {
if (device.kind === 'audioinput') {
}
});
const vuCallback = (db) => {
}
WebVoiceProcessor.setOptions({deviceId: 'default'});
const vuEngine = new VuMeterEngine(vuCallback);
//WebVoiceProcessor.subscribe(vuEngine);
const cobra = await CobraWorker.create('qQG03oXEGQRfPbX7H1VTZHLy/zelmMxcWXSy14/pskqri4LTJvBWmQ==',
(isVoice) => {
voicePresent = (isVoice && isVoice > .85);
});
WebVoiceProcessor.subscribe(cobra);
WebVoiceProcessor.subscribe(engine);
}
}

View File

@ -2,7 +2,6 @@ import {Color3, Engine, FreeCamera, Observable, Scene, Vector3, WebGPUEngine} fr
import '@babylonjs/loaders'; import '@babylonjs/loaders';
import {DiagramManager} from "./diagram/diagramManager"; import {DiagramManager} from "./diagram/diagramManager";
import log, {Logger} from "loglevel"; import log, {Logger} from "loglevel";
import {GamepadManager} from "./controllers/gamepadManager";
import {CustomEnvironment} from "./util/customEnvironment"; import {CustomEnvironment} from "./util/customEnvironment";
import {Spinner} from "./objects/spinner"; import {Spinner} from "./objects/spinner";
import {PouchdbPersistenceManager} from "./integration/database/pouchdbPersistenceManager"; import {PouchdbPersistenceManager} from "./integration/database/pouchdbPersistenceManager";
@ -17,11 +16,8 @@ import {Introduction} from "./tutorial/introduction";
const webGpu = false; const webGpu = false;
log.setLevel('error', false); log.setLevel('error', false);
log.getLogger('PouchdbPersistenceManager').setLevel('debug', false);
const canvas = (document.querySelector('#gameCanvas') as HTMLCanvasElement); const canvas = (document.querySelector('#gameCanvas') as HTMLCanvasElement);
export class VrApp { export class VrApp {
//preTasks = [havokModule]; //preTasks = [havokModule];
private logger: Logger = log.getLogger('App'); private logger: Logger = log.getLogger('App');
@ -32,7 +28,6 @@ export class VrApp {
} }
public async initialize(scene: Scene) { public async initialize(scene: Scene) {
//const mesh = SceneLoader.ImportMesh(null, '/assets/models/', 'person.stl', DefaultScene.Scene);
setMainCamera(scene); setMainCamera(scene);
const spinner = new Spinner(); const spinner = new Spinner();
spinner.show(); spinner.show();
@ -46,9 +41,7 @@ export class VrApp {
} }
}); });
initEnvironment(diagramManager, spinner); initEnvironment(diagramManager, spinner);
const gamepadManager = new GamepadManager(scene);
addSceneInspector(); addSceneInspector();
//const camMenu = new CameraMenu(scene);
const el = document.querySelector('#download'); const el = document.querySelector('#download');
if (el) { if (el) {
el.addEventListener('click', () => { el.addEventListener('click', () => {
@ -65,35 +58,25 @@ export class VrApp {
} }
private async initializeEngine() { private async initializeEngine() {
let engine: WebGPUEngine | Engine = null; let engine: WebGPUEngine | Engine = null;
if (webGpu) { if (webGpu) {
engine = new WebGPUEngine(canvas); engine = new WebGPUEngine(canvas);
await (engine as WebGPUEngine).initAsync(); await (engine as WebGPUEngine).initAsync();
} else { } else {
engine = new Engine(canvas, true); engine = new Engine(canvas, true);
} }
engine.setHardwareScalingLevel(1 / window.devicePixelRatio); engine.setHardwareScalingLevel(1 / window.devicePixelRatio);
window.onresize = () => { window.onresize = () => {
engine.resize(); engine.resize();
} }
const scene = new Scene(engine); const scene = new Scene(engine);
DefaultScene.Scene = scene; DefaultScene.Scene = scene;
//const a = new CurveObject();
scene.ambientColor = new Color3(.1, .1, .1); scene.ambientColor = new Color3(.1, .1, .1);
//log.resetLevel();
//log.setDefaultLevel('error');
await this.initialize(scene); await this.initialize(scene);
engine.runRenderLoop(() => { engine.runRenderLoop(() => {
scene.render(); scene.render();
}); });
} }
} }
const vrApp = new VrApp(); const vrApp = new VrApp();
buildQuestLink(); buildQuestLink();
@ -107,7 +90,6 @@ function setMainCamera(scene: Scene) {
async function initDb(diagramManager: DiagramManager) { async function initDb(diagramManager: DiagramManager) {
const db = new PouchdbPersistenceManager(); const db = new PouchdbPersistenceManager();
//const userManager = new UserManager(db.onUserObservable);
db.setDiagramManager(diagramManager); db.setDiagramManager(diagramManager);
await db.initialize(); await db.initialize();
} }
@ -119,10 +101,4 @@ function initEnvironment(diagramManager: DiagramManager, spinner: Spinner) {
}); });
}, -1, false, this); }, -1, false, this);
} }