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",
|
"dexie-observable": "^4.0.1-beta.13",
|
||||||
"earcut": "^2.2.4",
|
"earcut": "^2.2.4",
|
||||||
"loglevel": "^1.8.1",
|
"loglevel": "^1.8.1",
|
||||||
|
"p2p-data-channel": "^1.10.7",
|
||||||
"query-string": "^8.1.0",
|
"query-string": "^8.1.0",
|
||||||
"ring-client-api": "11.7.7",
|
"ring-client-api": "11.7.7",
|
||||||
"round": "^2.0.1",
|
"round": "^2.0.1",
|
||||||
@ -882,6 +883,14 @@
|
|||||||
"url": "https://github.com/sindresorhus/is?sponsor=1"
|
"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": {
|
"node_modules/@szmarczak/http-timer": {
|
||||||
"version": "4.0.6",
|
"version": "4.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
|
||||||
@ -1820,6 +1829,11 @@
|
|||||||
"node": ">=0.8.0"
|
"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": {
|
"node_modules/events": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
||||||
@ -2961,6 +2975,15 @@
|
|||||||
"node": ">=8"
|
"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": {
|
"node_modules/parse-exponential": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/parse-exponential/-/parse-exponential-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/parse-exponential/-/parse-exponential-1.0.1.tgz",
|
||||||
@ -3011,6 +3034,29 @@
|
|||||||
"node": ">=8"
|
"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": {
|
"node_modules/pick-port": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/pick-port/-/pick-port-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/pick-port/-/pick-port-1.0.1.tgz",
|
||||||
@ -3343,6 +3389,18 @@
|
|||||||
"node": ">=0.10.0"
|
"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": {
|
"node_modules/run-async": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
|
"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",
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
"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": {
|
"node_modules/set-cookie-parser": {
|
||||||
"version": "2.6.0",
|
"version": "2.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz",
|
"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",
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
"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": {
|
"node_modules/werift": {
|
||||||
"version": "0.18.2",
|
"version": "0.18.2",
|
||||||
"resolved": "https://registry.npmjs.org/werift/-/werift-0.18.2.tgz",
|
"resolved": "https://registry.npmjs.org/werift/-/werift-0.18.2.tgz",
|
||||||
|
|||||||
@ -23,7 +23,8 @@
|
|||||||
"loglevel": "^1.8.1",
|
"loglevel": "^1.8.1",
|
||||||
"round": "^2.0.1",
|
"round": "^2.0.1",
|
||||||
"earcut": "^2.2.4",
|
"earcut": "^2.2.4",
|
||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0",
|
||||||
|
"p2p-data-channel": "^1.10.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5.0.2",
|
"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 {
|
import {
|
||||||
ArcRotateCamera,
|
ArcRotateCamera,
|
||||||
DualShockPad,
|
DualShockPad,
|
||||||
Engine,
|
Engine,
|
||||||
|
GroundMesh,
|
||||||
HavokPlugin,
|
HavokPlugin,
|
||||||
HemisphericLight,
|
HemisphericLight,
|
||||||
MeshBuilder,
|
MeshBuilder,
|
||||||
PBRMetallicRoughnessMaterial,
|
PBRMetallicRoughnessMaterial,
|
||||||
PhotoDome,
|
|
||||||
PhysicsAggregate,
|
PhysicsAggregate,
|
||||||
PhysicsShapeType,
|
PhysicsShapeType,
|
||||||
Scene,
|
Scene,
|
||||||
@ -18,7 +15,6 @@ import {
|
|||||||
WebXRDefaultExperience,
|
WebXRDefaultExperience,
|
||||||
WebXRState
|
WebXRState
|
||||||
} from "@babylonjs/core";
|
} from "@babylonjs/core";
|
||||||
///import {havokModule} from "./util/havok";
|
|
||||||
import HavokPhysics from "@babylonjs/havok";
|
import HavokPhysics from "@babylonjs/havok";
|
||||||
import {Rigplatform} from "./controllers/rigplatform";
|
import {Rigplatform} from "./controllers/rigplatform";
|
||||||
import {DiagramManager} from "./diagram/diagramManager";
|
import {DiagramManager} from "./diagram/diagramManager";
|
||||||
@ -26,7 +22,6 @@ import {Toolbox} from "./toolbox/toolbox";
|
|||||||
import {DualshockEventMapper} from "./util/dualshockEventMapper";
|
import {DualshockEventMapper} from "./util/dualshockEventMapper";
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import {AppConfig} from "./util/appConfig";
|
import {AppConfig} from "./util/appConfig";
|
||||||
import {IndexdbPersistenceManager} from "./diagram/indexdbPersistenceManager";
|
|
||||||
import {DiaSounds} from "./util/diaSounds";
|
import {DiaSounds} from "./util/diaSounds";
|
||||||
|
|
||||||
export class App {
|
export class App {
|
||||||
@ -35,7 +30,7 @@ export class App {
|
|||||||
|
|
||||||
|
|
||||||
private scene: Scene;
|
private scene: Scene;
|
||||||
private xr: WebXRDefaultExperience;
|
|
||||||
private rig: Rigplatform;
|
private rig: Rigplatform;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -51,13 +46,11 @@ export class App {
|
|||||||
this.initialize(canvas).then(() => {
|
this.initialize(canvas).then(() => {
|
||||||
log.debug('App', 'Scene Initialized');
|
log.debug('App', 'Scene Initialized');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async initialize(canvas) {
|
async initialize(canvas) {
|
||||||
if (this.xr) {
|
|
||||||
this.xr.dispose();
|
|
||||||
this.xr = null;
|
|
||||||
}
|
|
||||||
if (this.scene) {
|
if (this.scene) {
|
||||||
this.scene.dispose();
|
this.scene.dispose();
|
||||||
this.scene = null;
|
this.scene = null;
|
||||||
@ -81,13 +74,15 @@ export class App {
|
|||||||
camera.radius = 0;
|
camera.radius = 0;
|
||||||
camera.attachControl(canvas, true);
|
camera.attachControl(canvas, true);
|
||||||
|
|
||||||
|
|
||||||
new HemisphericLight("light1", new Vector3(1, 1, 0), scene);
|
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', {},
|
'./outdoor_field2.jpeg', {},
|
||||||
scene);
|
scene);
|
||||||
|
});
|
||||||
|
|
||||||
const ground = this.createGround();
|
const ground = this.createGround();
|
||||||
this.xr = await WebXRDefaultExperience.CreateAsync(scene, {
|
const xr = await WebXRDefaultExperience.CreateAsync(scene, {
|
||||||
floorMeshes: [ground],
|
floorMeshes: [ground],
|
||||||
disableTeleportation: true,
|
disableTeleportation: true,
|
||||||
outputCanvasOptions: {
|
outputCanvasOptions: {
|
||||||
@ -102,10 +97,10 @@ export class App {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.xr.baseExperience.onStateChangedObservable.add((state) => {
|
xr.baseExperience.onStateChangedObservable.add((state) => {
|
||||||
if (state == WebXRState.IN_XR) {
|
if (state == WebXRState.IN_XR) {
|
||||||
this.scene.audioEnabled = true;
|
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) => {
|
window.addEventListener(('pa-button-state-change'), (event: any) => {
|
||||||
if (event.detail) {
|
if (event.detail) {
|
||||||
log.debug('App', 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, xr.baseExperience);
|
||||||
const diagramManager = new DiagramManager(this.scene, this.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);
|
diagramManager.setPersistenceManager(persistenceManager);
|
||||||
AppConfig.config.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) => {
|
this.scene.gamepadManager.onGamepadConnectedObservable.add((gamepad) => {
|
||||||
try {
|
try {
|
||||||
const dualshock = (gamepad as DualShockPad);
|
const dualshock = (gamepad as DualShockPad);
|
||||||
@ -190,15 +188,19 @@ export class App {
|
|||||||
window.addEventListener("keydown", (ev) => {
|
window.addEventListener("keydown", (ev) => {
|
||||||
// Shift+Ctrl+Alt+I
|
// Shift+Ctrl+Alt+I
|
||||||
if (ev.shiftKey && ev.ctrlKey && ev.altKey && ev.keyCode === 73) {
|
if (ev.shiftKey && ev.ctrlKey && ev.altKey && ev.keyCode === 73) {
|
||||||
|
import("@babylonjs/core/Debug/debugLayer").then(() => {
|
||||||
|
import("@babylonjs/inspector").then(() => {
|
||||||
if (scene.debugLayer.isVisible()) {
|
if (scene.debugLayer.isVisible()) {
|
||||||
scene.debugLayer.hide();
|
scene.debugLayer.hide();
|
||||||
} else {
|
} else {
|
||||||
scene.debugLayer.show();
|
scene.debugLayer.show();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.logger.info('keydown event listener added, use Ctrl+Shift+Alt+I to toggle debug layer');
|
this.logger.info('keydown event listener added, use Ctrl+Shift+Alt+I to toggle debug layer');
|
||||||
persistenceManager.initialize();
|
|
||||||
engine.runRenderLoop(() => {
|
engine.runRenderLoop(() => {
|
||||||
scene.render();
|
scene.render();
|
||||||
|
|
||||||
@ -215,7 +217,11 @@ export class App {
|
|||||||
groundMaterial.metallic = 0;
|
groundMaterial.metallic = 0;
|
||||||
groundMaterial.roughness = 1;
|
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;
|
ground.material = groundMaterial;
|
||||||
new PhysicsAggregate(ground, PhysicsShapeType.BOX, {mass: 0}, this.scene);
|
new PhysicsAggregate(ground, PhysicsShapeType.BOX, {mass: 0}, this.scene);
|
||||||
|
|||||||
@ -79,7 +79,6 @@ export class Base {
|
|||||||
if (init.components['xr-standard-squeeze']) {
|
if (init.components['xr-standard-squeeze']) {
|
||||||
this.initGrip(init.components['xr-standard-squeeze'])
|
this.initGrip(init.components['xr-standard-squeeze'])
|
||||||
}
|
}
|
||||||
;
|
|
||||||
});
|
});
|
||||||
Controllers.controllerObserver.add((event) => {
|
Controllers.controllerObserver.add((event) => {
|
||||||
if (event.type == 'pulse') {
|
if (event.type == 'pulse') {
|
||||||
@ -88,8 +87,7 @@ export class Base {
|
|||||||
this.controller?.motionController?.pulse(.25, 30);
|
this.controller?.motionController?.pulse(.25, 30);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public disable() {
|
public disable() {
|
||||||
@ -101,11 +99,6 @@ export class Base {
|
|||||||
this.controller.motionController.rootMesh.setEnabled(true);
|
this.controller.motionController.rootMesh.setEnabled(true);
|
||||||
this.controller.pointer.setEnabled(true);
|
this.controller.pointer.setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private buildTransformNode() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private setupTransformNode(mesh: TransformNode) {
|
private setupTransformNode(mesh: TransformNode) {
|
||||||
const transformNode = new TransformNode("grabAnchor, this.scene");
|
const transformNode = new TransformNode("grabAnchor, this.scene");
|
||||||
transformNode.id = "grabAnchor";
|
transformNode.id = "grabAnchor";
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import {
|
|||||||
WebXRExperienceHelper
|
WebXRExperienceHelper
|
||||||
} from "@babylonjs/core";
|
} from "@babylonjs/core";
|
||||||
import {DiagramEntity, DiagramEvent, DiagramEventType} from "./diagramEntity";
|
import {DiagramEntity, DiagramEvent, DiagramEventType} from "./diagramEntity";
|
||||||
import {IPersistenceManager} from "./persistenceManager";
|
import {IPersistenceManager} from "./iPersistenceManager";
|
||||||
import {MeshConverter} from "./meshConverter";
|
import {MeshConverter} from "./meshConverter";
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import {Controllers} from "../controllers/controllers";
|
import {Controllers} from "../controllers/controllers";
|
||||||
|
|||||||
@ -17,6 +17,7 @@ export class DiagramShapePhysics {
|
|||||||
if (mesh.physicsBody) {
|
if (mesh.physicsBody) {
|
||||||
mesh.physicsBody.dispose();
|
mesh.physicsBody.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
let shapeType = PhysicsShapeType.BOX;
|
let shapeType = PhysicsShapeType.BOX;
|
||||||
switch (mesh.metadata.template) {
|
switch (mesh.metadata.template) {
|
||||||
case "#sphere-template":
|
case "#sphere-template":
|
||||||
@ -30,8 +31,9 @@ export class DiagramShapePhysics {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
let mass = mesh.scaling.x * mesh.scaling.y * mesh.scaling.z * 10;
|
||||||
const aggregate = new PhysicsAggregate(mesh,
|
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.setCollisionCallbackEnabled(true);
|
||||||
aggregate.body.getCollisionObservable().add((event, state) => {
|
aggregate.body.getCollisionObservable().add((event, state) => {
|
||||||
if (event.distance > .001 && !DiaSounds.instance.low.isPlaying) {
|
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 {AbstractMesh, Observable, Vector3} from "@babylonjs/core";
|
||||||
import {DiagramEntity} from "./diagramEntity";
|
import {DiagramEntity} from "./diagramEntity";
|
||||||
import Dexie from "dexie";
|
import Dexie from "dexie";
|
||||||
@ -6,20 +6,25 @@ import {MeshConverter} from "./meshConverter";
|
|||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import {AppConfigType} from "../util/appConfigType";
|
import {AppConfigType} from "../util/appConfigType";
|
||||||
|
|
||||||
|
|
||||||
export class IndexdbPersistenceManager implements IPersistenceManager {
|
export class IndexdbPersistenceManager implements IPersistenceManager {
|
||||||
private readonly logger = log.getLogger('IndexdbPersistenceManager');
|
private readonly logger = log.getLogger('IndexdbPersistenceManager');
|
||||||
|
public readonly diagramListingObserver: Observable<DiagramListingEvent> = new Observable<DiagramListingEvent>();
|
||||||
public readonly updateObserver: Observable<DiagramEntity> = new Observable<DiagramEntity>();
|
public readonly updateObserver: Observable<DiagramEntity> = new Observable<DiagramEntity>();
|
||||||
public readonly configObserver: Observable<AppConfigType> = new Observable<AppConfigType>();
|
public readonly configObserver: Observable<AppConfigType> = new Observable<AppConfigType>();
|
||||||
private db: Dexie;
|
private db: Dexie;
|
||||||
|
private currentDiagramId: string;
|
||||||
|
|
||||||
constructor(name: string) {
|
constructor(name: string) {
|
||||||
this.db = new Dexie(name);
|
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({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");
|
this.logger.debug("IndexdbPersistenceManager constructed");
|
||||||
|
}
|
||||||
|
|
||||||
|
public setCurrentDiagram(diagram: DiagramListing) {
|
||||||
|
this.currentDiagramId = diagram.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public add(mesh: AbstractMesh) {
|
public add(mesh: AbstractMesh) {
|
||||||
@ -31,10 +36,20 @@ export class IndexdbPersistenceManager implements IPersistenceManager {
|
|||||||
entity.position = this.vectoxys(mesh.position);
|
entity.position = this.vectoxys(mesh.position);
|
||||||
entity.rotation = this.vectoxys(mesh.rotation);
|
entity.rotation = this.vectoxys(mesh.rotation);
|
||||||
entity.scale = this.vectoxys(mesh.scaling);
|
entity.scale = this.vectoxys(mesh.scaling);
|
||||||
|
entity.diagramlistingid = this.currentDiagramId;
|
||||||
this.db["entities"].add(entity);
|
this.db["entities"].add(entity);
|
||||||
this.logger.debug('add', mesh, 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) {
|
public remove(mesh: AbstractMesh) {
|
||||||
if (!mesh) {
|
if (!mesh) {
|
||||||
this.logger.error("Removing null mesh, early return");
|
this.logger.error("Removing null mesh, early return");
|
||||||
@ -50,6 +65,55 @@ export class IndexdbPersistenceManager implements IPersistenceManager {
|
|||||||
this.configObserver.notifyObservers(config);
|
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) {
|
public modify(mesh) {
|
||||||
if (!mesh) {
|
if (!mesh) {
|
||||||
this.logger.error("Modifying null mesh, early return");
|
this.logger.error("Modifying null mesh, early return");
|
||||||
@ -67,21 +131,6 @@ export class IndexdbPersistenceManager implements IPersistenceManager {
|
|||||||
this.logger.debug('modify', mesh, entity);
|
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) {
|
public changeColor(oldColor, newColor) {
|
||||||
if (!oldColor) {
|
if (!oldColor) {
|
||||||
if (!newColor) {
|
if (!newColor) {
|
||||||
@ -92,7 +141,31 @@ export class IndexdbPersistenceManager implements IPersistenceManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.logger.debug(`changeColor ${oldColor.toHexString()} to ${newColor.toHexString()}`);
|
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 } {
|
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) {
|
private setCopying(mesh: AbstractMesh) {
|
||||||
if (mesh) {
|
if (mesh) {
|
||||||
const newMesh = this.diagramManager.createCopy(mesh);
|
const newMesh = this.diagramManager.createCopy(mesh, true);
|
||||||
|
newMesh.setParent(null);
|
||||||
DiagramShapePhysics.applyPhysics(newMesh, this.scene);
|
DiagramShapePhysics.applyPhysics(newMesh, this.scene);
|
||||||
newMesh.parent = null;
|
|
||||||
}
|
}
|
||||||
this.logger.warn('copying not implemented', mesh);
|
this.logger.warn('copying not implemented', mesh);
|
||||||
//@todo implement
|
//@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