UNPKG

@vrspace/babylonjs

Version:

vrspace.org babylonjs client

216 lines (205 loc) 8.91 kB
import {VRSPACEUI} from '../vrspace-ui.js'; import {WorldListener} from '../../world/world-listener.js'; import {World} from '../../world/world.js'; import {TextureSelector} from './texture-selector.js'; export class TerrainEditor extends WorldListener { /** * @param {World} world */ constructor(world) { super(); this.world = world; this.scene = world.scene; this.terrain = world.terrain; this.heightIncrement=1; this.sharedTerrain = null; this.editing = false; world.addListener(this); 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); } /** Called by WorldManager when user enters the world */ entered(welcome) { //console.log(welcome); if ( welcome.permanents ) { welcome.permanents.forEach( obj => { if (obj.Terrain) { this.sharedTerrain = obj.Terrain; if ( obj.Terrain.points ) { obj.Terrain.points.forEach( p => { this.terrain.update(p.index, p.x, p.y, p.z); }); this.terrain.refresh(); } if ( obj.Terrain.specularColor ) { this.terrain.terrainMaterial.specularColor = new BABYLON.Color3(obj.Terrain.specularColor.r, obj.Terrain.specularColor.g, obj.Terrain.specularColor.b) } if ( obj.Terrain.diffuseColor ) { this.terrain.terrainMaterial.diffuseColor = new BABYLON.Color3(obj.Terrain.diffuseColor.r, obj.Terrain.diffuseColor.g, obj.Terrain.diffuseColor.b) } if ( obj.Terrain.emissiveColor ) { this.terrain.terrainMaterial.emissiveColor = new BABYLON.Color3(obj.Terrain.emissiveColor.r, obj.Terrain.emissiveColor.g, obj.Terrain.emissiveColor.b) } if ( obj.Terrain.diffuseTexture ) { this.setTexture(obj.Terrain.diffuseTexture); } }; }); } } added(added) { if ( added && added.className == "Terrain") { console.log("Terrain added", added); this.sharedTerrain = added; added.addListener((obj,change)=>this.terrainChanged(change)); this.terrain.mesh().setEnabled(true); } } terrainChanged(e) { console.log("Terrain changed", e); if ( e.change ) { this.terrain.update(e.change.index, e.change.point.x, e.change.point.y, e.change.point.z); this.terrain.refresh(); } else { for ( const field in e ) { if ( field.indexOf('Color') > 0 ) { // e.g. emissiveColor, diffuseColor, specularColor console.log(field + "="+e[field]); this.terrain.terrainMaterial[field] = new BABYLON.Color3(e[field].r, e[field].g, e[field].b); } else if (field.indexOf('Texture') > 0) { this.setTexture(e[field]); } } } } createSharedTerrain() { if ( ! this.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); this.sharedTerrain = obj; }); } } edit() { this.createSharedTerrain(); 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; } }); 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.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.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); }); 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(this.sharedTerrain, {specularColor:val}); }); this.diffusePicker.onValueChangedObservable.add( (val) => { //this.terrain.terrainMaterial.diffuseColor.copyFrom(val); this.world.worldManager.VRSPACE.sendEvent(this.sharedTerrain, {diffuseColor:val}); }); this.emissivePicker.onValueChangedObservable.add( (val) => { //this.terrain.terrainMaterial.emissiveColor.copyFrom(val); this.world.worldManager.VRSPACE.sendEvent(this.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() && this.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(this.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(this.sharedTerrain, {diffuseTexture:imgUrl}); } setTexture(imgUrl) { console.log("New texture: "+imgUrl); if ( this.terrainTexture ) { this.terrainTexture.dispose(); } this.terrainTexture = new BABYLON.Texture(imgUrl, this.scene); this.terrain.mesh().material.diffuseTexture = this.terrainTexture; } dispose() { this.world.removeSelectionPredicate(this.selectionPredicate); this.world.removeListener(this); // ..etc, CHECKME } isSelectableMesh(mesh) { // terrain is selectable only while editing return this.editing && this.terrain && mesh == this.terrain.mesh(); } }