diff --git a/com/dom.js b/com/dom.js index 3eb98b9..3241417 100644 --- a/com/dom.js +++ b/com/dom.js @@ -59,7 +59,6 @@ if( !AFRAME.components.dom ){ .assignUniqueID() .scaleDOMvsXR() .triggerKeyboardForInputs() - .stubRequestAnimationFrame() document.querySelector('#overlay').appendChild(this.el.dom) this.el.emit('DOMready',{el: this.el.dom}) @@ -131,10 +130,5 @@ if( !AFRAME.components.dom ){ return this }, - stubRequestAnimationFrame: async function(){ - let s = await AFRAME.utils.require(this.requires) - this.el.setAttribute("requestAnimationFrameXR","") - } - }) } diff --git a/com/isoterminal.js b/com/isoterminal.js index b1a48eb..a2bea00 100644 --- a/com/isoterminal.js +++ b/com/isoterminal.js @@ -38,13 +38,13 @@ if( typeof AFRAME != 'undefined '){ rows: { type: 'number',"default": 30 }, padding: { type: 'number',"default": 18 }, minimized: { type: 'boolean',"default":false}, - maximized: { type: 'boolean',"default":true}, + maximized: { type: 'boolean',"default":false}, transparent: { type:'boolean', "default":false }, // need good gpu xterm: { type: 'boolean', "default":true }, // use xterm.js? (=slower) memory: { type: 'number', "default":48 } // VM memory (in MB) }, - init: async function(){ + init: function(){ this.el.object3D.visible = false fetch(this.data.iso,{method: 'HEAD'}) .then( (res) => { @@ -125,6 +125,7 @@ if( typeof AFRAME != 'undefined '){ .wb-body:has(> .isoterminal){ background: #000C; overflow:hidden; + border-radius:7px; } .XR .wb-body:has(> .isoterminal){ @@ -159,6 +160,7 @@ if( typeof AFRAME != 'undefined '){ this.requires.xtermjs = "https://unpkg.com/@xterm/xterm@5.5.0/lib/xterm.js" this.requires.xtermcss = "https://unpkg.com/@xterm/xterm@5.5.0/css/xterm.css" this.requires.xterm = "com/isoterminal/feat/xterm.js" + // xterm relies on window.requestAnimationFrame which is not called in XR (xrSession.requestAnimationFrame is) } let s = await AFRAME.utils.require(this.requires) @@ -199,7 +201,6 @@ if( typeof AFRAME != 'undefined '){ instance.setAttribute("dom", "") - this.isoterminal.addEventListener('postReady', (e)=>{ // bugfix: send window dimensions to xterm (xterm.js does that from dom-sizechange to xterm via escape codes) let wb = instance.winbox @@ -246,7 +247,6 @@ if( typeof AFRAME != 'undefined '){ instance.object3D.quaternion.copy( AFRAME.scenes[0].camera.quaternion ) // face towards camera }, - events:{ // combined AFRAME+DOM reactive events diff --git a/com/isoterminal/feat/xterm.js b/com/isoterminal/feat/xterm.js index 3d0cd58..582bb9d 100644 --- a/com/isoterminal/feat/xterm.js +++ b/com/isoterminal/feat/xterm.js @@ -25,9 +25,30 @@ ISOTerminal.prototype.xtermInit = function(){ term.select(0, 0, 0) isoterm.emit('status','copied to clipboard') }) + + term.onRender( () => { + console.log("render") + // xterm relies on requestAnimationFrame (which does not called in immersive mode) + const _window = term._core._coreBrowserService._window + const requestAnimationFrame = _window.requestAnimationFrame + // luckily xterm allows a swappable window object + let newWindow = function(){}.bind(window) + for( var i in window ) newWindow[i] = window[i] + newWindow.requestAnimationFrame = (cb) => { + if( term.tid != null ) return + setTimeout( () => { + cb() + term.tid = null + },200) + } + term._core._coreBrowserService._window = newWindow + + }) + return term } + this.addEventListener('emulator-started', function(){ this.emulator.serial_adapter.term.element.querySelector('.xterm-viewport').style.background = 'transparent' // toggle immersive with ESCAPE @@ -36,7 +57,9 @@ ISOTerminal.prototype.xtermInit = function(){ const resize = (w,h) => { setTimeout( () => { - isoterm.xtermAutoResize(isoterm.emulator.serial_adapter.term, isoterm.instance,-3) + if( isoterm?.emulator?.serial_adapter?.term ){ + isoterm.xtermAutoResize(isoterm.emulator.serial_adapter.term, isoterm.instance,-3) + } },800) // wait for resize anim } isoterm.instance.addEventListener('window.onresize', resize ) diff --git a/com/requestAnimationFrameXR.js b/com/requestAnimationFrameXR.js deleted file mode 100644 index 1192bec..0000000 --- a/com/requestAnimationFrameXR.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * ## requestAnimationFrameXR - * - * reroutes requestAnimationFrame-calls to xrSession.requestAnimationFrame - * reason: in immersive mode this function behaves differently - * (causing HTML apps like xterm.js not getting updated due to relying - * on window.requestAnimationFrame) - * - * ```html - * - * ``` - */ - -if( !AFRAME.systems.requestAnimationFrameXR ){ - - AFRAME.registerSystem('requestAnimationFrameXR',{ - - init: function init(){ - if( document.location.hostname.match(/localhost/) ) return // allow webxr polyfill during development (they hang in XR) - AFRAME.systems.requestAnimationFrameXR.q = [] - this.sceneEl.addEventListener('enter-vr', this.enable ) - this.sceneEl.addEventListener('enter-ar', this.enable ) - this.sceneEl.addEventListener('exit-vr', this.disable ) - this.sceneEl.addEventListener('exit-ar', this.disable ) - }, - - enable: function enable(){ - this.requestAnimationFrame = window.requestAnimationFrame - // NOTE: we don't call xrSession.requestAnimationFrame directly like this: - // - // window.requestAnimationFrame = AFRAME.utils.throttleTick( (cb) => this.sceneEl.xrSession.requestAnimationFrame(cb), 50 ) - // - // as that breaks webxr polyfill (for in-browser testing) - // instead we defer calls to tick() (which is called both in XR and non-XR) - // - window.requestAnimationFrame = (cb) => AFRAME.systems.requestAnimationFrameXR.q.push(cb) - const q = AFRAME.systems.requestAnimationFrameXR.q - this.tick = AFRAME.utils.throttleTick( () => { - while( q.length != 0 ) (q.pop())() - },50) - }, - - disable: function disable(){ - delete this.tick - window.requestAnimationFrame = this.requestAnimationFrame - } - - - }) -} diff --git a/com/xrfragments.js b/com/xrfragments.js deleted file mode 100644 index 50c4ea8..0000000 --- a/com/xrfragments.js +++ /dev/null @@ -1,81 +0,0 @@ -AFRAME.registerComponent('xrfragments', { - schema: { - url: { type:"string"} - }, - - init: function () { - }, - - events:{ - - launcher: async function(){ - let url = prompt('enter URL to glb/fbx/json/obj/usdz asset', 'https://xrfragment.org/index.glb') - if( !url ) return - await AFRAME.utils.require({ - xrfragments: "https://xrfragment.org/dist/xrfragment.aframe.js", - }) - - // remove objects which are marked to be removed from scene (with noxrf) - let els = [...document.querySelectorAll('[noxrf]') ] - els.map( (el) => el.remove() ) - - if( !this.el.getAttribute("xrf") ){ - this.el.setAttribute("xrf", url ) - let ARbutton = document.querySelector('.a-enter-ar-button') - if( ARbutton ){ - ARbutton.addEventListener('click', () => { - AFRAME.XRF.reset() - }) - } - }else AFRAME.XRF.navigator.to(url) - } - - }, - - manifest: { // HTML5 manifest to identify app to xrsh - "short_name": "XRF", - "name": "XR Fragment URL", - "icons": [ ], - "id": "/?source=pwa", - "start_url": "/?source=pwa", - "background_color": "#3367D6", - "display": "standalone", - "scope": "/", - "theme_color": "#3367D6", - "shortcuts": [ - { - "name": "What is the latest news?", - "cli":{ - "usage": "helloworld [options]", - "example": "helloworld news", - "args":{ - "--latest": {type:"string"} - } - }, - "short_name": "Today", - "description": "View weather information for today", - "url": "/today?source=pwa", - "icons": [{ "src": "/images/today.png", "sizes": "192x192" }] - } - ], - "description": "Hello world information", - "screenshots": [ - { - "src": "/images/screenshot1.png", - "type": "image/png", - "sizes": "540x720", - "form_factor": "narrow" - } - ], - "help":` -Helloworld application - -This is a help file which describes the application. -It will be rendered thru troika text, and will contain -headers based on non-punctualized lines separated by linebreaks, -in above's case "\nHelloworld application\n" will qualify as header. - ` - } - -}); -