diff --git a/index.html b/index.html
index d000dc6..6776f9f 100644
--- a/index.html
+++ b/index.html
@@ -40,6 +40,7 @@
*/
+
diff --git a/package-lock.json b/package-lock.json
index 1d70bcc..609666c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -20,11 +20,14 @@
"@picovoice/eagle-web": "^1.0.0",
"@picovoice/web-voice-processor": "^4.0.9",
"@typed-mxgraph/typed-mxgraph": "^1.0.8",
+ "@types/dom-to-image": "^2.6.7",
"@types/file-saver": "^2.0.6",
"@types/node": "^18.14.0",
"@types/react": "^18.2.72",
"@types/react-dom": "^18.2.22",
"axios": "^1.6.8",
+ "babylon-html": "0.0.1",
+ "dom-to-image-more": "^3.3.0",
"earcut": "^2.2.4",
"events": "^3.3.0",
"file-saver": "^2.0.5",
@@ -41,8 +44,9 @@
"uuid": "^9.0.1"
},
"devDependencies": {
+ "@types/dom-to-image": "^2.6.7",
"typescript": "^4.9.5",
- "vite": "^5.2.6",
+ "vite": "^5.2.9",
"vite-plugin-cp": "^1.0.0",
"vitest": "^1.4.0"
},
@@ -50,6 +54,20 @@
"node": ">=18.0.0"
}
},
+ "../babylon-html": {
+ "version": "0.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "@babylonjs/core": "^7.1.0",
+ "dom-to-image-more": "^3.3.0"
+ },
+ "devDependencies": {
+ "@types/dom-to-image": "^2.6.7",
+ "ts-node": "^10.9.2",
+ "tsup": "^8.0.2",
+ "typescript": "^5.4.5"
+ }
+ },
"node_modules/@babylonjs/core": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-7.1.0.tgz",
@@ -878,6 +896,12 @@
"resolved": "https://registry.npmjs.org/@typed-mxgraph/typed-mxgraph/-/typed-mxgraph-1.0.8.tgz",
"integrity": "sha512-rzTbmD/XofRq0YZMY/BU9cjbCTw9q8rpIvWRhQO0DcgCx3+rpHTsVOk3pfuhcnUigUYNFkljmDkRuVjbl7zZoQ=="
},
+ "node_modules/@types/dom-to-image": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/@types/dom-to-image/-/dom-to-image-2.6.7.tgz",
+ "integrity": "sha512-me5VbCv+fcXozblWwG13krNBvuEOm6kA5xoa4RrjDJCNFOZSWR3/QLtOXimBHk1Fisq69Gx3JtOoXtg1N1tijg==",
+ "dev": true
+ },
"node_modules/@types/emscripten": {
"version": "1.39.6",
"resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.6.tgz",
@@ -1082,6 +1106,10 @@
"proxy-from-env": "^1.1.0"
}
},
+ "node_modules/babylon-html": {
+ "resolved": "../babylon-html",
+ "link": true
+ },
"node_modules/babylonjs-gltf2interface": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/babylonjs-gltf2interface/-/babylonjs-gltf2interface-7.1.0.tgz",
@@ -1320,6 +1348,11 @@
"node": ">=8"
}
},
+ "node_modules/dom-to-image-more": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/dom-to-image-more/-/dom-to-image-more-3.3.0.tgz",
+ "integrity": "sha512-4k0oxVfQ4Nrv4/Iva6FpsXTAtPCp5JnZNO/n/hsuOpe3ANlMiK50URZDQKzJslthQD8k76z9vHS3usIzmJoFVw=="
+ },
"node_modules/double-ended-queue": {
"version": "2.1.0-0",
"resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz",
@@ -2990,13 +3023,13 @@
}
},
"node_modules/vite": {
- "version": "5.2.6",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.6.tgz",
- "integrity": "sha512-FPtnxFlSIKYjZ2eosBQamz4CbyrTizbZ3hnGJlh/wMtCrlp1Hah6AzBLjGI5I2urTfNnpovpHdrL6YRuBOPnCA==",
+ "version": "5.2.9",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.9.tgz",
+ "integrity": "sha512-uOQWfuZBlc6Y3W/DTuQ1Sr+oIXWvqljLvS881SVmAj00d5RdgShLcuXWxseWPd4HXwiYBFW/vXHfKFeqj9uQnw==",
"dev": true,
"dependencies": {
"esbuild": "^0.20.1",
- "postcss": "^8.4.36",
+ "postcss": "^8.4.38",
"rollup": "^4.13.0"
},
"bin": {
diff --git a/package.json b/package.json
index 2cd7751..f8c1193 100644
--- a/package.json
+++ b/package.json
@@ -7,7 +7,7 @@
"node": ">=18.0.0"
},
"scripts": {
- "dev": "cp ./node_modules/@babylonjs/havok/lib/esm/HavokPhysics.wasm ./node_modules/.vite/deps && vite",
+ "dev": "vite",
"test": "vitest",
"build": "vite build",
"preview": "vite preview",
@@ -16,7 +16,6 @@
"havok": "cp ./node_modules/@babylonjs/havok/lib/esm/HavokPhysics.wasm ./node_modules/.vite/deps"
},
"dependencies": {
- "axios": "^1.6.8",
"@babylonjs/core": "^7.1.0",
"@babylonjs/gui": "^7.1.0",
"@babylonjs/havok": "1.3.1",
@@ -25,33 +24,38 @@
"@babylonjs/materials": "^7.1.0",
"@babylonjs/procedural-textures": "^7.1.0",
"@babylonjs/serializers": "^7.1.0",
- "events": "^3.3.0",
- "@typed-mxgraph/typed-mxgraph": "^1.0.8",
- "@types/node": "^18.14.0",
- "earcut": "^2.2.4",
- "file-saver": "^2.0.5",
- "@types/file-saver": "^2.0.6",
+ "@picovoice/cobra-web": "^2.0.3",
"@picovoice/eagle-web": "^1.0.0",
"@picovoice/web-voice-processor": "^4.0.9",
- "@picovoice/cobra-web": "^2.0.3",
+ "@typed-mxgraph/typed-mxgraph": "^1.0.8",
+ "@types/dom-to-image": "^2.6.7",
+ "@types/file-saver": "^2.0.6",
+ "@types/node": "^18.14.0",
+ "@types/react": "^18.2.72",
+ "@types/react-dom": "^18.2.22",
+ "axios": "^1.6.8",
+ "babylon-html": "0.0.1",
+ "dom-to-image-more": "^3.3.0",
+ "earcut": "^2.2.4",
+ "events": "^3.3.0",
+ "file-saver": "^2.0.5",
"hls.js": "^1.1.4",
"loglevel": "^1.9.1",
"niceware": "^4.0.0",
"pouchdb": "^8.0.1",
"pouchdb-find": "^8.0.1",
"query-string": "^8.1.0",
- "recordrtc": "^5.6.0",
"react-dom": "^18.2.0",
+ "recordrtc": "^5.6.0",
"rfc4648": "^1.5.3",
- "@types/react-dom": "^18.2.22",
- "@types/react": "^18.2.72",
"round": "^2.0.1",
"uuid": "^9.0.1"
},
"devDependencies": {
+ "@types/dom-to-image": "^2.6.7",
"typescript": "^4.9.5",
- "vite": "^5.2.6",
- "vitest": "^1.4.0",
- "vite-plugin-cp": "^1.0.0"
+ "vite": "^5.2.9",
+ "vite-plugin-cp": "^1.0.0",
+ "vitest": "^1.4.0"
}
}
diff --git a/src/integration/pouchdbPersistenceManager.ts b/src/integration/pouchdbPersistenceManager.ts
index a23bf3e..c9eb573 100644
--- a/src/integration/pouchdbPersistenceManager.ts
+++ b/src/integration/pouchdbPersistenceManager.ts
@@ -1,26 +1,21 @@
import PouchDB from 'pouchdb';
import {DiagramEntity, DiagramEventType} from "../diagram/types/diagramEntity";
import {Color3, Observable} from "@babylonjs/core";
-import {AppConfigType} from "../util/appConfigType";
-import {v4 as uuidv4} from 'uuid';
import axios from "axios";
import {DiagramManager} from "../diagram/diagramManager";
import log, {Logger} from "loglevel";
const logger: Logger = log.getLogger('PouchdbPersistenceManager');
export class PouchdbPersistenceManager {
- configObserver: Observable
= new Observable();
updateObserver: Observable = new Observable();
removeObserver: Observable = new Observable();
private db: PouchDB;
private remote: PouchDB;
-
- private diagramListings: PouchDB;
private user: string;
constructor() {
- this.diagramListings = new PouchDB("diagramListings");
+
}
public setDiagramManager(diagramManager: DiagramManager) {
@@ -58,23 +53,6 @@ export class PouchdbPersistenceManager {
});
}
- private _currentDiagramId: string;
-
- public get currentDiagramId(): string {
- return this._currentDiagramId;
- }
-
- public set currentDiagramId(value: string) {
- this._currentDiagramId = value;
- try {
- const listing = this.diagramListings.get(value);
- } catch (err) {
- this.diagramListings.put({_id: value, name: "New Diagram"});
- }
- this.db = new PouchDB(value);
- this.db.sync(this.remote, {live: true});
- }
-
public async add(entity: DiagramEntity) {
if (!entity) {
return;
@@ -121,63 +99,26 @@ export class PouchdbPersistenceManager {
return data;
}
- public async setConfig(config: AppConfigType, initial: boolean = false) {
- if (!initial) {
- localStorage.setItem('config', JSON.stringify(config));
- } else {
- localStorage.setItem('config', JSON.stringify(config));
- }
- }
-
- public getConfig(): AppConfigType {
- return JSON.parse(localStorage.getItem('config')) as AppConfigType;
- }
-
public async initialize() {
try {
let current = this.getPath();
- const configString = localStorage.getItem('config');
- const config = JSON.parse(configString) as AppConfigType;
- if (!current && config.currentDiagramId) {
- this.db = new PouchDB(config.currentDiagramId);
- await this.beginSync(config.currentDiagramId);
+ if (current) {
+ this.db = new PouchDB(current);
} else {
- if (current) {
- config.currentDiagramId = current;
- } else {
- config.currentDiagramId = uuidv4();
- }
- this.db = new PouchDB(config.currentDiagramId);
- await this.beginSync(config.currentDiagramId);
- localStorage.setItem('config', JSON.stringify(config));
- }
- this.configObserver.notifyObservers(config);
- } catch (err) {
- const defaultConfig = {
- _id: '1',
- demoCompleted: false,
- gridSnap: 1,
- rotateSnap: 0,
- createSnap: 0,
- turnSnap: 0,
- flyMode: true,
- currentDiagramId: 'public'
- }
- try {
- await this.setConfig(defaultConfig, true);
- } catch (err) {
- logger.error(err);
+ current = 'public';
+ this.db = new PouchDB(current);
}
- this.diagramListings.put({_id: defaultConfig.currentDiagramId, name: "New Diagram"});
- this.db = new PouchDB(defaultConfig.currentDiagramId);
- await this.beginSync(defaultConfig.currentDiagramId);
- this.configObserver.notifyObservers(defaultConfig);
+ await this.beginSync(current);
+
+ } catch (err) {
+ logger.error(err);
+ logger.error('cannot initialize pouchdb for sync');
+ return;
}
try {
const all = await this.db.allDocs({include_docs: true});
-
for (const entity of all.rows) {
logger.debug(entity.doc);
this.updateObserver.notifyObservers(entity.doc, 1);
@@ -258,7 +199,6 @@ export class PouchdbPersistenceManager {
} else {
return;
}
-
}
const userEndpoint: string = import.meta.env.VITE_USER_ENDPOINT
logger.debug(userEndpoint);
diff --git a/src/util/appConfig.ts b/src/util/appConfig.ts
index d301084..e8267bd 100644
--- a/src/util/appConfig.ts
+++ b/src/util/appConfig.ts
@@ -4,20 +4,31 @@ import {AppConfigType} from "./appConfigType";
export class AppConfig {
public readonly onConfigChangedObservable = new Observable();
private _currentConfig: AppConfigType;
+ public readonly defaultConfig: AppConfigType = {
+ id: 1,
+ gridSnap: .1,
+ rotateSnap: 90,
+ createSnap: .1,
+ turnSnap: 22.5,
+ newRelicKey: null,
+ newRelicAccount: null,
+ physicsEnabled: false,
+ demoCompleted: false,
+ flyMode: true
+ }
constructor() {
- this._currentConfig = {
- id: 1,
- gridSnap: .1,
- rotateSnap: 90,
- createSnap: .1,
- turnSnap: 22.5,
- newRelicKey: null,
- newRelicAccount: null,
- physicsEnabled: false,
- demoCompleted: false,
- flyMode: true
- };
+ this._currentConfig = this.defaultConfig;
+ try {
+ const config = JSON.parse(localStorage.getItem('appConfig'));
+ if (config) {
+ this._currentConfig = config;
+ } else {
+ localStorage.setItem('appConfig', JSON.stringify(this._currentConfig));
+ }
+ } catch (err) {
+ console.error(err);
+ }
this.onConfigChangedObservable.add((config) => {
this._currentConfig = config;
}, -1);
@@ -27,55 +38,49 @@ export class AppConfig {
return this._currentConfig;
}
+ public set current(config: AppConfigType) {
+ this._currentConfig = config;
+ localStorage.setItem('appConfig', JSON.stringify(this._currentConfig));
+ this.onConfigChangedObservable.notifyObservers(this._currentConfig, -1);
+ }
+
public setRotateSnap(value: number) {
this._currentConfig.rotateSnap = value;
- this.onConfigChangedObservable.notifyObservers(this._currentConfig, 2);
+ this.save();
}
public setFlyMode(value: boolean) {
this._currentConfig.flyMode = value;
- this.onConfigChangedObservable.notifyObservers(this._currentConfig, 2);
+ this.save();
}
public setCreateSnap(value: number) {
this._currentConfig.createSnap = value;
- this.onConfigChangedObservable.notifyObservers(this._currentConfig, 2);
+ this.save();
}
public setTurnSnap(value: number) {
this._currentConfig.turnSnap = value;
- this.onConfigChangedObservable.notifyObservers(this._currentConfig, 2);
+ this.save();
}
public setGridSnap(value: number) {
this._currentConfig.gridSnap = value;
- this.onConfigChangedObservable.notifyObservers(this._currentConfig, 2);
- }
-
- public set current(config: AppConfigType) {
- this._currentConfig = config;
- this.onConfigChangedObservable.notifyObservers(config, 2);
- }
-
- public load(config: AppConfigType) {
- this._currentConfig = config;
- this.onConfigChangedObservable.notifyObservers(this._currentConfig, 1);
- }
-
- public setPassphrase(passphrase: string) {
- this._currentConfig.passphrase = passphrase;
- this.onConfigChangedObservable.notifyObservers(this._currentConfig, 2);
-
+ this.save();
}
public setPhysicsEnabled(physicsEnabled: boolean) {
this._currentConfig.physicsEnabled = physicsEnabled;
- this.onConfigChangedObservable.notifyObservers(this._currentConfig, 2);
-
+ this.save();
}
public setDemoCompleted(demoCompleted: boolean) {
this._currentConfig.demoCompleted = demoCompleted;
- this.onConfigChangedObservable.notifyObservers(this._currentConfig, 2);
+ this.save();
+ }
+
+ private save() {
+ localStorage.setItem('appConfig', JSON.stringify(this._currentConfig));
+ this.onConfigChangedObservable.notifyObservers(this._currentConfig, -1);
}
}
\ No newline at end of file
diff --git a/src/util/functions/groundMeshObserver.ts b/src/util/functions/groundMeshObserver.ts
index a998072..376569f 100644
--- a/src/util/functions/groundMeshObserver.ts
+++ b/src/util/functions/groundMeshObserver.ts
@@ -75,7 +75,7 @@ export async function groundMeshObserver(ground: AbstractMesh,
diagramManager.config.onConfigChangedObservable.add((config) => {
rig.flyMode = config.flyMode;
rig.turnSnap = config.turnSnap;
- });
+ }, -1, false, this);
const config = new ConfigMenu(xr, diagramManager.controllers, diagramManager.config);
const webController = new WebController(ground.getScene(), rig, diagramManager, diagramManager.controllers);
diff --git a/src/util/functions/updateTextNode.ts b/src/util/functions/updateTextNode.ts
index a8bd186..db8e625 100644
--- a/src/util/functions/updateTextNode.ts
+++ b/src/util/functions/updateTextNode.ts
@@ -1,14 +1,4 @@
-import {
- AbstractMesh,
- Color3,
- DynamicTexture,
- Material,
- Mesh,
- MeshBuilder,
- Scene,
- StandardMaterial,
- Vector3
-} from "@babylonjs/core";
+import {AbstractMesh, Color3, DynamicTexture, Material, MeshBuilder, StandardMaterial} from "@babylonjs/core";
import log from "loglevel";
@@ -61,29 +51,26 @@ export function updateTextNode(mesh: AbstractMesh, text: string) {
const mat = new StandardMaterial("mat", mesh.getScene());
mat.diffuseColor = Color3.Black();
mat.disableLighting = true;
- mat.backFaceCulling = true;
+ mat.backFaceCulling = false;
mat.emissiveTexture = dynamicTexture;
mat.freeze();
- //mat.emissiveColor = Color3.White();
- //Create plane and set dynamic texture as material
- //const plane = MeshBuilder.CreatePlane("text" + text, {width: planeWidth, height: height}, mesh.getScene());
const plane1 = createPlane(mat, mesh, text, planeWidth, height);
- const plane2 = createPlane(mat, mesh, text, planeWidth, height);
- plane2.rotation.y = Math.PI;
+ //const plane2 = createPlane(mat, mesh, text, planeWidth, height);
+ //plane2.rotation.y = Math.PI;
}
function createPlane(mat: Material, mesh: AbstractMesh, text: string, planeWidth: number, height: number): AbstractMesh {
const plane = MeshBuilder.CreatePlane("text" + text, {width: planeWidth, height: height}, mesh.getScene());
const yOffset = mesh.getBoundingInfo().boundingSphere.maximum.y;
- plane.parent = mesh;
+ plane.parent = mesh;
plane.scaling.y = (1 / mesh.scaling.y);
plane.scaling.x = (1 / mesh.scaling.x);
plane.scaling.z = (1 / mesh.scaling.z);
plane.material = mat;
- //plane.billboardMode = Mesh.BILLBOARDMODE_ALL;
plane.metadata = {exportable: true, label: true};
+
if (mesh.metadata?.template == "#connection-template") {
plane.billboardMode = AbstractMesh.BILLBOARDMODE_Y;
plane.position.y = mesh.position.y + .1;
@@ -91,22 +78,7 @@ function createPlane(mat: Material, mesh: AbstractMesh, text: string, planeWidth
} else {
plane.position.y = yOffset + (height * plane.scaling.y);
}
- //plane.addLODLevel(5, getDistantPlane(mesh.getScene(), plane.scaling, planeWidth, height));
plane.addLODLevel(3, null);
return plane;
}
-let distantPlane = null;
-
-function getDistantPlane(scene: Scene, scaling: Vector3, planeWidth: number, planeHeight: number): Mesh {
- //if (distantPlane == null) {
- distantPlane = MeshBuilder.CreatePlane("distantPlane", {width: planeWidth, height: planeHeight}, scene);
- distantPlane.scaling = scaling;
- //distantPlane.scaling.y = distantPlane.scaling.y /4;
- const material = new StandardMaterial("distantPlaneMaterial", scene);
- material.emissiveColor = Color3.White()
- material.freeze()
- distantPlane.material = material;
- // }
- return distantPlane;
-}
diff --git a/src/vrApp.ts b/src/vrApp.ts
index ee0db22..d990b9b 100644
--- a/src/vrApp.ts
+++ b/src/vrApp.ts
@@ -35,17 +35,6 @@ export class VrApp {
const diagramManager = new DiagramManager();
const db = new PouchdbPersistenceManager();
db.setDiagramManager(diagramManager);
- db.configObserver.add((newConfig) => {
- if (!newConfig.demoCompleted) {
- const main = document.querySelector('#main');
- } else {
- const create = document.querySelector('#create');
- }
- diagramManager.config.onConfigChangedObservable.notifyObservers(newConfig, 1);
- });
- diagramManager.config.onConfigChangedObservable.add((newConfig) => {
- db.setConfig(newConfig);
- }, 2, false, this);
await db.initialize();
const camera: FreeCamera = new FreeCamera("Main Camera",
@@ -71,24 +60,8 @@ export class VrApp {
})
}
this.logger.info('keydown event listener added, use Ctrl+Shift+Alt+I to toggle debug layer');
- /*
-
- const textGen = new TextMeshGenerator();
- let y = .1;
- for (let i = 0; i < 1000; i++) {
- const text = textGen.generateCharMesh("hijklmnop Hello World");
- text.position.y = y;
- text.position.z = -5;
- text.rotation.y = Math.PI;
- y+=.1;
- }
- */
- let i = 0;
this.engine.runRenderLoop(() => {
scene.render();
- if (i++ % 60 == 0) {
-
- }
});
this.logger.info('Render loop started');
@@ -103,14 +76,11 @@ export class VrApp {
this.engine = new Engine(canvas, true);
}
- //this.engine.setHardwareScalingLevel(1 / window.devicePixelRatio);
+ this.engine.setHardwareScalingLevel(1 / window.devicePixelRatio);
- //window.onresize = () => {
- // this.engine.resize();
- // }
- /*window.setInterval(() => {
- console.log(this.engine.performanceMonitor.instantaneousFPS.toFixed(2) + " fps");
- }, 1000);*/
+ window.onresize = () => {
+ this.engine.resize();
+ }
const scene = new Scene(this.engine);
scene.ambientColor = new Color3(.1, .1, .1);
DefaultScene.Scene = scene;