Simplified interactions, changed menu interactions for changing entities.
This commit is contained in:
parent
2d3855621e
commit
727977d5c6
98
package-lock.json
generated
98
package-lock.json
generated
@ -8,14 +8,14 @@
|
||||
"name": "immersive",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"@babylonjs/core": "^6.45.1",
|
||||
"@babylonjs/gui": "^6.45.1",
|
||||
"@babylonjs/core": "^7.1.0",
|
||||
"@babylonjs/gui": "^7.1.0",
|
||||
"@babylonjs/havok": "1.3.1",
|
||||
"@babylonjs/inspector": "^6.45.1",
|
||||
"@babylonjs/loaders": "^6.45.1",
|
||||
"@babylonjs/materials": "^6.45.1",
|
||||
"@babylonjs/procedural-textures": "^6.45.1",
|
||||
"@babylonjs/serializers": "^6.45.1",
|
||||
"@babylonjs/inspector": "^7.1.0",
|
||||
"@babylonjs/loaders": "^7.1.0",
|
||||
"@babylonjs/materials": "^7.1.0",
|
||||
"@babylonjs/procedural-textures": "^7.1.0",
|
||||
"@babylonjs/serializers": "^7.1.0",
|
||||
"@picovoice/cobra-web": "^2.0.3",
|
||||
"@picovoice/eagle-web": "^1.0.0",
|
||||
"@picovoice/web-voice-processor": "^4.0.9",
|
||||
@ -51,26 +51,26 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babylonjs/core": {
|
||||
"version": "6.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-6.45.1.tgz",
|
||||
"integrity": "sha512-wkORoAqpnZb10bUhrI0vinE9IiW7+gSgH4U4Zp41wO4kSeV0mtJY+Q5Ez6/n9ad9sLykD2FD7650B+Qi5tTMSw=="
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-7.1.0.tgz",
|
||||
"integrity": "sha512-nz1CmflajMPnjdnwYrj72s4D/Q8IkOW4DBbwMfUNLFSCondfFXS3sZBgHeCAHpimR5n4e27YwvJ66MkQJsSraQ=="
|
||||
},
|
||||
"node_modules/@babylonjs/gui": {
|
||||
"version": "6.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@babylonjs/gui/-/gui-6.45.1.tgz",
|
||||
"integrity": "sha512-lev/3nprv4t8lu3kW1zdlH7VzlWh9dmyZ2PkzybmBI6nB48bswPm7cX2ppaFTkpY8Z904js9TOsrYQotMzsUiw==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@babylonjs/gui/-/gui-7.1.0.tgz",
|
||||
"integrity": "sha512-tY6MGtigjZwv+9rqtGTsyBZL9sHSPjgVq+JEWHUsACH0ffNkKsQxtKSDc5bryzNQpo1rzTMHqEeU+DnqNSVe1Q==",
|
||||
"peerDependencies": {
|
||||
"@babylonjs/core": "^6.0.0"
|
||||
"@babylonjs/core": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babylonjs/gui-editor": {
|
||||
"version": "6.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@babylonjs/gui-editor/-/gui-editor-6.8.0.tgz",
|
||||
"integrity": "sha512-XSTYEfCdf04Th1xrTuIO/lHBSmfiG4s4fIDzpi0+OERO19bKQffzhFGh95NVzdL0XhvnQT88Fb6bkvsuAxFI/Q==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@babylonjs/gui-editor/-/gui-editor-7.1.0.tgz",
|
||||
"integrity": "sha512-YHPR/2HxTT1ILSdGMAKOZ+askVCRV/hnI5CQqLVmAYkoW5FlY7TdRJtHn0JGEiOuK6Z5T3lJ3ru89wM+lGLqeg==",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"@babylonjs/core": "^6.0.0",
|
||||
"@babylonjs/gui": "^6.0.0",
|
||||
"@babylonjs/core": "^7.0.0",
|
||||
"@babylonjs/gui": "^7.0.0",
|
||||
"@types/react": ">=16.7.3",
|
||||
"@types/react-dom": ">=16.0.9"
|
||||
}
|
||||
@ -84,57 +84,57 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babylonjs/inspector": {
|
||||
"version": "6.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@babylonjs/inspector/-/inspector-6.45.1.tgz",
|
||||
"integrity": "sha512-4YhJLD2FrVXUFIU+ttBanhevVaCBVLaBxhPuwrxXxKWkuBulFOQz7GkvRT/CJwA3Ad9/66qwS5+vfRT99GLM/w==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@babylonjs/inspector/-/inspector-7.1.0.tgz",
|
||||
"integrity": "sha512-Hs9pk1LstJMnD4xXpHFlQVqXPtH/hhUcNSPaZlz8iesFrHJEXF4Mlao+ozwbl2WzDbMzmmex5nc1lw2HEBdhww==",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^6.1.0",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.0.0",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babylonjs/core": "^6.0.0",
|
||||
"@babylonjs/gui": "^6.0.0",
|
||||
"@babylonjs/gui-editor": "^6.0.0",
|
||||
"@babylonjs/loaders": "^6.0.0",
|
||||
"@babylonjs/materials": "^6.0.0",
|
||||
"@babylonjs/serializers": "^6.0.0",
|
||||
"@babylonjs/core": "^7.0.0",
|
||||
"@babylonjs/gui": "^7.0.0",
|
||||
"@babylonjs/gui-editor": "^7.0.0",
|
||||
"@babylonjs/loaders": "^7.0.0",
|
||||
"@babylonjs/materials": "^7.0.0",
|
||||
"@babylonjs/serializers": "^7.0.0",
|
||||
"@types/react": ">=16.7.3",
|
||||
"@types/react-dom": ">=16.0.9"
|
||||
}
|
||||
},
|
||||
"node_modules/@babylonjs/loaders": {
|
||||
"version": "6.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@babylonjs/loaders/-/loaders-6.45.1.tgz",
|
||||
"integrity": "sha512-a75JvRVxT3DROCrl5iigLEpI5/eR7Rh4wdsDzZNn7bv3sXB40Kbw8EL60W3jDBXPdGUqNVzqtrxJF/ec2udg/Q==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@babylonjs/loaders/-/loaders-7.1.0.tgz",
|
||||
"integrity": "sha512-6gLbFiUsiqsQDRWLl4TL5pMKiemSAB/E61SHpp8xkBalxZUiKroSbZt3Irxc7CHIq8SE5CYfPUPYjs6BmpTgqw==",
|
||||
"peerDependencies": {
|
||||
"@babylonjs/core": "^6.0.0",
|
||||
"babylonjs-gltf2interface": "^6.0.0"
|
||||
"@babylonjs/core": "^7.0.0",
|
||||
"babylonjs-gltf2interface": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babylonjs/materials": {
|
||||
"version": "6.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@babylonjs/materials/-/materials-6.45.1.tgz",
|
||||
"integrity": "sha512-v1jqgG0bfX+8Qezq4eDT2sSjpQYW+ocNU70dbJF0AYrhuhhgf0SpM28C7DAKi9GUOKjMvZrIBEbFmJ6AijLjcQ==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@babylonjs/materials/-/materials-7.1.0.tgz",
|
||||
"integrity": "sha512-tHzpV6xUqpAgF9rPudDXetk1tIPbhggrybfIpvoWwbKlffIPQw4URsA+IBG04U5owWsicdhvTLQWP1WEwfbMQg==",
|
||||
"peerDependencies": {
|
||||
"@babylonjs/core": "^6.0.0"
|
||||
"@babylonjs/core": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babylonjs/procedural-textures": {
|
||||
"version": "6.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@babylonjs/procedural-textures/-/procedural-textures-6.45.1.tgz",
|
||||
"integrity": "sha512-QpLuPknYIvylfUscSqorkuXO4QSI49atQnScWN43ZpRzr+ecXWnxEaOyAmt7bbf93htshtIkUQdJhwx8w4fqrg==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@babylonjs/procedural-textures/-/procedural-textures-7.1.0.tgz",
|
||||
"integrity": "sha512-ajjaXEQJpWNQQzWZdUJJzN4NBtI96lxbrhmBUpPdfQwAhX2LRG0tbKWKXd66QHh82f/FG+daIA2BCL7M4f2MMw==",
|
||||
"peerDependencies": {
|
||||
"@babylonjs/core": "^6.0.0"
|
||||
"@babylonjs/core": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babylonjs/serializers": {
|
||||
"version": "6.45.1",
|
||||
"resolved": "https://registry.npmjs.org/@babylonjs/serializers/-/serializers-6.45.1.tgz",
|
||||
"integrity": "sha512-iSPUdjZhQIbSyi21IFiFC/wm6Bj4zcH9NhsN9i+xqLTbO/Uho49cHU0ew39n0Xn+LRsGRMTJWQLTsp+TPvAvrw==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@babylonjs/serializers/-/serializers-7.1.0.tgz",
|
||||
"integrity": "sha512-ToYutpqvqFVic+mhFkza6rLeE31sXXpixhdpu2bE+MRP13FoxNKfPD4np/DGBP7zUWmXIi2yRm6sZ7cGs8jp1g==",
|
||||
"peerDependencies": {
|
||||
"@babylonjs/core": "^6.0.0",
|
||||
"babylonjs-gltf2interface": "^6.0.0"
|
||||
"@babylonjs/core": "^7.0.0",
|
||||
"babylonjs-gltf2interface": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
@ -1083,9 +1083,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/babylonjs-gltf2interface": {
|
||||
"version": "6.8.0",
|
||||
"resolved": "https://registry.npmjs.org/babylonjs-gltf2interface/-/babylonjs-gltf2interface-6.8.0.tgz",
|
||||
"integrity": "sha512-uCehLc8CnMUvWYttqQmJCHnhUjoftb4gK6Q+GXclgNr3CWiNDXHnbiBZQynA8SBfgkgE3bRk1+u+J5PQwkOepQ==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/babylonjs-gltf2interface/-/babylonjs-gltf2interface-7.1.0.tgz",
|
||||
"integrity": "sha512-44UnRGFj/kp6/MxB6SU5ThxYBjm9W0aYGkDbtSoPW2ZuWd4uTCjCKe8oS3fhsqXcZ5+K+rQVsHb785hxC4zRcw==",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
|
||||
14
package.json
14
package.json
@ -17,14 +17,14 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.6.8",
|
||||
"@babylonjs/core": "^6.45.1",
|
||||
"@babylonjs/gui": "^6.45.1",
|
||||
"@babylonjs/core": "^7.1.0",
|
||||
"@babylonjs/gui": "^7.1.0",
|
||||
"@babylonjs/havok": "1.3.1",
|
||||
"@babylonjs/inspector": "^6.45.1",
|
||||
"@babylonjs/loaders": "^6.45.1",
|
||||
"@babylonjs/materials": "^6.45.1",
|
||||
"@babylonjs/procedural-textures": "^6.45.1",
|
||||
"@babylonjs/serializers": "^6.45.1",
|
||||
"@babylonjs/inspector": "^7.1.0",
|
||||
"@babylonjs/loaders": "^7.1.0",
|
||||
"@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",
|
||||
|
||||
@ -20,7 +20,9 @@ import {snapGridVal} from "../util/functions/snapGridVal";
|
||||
import {snapRotateVal} from "../util/functions/snapRotateVal";
|
||||
import {grabAndClone} from "./functions/grab";
|
||||
import {isDiagramEntity} from "../diagram/functions/isDiagramEntity";
|
||||
import {ClickMenu} from "../menus/clickMenu";
|
||||
|
||||
const CLICK_TIME = 300;
|
||||
export class Base {
|
||||
static stickVector = Vector3.Zero();
|
||||
protected controller: WebXRInputSource;
|
||||
@ -32,7 +34,7 @@ export class Base {
|
||||
protected previousRotation: Vector3 = null;
|
||||
protected previousScaling: Vector3 = null;
|
||||
protected previousPosition: Vector3 = null;
|
||||
|
||||
private clickStart: number = 0;
|
||||
protected readonly xr: WebXRDefaultExperience;
|
||||
protected readonly diagramManager: DiagramManager;
|
||||
private logger: log.Logger;
|
||||
@ -45,6 +47,7 @@ export class Base {
|
||||
controllers: Controllers,
|
||||
diagramManager: DiagramManager) {
|
||||
this.logger = log.getLogger('Base');
|
||||
this.logger.setLevel(this.logger.levels.DEBUG);
|
||||
this.controller = controller;
|
||||
this.controllers = controllers;
|
||||
this.scene = scene;
|
||||
@ -71,9 +74,14 @@ export class Base {
|
||||
this.diagramManager = diagramManager;
|
||||
|
||||
this.controller.onMotionControllerInitObservable.add((init) => {
|
||||
this.logger.debug(init.components);
|
||||
if (init.components['xr-standard-squeeze']) {
|
||||
this.initGrip(init.components['xr-standard-squeeze'])
|
||||
}
|
||||
if (init.components['xr-standard-trigger']) {
|
||||
this.initClicker(init.components['xr-standard-trigger']);
|
||||
}
|
||||
|
||||
}, -1, false, this);
|
||||
this.controllers.controllerObserver.add((event) => {
|
||||
this.logger.debug(event);
|
||||
@ -108,7 +116,33 @@ export class Base {
|
||||
this.controller.pointer.setEnabled(true)
|
||||
}
|
||||
|
||||
private grab() {
|
||||
protected initClicker(trigger: WebXRControllerComponent) {
|
||||
this.logger.debug("initTrigger");
|
||||
trigger.onButtonStateChangedObservable.add(() => {
|
||||
if (trigger.changes.pressed) {
|
||||
if (trigger.pressed) {
|
||||
if (this.clickStart == 0) {
|
||||
this.clickStart = Date.now();
|
||||
window.setTimeout(() => {
|
||||
if (this.clickStart > 0) {
|
||||
this.logger.debug("grabbing and cloning");
|
||||
this.grab(true);
|
||||
}
|
||||
}, 300, this);
|
||||
}
|
||||
} else {
|
||||
const clickEnd = Date.now();
|
||||
if (this.clickStart > 0 && (clickEnd - this.clickStart) < CLICK_TIME) {
|
||||
this.click();
|
||||
}
|
||||
this.drop();
|
||||
this.clickStart = 0;
|
||||
}
|
||||
}
|
||||
}, -1, false, this);
|
||||
}
|
||||
|
||||
private grab(cloneEntity: boolean = false) {
|
||||
let mesh = this.xr.pointerSelection.getMeshUnderPointer(this.controller.uniqueId);
|
||||
if (!mesh) {
|
||||
return;
|
||||
@ -116,7 +150,7 @@ export class Base {
|
||||
let player = false;
|
||||
|
||||
if (!isDiagramEntity(mesh)) {
|
||||
if (mesh?.metadata?.handle == true) {
|
||||
if (this.handleWasGrabbed(mesh)) {
|
||||
mesh && mesh.setParent(this.controller.motionController.rootMesh);
|
||||
this.grabbedMesh = mesh;
|
||||
} else {
|
||||
@ -132,7 +166,6 @@ export class Base {
|
||||
|
||||
}
|
||||
} else {
|
||||
|
||||
if (mesh?.metadata?.template == '#connection-template') {
|
||||
return;
|
||||
}
|
||||
@ -143,7 +176,7 @@ export class Base {
|
||||
this.previousScaling = mesh?.scaling.clone();
|
||||
this.previousPosition = mesh?.position.clone();
|
||||
|
||||
if (!mesh.metadata?.grabClone || player) {
|
||||
if ((!mesh.metadata?.grabClone || player) && !cloneEntity) {
|
||||
if (mesh.physicsBody) {
|
||||
const transformNode = setupTransformNode(mesh, this.controller.motionController.rootMesh);
|
||||
mesh.physicsBody.setMotionType(PhysicsMotionType.ANIMATED);
|
||||
@ -151,9 +184,9 @@ export class Base {
|
||||
} else {
|
||||
mesh.setParent(this.controller.motionController.rootMesh);
|
||||
}
|
||||
|
||||
this.grabbedMesh = mesh;
|
||||
} else {
|
||||
this.logger.debug("cloning " + mesh?.id);
|
||||
const clone = grabAndClone(this.diagramManager, mesh, this.controller.motionController.rootMesh);
|
||||
clone.newMesh.metadata.grabClone = false;
|
||||
clone.newMesh.metadata.tool = false;
|
||||
@ -168,29 +201,25 @@ export class Base {
|
||||
}
|
||||
}
|
||||
|
||||
private toolboxHandleWasGrabbed(mesh: AbstractMesh): boolean {
|
||||
private handleWasGrabbed(mesh: AbstractMesh): boolean {
|
||||
if (isDiagramEntity(mesh)) {
|
||||
this.grabbedMesh = null;
|
||||
this.previousParentId = null;
|
||||
mesh.setParent(null);
|
||||
return false;
|
||||
} else {
|
||||
return (mesh?.metadata?.handle == true);
|
||||
}
|
||||
}
|
||||
|
||||
private drop() {
|
||||
const mesh = this.grabbedMesh;
|
||||
if (!mesh) {
|
||||
return;
|
||||
}
|
||||
if (this.toolboxHandleWasGrabbed(mesh)) {
|
||||
if (this.handleWasGrabbed(mesh)) {
|
||||
mesh.setParent(this.scene.getMeshByName("platform"))
|
||||
return;
|
||||
}
|
||||
|
||||
reparent(mesh, this.previousParentId, this.grabbedMeshParentId);
|
||||
this.grabbedMeshParentId = null;
|
||||
|
||||
if (!mesh.physicsBody) {
|
||||
mesh.position = snapGridVal(mesh.position, this.diagramManager._config.current.gridSnap);
|
||||
mesh.rotation = snapRotateVal(mesh.rotation, this.diagramManager._config.current.rotateSnap);
|
||||
@ -224,15 +253,32 @@ export class Base {
|
||||
this.diagramManager.onDiagramEventObservable.notifyObservers(event, -1);
|
||||
}
|
||||
|
||||
private click() {
|
||||
let mesh = this.xr.pointerSelection.getMeshUnderPointer(this.controller.uniqueId);
|
||||
if (pointable(mesh)) {
|
||||
this.logger.debug("click on " + mesh.id);
|
||||
const menu = new ClickMenu(mesh, this.diagramManager);
|
||||
} else {
|
||||
this.logger.debug("click on nothing");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private initGrip(grip: WebXRControllerComponent) {
|
||||
grip.onButtonStateChangedObservable.add(() => {
|
||||
if (grip.changes.pressed) {
|
||||
if (grip.pressed) {
|
||||
this.grab();
|
||||
} else {
|
||||
|
||||
this.drop();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function pointable(mesh: AbstractMesh): boolean {
|
||||
return (mesh && mesh.metadata?.template && !mesh.metadata?.tool && !mesh.metadata?.handle && !mesh.metadata?.grabbable && !mesh.metadata?.grabClone);
|
||||
}
|
||||
1
src/env.d.ts
vendored
1
src/env.d.ts
vendored
@ -3,6 +3,7 @@
|
||||
interface ImportMetaEnv {
|
||||
readonly VITE_SYNCDB_ENDPOINT: string,
|
||||
readonly VITE_SYNCDB_USER: string
|
||||
readonly VITE_CREATE_ENDPOINT: string
|
||||
// more env variables...
|
||||
}
|
||||
|
||||
|
||||
@ -37,8 +37,6 @@ export class InputTextView {
|
||||
}
|
||||
|
||||
public showVirtualKeyboard() {
|
||||
|
||||
|
||||
const inputMesh = MeshBuilder.CreatePlane("input", {width: 1, height: .5}, this.scene);
|
||||
const handle = new Handle(inputMesh);
|
||||
setMenuPosition(handle.mesh, this.scene, new Vector3(0, .4, 0));
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
import log from "loglevel";
|
||||
|
||||
const logger = log.getLogger('syncDoc');
|
||||
export function syncDoc(info) {
|
||||
logger.debug(info);
|
||||
if (info.direction == 'pull') {
|
||||
const docs = info.change.docs;
|
||||
for (const doc of docs) {
|
||||
logger.debug(doc);
|
||||
if (doc._deleted) {
|
||||
logger.debug('Delete', doc);
|
||||
this.removeObserver.notifyObservers({id: doc._id, template: doc.template}, 1);
|
||||
} else {
|
||||
this.updateObserver.notifyObservers(doc, 1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -6,7 +6,6 @@ import {v4 as uuidv4} from 'uuid';
|
||||
import axios from "axios";
|
||||
import {DiagramManager} from "../diagram/diagramManager";
|
||||
import log, {Logger} from "loglevel";
|
||||
import {syncDoc} from "./functions/syncDoc";
|
||||
|
||||
const logger: Logger = log.getLogger('PouchdbPersistenceManager');
|
||||
export class PouchdbPersistenceManager {
|
||||
@ -166,7 +165,7 @@ export class PouchdbPersistenceManager {
|
||||
createSnap: 0,
|
||||
turnSnap: 0,
|
||||
flyMode: true,
|
||||
currentDiagramId: uuidv4()
|
||||
currentDiagramId: 'public'
|
||||
}
|
||||
try {
|
||||
await this.setConfig(defaultConfig, true);
|
||||
@ -217,22 +216,53 @@ export class PouchdbPersistenceManager {
|
||||
|
||||
}
|
||||
|
||||
private async beginSync(remoteDbName: string) {
|
||||
private syncDoc(info) {
|
||||
logger.debug(info);
|
||||
if (info.direction == 'pull') {
|
||||
const docs = info.change.docs;
|
||||
for (const doc of docs) {
|
||||
logger.debug(doc);
|
||||
if (doc._deleted) {
|
||||
logger.debug('Delete', doc);
|
||||
this.removeObserver.notifyObservers({id: doc._id, template: doc.template}, 1);
|
||||
} else {
|
||||
this.updateObserver.notifyObservers(doc, 1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private async beginSync(localName: string) {
|
||||
try {
|
||||
//const remoteDbName = "db1";
|
||||
const userHex = remoteDbName.split('-');
|
||||
if (userHex.length < 2) {
|
||||
return;
|
||||
}
|
||||
const username = hex_to_ascii(userHex[1]);
|
||||
const remoteUserName = username;
|
||||
const password = "password";
|
||||
|
||||
const userHex = ascii_to_hex(localName);
|
||||
const remoteDbName = 'userdb-' + userHex;
|
||||
const remoteUserName = localName;
|
||||
const password = localName;
|
||||
const dbs = await axios.get(import.meta.env.VITE_SYNCDB_ENDPOINT + 'list');
|
||||
logger.debug(dbs.data);
|
||||
if (dbs.data.indexOf(remoteDbName) == -1) {
|
||||
logger.warn('sync target missing');
|
||||
logger.warn('sync target missing attempting to create');
|
||||
const newdb = await axios.post(import.meta.env.VITE_CREATE_ENDPOINT,
|
||||
|
||||
{
|
||||
"_id": "org.couchdb.user:" + localName,
|
||||
"name": localName,
|
||||
"password": localName,
|
||||
"roles": ["readers"],
|
||||
"type": "user"
|
||||
}
|
||||
);
|
||||
if (newdb.status == 200) {
|
||||
logger.info('sync target created');
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
const userEndpoint: string = import.meta.env.VITE_USER_ENDPOINT
|
||||
logger.debug(userEndpoint);
|
||||
logger.debug(remoteDbName);
|
||||
@ -262,9 +292,11 @@ export class PouchdbPersistenceManager {
|
||||
{auth: {username: remoteUserName, password: password}, skip_setup: true});
|
||||
const dbInfo = await this.remote.info();
|
||||
logger.debug(dbInfo);
|
||||
syncDoc.bind(this);
|
||||
|
||||
this.db.sync(this.remote, {live: true, retry: true})
|
||||
.on('change', syncDoc)
|
||||
.on('change', (info) => {
|
||||
this.syncDoc(info)
|
||||
})
|
||||
.on('active', function (info) {
|
||||
logger.debug('sync active', info)
|
||||
})
|
||||
@ -272,7 +304,7 @@ export class PouchdbPersistenceManager {
|
||||
logger.debug('sync paused', info)
|
||||
})
|
||||
.on('error', function (err) {
|
||||
logger.debug('sync error', err)
|
||||
logger.error('sync error', err)
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
@ -283,8 +315,17 @@ export class PouchdbPersistenceManager {
|
||||
function hex_to_ascii(input) {
|
||||
var hex = input.toString();
|
||||
let output = '';
|
||||
for (var n = 0; n < hex.length; n += 2) {
|
||||
for (let n = 0; n < hex.length; n += 2) {
|
||||
output += String.fromCharCode(parseInt(hex.substr(n, 2), 16));
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
function ascii_to_hex(str) {
|
||||
const arr1 = [];
|
||||
for (let n = 0, l = str.length; n < l; n++) {
|
||||
var hex = Number(str.charCodeAt(n)).toString(16);
|
||||
arr1.push(hex);
|
||||
}
|
||||
return arr1.join('');
|
||||
}
|
||||
78
src/menus/clickMenu.ts
Normal file
78
src/menus/clickMenu.ts
Normal file
@ -0,0 +1,78 @@
|
||||
import {Button3D, GUI3DManager, PlanePanel, TextBlock} from "@babylonjs/gui";
|
||||
import {AbstractMesh, TransformNode} from "@babylonjs/core";
|
||||
import {DiagramEvent, DiagramEventType} from "../diagram/types/diagramEntity";
|
||||
import {toDiagramEntity} from "../diagram/functions/toDiagramEntity";
|
||||
import {DiagramManager} from "../diagram/diagramManager";
|
||||
|
||||
export class ClickMenu {
|
||||
private static readonly sounds;
|
||||
private readonly entity: AbstractMesh;
|
||||
private readonly manager: GUI3DManager;
|
||||
private readonly transform: TransformNode;
|
||||
private readonly diagramManager: DiagramManager;
|
||||
|
||||
constructor(entity: AbstractMesh, diagramManager: DiagramManager) {
|
||||
this.entity = entity;
|
||||
this.diagramManager = diagramManager;
|
||||
const scene = entity.getScene();
|
||||
const manager = new GUI3DManager(scene);
|
||||
const transform = new TransformNode("transform", scene);
|
||||
|
||||
transform.position = entity.absolutePosition.clone();
|
||||
transform.position.y += entity.scaling.y;
|
||||
|
||||
const panel = new PlanePanel();
|
||||
|
||||
panel.orientation = PlanePanel.FACEFORWARDREVERSED_ORIENTATION;
|
||||
panel.columns = 4;
|
||||
|
||||
manager.controlScaling = .1;
|
||||
manager.addControl(panel);
|
||||
|
||||
panel.addControl(this.makeButton("Remove", "remove"));
|
||||
panel.addControl(this.makeButton("Label", "label"));
|
||||
panel.addControl(this.makeButton("Connect", "connect"));
|
||||
panel.addControl(this.makeButton("Close", "close"));
|
||||
|
||||
panel.linkToTransformNode(transform);
|
||||
this.transform = transform;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
private makeButton(name: string, id: string) {
|
||||
const button = new Button3D(name);
|
||||
//button.scaling = new Vector3(.1, .1, .1);
|
||||
button.name = id;
|
||||
const text = new TextBlock(name, name);
|
||||
text.fontSize = "48px";
|
||||
text.color = "#ffffff";
|
||||
text.alpha = 1;
|
||||
button.content = text;
|
||||
button.onPointerClickObservable.add(() => {
|
||||
switch (id) {
|
||||
case "close":
|
||||
this.dispose();
|
||||
break;
|
||||
case "remove":
|
||||
const event: DiagramEvent = {
|
||||
type: DiagramEventType.REMOVE,
|
||||
entity:
|
||||
toDiagramEntity(this.entity)
|
||||
}
|
||||
this.diagramManager.onDiagramEventObservable.notifyObservers(event, -1);
|
||||
this.dispose();
|
||||
break;
|
||||
case "label":
|
||||
|
||||
|
||||
}
|
||||
|
||||
}, -1, false, this, true);
|
||||
return button;
|
||||
}
|
||||
|
||||
private dispose() {
|
||||
this.manager.dispose();
|
||||
this.transform.dispose();
|
||||
}
|
||||
}
|
||||
@ -13,6 +13,7 @@ export class Handle {
|
||||
private buildHandle() {
|
||||
const scene: Scene = this.transformNode.getScene();
|
||||
const handle = getHandleMesh("handle-" + this.transformNode.id + "-mesh", scene);
|
||||
|
||||
handle.position = Vector3.Zero();
|
||||
handle.metadata = {handle: true};
|
||||
if (this.transformNode) {
|
||||
|
||||
6
src/objects/objectMetaType.ts
Normal file
6
src/objects/objectMetaType.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export type ObjectMetaType = {
|
||||
id: string;
|
||||
parent: string;
|
||||
position: { x: number, y: number, z: number };
|
||||
rotation: { x: number, y: number, z: number };
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
import {AxesViewer, Color3, Mesh, Node, Observable, Scene, TransformNode, Vector3} from "@babylonjs/core";
|
||||
import {AbstractMesh, AxesViewer, Color3, Node, Observable, Scene, TransformNode, Vector3} from "@babylonjs/core";
|
||||
import {GUI3DManager, StackPanel3D,} from "@babylonjs/gui";
|
||||
import {setMenuPosition} from "../util/functions/setMenuPosition";
|
||||
import {buildColor} from "./functions/buildColor";
|
||||
import log from "loglevel";
|
||||
import {Handle} from "../objects/handle";
|
||||
@ -34,7 +33,7 @@ export class Toolbox {
|
||||
new Handle(this.toolboxBaseNode);
|
||||
this.toolboxBaseNode.position.y = .2;
|
||||
//this.toolboxBaseNode.position.z = .05;
|
||||
/**this.axes = new AxesViewer(this.scene);
|
||||
/*this.axes = new AxesViewer(this.scene);
|
||||
this.axes.xAxis.parent = this.toolboxBaseNode;
|
||||
this.axes.yAxis.parent = this.toolboxBaseNode;
|
||||
this.axes.zAxis.parent = this.toolboxBaseNode; */
|
||||
@ -42,12 +41,6 @@ export class Toolbox {
|
||||
this.buildToolbox();
|
||||
}
|
||||
|
||||
public toggle() {
|
||||
this.toolboxBaseNode.parent.setEnabled(!this.toolboxBaseNode.parent.isEnabled(false));
|
||||
setMenuPosition(this.toolboxBaseNode.parent as Mesh, this.scene,
|
||||
Vector3.Zero());
|
||||
}
|
||||
|
||||
public updateToolbox(color: string) {
|
||||
if (color) {
|
||||
if (this.scene.getMeshById("toolbox-color-" + color)) {
|
||||
@ -98,9 +91,27 @@ export class Toolbox {
|
||||
}
|
||||
}
|
||||
//this.toolboxBaseNode.parent.setEnabled(false);
|
||||
setMenuPosition(this.toolboxBaseNode.parent as Mesh, this.scene,
|
||||
Vector3.Zero());
|
||||
const offset = new Vector3(0, 1, 1);
|
||||
if (this.toolboxBaseNode.parent) {
|
||||
const platform = this.scene.getNodeById("platform");
|
||||
if (platform) {
|
||||
const handle = (this.toolboxBaseNode.parent as TransformNode);
|
||||
handle.parent = platform;
|
||||
handle.position = offset;
|
||||
} else {
|
||||
this.scene.onNewMeshAddedObservable.add((mesh: AbstractMesh) => {
|
||||
if (mesh.id == "platform") {
|
||||
const handle = (this.toolboxBaseNode.parent as TransformNode);
|
||||
handle.parent = mesh;
|
||||
handle.position = offset;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*setMenuPosition(this.toolboxBaseNode.parent as Mesh, this.scene,
|
||||
Vector3.Zero());*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import {MeshBuilder, Scene, Vector3} from "@babylonjs/core";
|
||||
|
||||
const debug = false;
|
||||
const debug = true;
|
||||
export function getFrontPosition(distance: number, scene: Scene): Vector3 {
|
||||
const offset = new Vector3(0, 0, distance);
|
||||
offset.applyRotationQuaternionInPlace(scene.activeCamera.absoluteRotation);
|
||||
const newPos = scene.activeCamera.globalPosition.add(offset);
|
||||
//offset.applyRotationQuaternionInPlace(scene.activeCamera.absoluteRotation);
|
||||
const camPos = scene.activeCamera.globalPosition.clone();
|
||||
const newPos = camPos.add(offset);
|
||||
if (debug) {
|
||||
const mesh = MeshBuilder.CreateIcoSphere("front", {radius: .1}, scene);
|
||||
mesh.position = newPos;
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import {Scene, TransformNode, Vector3} from "@babylonjs/core";
|
||||
import {getFrontPosition} from "./getFrontPosition";
|
||||
import {Scene, TransformNode, Vector3, WebXRCamera} from "@babylonjs/core";
|
||||
import log from "loglevel";
|
||||
|
||||
const logger = log.getLogger('setMenuPosition');
|
||||
@ -39,34 +38,33 @@ export function setMenuPosition(node: TransformNode, scene: Scene, offset: Vecto
|
||||
|
||||
*/
|
||||
if (scene.activeCamera) {
|
||||
setPosition(node, scene, offset);
|
||||
//setPosition(node, scene, offset);
|
||||
|
||||
} else {
|
||||
scene.onActiveCameraChanged.add((scene: Scene) => {
|
||||
setPosition(node, scene, offset);
|
||||
//setPosition(node, scene, offset);
|
||||
});
|
||||
logger.error("No active camera");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const debug = true;
|
||||
const debug = false;
|
||||
function setPosition(node: TransformNode, scene: Scene, offset: Vector3 = Vector3.Zero()) {
|
||||
const platform = scene.getNodeById("platform");
|
||||
switch (scene.activeCamera.getClassName()) {
|
||||
case "WebXRCamera":
|
||||
//const oldParent = node.parent;
|
||||
|
||||
window.setTimeout(() => {
|
||||
node.setParent(null);
|
||||
const front = getFrontPosition(1, scene).clone();
|
||||
const camPos = scene.activeCamera.globalPosition.clone();
|
||||
const newPos = new Vector3(front.x + offset.x, 1.2 + offset.y, front.z + offset.z);
|
||||
const camera = scene.activeCamera as WebXRCamera;
|
||||
const front = camera.getFrontPosition(.7);
|
||||
const camPos = camera.globalPosition.clone();
|
||||
const newPos = new Vector3(front.x + offset.x, front.y + offset.y - .3, front.z + offset.z);
|
||||
node.position = newPos;
|
||||
node.lookAt(camPos);
|
||||
// const target = MeshBuilder.CreateIcoSphere("target", {radius: .1}, scene);
|
||||
// target.position = newPos;
|
||||
// target.setParent(platform);
|
||||
node.setParent(platform);
|
||||
}, 1000);
|
||||
break;
|
||||
case "FreeCamera":
|
||||
case "DeviceOrientationCamera":
|
||||
|
||||
@ -18,6 +18,10 @@ export default defineConfig({
|
||||
'^/sync/.*': {
|
||||
target: 'https://www.deepdiagram.com/',
|
||||
changeOrigin: true,
|
||||
},
|
||||
'^/create-db': {
|
||||
target: 'https://www.deepdiagram.com/',
|
||||
changeOrigin: true,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Loading…
Reference in New Issue
Block a user