diff --git a/index.html b/index.html index 140e0e480..30a3c6ba0 100644 --- a/index.html +++ b/index.html @@ -46,6 +46,7 @@ renderer="colorManagement: true; physicallyCorrectLights: true;" inspector="url: //3dstreet.app/dist/3dstreet-editor.js" notify + metadata > @@ -74,6 +75,10 @@ diff --git a/src/components/notify.js b/src/components/notify.js index d6221f4c2..3acdc589d 100644 --- a/src/components/notify.js +++ b/src/components/notify.js @@ -3,7 +3,7 @@ var { Notyf } = require('../lib/notyf.min.js'); AFRAME.registerComponent('notify', { schema: { - duration: { type: 'number', default: 2000 }, + duration: { type: 'number', default: 6000 }, ripple: { type: 'boolean', default: true }, position: { type: 'string', diff --git a/src/index.js b/src/index.js index 9d71b3110..d843b420b 100644 --- a/src/index.js +++ b/src/index.js @@ -87,7 +87,15 @@ AFRAME.registerComponent('streetmix-loader', { const streetmixResponseObject = JSON.parse(this.response); const streetmixSegments = streetmixResponseObject.data.street.segments; const streetmixName = streetmixResponseObject.name; + console.log('streetmixName', streetmixName) el.setAttribute('streetmix-loader', 'name', streetmixName); + + let currentSceneTitle = AFRAME.scenes[0].getAttribute('metadata').sceneTitle; + if (!currentSceneTitle) { // only set title from streetmix if none exists + AFRAME.scenes[0].setAttribute('metadata', 'sceneTitle', streetmixName); + console.log('therefore setting metadata sceneTitle as streetmixName', streetmixName) + } + if (data.showBuildings) { el.setAttribute('street', 'right', streetmixResponseObject.data.street.rightBuildingVariant); el.setAttribute('street', 'left', streetmixResponseObject.data.street.leftBuildingVariant); diff --git a/src/json-utils.js b/src/json-utils.js index 76b6c53fa..943a9600f 100644 --- a/src/json-utils.js +++ b/src/json-utils.js @@ -368,3 +368,150 @@ function createEntityFromObj (entityData, parentEl) { } } } + +/* + Code imported from index.html, mix of save load utils and some ui functions +*/ + + +AFRAME.registerComponent('metadata', { + schema: { + sceneTitle: {default: ''}, + sceneId: {default: ''} + }, + init: function() { + } +}) + +AFRAME.registerComponent('set-loader-from-hash', { + dependencies: ['streetmix-loader'], + schema: { + defaultURL: { type: 'string' } + }, + init: function () { + // get hash from window + const streetURL = window.location.hash.substring(1); + if (!streetURL) { + return; + } + if (streetURL.includes('//streetmix.net')) { + console.log('[set-loader-from-hash]','Set streetmix-loader streetmixStreetURL to', streetURL) + this.el.setAttribute('streetmix-loader', 'streetmixStreetURL', streetURL); + } else { + // try to load JSON file from remote resource + console.log('[set-loader-from-hash]','Load 3DStreet scene with fetchJSON from', streetURL) + this.fetchJSON(streetURL); + } + // else { + // console.log('[set-loader-from-hash]','Using default URL', this.data.defaultURL) + // this.el.setAttribute('streetmix-loader', 'streetmixStreetURL', this.data.defaultURL); + // } + }, + fetchJSON: function (requestURL) { + let sceneId = getUUIDFromPath(requestURL); + if (sceneId) { + console.log('sceneId from fetchJSON from url hash loader', sceneId); + AFRAME.scenes[0].setAttribute('metadata', 'sceneId', sceneId); + } + const request = new XMLHttpRequest(); + request.open('GET', requestURL, true); + request.onload = function () { + if (this.status >= 200 && this.status < 400) { + // Connection success + // remove 'set-loader-from-hash' component from json data + const jsonData = JSON.parse(this.response, + (key, value) => (key === 'set-loader-from-hash') ? undefined : value ); + + console.log('[set-loader-from-hash]', '200 response received and JSON parsed, now createElementsFromJSON'); + createElementsFromJSON(jsonData); + let sceneId = getUUIDFromPath(requestURL); + if (sceneId) { + console.log('sceneId from fetchJSON from url hash loader', sceneId); + AFRAME.scenes[0].setAttribute('metadata', 'sceneId', sceneId); + } + } + }; + request.onerror = function () { + // There was a connection error of some sort + console.log('Loading Error: There was a connection error during JSON loading'); + }; + request.send(); + } +}); + +function getUUIDFromPath(path) { + // UUID regex pattern: [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} + const uuidPattern = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/; + + const match = path.match(uuidPattern); + if (match) { + return match[0]; + } + + return null; // return null or whatever default value you prefer if no UUID found +} + +// this use os text input prompt, delete current scene, then load streetmix file +function inputStreetmix() { + streetmixURL = prompt("Please enter a Streetmix URL", "https://streetmix.net/kfarr/3/example-street"); + setTimeout(function() { window.location.hash = streetmixURL; }); + streetContainerEl = document.getElementById('street-container'); + while (streetContainerEl.firstChild) { + streetContainerEl.removeChild(streetContainerEl.lastChild); + } + AFRAME.scenes[0].setAttribute('metadata', 'sceneId', ''); + AFRAME.scenes[0].setAttribute('metadata', 'sceneTitle', ''); + streetContainerEl.innerHTML = ''; +} + +// JSON loading starts here +function getValidJSON(stringJSON) { + // Preserve newlines, etc. - use valid JSON + // Remove non-printable and other non-valid JSON characters + return stringJSON.replace(/\'/g, "") + .replace(/\n/g, "") + .replace(/[\u0000-\u0019]+/g,""); +} + +function createElementsFromJSON(streetJSON) { + let streetObject = {}; + if (typeof streetJSON == 'string') { + const validJSONString = getValidJSON(streetJSON); + streetObject = JSON.parse(validJSONString); + } else if (typeof streetJSON == 'object') { + streetObject = streetJSON; + } + + let sceneTitle = streetObject.title; + if (sceneTitle) { + console.log('sceneTitle from createElementsFromJSON', sceneTitle); + AFRAME.scenes[0].setAttribute('metadata', 'sceneTitle', sceneTitle); + } + + streetContainerEl = document.getElementById('street-container'); + while (streetContainerEl.firstChild) { + streetContainerEl.removeChild(streetContainerEl.lastChild); + } + + createEntities(streetObject.data, streetContainerEl); + AFRAME.scenes[0].components['notify'].message('Scene loaded from JSON', 'success') +} + +// viewer widget click to paste json string of 3dstreet scene +function inputJSON() { + const stringJSON = prompt("Please paste 3DStreet JSON string"); + if (stringJSON) { + createElementsFromJSON(stringJSON); + } +} + +// handle viewer widget click to open 3dstreet json scene +function fileJSON() { + let reader=new FileReader(); + reader.onload=function(){ + AFRAME.scenes[0].setAttribute('metadata', 'sceneId', ''); + AFRAME.scenes[0].setAttribute('metadata', 'sceneTitle', ''); + createElementsFromJSON(reader.result); + } + reader.readAsText(this.files[0]); +} diff --git a/src/viewer-styles.css b/src/viewer-styles.css index 754ad4ce3..0418d02d9 100644 --- a/src/viewer-styles.css +++ b/src/viewer-styles.css @@ -18,6 +18,14 @@ body { margin: 0; } +/* notification hack */ +.notyf__message { font-size: 20px !important; } + +/* notification width hack */ +.notyf__toast { + max-width: 66.66vw !important; /* 2/3rds of viewport width */ + width: auto !important; /* Resetting any specific width, if set */ +} /********* viewer header css *********/