Refactored physics to reduce duplicate code.
This commit is contained in:
parent
89623b5007
commit
8412b6f378
891
package-lock.json
generated
891
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "immersive",
|
"name": "immersive",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.0",
|
"version": "0.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@ -16,19 +16,12 @@
|
|||||||
"@babylonjs/gui": "^6.14.0",
|
"@babylonjs/gui": "^6.14.0",
|
||||||
"@babylonjs/havok": "1.1.1",
|
"@babylonjs/havok": "1.1.1",
|
||||||
"@babylonjs/inspector": "^6.14.0",
|
"@babylonjs/inspector": "^6.14.0",
|
||||||
"express": "^4.18.2",
|
"ring-client-api": "11.7.7",
|
||||||
"@auth0/auth0-spa-js": "^2.0.8",
|
|
||||||
"ring-client-api": "^11.8.0",
|
|
||||||
"@maptiler/client": "^1.5.0",
|
|
||||||
"axios": "^1.4.0",
|
|
||||||
"dexie": "^3.2.4",
|
"dexie": "^3.2.4",
|
||||||
"dexie-observable": "^4.0.1-beta.13",
|
"dexie-observable": "^4.0.1-beta.13",
|
||||||
"google-static-maps-tile": "1.0.0",
|
|
||||||
"query-string": "^8.1.0",
|
"query-string": "^8.1.0",
|
||||||
"vite-express": "^0.9.1",
|
|
||||||
"loglevel": "^1.8.1",
|
"loglevel": "^1.8.1",
|
||||||
"round": "^2.0.1",
|
"round": "^2.0.1",
|
||||||
"express-http-proxy": "^1.6.3",
|
|
||||||
"earcut": "^2.2.4",
|
"earcut": "^2.2.4",
|
||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import {MeshConverter} from "../diagram/meshConverter";
|
|||||||
import {DiagramManager} from "../diagram/diagramManager";
|
import {DiagramManager} from "../diagram/diagramManager";
|
||||||
import {DiagramEvent, DiagramEventType} from "../diagram/diagramEntity";
|
import {DiagramEvent, DiagramEventType} from "../diagram/diagramEntity";
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import {AppConfig} from "../util/appConfig";
|
|
||||||
import {Controllers} from "./controllers";
|
import {Controllers} from "./controllers";
|
||||||
|
|
||||||
|
|
||||||
@ -135,10 +134,8 @@ export class Base {
|
|||||||
|
|
||||||
if ("toolbox" != mesh?.parent?.parent?.id) {
|
if ("toolbox" != mesh?.parent?.parent?.id) {
|
||||||
if (mesh.physicsBody) {
|
if (mesh.physicsBody) {
|
||||||
|
|
||||||
const transformNode = this.setupTransformNode(mesh);
|
const transformNode = this.setupTransformNode(mesh);
|
||||||
mesh.physicsBody.setMotionType(PhysicsMotionType.ANIMATED);
|
mesh.physicsBody.setMotionType(PhysicsMotionType.ANIMATED);
|
||||||
//mesh.setParent(transformNode);
|
|
||||||
this.grabbedMeshParentId = transformNode.id;
|
this.grabbedMeshParentId = transformNode.id;
|
||||||
} else {
|
} else {
|
||||||
mesh.setParent(this.controller.motionController.rootMesh);
|
mesh.setParent(this.controller.motionController.rootMesh);
|
||||||
@ -194,29 +191,17 @@ export class Base {
|
|||||||
log.getLogger("Base").warn("Base", "Have not implemented snapping to parent yet");
|
log.getLogger("Base").warn("Base", "Have not implemented snapping to parent yet");
|
||||||
//@note: this is not implemented yet
|
//@note: this is not implemented yet
|
||||||
} else {
|
} else {
|
||||||
//mesh.setParent(null);
|
mesh.setParent(null);
|
||||||
this.applyTransform(mesh)
|
|
||||||
mesh?.physicsBody?.setMotionType(PhysicsMotionType.DYNAMIC);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const parent = this.scene.getTransformNodeById(this.grabbedMeshParentId);
|
const parent = this.scene.getTransformNodeById(this.grabbedMeshParentId);
|
||||||
if (parent) {
|
if (parent) {
|
||||||
this.applyTransform(parent);
|
|
||||||
this.grabbedMeshParentId = null;
|
this.grabbedMeshParentId = null;
|
||||||
parent.dispose();
|
parent.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private applyTransform(mesh: TransformNode) {
|
|
||||||
const config = AppConfig.config;
|
|
||||||
const snappedRotation = config.snapRotateVal(mesh.absoluteRotationQuaternion.toEulerAngles().clone());
|
|
||||||
const snappedPosition = config.snapGridVal(mesh.absolutePosition.clone());
|
|
||||||
|
|
||||||
mesh.rotation = snappedRotation;
|
|
||||||
mesh.position = snappedPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
private drop() {
|
private drop() {
|
||||||
const mesh = this.grabbedMesh;
|
const mesh = this.grabbedMesh;
|
||||||
if (!mesh) {
|
if (!mesh) {
|
||||||
@ -225,6 +210,7 @@ export class Base {
|
|||||||
if (this.handleGrabbed(mesh)) {
|
if (this.handleGrabbed(mesh)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.reparent(mesh);
|
this.reparent(mesh);
|
||||||
this.previousParentId = null;
|
this.previousParentId = null;
|
||||||
this.previousScaling = null;
|
this.previousScaling = null;
|
||||||
|
|||||||
@ -8,7 +8,9 @@ import {
|
|||||||
MeshBuilder,
|
MeshBuilder,
|
||||||
PhysicsAggregate,
|
PhysicsAggregate,
|
||||||
PhysicsBody,
|
PhysicsBody,
|
||||||
|
PhysicsMotionType,
|
||||||
PhysicsShapeType,
|
PhysicsShapeType,
|
||||||
|
Quaternion,
|
||||||
Scene,
|
Scene,
|
||||||
StandardMaterial
|
StandardMaterial
|
||||||
} from "@babylonjs/core";
|
} from "@babylonjs/core";
|
||||||
@ -79,8 +81,13 @@ export class MeshConverter {
|
|||||||
|
|
||||||
}
|
}
|
||||||
if (entity.rotation) {
|
if (entity.rotation) {
|
||||||
|
if (mesh.rotationQuaternion) {
|
||||||
|
mesh.rotationQuaternion = Quaternion.FromEulerAngles(entity.rotation.x, entity.rotation.y, entity.rotation.z);
|
||||||
|
} else {
|
||||||
mesh.rotation = entity.rotation;
|
mesh.rotation = entity.rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
if (entity.parent) {
|
if (entity.parent) {
|
||||||
mesh.parent = scene.getNodeById(entity.parent);
|
mesh.parent = scene.getNodeById(entity.parent);
|
||||||
}
|
}
|
||||||
@ -119,7 +126,7 @@ export class MeshConverter {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (mesh.physicsBody) {
|
if (mesh.physicsBody) {
|
||||||
return mesh.physicsBody;
|
mesh.physicsBody.dispose();
|
||||||
}
|
}
|
||||||
let shapeType = PhysicsShapeType.BOX;
|
let shapeType = PhysicsShapeType.BOX;
|
||||||
switch (mesh.metadata.template) {
|
switch (mesh.metadata.template) {
|
||||||
@ -136,10 +143,11 @@ export class MeshConverter {
|
|||||||
}
|
}
|
||||||
const aggregate = new PhysicsAggregate(mesh,
|
const aggregate = new PhysicsAggregate(mesh,
|
||||||
shapeType, {mass: 20, restitution: .2, friction: .9}, scene);
|
shapeType, {mass: 20, restitution: .2, friction: .9}, scene);
|
||||||
aggregate.body.setLinearDamping(.9);
|
const body = aggregate.body;
|
||||||
aggregate.body.setAngularDamping(.5);
|
body.setMotionType(PhysicsMotionType.ANIMATED);
|
||||||
|
body.setLinearDamping(.9);
|
||||||
|
body.setAngularDamping(.5);
|
||||||
|
body.setGravityFactor(0);
|
||||||
return aggregate.body;
|
return aggregate.body;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,46 +1,47 @@
|
|||||||
import {AbstractMesh, Angle, MeshBuilder, Scene, WebXRExperienceHelper} from "@babylonjs/core";
|
import {Right} from "../controllers/right";
|
||||||
import {AdvancedDynamicTexture, InputText} from "@babylonjs/gui";
|
import {Left} from "../controllers/left";
|
||||||
|
import {Observable, WebXRSessionManager} from "@babylonjs/core";
|
||||||
|
import log from "loglevel";
|
||||||
|
|
||||||
|
export type TextEvent = {
|
||||||
|
text: string;
|
||||||
|
}
|
||||||
|
|
||||||
export class InputTextView {
|
export class InputTextView {
|
||||||
private mesh: AbstractMesh;
|
public readonly onTextObservable: Observable<TextEvent> = new Observable<TextEvent>();
|
||||||
private readonly scene: Scene;
|
private text: string;
|
||||||
private xr: WebXRExperienceHelper;
|
private xrSession: WebXRSessionManager;
|
||||||
private inputPlane: AbstractMesh;
|
|
||||||
private inputText: InputText;
|
constructor(xrSession: WebXRSessionManager, text: string) {
|
||||||
constructor(scene: Scene, xr: WebXRExperienceHelper, mesh: AbstractMesh ) {
|
this.xrSession = xrSession;
|
||||||
this.scene = scene;
|
this.text = text;
|
||||||
this.xr = xr;
|
|
||||||
this.mesh = mesh;
|
|
||||||
}
|
}
|
||||||
public async show(text: string) {
|
|
||||||
this.inputPlane = MeshBuilder.CreatePlane("myPlane", {width: 1, height: .125}, this.scene);
|
public show() {
|
||||||
const pos = this.mesh.absolutePosition;
|
const textInput = document.createElement("input");
|
||||||
pos.y += .2;
|
textInput.type = "text";
|
||||||
this.inputPlane.position= pos;
|
document.body.appendChild(textInput);
|
||||||
this.inputPlane.rotation.y = Angle.FromDegrees(180).radians();
|
textInput.value = this.text;
|
||||||
const textDisplayTexture = AdvancedDynamicTexture.CreateForMesh(this.inputPlane, 1024, 128);
|
|
||||||
this.inputPlane.material.backFaceCulling = false;
|
if (this.xrSession.inXRSession) {
|
||||||
this.inputText = this.createInputText();
|
Right.instance.disable();
|
||||||
this.inputText.text = text;
|
Left.instance.disable();
|
||||||
textDisplayTexture.addControl(this.inputText);
|
}
|
||||||
|
textInput.focus();
|
||||||
|
if (navigator.userAgent.indexOf('Macintosh') > -1) {
|
||||||
|
textInput.addEventListener('input', (event) => {
|
||||||
|
log.debug(event);
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
textInput.addEventListener('blur', () => {
|
||||||
|
log.getLogger('bmenu').debug("blur");
|
||||||
|
this.onTextObservable.notifyObservers({text: textInput.value});
|
||||||
|
Right.instance.enable();
|
||||||
|
Left.instance.enable();
|
||||||
|
textInput.blur();
|
||||||
|
textInput.remove();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
private createInputText(): InputText {
|
|
||||||
const inputText = new InputText("input");
|
|
||||||
inputText.color= "white";
|
|
||||||
inputText.background = "black";
|
|
||||||
inputText.height= "128px";
|
|
||||||
inputText.width= "1024px";
|
|
||||||
inputText.maxWidth= "1024px";
|
|
||||||
inputText.margin="0px";
|
|
||||||
inputText.fontSize= "48px";
|
|
||||||
return inputText;
|
|
||||||
}
|
|
||||||
public async dispose() {
|
|
||||||
this.inputPlane.dispose(false, true);
|
|
||||||
this.inputPlane = null;
|
|
||||||
this.inputText = null;
|
|
||||||
}
|
|
||||||
public async updateText(text: string) {
|
|
||||||
this.inputText.text = text;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,46 +1,57 @@
|
|||||||
import {Angle, Color3, MeshBuilder, Scene, StandardMaterial, Texture} from "@babylonjs/core";
|
import {
|
||||||
import axios from "axios";
|
Angle,
|
||||||
|
Color3,
|
||||||
|
MeshBuilder,
|
||||||
|
Scene,
|
||||||
|
StandardMaterial,
|
||||||
|
Texture,
|
||||||
|
Vector3,
|
||||||
|
WebXRSessionManager
|
||||||
|
} from "@babylonjs/core";
|
||||||
|
import log from "loglevel";
|
||||||
|
|
||||||
|
|
||||||
export class Cameras {
|
export class Cameras {
|
||||||
private readonly scene: Scene;
|
private readonly scene: Scene;
|
||||||
private token: string;
|
private readonly logger = log.getLogger('bmenu');
|
||||||
private cameras;
|
|
||||||
private cameratextures = new Array<Texture>();
|
|
||||||
|
|
||||||
constructor(scene: Scene, token: string) {
|
private xrSession: WebXRSessionManager;
|
||||||
|
private startPosition = new Vector3(0, 0, 0);
|
||||||
|
|
||||||
|
constructor(scene: Scene, xrSession: WebXRSessionManager) {
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
this.token = token;
|
this.xrSession = xrSession;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getCameras() {
|
public createCameras(position: Vector3) {
|
||||||
this.cameras = await axios.get('https://local.immersiveidea.com/api/cameras');
|
this.startPosition = position;
|
||||||
|
this.getCameras();
|
||||||
}
|
}
|
||||||
|
|
||||||
public createCameras() {
|
private getCameras() {
|
||||||
this.createCamera(12333524, 0);
|
|
||||||
this.createCamera(115860395, 1);
|
|
||||||
this.createCamera(115855810, 2);
|
|
||||||
this.createCamera(99677736, 3);
|
|
||||||
this.createCamera(48497021, 4);
|
|
||||||
this.createCamera(55870327, 5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public createCamera(id, index) {
|
private async createCamera() {
|
||||||
const width = 1.6;
|
const width = 1.6;
|
||||||
const height = .9
|
const height = .9
|
||||||
const plane = MeshBuilder.CreatePlane("plane", {width: width, height: height}, this.scene);
|
const plane = MeshBuilder.CreatePlane("plane", {width: width, height: height}, this.scene);
|
||||||
const materialPlane = new StandardMaterial("texturePlane", this.scene);
|
const materialPlane = new StandardMaterial("texturePlane", this.scene);
|
||||||
const imageText = new Texture("https://local.immersiveidea.com/api/cameras?id=" + id, this.scene);
|
//const photo = []
|
||||||
|
//await cam.getSnapshot();
|
||||||
|
//const textureBlob = new Blob([photo], {type: 'image/jpeg'});
|
||||||
|
//const textureUrl = URL.createObjectURL(textureBlob);
|
||||||
|
const imageText = new Texture("", this.scene);
|
||||||
|
|
||||||
materialPlane.diffuseTexture = new Texture("https://local.immersiveidea.com/api/cameras?id=" + id, this.scene);
|
materialPlane.diffuseTexture = imageText;
|
||||||
materialPlane.specularColor = new Color3(0, 0, 0);
|
materialPlane.specularColor = new Color3(0, 0, 0);
|
||||||
materialPlane.backFaceCulling = false;
|
materialPlane.backFaceCulling = false;
|
||||||
plane.material = materialPlane;
|
plane.material = materialPlane;
|
||||||
plane.rotation.y = Angle.FromDegrees(180).radians();
|
plane.rotation.y = Angle.FromDegrees(180).radians();
|
||||||
plane.position.y = height / 2 + .2;
|
plane.position.y = height / 2 + .2;
|
||||||
plane.position.z = -3;
|
plane.position.z = -3;
|
||||||
plane.position.x = (width * 3) - (index * width);
|
plane.position.x = (width * 3) + this.startPosition.x;
|
||||||
this.cameratextures.push(imageText);
|
this.startPosition.x += 3;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,9 +14,8 @@ import {DiagramEvent, DiagramEventType} from "../diagram/diagramEntity";
|
|||||||
import {MeshConverter} from "../diagram/meshConverter";
|
import {MeshConverter} from "../diagram/meshConverter";
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
import {InputTextView} from "../information/inputTextView";
|
import {InputTextView} from "../information/inputTextView";
|
||||||
import {Right} from "../controllers/right";
|
|
||||||
import {Left} from "../controllers/left";
|
|
||||||
import {DiaSounds} from "../util/diaSounds";
|
import {DiaSounds} from "../util/diaSounds";
|
||||||
|
import {Cameras} from "../integration/ring/cameras";
|
||||||
|
|
||||||
export class EditMenu {
|
export class EditMenu {
|
||||||
private state: BmenuState = BmenuState.NONE;
|
private state: BmenuState = BmenuState.NONE;
|
||||||
@ -45,115 +44,43 @@ export class EditMenu {
|
|||||||
case PointerEventTypes.POINTERPICK:
|
case PointerEventTypes.POINTERPICK:
|
||||||
if (pointerInfo.pickInfo?.pickedMesh?.metadata?.template &&
|
if (pointerInfo.pickInfo?.pickedMesh?.metadata?.template &&
|
||||||
pointerInfo.pickInfo?.pickedMesh?.parent?.parent?.id != "toolbox") {
|
pointerInfo.pickInfo?.pickedMesh?.parent?.parent?.id != "toolbox") {
|
||||||
this.cleanup()
|
|
||||||
.then(() => {
|
|
||||||
log.getLogger("bmenu").debug("cleaned up");
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
log.getLogger("bmenu").error(e);
|
|
||||||
});
|
|
||||||
this.handleEventStateAction(pointerInfo).then(() => {
|
this.handleEventStateAction(pointerInfo).then(() => {
|
||||||
log.getLogger("bmenu").debug("handled");
|
log.getLogger("bmenu").debug("handled");
|
||||||
}).catch((e) => {
|
}).catch((e) => {
|
||||||
log.getLogger("bmenu").error(e);
|
log.getLogger("bmenu").error(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async handleEventStateAction(pointerInfo: PointerInfo) {
|
toggle() {
|
||||||
switch (this.state) {
|
if (this.manager) {
|
||||||
case BmenuState.REMOVING:
|
DiaSounds.instance.exit.play();
|
||||||
log.debug("removing " + pointerInfo.pickInfo.pickedMesh.id);
|
this.manager.dispose();
|
||||||
const event: DiagramEvent = {
|
this.manager = null;
|
||||||
type: DiagramEventType.REMOVE,
|
|
||||||
entity:
|
|
||||||
MeshConverter.toDiagramEntity(pointerInfo.pickInfo.pickedMesh)
|
|
||||||
}
|
|
||||||
this.diagramManager.onDiagramEventObservable.notifyObservers(event);
|
|
||||||
break;
|
|
||||||
case BmenuState.MODIFYING:
|
|
||||||
if (pointerInfo.pickInfo.pickedMesh.metadata?.template &&
|
|
||||||
pointerInfo.pickInfo.pickedMesh.parent?.parent?.id != "toolbox") {
|
|
||||||
if (this.gizmoManager.gizmos.boundingBoxGizmo.attachedMesh?.id == pointerInfo.pickInfo?.pickedMesh?.id) {
|
|
||||||
this.gizmoManager.gizmos.boundingBoxGizmo.attachedMesh = null;
|
|
||||||
} else {
|
|
||||||
const mesh = pointerInfo.pickInfo.pickedMesh;
|
|
||||||
this.gizmoManager.attachToMesh(mesh);
|
|
||||||
|
|
||||||
this.gizmoManager.gizmos.boundingBoxGizmo.onScaleBoxDragObservable.add(() => {
|
|
||||||
this.diagramManager.onDiagramEventObservable.notifyObservers({
|
|
||||||
type: DiagramEventType.MODIFY,
|
|
||||||
entity: MeshConverter.toDiagramEntity(mesh),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
log.debug(mesh.scaling);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case BmenuState.LABELING:
|
|
||||||
const mesh = pointerInfo.pickInfo.pickedMesh;
|
|
||||||
log.debug("labeling " + mesh.id);
|
|
||||||
const textInput = document.createElement("input");
|
|
||||||
textInput.type = "text";
|
|
||||||
document.body.appendChild(textInput);
|
|
||||||
if (mesh?.metadata?.text) {
|
|
||||||
textInput.value = mesh.metadata.text;
|
|
||||||
} else {
|
} else {
|
||||||
textInput.value = "";
|
DiaSounds.instance.enter.play();
|
||||||
}
|
this.manager = new GUI3DManager(this.scene);
|
||||||
if (this.xr.sessionManager.inXRSession) {
|
const panel = new StackPanel3D();
|
||||||
Right.instance.disable();
|
this.manager.addControl(panel);
|
||||||
Left.instance.disable();
|
panel.addControl(this.makeButton("Modify", "modify"));
|
||||||
}
|
panel.addControl(this.makeButton("Remove", "remove"));
|
||||||
textInput.focus();
|
panel.addControl(this.makeButton("Add Label", "label"));
|
||||||
|
panel.addControl(this.makeButton("Add Ring Cameras", "addRingCameras"));
|
||||||
if (navigator.userAgent.indexOf('Macintosh') > -1) {
|
this.manager.controlScaling = .5;
|
||||||
textInput.addEventListener('input', (event) => {
|
const offset = new Vector3(0, -.2, 3);
|
||||||
log.debug(event);
|
offset.applyRotationQuaternionInPlace(this.scene.activeCamera.absoluteRotation);
|
||||||
});
|
panel.node.position =
|
||||||
const textView = new InputTextView(this.scene, this.xr, mesh)
|
this.scene.activeCamera.globalPosition.add(offset);
|
||||||
await textView.show(textInput.value);
|
panel.node.lookAt(this.scene.activeCamera.globalPosition);
|
||||||
textInput.addEventListener('keydown', (event) => {
|
panel.node.rotation.y = panel.node.rotation.y + Math.PI;
|
||||||
if (event.key == "Enter") {
|
|
||||||
log.getLogger('bmenu').debug("enter");
|
|
||||||
MeshConverter.updateTextNode(mesh, textInput.value);
|
|
||||||
this.persist(mesh, textInput.value);
|
|
||||||
this.cleanup();
|
|
||||||
} else {
|
|
||||||
textView.updateText(textInput.value);
|
|
||||||
MeshConverter.updateTextNode(mesh, textInput.value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.textView = textView;
|
|
||||||
} else {
|
|
||||||
textInput.addEventListener('blur', () => {
|
|
||||||
log.getLogger('bmenu').debug("blur");
|
|
||||||
MeshConverter.updateTextNode(mesh, textInput.value);
|
|
||||||
this.persist(mesh, textInput.value);
|
|
||||||
this.cleanup();
|
|
||||||
Right.instance.enable();
|
|
||||||
Left.instance.enable();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.textInput = textInput;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private async cleanup() {
|
|
||||||
if (this.textInput) {
|
|
||||||
this.textInput.blur();
|
|
||||||
this.textInput.remove();
|
|
||||||
}
|
|
||||||
this.textInput = null;
|
|
||||||
this.textView && await this.textView.dispose();
|
|
||||||
this.textView = null;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private persist(mesh: AbstractMesh, text: string) {
|
private persist(mesh: AbstractMesh, text: string) {
|
||||||
if (mesh.metadata) {
|
if (mesh.metadata) {
|
||||||
mesh.metadata.text = text;
|
mesh.metadata.text = text;
|
||||||
@ -178,29 +105,54 @@ export class EditMenu {
|
|||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle() {
|
private async handleEventStateAction(pointerInfo: PointerInfo) {
|
||||||
//console.log(mesh.name);
|
const mesh = pointerInfo.pickInfo.pickedMesh;
|
||||||
if (this.manager) {
|
if (!mesh) {
|
||||||
DiaSounds.instance.exit.play();
|
log.warn("no mesh");
|
||||||
this.manager.dispose();
|
return;
|
||||||
this.manager = null;
|
}
|
||||||
|
switch (this.state) {
|
||||||
|
case BmenuState.REMOVING:
|
||||||
|
log.debug("removing " + mesh?.id);
|
||||||
|
const event: DiagramEvent = {
|
||||||
|
type: DiagramEventType.REMOVE,
|
||||||
|
entity:
|
||||||
|
MeshConverter.toDiagramEntity(pointerInfo.pickInfo.pickedMesh)
|
||||||
|
}
|
||||||
|
this.diagramManager.onDiagramEventObservable.notifyObservers(event);
|
||||||
|
break;
|
||||||
|
case BmenuState.MODIFYING:
|
||||||
|
if (mesh.metadata?.template &&
|
||||||
|
mesh.parent?.parent?.id != "toolbox") {
|
||||||
|
if (this.gizmoManager.gizmos.boundingBoxGizmo.attachedMesh?.id == mesh.id) {
|
||||||
|
this.gizmoManager.gizmos.boundingBoxGizmo.attachedMesh = null;
|
||||||
} else {
|
} else {
|
||||||
DiaSounds.instance.enter.play();
|
this.gizmoManager.attachToMesh(mesh);
|
||||||
this.manager = new GUI3DManager(this.scene);
|
this.gizmoManager.gizmos.boundingBoxGizmo.onScaleBoxDragObservable.add(() => {
|
||||||
const panel = new StackPanel3D();
|
this.diagramManager.onDiagramEventObservable.notifyObservers({
|
||||||
this.manager.addControl(panel);
|
type: DiagramEventType.MODIFY,
|
||||||
panel.addControl(this.makeButton("Modify", "modify"));
|
entity: MeshConverter.toDiagramEntity(mesh),
|
||||||
panel.addControl(this.makeButton("Remove", "remove"));
|
}
|
||||||
panel.addControl(this.makeButton("Add Label", "label"));
|
)
|
||||||
this.manager.controlScaling = .5;
|
|
||||||
const offset = new Vector3(0, -.2, 3);
|
|
||||||
offset.applyRotationQuaternionInPlace(this.scene.activeCamera.absoluteRotation);
|
|
||||||
panel.node.position =
|
|
||||||
this.scene.activeCamera.globalPosition.add(offset);
|
|
||||||
panel.node.lookAt(this.scene.activeCamera.globalPosition);
|
|
||||||
panel.node.rotation.y = panel.node.rotation.y + Math.PI;
|
|
||||||
|
|
||||||
|
log.debug(mesh.scaling);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BmenuState.LABELING:
|
||||||
|
log.debug("labeling " + mesh.id);
|
||||||
|
let text = "";
|
||||||
|
if (mesh?.metadata?.text) {
|
||||||
|
text = mesh.metadata.text;
|
||||||
|
}
|
||||||
|
const textInput = new InputTextView(this.xr.sessionManager, text);
|
||||||
|
textInput.show();
|
||||||
|
textInput.onTextObservable.addOnce((value) => {
|
||||||
|
this.persist(mesh, value.text);
|
||||||
|
MeshConverter.updateTextNode(mesh, value.text);
|
||||||
|
});
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,6 +167,9 @@ export class EditMenu {
|
|||||||
case "label":
|
case "label":
|
||||||
this.state = BmenuState.LABELING;
|
this.state = BmenuState.LABELING;
|
||||||
break;
|
break;
|
||||||
|
case "addRingCameras":
|
||||||
|
const cameras = new Cameras(this.scene, this.xr.sessionManager);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
log.error("Unknown button");
|
log.error("Unknown button");
|
||||||
return;
|
return;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user