UNPKG

@vrspace/babylonjs

Version:

vrspace.org babylonjs client

182 lines (168 loc) 7.48 kB
import { VRSPACEUI } from '../vrspace-ui.js'; import { World } from '../../world/world.js'; import { TextureSelector } from './texture-selector.js'; export class TerrainEditor { /** * @param {World} world */ constructor(world) { this.world = world; this.scene = world.scene; this.terrain = world.terrain; this.heightIncrement = 1; this.editing = false; this.textureSelector = new TextureSelector(this.scene, (img) => this.publishTexture(img)); // add own selection predicate to the world this.selectionPredicate = (mesh) => this.isSelectableMesh(mesh); world.addSelectionPredicate(this.selectionPredicate); this.observer = null; this.groundPickable = null; this.movementMode = null; } createSharedTerrain() { if (!World.lastInstance.sharedTerrain) { var object = { permanent: true, active: true, specularColor: this.terrain.terrainMaterial.specularColor, diffuseColor: this.terrain.terrainMaterial.diffuseColor, emissiveColor: this.terrain.terrainMaterial.emissiveColor }; this.world.worldManager.VRSPACE.createSharedObject(object, "Terrain").then(obj => { console.log("Created new Terrain", obj); World.lastInstance.sharedTerrain = obj; }); } } edit() { this.createSharedTerrain(); if (!this.observer) { this.observer = this.scene.onPointerObservable.add((pointerInfo) => { switch (pointerInfo.type) { case BABYLON.PointerEventTypes.POINTERDOWN: if (pointerInfo.pickInfo.hit && pointerInfo.pickInfo.pickedMesh == this.terrain.mesh()) { this.lastIndex = this.updatePicked(pointerInfo.pickInfo); this.terrain.mesh().enablePointerMoveEvents = true; } break; case BABYLON.PointerEventTypes.POINTERUP: this.lastIndex = -1; this.terrain.mesh().enablePointerMoveEvents = false; break; case BABYLON.PointerEventTypes.POINTERMOVE: if (this.lastIndex >= 0 && pointerInfo.pickInfo.pickedMesh == this.terrain.mesh()) { var newIndex = this.terrain.findIndex(pointerInfo.pickInfo.pickedPoint.x, pointerInfo.pickInfo.pickedPoint.z); if (newIndex != this.lastIndex) { this.lastIndex = newIndex; this.updatePicked(pointerInfo.pickInfo); } } break; } }); } if (World.lastInstance.ground) { this.groundPickable = World.lastInstance.ground.isPickable; World.lastInstance.ground.isPickable = false; } this.raiseButton = VRSPACEUI.hud.addButton("Raise", VRSPACEUI.contentBase + "/content/icons/upload.png"); this.digButton = VRSPACEUI.hud.addButton("Dig", VRSPACEUI.contentBase + "/content/icons/download.png"); this.textureButton = VRSPACEUI.hud.addButton("Texture", VRSPACEUI.contentBase + "/content/icons/terrain-texture.png"); this.raiseSlider = VRSPACEUI.hud.addSlider("Height", 0, 2, this.heightIncrement) this.raiseButton.onPointerDownObservable.add(() => { this.direction = 1; VRSPACEUI.hud.showButtons(this.editing, this.raiseButton, this.raiseSlider); this.world.enableFloorSelection(this.editing); this.enableMovement(this.editing); this.editing = !this.editing; this.terrain.terrainMaterial.wireframe = this.editing; }); this.digButton.onPointerDownObservable.add(() => { this.direction = -1; VRSPACEUI.hud.showButtons(this.editing, this.digButton, this.raiseSlider); this.world.enableFloorSelection(this.editing); this.enableMovement(this.editing); this.editing = !this.editing; this.terrain.terrainMaterial.wireframe = this.editing; }); this.textureButton.onPointerDownObservable.add(() => { this.editing = !this.editing; if (this.editing) { this.textureSelector.show(); } else { this.textureSelector.hide(); } VRSPACEUI.hud.showButtons(!this.editing, this.textureButton); }); this.raiseSlider.onValueChangedObservable.add(value => { this.heightIncrement = value }); this.diffusePicker = VRSPACEUI.hud.addColorPicker("Diffuse", this.terrain.terrainMaterial.diffuseColor); this.specularPicker = VRSPACEUI.hud.addColorPicker("Specular", this.terrain.terrainMaterial.specularColor); this.emissivePicker = VRSPACEUI.hud.addColorPicker("Emissive", this.terrain.terrainMaterial.emissiveColor); this.specularPicker.onValueChangedObservable.add((val) => { //this.terrain.terrainMaterial.specularColor.copyFrom(val); this.world.worldManager.VRSPACE.sendEvent(World.lastInstance.sharedTerrain, { specularColor: val }); }); this.diffusePicker.onValueChangedObservable.add((val) => { //this.terrain.terrainMaterial.diffuseColor.copyFrom(val); this.world.worldManager.VRSPACE.sendEvent(World.lastInstance.sharedTerrain, { diffuseColor: val }); }); this.emissivePicker.onValueChangedObservable.add((val) => { //this.terrain.terrainMaterial.emissiveColor.copyFrom(val); this.world.worldManager.VRSPACE.sendEvent(World.lastInstance.sharedTerrain, { emissiveColor: val }); }); VRSPACEUI.hud.enableSpeech(true); } enableMovement(enable) { if (!enable) { this.movementMode = this.world.xrHelper.disableMovement(); } else if (this.movementMode) { this.world.xrHelper.enableMovement(this.movementMode); } } updatePicked(pickInfo) { var index = -1; var x = pickInfo.pickedPoint.x; var z = pickInfo.pickedPoint.z; if (this.editing) { var online = this.world.isOnline() && World.lastInstance.sharedTerrain; if (online) { // if online, terrain is not refreshed until the server responds with updated height index = this.terrain.findIndex(x, z); if (index) { var point = this.terrain.point(index); point.y += this.heightIncrement * this.direction; // publish updates var change = { change: { index: index, point: point } }; this.world.worldManager.VRSPACE.sendEvent(World.lastInstance.sharedTerrain, change); } else { console.log("ERROR: index " + index + " for " + x + "," + z); } } else { index = this.terrain.raise(x, z, this.heightIncrement * this.direction, online); } } return index; } publishTexture(imgUrl) { console.log("Publishing texture: " + imgUrl); this.world.worldManager.VRSPACE.sendEvent(World.lastInstance.sharedTerrain, { diffuseTexture: imgUrl }); } dispose() { this.world.removeSelectionPredicate(this.selectionPredicate); this.world.removeListener(this); this.terrain.terrainMaterial.wireframe = false; this.scene.onPointerObservable.remove(this.observer); this.raiseButton.dispose(); this.digButton.dispose(); this.textureButton.dispose(); this.raiseSlider.dispose(); if (World.lastInstance.ground) { World.lastInstance.ground.isPickable = this.groundPickable; } this.enableMovement(true); } isSelectableMesh(mesh) { // terrain is selectable only while editing return this.editing && this.terrain && mesh == this.terrain.mesh(); } }