diff --git a/src/controllers/right.ts b/src/controllers/right.ts index 2a188e2..72d263e 100644 --- a/src/controllers/right.ts +++ b/src/controllers/right.ts @@ -3,12 +3,16 @@ import {Scene, Vector3, WebXRControllerComponent, WebXRDefaultExperience, WebXRI import {ControllerEventType, Controllers} from "./controllers"; import log from "loglevel"; import {DiagramManager} from "../diagram/diagramManager"; +import {DiagramListingMenu} from "../menus/diagramListingMenu"; export class Right extends Base { + private listingMenu: DiagramListingMenu; + constructor(controller: WebXRInputSource, scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager, controllers: Controllers, ) { super(controller, scene, xr, controllers, diagramManager); + this.listingMenu = new DiagramListingMenu(this.scene, xr, this.controllers); this.controller.onMotionControllerInitObservable.add((init) => { this.initTrigger(init.components['xr-standard-trigger']); this.initBButton(init.components['b-button']); diff --git a/src/diagram/diagramConnection.ts b/src/diagram/diagramConnection.ts index 8a74226..8fb0a4b 100644 --- a/src/diagram/diagramConnection.ts +++ b/src/diagram/diagramConnection.ts @@ -85,13 +85,16 @@ export class DiagramConnection { public get id(): string { return "connection_" + this?.fromAnchor?.id + "_" + this?.toAnchor?.id; } - + private tick: number = 0; private recalculate() { + + if (this.fromAnchor && this.toAnchor) { this.points = [this.fromAnchor.absolutePosition, this.toAnchor.absolutePosition]; } else { this.points = [Vector3.Zero(), Vector3.Zero()]; } + } private setPoints() { @@ -132,8 +135,11 @@ export class DiagramConnection { } private beforeRender = () => { - this.recalculate(); - this.setPoints(); + this.tick++; + if (this.tick % 10 == 0) { + this.recalculate(); + this.setPoints(); + } } private removeConnection = () => { this.logger.debug("removeConnection"); diff --git a/src/diagram/diagramEntity.ts b/src/diagram/diagramEntity.ts index 194aa38..94b5f7f 100644 --- a/src/diagram/diagramEntity.ts +++ b/src/diagram/diagramEntity.ts @@ -9,7 +9,12 @@ export enum DiagramEventType { DROPPED, CLEAR, CHANGECOLOR, - COPY + SYNC +} + +export enum DiagramEventMask { + LOCAL = 1, + REMOTE = 2, } @@ -35,6 +40,4 @@ export type DiagramEntity = { scale?: { x: number, y: number, z: number }; parent?: string; diagramlistingid?: string; -} - - +} \ No newline at end of file diff --git a/src/diagram/textLabel.ts b/src/diagram/textLabel.ts index 91cd668..1ea7ab6 100644 --- a/src/diagram/textLabel.ts +++ b/src/diagram/textLabel.ts @@ -1,4 +1,4 @@ -import {AbstractMesh, DynamicTexture, Mesh, MeshBuilder, StandardMaterial} from "@babylonjs/core"; +import {AbstractMesh, Color3, DynamicTexture, Mesh, MeshBuilder, StandardMaterial} from "@babylonjs/core"; import log from "loglevel"; export class TextLabel { @@ -44,10 +44,11 @@ export class TextLabel { }, mesh.getScene(), false); const mat = new StandardMaterial("mat", mesh.getScene()); mat.diffuseTexture = dynamicTexture; + mat.emissiveColor = Color3.White(); 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()); + const plane = MeshBuilder.CreatePlane("text" + text, {width: planeWidth, height: height}, mesh.getScene()); plane.material = mat; plane.billboardMode = Mesh.BILLBOARDMODE_ALL; diff --git a/src/menus/abstractMenu.ts b/src/menus/abstractMenu.ts index a851e9b..883ba37 100644 --- a/src/menus/abstractMenu.ts +++ b/src/menus/abstractMenu.ts @@ -1,7 +1,9 @@ -import {Scene, WebXRDefaultExperience} from "@babylonjs/core"; +import {Scene, TransformNode, WebXRDefaultExperience} from "@babylonjs/core"; import {Controllers} from "../controllers/controllers"; +import {MenuHandle} from "./menuHandle"; export class AbstractMenu { + protected handle: MenuHandle; protected scene: Scene; protected xr: WebXRDefaultExperience; protected controllers: Controllers; @@ -12,6 +14,10 @@ export class AbstractMenu { this.controllers = controllers; } + protected createHandle(mesh: TransformNode) { + this.handle = new MenuHandle(mesh); + } + public toggle() { throw new Error("AbstractMenu.toggle() not implemented"); } diff --git a/src/menus/configMenu.ts b/src/menus/configMenu.ts index 195d5e6..b651b9d 100644 --- a/src/menus/configMenu.ts +++ b/src/menus/configMenu.ts @@ -5,7 +5,6 @@ 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; @@ -42,7 +41,7 @@ export class ConfigMenu extends AbstractMenu { } - private handle: MenuHandle; + public toggle() { if (this.handle) { @@ -58,7 +57,7 @@ export class ConfigMenu extends AbstractMenu { width: .6, height: .3 }, this.scene); - this.handle = new MenuHandle(configPlane); + this.createHandle(configPlane); const configTexture = AdvancedDynamicTexture.CreateForMesh(configPlane, 2048, 1024); configTexture.background = "white"; diff --git a/src/menus/diagramListingMenu.ts b/src/menus/diagramListingMenu.ts new file mode 100644 index 0000000..c5da741 --- /dev/null +++ b/src/menus/diagramListingMenu.ts @@ -0,0 +1,66 @@ +import {MeshBuilder, Scene, Vector3, WebXRDefaultExperience} from "@babylonjs/core"; +import {AbstractMenu} from "./abstractMenu"; +import {ControllerEventType, Controllers} from "../controllers/controllers"; +import {AdvancedDynamicTexture, Button, Control, ScrollViewer, StackPanel, TextBlock} from "@babylonjs/gui"; +import {setMenuPosition} from "../util/functions/setMenuPosition"; + +export class DiagramListingMenu extends AbstractMenu { + constructor(scene: Scene, xr: WebXRDefaultExperience, controllers: Controllers) { + super(scene, xr, controllers); + this.buildMenu(); + this.controllers.controllerObserver.add((event) => { + if (event.type == ControllerEventType.B_BUTTON) { + this.toggle(); + } + }); + } + + public toggle() { + setMenuPosition(this.handle.mesh, this.scene, new Vector3(0, .4, 0)); + } + + private buildMenu() { + const configPlane = MeshBuilder + .CreatePlane("gridSizePlane", + { + width: 1, + height: .5 + }, this.scene); + const configTexture = AdvancedDynamicTexture.CreateForMesh(configPlane, 2048, 1024); + + configTexture.background = "white"; + const scrollViewer = new ScrollViewer('diagramListingScroll'); + configTexture.addControl(scrollViewer); + const stackpanel = new StackPanel('diagramListingStack'); + scrollViewer.addControl(stackpanel); + for (let i = 0; i < 100; i++) { + const row = new StackPanel('diagramListingRow ' + i); + row.isVertical = false; + row.height = "68px"; + row.width = 1; + stackpanel.addControl(row); + const selectButton = Button.CreateSimpleButton('diagramListingText ' + i, 'Select'); + selectButton.height = "64px"; + selectButton.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT; + selectButton.width = "220px"; + selectButton.color = "white"; + selectButton.fontSize = "48px"; + selectButton.background = "#333333"; + selectButton.onPointerClickObservable.add(() => { + + }); + const textBlock = new TextBlock('diagramListingText ' + i, 'Diagram ' + i); + textBlock.width = "1000px"; + textBlock.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT; + textBlock.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT; + textBlock.fontSize = "48px"; + row.addControl(selectButton); + row.addControl(textBlock); + + } + this.createHandle(configPlane); + configPlane.position.y = .5; + setMenuPosition(this.handle.mesh, this.scene, new Vector3(0, .4, 0)); + + } +} \ No newline at end of file diff --git a/src/menus/editMenu.ts b/src/menus/editMenu.ts index 4be5c16..f9923cd 100644 --- a/src/menus/editMenu.ts +++ b/src/menus/editMenu.ts @@ -42,13 +42,6 @@ export class EditMenu extends AbstractMenu { return this.panel.isVisible; } - private set isVisible(visible: boolean) { - this.panel.isVisible = visible; - this.panel.children.forEach((child) => { - child.isVisible = visible; - }); - } - constructor(scene: Scene, xr: WebXRDefaultExperience, diagramManager: DiagramManager, controllers: Controllers) { super(scene, xr, controllers); this.scene = scene; @@ -63,6 +56,7 @@ export class EditMenu extends AbstractMenu { this.gizmoManager.usePointerToAttachGizmos = false; this.manager = new GUI3DManager(this.scene); const panel = new PlanePanel(); + panel.columns = 4; this.manager.addControl(panel); this.buttonMaterial = new StandardMaterial("buttonMaterial", this.scene); @@ -103,7 +97,18 @@ export class EditMenu extends AbstractMenu { } }); this.panel = panel; + this.createHandle(this.manager.rootContainer.children[0].node); + this.manager.rootContainer.children[0].node.position.y = .2; this.isVisible = false; + + } + + private set isVisible(visible: boolean) { + this.panel.isVisible = visible; + this.panel.children.forEach((child) => { + child.isVisible = visible; + }); + this.handle.mesh.isVisible = visible; } private getTool(template: string, color: Color3): Mesh { const baseMeshId = 'tool-' + template + '-' + color.toHexString(); @@ -129,7 +134,7 @@ export class EditMenu extends AbstractMenu { } else { this.sounds.enter.play(); - setMenuPosition(this.manager.rootContainer.children[0].node, this.scene, new Vector3(0, .4, 0)); + setMenuPosition(this.handle.mesh, this.scene, new Vector3(0, .4, 0)); this.isVisible = true; } }