Added initial networkmanager component.
This commit is contained in:
parent
afba69042c
commit
0e2ced65e8
76
package-lock.json
generated
76
package-lock.json
generated
@ -17,6 +17,7 @@
|
||||
"dexie-observable": "^4.0.1-beta.13",
|
||||
"earcut": "^2.2.4",
|
||||
"loglevel": "^1.8.1",
|
||||
"p2p-data-channel": "^1.10.7",
|
||||
"query-string": "^8.1.0",
|
||||
"ring-client-api": "11.7.7",
|
||||
"round": "^2.0.1",
|
||||
@ -882,6 +883,14 @@
|
||||
"url": "https://github.com/sindresorhus/is?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/helpers": {
|
||||
"version": "0.3.17",
|
||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.3.17.tgz",
|
||||
"integrity": "sha512-tb7Iu+oZ+zWJZ3HJqwx8oNwSDIU440hmVMDPhpACWQWnrZHK99Bxs70gT1L2dnr5Hg50ZRWEFkQCAnOVVV0z1Q==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@szmarczak/http-timer": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
|
||||
@ -1820,6 +1829,11 @@
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eventemitter3": {
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
|
||||
},
|
||||
"node_modules/events": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
||||
@ -2961,6 +2975,15 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/p2p-data-channel": {
|
||||
"version": "1.10.7",
|
||||
"resolved": "https://registry.npmjs.org/p2p-data-channel/-/p2p-data-channel-1.10.7.tgz",
|
||||
"integrity": "sha512-YPpmzm75hX773d2dB1KYYUhvEXBM5NlkWHALvudQOG3Xv8AGceJuNcGpAKxprMu/dY3WL7RgJuqM/EzZojlUcw==",
|
||||
"dependencies": {
|
||||
"peerjs": "^1.4.7",
|
||||
"uuid": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/parse-exponential": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parse-exponential/-/parse-exponential-1.0.1.tgz",
|
||||
@ -3011,6 +3034,29 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/peerjs": {
|
||||
"version": "1.4.7",
|
||||
"resolved": "https://registry.npmjs.org/peerjs/-/peerjs-1.4.7.tgz",
|
||||
"integrity": "sha512-dWE2HIGvJO0Hm8lYHJiO/5OWl8xYtGcAuU08To1HMIfhh76ULzkCS3NIQO/PZm4noO1RhaGTkQaQ6sbAss6/Tg==",
|
||||
"dependencies": {
|
||||
"@swc/helpers": "^0.3.13",
|
||||
"eventemitter3": "^4.0.7",
|
||||
"peerjs-js-binarypack": "1.0.1",
|
||||
"webrtc-adapter": "^7.7.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/peer"
|
||||
}
|
||||
},
|
||||
"node_modules/peerjs-js-binarypack": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/peerjs-js-binarypack/-/peerjs-js-binarypack-1.0.1.tgz",
|
||||
"integrity": "sha512-N6aeia3NhdpV7kiGxJV5xQiZZCVEEVjRz2T2C6UZQiBkHWHzUv/oWA4myQLcwBwO8LUoR1KWW5oStvwVesmfCg=="
|
||||
},
|
||||
"node_modules/pick-port": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pick-port/-/pick-port-1.0.1.tgz",
|
||||
@ -3343,6 +3389,18 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rtcpeerconnection-shim": {
|
||||
"version": "1.2.15",
|
||||
"resolved": "https://registry.npmjs.org/rtcpeerconnection-shim/-/rtcpeerconnection-shim-1.2.15.tgz",
|
||||
"integrity": "sha512-C6DxhXt7bssQ1nHb154lqeL0SXz5Dx4RczXZu2Aa/L1NJFnEVDxFwCBo3fqtuljhHIGceg5JKBV4XJ0gW5JKyw==",
|
||||
"dependencies": {
|
||||
"sdp": "^2.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0",
|
||||
"npm": ">=3.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/run-async": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
|
||||
@ -3411,6 +3469,11 @@
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"node_modules/sdp": {
|
||||
"version": "2.12.0",
|
||||
"resolved": "https://registry.npmjs.org/sdp/-/sdp-2.12.0.tgz",
|
||||
"integrity": "sha512-jhXqQAQVM+8Xj5EjJGVweuEzgtGWb3tmEEpl3CLP3cStInSbVHSg0QWOGQzNq8pSID4JkpeV2mPqlMDLrm0/Vw=="
|
||||
},
|
||||
"node_modules/set-cookie-parser": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz",
|
||||
@ -3927,6 +3990,19 @@
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||
},
|
||||
"node_modules/webrtc-adapter": {
|
||||
"version": "7.7.1",
|
||||
"resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-7.7.1.tgz",
|
||||
"integrity": "sha512-TbrbBmiQBL9n0/5bvDdORc6ZfRY/Z7JnEj+EYOD1ghseZdpJ+nF2yx14k3LgQKc7JZnG7HAcL+zHnY25So9d7A==",
|
||||
"dependencies": {
|
||||
"rtcpeerconnection-shim": "^1.2.15",
|
||||
"sdp": "^2.12.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0",
|
||||
"npm": ">=3.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/werift": {
|
||||
"version": "0.18.2",
|
||||
"resolved": "https://registry.npmjs.org/werift/-/werift-0.18.2.tgz",
|
||||
|
||||
@ -23,7 +23,8 @@
|
||||
"loglevel": "^1.8.1",
|
||||
"round": "^2.0.1",
|
||||
"earcut": "^2.2.4",
|
||||
"uuid": "^9.0.0"
|
||||
"uuid": "^9.0.0",
|
||||
"p2p-data-channel": "^1.10.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.0.2",
|
||||
|
||||
52
src/app.ts
52
src/app.ts
@ -1,15 +1,12 @@
|
||||
import "@babylonjs/core/Debug/debugLayer";
|
||||
import "@babylonjs/inspector";
|
||||
|
||||
import {
|
||||
ArcRotateCamera,
|
||||
DualShockPad,
|
||||
Engine,
|
||||
GroundMesh,
|
||||
HavokPlugin,
|
||||
HemisphericLight,
|
||||
MeshBuilder,
|
||||
PBRMetallicRoughnessMaterial,
|
||||
PhotoDome,
|
||||
PhysicsAggregate,
|
||||
PhysicsShapeType,
|
||||
Scene,
|
||||
@ -18,7 +15,6 @@ import {
|
||||
WebXRDefaultExperience,
|
||||
WebXRState
|
||||
} from "@babylonjs/core";
|
||||
///import {havokModule} from "./util/havok";
|
||||
import HavokPhysics from "@babylonjs/havok";
|
||||
import {Rigplatform} from "./controllers/rigplatform";
|
||||
import {DiagramManager} from "./diagram/diagramManager";
|
||||
@ -26,7 +22,6 @@ import {Toolbox} from "./toolbox/toolbox";
|
||||
import {DualshockEventMapper} from "./util/dualshockEventMapper";
|
||||
import log from "loglevel";
|
||||
import {AppConfig} from "./util/appConfig";
|
||||
import {IndexdbPersistenceManager} from "./diagram/indexdbPersistenceManager";
|
||||
import {DiaSounds} from "./util/diaSounds";
|
||||
|
||||
export class App {
|
||||
@ -35,7 +30,7 @@ export class App {
|
||||
|
||||
|
||||
private scene: Scene;
|
||||
private xr: WebXRDefaultExperience;
|
||||
|
||||
private rig: Rigplatform;
|
||||
|
||||
constructor() {
|
||||
@ -51,13 +46,11 @@ export class App {
|
||||
this.initialize(canvas).then(() => {
|
||||
log.debug('App', 'Scene Initialized');
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
async initialize(canvas) {
|
||||
if (this.xr) {
|
||||
this.xr.dispose();
|
||||
this.xr = null;
|
||||
}
|
||||
if (this.scene) {
|
||||
this.scene.dispose();
|
||||
this.scene = null;
|
||||
@ -81,13 +74,15 @@ export class App {
|
||||
camera.radius = 0;
|
||||
camera.attachControl(canvas, true);
|
||||
|
||||
|
||||
new HemisphericLight("light1", new Vector3(1, 1, 0), scene);
|
||||
const photoDome = new PhotoDome('sky',
|
||||
import('@babylonjs/core').then((babylon) => {
|
||||
new babylon.PhotoDome('sky',
|
||||
'./outdoor_field2.jpeg', {},
|
||||
scene);
|
||||
});
|
||||
|
||||
const ground = this.createGround();
|
||||
this.xr = await WebXRDefaultExperience.CreateAsync(scene, {
|
||||
const xr = await WebXRDefaultExperience.CreateAsync(scene, {
|
||||
floorMeshes: [ground],
|
||||
disableTeleportation: true,
|
||||
outputCanvasOptions: {
|
||||
@ -102,10 +97,10 @@ export class App {
|
||||
|
||||
});
|
||||
|
||||
this.xr.baseExperience.onStateChangedObservable.add((state) => {
|
||||
xr.baseExperience.onStateChangedObservable.add((state) => {
|
||||
if (state == WebXRState.IN_XR) {
|
||||
this.scene.audioEnabled = true;
|
||||
this.xr.baseExperience.camera.position = new Vector3(0, 1.6, 0);
|
||||
xr.baseExperience.camera.position = new Vector3(0, 1.6, 0);
|
||||
window.addEventListener(('pa-button-state-change'), (event: any) => {
|
||||
if (event.detail) {
|
||||
log.debug('App', event.detail);
|
||||
@ -114,15 +109,18 @@ export class App {
|
||||
|
||||
}
|
||||
});
|
||||
const persistenceManager = new IndexdbPersistenceManager("diagram");
|
||||
const diagramManager = new DiagramManager(this.scene, this.xr.baseExperience);
|
||||
const diagramManager = new DiagramManager(this.scene, xr.baseExperience);
|
||||
this.rig = new Rigplatform(this.scene, xr, diagramManager);
|
||||
const toolbox = new Toolbox(scene, xr.baseExperience, diagramManager);
|
||||
|
||||
import ('./diagram/indexdbPersistenceManager').then((module) => {
|
||||
const persistenceManager = new module.IndexdbPersistenceManager("diagram");
|
||||
diagramManager.setPersistenceManager(persistenceManager);
|
||||
AppConfig.config.setPersistenceManager(persistenceManager);
|
||||
persistenceManager.initialize();
|
||||
});
|
||||
|
||||
|
||||
this.rig = new Rigplatform(this.scene, this.xr, diagramManager);
|
||||
const toolbox = new Toolbox(scene, this.xr.baseExperience, diagramManager);
|
||||
|
||||
this.scene.gamepadManager.onGamepadConnectedObservable.add((gamepad) => {
|
||||
try {
|
||||
const dualshock = (gamepad as DualShockPad);
|
||||
@ -190,15 +188,19 @@ export class App {
|
||||
window.addEventListener("keydown", (ev) => {
|
||||
// Shift+Ctrl+Alt+I
|
||||
if (ev.shiftKey && ev.ctrlKey && ev.altKey && ev.keyCode === 73) {
|
||||
import("@babylonjs/core/Debug/debugLayer").then(() => {
|
||||
import("@babylonjs/inspector").then(() => {
|
||||
if (scene.debugLayer.isVisible()) {
|
||||
scene.debugLayer.hide();
|
||||
} else {
|
||||
scene.debugLayer.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
this.logger.info('keydown event listener added, use Ctrl+Shift+Alt+I to toggle debug layer');
|
||||
persistenceManager.initialize();
|
||||
|
||||
engine.runRenderLoop(() => {
|
||||
scene.render();
|
||||
|
||||
@ -215,7 +217,11 @@ export class App {
|
||||
groundMaterial.metallic = 0;
|
||||
groundMaterial.roughness = 1;
|
||||
|
||||
const ground = MeshBuilder.CreateGround("ground", {width: 100, height: 100, subdivisions: 1}, this.scene);
|
||||
const ground: GroundMesh = MeshBuilder.CreateGround("ground", {
|
||||
width: 100,
|
||||
height: 100,
|
||||
subdivisions: 1
|
||||
}, this.scene);
|
||||
|
||||
ground.material = groundMaterial;
|
||||
new PhysicsAggregate(ground, PhysicsShapeType.BOX, {mass: 0}, this.scene);
|
||||
|
||||
@ -79,7 +79,6 @@ export class Base {
|
||||
if (init.components['xr-standard-squeeze']) {
|
||||
this.initGrip(init.components['xr-standard-squeeze'])
|
||||
}
|
||||
;
|
||||
});
|
||||
Controllers.controllerObserver.add((event) => {
|
||||
if (event.type == 'pulse') {
|
||||
@ -88,8 +87,7 @@ export class Base {
|
||||
this.controller?.motionController?.pulse(.25, 30);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
public disable() {
|
||||
@ -101,11 +99,6 @@ export class Base {
|
||||
this.controller.motionController.rootMesh.setEnabled(true);
|
||||
this.controller.pointer.setEnabled(true);
|
||||
}
|
||||
|
||||
private buildTransformNode() {
|
||||
|
||||
}
|
||||
|
||||
private setupTransformNode(mesh: TransformNode) {
|
||||
const transformNode = new TransformNode("grabAnchor, this.scene");
|
||||
transformNode.id = "grabAnchor";
|
||||
|
||||
@ -12,7 +12,7 @@ import {
|
||||
WebXRExperienceHelper
|
||||
} from "@babylonjs/core";
|
||||
import {DiagramEntity, DiagramEvent, DiagramEventType} from "./diagramEntity";
|
||||
import {IPersistenceManager} from "./persistenceManager";
|
||||
import {IPersistenceManager} from "./iPersistenceManager";
|
||||
import {MeshConverter} from "./meshConverter";
|
||||
import log from "loglevel";
|
||||
import {Controllers} from "../controllers/controllers";
|
||||
|
||||
@ -17,6 +17,7 @@ export class DiagramShapePhysics {
|
||||
if (mesh.physicsBody) {
|
||||
mesh.physicsBody.dispose();
|
||||
}
|
||||
|
||||
let shapeType = PhysicsShapeType.BOX;
|
||||
switch (mesh.metadata.template) {
|
||||
case "#sphere-template":
|
||||
@ -30,8 +31,9 @@ export class DiagramShapePhysics {
|
||||
break;
|
||||
|
||||
}
|
||||
let mass = mesh.scaling.x * mesh.scaling.y * mesh.scaling.z * 10;
|
||||
const aggregate = new PhysicsAggregate(mesh,
|
||||
shapeType, {mass: 20, restitution: .02, friction: .9}, scene);
|
||||
shapeType, {mass: mass, restitution: .02, friction: .9}, scene);
|
||||
aggregate.body.setCollisionCallbackEnabled(true);
|
||||
aggregate.body.getCollisionObservable().add((event, state) => {
|
||||
if (event.distance > .001 && !DiaSounds.instance.low.isPlaying) {
|
||||
|
||||
50
src/diagram/iPersistenceManager.ts
Normal file
50
src/diagram/iPersistenceManager.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import {AbstractMesh, Color3, Observable} from "@babylonjs/core";
|
||||
import {DiagramEntity} from "./diagramEntity";
|
||||
import {AppConfigType} from "../util/appConfigType";
|
||||
|
||||
export enum DiagramListingEventType {
|
||||
GET,
|
||||
ADD,
|
||||
REMOVE,
|
||||
MODIFY
|
||||
}
|
||||
|
||||
export type DiagramListingEvent = {
|
||||
type: DiagramListingEventType;
|
||||
listing: DiagramListing;
|
||||
}
|
||||
export type DiagramListing = {
|
||||
type: DiagramListingEvent;
|
||||
id: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
sharekey?: string;
|
||||
|
||||
}
|
||||
|
||||
export interface IPersistenceManager {
|
||||
diagramListingObserver: Observable<DiagramListingEvent>;
|
||||
|
||||
addDiagram(diagram: DiagramListing);
|
||||
|
||||
removeDiagram(diagram: DiagramListing);
|
||||
|
||||
add(mesh: AbstractMesh);
|
||||
|
||||
remove(mesh: AbstractMesh);
|
||||
|
||||
modify(mesh: AbstractMesh);
|
||||
|
||||
initialize();
|
||||
|
||||
setConfig(config: AppConfigType);
|
||||
|
||||
modifyDiagram(diagram: DiagramListing);
|
||||
|
||||
updateObserver: Observable<DiagramEntity>;
|
||||
configObserver: Observable<AppConfigType>;
|
||||
|
||||
changeColor(oldColor: Color3, newColor: Color3);
|
||||
|
||||
setCurrentDiagram(diagram: DiagramListing);
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
import {IPersistenceManager} from "./persistenceManager";
|
||||
import {DiagramListing, DiagramListingEvent, DiagramListingEventType, IPersistenceManager} from "./iPersistenceManager";
|
||||
import {AbstractMesh, Observable, Vector3} from "@babylonjs/core";
|
||||
import {DiagramEntity} from "./diagramEntity";
|
||||
import Dexie from "dexie";
|
||||
@ -6,20 +6,25 @@ import {MeshConverter} from "./meshConverter";
|
||||
import log from "loglevel";
|
||||
import {AppConfigType} from "../util/appConfigType";
|
||||
|
||||
|
||||
export class IndexdbPersistenceManager implements IPersistenceManager {
|
||||
private readonly logger = log.getLogger('IndexdbPersistenceManager');
|
||||
public readonly diagramListingObserver: Observable<DiagramListingEvent> = new Observable<DiagramListingEvent>();
|
||||
public readonly updateObserver: Observable<DiagramEntity> = new Observable<DiagramEntity>();
|
||||
public readonly configObserver: Observable<AppConfigType> = new Observable<AppConfigType>();
|
||||
private db: Dexie;
|
||||
private currentDiagramId: string;
|
||||
|
||||
constructor(name: string) {
|
||||
this.db = new Dexie(name);
|
||||
const version = 2;
|
||||
const version = 3;
|
||||
this.db.version(version).stores({config: "id,gridSnap,rotateSnap,createSnap"});
|
||||
this.db.version(version).stores({entities: "id,position,rotation,last_seen,template,text,scale,color"});
|
||||
this.db.version(version).stores({entities: "id,diagramlistingid,position,rotation,last_seen,template,text,scale,color"});
|
||||
this.db.version(version).stores({diagramlisting: "id,name,description,sharekey"});
|
||||
this.logger.debug("IndexdbPersistenceManager constructed");
|
||||
}
|
||||
|
||||
public setCurrentDiagram(diagram: DiagramListing) {
|
||||
this.currentDiagramId = diagram.id;
|
||||
}
|
||||
|
||||
public add(mesh: AbstractMesh) {
|
||||
@ -31,10 +36,20 @@ export class IndexdbPersistenceManager implements IPersistenceManager {
|
||||
entity.position = this.vectoxys(mesh.position);
|
||||
entity.rotation = this.vectoxys(mesh.rotation);
|
||||
entity.scale = this.vectoxys(mesh.scaling);
|
||||
entity.diagramlistingid = this.currentDiagramId;
|
||||
this.db["entities"].add(entity);
|
||||
this.logger.debug('add', mesh, entity);
|
||||
}
|
||||
|
||||
public addDiagram(diagram: DiagramListing) {
|
||||
this.db["diagramlisting"].add(diagram);
|
||||
const event = {
|
||||
type: DiagramListingEventType.ADD,
|
||||
listing: diagram
|
||||
}
|
||||
this.diagramListingObserver.notifyObservers(event);
|
||||
}
|
||||
|
||||
public remove(mesh: AbstractMesh) {
|
||||
if (!mesh) {
|
||||
this.logger.error("Removing null mesh, early return");
|
||||
@ -50,6 +65,55 @@ export class IndexdbPersistenceManager implements IPersistenceManager {
|
||||
this.configObserver.notifyObservers(config);
|
||||
}
|
||||
|
||||
public removeDiagram(diagram: DiagramListing) {
|
||||
this.db["diagramlisting"].delete(diagram.id);
|
||||
const event = {
|
||||
type: DiagramListingEventType.REMOVE,
|
||||
listing: diagram
|
||||
}
|
||||
this.diagramListingObserver.notifyObservers(event);
|
||||
}
|
||||
|
||||
modifyDiagram(diagram: DiagramListing) {
|
||||
this.db["diagramlisting"].update(diagram.id, diagram);
|
||||
const event = {
|
||||
type: DiagramListingEventType.MODIFY,
|
||||
listing: diagram
|
||||
}
|
||||
this.diagramListingObserver.notifyObservers(event);
|
||||
}
|
||||
|
||||
public async initialize() {
|
||||
this.logger.info('initialize', this.db['entities'].length);
|
||||
const configs = await this.db['config'].toArray();
|
||||
const config = configs[0];
|
||||
if (config) {
|
||||
this.logger.debug('initialize config', config);
|
||||
this.configObserver.notifyObservers(config);
|
||||
if (config.currentDiagramId) {
|
||||
this.logger.debug('initialize currentDiagramId', config.currentDiagramId);
|
||||
const currentDiagram = await this.db['diagramlisting'].get(config.currentDiagramId);
|
||||
if (currentDiagram) {
|
||||
this.logger.debug('found currentDiagram', currentDiagram);
|
||||
this.currentDiagramId = currentDiagram.id;
|
||||
} else {
|
||||
this.logger.error('could not find currentDiagram', config.currentDiagramId);
|
||||
}
|
||||
} else {
|
||||
this.logger.warn('no currentDiagramId, using default');
|
||||
}
|
||||
}
|
||||
this.getFilteredEntities().each((e) => {
|
||||
e.position = this.xyztovec(e.position);
|
||||
e.rotation = this.xyztovec(e.rotation);
|
||||
e.scale = this.xyztovec(e.scale);
|
||||
this.logger.debug('adding', e);
|
||||
this.updateObserver.notifyObservers(e);
|
||||
});
|
||||
this.listDiagrams();
|
||||
this.logger.info("initialize finished");
|
||||
}
|
||||
|
||||
public modify(mesh) {
|
||||
if (!mesh) {
|
||||
this.logger.error("Modifying null mesh, early return");
|
||||
@ -67,21 +131,6 @@ export class IndexdbPersistenceManager implements IPersistenceManager {
|
||||
this.logger.debug('modify', mesh, entity);
|
||||
}
|
||||
|
||||
public initialize() {
|
||||
this.logger.info('initialize', this.db['entities'].length);
|
||||
this.db['entities'].each((e) => {
|
||||
e.position = this.xyztovec(e.position);
|
||||
e.rotation = this.xyztovec(e.rotation);
|
||||
e.scale = this.xyztovec(e.scale);
|
||||
this.logger.debug('adding', e);
|
||||
this.updateObserver.notifyObservers(e);
|
||||
});
|
||||
this.db['config'].each((c) => {
|
||||
this.configObserver.notifyObservers(c);
|
||||
});
|
||||
this.logger.info("initialize finished");
|
||||
}
|
||||
|
||||
public changeColor(oldColor, newColor) {
|
||||
if (!oldColor) {
|
||||
if (!newColor) {
|
||||
@ -92,7 +141,31 @@ export class IndexdbPersistenceManager implements IPersistenceManager {
|
||||
return;
|
||||
}
|
||||
this.logger.debug(`changeColor ${oldColor.toHexString()} to ${newColor.toHexString()}`);
|
||||
this.db['entities'].where('color').equals(oldColor.toHexString()).modify({color: newColor.toHexString()});
|
||||
this.getFilteredEntities().filter((e) => e.color == oldColor.toHexString()).modify({color: newColor.toHexString()});
|
||||
}
|
||||
|
||||
private listDiagrams() {
|
||||
return this.db["diagramlisting"].toArray((diagrams) => {
|
||||
this.logger.debug('listDiagrams', diagrams);
|
||||
for (const diagram of diagrams) {
|
||||
const event = {
|
||||
type: DiagramListingEventType.GET,
|
||||
listing: diagram
|
||||
}
|
||||
this.diagramListingObserver.notifyObservers(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private getFilteredEntities() {
|
||||
return this.db['entities'].filter((e) => {
|
||||
if (!this.currentDiagramId && !e.diagramlistingid) {
|
||||
return true;
|
||||
} else {
|
||||
return e.diagramlistingid == this.currentDiagramId;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private vectoxys(v: Vector3): { x, y, z } {
|
||||
|
||||
@ -1,22 +0,0 @@
|
||||
import {AbstractMesh, Color3, Observable} from "@babylonjs/core";
|
||||
import {DiagramEntity} from "./diagramEntity";
|
||||
import {AppConfigType} from "../util/appConfigType";
|
||||
|
||||
|
||||
export interface IPersistenceManager {
|
||||
add(mesh: AbstractMesh);
|
||||
|
||||
remove(mesh: AbstractMesh);
|
||||
|
||||
modify(mesh: AbstractMesh);
|
||||
|
||||
initialize();
|
||||
|
||||
setConfig(config: AppConfigType);
|
||||
|
||||
changeColor(oldColor: Color3, newColor: Color3)
|
||||
|
||||
updateObserver: Observable<DiagramEntity>;
|
||||
configObserver: Observable<AppConfigType>;
|
||||
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
class Database {
|
||||
constructor() {
|
||||
|
||||
}
|
||||
}
|
||||
20
src/integration/iNetworkConnection.ts
Normal file
20
src/integration/iNetworkConnection.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import {Observable} from "@babylonjs/core";
|
||||
|
||||
export enum NetworkMessageType {
|
||||
DIAGRAM_EVENT = 'diagramEvent',
|
||||
CONNECTION_EVENT = 'connectionEvent',
|
||||
}
|
||||
|
||||
class NetworkMessage {
|
||||
type: NetworkMessageType;
|
||||
data: any;
|
||||
}
|
||||
|
||||
export interface INetworkConnection {
|
||||
onMessageObservable: Observable<NetworkMessage>;
|
||||
|
||||
connect(name: string, room: string);
|
||||
|
||||
disconnect();
|
||||
|
||||
}
|
||||
3
src/integration/peerjsNetworkConnection.ts
Normal file
3
src/integration/peerjsNetworkConnection.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export class PeerjsNetworkConnection {
|
||||
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
import {
|
||||
Angle,
|
||||
Color3,
|
||||
MeshBuilder,
|
||||
Scene,
|
||||
StandardMaterial,
|
||||
Texture,
|
||||
Vector3,
|
||||
WebXRSessionManager
|
||||
} from "@babylonjs/core";
|
||||
import log from "loglevel";
|
||||
|
||||
|
||||
export class Cameras {
|
||||
private readonly scene: Scene;
|
||||
private readonly logger = log.getLogger('bmenu');
|
||||
|
||||
private xrSession: WebXRSessionManager;
|
||||
private startPosition = new Vector3(0, 0, 0);
|
||||
|
||||
constructor(scene: Scene, xrSession: WebXRSessionManager) {
|
||||
this.scene = scene;
|
||||
this.xrSession = xrSession;
|
||||
|
||||
}
|
||||
|
||||
public createCameras(position: Vector3) {
|
||||
this.startPosition = position;
|
||||
this.getCameras();
|
||||
}
|
||||
|
||||
private getCameras() {
|
||||
|
||||
}
|
||||
|
||||
private async createCamera() {
|
||||
const width = 1.6;
|
||||
const height = .9
|
||||
const plane = MeshBuilder.CreatePlane("plane", {width: width, height: height}, this.scene);
|
||||
const materialPlane = new StandardMaterial("texturePlane", this.scene);
|
||||
//const photo = []
|
||||
//await cam.getSnapshot();
|
||||
//const textureBlob = new Blob([photo], {type: 'image/jpeg'});
|
||||
//const textureUrl = URL.createObjectURL(textureBlob);
|
||||
|
||||
|
||||
materialPlane.diffuseTexture = new Texture("", this.scene);
|
||||
materialPlane.specularColor = new Color3(0, 0, 0);
|
||||
materialPlane.backFaceCulling = false;
|
||||
plane.material = materialPlane;
|
||||
plane.rotation.y = Angle.FromDegrees(180).radians();
|
||||
plane.position.y = height / 2 + .2;
|
||||
plane.position.z = -3;
|
||||
plane.position.x = (width * 3) + this.startPosition.x;
|
||||
this.startPosition.x += 3;
|
||||
}
|
||||
}
|
||||
@ -156,9 +156,9 @@ export class EditMenu {
|
||||
|
||||
private setCopying(mesh: AbstractMesh) {
|
||||
if (mesh) {
|
||||
const newMesh = this.diagramManager.createCopy(mesh);
|
||||
const newMesh = this.diagramManager.createCopy(mesh, true);
|
||||
newMesh.setParent(null);
|
||||
DiagramShapePhysics.applyPhysics(newMesh, this.scene);
|
||||
newMesh.parent = null;
|
||||
}
|
||||
this.logger.warn('copying not implemented', mesh);
|
||||
//@todo implement
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
import {AbstractMesh, MeshBuilder, Scene, WebXRExperienceHelper} from "@babylonjs/core";
|
||||
import {
|
||||
AdvancedDynamicTexture
|
||||
} from "@babylonjs/gui";
|
||||
|
||||
export class Keyboard {
|
||||
private readonly scene: Scene;
|
||||
private mesh: AbstractMesh;
|
||||
private panel: AbstractMesh;
|
||||
private xr: WebXRExperienceHelper;
|
||||
constructor(scene: Scene, xr: WebXRExperienceHelper, mesh: AbstractMesh ) {
|
||||
this.scene = scene;
|
||||
this.xr = xr;
|
||||
this.mesh = mesh;
|
||||
}
|
||||
public async show() {
|
||||
this.panel = MeshBuilder.CreatePlane("hudPlane", {width: 1, height: 1}, this.scene);
|
||||
const inputTexture = AdvancedDynamicTexture.CreateForMesh(this.panel, 1024, 1024);
|
||||
await inputTexture.parseFromURLAsync("./textInputTexture.json", false);
|
||||
|
||||
this.panel.position = this.xr.camera.getFrontPosition(3);
|
||||
this.panel.position.y = this.panel.position.y + 2;
|
||||
this.panel.lookAt(this.xr.camera.getFrontPosition(-1));
|
||||
this.panel.rotation.y = this.panel.rotation.y + Math.PI;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
import {AdvancedDynamicTexture, Button, Control, Slider, StackPanel} from "@babylonjs/gui";
|
||||
import {Angle, Mesh} from "@babylonjs/core";
|
||||
|
||||
export class ObjectEditor {
|
||||
private scene;
|
||||
private editor: Mesh;
|
||||
private mesh;
|
||||
|
||||
constructor(scene, mesh) {
|
||||
this.scene = scene;
|
||||
this.mesh = mesh;
|
||||
this.edit();
|
||||
}
|
||||
|
||||
public edit() {
|
||||
this.editor = Mesh.CreatePlane("editor", 2, this.scene);
|
||||
this.editor.position.z = -2;
|
||||
this.editor.position.y = 2;
|
||||
this.editor.rotation.y = Angle.FromDegrees(180).radians();
|
||||
const texture = AdvancedDynamicTexture.CreateForMesh(this.editor);
|
||||
const panel = new StackPanel();
|
||||
|
||||
panel.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_RIGHT;
|
||||
panel.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
|
||||
panel.width = '100%';
|
||||
panel.height = '100%';
|
||||
texture.addControl(panel);
|
||||
const x = this.createControl();
|
||||
|
||||
const y = this.createControl();
|
||||
const z = this.createControl()
|
||||
const myMesh = this.mesh;
|
||||
z.value = myMesh.scaling.z;
|
||||
z.onValueChangedObservable.add((value) => {
|
||||
myMesh.scaling.z = value;
|
||||
});
|
||||
y.onValueChangedObservable.add((value) => {
|
||||
myMesh.scaling.y = value;
|
||||
});
|
||||
y.value = myMesh.scaling.x;
|
||||
x.onValueChangedObservable.add((value) => {
|
||||
myMesh.scaling.x = value;
|
||||
});
|
||||
x.value = myMesh.scaling.x;
|
||||
panel.addControl(x);
|
||||
panel.addControl(y);
|
||||
panel.addControl(z);
|
||||
const button1 = Button.CreateSimpleButton("close-editor", "Close");
|
||||
button1.height = '20px';
|
||||
button1.background = "#FFF";
|
||||
panel.addControl(button1);
|
||||
button1.onPointerClickObservable.add(() => {
|
||||
this.close();
|
||||
}, -1, false, this);
|
||||
}
|
||||
|
||||
createControl(): Slider {
|
||||
const slider = new Slider();
|
||||
slider.minimum = .1
|
||||
slider.maximum = 10;
|
||||
slider.height = '40px';
|
||||
slider.step = .1
|
||||
return slider;
|
||||
}
|
||||
|
||||
close() {
|
||||
this.editor.dispose();
|
||||
this.mesh = null;
|
||||
this.scene = null;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user