Refactored scene to use DefaultScene.

This commit is contained in:
Michael Mainguy 2024-04-16 11:14:32 -05:00
parent d7e812d253
commit a1248a2e34
16 changed files with 89 additions and 66 deletions

View File

@ -26,6 +26,7 @@ import {motionControllerObserver} from "./functions/motionControllerObserver";
import {handleWasGrabbed} from "./functions/handleWasGrabbed"; import {handleWasGrabbed} from "./functions/handleWasGrabbed";
import {buildDrop} from "./functions/buildDrop"; import {buildDrop} from "./functions/buildDrop";
import {pointable} from "./functions/pointable"; import {pointable} from "./functions/pointable";
import {DefaultScene} from "../defaultScene";
const CLICK_TIME = 300; const CLICK_TIME = 300;
export class Base { export class Base {
@ -54,7 +55,7 @@ export class Base {
this.logger.setLevel(this.logger.levels.DEBUG); this.logger.setLevel(this.logger.levels.DEBUG);
this.controller = controller; this.controller = controller;
this.controllers = diagramManager.controllers; this.controllers = diagramManager.controllers;
this.scene = diagramManager.scene; this.scene = DefaultScene.scene;
this.xr = xr; this.xr = xr;
this.diagramManager = diagramManager; this.diagramManager = diagramManager;
this.scene.onBeforeRenderObservable.add(beforeRenderObserver, -1, false, this); this.scene.onBeforeRenderObservable.add(beforeRenderObserver, -1, false, this);

View File

@ -1,11 +1,13 @@
import {HavokPlugin} from "@babylonjs/core"; import {HavokPlugin} from "@babylonjs/core";
import {DefaultScene} from "../../defaultScene";
export function beforeRenderObserver() { export function beforeRenderObserver() {
if (this?.grabbedMesh?.physicsBody) { if (this?.grabbedMesh?.physicsBody) {
const hk = (this.scene.getPhysicsEngine().getPhysicsPlugin() as HavokPlugin); const scene = DefaultScene.scene;
const hk = (scene.getPhysicsEngine().getPhysicsPlugin() as HavokPlugin);
this.lastPosition = this?.grabbedMesh?.physicsBody?.transformNode.absolutePosition.clone(); this.lastPosition = this?.grabbedMesh?.physicsBody?.transformNode.absolutePosition.clone();
if (this.grabbedMeshParentId) { if (this.grabbedMeshParentId) {
const parent = this.scene.getTransformNodeById(this.grabbedMeshParentId); const parent = scene.getTransformNodeById(this.grabbedMeshParentId);
if (parent) { if (parent) {
hk.setPhysicsBodyTransformation(this.grabbedMesh.physicsBody, parent); hk.setPhysicsBodyTransformation(this.grabbedMesh.physicsBody, parent);
hk.sync(this.grabbedMesh.physicsBody); hk.sync(this.grabbedMesh.physicsBody);

View File

@ -11,13 +11,14 @@ import {ControllerEventType} from "./controllers";
import log from "loglevel"; import log from "loglevel";
import {DiagramManager} from "../diagram/diagramManager"; import {DiagramManager} from "../diagram/diagramManager";
import {RoundButton} from "../objects/roundButton"; import {RoundButton} from "../objects/roundButton";
import {DefaultScene} from "../defaultScene";
const logger = log.getLogger('Left'); const logger = log.getLogger('Left');
export class Left extends Base { export class Left extends Base {
constructor(controller: constructor(controller:
WebXRInputSource, xr: WebXRDefaultExperience, diagramManager: DiagramManager) { WebXRInputSource, xr: WebXRDefaultExperience, diagramManager: DiagramManager) {
super(controller, xr, diagramManager); super(controller, xr, diagramManager);
const scene = diagramManager.scene; const scene = DefaultScene.scene;
this.controller.onMotionControllerInitObservable.add((init) => { this.controller.onMotionControllerInitObservable.add((init) => {
if (init.components['xr-standard-thumbstick']) { if (init.components['xr-standard-thumbstick']) {
init.components['xr-standard-thumbstick'] init.components['xr-standard-thumbstick']

View File

@ -12,6 +12,7 @@ import {ControllerEventType} from "./controllers";
import {DiagramManager} from "../diagram/diagramManager"; import {DiagramManager} from "../diagram/diagramManager";
import {RoundButton} from "../objects/roundButton"; import {RoundButton} from "../objects/roundButton";
import log from "loglevel"; import log from "loglevel";
import {DefaultScene} from "../defaultScene";
const logger = log.getLogger("Right"); const logger = log.getLogger("Right");
export class Right extends Base { export class Right extends Base {
@ -41,7 +42,7 @@ export class Right extends Base {
) { ) {
super(controller, xr, diagramManager); super(controller, xr, diagramManager);
const scene = diagramManager.scene; const scene = DefaultScene.scene;
this.controller.onMotionControllerInitObservable.add((init) => { this.controller.onMotionControllerInitObservable.add((init) => {
this.initTrigger(init.components['xr-standard-trigger']); this.initTrigger(init.components['xr-standard-trigger']);

View File

@ -5,6 +5,7 @@ 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";
const RIGHT = "right"; const RIGHT = "right";
const LEFT = "left"; const LEFT = "left";
@ -39,7 +40,7 @@ export class Rigplatform {
xr: WebXRDefaultExperience, xr: WebXRDefaultExperience,
diagramManager: DiagramManager diagramManager: DiagramManager
) { ) {
this.scene = diagramManager.scene; this.scene = DefaultScene.scene;
this.diagramManager = diagramManager; this.diagramManager = diagramManager;
this.controllers = diagramManager.controllers; this.controllers = diagramManager.controllers;
this.xr = xr; this.xr = xr;

13
src/defaultScene.ts Normal file
View File

@ -0,0 +1,13 @@
import {Scene} from "@babylonjs/core";
export class DefaultScene {
private static _scene: Scene;
public static get scene(): Scene {
return DefaultScene._scene;
}
static create(scene: Scene) {
DefaultScene._scene = scene;
}
}

View File

@ -4,7 +4,6 @@ import log from "loglevel";
import {Controllers} from "../controllers/controllers"; import {Controllers} from "../controllers/controllers";
import {AppConfig} from "../util/appConfig"; import {AppConfig} from "../util/appConfig";
import {Toolbox} from "../toolbox/toolbox"; import {Toolbox} from "../toolbox/toolbox";
import {PresentationManager} from "./presentationManager";
import {diagramEventHandler} from "./functions/diagramEventHandler"; import {diagramEventHandler} from "./functions/diagramEventHandler";
import {deepCopy} from "../util/functions/deepCopy"; import {deepCopy} from "../util/functions/deepCopy";
import {applyPhysics} from "./functions/diagramShapePhysics"; import {applyPhysics} from "./functions/diagramShapePhysics";
@ -14,13 +13,13 @@ import {v4 as uuidv4} from 'uuid';
import {buildEntityActionManager} from "./functions/buildEntityActionManager"; import {buildEntityActionManager} from "./functions/buildEntityActionManager";
import {isDiagramEntity} from "./functions/isDiagramEntity"; import {isDiagramEntity} from "./functions/isDiagramEntity";
import {InputTextView} from "../information/inputTextView"; import {InputTextView} from "../information/inputTextView";
import {DefaultScene} from "../defaultScene";
export class DiagramManager { export class DiagramManager {
public readonly _config: AppConfig; public readonly _config: AppConfig;
private readonly _controllers: Controllers; private readonly _controllers: Controllers;
private readonly diagramEntityActionManager: ActionManager; private readonly diagramEntityActionManager: ActionManager;
private presentationManager: PresentationManager;
private readonly inputTextView: InputTextView; private readonly inputTextView: InputTextView;
public readonly onDiagramEventObservable: Observable<DiagramEvent> = new Observable(); public readonly onDiagramEventObservable: Observable<DiagramEvent> = new Observable();
@ -29,12 +28,13 @@ export class DiagramManager {
private readonly _scene: Scene; private readonly _scene: Scene;
constructor(scene: Scene) { constructor() {
this._scene = DefaultScene.scene;
this._config = new AppConfig(); this._config = new AppConfig();
this._controllers = new Controllers(); this._controllers = new Controllers();
this.inputTextView = new InputTextView(scene, this._controllers); this.inputTextView = new InputTextView(this._controllers);
this.inputTextView.onTextObservable.add((evt) => { this.inputTextView.onTextObservable.add((evt) => {
const mesh = scene.getMeshById(evt.id); const mesh = this._scene.getMeshById(evt.id);
if (mesh) { if (mesh) {
const entity = toDiagramEntity(mesh); const entity = toDiagramEntity(mesh);
entity.text = evt.text; entity.text = evt.text;
@ -47,11 +47,9 @@ export class DiagramManager {
} }
}); });
this.toolbox = new Toolbox();
this._scene = scene; //this.presentationManager = new PresentationManager(this._scene);
this.toolbox = new Toolbox(scene); this.diagramEntityActionManager = buildEntityActionManager(this._controllers);
this.presentationManager = new PresentationManager(this._scene);
this.diagramEntityActionManager = buildEntityActionManager(this._scene, this._controllers);
if (this.onDiagramEventObservable.hasObservers()) { if (this.onDiagramEventObservable.hasObservers()) {
this.logger.warn("onDiagramEventObservable already has Observers, you should be careful"); this.logger.warn("onDiagramEventObservable already has Observers, you should be careful");
@ -66,10 +64,10 @@ export class DiagramManager {
this.onDiagramEventObservable.add(this.onDiagramEvent, 1, true, this); this.onDiagramEventObservable.add(this.onDiagramEvent, 1, true, this);
this.logger.debug("DiagramManager constructed"); this.logger.debug("DiagramManager constructed");
scene.onMeshRemovedObservable.add((mesh) => { this._scene.onMeshRemovedObservable.add((mesh) => {
if (isDiagramEntity(mesh)) { if (isDiagramEntity(mesh)) {
if (mesh.metadata.template != '#connection-template') { if (mesh.metadata.template != '#connection-template') {
scene.meshes.forEach((m) => { this._scene.meshes.forEach((m) => {
if (m?.metadata?.to == mesh.id || m?.metadata?.from == mesh.id) { if (m?.metadata?.to == mesh.id || m?.metadata?.from == mesh.id) {
this.logger.debug("removing connection", m.id); this.logger.debug("removing connection", m.id);
this.onDiagramEventObservable.notifyObservers({ this.onDiagramEventObservable.notifyObservers({

View File

@ -1,10 +1,11 @@
import {ActionManager, ExecuteCodeAction, Scene} from "@babylonjs/core"; import {ActionManager, ExecuteCodeAction} from "@babylonjs/core";
import {ControllerEventType, Controllers} from "../../controllers/controllers"; import {ControllerEventType, Controllers} from "../../controllers/controllers";
import log from "loglevel"; import log from "loglevel";
import {DefaultScene} from "../../defaultScene";
export function buildEntityActionManager(scene: Scene, controllers: Controllers) { export function buildEntityActionManager(controllers: Controllers) {
const logger = log.getLogger('buildEntityActionManager'); const logger = log.getLogger('buildEntityActionManager');
const actionManager = new ActionManager(scene); const actionManager = new ActionManager(DefaultScene.scene);
/*actionManager.registerAction( /*actionManager.registerAction(
new PlaySoundAction(ActionManager.OnPointerOverTrigger, sounds.tick));*/ new PlaySoundAction(ActionManager.OnPointerOverTrigger, sounds.tick));*/
actionManager.registerAction( actionManager.registerAction(

View File

@ -3,6 +3,7 @@ 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 {ControllerEventType, Controllers} from "../controllers/controllers";
import {Handle} from "../objects/handle"; import {Handle} from "../objects/handle";
import {DefaultScene} from "../defaultScene";
export type TextEvent = { export type TextEvent = {
id: string; id: string;
@ -21,9 +22,9 @@ export class InputTextView {
private diagramMesh: AbstractMesh; private diagramMesh: AbstractMesh;
private keyboard: VirtualKeyboard; private keyboard: VirtualKeyboard;
constructor(scene: Scene, controllers: Controllers) { constructor(controllers: Controllers) {
this.controllers = controllers; this.controllers = controllers;
this.scene = 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); this.handle = new Handle(this.inputMesh);

View File

@ -10,14 +10,15 @@ import {
StandardMaterial, StandardMaterial,
Texture Texture
} from "@babylonjs/core"; } from "@babylonjs/core";
import {DefaultScene} from "../defaultScene";
export class Spinner { export class Spinner {
private readonly scene: Scene; private readonly _scene: Scene;
private spinner: AbstractMesh; private spinner: AbstractMesh;
private particleSystem: ParticleSystem; private particleSystem: ParticleSystem;
constructor(scene: Scene) { constructor() {
this.scene = scene; this._scene = DefaultScene.scene;
this.build(); this.build();
} }
@ -32,9 +33,9 @@ export class Spinner {
} }
private build() { private build() {
const spinner: AbstractMesh = MeshBuilder.CreateSphere("spinner", {diameter: 2}, this.scene); const spinner: AbstractMesh = MeshBuilder.CreateSphere("spinner", {diameter: 2}, this._scene);
const material = new StandardMaterial("spinner", this.scene); const material = new StandardMaterial("spinner", this._scene);
const text = new DynamicTexture("spinner", {width: 1024, height: 1024}, this.scene, false); const text = new DynamicTexture("spinner", {width: 1024, height: 1024}, this._scene, false);
text.drawText("Please Wait", 250, 500, "bold 150px Segoe UI", "white", "transparent", true, true); text.drawText("Please Wait", 250, 500, "bold 150px Segoe UI", "white", "transparent", true, true);
spinner.rotation.z = Math.PI; spinner.rotation.z = Math.PI;
material.diffuseTexture = text; material.diffuseTexture = text;
@ -52,23 +53,23 @@ export class Spinner {
}); });
rotate.setKeys(keys); rotate.setKeys(keys);
spinner.animations.push(rotate); spinner.animations.push(rotate);
this.scene.beginAnimation(spinner, 0, 30, true); this._scene.beginAnimation(spinner, 0, 30, true);
material.alpha = .9; material.alpha = .9;
spinner.material = material; spinner.material = material;
let particleSystem; let particleSystem;
if (GPUParticleSystem.IsSupported) { if (GPUParticleSystem.IsSupported) {
particleSystem = new GPUParticleSystem("particles", {capacity: 100000}, this.scene); particleSystem = new GPUParticleSystem("particles", {capacity: 100000}, this._scene);
particleSystem.activeParticleCount = 2048; particleSystem.activeParticleCount = 2048;
} else { } else {
particleSystem = new ParticleSystem("particles", 2048, this.scene); particleSystem = new ParticleSystem("particles", 2048, this._scene);
} }
particleSystem.emitRate = 10; particleSystem.emitRate = 10;
const emitter = new SphereParticleEmitter(.9); const emitter = new SphereParticleEmitter(.9);
emitter.radiusRange = .2; emitter.radiusRange = .2;
particleSystem.particleEmitterType = emitter; particleSystem.particleEmitterType = emitter;
particleSystem.particleTexture = new Texture("/assets/textures/flare.png", this.scene); particleSystem.particleTexture = new Texture("/assets/textures/flare.png", this._scene);
particleSystem.minEmitPower = .1; particleSystem.minEmitPower = .1;

View File

@ -3,6 +3,7 @@ import {GUI3DManager, StackPanel3D,} from "@babylonjs/gui";
import {buildColor} from "./functions/buildColor"; import {buildColor} from "./functions/buildColor";
import log from "loglevel"; import log from "loglevel";
import {Handle} from "../objects/handle"; import {Handle} from "../objects/handle";
import {DefaultScene} from "../defaultScene";
const colors: string[] = [ const colors: string[] = [
"#222222", "#8b4513", "#006400", "#778899", "#222222", "#8b4513", "#006400", "#778899",
@ -26,10 +27,10 @@ export class Toolbox {
new Observable<{ oldColor: string; newColor: string }>() new Observable<{ oldColor: string; newColor: string }>()
private axes: AxesViewer; private axes: AxesViewer;
constructor(scene: Scene) { constructor() {
this.scene = scene; this.scene = DefaultScene.scene;
this.addPanel = new StackPanel3D(); this.addPanel = new StackPanel3D();
this.manager = new GUI3DManager(scene); this.manager = new GUI3DManager(this.scene);
this.manager.addControl(this.addPanel); this.manager.addControl(this.addPanel);
this.toolboxBaseNode = new TransformNode("toolbox", this.scene); this.toolboxBaseNode = new TransformNode("toolbox", this.scene);
this.handle = new Handle(this.toolboxBaseNode); this.handle = new Handle(this.toolboxBaseNode);

View File

@ -9,14 +9,14 @@ export class AppConfig {
this._currentConfig = { this._currentConfig = {
id: 1, id: 1,
gridSnap: .1, gridSnap: .1,
rotateSnap: 45, rotateSnap: 90,
createSnap: .1, createSnap: .1,
turnSnap: 22.5, turnSnap: 22.5,
newRelicKey: null, newRelicKey: null,
newRelicAccount: null, newRelicAccount: null,
physicsEnabled: false, physicsEnabled: false,
demoCompleted: false, demoCompleted: false,
flyMode: false flyMode: true
}; };
this.onConfigChangedObservable.add((config) => { this.onConfigChangedObservable.add((config) => {
this._currentConfig = config; this._currentConfig = config;

View File

@ -1,6 +1,7 @@
import {Scene} from "@babylonjs/core"; import {DefaultScene} from "../../defaultScene";
export function exportGltf(scene: Scene) { export function exportGltf() {
const scene = DefaultScene.scene;
import("@babylonjs/serializers").then((serializers) => { import("@babylonjs/serializers").then((serializers) => {
serializers.GLTF2Export.GLBAsync(scene, 'diagram.glb', { serializers.GLTF2Export.GLBAsync(scene, 'diagram.glb', {
shouldExportNode: function (node) { shouldExportNode: function (node) {

View File

@ -4,7 +4,7 @@ import {WebController} from "../../controllers/webController";
import {ConfigMenu} from "../../menus/configMenu"; import {ConfigMenu} from "../../menus/configMenu";
import {Rigplatform} from "../../controllers/rigplatform"; import {Rigplatform} from "../../controllers/rigplatform";
import {DiagramManager} from "../../diagram/diagramManager"; import {DiagramManager} from "../../diagram/diagramManager";
import {Spinner} from "../spinner"; import {Spinner} from "../../objects/spinner";
const logger = log.getLogger('groungMeshObserver'); const logger = log.getLogger('groungMeshObserver');

View File

@ -1,4 +1,7 @@
export function addSceneInspector(scene) { import {DefaultScene} from "../../defaultScene";
export function addSceneInspector() {
const scene = DefaultScene.scene;
window.addEventListener("keydown", (ev) => { window.addEventListener("keydown", (ev) => {
if (ev.key == "z") { if (ev.key == "z") {
//voiceManager.startRecording(); //voiceManager.startRecording();

View File

@ -4,45 +4,43 @@ import {DiagramManager} from "./diagram/diagramManager";
import log, {Logger} from "loglevel"; import log, {Logger} from "loglevel";
import {GamepadManager} from "./controllers/gamepadManager"; import {GamepadManager} from "./controllers/gamepadManager";
import {CustomEnvironment} from "./util/customEnvironment"; import {CustomEnvironment} from "./util/customEnvironment";
import {Spinner} from "./util/spinner"; import {Spinner} from "./objects/spinner";
import {PouchdbPersistenceManager} from "./integration/pouchdbPersistenceManager"; import {PouchdbPersistenceManager} from "./integration/pouchdbPersistenceManager";
import {addSceneInspector} from "./util/functions/sceneInspctor"; import {addSceneInspector} from "./util/functions/sceneInspctor";
import {groundMeshObserver} from "./util/functions/groundMeshObserver"; import {groundMeshObserver} from "./util/functions/groundMeshObserver";
import {MainMenu} from "./menus/mainMenu";
import {buildQuestLink} from "./util/functions/buildQuestLink"; import {buildQuestLink} from "./util/functions/buildQuestLink";
import {exportGltf} from "./util/functions/exportGltf"; import {exportGltf} from "./util/functions/exportGltf";
import {DefaultScene} from "./defaultScene";
export class VrApp { export class VrApp {
private scene: Scene;
private engine: Engine; private engine: Engine;
//preTasks = [havokModule]; //preTasks = [havokModule];
private logger: Logger = log.getLogger('App'); private logger: Logger = log.getLogger('App');
constructor() { constructor() {
//log.getLogger('App').setLevel('debug'); const canvas = (document.querySelector('#gameCanvas') as HTMLCanvasElement);
//log.getLogger('DiagramManager').setLevel('debug');
log.resetLevel();
log.setDefaultLevel('error');
const canvas = document.querySelector('#gameCanvas');
this.logger.debug('App', 'gameCanvas created');
}
public async initialize(canvas: HTMLCanvasElement) {
this.engine = new Engine(canvas, true); this.engine = new Engine(canvas, true);
this.engine.setHardwareScalingLevel(1 / window.devicePixelRatio); this.engine.setHardwareScalingLevel(1 / window.devicePixelRatio);
window.onresize = () => { window.onresize = () => {
this.engine.resize(); this.engine.resize();
} }
const scene = new Scene(this.engine); const scene = new Scene(this.engine);
this.scene = scene; scene.ambientColor = new Color3(.1, .1, .1);
this.scene.ambientColor = new Color3(.1, .1, .1); DefaultScene.create(scene);
const spinner = new Spinner(scene); log.resetLevel();
log.setDefaultLevel('error');
this.logger.debug('App', 'gameCanvas created');
}
public async initialize() {
const scene = DefaultScene.scene;
const spinner = new Spinner();
spinner.show(); spinner.show();
const diagramManager = new DiagramManager();
const diagramManager = new DiagramManager(scene);
const db = new PouchdbPersistenceManager(); const db = new PouchdbPersistenceManager();
db.setDiagramManager(diagramManager); db.setDiagramManager(diagramManager);
db.configObserver.add((newConfig) => { db.configObserver.add((newConfig) => {
@ -72,18 +70,18 @@ export class VrApp {
*/ */
addSceneInspector(scene); addSceneInspector();
const mainMenu = new MainMenu(scene); //const mainMenu = new MainMenu(scene);
const el = document.querySelector('#download'); const el = document.querySelector('#download');
if (el) { if (el) {
el.addEventListener('click', () => { el.addEventListener('click', () => {
exportGltf(scene); exportGltf();
}) })
} }
this.logger.info('keydown event listener added, use Ctrl+Shift+Alt+I to toggle debug layer'); this.logger.info('keydown event listener added, use Ctrl+Shift+Alt+I to toggle debug layer');
let i = 0; let i = 0;
this.engine.runRenderLoop(() => { this.engine.runRenderLoop(() => {
this.scene.render(); scene.render();
if (i++ % 60 == 0) { if (i++ % 60 == 0) {
} }
@ -98,8 +96,8 @@ export class VrApp {
} }
const vrApp = new VrApp(); const vrApp = new VrApp();
const canvas = (document.querySelector('#gameCanvas') as HTMLCanvasElement);
vrApp.initialize(canvas).then(() => { vrApp.initialize().then(() => {
buildQuestLink(); buildQuestLink();
}); });