UNPKG

@vrspace/babylonjs

Version:

vrspace.org babylonjs client

238 lines (205 loc) 7.76 kB
import { ImageArea } from "../widget/image-area.js"; import { ColorPickerPanel } from '../widget/colorpicker-panel.js'; import { VerticalSliderPlane } from '../widget/slider-panel.js'; import { WorldManager } from "../../core/world-manager.js"; import { VRSPACE } from '../../client/vrspace.js'; import { VRSPACEUI } from '../vrspace-ui.js'; export class Whiteboard extends ImageArea { constructor(scene, name = "Whiteboard-root") { super(scene, name); this.backgroundColor = new BABYLON.Color3(1, 1, 1); this.foregroundColor = new BABYLON.Color3(0, 0, 0); this.lineWidth = 1; this.share = null; this.closeCallback = null; this.selectionPredicate = (mesh) => this.isSelectableMesh(mesh); this.billboardMode = BABYLON.Mesh.BILLBOARDMODE_Y; } show() { super.show(); this.areaPlane.isNearPickable = VRSPACEUI.allowHands; this.ui(); this.texturesDispose(); //new DynamicTexture(name, options, scene?, generateMipMaps?, samplingMode?, format?, invertY?) this.texture = new BABYLON.DynamicTexture( "Whiteboard", { width: this.width, height: this.height }, this.scene, false, BABYLON.Texture.TRILINEAR_SAMPLINGMODE, BABYLON.Engine.TEXTUREFORMAT_RGBA, false ); this.material.diffuseTexture = this.texture; this.fullyVisible(); this.canvas = this.texture.getContext(); this.canvas.fillStyle = this.backgroundColor.toHexString(); this.canvas.fillRect(0, 0, this.width - 1, this.height - 1); this.texture.update(); } ui() { this.buttonClose = new BABYLON.GUI.HolographicButton("close"); this.buttonClose.imageUrl = VRSPACEUI.contentBase + "/content/icons/close.png"; VRSPACEUI.guiManager.addControl(this.buttonClose); this.buttonClose.mesh.isNearPickable = VRSPACEUI.allowHands; this.buttonClose.backMaterial.alpha = this.handles.material.alpha; this.buttonClose.linkToTransformNode(this.handles.box); this.buttonClose.position = new BABYLON.Vector3(5, 0, 0); this.buttonClose.scaling = new BABYLON.Vector3(2, 2, 2); this.buttonClose.text = "Close"; this.buttonClose.onPointerDownObservable.add(() => this.close()); this.buttonUndo = new BABYLON.GUI.HolographicButton("undo"); this.buttonUndo.imageUrl = VRSPACEUI.contentBase + "/content/icons/undo.png"; VRSPACEUI.guiManager.addControl(this.buttonUndo); this.buttonUndo.mesh.isNearPickable = VRSPACEUI.allowHands; this.buttonUndo.backMaterial.alpha = this.handles.material.alpha; this.buttonUndo.linkToTransformNode(this.handles.box); this.buttonUndo.position = new BABYLON.Vector3(10, 0, 0); this.buttonUndo.scaling = new BABYLON.Vector3(2, 2, 2); this.buttonUndo.text = "Undo"; this.buttonUndo.onPointerDownObservable.add(() => { this.undo(); this.sendEvent({ undo: {} }); }); this.widthPanel = new VerticalSliderPlane(3, "Width", 1, 20, 1); this.widthPanel.plane.parent = this.handles.box; this.widthPanel.plane.position = new BABYLON.Vector3(43, 0, 0); this.widthPanel.slider.onValueChangedObservable.add(value => { this.setLineWidth(value); this.sendEvent({ setLineWidth: value }); }); this.foregroundSelector = new ColorPickerPanel(4, "Foreground", this.foregroundColor); this.foregroundSelector.plane.parent = this.handles.box; this.foregroundSelector.plane.position = new BABYLON.Vector3(46, 0, 0); this.foregroundSelector.picker.onValueChangedObservable.add(val => { this.changeForeground(val); this.sendEvent({ foreground: { r: val.r, g: val.g, b: val.b } }); }); this.backgroundSelector = new ColorPickerPanel(4, "Background", this.backgroundColor); this.backgroundSelector.plane.parent = this.handles.box; this.backgroundSelector.plane.position = new BABYLON.Vector3(50, 0, 0); this.backgroundSelector.picker.onValueChangedObservable.add(color => { this.changeBackground(color); this.sendEvent({ background: { r: color.r, g: color.g, b: color.b } }); }); } setLineWidth(value) { this.lineWidth = value; this.canvas.lineWidth = value; } foreground(r,g,b) { this.changeForeground( new BABYLON.Color3(r,g,b) ); } changeForeground(color) { this.foregroundColor = color; this.canvas.strokeStyle = this.foregroundColor.toHexString(); } background(r,g,b) { this.changeBackground( new BABYLON.Color3(r,g,b) ); } changeBackground(color) { this.imageData = this.canvas.getImageData(0, 0, this.width, this.height); this.backgroundColor = color; this.canvas.fillStyle = this.backgroundColor.toHexString(); this.canvas.fillRect(0, 0, this.width - 1, this.height - 1); this.texture.update(); } clickAt(x,y) { super.click(x, y); this.canvas.save(); this.imageData = this.canvas.getImageData(0, 0, this.width, this.height); this.canvas.beginPath(); this.canvas.moveTo(x, y); this.scene.activeCamera.detachControl(); } click(x, y) { this.clickAt(x,y); this.sendEvent({ clickAt: { x: x, y: y } }); } dragTo(x,y) { this.canvas.lineTo(x, y); this.canvas.stroke(); this.texture.update(); } pointerDrag(x, y) { this.dragTo(x,y); this.sendEvent({ dragTo: { x: x, y: y } }); } dragEnd() { this.scene.activeCamera.attachControl(); } pointerUp() { this.dragEnd(); this.sendEvent({ dragEnd: {} }); } undo() { this.canvas.restore(); if (this.imageData) { this.canvas.putImageData(this.imageData, 0, 0); this.texture.update(); this.imageData = null; } } dispose() { this.deleteSharedObject(); this.buttonClose.dispose(); this.buttonUndo.dispose(); this.widthPanel.dispose(); this.foregroundSelector.dispose(); this.backgroundSelector.dispose(); super.dispose(); } async startSharing() { if (!WorldManager.instance) { console.log("Can't share whiteboard - WorldManager offline"); return; } VRSPACE.createSharedObject({ properties: { name: this.name, type: "Whiteboard", clientId: VRSPACE.me.id, size: this.size, addHandles: this.addHandles }, active: true, script: '/babylon/js/scripts/remote-whiteboard.js', position: { x: this.position.x, y: this.position.y, z: this.position.z } //rotation: {x: this.rotation.x, y: this.rotation.y, z: this.rotation.z} }).then( obj => { this.share = obj; console.log("Created new VRObject", obj); }); } deleteSharedObject() { if (this.share) { VRSPACE.deleteSharedObject(this.share); this.share = null; } } sendEvent(event) { if (!this.share) { this.startSharing(); } if (this.share) { event['clientId'] = VRSPACE.me.id; //console.log("Sending ", event); VRSPACE.sendEvent(this.share, event); } } close() { this.deleteSharedObject() this.dispose(); if ( this.closeCallback ) { this.closeCallback(); } } isSelectableMesh(mesh) { return this.areaPlane == mesh; } /** * WorldListener interface. Upon receiving own notification, adds itself to the VRObject. * This prevents creation of another whiteboard instance when VRObject loads. */ loaded(vrobject){ if ( vrobject.properties && vrobject.properties.name == this.name ) { console.log("Shared object added to the scene", vrobject); this.share = vrobject; vrobject.attachedScript.whiteboard = this; } } }