Updated OPTIONS method for user function

This commit is contained in:
Michael Mainguy 2023-10-31 12:49:36 -05:00
parent bb93e502c9
commit d7d8b414e5
12 changed files with 221 additions and 36 deletions

12
package-lock.json generated
View File

@ -19,11 +19,13 @@
"@cloudflare/workers-types": "^4.20230821.0", "@cloudflare/workers-types": "^4.20230821.0",
"@netlify/functions": "^1.6.0", "@netlify/functions": "^1.6.0",
"@typed-mxgraph/typed-mxgraph": "^1.0.8", "@typed-mxgraph/typed-mxgraph": "^1.0.8",
"@types/file-saver": "^2.0.6",
"@types/node": "^18.14.0", "@types/node": "^18.14.0",
"dexie": "^3.2.4", "dexie": "^3.2.4",
"dexie-observable": "^4.0.1-beta.13", "dexie-observable": "^4.0.1-beta.13",
"earcut": "^2.2.4", "earcut": "^2.2.4",
"events": "^3.3.0", "events": "^3.3.0",
"file-saver": "^2.0.5",
"hls.js": "^1.1.4", "hls.js": "^1.1.4",
"loglevel": "^1.8.1", "loglevel": "^1.8.1",
"mxgraph": "^4.2.2", "mxgraph": "^4.2.2",
@ -974,6 +976,11 @@
"resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.6.tgz", "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.6.tgz",
"integrity": "sha512-H90aoynNhhkQP6DRweEjJp5vfUVdIj7tdPLsu7pq89vODD/lcugKfZOsfgwpvM6XUewEp2N5dCg1Uf3Qe55Dcg==" "integrity": "sha512-H90aoynNhhkQP6DRweEjJp5vfUVdIj7tdPLsu7pq89vODD/lcugKfZOsfgwpvM6XUewEp2N5dCg1Uf3Qe55Dcg=="
}, },
"node_modules/@types/file-saver": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/file-saver/-/file-saver-2.0.6.tgz",
"integrity": "sha512-Mw671DVqoMHbjw0w4v2iiOro01dlT/WhWp5uwecBa0Wg8c+bcZOjgF1ndBnlaxhtvFCgTRBtsGivSVhrK/vnag=="
},
"node_modules/@types/http-cache-semantics": { "node_modules/@types/http-cache-semantics": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz",
@ -2117,6 +2124,11 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/file-saver": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
"integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
},
"node_modules/fill-range": { "node_modules/fill-range": {
"version": "7.0.1", "version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",

View File

@ -31,6 +31,8 @@
"dexie": "^3.2.4", "dexie": "^3.2.4",
"dexie-observable": "^4.0.1-beta.13", "dexie-observable": "^4.0.1-beta.13",
"earcut": "^2.2.4", "earcut": "^2.2.4",
"file-saver": "^2.0.5",
"@types/file-saver": "^2.0.6",
"hls.js": "^1.1.4", "hls.js": "^1.1.4",
"loglevel": "^1.8.1", "loglevel": "^1.8.1",
"mxgraph": "^4.2.2", "mxgraph": "^4.2.2",

View File

@ -23,6 +23,7 @@ import {DiagramExporter} from "./util/diagramExporter";
import {Spinner} from "./util/spinner"; import {Spinner} from "./util/spinner";
import {WebController} from "./controllers/webController"; import {WebController} from "./controllers/webController";
import {PouchdbPersistenceManager} from "./integration/pouchdbPersistenceManager"; import {PouchdbPersistenceManager} from "./integration/pouchdbPersistenceManager";
import {addSceneInspector} from "./util/functions/sceneInspctor";
export class App { export class App {
@ -78,6 +79,7 @@ export class App {
const diagramManager = new DiagramManager(scene, controllers, toolbox, config); const diagramManager = new DiagramManager(scene, controllers, toolbox, config);
const db = new PouchdbPersistenceManager("diagram"); const db = new PouchdbPersistenceManager("diagram");
//diagramManager.setPersistenceManager(db);
db.configObserver.add((newConfig) => { db.configObserver.add((newConfig) => {
config.onConfigChangedObservable.notifyObservers(newConfig, 1); config.onConfigChangedObservable.notifyObservers(newConfig, 1);
@ -253,31 +255,13 @@ export class App {
}); });
*/ */
window.addEventListener("keydown", (ev) => { addSceneInspector(scene);
if (ev.key == "z") {
//voiceManager.startRecording();
}
if (ev.key == "x") {
//voiceManager.stopRecording();
}
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();
}
});
});
}
});
const exportLink = document.querySelector('#downloadLink'); const exportLink = document.querySelector('#downloadLink');
if (exportLink) { if (exportLink) {
exportLink.addEventListener('click', (ev) => { exportLink.addEventListener('click', (ev) => {
ev.preventDefault(); ev.preventDefault();
const exporter = new DiagramExporter(scene); const exporter = new DiagramExporter(scene);
exporter.export(); exporter.exportgltf();
}); });
} }

