From c668a8ba8f65c3d36e3a4da5ea8b87af5eb6091c Mon Sep 17 00:00:00 2001 From: Leon van Kammen Date: Thu, 4 Jul 2024 23:00:44 +0200 Subject: [PATCH] fix requestAnimationFrame mystery --- com/dom.js | 9 ++++++++ com/isoterminal.js | 52 ++++++++++++++++++++++++++++++---------------- com/window.js | 14 ++++++++----- com/xd.js | 2 +- 4 files changed, 53 insertions(+), 24 deletions(-) diff --git a/com/dom.js b/com/dom.js index c16f90f..fb77222 100644 --- a/com/dom.js +++ b/com/dom.js @@ -53,6 +53,7 @@ AFRAME.registerComponent('dom',{ .assignUniqueID() .scaleDOMvsXR() .triggerKeyboardForInputs() + .stubRequestAnimationFrame() document.querySelector('#overlay').appendChild(this.el.dom) this.el.emit('DOMready',{el: this.el.dom}) @@ -121,6 +122,14 @@ AFRAME.registerComponent('dom',{ input.addEventListener('click', triggerKeyboard ) }) return this + }, + + stubRequestAnimationFrame: function(){ + // stub, because WebXR with overrule this (it will not call the callback as expected in immersive mode) + const requestAnimationFrame = window.requestAnimationFrame + window.requestAnimationFrame = (cb) => { + setTimeout( cb, 25 ) + } } }) diff --git a/com/isoterminal.js b/com/isoterminal.js index bbe437d..ec65ce6 100644 --- a/com/isoterminal.js +++ b/com/isoterminal.js @@ -1,9 +1,10 @@ AFRAME.registerComponent('isoterminal', { schema: { - iso: { type:"string", "default":"com/isoterminal/xrsh.iso" }, - cols: { type: 'number', default: 120 }, - rows: { type: 'number', default: 30 }, - transparent: { type:'boolean', default:false } // need good gpu + iso: { type:"string", "default":"com/isoterminal/xrsh.iso" }, + cols: { type: 'number',"default": 120 }, + rows: { type: 'number',"default": 30 }, + padding:{ type: 'number',"default": 15 }, + transparent: { type:'boolean', "default":false } // need good gpu }, init: function(){ @@ -12,7 +13,6 @@ AFRAME.registerComponent('isoterminal', { requires:{ 'window': "com/window.js", - html: "https://unpkg.com/aframe-htmlmesh@2.1.0/build/aframe-html.js", // html to AFRAME winboxjs: "https://unpkg.com/winbox@0.2.82/dist/winbox.bundle.min.js", // deadsimple windows: https://nextapps-de.github.io/winbox winboxcss: "https://unpkg.com/winbox@0.2.82/dist/css/winbox.min.css", // xtermcss: "https://unpkg.com/xterm@3.12.0/dist/xterm.css", @@ -31,23 +31,25 @@ AFRAME.registerComponent('isoterminal', { css: (me) => `.isoterminal{ background:#000; - padding:15px; + padding: ${me.com.data.padding}px; /*overflow:hidden; */ } .isoterminal *{ white-space: pre; font-size: 14px; font-family: Liberation Mono,DejaVu Sans Mono,Courier New,monospace; - display: block; font-weight:700; + display:inline; + overflow: hidden; } - .terminal{ - padding:15px; - }` + .wb-body:has(> .isoterminal){ background: #000; } + .isoterminal div{ display:block; } + .isoterminal span{ display: inline } + ` }, runISO: function(dom){ - var emulator = window.emulator = new V86({ + var emulator = window.emulator = dom.emulator = new V86({ wasm_path: "com/isoterminal/v86.wasm", memory_size: 32 * 1024 * 1024, vga_memory_size: 2 * 1024 * 1024, @@ -75,13 +77,17 @@ AFRAME.registerComponent('isoterminal', { screen_dummy: true, autostart: true, }); + + //setTimeout( () => { + // window.requestAnimationFrame = requestAnimationFrame + //},1000) }, events:{ // combined AFRAME+DOM reactive events click: function(e){ }, // - keydown: function(e){ }, // + keydown: function(e){ }, // reactive events for this.data updates myvalue: function(e){ this.el.dom.querySelector('b').innerText = this.data.myvalue }, @@ -98,7 +104,18 @@ AFRAME.registerComponent('isoterminal', { instance.addEventListener('DOMready', () => { this.runISO(instance.dom) - instance.setAttribute("window", `title: ${this.data.iso}; uid: ${instance.uid}; attach: #overlay; dom: #${instance.dom.id}`) + instance.setAttribute("window", `title: ${this.data.iso}; uid: ${instance.uid}; attach: #overlay; dom: #${instance.dom.id}`) + }) + + instance.addEventListener('window.oncreate', (e) => { + // resize after the dom content has been rendered & updated + setTimeout( () => { + let spans = [...instance.dom.querySelectorAll('span')] + instance.winbox.resize( + (spans[0].offsetWidth + (2*this.data.padding))+'px', + ((spans.length * spans[0].offsetHeight) ) +'px' + ) + },1200) }) instance.addEventListener('window.onclose', (e) => { @@ -111,13 +128,12 @@ AFRAME.registerComponent('isoterminal', { instance.setAttribute("position", AFRAME.utils.XD.getPositionInFrontOfCamera(0.5) ) instance.setAttribute("grabbable","") - this.el.sceneEl.addEventListener('enter-vr', function(){ - instance.dom.focus() - console.log("focusing terminal") - }) + const focus = () => document.querySelector('canvas.a-canvas').focus() + instance.addEventListener('obbcollisionstarted', focus ) + this.el.sceneEl.addEventListener('enter-vr', focus ) instance.object3D.quaternion.copy( AFRAME.scenes[0].camera.quaternion ) // face towards camera - }, + } }, diff --git a/com/window.js b/com/window.js index fac3780..f3bc925 100644 --- a/com/window.js +++ b/com/window.js @@ -10,19 +10,23 @@ AFRAME.registerComponent('window', { y: {type:'string',"default":"center"} }, - dependencies:['dom'], + dependencies:{ + dom: "com/dom.js", + html: "https://unpkg.com/aframe-htmlmesh@2.1.0/build/aframe-html.js", // html to AFRAME + }, init: function(){ setTimeout( () => this.setupWindow(), 10 ) // init after other components }, - setupWindow: function(){ + setupWindow: async function(){ + await AFRAME.utils.require(this.dependencies) if( !this.el.dom ) return console.error('window element requires dom-component as dependency') this.el.dom.style.display = 'none' - let winbox = new WinBox( this.data.title, { + let winbox = this.el.winbox = new WinBox( this.data.title, { height:this.data.height, - height:this.data.width, + width:this.data.width, x: this.data.x, y: this.data.y, id: this.data.uid || String(Math.random()).substr(4), // important hint for html-mesh @@ -32,7 +36,7 @@ AFRAME.registerComponent('window', { this.el.emit('window.oncreate',{}) // resize after the dom content has been rendered & updated setTimeout( () => { - winbox.resize( winbox.width+'px', (this.data.dom.offsetHeight+(2*15))+'px' ) + winbox.resize( this.el.dom.offsetWidth+'px', this.el.dom.offsetHeight+'px' ) setTimeout( () => this.el.setAttribute("html",`html:#${this.data.uid}; cursor:#cursor`), 1000) this.el.setAttribute("grabbable","") },1000) diff --git a/com/xd.js b/com/xd.js index 4f86df0..d331104 100644 --- a/com/xd.js +++ b/com/xd.js @@ -36,7 +36,7 @@ AFRAME.registerComponent('xd', { // draw a button so we can toggle apps between 2D / XR toggle: function(state){ - state = state || !document.body.className.match(/XR/) + state = state != undefined ? state : state || !document.body.className.match(/XR/) document.body.classList[ state ? 'add' : 'remove'](['XR']) AFRAME.scenes[0].emit( state ? '3D' : '2D') },