Committed new Relic Starting point.
Committed new Relic Starting point.
This commit is contained in:
parent
fab12ff6ea
commit
ceaf6c4fb5
23
package-lock.json
generated
23
package-lock.json
generated
@ -23,6 +23,7 @@
|
|||||||
"earcut": "^2.2.4",
|
"earcut": "^2.2.4",
|
||||||
"loglevel": "^1.8.1",
|
"loglevel": "^1.8.1",
|
||||||
"mxgraph": "^4.2.2",
|
"mxgraph": "^4.2.2",
|
||||||
|
"niceware": "^4.0.0",
|
||||||
"p2p-data-channel": "^1.10.7",
|
"p2p-data-channel": "^1.10.7",
|
||||||
"query-string": "^8.1.0",
|
"query-string": "^8.1.0",
|
||||||
"recordrtc": "^5.6.2",
|
"recordrtc": "^5.6.2",
|
||||||
@ -1248,6 +1249,11 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/binary-search": {
|
||||||
|
"version": "1.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/binary-search/-/binary-search-1.3.6.tgz",
|
||||||
|
"integrity": "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA=="
|
||||||
|
},
|
||||||
"node_modules/bl": {
|
"node_modules/bl": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||||
@ -2890,6 +2896,15 @@
|
|||||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/niceware": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/niceware/-/niceware-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-7uFcxHr5zwNZO4NEMwxK0N+GbqVMGp2YLZ8x/0dx/nxiT0qCt1zL3hZfqawQoq4XiP2OWa665Xid0g/LyoMfQA==",
|
||||||
|
"dependencies": {
|
||||||
|
"binary-search": "^1.3.6",
|
||||||
|
"randombytes": "^2.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-fetch": {
|
"node_modules/node-fetch": {
|
||||||
"version": "2.6.12",
|
"version": "2.6.12",
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz",
|
||||||
@ -3268,6 +3283,14 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/randombytes": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "^5.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/readable-stream": {
|
"node_modules/readable-stream": {
|
||||||
"version": "3.6.2",
|
"version": "3.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
"earcut": "^2.2.4",
|
"earcut": "^2.2.4",
|
||||||
"loglevel": "^1.8.1",
|
"loglevel": "^1.8.1",
|
||||||
"mxgraph": "^4.2.2",
|
"mxgraph": "^4.2.2",
|
||||||
|
"niceware": "^4.0.0",
|
||||||
"p2p-data-channel": "^1.10.7",
|
"p2p-data-channel": "^1.10.7",
|
||||||
"query-string": "^8.1.0",
|
"query-string": "^8.1.0",
|
||||||
"recordrtc": "^5.6.2",
|
"recordrtc": "^5.6.2",
|
||||||
|
|||||||
@ -96,12 +96,15 @@ export class App {
|
|||||||
const diagramManager = new DiagramManager(scene, xr.baseExperience, controllers);
|
const diagramManager = new DiagramManager(scene, xr.baseExperience, controllers);
|
||||||
const rig = new Rigplatform(scene, xr, diagramManager, controllers);
|
const rig = new Rigplatform(scene, xr, diagramManager, controllers);
|
||||||
const toolbox = new Toolbox(scene, xr.baseExperience, diagramManager, controllers);
|
const toolbox = new Toolbox(scene, xr.baseExperience, diagramManager, controllers);
|
||||||
|
|
||||||
//const dioManager = new DrawioManager(scene, diagramManager);
|
//const dioManager = new DrawioManager(scene, diagramManager);
|
||||||
import ('./integration/indexdbPersistenceManager').then((module) => {
|
import ('./integration/indexdbPersistenceManager').then((module) => {
|
||||||
const persistenceManager = new module.IndexdbPersistenceManager("diagram");
|
const persistenceManager = new module.IndexdbPersistenceManager("diagram");
|
||||||
diagramManager.setPersistenceManager(persistenceManager);
|
diagramManager.setPersistenceManager(persistenceManager);
|
||||||
AppConfig.config.setPersistenceManager(persistenceManager);
|
AppConfig.config.setPersistenceManager(persistenceManager);
|
||||||
persistenceManager.initialize();
|
persistenceManager.initialize();
|
||||||
|
//const newRelicData = new NewRelicData(persistenceManager, scene);
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,6 @@ import {Scene, Vector3, WebXRControllerComponent, WebXRDefaultExperience, WebXRI
|
|||||||
import {Controllers} from "./controllers";
|
import {Controllers} from "./controllers";
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import {DiagramManager} from "../diagram/diagramManager";
|
import {DiagramManager} from "../diagram/diagramManager";
|
||||||
import {NewRelicData} from "../integration/newRelic/newRelicData";
|
|
||||||
|
|
||||||
export class Right extends Base {
|
export class Right extends Base {
|
||||||
constructor(controller:
|
constructor(controller:
|
||||||
@ -22,8 +21,6 @@ export class Right extends Base {
|
|||||||
if (bbutton) {
|
if (bbutton) {
|
||||||
bbutton.onButtonStateChangedObservable.add((button) => {
|
bbutton.onButtonStateChangedObservable.add((button) => {
|
||||||
if (button.pressed) {
|
if (button.pressed) {
|
||||||
const newRelic = new NewRelicData();
|
|
||||||
newRelic.getNewRelicData();
|
|
||||||
this.controllers.controllerObserver.notifyObservers({type: 'b-button', value: button.value});
|
this.controllers.controllerObserver.notifyObservers({type: 'b-button', value: button.value});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -27,6 +27,10 @@ export interface IPersistenceManager {
|
|||||||
|
|
||||||
addDiagram(diagram: DiagramListing);
|
addDiagram(diagram: DiagramListing);
|
||||||
|
|
||||||
|
getNewRelicData(): Promise<any[]>;
|
||||||
|
|
||||||
|
setNewRelicData(data: any): Promise<any>;
|
||||||
|
|
||||||
removeDiagram(diagram: DiagramListing);
|
removeDiagram(diagram: DiagramListing);
|
||||||
|
|
||||||
add(mesh: AbstractMesh);
|
add(mesh: AbstractMesh);
|
||||||
|
|||||||
@ -16,10 +16,11 @@ export class IndexdbPersistenceManager implements IPersistenceManager {
|
|||||||
|
|
||||||
constructor(name: string) {
|
constructor(name: string) {
|
||||||
this.db = new Dexie(name);
|
this.db = new Dexie(name);
|
||||||
const version = 3;
|
const version = 5;
|
||||||
this.db.version(version).stores({config: "id,gridSnap,rotateSnap,createSnap"});
|
this.db.version(version).stores({config: "id,gridSnap,rotateSnap,createSnap"});
|
||||||
this.db.version(version).stores({entities: "id,diagramlistingid,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.db.version(version).stores({diagramlisting: "id,name,description,sharekey"});
|
||||||
|
this.db.version(version).stores({newRelicData: "id,priority, incidentId"});
|
||||||
this.logger.debug("IndexdbPersistenceManager constructed");
|
this.logger.debug("IndexdbPersistenceManager constructed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,6 +84,17 @@ export class IndexdbPersistenceManager implements IPersistenceManager {
|
|||||||
this.diagramListingObserver.notifyObservers(event);
|
this.diagramListingObserver.notifyObservers(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async setNewRelicData(data: any[]) {
|
||||||
|
this.db["newRelicData"].clear();
|
||||||
|
data.forEach((d) => {
|
||||||
|
this.db["newRelicData"].add(d);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getNewRelicData(): Promise<any[]> {
|
||||||
|
return this.db["newRelicData"].toArray();
|
||||||
|
}
|
||||||
|
|
||||||
public async initialize() {
|
public async initialize() {
|
||||||
this.logger.info('initialize', this.db['entities'].length);
|
this.logger.info('initialize', this.db['entities'].length);
|
||||||
const configs = await this.db['config'].toArray();
|
const configs = await this.db['config'].toArray();
|
||||||
|
|||||||
@ -1,18 +1,199 @@
|
|||||||
|
import {IPersistenceManager} from "../iPersistenceManager";
|
||||||
|
import {
|
||||||
|
AbstractMesh,
|
||||||
|
Color3,
|
||||||
|
DynamicTexture,
|
||||||
|
InstancedMesh,
|
||||||
|
MeshBuilder,
|
||||||
|
Scene,
|
||||||
|
StandardMaterial,
|
||||||
|
Vector3
|
||||||
|
} from "@babylonjs/core";
|
||||||
|
|
||||||
export class NewRelicData {
|
export class NewRelicData {
|
||||||
private readonly key: string;
|
private key: string;
|
||||||
private readonly account: string;
|
private account: string;
|
||||||
|
private data: any[];
|
||||||
|
private scene: Scene;
|
||||||
|
private persistenceManager: IPersistenceManager;
|
||||||
|
private policyLabels: AbstractMesh[] = [];
|
||||||
|
|
||||||
constructor() {
|
constructor(persistenceManager: IPersistenceManager, scene: Scene) {
|
||||||
|
this.persistenceManager = persistenceManager;
|
||||||
|
this.scene = scene;
|
||||||
|
this.persistenceManager.getNewRelicData()
|
||||||
|
.then((data) => {
|
||||||
|
this.data = data;
|
||||||
|
this.getNewRelicData().then(() => {
|
||||||
|
this.drawGraph();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public setCredentials(key: string, account: string) {
|
||||||
|
this.key = key;
|
||||||
|
this.account = account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async clearData() {
|
||||||
|
this.data = [];
|
||||||
|
await this.persistenceManager.setNewRelicData(this.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getNewRelicData() {
|
public async getNewRelicData() {
|
||||||
try {
|
if (this.data && this.data.length > 0) {
|
||||||
|
console.warn("Already have data, early return");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch('https://deepdiagram.com/.netlify/functions/nerdgraph', {
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'include',
|
||||||
|
body: '{"query": "{actor { nrql(query: \\"select * from NrAiIncident \\", accounts: ' + this.account + ') { results } } }"}',
|
||||||
|
headers: {"Api-Key": this.key}
|
||||||
|
});
|
||||||
|
const data = await res.json();
|
||||||
|
if (data?.data?.actor?.nrql?.results) {
|
||||||
|
const newdata = data.data.actor.nrql.results.map((item: any) => {
|
||||||
|
item.id = item.incidentId;
|
||||||
|
item.policyName = item.policyName ? item.policyName : "No Policy";
|
||||||
|
return item
|
||||||
|
});
|
||||||
|
await this.persistenceManager.setNewRelicData(newdata);
|
||||||
|
this.data = newdata;
|
||||||
|
}
|
||||||
|
console.log(JSON.stringify(data, null, 2));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public drawGraph() {
|
||||||
|
this.data.sort((a, b) => {
|
||||||
|
return parseInt(a.openTime) - parseInt(b.openTime);
|
||||||
|
});
|
||||||
|
|
||||||
|
const duration = this.data[this.data.length - 1].openTime - this.data[0].openTime;
|
||||||
|
console.log(duration);
|
||||||
|
const interval = 10 / duration;
|
||||||
|
const first = parseInt(this.data[0].openTime);
|
||||||
|
const material = new StandardMaterial("material", this.scene);
|
||||||
|
material.diffuseColor = new Color3(0, 0, .7);
|
||||||
|
material.alpha = .3;
|
||||||
|
const baseMesh = MeshBuilder.CreateBox("baseItem", {width: 1, height: 1, depth: 1}, this.scene);
|
||||||
|
baseMesh.material = material;
|
||||||
|
|
||||||
|
const warningMaterial = new StandardMaterial("warningMaterial", this.scene);
|
||||||
|
warningMaterial.diffuseColor = new Color3(.7, .7, .2);
|
||||||
|
warningMaterial.alpha = .5;
|
||||||
|
const warningMesh = MeshBuilder.CreateBox("warningItem", {width: 1, height: 1, depth: 1}, this.scene);
|
||||||
|
warningMesh.material = warningMaterial;
|
||||||
|
|
||||||
|
const criticalMaterial = new StandardMaterial("criticalMaterial", this.scene);
|
||||||
|
criticalMaterial.diffuseColor = new Color3(.9, .2, .2);
|
||||||
|
criticalMaterial.alpha = .7;
|
||||||
|
const criticalMesh = MeshBuilder.CreateBox("criticalItem", {width: 1, height: 1, depth: 1}, this.scene);
|
||||||
|
criticalMesh.material = criticalMaterial;
|
||||||
|
|
||||||
|
|
||||||
|
const policies: Map<String, { x: number, y: number }> = new Map<string, { x: number, y: number }>();
|
||||||
|
this.data.forEach((item) => {
|
||||||
|
const policy = item.policyName ? item.policyName : "No Policy";
|
||||||
|
let x = 0;
|
||||||
|
let y: number = 0;
|
||||||
|
if (policies.has(policy)) {
|
||||||
|
const value = policies.get(policy);
|
||||||
|
x = value.x;
|
||||||
|
y = value.y + .105;
|
||||||
|
policies.set(policy, {x, y});
|
||||||
|
} else {
|
||||||
|
policies.set(policy, {x: policies.size / 10, y: 0});
|
||||||
|
x = policies.get(policy).x;
|
||||||
|
const policyLabel = this.buildText(policy);
|
||||||
|
policyLabel.scaling = new Vector3(3, 3, 3);
|
||||||
|
policyLabel.position = new Vector3(x, .4, 0);
|
||||||
|
policyLabel.rotation.x = Math.PI / 2;
|
||||||
|
policyLabel.rotation.y = -Math.PI / 2;
|
||||||
|
|
||||||
|
this.policyLabels.push(policyLabel);
|
||||||
|
}
|
||||||
|
const start = parseInt(item.openTime) - first;
|
||||||
|
let end = duration;
|
||||||
|
if (item.closeTime) {
|
||||||
|
end = parseInt(item.closeTime) - first;
|
||||||
|
}
|
||||||
|
let box: AbstractMesh;
|
||||||
|
switch (item.priority) {
|
||||||
|
case "critical":
|
||||||
|
box = new InstancedMesh(item.id, criticalMesh);
|
||||||
|
break;
|
||||||
|
case "warning":
|
||||||
|
box = new InstancedMesh(item.id, warningMesh);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
box = new InstancedMesh(item.id, baseMesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
box.position = new Vector3(x, y + .5, (start * interval));
|
||||||
|
if (item.closeTime) {
|
||||||
|
box.scaling = new Vector3(.1, .1, (end - start) * interval);
|
||||||
|
} else {
|
||||||
|
box.scaling = new Vector3(.1, .1, .01);
|
||||||
|
}
|
||||||
|
box.position.z = box.position.z + box.scaling.z / 2;
|
||||||
|
|
||||||
|
const startLabel = this.buildText(new Date(start + first).toLocaleString());
|
||||||
|
startLabel.position = box.position.add(new Vector3(.05, .05, 0));
|
||||||
|
startLabel.position.z = (start * interval) - .01;
|
||||||
|
|
||||||
|
const endLabel = this.buildText(new Date(end + first).toLocaleString());
|
||||||
|
endLabel.position = box.position.add(new Vector3(.05, .05, 0));
|
||||||
|
endLabel.position.z = (end * interval) + .01;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
this.scene.onBeforeRenderObservable.add(() => {
|
||||||
|
this.policyLabels.forEach((label) => {
|
||||||
|
label.position.z = this.scene.activeCamera.globalPosition.z;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildText(text: string) {
|
||||||
|
//Set font
|
||||||
|
const height = 0.03;
|
||||||
|
const font_size = 24;
|
||||||
|
const font = "bold " + font_size + "px Arial";
|
||||||
|
//Set height for dynamic texture
|
||||||
|
const DTHeight = 1.5 * font_size; //or set as wished
|
||||||
|
//Calc Ratio
|
||||||
|
const ratio = height / DTHeight;
|
||||||
|
|
||||||
|
//Use a temporary dynamic texture to calculate the length of the text on the dynamic texture canvas
|
||||||
|
const temp = new DynamicTexture("DynamicTexture", 32, this.scene);
|
||||||
|
const tmpctx = temp.getContext();
|
||||||
|
tmpctx.font = font;
|
||||||
|
const DTWidth = tmpctx.measureText(text).width + 8;
|
||||||
|
|
||||||
|
//Calculate width the plane has to be
|
||||||
|
const planeWidth = DTWidth * ratio;
|
||||||
|
|
||||||
|
//Create dynamic texture and write the text
|
||||||
|
const dynamicTexture = new DynamicTexture("DynamicTexture", {
|
||||||
|
width: DTWidth,
|
||||||
|
height: DTHeight
|
||||||
|
}, this.scene, false);
|
||||||
|
const mat = new StandardMaterial("mat", this.scene);
|
||||||
|
mat.diffuseTexture = dynamicTexture;
|
||||||
|
dynamicTexture.drawText(text, null, null, font, "#000000", "#ffffff", true);
|
||||||
|
|
||||||
|
//Create plane and set dynamic texture as material
|
||||||
|
const plane = MeshBuilder.CreatePlane("text", {width: planeWidth, height: height}, this.scene);
|
||||||
|
|
||||||
|
plane.material = mat;
|
||||||
|
|
||||||
|
return plane;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
15
src/menus/baseMenu.ts
Normal file
15
src/menus/baseMenu.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import {Scene, WebXRExperienceHelper} from "@babylonjs/core";
|
||||||
|
import {Controllers} from "../controllers/controllers";
|
||||||
|
|
||||||
|
export class BaseMenu {
|
||||||
|
protected scene: Scene;
|
||||||
|
protected xr: WebXRExperienceHelper;
|
||||||
|
protected controllers: Controllers;
|
||||||
|
|
||||||
|
constructor(scene: Scene, xr: WebXRExperienceHelper, controllers: Controllers) {
|
||||||
|
this.scene = scene;
|
||||||
|
this.xr = xr;
|
||||||
|
this.controllers = controllers;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -5,19 +5,15 @@ import log from "loglevel";
|
|||||||
import {AppConfig} from "../util/appConfig";
|
import {AppConfig} from "../util/appConfig";
|
||||||
import {Controllers} from "../controllers/controllers";
|
import {Controllers} from "../controllers/controllers";
|
||||||
import {DiaSounds} from "../util/diaSounds";
|
import {DiaSounds} from "../util/diaSounds";
|
||||||
|
import {BaseMenu} from "./baseMenu";
|
||||||
|
|
||||||
export class ConfigMenu {
|
export class ConfigMenu extends BaseMenu {
|
||||||
private readonly scene: Scene;
|
|
||||||
private readonly xr: WebXRExperienceHelper;
|
|
||||||
private configPlane: AbstractMesh = null;
|
private configPlane: AbstractMesh = null;
|
||||||
|
|
||||||
private controllers: Controllers;
|
|
||||||
private yObserver;
|
private yObserver;
|
||||||
|
|
||||||
constructor(scene: Scene, xr: WebXRExperienceHelper, controllers: Controllers) {
|
constructor(scene: Scene, xr: WebXRExperienceHelper, controllers: Controllers) {
|
||||||
this.scene = scene;
|
super(scene, xr, controllers);
|
||||||
this.xr = xr;
|
|
||||||
this.controllers = controllers;
|
|
||||||
if (!this.yObserver) {
|
if (!this.yObserver) {
|
||||||
this.controllers.controllerObserver.add((event) => {
|
this.controllers.controllerObserver.add((event) => {
|
||||||
if (event.type == 'y-button') {
|
if (event.type == 'y-button') {
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import {
|
|||||||
Vector3,
|
Vector3,
|
||||||
WebXRDefaultExperience
|
WebXRDefaultExperience
|
||||||
} from "@babylonjs/core";
|
} from "@babylonjs/core";
|
||||||
import {Button3D, GUI3DManager, StackPanel3D, TextBlock} from "@babylonjs/gui";
|
import {Button3D, GUI3DManager, PlanePanel, TextBlock} from "@babylonjs/gui";
|
||||||
import {DiagramManager} from "../diagram/diagramManager";
|
import {DiagramManager} from "../diagram/diagramManager";
|
||||||
import {EditMenuState} from "./editMenuState";
|
import {EditMenuState} from "./editMenuState";
|
||||||
import {DiagramEvent, DiagramEventType} from "../diagram/diagramEntity";
|
import {DiagramEvent, DiagramEventType} from "../diagram/diagramEntity";
|
||||||
@ -23,6 +23,7 @@ import {CameraHelper} from "../util/cameraHelper";
|
|||||||
import {TextLabel} from "../diagram/textLabel";
|
import {TextLabel} from "../diagram/textLabel";
|
||||||
import {DiagramConnection} from "../diagram/diagramConnection";
|
import {DiagramConnection} from "../diagram/diagramConnection";
|
||||||
import {GLTF2Export} from "@babylonjs/serializers";
|
import {GLTF2Export} from "@babylonjs/serializers";
|
||||||
|
import {AppConfig} from "../util/appConfig";
|
||||||
|
|
||||||
export class EditMenu {
|
export class EditMenu {
|
||||||
private state: EditMenuState = EditMenuState.NONE;
|
private state: EditMenuState = EditMenuState.NONE;
|
||||||
@ -34,60 +35,8 @@ export class EditMenu {
|
|||||||
private readonly xr: WebXRDefaultExperience;
|
private readonly xr: WebXRDefaultExperience;
|
||||||
private readonly diagramManager: DiagramManager;
|
private readonly diagramManager: DiagramManager;
|
||||||
private connection: DiagramConnection = null;
|
private connection: DiagramConnection = null;
|
||||||
private panel: StackPanel3D;
|
private panel: PlanePanel;
|
||||||
|
private buttonMaterial: StandardMaterial;
|
||||||
constructor(scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager) {
|
|
||||||
this.scene = scene;
|
|
||||||
this.xr = xr;
|
|
||||||
this.diagramManager = diagramManager;
|
|
||||||
this.gizmoManager = new GizmoManager(scene);
|
|
||||||
this.gizmoManager.boundingBoxGizmoEnabled = true;
|
|
||||||
this.gizmoManager.gizmos.boundingBoxGizmo.scaleBoxSize = .020;
|
|
||||||
this.gizmoManager.gizmos.boundingBoxGizmo.rotationSphereSize = .020;
|
|
||||||
this.gizmoManager.gizmos.boundingBoxGizmo.scaleDragSpeed = 2;
|
|
||||||
this.gizmoManager.clearGizmoOnEmptyPointerEvent = true;
|
|
||||||
this.gizmoManager.usePointerToAttachGizmos = false;
|
|
||||||
this.manager = new GUI3DManager(this.scene);
|
|
||||||
const panel = new StackPanel3D();
|
|
||||||
|
|
||||||
this.manager.addControl(panel);
|
|
||||||
panel.addControl(this.makeButton("Modify", "modify"));
|
|
||||||
panel.addControl(this.makeButton("Remove", "remove"));
|
|
||||||
panel.addControl(this.makeButton("Add Label", "label"));
|
|
||||||
panel.addControl(this.makeButton("Copy", "copy"));
|
|
||||||
panel.addControl(this.makeButton("Connect", "connect"));
|
|
||||||
panel.addControl(this.makeButton("Export", "export"));
|
|
||||||
panel.addControl(this.makeButton("Recolor", "recolor"));
|
|
||||||
|
|
||||||
//panel.addControl(this.makeButton("Add Ring Cameras", "addRingCameras"));
|
|
||||||
this.manager.controlScaling = .1;
|
|
||||||
this.scene.onPointerObservable.add((pointerInfo) => {
|
|
||||||
switch (pointerInfo.type) {
|
|
||||||
case PointerEventTypes.POINTERPICK:
|
|
||||||
const pickedMesh = pointerInfo.pickInfo?.pickedMesh;
|
|
||||||
if (pickedMesh.metadata?.template &&
|
|
||||||
pickedMesh?.parent?.parent?.id != "toolbox") {
|
|
||||||
this.diagramEntityPicked(pointerInfo).then(() => {
|
|
||||||
this.logger.debug("handled");
|
|
||||||
}).catch((e) => {
|
|
||||||
this.logger.error(e);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
const tool = pickedMesh?.metadata?.tool;
|
|
||||||
if (tool) {
|
|
||||||
this.logger.debug("tool type", tool);
|
|
||||||
this.paintColor = (pickedMesh.material as StandardMaterial).diffuseColor.toHexString();
|
|
||||||
this.logger.debug((pickedMesh.material as StandardMaterial).diffuseColor.toHexString());
|
|
||||||
this.logger.debug(pickedMesh.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.panel = panel;
|
|
||||||
this.isVisible = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private get isVisible(): boolean {
|
private get isVisible(): boolean {
|
||||||
return this.panel.isVisible;
|
return this.panel.isVisible;
|
||||||
@ -128,13 +77,70 @@ export class EditMenu {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constructor(scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager) {
|
||||||
|
this.scene = scene;
|
||||||
|
this.xr = xr;
|
||||||
|
this.diagramManager = diagramManager;
|
||||||
|
this.gizmoManager = new GizmoManager(scene);
|
||||||
|
this.gizmoManager.boundingBoxGizmoEnabled = true;
|
||||||
|
this.gizmoManager.gizmos.boundingBoxGizmo.scaleBoxSize = .020;
|
||||||
|
this.gizmoManager.gizmos.boundingBoxGizmo.rotationSphereSize = .020;
|
||||||
|
this.gizmoManager.gizmos.boundingBoxGizmo.scaleDragSpeed = 2;
|
||||||
|
this.gizmoManager.clearGizmoOnEmptyPointerEvent = true;
|
||||||
|
this.gizmoManager.usePointerToAttachGizmos = false;
|
||||||
|
this.manager = new GUI3DManager(this.scene);
|
||||||
|
const panel = new PlanePanel();
|
||||||
|
panel.columns = 4;
|
||||||
|
this.manager.addControl(panel);
|
||||||
|
this.buttonMaterial = new StandardMaterial("buttonMaterial", this.scene);
|
||||||
|
this.buttonMaterial.diffuseColor = Color3.FromHexString("#000000");
|
||||||
|
panel.addControl(this.makeButton("Modify", "modify"));
|
||||||
|
panel.addControl(this.makeButton("Remove", "remove"));
|
||||||
|
panel.addControl(this.makeButton("Add Label", "label"));
|
||||||
|
panel.addControl(this.makeButton("Copy", "copy"));
|
||||||
|
panel.addControl(this.makeButton("Connect", "connect"));
|
||||||
|
panel.addControl(this.makeButton("Export", "export"));
|
||||||
|
panel.addControl(this.makeButton("Recolor", "recolor"));
|
||||||
|
panel.addControl(this.makeButton("New Relic", "newrelic"));
|
||||||
|
|
||||||
|
//panel.addControl(this.makeButton("Add Ring Cameras", "addRingCameras"));
|
||||||
|
this.manager.controlScaling = .1;
|
||||||
|
this.scene.onPointerObservable.add((pointerInfo) => {
|
||||||
|
switch (pointerInfo.type) {
|
||||||
|
case PointerEventTypes.POINTERPICK:
|
||||||
|
const pickedMesh = pointerInfo.pickInfo?.pickedMesh;
|
||||||
|
if (pickedMesh.metadata?.template &&
|
||||||
|
pickedMesh?.parent?.parent?.id != "toolbox") {
|
||||||
|
this.diagramEntityPicked(pointerInfo).then(() => {
|
||||||
|
this.logger.debug("handled");
|
||||||
|
}).catch((e) => {
|
||||||
|
this.logger.error(e);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
const tool = pickedMesh?.metadata?.tool;
|
||||||
|
if (tool) {
|
||||||
|
this.logger.debug("tool type", tool);
|
||||||
|
this.paintColor = (pickedMesh.material as StandardMaterial).diffuseColor.toHexString();
|
||||||
|
this.logger.debug((pickedMesh.material as StandardMaterial).diffuseColor.toHexString());
|
||||||
|
this.logger.debug(pickedMesh.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.panel = panel;
|
||||||
|
this.isVisible = false;
|
||||||
|
}
|
||||||
|
|
||||||
makeButton(name: string, id: string) {
|
makeButton(name: string, id: string) {
|
||||||
const button = new Button3D(name);
|
const button = new Button3D(name);
|
||||||
button.scaling = new Vector3(.1, .1, .1);
|
button.scaling = new Vector3(.1, .1, .1);
|
||||||
button.name = id;
|
button.name = id;
|
||||||
const text = new TextBlock(name, name);
|
const text = new TextBlock(name, name);
|
||||||
text.fontSize = "24px";
|
text.fontSize = "48px";
|
||||||
text.color = "white";
|
text.color = "#ffffff";
|
||||||
|
text.alpha = 1;
|
||||||
button.content = text;
|
button.content = text;
|
||||||
button.onPointerClickObservable.add(this.handleClick, -1, false, this);
|
button.onPointerClickObservable.add(this.handleClick, -1, false, this);
|
||||||
return button;
|
return button;
|
||||||
@ -250,6 +256,22 @@ export class EditMenu {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private showNewRelic() {
|
||||||
|
const inputTextView = new InputTextView({xr: this.xr, scene: this.scene, text: "New Relic"});
|
||||||
|
inputTextView.show();
|
||||||
|
inputTextView.onTextObservable.addOnce((value) => {
|
||||||
|
console.log(value.text);
|
||||||
|
AppConfig.config.newRelicKey = value.text;
|
||||||
|
inputTextView.show();
|
||||||
|
inputTextView.onTextObservable.addOnce((value) => {
|
||||||
|
console.log(value.text);
|
||||||
|
AppConfig.config.newRelicAccount = value.text;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private handleClick(_info, state) {
|
private handleClick(_info, state) {
|
||||||
switch (state.currentTarget.name) {
|
switch (state.currentTarget.name) {
|
||||||
case "modify":
|
case "modify":
|
||||||
@ -270,6 +292,9 @@ export class EditMenu {
|
|||||||
case "recolor":
|
case "recolor":
|
||||||
this.state = EditMenuState.RECOLORING;
|
this.state = EditMenuState.RECOLORING;
|
||||||
break;
|
break;
|
||||||
|
case "newrelic":
|
||||||
|
this.showNewRelic();
|
||||||
|
break;
|
||||||
case "export":
|
case "export":
|
||||||
GLTF2Export.GLTFAsync(this.scene, 'diagram.gltf', {
|
GLTF2Export.GLTFAsync(this.scene, 'diagram.gltf', {
|
||||||
shouldExportNode: function (node) {
|
shouldExportNode: function (node) {
|
||||||
|
|||||||
35
src/menus/integrationMenu.ts
Normal file
35
src/menus/integrationMenu.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import {AbstractMesh, MeshBuilder, Scene, WebXRExperienceHelper} from "@babylonjs/core";
|
||||||
|
import {Controllers} from "../controllers/controllers";
|
||||||
|
import {BaseMenu} from "./baseMenu";
|
||||||
|
import {AdvancedDynamicTexture, Grid, TextBlock} from "@babylonjs/gui";
|
||||||
|
import {CameraHelper} from "../util/cameraHelper";
|
||||||
|
|
||||||
|
export class IntegrationMenu extends BaseMenu {
|
||||||
|
private plane: AbstractMesh = null;
|
||||||
|
|
||||||
|
constructor(scene: Scene, xr: WebXRExperienceHelper, controllers: Controllers) {
|
||||||
|
super(scene, xr, controllers);
|
||||||
|
this.buildMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggle() {
|
||||||
|
this.plane.isVisible = !this.plane.isVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
private buildMenu() {
|
||||||
|
this.plane = MeshBuilder.CreatePlane("plane", {size: 1}, this.scene);
|
||||||
|
const advancedTexture2 = AdvancedDynamicTexture.CreateForMesh(this.plane, 1024, 1024, false);
|
||||||
|
|
||||||
|
const grid = new Grid("grid");
|
||||||
|
advancedTexture2.addControl(grid);
|
||||||
|
grid.addColumnDefinition(.25);
|
||||||
|
grid.addColumnDefinition(.75);
|
||||||
|
const labelText1 = new TextBlock("labelText1", "New Relic Key");
|
||||||
|
grid.addControl(labelText1, 0, 0);
|
||||||
|
const labelText2 = new TextBlock("labelText1", "New Relic Account");
|
||||||
|
grid.addControl(labelText2, 1, 0);
|
||||||
|
CameraHelper.setMenuPosition(this.plane, this.scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -16,6 +16,12 @@ export class AppConfig {
|
|||||||
private _turnSnap = 0;
|
private _turnSnap = 0;
|
||||||
private rotateSnap = 0;
|
private rotateSnap = 0;
|
||||||
private createSnap = 0;
|
private createSnap = 0;
|
||||||
|
private _newRelicKey: string = null;
|
||||||
|
|
||||||
|
public get newRelicKey(): string {
|
||||||
|
return this._newRelicKey;
|
||||||
|
}
|
||||||
|
|
||||||
_physicsEnabled = false;
|
_physicsEnabled = false;
|
||||||
private readonly defaultGridSnapIndex = 1;
|
private readonly defaultGridSnapIndex = 1;
|
||||||
private persistenceManager: IPersistenceManager = null;
|
private persistenceManager: IPersistenceManager = null;
|
||||||
@ -46,6 +52,22 @@ export class AppConfig {
|
|||||||
return this.gridSnapArray[this.gridSnap];
|
return this.gridSnapArray[this.gridSnap];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public set newRelicKey(val: string) {
|
||||||
|
this._newRelicKey = val;
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _newRelicAccount: string = null;
|
||||||
|
|
||||||
|
public get newRelicAccount(): string {
|
||||||
|
return this._newRelicAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set newRelicAccount(val: string) {
|
||||||
|
this._newRelicAccount = val;
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
|
|
||||||
public get physicsEnabled(): boolean {
|
public get physicsEnabled(): boolean {
|
||||||
return this._physicsEnabled;
|
return this._physicsEnabled;
|
||||||
}
|
}
|
||||||
@ -173,7 +195,9 @@ export class AppConfig {
|
|||||||
rotateSnap: this.currentRotateSnap.value,
|
rotateSnap: this.currentRotateSnap.value,
|
||||||
createSnap: this.currentCreateSnap.value,
|
createSnap: this.currentCreateSnap.value,
|
||||||
turnSnap: this.currentTurnSnap.value,
|
turnSnap: this.currentTurnSnap.value,
|
||||||
physicsEnabled: this._physicsEnabled
|
physicsEnabled: this._physicsEnabled,
|
||||||
|
newRelicKey: this._newRelicKey,
|
||||||
|
newRelicAccount: this._newRelicAccount
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,5 +4,8 @@ export type AppConfigType = {
|
|||||||
rotateSnap: number,
|
rotateSnap: number,
|
||||||
createSnap: number,
|
createSnap: number,
|
||||||
turnSnap: number,
|
turnSnap: number,
|
||||||
physicsEnabled: boolean
|
physicsEnabled: boolean,
|
||||||
|
newRelicKey: string,
|
||||||
|
newRelicAccount: string,
|
||||||
|
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user