Added webxr exit button
This commit is contained in:
parent
5ce0c9ce4f
commit
9d5234b629
@ -3,14 +3,14 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport"/>
|
||||
<meta content="An immersive vr diagramming experience based using webxr version 0.0.8-14 (2024-07-03T13:09:05.707Z) 4fdcc9694d3614be538e425110d1ab50cd20b302"
|
||||
<meta content="An immersive vr diagramming experience based using webxr version 0.0.8-14 (2024-12-29Z)"
|
||||
name="description">
|
||||
<meta content="width=device-width, initial-scale=1, height=device-height" name="viewport">
|
||||
<!--<link href="/styles.css" rel="stylesheet"> -->
|
||||
<link href="/assets/dasfad/favicon-32x32.png" rel="icon" sizes="32x32" type="image/png">
|
||||
<link href="/assets/dasfad/favicon-16x16.png" rel="icon" sizes="16x16" type="image/png">
|
||||
<link href="/assets/dasfad/favicon-96x96.png" rel="icon" sizes="96x96" type="image/png">
|
||||
<title>Deep Diagram</title>
|
||||
<title>DASFAD</title>
|
||||
<!-- <link as="script" href="/newRelic.js" rel="preload">
|
||||
<script defer src="/newRelic.js"></script> -->
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@ import {DiagramManager} from "../../diagram/diagramManager";
|
||||
import {DiagramObject} from "../../diagram/diagramObject";
|
||||
import log from "loglevel";
|
||||
import {vectoxys} from "../../diagram/functions/vectorConversion";
|
||||
import {DiagramEntityType} from "../../diagram/types/diagramEntity";
|
||||
|
||||
export function grabAndClone(diagramManager: DiagramManager, mesh: AbstractMesh, parent: AbstractMesh):
|
||||
DiagramObject {
|
||||
@ -23,7 +24,8 @@ export function grabAndClone(diagramManager: DiagramManager, mesh: AbstractMesh,
|
||||
color: mesh.metadata.color,
|
||||
position: vectoxys(mesh.absolutePosition),
|
||||
rotation: vectoxys(mesh.absoluteRotationQuaternion.toEulerAngles()),
|
||||
scale: vectoxys(mesh.scaling)
|
||||
scale: vectoxys(mesh.scaling),
|
||||
type: DiagramEntityType.ENTITY
|
||||
|
||||
}
|
||||
const obj = new DiagramObject(parent.getScene(),
|
||||
|
||||
@ -8,6 +8,7 @@ import {DefaultScene} from "../defaultScene";
|
||||
import {ControllerEvent} from "./types/controllerEvent";
|
||||
import {ControllerEventType} from "./types/controllerEventType";
|
||||
import {controllerObservable} from "./controllers";
|
||||
import {Button} from "../objects/Button";
|
||||
|
||||
const RIGHT = "right";
|
||||
const LEFT = "left";
|
||||
@ -44,6 +45,27 @@ export class Rigplatform {
|
||||
|
||||
this._xr = xr;
|
||||
this.rigMesh = buildRig(xr);
|
||||
this._xr.baseExperience.onStateChangedObservable.add((state) => {
|
||||
if (state == 2) {
|
||||
const button = Button.CreateButton("exitXr", "exitXr", this._scene, {});
|
||||
button.transform.position.z = 1;
|
||||
button.transform.rotation.y = Math.PI;
|
||||
button.transform.position.y = 1.2;
|
||||
button.transform.scaling = new Vector3(.1, .1, .1);
|
||||
button.transform.parent = this.rigMesh;
|
||||
button.onPointerObservable.add((evt) => {
|
||||
console.log(evt);
|
||||
console.log(evt.sourceEvent.type);
|
||||
if (evt.sourceEvent.type == 'pointerdown') {
|
||||
xr.baseExperience.exitXRAsync();
|
||||
}
|
||||
//xr.baseExperience.exitXRAsync();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
this._fixRotation();
|
||||
this._initializeControllers();
|
||||
this._registerVelocityObserver();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import {AbstractActionManager, AbstractMesh, ActionManager, Observable, Scene} from "@babylonjs/core";
|
||||
import {DiagramEntity, DiagramEvent, DiagramEventType} from "./types/diagramEntity";
|
||||
import {DiagramEntity, DiagramEntityType, DiagramEvent, DiagramEventType} from "./types/diagramEntity";
|
||||
import log from "loglevel";
|
||||
|
||||
import {AppConfig} from "../util/appConfig";
|
||||
@ -33,7 +33,7 @@ export class DiagramManager {
|
||||
this._me = getMe();
|
||||
this._scene = DefaultScene.Scene;
|
||||
this._config = new AppConfig();
|
||||
this._diagramMenuManager = new DiagramMenuManager(this.onDiagramEventObservable, controllerObservable, this._config, readyObservable);
|
||||
this._diagramMenuManager = new DiagramMenuManager(this.onDiagramEventObservable, controllerObservable, readyObservable);
|
||||
this._diagramEntityActionManager = buildEntityActionManager(controllerObservable);
|
||||
this.onDiagramEventObservable.add(this.onDiagramEvent, DiagramEventObserverMask.FROM_DB, true, this);
|
||||
this.onUserEventObservable.add((user) => {
|
||||
@ -79,7 +79,7 @@ export class DiagramManager {
|
||||
template: '#image-template',
|
||||
image: event.detail.data,
|
||||
text: event.detail.name,
|
||||
type: 'entity',
|
||||
type: DiagramEntityType.ENTITY,
|
||||
position: {x: 0, y: 1.6, z: 0},
|
||||
rotation: {x: 0, y: Math.PI, z: 0},
|
||||
scale: {x: 1, y: 1, z: 1},
|
||||
@ -97,7 +97,6 @@ export class DiagramManager {
|
||||
|
||||
});
|
||||
this._logger.debug("DiagramManager constructed");
|
||||
|
||||
}
|
||||
|
||||
public get actionManager(): AbstractActionManager {
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
import {DiagramEvent, DiagramEventType} from "./types/diagramEntity";
|
||||
import {DiagramEntityType, DiagramEvent, DiagramEventType} from "./types/diagramEntity";
|
||||
import {AbstractMesh, ActionEvent, Observable, Scene, Vector3, WebXRInputSource} from "@babylonjs/core";
|
||||
import {InputTextView} from "../information/inputTextView";
|
||||
import {DefaultScene} from "../defaultScene";
|
||||
import log from "loglevel";
|
||||
import {Toolbox} from "../toolbox/toolbox";
|
||||
import {ClickMenu} from "../menus/clickMenu";
|
||||
import {ConfigMenu} from "../menus/configMenu";
|
||||
import {AppConfig} from "../util/appConfig";
|
||||
import {DiagramEventObserverMask} from "./types/diagramEventObserverMask";
|
||||
import {ConnectionPreview} from "../menus/connectionPreview";
|
||||
import {ScaleMenu2} from "../menus/ScaleMenu2";
|
||||
@ -19,7 +17,6 @@ import {ControllerEventType} from "../controllers/types/controllerEventType";
|
||||
export class DiagramMenuManager {
|
||||
public readonly toolbox: Toolbox;
|
||||
public readonly scaleMenu: ScaleMenu2;
|
||||
public readonly configMenu: ConfigMenu;
|
||||
private readonly _notifier: Observable<DiagramEvent>;
|
||||
private readonly _inputTextView: InputTextView;
|
||||
private _groupMenu: GroupMenu;
|
||||
@ -27,22 +24,27 @@ export class DiagramMenuManager {
|
||||
private _logger = log.getLogger('DiagramMenuManager');
|
||||
private _connectionPreview: ConnectionPreview;
|
||||
|
||||
constructor(notifier: Observable<DiagramEvent>, controllerObservable: Observable<ControllerEvent>, config: AppConfig, readyObservable: Observable<boolean>) {
|
||||
constructor(notifier: Observable<DiagramEvent>, controllerObservable: Observable<ControllerEvent>, readyObservable: Observable<boolean>) {
|
||||
this._scene = DefaultScene.Scene;
|
||||
this._notifier = notifier;
|
||||
this._inputTextView = new InputTextView(controllerObservable);
|
||||
this.configMenu = new ConfigMenu(config);
|
||||
//this.configMenu = new ConfigMenu(config);
|
||||
|
||||
this._inputTextView.onTextObservable.add((evt) => {
|
||||
const event = {type: DiagramEventType.MODIFY, entity: {id: evt.id, text: evt.text}}
|
||||
const event = {
|
||||
type: DiagramEventType.MODIFY,
|
||||
entity: {id: evt.id, text: evt.text, type: DiagramEntityType.ENTITY}
|
||||
}
|
||||
this._notifier.notifyObservers(event, DiagramEventObserverMask.FROM_DB);
|
||||
});
|
||||
this.toolbox = new Toolbox(readyObservable);
|
||||
|
||||
|
||||
this.scaleMenu = new ScaleMenu2(this._notifier);
|
||||
if (viewOnly()) {
|
||||
this.toolbox.handleMesh.setEnabled(false);
|
||||
//this.scaleMenu.handleMesh.setEnabled(false)
|
||||
this.configMenu.handleTransformNode.setEnabled(false);
|
||||
// this.configMenu.handleTransformNode.setEnabled(false);
|
||||
}
|
||||
controllerObservable.add((event: ControllerEvent) => {
|
||||
if (event.type == ControllerEventType.B_BUTTON) {
|
||||
@ -64,9 +66,9 @@ export class DiagramMenuManager {
|
||||
this._inputTextView.handleMesh.position.y = localCamera.y - .2;
|
||||
}
|
||||
const configY = this._inputTextView.handleMesh.absolutePosition.y;
|
||||
if (configY > (cameraPos.y - .2)) {
|
||||
/*if (configY > (cameraPos.y - .2)) {
|
||||
this.configMenu.handleTransformNode.position.y = localCamera.y - .2;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -94,7 +96,10 @@ export class DiagramMenuManager {
|
||||
|
||||
switch (evt.source.id) {
|
||||
case "remove":
|
||||
this.notifyAll({type: DiagramEventType.REMOVE, entity: {id: clickMenu.mesh.id}});
|
||||
this.notifyAll({
|
||||
type: DiagramEventType.REMOVE,
|
||||
entity: {id: clickMenu.mesh.id, type: DiagramEntityType.ENTITY}
|
||||
});
|
||||
break;
|
||||
case "label":
|
||||
this.editText(clickMenu.mesh);
|
||||
|
||||
@ -12,7 +12,7 @@ import {
|
||||
TransformNode,
|
||||
Vector3
|
||||
} from "@babylonjs/core";
|
||||
import {DiagramEntity, DiagramEvent, DiagramEventType} from "./types/diagramEntity";
|
||||
import {DiagramEntity, DiagramEntityType, DiagramEvent, DiagramEventType} from "./types/diagramEntity";
|
||||
import {buildMeshFromDiagramEntity} from "./functions/buildMeshFromDiagramEntity";
|
||||
import {toDiagramEntity} from "./functions/toDiagramEntity";
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
@ -29,6 +29,7 @@ type DiagramObjectOptionsType = {
|
||||
|
||||
export class DiagramObject {
|
||||
private readonly _logger: Logger = log.getLogger('DiagramObject');
|
||||
private _group: TransformNode;
|
||||
private _scene: Scene;
|
||||
public grabbed: boolean = false;
|
||||
private _from: string;
|
||||
@ -177,7 +178,7 @@ export class DiagramObject {
|
||||
position: oldEntity.position,
|
||||
rotation: oldEntity.rotation,
|
||||
scale: oldEntity.scale,
|
||||
type: 'entity',
|
||||
type: DiagramEntityType.ENTITY,
|
||||
image: oldEntity.image,
|
||||
template: oldEntity.template,
|
||||
color: oldEntity.color,
|
||||
|
||||
@ -13,7 +13,8 @@ export enum DiagramEventType {
|
||||
}
|
||||
|
||||
export enum DiagramEntityType {
|
||||
USER = "user"
|
||||
USER = "user",
|
||||
ENTITY = "entity",
|
||||
}
|
||||
|
||||
export enum DiagramEventMask {
|
||||
@ -38,8 +39,8 @@ export type DiagramEvent = {
|
||||
entity?: DiagramEntity;
|
||||
oldColor?: Color3;
|
||||
newColor?: Color3;
|
||||
|
||||
}
|
||||
|
||||
export type DiagramEntity = {
|
||||
color?: string;
|
||||
id?: string;
|
||||
@ -50,7 +51,7 @@ export type DiagramEntity = {
|
||||
position?: { x: number, y: number, z: number };
|
||||
rotation?: { x: number, y: number, z: number };
|
||||
template?: string;
|
||||
type: 'entity'
|
||||
type: DiagramEntityType;
|
||||
text?: string;
|
||||
scale?: { x: number, y: number, z: number };
|
||||
parent?: string;
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
import {DEFAULT_DB_NAME} from "../../util/constants";
|
||||
import {DIRECTORY_DB} from "../../util/constants";
|
||||
|
||||
export const db = new PouchDB(DEFAULT_DB_NAME);
|
||||
export const db = new PouchDB(DIRECTORY_DB);
|
||||
@ -57,6 +57,16 @@ export class PouchData {
|
||||
diagramManager.onDiagramEventObservable.notifyObservers(
|
||||
{type: DiagramEventType.REMOVE, entity: entity}, DiagramEventObserverMask.FROM_DB);
|
||||
});
|
||||
this._db.allDocs({include_docs: true}).then((docs) => {
|
||||
docs.rows.forEach((row) => {
|
||||
if (row.doc.id != 'metadata') {
|
||||
diagramManager.onDiagramEventObservable.notifyObservers({
|
||||
type: DiagramEventType.ADD,
|
||||
entity: row.doc
|
||||
}, DiagramEventObserverMask.FROM_DB);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async remove(id: string) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import PouchDB from 'pouchdb';
|
||||
import {DiagramEntity, DiagramEventType} from "../../diagram/types/diagramEntity";
|
||||
import {DiagramEntity, DiagramEntityType, DiagramEventType} from "../../diagram/types/diagramEntity";
|
||||
import {Observable} from "@babylonjs/core";
|
||||
import axios from "axios";
|
||||
import {DiagramManager} from "../../diagram/diagramManager";
|
||||
@ -93,7 +93,7 @@ export class PouchdbPersistenceManager {
|
||||
|
||||
this.onDBEntityUpdateObservable.add((evt) => {
|
||||
this._logger.debug(evt);
|
||||
if (evt.id != 'metadata' && evt.type = 'user') {
|
||||
if (evt.id != 'metadata' && evt?.type == DiagramEntityType.USER) {
|
||||
diagramManager.onDiagramEventObservable.notifyObservers({
|
||||
type: DiagramEventType.ADD,
|
||||
entity: evt
|
||||
@ -263,7 +263,7 @@ export class PouchdbPersistenceManager {
|
||||
let sync = false;
|
||||
let current = getPath();
|
||||
if (current && current != 'localdb') {
|
||||
//sync = true;
|
||||
sync = true;
|
||||
} else {
|
||||
current = 'localdb';
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import log from "loglevel";
|
||||
import {DiagramEntity} from "../../diagram/types/diagramEntity";
|
||||
import {DiagramEntity, DiagramEntityType} from "../../diagram/types/diagramEntity";
|
||||
import {Observable} from "@babylonjs/core";
|
||||
import {Encryption} from "../encryption";
|
||||
import {DiagramEventObserverMask} from "../../diagram/types/diagramEventObserverMask";
|
||||
@ -19,7 +19,7 @@ export async function syncDoc(info: any, onDBRemoveObservable: Observable<Diagra
|
||||
salt = doc.encrypted.salt
|
||||
}
|
||||
const decrypted = await encryption.decryptToObject(doc.encrypted.encrypted, doc.encrypted.iv);
|
||||
if (decrypted.type == 'user') {
|
||||
if (decrypted.type == DiagramEntityType.USER) {
|
||||
//onUserObservable.notifyObservers(doc, -1);
|
||||
} else {
|
||||
logger.debug(decrypted);
|
||||
@ -27,7 +27,8 @@ export async function syncDoc(info: any, onDBRemoveObservable: Observable<Diagra
|
||||
logger.debug('Delete', doc);
|
||||
onDBRemoveObservable.notifyObservers({
|
||||
id: doc._id,
|
||||
template: decrypted.template
|
||||
template: decrypted.template,
|
||||
type: doc.type
|
||||
}, DiagramEventObserverMask.FROM_DB);
|
||||
} else {
|
||||
onDBUpdateObservable.notifyObservers(decrypted, DiagramEventObserverMask.FROM_DB);
|
||||
@ -42,7 +43,8 @@ export async function syncDoc(info: any, onDBRemoveObservable: Observable<Diagra
|
||||
logger.debug('Delete', doc);
|
||||
onDBRemoveObservable.notifyObservers({
|
||||
id: doc._id,
|
||||
template: doc.template
|
||||
template: doc.template,
|
||||
type: doc.type
|
||||
}, DiagramEventObserverMask.FROM_DB);
|
||||
} else {
|
||||
if (doc.template) {
|
||||
|
||||
@ -33,6 +33,7 @@ export class ConfigMenu {
|
||||
this._handle = new Handle(this.baseTransform, 'Configuration');
|
||||
this.config = config;
|
||||
this.buildMenu();
|
||||
|
||||
}
|
||||
|
||||
public get handleTransformNode(): TransformNode {
|
||||
|
||||
@ -14,7 +14,7 @@ import {
|
||||
WebXRInputSource
|
||||
} from "@babylonjs/core";
|
||||
import {DefaultScene} from "../defaultScene";
|
||||
import {DiagramEvent, DiagramEventType, DiagramTemplates} from "../diagram/types/diagramEntity";
|
||||
import {DiagramEntityType, DiagramEvent, DiagramEventType, DiagramTemplates} from "../diagram/types/diagramEntity";
|
||||
import {DiagramEventObserverMask} from "../diagram/types/diagramEventObserverMask";
|
||||
import {AnimatedLineTexture} from "../util/animatedLineTexture";
|
||||
|
||||
@ -101,7 +101,7 @@ export class ConnectionPreview {
|
||||
entity: {
|
||||
from: this._fromId,
|
||||
to: mesh.id,
|
||||
type: 'entity',
|
||||
type: DiagramEntityType.ENTITY,
|
||||
template: DiagramTemplates.CONNECTION,
|
||||
color: '#000000'
|
||||
}
|
||||
|
||||
@ -7,8 +7,8 @@ export class InputFile {
|
||||
this.fileInput = document.createElement('input');
|
||||
this.fileInput.type = 'file';
|
||||
this.fileInput.accept = 'application/json';
|
||||
this.fileInput.onchange = (event) => {
|
||||
this.file = event.target.files[0];
|
||||
this.fileInput.onchange = (event: InputEvent) => {
|
||||
this.file = (event.target as HTMLInputElement).files[0];
|
||||
};
|
||||
//document.body.appendChild(this.fileInput);
|
||||
this.fileInput.click();
|
||||
|
||||
@ -4,18 +4,16 @@ import React from "react";
|
||||
import {theme} from "./theme";
|
||||
import {Provider} from "use-pouchdb";
|
||||
import PouchDB from 'pouchdb';
|
||||
import {DEFAULT_DB_NAME} from "../util/constants";
|
||||
import {DIRECTORY_DB} from "../util/constants";
|
||||
|
||||
|
||||
const db = new PouchDB(DEFAULT_DB_NAME);
|
||||
const db = new PouchDB(DIRECTORY_DB);
|
||||
export default function VrTemplate(props: { children: React.ReactNode }) {
|
||||
return (
|
||||
<Provider pouchdb={db}>
|
||||
<MantineProvider defaultColorScheme="dark" theme={theme}>
|
||||
<Container fluid={true}>
|
||||
|
||||
{props.children}
|
||||
|
||||
</Container>
|
||||
</MantineProvider>
|
||||
</Provider>
|
||||
|
||||
@ -1 +1 @@
|
||||
export const DEFAULT_DB_NAME = "mydb";
|
||||
export const DIRECTORY_DB = "local-directory";
|
||||
@ -19,14 +19,16 @@ import {CustomPhysics} from "./customPhysics";
|
||||
import {AppConfig} from "./appConfig";
|
||||
import {GridMaterial} from "@babylonjs/materials";
|
||||
import {DefaultScene} from "../defaultScene";
|
||||
import log from "loglevel";
|
||||
|
||||
|
||||
export class CustomEnvironment {
|
||||
private readonly scene: Scene;
|
||||
private readonly name: string;
|
||||
private readonly _groundMeshObservable: Observable<GroundMesh> = new Observable<GroundMesh>();
|
||||
|
||||
private readonly _logger = log.getLogger('CustomEnvironment');
|
||||
constructor(name: string = "default", config: AppConfig) {
|
||||
this._logger.debug('CustomEnvironment constructor', config);
|
||||
this.scene = DefaultScene.Scene;
|
||||
this.name = name;
|
||||
|
||||
@ -35,7 +37,7 @@ export class CustomEnvironment {
|
||||
light.groundColor = new Color3(0, 0, 0);
|
||||
light.diffuse = new Color3(1, 1, 1);
|
||||
light.intensity = .8;
|
||||
const physics = new CustomPhysics(this.scene, config);
|
||||
const physics = new CustomPhysics(this.scene);
|
||||
physics
|
||||
.initializeAsync()
|
||||
.then(() => {
|
||||
|
||||
@ -31,7 +31,7 @@ export async function groundMeshObserver(ground: AbstractMesh,
|
||||
enablePointerSelectionOnAllControllers: true
|
||||
}
|
||||
});
|
||||
window.addEventListener('enterXr', async (e: CustomEvent) => {
|
||||
window.addEventListener('enterXr', async () => {
|
||||
await xr.baseExperience.enterXRAsync('immersive-vr', 'local-floor');
|
||||
logger.debug("Entering XR Experience");
|
||||
})
|
||||
|
||||
@ -15,7 +15,6 @@ import {CustomEnvironment} from "./util/customEnvironment";
|
||||
import {Spinner} from "./objects/spinner";
|
||||
import {addSceneInspector} from "./util/functions/sceneInspector";
|
||||
import {groundMeshObserver} from "./util/functions/groundMeshObserver";
|
||||
import {exportGltf} from "./util/functions/exportGltf";
|
||||
import {DefaultScene} from "./defaultScene";
|
||||
import {Introduction} from "./tutorial/introduction";
|
||||
import {PouchData} from "./integration/database/pouchData";
|
||||
@ -23,6 +22,7 @@ import {PouchData} from "./integration/database/pouchData";
|
||||
const webGpu = false;
|
||||
|
||||
log.setLevel('error', false);
|
||||
log.getLogger('PouchdbPersistenceManager').setLevel('debug', false);
|
||||
export default class VrApp {
|
||||
//preTasks = [havokModule];
|
||||
private logger: Logger = log.getLogger('App');
|
||||
@ -58,14 +58,14 @@ export default class VrApp {
|
||||
});
|
||||
initEnvironment(diagramManager, spinner);
|
||||
addSceneInspector();
|
||||
const el = document.querySelector('#download');
|
||||
/*const el = document.querySelector('#download');
|
||||
if (el) {
|
||||
el.addEventListener('click', () => {
|
||||
exportGltf();
|
||||
})
|
||||
} else {
|
||||
this.logger.error('Download button not found');
|
||||
}
|
||||
}*/
|
||||
if (!localStorage.getItem('tutorialCompleted')) {
|
||||
this.logger.info('Starting tutorial');
|
||||
const intro = new Introduction();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user