Updated text input to work on desktop Mac
This commit is contained in:
parent
af2227b746
commit
c74dc62654
43
src/app.ts
43
src/app.ts
@ -30,10 +30,9 @@ import log from "loglevel";
|
|||||||
export class App {
|
export class App {
|
||||||
//preTasks = [havokModule];
|
//preTasks = [havokModule];
|
||||||
|
|
||||||
public static scene: Scene;
|
private scene: Scene;
|
||||||
public static xr: WebXRDefaultExperience;
|
private xr: WebXRDefaultExperience;
|
||||||
public static rig: Rigplatform;
|
private rig: Rigplatform;
|
||||||
public static gamepad: Gamepad;
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
log.setLevel('debug');
|
log.setLevel('debug');
|
||||||
@ -49,13 +48,13 @@ export class App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async initialize(canvas) {
|
async initialize(canvas) {
|
||||||
if (App.xr) {
|
if (this.xr) {
|
||||||
App.xr.dispose();
|
this.xr.dispose();
|
||||||
App.xr = null;
|
this.xr = null;
|
||||||
}
|
}
|
||||||
if (App.scene) {
|
if (this.scene) {
|
||||||
App.scene.dispose();
|
this.scene.dispose();
|
||||||
App.scene = null;
|
this.scene = null;
|
||||||
}
|
}
|
||||||
if (DiagramManager.onDiagramEventObservable) {
|
if (DiagramManager.onDiagramEventObservable) {
|
||||||
DiagramManager.onDiagramEventObservable.clear();
|
DiagramManager.onDiagramEventObservable.clear();
|
||||||
@ -64,7 +63,7 @@ export class App {
|
|||||||
const engine = new Engine(canvas, true);
|
const engine = new Engine(canvas, true);
|
||||||
const scene = new Scene(engine);
|
const scene = new Scene(engine);
|
||||||
|
|
||||||
App.scene = scene;
|
this.scene = scene;
|
||||||
|
|
||||||
|
|
||||||
const havokInstance = await HavokPhysics();
|
const havokInstance = await HavokPhysics();
|
||||||
@ -82,7 +81,7 @@ export class App {
|
|||||||
'./outdoor_field.jpeg', {},
|
'./outdoor_field.jpeg', {},
|
||||||
scene);
|
scene);
|
||||||
const ground = this.createGround();
|
const ground = this.createGround();
|
||||||
App.xr = await WebXRDefaultExperience.CreateAsync(scene, {
|
this.xr = await WebXRDefaultExperience.CreateAsync(scene, {
|
||||||
floorMeshes: [ground],
|
floorMeshes: [ground],
|
||||||
disableTeleportation: true,
|
disableTeleportation: true,
|
||||||
outputCanvasOptions: {
|
outputCanvasOptions: {
|
||||||
@ -96,9 +95,9 @@ export class App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
App.xr.baseExperience.onStateChangedObservable.add((state) => {
|
this.xr.baseExperience.onStateChangedObservable.add((state) => {
|
||||||
if (state == WebXRState.IN_XR) {
|
if (state == WebXRState.IN_XR) {
|
||||||
App.xr.baseExperience.camera.position = new Vector3(0, 1.6, 0);
|
this.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);
|
||||||
@ -108,11 +107,11 @@ export class App {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const diagramManager = new DiagramManager(App.scene, App.xr.baseExperience);
|
const diagramManager = new DiagramManager(this.scene, this.xr.baseExperience);
|
||||||
App.rig = new Rigplatform(App.scene, App.xr);
|
this.rig = new Rigplatform(this.scene, this.xr);
|
||||||
const toolbox = new Toolbox(scene, App.xr.baseExperience);
|
const toolbox = new Toolbox(scene, this.xr.baseExperience);
|
||||||
|
|
||||||
App.scene.gamepadManager.onGamepadConnectedObservable.add((gamepad) => {
|
this.scene.gamepadManager.onGamepadConnectedObservable.add((gamepad) => {
|
||||||
try {
|
try {
|
||||||
const dualshock = (gamepad as DualShockPad);
|
const dualshock = (gamepad as DualShockPad);
|
||||||
|
|
||||||
@ -197,18 +196,18 @@ export class App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createGround() {
|
createGround() {
|
||||||
const groundMaterial = new PBRMetallicRoughnessMaterial("groundMaterial", App.scene);
|
const groundMaterial = new PBRMetallicRoughnessMaterial("groundMaterial", this.scene);
|
||||||
const gText = new Texture("./grass1.jpeg", App.scene);
|
const gText = new Texture("./grass1.jpeg", this.scene);
|
||||||
gText.uScale = 40;
|
gText.uScale = 40;
|
||||||
gText.vScale = 40;
|
gText.vScale = 40;
|
||||||
groundMaterial.baseTexture = gText;
|
groundMaterial.baseTexture = gText;
|
||||||
groundMaterial.metallic = 0;
|
groundMaterial.metallic = 0;
|
||||||
groundMaterial.roughness = 1;
|
groundMaterial.roughness = 1;
|
||||||
|
|
||||||
const ground = MeshBuilder.CreateGround("ground", {width: 100, height: 100, subdivisions: 1}, App.scene);
|
const ground = MeshBuilder.CreateGround("ground", {width: 100, height: 100, subdivisions: 1}, this.scene);
|
||||||
|
|
||||||
ground.material = groundMaterial;
|
ground.material = groundMaterial;
|
||||||
new PhysicsAggregate(ground, PhysicsShapeType.BOX, {mass: 0}, App.scene);
|
new PhysicsAggregate(ground, PhysicsShapeType.BOX, {mass: 0}, this.scene);
|
||||||
return ground;
|
return ground;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,30 +1,7 @@
|
|||||||
import {AbstractMesh, Observable, TransformNode} from "@babylonjs/core";
|
import {AbstractMesh, Observable, TransformNode} from "@babylonjs/core";
|
||||||
|
|
||||||
export enum ControllerMovementMode {
|
|
||||||
ROTATE,
|
|
||||||
TRANSLATE
|
|
||||||
}
|
|
||||||
export class MeshHoverEvent {
|
|
||||||
public readonly mesh: AbstractMesh;
|
|
||||||
public readonly pointerId: string;
|
|
||||||
public readonly pointerMeshId: string;
|
|
||||||
public readonly isHovered: boolean;
|
|
||||||
constructor(mesh: AbstractMesh, isHovered: boolean, pointerId: string, pointerMeshId: string) {
|
|
||||||
this.mesh = mesh;
|
|
||||||
this.isHovered = isHovered;
|
|
||||||
this.pointerId = pointerId;
|
|
||||||
this.pointerMeshId = pointerMeshId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export class Controllers {
|
export class Controllers {
|
||||||
public static movable: TransformNode | AbstractMesh;
|
public static movable: TransformNode | AbstractMesh;
|
||||||
public static controllerObserver = new Observable();
|
public static controllerObserver = new Observable();
|
||||||
public static movementMode: ControllerMovementMode = ControllerMovementMode.ROTATE;
|
|
||||||
public static toggleMovementMode() {
|
|
||||||
if (this.movementMode == ControllerMovementMode.ROTATE) {
|
|
||||||
this.movementMode = ControllerMovementMode.TRANSLATE;
|
|
||||||
} else {
|
|
||||||
this.movementMode = ControllerMovementMode.ROTATE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -1,13 +1,12 @@
|
|||||||
import {Base} from "./base";
|
import {Base} from "./base";
|
||||||
import {
|
import {
|
||||||
Angle,
|
|
||||||
Scene,
|
Scene,
|
||||||
Vector3,
|
Vector3,
|
||||||
WebXRControllerComponent,
|
WebXRControllerComponent,
|
||||||
WebXRDefaultExperience,
|
WebXRDefaultExperience,
|
||||||
WebXRInputSource
|
WebXRInputSource
|
||||||
} from "@babylonjs/core";
|
} from "@babylonjs/core";
|
||||||
import {ControllerMovementMode, Controllers} from "./controllers";
|
import {Controllers} from "./controllers";
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
|
|
||||||
export class Right extends Base {
|
export class Right extends Base {
|
||||||
@ -26,6 +25,7 @@ export class Right extends Base {
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private initBButton(bbutton: WebXRControllerComponent) {
|
private initBButton(bbutton: WebXRControllerComponent) {
|
||||||
if (bbutton) {
|
if (bbutton) {
|
||||||
bbutton.onButtonStateChangedObservable.add((button) => {
|
bbutton.onButtonStateChangedObservable.add((button) => {
|
||||||
@ -62,15 +62,7 @@ export class Right extends Base {
|
|||||||
if (thumbstick) {
|
if (thumbstick) {
|
||||||
thumbstick.onAxisValueChangedObservable.add((value) => {
|
thumbstick.onAxisValueChangedObservable.add((value) => {
|
||||||
log.trace('Right', `thumbstick moved ${value.x}, ${value.y}`);
|
log.trace('Right', `thumbstick moved ${value.x}, ${value.y}`);
|
||||||
if (!Controllers.movable) {
|
|
||||||
this.moveRig(value);
|
this.moveRig(value);
|
||||||
} else {
|
|
||||||
if (Controllers.movementMode == ControllerMovementMode.ROTATE) {
|
|
||||||
this.rotateMovable(value);
|
|
||||||
} else {
|
|
||||||
this.moveMovable(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
thumbstick.onButtonStateChangedObservable.add((value) => {
|
thumbstick.onButtonStateChangedObservable.add((value) => {
|
||||||
if (value.pressed) {
|
if (value.pressed) {
|
||||||
@ -98,32 +90,4 @@ export class Right extends Base {
|
|||||||
Controllers.controllerObserver.notifyObservers({type: 'updown', value: 0});
|
Controllers.controllerObserver.notifyObservers({type: 'updown', value: 0});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private rotateMovable(value: { x: number; y: number }) {
|
|
||||||
if (Math.abs(value.y) > .1) {
|
|
||||||
Controllers.movable.rotation.x +=
|
|
||||||
Angle.FromDegrees(Math.sign(value.y)).radians();
|
|
||||||
Controllers.movable.rotation.x = this.fixRadians(Controllers.movable.rotation.x);
|
|
||||||
}
|
|
||||||
if (Math.abs(value.x) > .1) {
|
|
||||||
Controllers.movable.rotation.z +=
|
|
||||||
Angle.FromDegrees(Math.sign(value.x)).radians();
|
|
||||||
Controllers.movable.rotation.z = this.fixRadians(Controllers.movable.rotation.z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private fixRadians(value: number) {
|
|
||||||
if (value > 2 * Math.PI) {
|
|
||||||
return value - 2 * Math.PI;
|
|
||||||
} else {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private moveMovable(value: { x: number; y: number }) {
|
|
||||||
if (Math.abs(value.y) > .1) {
|
|
||||||
Controllers.movable.position.z += Math.sign(value.y) * -.005;
|
|
||||||
}
|
|
||||||
if (Math.abs(value.x) > .1) {
|
|
||||||
Controllers.movable.position.x += Math.sign(value.x) * .005;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -10,7 +10,7 @@ import {
|
|||||||
PhysicsShapeType,
|
PhysicsShapeType,
|
||||||
Quaternion,
|
Quaternion,
|
||||||
Scene,
|
Scene,
|
||||||
StandardMaterial, TransformNode,
|
StandardMaterial,
|
||||||
Vector3,
|
Vector3,
|
||||||
WebXRDefaultExperience
|
WebXRDefaultExperience
|
||||||
} from "@babylonjs/core";
|
} from "@babylonjs/core";
|
||||||
@ -26,7 +26,7 @@ export class Rigplatform {
|
|||||||
private velocityIndex = 2;
|
private velocityIndex = 2;
|
||||||
private readonly velocityArray = [0.01, 0.1, 1, 2, 5];
|
private readonly velocityArray = [0.01, 0.1, 1, 2, 5];
|
||||||
public bMenu: Bmenu;
|
public bMenu: Bmenu;
|
||||||
private scene: Scene;
|
private readonly scene: Scene;
|
||||||
public static instance: Rigplatform;
|
public static instance: Rigplatform;
|
||||||
private static xr: WebXRDefaultExperience;
|
private static xr: WebXRDefaultExperience;
|
||||||
private yRotation: number = 0;
|
private yRotation: number = 0;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import {AbstractMesh, Color3, Material, Observable, Scene, WebXRExperienceHelper} from "@babylonjs/core";
|
import {Observable, Scene, WebXRExperienceHelper} from "@babylonjs/core";
|
||||||
|
|
||||||
import {DiagramEntity, DiagramEvent, DiagramEventType} from "./diagramEntity";
|
import {DiagramEntity, DiagramEvent, DiagramEventType} from "./diagramEntity";
|
||||||
import {IPersistenceManager} from "./persistenceManager";
|
import {IPersistenceManager} from "./persistenceManager";
|
||||||
@ -6,41 +6,36 @@ import {IndexdbPersistenceManager} from "./indexdbPersistenceManager";
|
|||||||
import {MeshConverter} from "./meshConverter";
|
import {MeshConverter} from "./meshConverter";
|
||||||
import log from "loglevel";
|
import log from "loglevel";
|
||||||
|
|
||||||
|
|
||||||
export class DiagramManager {
|
export class DiagramManager {
|
||||||
private persistenceManager: IPersistenceManager = new IndexdbPersistenceManager("diagram");
|
private persistenceManager: IPersistenceManager = new IndexdbPersistenceManager("diagram");
|
||||||
static onDiagramEventObservable: Observable<DiagramEvent> = new Observable();
|
static onDiagramEventObservable: Observable<DiagramEvent> = new Observable();
|
||||||
|
|
||||||
private readonly scene: Scene;
|
private readonly scene: Scene;
|
||||||
private xr: WebXRExperienceHelper;
|
private xr: WebXRExperienceHelper;
|
||||||
static currentMesh: AbstractMesh;
|
|
||||||
|
|
||||||
private materialMap: Map<string, Material> = new Map<string, Material>();
|
|
||||||
|
|
||||||
constructor(scene: Scene, xr: WebXRExperienceHelper) {
|
constructor(scene: Scene, xr: WebXRExperienceHelper) {
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
this.xr = xr;
|
this.xr = xr;
|
||||||
this.persistenceManager.updateObserver.add(this.onRemoteEvent, -1, true, this);
|
this.persistenceManager.updateObserver.add(this.onRemoteEvent, -1, true, this);
|
||||||
log.debug('DiagramManager', "remove event observer added");
|
log.getLogger('DiagramManager').debug( "remote event observer added");
|
||||||
this.persistenceManager.initialize();
|
this.persistenceManager.initialize();
|
||||||
|
|
||||||
if (!DiagramManager.onDiagramEventObservable) {
|
if (!DiagramManager.onDiagramEventObservable) {
|
||||||
log.debug('DiagramManager', "onDiagramEventObservable missing, recreated");
|
log.getLogger('DiagramManager').debug( "onDiagramEventObservable missing, recreated");
|
||||||
DiagramManager.onDiagramEventObservable = new Observable();
|
DiagramManager.onDiagramEventObservable = new Observable();
|
||||||
}
|
}
|
||||||
if (DiagramManager.onDiagramEventObservable.hasObservers()) {
|
if (DiagramManager.onDiagramEventObservable.hasObservers()) {
|
||||||
log.warn('DiagramManager', "onDiagramEventObservable already has Observers, this shouldn't happen");
|
log.getLogger('DiagramManager').debug("onDiagramEventObservable already has Observers, this shouldn't happen");
|
||||||
} else {
|
} else {
|
||||||
DiagramManager.onDiagramEventObservable.add(this.onDiagramEvent, -1, true, this);
|
DiagramManager.onDiagramEventObservable.add(this.onDiagramEvent, -1, true, this);
|
||||||
log.debug('DiagramManager', "onDiagramEventObservable Observer added");
|
log.getLogger('DiagramManager').debug( "onDiagramEventObservable Observer added");
|
||||||
}
|
}
|
||||||
log.debug('DiagramManager', "DiagramManager constructed");
|
log.getLogger('DiagramManager').debug( "DiagramManager constructed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private onRemoteEvent(event: DiagramEntity) {
|
private onRemoteEvent(event: DiagramEntity) {
|
||||||
//const mesh = Toolbox.instance.newMesh(ToolType[Object.entries(ToolType).find(e => e[1] == event.template)[0]], event.id);
|
//const mesh = Toolbox.instance.newMesh(ToolType[Object.entries(ToolType).find(e => e[1] == event.template)[0]], event.id);
|
||||||
log.debug('DiagramManager', event);
|
log.getLogger('DiagramManager').debug(event);
|
||||||
const mesh = MeshConverter.fromDiagramEntity(event, this.scene);
|
const mesh = MeshConverter.fromDiagramEntity(event, this.scene);
|
||||||
if (event.parent) {
|
if (event.parent) {
|
||||||
mesh.parent = this.scene.getMeshById(event.parent);
|
mesh.parent = this.scene.getMeshById(event.parent);
|
||||||
@ -48,6 +43,7 @@ export class DiagramManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onDiagramEvent(event: DiagramEvent) {
|
private onDiagramEvent(event: DiagramEvent) {
|
||||||
|
log.getLogger("DiagramManager").debug(event);
|
||||||
const entity = event.entity;
|
const entity = event.entity;
|
||||||
let mesh;
|
let mesh;
|
||||||
if (entity) {
|
if (entity) {
|
||||||
|
|||||||
46
src/information/inputTextView.ts
Normal file
46
src/information/inputTextView.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import {AbstractMesh, Angle, MeshBuilder, Scene, WebXRExperienceHelper} from "@babylonjs/core";
|
||||||
|
import {AdvancedDynamicTexture, InputText} from "@babylonjs/gui";
|
||||||
|
|
||||||
|
export class InputTextView {
|
||||||
|
private mesh: AbstractMesh;
|
||||||
|
private scene: Scene;
|
||||||
|
private xr: WebXRExperienceHelper;
|
||||||
|
private inputPlane: AbstractMesh;
|
||||||
|
private inputText: InputText;
|
||||||
|
constructor(scene: Scene, xr: WebXRExperienceHelper, mesh: AbstractMesh ) {
|
||||||
|
this.scene = scene;
|
||||||
|
this.xr = xr;
|
||||||
|
this.mesh = mesh;
|
||||||
|
}
|
||||||
|
public async show(text: string) {
|
||||||
|
this.inputPlane = MeshBuilder.CreatePlane("myPlane", {width: 1, height: .125}, this.scene);
|
||||||
|
const pos = this.mesh.absolutePosition;
|
||||||
|
pos.y += .2;
|
||||||
|
this.inputPlane.position= pos;
|
||||||
|
this.inputPlane.rotation.y = Angle.FromDegrees(180).radians();
|
||||||
|
const textDisplayTexture = AdvancedDynamicTexture.CreateForMesh(this.inputPlane, 1024, 128);
|
||||||
|
this.inputPlane.material.backFaceCulling = false;
|
||||||
|
this.inputText = this.createInputText();
|
||||||
|
this.inputText.text = text;
|
||||||
|
textDisplayTexture.addControl(this.inputText);
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,10 +13,7 @@ export class Cameras {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async getCameras() {
|
public async getCameras() {
|
||||||
|
this.cameras = await axios.get('https://local.immersiveidea.com/api/cameras');
|
||||||
const cameras = await axios.get('https://local.immersiveidea.com/api/cameras');
|
|
||||||
this.cameras = cameras;
|
|
||||||
//console.log(cameras);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public createCameras() {
|
public createCameras() {
|
||||||
|
|||||||
@ -1,34 +1,27 @@
|
|||||||
import {
|
import {
|
||||||
Angle,
|
AbstractMesh,
|
||||||
GizmoManager,
|
GizmoManager,
|
||||||
MeshBuilder,
|
|
||||||
PointerEventTypes,
|
PointerEventTypes,
|
||||||
Scene,
|
Scene,
|
||||||
Vector3,
|
Vector3,
|
||||||
WebXRExperienceHelper
|
WebXRExperienceHelper
|
||||||
} from "@babylonjs/core";
|
} from "@babylonjs/core";
|
||||||
import {
|
import {Button3D, GUI3DManager, StackPanel3D, TextBlock} from "@babylonjs/gui";
|
||||||
AdvancedDynamicTexture,
|
|
||||||
Button3D,
|
|
||||||
ColorPicker,
|
|
||||||
GUI3DManager,
|
|
||||||
InputText,
|
|
||||||
StackPanel3D,
|
|
||||||
TextBlock
|
|
||||||
} from "@babylonjs/gui";
|
|
||||||
import {DiagramManager} from "../diagram/diagramManager";
|
import {DiagramManager} from "../diagram/diagramManager";
|
||||||
import {BmenuState} from "./MenuState";
|
import {BmenuState} from "./MenuState";
|
||||||
import {DiagramEvent, DiagramEventType} from "../diagram/diagramEntity";
|
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";
|
||||||
|
|
||||||
export class Bmenu {
|
export class Bmenu {
|
||||||
private state: BmenuState = BmenuState.NONE;
|
private state: BmenuState = BmenuState.NONE;
|
||||||
private manager: GUI3DManager;
|
private manager: GUI3DManager;
|
||||||
private readonly scene: Scene;
|
private readonly scene: Scene;
|
||||||
|
private textView: InputTextView;
|
||||||
|
private textInput: HTMLElement;
|
||||||
private gizmoManager: GizmoManager;
|
private gizmoManager: GizmoManager;
|
||||||
private xr: WebXRExperienceHelper;
|
private xr: WebXRExperienceHelper;
|
||||||
private textInput: any;
|
|
||||||
|
|
||||||
constructor(scene: Scene, xr: WebXRExperienceHelper) {
|
constructor(scene: Scene, xr: WebXRExperienceHelper) {
|
||||||
|
|
||||||
@ -47,7 +40,21 @@ export class Bmenu {
|
|||||||
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") {
|
||||||
|
if (this.textInput) {
|
||||||
|
this.textInput.blur();
|
||||||
|
this.textInput.remove();
|
||||||
|
this.textInput = null;
|
||||||
|
}
|
||||||
|
if (this.textView) {
|
||||||
|
this.textView.dispose().then(() => {
|
||||||
|
log.getLogger("bmenu").debug("disposed");
|
||||||
|
}).catch((e) => {
|
||||||
|
log.getLogger("bmenu").error(e);
|
||||||
|
});
|
||||||
|
this.textView = null;
|
||||||
|
}
|
||||||
switch (this.state) {
|
switch (this.state) {
|
||||||
|
|
||||||
case BmenuState.REMOVING:
|
case BmenuState.REMOVING:
|
||||||
log.debug("removing " + pointerInfo.pickInfo.pickedMesh.id);
|
log.debug("removing " + pointerInfo.pickInfo.pickedMesh.id);
|
||||||
const event: DiagramEvent = {
|
const event: DiagramEvent = {
|
||||||
@ -82,40 +89,51 @@ export class Bmenu {
|
|||||||
case BmenuState.LABELING:
|
case BmenuState.LABELING:
|
||||||
const mesh = pointerInfo.pickInfo.pickedMesh;
|
const mesh = pointerInfo.pickInfo.pickedMesh;
|
||||||
log.debug("labeling " + mesh.id);
|
log.debug("labeling " + mesh.id);
|
||||||
/* const myPlane = MeshBuilder.CreatePlane("myPlane", {width: 1, height: .125}, this.scene);
|
|
||||||
//myPlane.parent=mesh;
|
|
||||||
const pos = mesh.absolutePosition;
|
|
||||||
pos.y += .2;
|
|
||||||
myPlane.position= pos;
|
|
||||||
myPlane.rotation.y = Angle.FromDegrees(180).radians();
|
|
||||||
const advancedTexture2 = AdvancedDynamicTexture.CreateForMesh(myPlane, 1024, 128);
|
|
||||||
myPlane.material.backFaceCulling = false;
|
|
||||||
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";
|
|
||||||
advancedTexture2.addControl(inputText);
|
|
||||||
|
|
||||||
*/
|
|
||||||
const textInput = document.createElement("input");
|
const textInput = document.createElement("input");
|
||||||
textInput.type = "text";
|
textInput.type = "text";
|
||||||
document.body.appendChild(textInput);
|
document.body.appendChild(textInput);
|
||||||
|
if (mesh?.metadata?.text) {
|
||||||
|
textInput.value = mesh.metadata.text;
|
||||||
|
} else {
|
||||||
textInput.value = "";
|
textInput.value = "";
|
||||||
|
}
|
||||||
textInput.focus();
|
textInput.focus();
|
||||||
|
|
||||||
|
if (navigator.userAgent.indexOf('Macintosh') > -1) {
|
||||||
textInput.addEventListener('input', (event)=> {
|
textInput.addEventListener('input', (event)=> {
|
||||||
log.debug(event);
|
log.debug(event);
|
||||||
});
|
});
|
||||||
|
const textView = new InputTextView(this.scene, this.xr, mesh)
|
||||||
|
textView.show(textInput.value);
|
||||||
|
textInput.addEventListener('keydown', (event)=> {
|
||||||
|
if (event.key == "Enter") {
|
||||||
|
this.persist(mesh, textInput.value);
|
||||||
|
textInput.blur();
|
||||||
|
textInput.remove();
|
||||||
|
this.textView.dispose();
|
||||||
|
this.textView = null;
|
||||||
|
this.textInput = null;
|
||||||
|
} else {
|
||||||
|
textView.updateText(textInput.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.textView = textView;
|
||||||
|
} else {
|
||||||
textInput.addEventListener('keydown', (event)=> {
|
textInput.addEventListener('keydown', (event)=> {
|
||||||
log.debug(event);
|
log.debug(event);
|
||||||
if (event.key == "Enter") {
|
if (event.key == "Enter") {
|
||||||
|
this.persist(mesh, textInput.value);
|
||||||
textInput.blur();
|
textInput.blur();
|
||||||
textInput.remove();
|
textInput.remove();
|
||||||
|
this.textInput = null;
|
||||||
|
this.textView = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
this.textInput = textInput;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -124,7 +142,17 @@ export class Bmenu {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
private persist(mesh: AbstractMesh, text: string) {
|
||||||
|
if (mesh.metadata) {
|
||||||
|
mesh.metadata.text = text;
|
||||||
|
} else {
|
||||||
|
log.getLogger('bmenu').error("mesh has no metadata");
|
||||||
|
}
|
||||||
|
DiagramManager.onDiagramEventObservable.notifyObservers({
|
||||||
|
type: DiagramEventType.MODIFY,
|
||||||
|
entity: MeshConverter.toDiagramEntity(mesh),
|
||||||
|
});
|
||||||
|
}
|
||||||
makeButton(name: string, id: string) {
|
makeButton(name: string, id: string) {
|
||||||
const button = new Button3D(name);
|
const button = new Button3D(name);
|
||||||
button.scaling = new Vector3(.1, .1, .1);
|
button.scaling = new Vector3(.1, .1, .1);
|
||||||
@ -133,18 +161,10 @@ export class Bmenu {
|
|||||||
text.fontSize = "24px";
|
text.fontSize = "24px";
|
||||||
text.color = "white";
|
text.color = "white";
|
||||||
button.content = text;
|
button.content = text;
|
||||||
button.onPointerClickObservable.add(this.#clickhandler, -1, false, this);
|
button.onPointerClickObservable.add(this.handleClick, -1, false, this);
|
||||||
return button;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getState() {
|
|
||||||
return this.state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public setState(state: BmenuState) {
|
|
||||||
this.state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
toggle() {
|
toggle() {
|
||||||
//console.log(mesh.name);
|
//console.log(mesh.name);
|
||||||
if (this.manager) {
|
if (this.manager) {
|
||||||
@ -167,7 +187,7 @@ export class Bmenu {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#clickhandler(_info, state) {
|
private handleClick(_info, state) {
|
||||||
switch (state.currentTarget.name) {
|
switch (state.currentTarget.name) {
|
||||||
case "modify":
|
case "modify":
|
||||||
this.state = BmenuState.MODIFYING;
|
this.state = BmenuState.MODIFYING;
|
||||||
|
|||||||
@ -1,16 +1,9 @@
|
|||||||
import {AbstractMesh, MeshBuilder, Scene, Vector3, WebXRExperienceHelper} from "@babylonjs/core";
|
import {AbstractMesh, MeshBuilder, Scene, WebXRExperienceHelper} from "@babylonjs/core";
|
||||||
import {
|
import {
|
||||||
AdvancedDynamicTexture,
|
AdvancedDynamicTexture
|
||||||
Button3D,
|
|
||||||
GUI3DManager, InputText, PlanePanel,
|
|
||||||
StackPanel, StackPanel3D,
|
|
||||||
TextBlock,
|
|
||||||
TouchHolographicButton
|
|
||||||
} from "@babylonjs/gui";
|
} from "@babylonjs/gui";
|
||||||
import {MyMenu} from "../util/myMenu";
|
|
||||||
|
|
||||||
export class Keyboard {
|
export class Keyboard {
|
||||||
private manager: GUI3DManager;
|
|
||||||
private readonly scene: Scene;
|
private readonly scene: Scene;
|
||||||
private mesh: AbstractMesh;
|
private mesh: AbstractMesh;
|
||||||
private panel: AbstractMesh;
|
private panel: AbstractMesh;
|
||||||
|
|||||||
@ -34,7 +34,7 @@ export class Toolbox {
|
|||||||
public readonly node : TransformNode;
|
public readonly node : TransformNode;
|
||||||
private readonly manager: GUI3DManager;
|
private readonly manager: GUI3DManager;
|
||||||
private readonly gridsize = 5;
|
private readonly gridsize = 5;
|
||||||
private addPanel: StackPanel3D;
|
private readonly addPanel: StackPanel3D;
|
||||||
constructor (scene:Scene, xr: WebXRExperienceHelper) {
|
constructor (scene:Scene, xr: WebXRExperienceHelper) {
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
this.addPanel = new StackPanel3D();
|
this.addPanel = new StackPanel3D();
|
||||||
@ -145,9 +145,6 @@ export class Toolbox {
|
|||||||
this.buildColor(Color3.FromHexString(color));
|
this.buildColor(Color3.FromHexString(color));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private nextPosition() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public buildTool(tool: ToolType, parent: AbstractMesh) {
|
public buildTool(tool: ToolType, parent: AbstractMesh) {
|
||||||
let newItem: Mesh;
|
let newItem: Mesh;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import {Angle, Color3, MeshBuilder, Scene, StandardMaterial, Texture} from "@babylonjs/core";
|
import {Angle, Color3, MeshBuilder, Scene, StandardMaterial, Texture} from "@babylonjs/core";
|
||||||
import googleStaticMapsTile from "google-static-maps-tile";
|
import googleStaticMapsTile from "google-static-maps-tile";
|
||||||
|
import log from "loglevel";
|
||||||
|
|
||||||
export class Gmap {
|
export class Gmap {
|
||||||
private readonly scene: Scene;
|
private readonly scene: Scene;
|
||||||
@ -9,6 +10,7 @@ export class Gmap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async createMapTiles(lat, lon) {
|
public async createMapTiles(lat, lon) {
|
||||||
|
log.debug('createMapTiles', lat, lon)
|
||||||
googleStaticMapsTile({
|
googleStaticMapsTile({
|
||||||
areaSize: '2560x2560',
|
areaSize: '2560x2560',
|
||||||
center: '26.443397,-82.111512',
|
center: '26.443397,-82.111512',
|
||||||
@ -19,10 +21,7 @@ export class Gmap {
|
|||||||
maptype: 'satellite'
|
maptype: 'satellite'
|
||||||
})
|
})
|
||||||
.on('progress', function (info) {
|
.on('progress', function (info) {
|
||||||
//console.log(info.count);
|
|
||||||
//console.log(info.total);
|
|
||||||
const image = info.image;
|
const image = info.image;
|
||||||
|
|
||||||
image.style.position = 'absolute';
|
image.style.position = 'absolute';
|
||||||
image.style.left = info.data.x + 'px';
|
image.style.left = info.data.x + 'px';
|
||||||
image.style.top = info.data.y + 'px';
|
image.style.top = info.data.y + 'px';
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import {PlanePanel, TouchHolographicMenu} from "@babylonjs/gui";
|
import {PlanePanel} from "@babylonjs/gui";
|
||||||
|
|
||||||
export class MyMenu extends PlanePanel {
|
export class MyMenu extends PlanePanel {
|
||||||
public arrangeChildren: boolean = true;
|
public arrangeChildren: boolean = true;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user