Fixed up menu system.

This commit is contained in:
Michael Mainguy 2023-08-25 13:26:19 -05:00
parent 16f9f7f92c
commit e43a9e9d41
7 changed files with 154 additions and 65 deletions

View File

@ -96,11 +96,13 @@ export class Base {
}
public disable() {
this.scene.preventDefaultOnPointerDown = true;
this.controller.motionController.rootMesh.setEnabled(false)
this.controller.pointer.setEnabled(false);
}
public enable() {
this.scene.preventDefaultOnPointerDown = false;
this.controller.motionController.rootMesh.setEnabled(true);
this.controller.pointer.setEnabled(true)
}
@ -112,7 +114,7 @@ export class Base {
}
const template = mesh?.metadata?.template;
if (!template) {
if (mesh?.id == "handle") {
if (mesh?.metadata?.handle == true) {
mesh && mesh.setParent(this.controller.motionController.rootMesh);
this.grabbedMesh = mesh;
} else {
@ -163,7 +165,7 @@ export class Base {
private toolboxHandleWasGrabbed(mesh: AbstractMesh): boolean {
if (!mesh?.metadata?.template
&& mesh?.id == "handle") {
&& mesh?.metadata?.handle == true) {
this.grabbedMesh = null;
this.previousParentId = null;
mesh.setParent(null);

View File

@ -1,7 +1,8 @@
import {Observable, Scene, WebXRDefaultExperience} from "@babylonjs/core";
import {MeshBuilder, Observable, Scene, Vector3, WebXRDefaultExperience} from "@babylonjs/core";
import log from "loglevel";
import {AdvancedDynamicTexture, InputText} from "@babylonjs/gui";
import {AdvancedDynamicTexture, Control, InputText, VirtualKeyboard} from "@babylonjs/gui";
import {ControllerEventType, Controllers} from "../controllers/controllers";
import {setMenuPosition} from "../util/functions/setMenuPosition";
export type TextEvent = {
text: string;
@ -15,33 +16,71 @@ export type InputTextViewOptions = {
export class InputTextView {
public readonly onTextObservable: Observable<TextEvent> = new Observable<TextEvent>();
private readonly text: string;
private readonly text: string = "";
private readonly scene: Scene;
private readonly controllers: Controllers;
private readonly xr: WebXRDefaultExperience;
constructor(options: InputTextViewOptions) {
if (options.text) {
this.text = options.text;
}
if (options.xr) {
this.xr = options.xr;
}
if (options.scene) {
this.scene = options.scene;
}
if (options.controllers) {
this.controllers = options.controllers;
}
constructor(text: string, xr: WebXRDefaultExperience, scene: Scene) {
this.text = text ? text : "";
this.xr = xr;
this.scene = scene;
}
public show() {
if ((this.xr as WebXRDefaultExperience).baseExperience?.sessionManager?.inXRSession) {
this.showVirtualKeyboard();
/*if ((this.xr as WebXRDefaultExperience).baseExperience?.sessionManager?.inXRSession) {
this.showXr();
} else {
this.showWeb();
}
}*/
}
public showVirtualKeyboard() {
const inputMesh = MeshBuilder.CreatePlane("input", {width: 1, height: .5}, this.scene);
const advancedTexture = AdvancedDynamicTexture.CreateForMesh(inputMesh, 2048, 1024, false);
const input = new InputText();
input.width = 0.5;
input.maxWidth = 0.5;
input.height = "64px";
input.text = this.text;
input.fontSize = "32px";
input.color = "white";
input.background = "black";
input.thickness = 3;
input.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
advancedTexture.addControl(input);
const keyboard = VirtualKeyboard.CreateDefaultLayout();
keyboard.scaleY = 2;
keyboard.scaleX = 2;
keyboard.transformCenterY = 0;
keyboard.transformCenterX = .5;
keyboard.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
keyboard.paddingTop = "70px"
keyboard.height = "768px";
keyboard.fontSizeInPixels = 24;
advancedTexture.addControl(keyboard);
keyboard.connect(input);
keyboard.isVisible = true;
keyboard.isEnabled = true;
keyboard.onKeyPressObservable.add((key) => {
if (key === '↵') {
this.onTextObservable.notifyObservers({text: input.text});
input.dispose();
keyboard.dispose();
advancedTexture.dispose();
inputMesh.dispose();
}
});
setMenuPosition(inputMesh, this.scene, new Vector3(0, .4, 0));
}
public showWeb() {
@ -59,6 +98,7 @@ export class InputTextView {
this.onTextObservable.notifyObservers({text: textInput.text});
textInput.dispose();
advancedTexture.dispose();
}
});

View File

@ -1,14 +1,14 @@
import {AdvancedDynamicTexture, RadioGroup, SelectionPanel} from "@babylonjs/gui";
import {AbstractMesh, MeshBuilder, Scene, WebXRDefaultExperience} from "@babylonjs/core";
import {AdvancedDynamicTexture, RadioGroup, SelectionPanel, StackPanel} from "@babylonjs/gui";
import {MeshBuilder, Scene, Vector3, WebXRDefaultExperience} from "@babylonjs/core";
import {AppConfig} from "../util/appConfig";
import {ControllerEventType, Controllers} from "../controllers/controllers";
import {DiaSounds} from "../util/diaSounds";
import {AbstractMenu} from "./abstractMenu";
import {setMenuPosition} from "../util/functions/setMenuPosition";
import {MenuHandle} from "./menuHandle";
export class ConfigMenu extends AbstractMenu {
private sounds: DiaSounds;
private configPlane: AbstractMesh = null;
private yObserver;
private config: AppConfig;
@ -42,44 +42,68 @@ export class ConfigMenu extends AbstractMenu {
}
private handle: MenuHandle;
public toggle() {
if (this.configPlane) {
if (this.handle) {
this.handle.mesh.dispose(false, true);
this.sounds.exit.play();
this.configPlane.dispose();
this.configPlane = null;
this.handle = null;
return;
}
this.sounds.enter.play();
const width = .25;
const height = .75;
const res = 256;
const heightPixels = Math.round((height / width) * res);
this.configPlane = MeshBuilder
const configPlane = MeshBuilder
.CreatePlane("gridSizePlane",
{
width: .25,
height: .75
width: .6,
height: .3
}, this.scene);
const configTexture = AdvancedDynamicTexture.CreateForMesh(this.configPlane, res, heightPixels);
configTexture.background = "white";
const selectionPanel = new SelectionPanel("selectionPanel");
configTexture.addControl(selectionPanel)
this.buildGridSizeControl(selectionPanel);
this.buildCreateScaleControl(selectionPanel);
this.buildRotationSnapControl(selectionPanel);
this.buildTurnSnapControl(selectionPanel);
this.handle = new MenuHandle(configPlane);
const configTexture = AdvancedDynamicTexture.CreateForMesh(configPlane, 2048, 1024);
setMenuPosition(this.configPlane, this.scene);
configTexture.background = "white";
const columnPanel = new StackPanel('columns');
columnPanel.fontSize = "48px";
columnPanel.isVertical = false;
configTexture.addControl(columnPanel);
const selectionPanel1 = new SelectionPanel("selectionPanel1");
selectionPanel1.width = .5;
columnPanel.addControl(selectionPanel1);
this.buildGridSizeControl(selectionPanel1);
this.buildCreateScaleControl(selectionPanel1);
const selectionPanel2 = new SelectionPanel("selectionPanel2");
selectionPanel2.width = .5;
columnPanel.addControl(selectionPanel2);
this.buildRotationSnapControl(selectionPanel2);
this.buildTurnSnapControl(selectionPanel2);
configPlane.position.set(0, .2, 0);
setMenuPosition(this.handle.mesh, this.scene, new Vector3(0, .4, 0));
}
private adjustRadio(radio: RadioGroup) {
radio.groupPanel.height = "512px";
radio.groupPanel.fontSize = "64px";
radio.groupPanel.children[0].height = "70px";
radio.groupPanel.paddingLeft = "16px";
radio.selectors.forEach((panel) => {
panel.children[0].height = "64px";
panel.children[0].width = "64px";
panel.children[1].paddingLeft = "32px";
panel.paddingTop = "16px";
panel.fontSize = "60px";
panel.adaptHeightToChildren = true;
});
}
private buildCreateScaleControl(selectionPanel: SelectionPanel): RadioGroup {
const radio = new RadioGroup("Create Scale");
selectionPanel.addGroup(radio);
selectionPanel.addGroup(radio);
for (const [index, snap] of this.gridSnaps.entries()) {
const selected = (this.config.current.createSnap == snap.value);
radio.addRadio(snap.label, this.createVal.bind(this), selected);
}
this.adjustRadio(radio);
return radio;
}
@ -90,6 +114,7 @@ export class ConfigMenu extends AbstractMenu {
const selected = (this.config.current.rotateSnap == snap.value);
radio.addRadio(snap.label, this.rotateVal.bind(this), selected);
}
this.adjustRadio(radio);
return radio;
}
@ -103,6 +128,7 @@ export class ConfigMenu extends AbstractMenu {
radio.addRadio(snap.label, this.gridVal.bind(this), selected);
}
this.adjustRadio(radio);
return radio;
}
@ -113,6 +139,7 @@ export class ConfigMenu extends AbstractMenu {
const selected = (this.config.current.turnSnap == snap.value);
radio.addRadio(snap.label, this.turnVal.bind(this), selected);
}
this.adjustRadio(radio);
return radio;
}

View File

@ -129,7 +129,7 @@ export class EditMenu extends AbstractMenu {
} else {
this.sounds.enter.play();
setMenuPosition(this.manager.rootContainer.children[0].node, this.scene);
setMenuPosition(this.manager.rootContainer.children[0].node, this.scene, new Vector3(0, .4, 0));
this.isVisible = true;
}
}
@ -252,7 +252,7 @@ export class EditMenu extends AbstractMenu {
if (mesh?.metadata?.text) {
text = mesh.metadata.text;
}
const textInput = new InputTextView({xr: this.xr, text: text, controllers: this.controllers});
const textInput = new InputTextView(text, this.xr, this.scene);
textInput.show();
textInput.onTextObservable.addOnce((value) => {
@ -264,7 +264,7 @@ export class EditMenu extends AbstractMenu {
}
private showNewRelic() {
const inputTextView = new InputTextView({xr: this.xr, scene: this.scene, text: "New Relic"});
const inputTextView = new InputTextView('test', this.xr, this.scene);
inputTextView.show();
inputTextView.onTextObservable.addOnce((value) => {
const config = this.diagramManager.config.current;

30
src/menus/menuHandle.ts Normal file
View File

@ -0,0 +1,30 @@
import {AbstractMesh, Color3, MeshBuilder, Scene, StandardMaterial, TransformNode, Vector3} from "@babylonjs/core";
export class MenuHandle {
public mesh: AbstractMesh;
private menuTransformNode: TransformNode;
constructor(mesh: TransformNode) {
this.menuTransformNode = mesh;
this.buildHandle(mesh.getScene());
}
private buildHandle(scene: Scene) {
const handle = MeshBuilder.CreateCapsule("handle", {
radius: .05,
orientation: Vector3.Right(),
height: .4
}, scene);
handle.id = "handle-" + this.menuTransformNode.id + "-mesh";
const handleMaterial = new StandardMaterial("handle-" + this.menuTransformNode.id, scene);
handleMaterial.diffuseColor = Color3.FromHexString("#EEEEFF");
handleMaterial.alpha = .8;
handle.material = handleMaterial;
handle.position = Vector3.Zero();
handle.metadata = {handle: true};
if (this.menuTransformNode) {
this.menuTransformNode.setParent(handle);
}
this.mesh = handle;
}
}

View File

@ -1,9 +1,10 @@
import {Color3, Mesh, MeshBuilder, Observable, Scene, StandardMaterial, TransformNode, Vector3} from "@babylonjs/core";
import {Color3, Mesh, Observable, Scene, TransformNode, Vector3} from "@babylonjs/core";
import {Button3D, GUI3DManager, StackPanel3D, TextBlock} from "@babylonjs/gui";
import {ControllerEventType, Controllers} from "../controllers/controllers";
import {setMenuPosition} from "../util/functions/setMenuPosition";
import {buildColor} from "./functions/buildColor";
import {MenuHandle} from "../menus/menuHandle";
export class Toolbox {
private index = 0;
@ -15,7 +16,7 @@ export class Toolbox {
private readonly xObserver;
public readonly colorChangeObservable: Observable<{ oldColor: string, newColor: string }> =
new Observable<{ oldColor: string; newColor: string }>()
private handle: MenuHandle;
constructor(scene: Scene, controllers: Controllers) {
this.scene = scene;
this.controllers = controllers;
@ -23,20 +24,9 @@ export class Toolbox {
this.manager = new GUI3DManager(scene);
this.manager.addControl(this.addPanel);
this.node = new TransformNode("toolbox", this.scene);
const handle = MeshBuilder.CreateCapsule("handle", {
radius: .05,
orientation: Vector3.Right(),
height: .4
}, this.scene);
handle.id = "handle";
const handleMaterial = new StandardMaterial("handle-material", this.scene);
handleMaterial.diffuseColor = Color3.FromHexString("#EEEEFF");
handleMaterial.alpha = .8;
handle.material = handleMaterial;
handle.position = Vector3.Zero();
this.node.parent = handle;
this.handle = new MenuHandle(this.node);
this.node.position.y = .1;
this.node.position.z = .2;
this.node.scaling = new Vector3(0.6, 0.6, 0.6);
this.buildToolbox();

View File

@ -3,11 +3,11 @@ import {getFrontPosition} from "./getFrontPosition";
export function setMenuPosition(node: TransformNode, scene: Scene, offset: Vector3 = Vector3.Zero()) {
const front = getFrontPosition(.8, scene);
front.y = scene.activeCamera.globalPosition.y;
//front.y = scene.activeCamera.globalPosition.y;
node.position = front;
node.position.addInPlace(offset);
node.lookAt(scene.activeCamera.globalPosition);
node.rotation.y = node.rotation.y + Math.PI;
node.position.y -= .5;
node.lookAt(scene.activeCamera.globalPosition);
node.rotation.y = node.rotation.y + Math.PI;
}