UNPKG

@vrspace/babylonjs

Version:

vrspace.org babylonjs client

151 lines (143 loc) 5.33 kB
import { VRSPACE } from '../../client/vrspace.js'; import { VRSPACEUI } from '../vrspace-ui.js'; import { World } from '../../world/world.js'; export class WorldPersistence { /** * @param {World} world * @param {HTMLInputElement} [fileInput] */ constructor(world, fileInput) { /** @type {World} */ this.world = world; this.autoCreateFileInput = true; /** @type {HTMLInputElement} */ this.fileInput = null; if (fileInput) { this.setFileInput(fileInput); this.autoCreateFileInput = false; } } /** * Save current scene: dumps everything using AssetLoader.dump(), and calls VRSPACEUI.saveFile(). */ save() { VRSPACEUI.progressStart("saveFile"); let scene = { terrain:null, skybox:null, objects:VRSPACEUI.assetLoader.dump() } if (this.world.sharedSkybox) { scene.skybox = { texture: this.world.sharedSkybox.texture, amibentIntensity: this.world.sharedSkybox.amibentIntensity } } if (this.world.sharedTerrain) { console.log(this.world.sharedTerrain); scene.terrain = { diffuseColor:this.world.sharedTerrain.diffuseColor, diffuseTexture:this.world.sharedTerrain.diffuseTexture, emissiveColor:this.world.sharedTerrain.emissiveColor, specularColor:this.world.sharedTerrain.specularColor, points:this.world.sharedTerrain.points } } if (Object.keys(scene.objects).length > 0) { VRSPACEUI.saveFile(this.world.name + ".json", JSON.stringify(scene)); } VRSPACEUI.progressEnd("saveFile"); } /** * Implements load by adding change listener to file input html element. Called from constructor. * @param fileInput html file input element */ setFileInput(fileInput) { this.fileInput = fileInput; fileInput.addEventListener('change', () => { const selectedFile = fileInput.files[0]; if (selectedFile) { VRSPACEUI.progressStart("loadFile"); console.log("Loading from ", selectedFile); const reader = new FileReader(); reader.onload = async e => { const scene = JSON.parse(e.target.result); console.log("Loaded scene", scene); try { await this.publish(scene); } catch (exception) { console.error("Failed to publish scene", exception); } VRSPACEUI.progressEnd("loadFile"); } reader.readAsText(selectedFile); } }, false); } /** * Create a hidden file input. */ createFileInput() { const input = document.createElement('input'); input.type = 'file'; input.id = 'VRSpace-fileInput'; input.style = 'display:none'; input.accept = '.json'; this.setFileInput(input); } /** * Load saved scene, requires file input html element */ load() { if (!this.fileInput && this.autoCreateFileInput) { console.log("WARNING no file input element, creating one"); this.createFileInput(); } this.fileInput.click(); } /** * Publish all loaded object to the server * @param scene scene object, containing world objects, terrain, skybox */ async publish(scene) { for (let url in scene.objects) { let instances = scene.objects[url].instances; if (!url.startsWith("/")) { // relative url, make it relative to world script path url = this.baseUrl + url; } instances.forEach(async instance => { let mesh = { mesh: url, active: true, position: instance.position, rotation: instance.rotation, scale: instance.scale }; let obj = await VRSPACE.createSharedObject(mesh); console.log("Created new VRObject", obj); }); } if (scene.skybox) { // CHECKME: this hangs, why? //this.world.skyBox.setTexture(scene.skybox.texture); await this.world.createSharedSkybox(); this.world.worldManager.VRSPACE.sendEvent(this.world.sharedSkybox, { texture: scene.skybox.texture }); } if (scene.terrain) { if ( !this.world.terrain ) { this.world.terrain = new Terrain(this.world); this.world.terrain.terrainMaterial = new BABYLON.StandardMaterial("terrainMaterial", this.world.scene); this.world.terrain.init(this.world.scene); } this.world.terrain.material().specularColor = new BABYLON.Color3(scene.terrain.specularColor.r, scene.terrain.specularColor.g, scene.terrain.specularColor.b); this.world.terrain.material().diffuseColor = new BABYLON.Color3(scene.terrain.diffuseColor.r, scene.terrain.diffuseColor.g, scene.terrain.diffuseColor.b); this.world.terrain.material().emissiveColor = new BABYLON.Color3(scene.terrain.emissiveColor.r, scene.terrain.emissiveColor.g, scene.terrain.emissiveColor.b); this.world.terrain.setTexture(scene.terrain.diffuseTexture); await this.world.createSharedTerrain(); this.terrain?.points?.forEach(point=>{ this.worldManager.VRSPACE.sendEvent(World.lastInstance.sharedTerrain, { change: { index: point.index, point: {x:point.x, y:point.y, z:point.z} } }); }); } } }