diff --git a/example/aframe/sandbox/index.html b/example/aframe/sandbox/index.html index dffcb21..d189f74 100644 --- a/example/aframe/sandbox/index.html +++ b/example/aframe/sandbox/index.html @@ -20,7 +20,7 @@ renderer="colorManagement: false; stencil: true; antialias:true; highRefreshRate:true; foveationLevel: 0.5; toneMapping: ACESFilmic; exposure: 3.0" device-orientation-permission-ui xrf-gaze-always joystick light="defaultLightsEnabled: false"> - + diff --git a/make b/make index def37ea..ac0feae 100755 --- a/make +++ b/make @@ -73,7 +73,7 @@ build(){ aframe(){ test -d src/3rd/js/aframe/build/aframe || git clone https://github.com/aframevr/aframe src/3rd/js/aframe/build/aframe --depth=1 curdir=$(pwd) - cd src/3rd/js/aframe/build && cp three.module.js aframe/src/lib/. # override to add extra loaders like fbx/collada e.g. + cd src/3rd/js/aframe/build && cp three*.js aframe/src/lib/. # override to add extra loaders like fbx/collada e.g. #cd aframe && npm install && npm install troika-three-text && npm run dist cd aframe && npm install && npm run dist cd "$curdir" diff --git a/src/3rd/js/aframe/build/three.js b/src/3rd/js/aframe/build/three.js new file mode 100644 index 0000000..e42150b --- /dev/null +++ b/src/3rd/js/aframe/build/three.js @@ -0,0 +1,36 @@ +import * as SUPER_THREE from 'super-three'; +import { DRACOLoader } from 'super-three/examples/jsm/loaders/DRACOLoader'; +import { GLTFLoader } from 'super-three/examples/jsm/loaders/GLTFLoader'; +//import { KTX2Loader } from 'super-three/examples/jsm/loaders/KTX2Loader'; +import { OBB } from 'super-three/addons/math/OBB.js'; +import { OBJLoader } from 'super-three/examples/jsm/loaders/OBJLoader'; +import { FBXLoader } from 'super-three/examples/jsm/loaders/FBXLoader'; +import { USDZLoader } from 'super-three/examples/jsm/loaders/USDZLoader'; +import { ColladaLoader } from 'super-three/examples/jsm/loaders/ColladaLoader'; +import { MTLLoader } from 'super-three/examples/jsm/loaders/MTLLoader'; +import * as BufferGeometryUtils from 'super-three/examples/jsm/utils/BufferGeometryUtils'; +import { LightProbeGenerator } from 'super-three/examples/jsm/lights/LightProbeGenerator'; +import { TransformControls } from 'super-three/examples/jsm/controls/TransformControls.js'; +import { GLTFExporter } from 'super-three/examples/jsm/exporters/GLTFExporter.js'; + +var THREE = globalThis.THREE = {...SUPER_THREE}; + +// TODO: Eventually include these only if they are needed by a component. +require('../../vendor/DeviceOrientationControls'); // THREE.DeviceOrientationControls +THREE.DRACOLoader = DRACOLoader; +THREE.GLTFLoader = GLTFLoader; +THREE.KTX2Loader = KTX2Loader; +THREE.OBJLoader = OBJLoader; +THREE.MTLLoader = MTLLoader; +THREE.FBXLoader = FBXLoader; +THREE.USDZLoader = USDZLoader; +THREE.ColladaLoader = ColladaLoader; +THREE.OBB = OBB; +THREE.BufferGeometryUtils = BufferGeometryUtils; +THREE.LightProbeGenerator = LightProbeGenerator; +THREE.TransformControls = TransformControls; +THREE.GLTFExporter = GLTFExporter; + +THREE.Cache.enabled = true; + +export default THREE; diff --git a/src/3rd/js/aframe/build/three.module.js b/src/3rd/js/aframe/build/three.module.js index 5e593a9..177242c 100644 --- a/src/3rd/js/aframe/build/three.module.js +++ b/src/3rd/js/aframe/build/three.module.js @@ -29,7 +29,7 @@ THREE.OBB = OBB; THREE.BufferGeometryUtils = BufferGeometryUtils; THREE.LightProbeGenerator = LightProbeGenerator; THREE.TransformControls = TransformControls; -THREE.GLTFExporter = GLTFExporter; +THREE.GLTFExporter = GLTFExporter || console.error("GLTFExporter not found"); //THREE.Text = Text export default THREE; diff --git a/src/3rd/js/plugin/frontend/$files.js b/src/3rd/js/plugin/frontend/$files.js index f32fc37..96aa734 100644 --- a/src/3rd/js/plugin/frontend/$files.js +++ b/src/3rd/js/plugin/frontend/$files.js @@ -4,19 +4,23 @@ filesComponent = (el) => new Proxy({ html: (data) => `
- +
${data.tabs.map( (t) => @@ -25,11 +29,12 @@ filesComponent = (el) => new Proxy({ ` ).join('') } -

+


- - + +
+
@@ -40,7 +45,7 @@ filesComponent = (el) => new Proxy({ `, tabs: [ - {name: "local files", id: "localFiles"} + {name: "offline", id: "localFiles"} ], show: false, @@ -50,6 +55,10 @@ filesComponent = (el) => new Proxy({ this.show = state !== undefined ? state : !this.show }, + remove(){ + el.parent.remove(el) + }, + init(opts){ this.decorateFileButton() // create HTML element @@ -72,7 +81,7 @@ filesComponent = (el) => new Proxy({ document.querySelector("#load").setAttribute("value","3D file") // decorate fileLoaders window.frontend.fileLoaders = ( (fileLoaders) => { - this.fileLoader = fileLoaders + this.fileLoaders = fileLoaders return () => this.toggle() })( window.frontend.fileLoaders ) }, diff --git a/src/3rd/js/plugin/frontend/css.js b/src/3rd/js/plugin/frontend/css.js index ba6ff6a..5dd51b7 100644 --- a/src/3rd/js/plugin/frontend/css.js +++ b/src/3rd/js/plugin/frontend/css.js @@ -889,6 +889,38 @@ document.head.innerHTML += ` bottom: 3px; } + .gg-globe-alt, + .gg-globe-alt::after, + .gg-globe-alt::before { + display: inline-block; + box-sizing: border-box; + height: 18px; + border: 2px solid; + } + .gg-globe-alt { + position: relative; + transform: scale(var(--ggs, 1)); + width: 18px; + border-radius: 22px; + } + .gg-globe-alt::after, + .gg-globe-alt::before { + content: ""; + position: absolute; + width: 8px; + border-radius: 100%; + top: -2px; + left: 3px; + } + .gg-globe-alt::after { + width: 24px; + height: 20px; + border: 2px solid transparent; + border-bottom: 2px solid; + top: -11px; + left: -5px; + } + ` diff --git a/src/3rd/js/plugin/frontend/frontend.js b/src/3rd/js/plugin/frontend/frontend.js index 038b97d..995d189 100644 --- a/src/3rd/js/plugin/frontend/frontend.js +++ b/src/3rd/js/plugin/frontend/frontend.js @@ -252,23 +252,26 @@ window.frontend = (opts) => new Proxy({ download(){ - function download(dataurl, filename) { - var a = document.createElement("a"); - a.href = URL.createObjectURL( new Blob([dataurl]) ); - a.setAttribute("download", filename); - a.click(); - return false; - } - function exportScene(model,ext,file){ + document.dispatchEvent( new CustomEvent('frontend.export',{detail:{ scene: model.scene,ext}}) ) xrf.emit('export', {scene: model.scene, ext}) .then( () => { + + function download(dataurl, filename) { + var a = document.createElement("a"); + a.href = URL.createObjectURL( new Blob([dataurl]) ); + a.setAttribute("download", filename); + a.click(); + return false; + } + // setup exporters let defaultExporter = THREE.GLTFExporter if( !xrf.loaders['gltf'].exporter ) xrf.loaders['gltf'].exporter = defaultExporter if( !xrf.loaders['glb'].exporter ) xrf.loaders['glb'].exporter = defaultExporter - const exporter = new xrf.loaders[ext]() + const exporter = new xrf.loaders[ext].exporter() + debugger exporter.parse( model.scene, function ( glb ) { download(glb, `${file}`) }, // ready @@ -287,13 +290,12 @@ window.frontend = (opts) => new Proxy({ // load original scene and overwrite with updates let url = document.location.search.replace(/\?/,'') let {urlObj,dir,file,hash,fileExt} = xrf.navigator.origin = xrf.URI.parse(url) - debugger const Loader = xrf.loaders[fileExt] loader = new Loader().setPath( dir ) notify('exporting scene

please wait..') loader.load(url, (model) => { exportScene(model,fileExt,file) - }) + }, console.error ) }, updateHashPosition(randomize){ diff --git a/src/3rd/js/plugin/remotestorage/remotestorage-module-webXRF.js b/src/3rd/js/plugin/remotestorage/remotestorage-module-webXRF.js new file mode 100644 index 0000000..2b11695 --- /dev/null +++ b/src/3rd/js/plugin/remotestorage/remotestorage-module-webXRF.js @@ -0,0 +1,7 @@ +const WebXRF = { name: 'webxr', builder: function(privateClient, publicClient) { + return { + exports: { + addScene: function() {} + } + } +}}; diff --git a/src/3rd/js/plugin/remotestorage/remotestorage.js b/src/3rd/js/plugin/remotestorage/remotestorage.js index 53287ca..c277557 100644 --- a/src/3rd/js/plugin/remotestorage/remotestorage.js +++ b/src/3rd/js/plugin/remotestorage/remotestorage.js @@ -3,33 +3,39 @@ // reactive component for displaying the menu remoteStorageComponent = (el) => new Proxy({ - html: ` + html: (data) => (`
-

- - +
+
- `, + `), - show: false, - - toggle(state){ - this.show = state !== undefined ? state : !this.show - }, + connected: false, init(opts){ // create HTML element - $files.tabs = $files.tabs.concat({id:"remoteFiles", name: "remote files"}) - el.innerHTML = this.html + $files.tabs = $files.tabs.concat({id:"remoteFiles", name: "online"}) + el.innerHTML = this.html(this) el.className = "tab" - this.toggle(this.show) // trigger visibility document.querySelector("#files .tab-frame").appendChild(el); // setup input listeners @@ -61,32 +67,36 @@ remoteStorageComponent = (el) => new Proxy({ let apis = { dropbox: "4jc8nx1lbarp472" } - window.remoteStorage = new RemoteStorage({logging: true }) + const modules = [] + if( typeof WebXRF != undefined ){ + modules.push(WebXRF) // defined in remotestorage-module-webXRF.js + } + window.remoteStorage = new RemoteStorage({logging: true, modules }) if( Object.keys(apis).length ) remoteStorage.setApiKeys(apis) - remoteStorage.on('connected', (e) => { console.log("connected") } ) + remoteStorage.on('connected', (e) => { this.connected = true }) //remoteStorage.on('network-offline', (e) => this.el.sceneEl.emit('remoteStorage.network-offline',e) ) //remoteStorage.on('network-online', (e) => this.el.sceneEl.emit('remoteStorage.network-online',e) ) //remoteStorage.on('error', (e) => this.el.sceneEl.emit('remoteStorage.error',e) ) - //remoteStorage.on('ready', (e) => { } ) + remoteStorage.on('ready', (e) => { } ) remoteStorage.access.claim( `webxr`, 'rw'); // our data dir remoteStorage.caching.enable( `/webxr/` ) // local-first, remotestorage-second + remoteStorage.caching.enable( `/public/webxr/` ) // local-first, remotestorage-second // create widget let opts = {} opts.modalBackdrop = false + opts.leaveOpen = true widget = new window.Widget(window.remoteStorage, opts) widget.attach( "rswidget" ); }, click(id,e){ - switch(id){ - case "icon": - case "more": return this.toggle(); break; - } - this.toggle(false) + //switch(id){ + // case "more": return this.toggle(); break; + //} } }, { @@ -95,6 +105,9 @@ remoteStorageComponent = (el) => new Proxy({ set(me,k,v){ me[k] = v + switch( k ){ + case 'connected': el.querySelector("#buttons").style.display = v ? 'block' : 'none'; break; + } }, }) diff --git a/src/3rd/js/three/navigator.js b/src/3rd/js/three/navigator.js index 6d39d50..38a100e 100644 --- a/src/3rd/js/three/navigator.js +++ b/src/3rd/js/three/navigator.js @@ -63,7 +63,6 @@ xrf.navigator.to = (url,flags,loader,data) => { evalFragment() return resolve(xrf.model) // eval non-positional fragments (no loader needed) } - xrf .emit('navigateLoading', {url,loader,data}) .then( () => { @@ -109,7 +108,7 @@ xrf.navigator.init = () => { xrf.navigator.URI = xrfragment.URI.parse(document.location.href) window.addEventListener('popstate', function (event){ - if( xrf.navigator.updateHash.active ){ // ignore programmatic hash updates (causes infinite recursion) + if( xrf.navigator.updateHash.active && document.location.hash.length > 1 ){ // ignore programmatic hash updates (causes infinite recursion) xrf.navigator.to( xrf.navigator.URI.last ) } }) @@ -119,7 +118,9 @@ xrf.navigator.init = () => { }) // allow other libraries to trigger popstate event without triggering the navigate-fallbacks during pageload - setTimeout( xrf.navigator.setupNavigateFallbacks(), 1500 ) + setTimeout( () => { + xrf.navigator.setupNavigateFallbacks() + }, 2500 ) // this allows selectionlines to be updated according to the camera (renderloop) xrf.focusLine = new xrf.THREE.Group()