UNPKG

@vrspace/babylonjs

Version:

vrspace.org babylonjs client

170 lines (157 loc) 7.13 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; } 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.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.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); } 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; } } isSelectableMesh(mesh) { // terrain is selectable only while editing return this.editing && this.terrain && mesh == this.terrain.mesh(); } }