Fixed up text entry for immersive and xr emulation.
This commit is contained in:
parent
c74dc62654
commit
06b2989f3a
@ -52,6 +52,7 @@ export class Right extends Base {
|
||||
if (abutton) {
|
||||
abutton.onButtonStateChangedObservable.add((value) => {
|
||||
if (value.pressed) {
|
||||
log.getLogger("right").debug("a-button pressed");
|
||||
Controllers.controllerObserver.notifyObservers({type: 'menu'});
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,5 +1,14 @@
|
||||
import {DiagramEntity} from "./diagramEntity";
|
||||
import {AbstractMesh, Color3, InstancedMesh, Mesh, Scene, StandardMaterial} from "@babylonjs/core";
|
||||
import {
|
||||
AbstractMesh,
|
||||
Color3,
|
||||
DynamicTexture,
|
||||
InstancedMesh,
|
||||
Mesh,
|
||||
MeshBuilder,
|
||||
Scene,
|
||||
StandardMaterial
|
||||
} from "@babylonjs/core";
|
||||
import {v4 as uuidv4} from 'uuid';
|
||||
import {Toolbox} from "../toolbox/toolbox";
|
||||
import log from "loglevel";
|
||||
@ -57,6 +66,7 @@ export class MeshConverter {
|
||||
mesh.metadata = {template: entity.template};
|
||||
if (entity.text) {
|
||||
mesh.metadata.text = entity.text;
|
||||
this.updateTextNode(mesh, entity.text);
|
||||
}
|
||||
if (entity.position) {
|
||||
mesh.position = entity.position;
|
||||
@ -82,4 +92,50 @@ export class MeshConverter {
|
||||
|
||||
}
|
||||
|
||||
public static updateTextNode(mesh: AbstractMesh, text: string) {
|
||||
let textNode = (mesh.getChildren((node) => {
|
||||
return node.name == 'text'
|
||||
})[0] as Mesh);
|
||||
if (textNode) {
|
||||
textNode.dispose(false, true);
|
||||
}
|
||||
|
||||
//Set font
|
||||
const height = 0.125;
|
||||
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", 64, mesh.getScene());
|
||||
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
|
||||
}, mesh.getScene(), false);
|
||||
const mat = new StandardMaterial("mat", mesh.getScene());
|
||||
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}, mesh.getScene());
|
||||
plane.material = mat;
|
||||
plane.billboardMode = Mesh.BILLBOARDMODE_ALL;
|
||||
//textNode = this.updateTextNode(mesh, entity.text);
|
||||
plane.parent = mesh;
|
||||
log.getLogger('bmenu').debug("max y", mesh.getBoundingInfo().boundingBox.maximum.y);
|
||||
plane.position.y = .5+ (height / 2);
|
||||
|
||||
return plane;
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,7 @@ import {
|
||||
AbstractMesh,
|
||||
GizmoManager,
|
||||
PointerEventTypes,
|
||||
PointerInfo,
|
||||
Scene,
|
||||
Vector3,
|
||||
WebXRExperienceHelper
|
||||
@ -40,21 +41,27 @@ export class Bmenu {
|
||||
case PointerEventTypes.POINTERPICK:
|
||||
if (pointerInfo.pickInfo?.pickedMesh?.metadata?.template &&
|
||||
pointerInfo.pickInfo?.pickedMesh?.parent?.parent?.id != "toolbox") {
|
||||
if (this.textInput) {
|
||||
this.textInput.blur();
|
||||
this.textInput.remove();
|
||||
this.textInput = null;
|
||||
}
|
||||
if (this.textView) {
|
||||
this.textView.dispose().then(() => {
|
||||
log.getLogger("bmenu").debug("disposed");
|
||||
this.cleanup()
|
||||
.then(() => {
|
||||
log.getLogger("bmenu").debug("cleaned up");
|
||||
})
|
||||
.catch((e) => {
|
||||
log.getLogger("bmenu").error(e);
|
||||
});
|
||||
this.handleEventStateAction(pointerInfo).then(() => {
|
||||
log.getLogger("bmenu").debug("handled");
|
||||
}).catch((e) => {
|
||||
log.getLogger("bmenu").error(e);
|
||||
});
|
||||
this.textView = null;
|
||||
}
|
||||
switch (this.state) {
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async handleEventStateAction(pointerInfo: PointerInfo) {
|
||||
switch (this.state) {
|
||||
case BmenuState.REMOVING:
|
||||
log.debug("removing " + pointerInfo.pickInfo.pickedMesh.id);
|
||||
const event: DiagramEvent = {
|
||||
@ -82,15 +89,11 @@ export class Bmenu {
|
||||
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);
|
||||
@ -106,41 +109,40 @@ export class Bmenu {
|
||||
log.debug(event);
|
||||
});
|
||||
const textView = new InputTextView(this.scene, this.xr, mesh)
|
||||
textView.show(textInput.value);
|
||||
await textView.show(textInput.value);
|
||||
textInput.addEventListener('keydown', (event) => {
|
||||
if (event.key == "Enter") {
|
||||
log.getLogger('bmenu').debug("enter");
|
||||
MeshConverter.updateTextNode(mesh, textInput.value);
|
||||
this.persist(mesh, textInput.value);
|
||||
textInput.blur();
|
||||
textInput.remove();
|
||||
this.textView.dispose();
|
||||
this.textView = null;
|
||||
this.textInput = null;
|
||||
this.cleanup();
|
||||
} else {
|
||||
textView.updateText(textInput.value);
|
||||
MeshConverter.updateTextNode(mesh, textInput.value);
|
||||
}
|
||||
});
|
||||
this.textView = textView;
|
||||
} else {
|
||||
textInput.addEventListener('keydown', (event)=> {
|
||||
log.debug(event);
|
||||
if (event.key == "Enter") {
|
||||
textInput.addEventListener('blur', () => {
|
||||
log.getLogger('bmenu').debug("blur");
|
||||
MeshConverter.updateTextNode(mesh, textInput.value);
|
||||
this.persist(mesh, textInput.value);
|
||||
textInput.blur();
|
||||
textInput.remove();
|
||||
this.textInput = null;
|
||||
this.textView = null;
|
||||
}
|
||||
this.cleanup();
|
||||
});
|
||||
}
|
||||
this.textInput = textInput;
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
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) {
|
||||
if (mesh.metadata) {
|
||||
@ -153,6 +155,7 @@ export class Bmenu {
|
||||
entity: MeshConverter.toDiagramEntity(mesh),
|
||||
});
|
||||
}
|
||||
|
||||
makeButton(name: string, id: string) {
|
||||
const button = new Button3D(name);
|
||||
button.scaling = new Vector3(.1, .1, .1);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user