View File

@ -1,9 +1,18 @@
import {Scene, Vector3, WebXRControllerComponent, WebXRDefaultExperience, WebXRInputSource} from "@babylonjs/core"; import {
Scene,
TransformNode,
Vector2,
Vector3,
WebXRControllerComponent,
WebXRDefaultExperience,
WebXRInputSource
} from "@babylonjs/core";
import {Base} from "./base"; import {Base} from "./base";
import {ControllerEventType, Controllers} from "./controllers"; import {ControllerEventType, Controllers} from "./controllers";
import log from "loglevel"; import log from "loglevel";
import {ConfigMenu} from "../menus/configMenu"; import {ConfigMenu} from "../menus/configMenu";
import {DiagramManager} from "../diagram/diagramManager"; import {DiagramManager} from "../diagram/diagramManager";
import {Button} from "../objects/button";
export class Left extends Base { export class Left extends Base {
@ -25,8 +34,22 @@ export class Left extends Base {
this.moveMovable(value); this.moveMovable(value);
} }
}); });
if (init.components['x-button']) {
const transform = new TransformNode('x-button', scene);
transform.parent = controller.grip;
transform.rotation.x = Math.PI / 2;
transform.scaling = new Vector3(.2, .2, .2);
const xbutton = new Button(transform, 'X', 'toggle toolbox menu', new Vector2(-.5, -.1));
const ybutton = new Button(transform, 'Y', 'toggle settings menu', new Vector2(-.4, .1));
}
this.initXButton(init.components['x-button']); this.initXButton(init.components['x-button']);
this.initYButton(init.components['y-button']); this.initYButton(init.components['y-button']);
const buttonhome = new TransformNode('buttons', scene)
//const xbutton = new Button(buttonhome, 'X', 'open edit menu', new Vector2(0,0));
//const ybutton = new Button(buttonhome, 'Y', 'open edit menu', new Vector2(.4,0));
this.initTrigger(init.components['xr-standard-trigger']); this.initTrigger(init.components['xr-standard-trigger']);
init.components['xr-standard-thumbstick'].onButtonStateChangedObservable.add((value) => { init.components['xr-standard-thumbstick'].onButtonStateChangedObservable.add((value) => {
if (value.pressed) { if (value.pressed) {
@ -58,6 +81,7 @@ export class Left extends Base {
private initXButton(xbutton: WebXRControllerComponent) { private initXButton(xbutton: WebXRControllerComponent) {
if (xbutton) { if (xbutton) {
xbutton.onButtonStateChangedObservable.add((button) => { xbutton.onButtonStateChangedObservable.add((button) => {
if (button.pressed) { if (button.pressed) {
this.controllers.controllerObserver.notifyObservers({ this.controllers.controllerObserver.notifyObservers({

View File

@ -1,9 +1,18 @@
import {Base} from "./base"; import {Base} from "./base";
import {Scene, Vector3, WebXRControllerComponent, WebXRDefaultExperience, WebXRInputSource} from "@babylonjs/core"; import {
Scene,
TransformNode,
Vector2,
Vector3,
WebXRControllerComponent,
WebXRDefaultExperience,
WebXRInputSource
} from "@babylonjs/core";
import {ControllerEventType, Controllers} from "./controllers"; import {ControllerEventType, Controllers} from "./controllers";
import log from "loglevel"; import log from "loglevel";
import {DiagramManager} from "../diagram/diagramManager"; import {DiagramManager} from "../diagram/diagramManager";
import {DiagramListingMenu} from "../menus/diagramListingMenu"; import {DiagramListingMenu} from "../menus/diagramListingMenu";
import {Button} from "../objects/button";
export class Right extends Base { export class Right extends Base {
private listingMenu: DiagramListingMenu; private listingMenu: DiagramListingMenu;
@ -36,6 +45,15 @@ export class Right extends Base {
this.listingMenu = new DiagramListingMenu(this.scene, xr, this.controllers); this.listingMenu = new DiagramListingMenu(this.scene, xr, this.controllers);
this.controller.onMotionControllerInitObservable.add((init) => { this.controller.onMotionControllerInitObservable.add((init) => {
this.initTrigger(init.components['xr-standard-trigger']); this.initTrigger(init.components['xr-standard-trigger']);
if (init.components['a-button']) {
const transform = new TransformNode('a-button', scene);
transform.parent = controller.grip;
transform.rotation.x = Math.PI / 2;
transform.scaling = new Vector3(.2, .2, .2);
const abutton = new Button(transform, 'A', 'toggle edit menu', new Vector2(.5, -.1));
const bbutton = new Button(transform, 'B', 'toggle diagram selector', new Vector2(.4, .1));
}
this.initBButton(init.components['b-button']); this.initBButton(init.components['b-button']);
this.initAButton(init.components['a-button']); this.initAButton(init.components['a-button']);
this.initThumbstick(init.components['xr-standard-thumbstick']); this.initThumbstick(init.components['xr-standard-thumbstick']);

View File

@ -21,7 +21,6 @@ export class PouchdbPersistenceManager implements IPersistenceManager {
console.log(name); console.log(name);
this.config = new PouchDB("config"); this.config = new PouchDB("config");
this.diagramListings = new PouchDB("diagramListings"); this.diagramListings = new PouchDB("diagramListings");
} }
private _currentDiagramId: string; private _currentDiagramId: string;
@ -38,7 +37,6 @@ export class PouchdbPersistenceManager implements IPersistenceManager {
this.diagramListings.put({_id: value, name: "New Diagram"}); this.diagramListings.put({_id: value, name: "New Diagram"});
} }
this.db = new PouchDB(value); this.db = new PouchDB(value);
this.db.sync(this.remote, {live: true}); this.db.sync(this.remote, {live: true});
} }
@ -108,11 +106,11 @@ export class PouchdbPersistenceManager implements IPersistenceManager {
} }
public async getNewRelicData(): Promise<any[]> { public async getNewRelicData(): Promise<any[]> {
return [];
} }
public async setNewRelicData(data: any[]): Promise<any> { public async setNewRelicData(data: any[]): Promise<any> {
return data;
} }
public async setConfig(config: any, initial: boolean = false): Promise<any> { public async setConfig(config: any, initial: boolean = false): Promise<any> {
@ -175,7 +173,6 @@ export class PouchdbPersistenceManager implements IPersistenceManager {
} }
} }
syncDoc = function (info) { syncDoc = function (info) {
console.log(info); console.log(info);
if (info.direction == 'pull') { if (info.direction == 'pull') {

80
src/menus/cameraMenu.ts Normal file
View File

@ -0,0 +1,80 @@
import {Color3, DynamicTexture, Mesh, MeshBuilder, Scene, StandardMaterial, Vector3} from "@babylonjs/core";
export class CameraMenu {
private scene: Scene;
private xr;
private controllers;
constructor(scene, xr, controllers) {
this.scene = scene;
this.xr = xr;
this.controllers = controllers;
this.buildMenu(1, new Vector3(0, 1, 0));
//this.buildMenu(4, new Vector3(0,2,0));
//this.buildMenu(5, new Vector3(1,2,0));
//this.buildMenu(6, new Vector3(1,1,0));
}
private buildMenu(camnum: number, position: Vector3) {
const camerasphere = MeshBuilder.CreateSphere("camerasphere", {
diameter: 10,
slice: .5,
sideOrientation: Mesh.DOUBLESIDE
}, this.scene);
//const camerasphere = MeshBuilder.CreatePlane("camerasphere", {width: 1.6, height: .6, sideOrientation: Mesh.DOUBLESIDE }, this.scene);
camerasphere.position = position;
const material = new StandardMaterial("cameramaterial", this.scene);
material.emissiveColor = new Color3(1, 1, 1);
//camerasphere.rotation.z = Math.PI;
/*const texture = new VideoTexture("video",
'https://local.immersiveidea.com/',
this.scene);
*/
//const texture = new DynamicTexture("dynamic texture", {width: 512, height: 256}, this.scene, false);
const texture = new DynamicTexture('texture', {width: 1600, height: 1600}, this.scene);
//const img = document.createElement('img');
//document.body.append(img);
//img.width=2592;
//img.height=1944;
material.diffuseTexture = texture;
const img = new Image();
img.src = 'https://cameras.immersiveidea.com/mjpg/video.mjpg?camera=' + camnum + '&timestamp=1698497537140';
const ctx = texture.getContext();
img.onload = () => {
ctx.drawImage(img, 250, 0, 2112, 1940, 0, 0, 1600, 1600);
texture.update();
window.setInterval((texture, img, ctx) => {
//const start = new Date();
ctx.drawImage(img, 250, 0, 2112, 1940, 0, 0, 1600, 1600);
texture.update();
//console.log(new Date() - start);
}, 60, texture, img, ctx);
}
//https://cameras.immersiveidea.com/mjpg/video.mjpg?camera=1&timestamp=1698497537140');
//texture.getContext().drawImage(img, 0,0);
texture.onLoadObservable.add(() => {
console.log('texture loaded');
});
this.scene.onAfterRenderObservable.add(() => {
// texture._rebuild();
}, 1, true, this);
camerasphere.material = material;
/*texture.video.play().then(() => {
console.log('video playing');
}).catch((err) => {
console.log(err);
console.log("here");
});
*/
console.log('video loaded');
//Material.diffuseColor = new Color3(0, 0, 0);
//https://cameras.immersiveidea.com/mjpg/video.mjpg?camera=1&resolution=2592x1944&compression=30&mirror=0&rotation=0&textsize=medium&textposition=top&textbackgroundcolor=black&textcolor=white&text=0&clock=0&date=0&overlayimage=0&fps=0&videokeyframeinterval=13&videobitrate=0&maxframesize=0&timestamp=1698491710423
}
}

View File

@ -27,6 +27,7 @@ import {Controllers} from "../controllers/controllers";
import {setMenuPosition} from "../util/functions/setMenuPosition"; import {setMenuPosition} from "../util/functions/setMenuPosition";
import {DiagramExporter} from "../util/diagramExporter"; import {DiagramExporter} from "../util/diagramExporter";
import {SoccerMenu} from "../soccer/soccerMenu"; import {SoccerMenu} from "../soccer/soccerMenu";
import {CameraMenu} from "./cameraMenu";
export class EditMenu extends AbstractMenu { export class EditMenu extends AbstractMenu {
private state: EditMenuState = EditMenuState.NONE; private state: EditMenuState = EditMenuState.NONE;
@ -37,6 +38,7 @@ export class EditMenu extends AbstractMenu {
private readonly diagramManager: DiagramManager; private readonly diagramManager: DiagramManager;
private connection: DiagramConnection = null; private connection: DiagramConnection = null;
private panel: PlanePanel; private panel: PlanePanel;
private cameraMenu: CameraMenu = null;
private sounds: DiaSounds; private sounds: DiaSounds;
private get isVisible(): boolean { private get isVisible(): boolean {
@ -237,13 +239,13 @@ export class EditMenu extends AbstractMenu {
panel.columns = 4; panel.columns = 4;
this.manager.addControl(panel); this.manager.addControl(panel);
panel.addControl(this.makeButton("Cameras", "camera"));
panel.addControl(this.makeButton("Modify", "modify")); panel.addControl(this.makeButton("Modify", "modify"));
panel.addControl(this.makeButton("Remove", "remove")); panel.addControl(this.makeButton("Remove", "remove"));
panel.addControl(this.makeButton("Add Label", "label")); panel.addControl(this.makeButton("Add Label", "label"));
panel.addControl(this.makeButton("Copy", "copy")); panel.addControl(this.makeButton("Copy", "copy"));
panel.addControl(this.makeButton("Connect", "connect")); panel.addControl(this.makeButton("Connect", "connect"));
panel.addControl(this.makeButton("Export", "export")); panel.addControl(this.makeButton("Export GLTF", "exportgltf"));
panel.addControl(this.makeButton("Recolor", "recolor")); panel.addControl(this.makeButton("Recolor", "recolor"));
panel.addControl(this.makeButton("New Relic", "newrelic")); panel.addControl(this.makeButton("New Relic", "newrelic"));
panel.addControl(this.makeButton("Soccer", "soccer")); panel.addControl(this.makeButton("Soccer", "soccer"));
@ -303,12 +305,16 @@ export class EditMenu extends AbstractMenu {
case "newrelic": case "newrelic":
this.showNewRelic(); this.showNewRelic();
break; break;
case "export": case "exportgltf":
this.download(); this.downloadgltf();
break; break;
case "soccer": case "soccer":
this.createSoccerField(); this.createSoccerField();
break; break;
case "camera":
if (!this.cameraMenu) {
this.cameraMenu = new CameraMenu(this.scene, null, null);
}
default: default:
this.logger.error("Unknown button"); this.logger.error("Unknown button");
return; return;
@ -324,8 +330,8 @@ export class EditMenu extends AbstractMenu {
} }
} }
private download() { private downloadgltf() {
const exporter = new DiagramExporter(this.scene); const exporter = new DiagramExporter(this.scene);
exporter.export(); exporter.exportgltf();
} }
} }

View File

@ -30,6 +30,4 @@ export class IntegrationMenu extends AbstractMenu {
grid.addControl(labelText2, 1, 0); grid.addControl(labelText2, 1, 0);
setMenuPosition(this.plane, this.scene); setMenuPosition(this.plane, this.scene);
} }
} }

43
src/objects/button.ts Normal file
View File

@ -0,0 +1,43 @@
import {DynamicTexture, MeshBuilder, StandardMaterial, TransformNode, Vector2, Vector3} from "@babylonjs/core";
export class Button {
private parent: TransformNode;
constructor(parent: TransformNode, label: string, description: string, position: Vector2) {
this.parent = parent;
this.buildButton(label, description, position);
}
private buildButton(label: string, description: string, position: Vector2) {
const button = MeshBuilder.CreateSphere(label, {diameter: .1}, this.parent.getScene());
const descriptionPlane = MeshBuilder.CreatePlane(label, {width: .3, height: .1}, this.parent.getScene());
button.parent = this.parent;
button.position.y = position.y;
button.position.x = position.x;
descriptionPlane.parent = this.parent;
descriptionPlane.position.y = position.y - .1;
descriptionPlane.position.x = position.x;
const descTexture = new DynamicTexture('texture_desc_' + label, {
width: 768,
height: 256
}, this.parent.getScene());
const descMaterial = new StandardMaterial('button_desc_' + label)
descriptionPlane.material = descMaterial;
descMaterial.diffuseTexture = descTexture;
descTexture.drawText(description, null, null, 'bold 64px Arial',
'#000000', '#ffffff', true);
const texture = new DynamicTexture('texture_' + label, {width: 256, height: 256}, this.parent.getScene());
const material = new StandardMaterial('button_' + label)
button.material = material;
material.diffuseTexture = texture;
texture.drawText(label, null, null, 'bold 128px Arial',
'#000000', '#ffffff', true);
button.scaling = new Vector3(.1, 1, 1);
button.rotation.y = Math.PI / 2;
button.rotation.z = Math.PI;
}
}

View File

@ -7,7 +7,7 @@ export class DiagramExporter {
this.scene = scene; this.scene = scene;
} }
public export() { public exportgltf() {
import("@babylonjs/serializers").then((serializers) => { import("@babylonjs/serializers").then((serializers) => {
serializers.GLTF2Export.GLBAsync(this.scene, 'diagram.glb', { serializers.GLTF2Export.GLBAsync(this.scene, 'diagram.glb', {
shouldExportNode: function (node) { shouldExportNode: function (node) {

View File

@ -0,0 +1,21 @@
export function addSceneInspector(scene) {
window.addEventListener("keydown", (ev) => {
if (ev.key == "z") {
//voiceManager.startRecording();
}
if (ev.key == "x") {
//voiceManager.stopRecording();
}
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();
}
});
});
}
});
}