Added Initial Config Menu.

This commit is contained in:
Michael Mainguy 2023-07-27 15:43:34 -05:00
parent 06b2989f3a
commit 9d5cb0ab95
13 changed files with 169 additions and 59 deletions

View File

@ -23,7 +23,7 @@ import HavokPhysics from "@babylonjs/havok";
import {Rigplatform} from "./controllers/rigplatform";
import {DiagramManager} from "./diagram/diagramManager";
import {Toolbox} from "./toolbox/toolbox";
import {DualshockEventMapper} from "./util/DualshockEventMapper";
import {DualshockEventMapper} from "./util/dualshockEventMapper";
import log from "loglevel";

View File

@ -24,6 +24,7 @@ export class Base {
protected previousRotation: Vector3 = null;
protected previousScaling: Vector3 = null;
protected previousPosition: Vector3 = null;
protected readonly xr: WebXRDefaultExperience;
constructor(controller: WebXRInputSource, scene: Scene, xr: WebXRDefaultExperience) {
@ -42,18 +43,30 @@ export class Base {
this.initGrip(init.components['xr-standard-squeeze']);
});
}
public disable() {
this.controller.motionController.rootMesh.setEnabled(false);
this.controller.pointer.setEnabled(false);
}
public enable() {
this.controller.motionController.rootMesh.setEnabled(true);
this.controller.pointer.setEnabled(true);
}
private createCopy(mesh: AbstractMesh) {
if (!mesh.isAnInstance) {
return new InstancedMesh("new", (mesh as Mesh));
return new InstancedMesh("new", (mesh as Mesh));
} else {
return new InstancedMesh("new", (mesh as InstancedMesh).sourceMesh);
return new InstancedMesh("new", (mesh as InstancedMesh).sourceMesh);
}
}
private initGrip(grip: WebXRControllerComponent) {
grip.onButtonStateChangedObservable.add(() => {
if (grip.changes.pressed) {
if (grip.pressed){
if (grip.pressed) {
let mesh = this.scene.meshUnderPointer;
if (this.xr.pointerSelection.getMeshUnderPointer) {
mesh = this.xr.pointerSelection.getMeshUnderPointer(this.controller.uniqueId);

View File

@ -1,7 +1,9 @@
import {AbstractMesh, Observable, TransformNode} from "@babylonjs/core";
export type ControllerEventType = {
type: string
}
export class Controllers {
public static movable: TransformNode | AbstractMesh;
public static controllerObserver = new Observable();
public static controllerObserver: Observable<ControllerEventType> = new Observable();
}

View File

@ -1,17 +1,18 @@
import {Scene, Vector3, WebXRDefaultExperience, WebXRInputSource} from "@babylonjs/core";
import {Scene, Vector3, WebXRControllerComponent, WebXRDefaultExperience, WebXRInputSource} from "@babylonjs/core";
import {Base} from "./base";
import {Controllers} from "./controllers";
import log from "loglevel";
import {ConfigMenu} from "../menus/configMenu";
export class Left extends Base {
public static instance: Left;
public configMenu: ConfigMenu;
constructor(controller:
WebXRInputSource, scene: Scene, xr: WebXRDefaultExperience) {
super(controller, scene, xr);
this.configMenu = new ConfigMenu(this.scene, xr.baseExperience);
Left.instance = this;
this.controller.onMotionControllerInitObservable.add((init) => {
if (init.components['xr-standard-thumbstick']) {
@ -24,6 +25,8 @@ export class Left extends Base {
this.moveMovable(value);
}
});
this.initXButton(init.components['x-button']);
this.initYButton(init.components['y-button']);
init.components['xr-standard-thumbstick'].onButtonStateChangedObservable.add((value) => {
if (value.pressed) {
log.trace('Left', 'thumbstick changed');
@ -35,6 +38,26 @@ export class Left extends Base {
}
private initXButton(xbutton: WebXRControllerComponent) {
if (xbutton) {
xbutton.onButtonStateChangedObservable.add((button) => {
if (button.pressed) {
Controllers.controllerObserver.notifyObservers({type: 'x-button', value: button.value});
}
});
}
}
private initYButton(ybutton: WebXRControllerComponent) {
if (ybutton) {
ybutton.onButtonStateChangedObservable.add((button) => {
if (button.pressed) {
Controllers.controllerObserver.notifyObservers({type: 'y-button', value: button.value});
}
});
}
}
private moveMovable(value: { x: number, y: number }) {
if (Math.abs(value.x) > .1) {
Controllers.movable.position.x += .005 * Math.sign(value.x);

View File

@ -1,11 +1,5 @@
import {Base} from "./base";
import {
Scene,
Vector3,
WebXRControllerComponent,
WebXRDefaultExperience,
WebXRInputSource
} from "@babylonjs/core";
import {Scene, Vector3, WebXRControllerComponent, WebXRDefaultExperience, WebXRInputSource} from "@babylonjs/core";
import {Controllers} from "./controllers";
import log from "loglevel";
@ -22,8 +16,6 @@ export class Right extends Base {
this.initAButton(init.components['a-button']);
this.initThumbstick(init.components['xr-standard-thumbstick']);
});
}
private initBButton(bbutton: WebXRControllerComponent) {

View File

@ -16,16 +16,15 @@ import {
} from "@babylonjs/core";
import {Right} from "./right";
import {Left} from "./left";
import {Bmenu} from "../menus/bmenu";
import {EditMenu} from "../menus/editMenu";
import {Controllers} from "./controllers";
import log from "loglevel";
export class Rigplatform {
private velocityIndex = 2;
private readonly velocityArray = [0.01, 0.1, 1, 2, 5];
public bMenu: Bmenu;
public bMenu: EditMenu;
private readonly scene: Scene;
public static instance: Rigplatform;
private static xr: WebXRDefaultExperience;
@ -41,8 +40,9 @@ export class Rigplatform {
this.scene = scene;
Rigplatform.xr = xr;
Rigplatform.instance = this;
this.bMenu = new Bmenu(scene, xr.baseExperience);
this.bMenu = new EditMenu(scene, xr.baseExperience);
this.camera = scene.activeCamera;
this.rigMesh = MeshBuilder.CreateBox("platform", {width: 2, height: .02, depth: 2}, scene);
for (const cam of scene.cameras) {
cam.parent = this.rigMesh;

View File

@ -1,11 +0,0 @@
export class Amenu {
private visible = false;
constructor() {
}
public toggle() {
this.visible = !this.visible;
}
}

68
src/menus/configMenu.ts Normal file
View File

@ -0,0 +1,68 @@
import {AdvancedDynamicTexture, RadioGroup, SelectionPanel} from "@babylonjs/gui";
import {AbstractMesh, Angle, MeshBuilder, Scene, WebXRExperienceHelper} from "@babylonjs/core";
import {CameraHelper} from "../util/cameraHelper";
import log from "loglevel";
import {AppConfig} from "../util/appConfig";
import {Controllers} from "../controllers/controllers";
export class ConfigMenu {
private readonly scene: Scene;
private readonly xr: WebXRExperienceHelper;
private configPlane: AbstractMesh = null;
constructor(scene: Scene, xr: WebXRExperienceHelper) {
this.scene = scene;
this.xr = xr;
Controllers.controllerObserver.add((event) => {
if (event.type == 'x-button') {
this.toggle();
}
});
}
public toggle() {
if (this.configPlane) {
this.configPlane.dispose();
this.configPlane = null;
return;
}
this.configPlane = MeshBuilder
.CreatePlane("gridSizePlane",
{
width: .25,
height: .5
}, this.scene);
const configTexture = AdvancedDynamicTexture.CreateForMesh(this.configPlane, 256, 512);
configTexture.background = "white";
const selectionPanel = new SelectionPanel("selectionPanel");
selectionPanel.fontSize = "24px";
selectionPanel.height = "100%";
configTexture.addControl(selectionPanel)
const radio1 = new RadioGroup("Rotation Snap");
radio1.addRadio("Off", this.rotateVal);
radio1.addRadio("22.5 degrees", this.rotateVal);
radio1.addRadio("45 degrees", this.rotateVal);
radio1.addRadio("90 degrees", this.rotateVal);
selectionPanel.addGroup(radio1);
const radio2 = new RadioGroup("Grid Snap");
radio2.addRadio("Off", this.gridVal);
radio2.addRadio("1 cm", this.gridVal);
radio2.addRadio("10 cm", this.gridVal);
radio2.addRadio("25 cm", this.gridVal);
selectionPanel.addGroup(radio1);
selectionPanel.addGroup(radio2);
this.configPlane.position = CameraHelper.getFrontPosition(2, this.scene);
this.configPlane.rotation.y = Angle.FromDegrees(180).radians();
}
private rotateVal(value) {
AppConfig.config.rotateSnap = AppConfig.config.rotateSnapArray[value];
log.debug("configMenu", "rotate Snap", value);
}
private gridVal(value) {
AppConfig.config.gridSnap = AppConfig.config.gridSnapArray[value];
log.debug("configMenu", "grid Snap", value);
}
}

View File

@ -14,8 +14,10 @@ import {DiagramEvent, DiagramEventType} from "../diagram/diagramEntity";
import {MeshConverter} from "../diagram/meshConverter";
import log from "loglevel";
import {InputTextView} from "../information/inputTextView";
import {Right} from "../controllers/right";
import {Left} from "../controllers/left";
export class Bmenu {
export class EditMenu {
private state: BmenuState = BmenuState.NONE;
private manager: GUI3DManager;
private readonly scene: Scene;
@ -102,6 +104,10 @@ export class Bmenu {
} else {
textInput.value = "";
}
if (this.xr.sessionManager.inXRSession) {
Right.instance.disable();
Left.instance.disable();
}
textInput.focus();
if (navigator.userAgent.indexOf('Macintosh') > -1) {
@ -128,6 +134,8 @@ export class Bmenu {
MeshConverter.updateTextNode(mesh, textInput.value);
this.persist(mesh, textInput.value);
this.cleanup();
Right.instance.enable();
Left.instance.enable();
});
}
this.textInput = textInput;

View File

@ -1,9 +1,13 @@
import {
AbstractMesh, Angle,
Color3, InstancedMesh, Mesh,
AbstractMesh,
Angle,
Color3,
InstancedMesh,
Mesh,
MeshBuilder,
Scene,
StandardMaterial, TransformNode,
StandardMaterial,
TransformNode,
Vector3,
WebXRExperienceHelper
} from "@babylonjs/core";
@ -80,8 +84,6 @@ export class Toolbox {
this.addPanel.position = new Vector3(0, 0, .5);
addButton.onPointerClickObservable.add(() => {
this.buildColor(Color3.Random());
});
}
@ -106,14 +108,16 @@ export class Toolbox {
newItem.position = new Vector3(this.calculatePosition(++i), .1, 0);
}
}
const myPlane = MeshBuilder
const colorPickerPlane = MeshBuilder
.CreatePlane("myPlane",
{width: Toolbox.WIDGET_SIZE,
height: Toolbox.WIDGET_SIZE}, this.scene);
myPlane.parent=mesh;
myPlane.position= new Vector3(this.calculatePosition(++i), .1, 0);
{
width: Toolbox.WIDGET_SIZE,
height: Toolbox.WIDGET_SIZE
}, this.scene);
colorPickerPlane.parent = mesh;
colorPickerPlane.position = new Vector3(this.calculatePosition(++i), .1, 0);
const advancedTexture2 = AdvancedDynamicTexture.CreateForMesh(myPlane, 1024, 1024);
const colorPickerTexture = AdvancedDynamicTexture.CreateForMesh(colorPickerPlane, 1024, 1024);
const colorPicker = new ColorPicker("color-picker");
colorPicker.scaleY = 5;
colorPicker.scaleX = 5;
@ -134,7 +138,7 @@ export class Toolbox {
);
});
advancedTexture2.addControl(colorPicker);
colorPickerTexture.addControl(colorPicker);
this.addPanel.position.z += .25;
this.node.position.z -= .125;
}

19
src/util/appConfig.ts Normal file
View File

@ -0,0 +1,19 @@
export class AppConfig {
public gridSnap = 0;
public rotateSnap = 0;
public gridSnapArray =
[0, 0.1, 0.5, 1];
public rotateSnapArray =
[0, 22.5, 45, 90]
private static _config: AppConfig;
public static get config() {
if (!AppConfig._config) {
AppConfig._config = new AppConfig();
}
return AppConfig._config;
}
}

View File

@ -1,5 +1,6 @@
import {DualShockButton} from "@babylonjs/core";
import log from "loglevel";
type ButtonEvent = {
objectName?: string,
pressed: boolean,
@ -57,17 +58,18 @@ export class DualshockEventMapper {
log.debug('DualshockEventMapper','D-Pad Up');
break;
case 13:
log.debug('DualshockEventMapper','D-Pad Down');
log.debug('DualshockEventMapper', 'D-Pad Down');
buttonEvent.objectName = "left-controller";
buttonEvent.buttonIndex = 3;
break;
case 14:
log.debug('DualshockEventMapper','D-Pad Left');
log.debug('DualshockEventMapper', 'D-Pad Left');
log.debug('DualshockEventMapper', 'D-Pad Left');
buttonEvent.objectName = "left-controller";
buttonEvent.buttonIndex = 4;
break;
case 15:
log.debug('DualshockEventMapper','D-Pad Right');
log.debug('DualshockEventMapper', 'D-Pad Right');
break;
case 10:
log.debug('DualshockEventMapper','L3');

View File

@ -1,10 +0,0 @@
import {PlanePanel} from "@babylonjs/gui";
export class MyMenu extends PlanePanel {
public arrangeChildren: boolean = true;
protected _arrangeChildren() {
if (this.arrangeChildren) {
super._arrangeChildren();
}
}
}