From 49177914552ac9448c21bde8189058703b265212 Mon Sep 17 00:00:00 2001 From: Leon van Kammen Date: Wed, 24 Apr 2024 10:18:57 +0000 Subject: [PATCH] wip --- make | 2 +- src/3rd/js/plugin/frontend/$chat.js | 6 +- src/3rd/js/plugin/frontend/accessibility.js | 41 +++++++++-- src/3rd/js/plugin/frontend/css.js | 2 +- src/3rd/js/plugin/vendors/README.md | 4 ++ src/3rd/js/plugin/vendors/spec.json | 6 ++ src/3rd/js/plugin/vendors/three/README.md | 1 + src/3rd/js/plugin/vendors/three/fragments.js | 10 +++ src/3rd/js/plugin/vendors/three/metadata.js | 16 +++++ .../js/plugin/vendors/three/refactor/env.js | 15 ++++ .../js/plugin/vendors/three/refactor/fov.js | 7 ++ .../js/plugin/vendors/three/refactor/macro.js | 71 +++++++++++++++++++ .../js/plugin/vendors/three/refactor/mov.js | 12 ++++ .../js/plugin/vendors/three/refactor/pos.js | 14 ++++ .../js/plugin/vendors/three/refactor/rot.js | 17 +++++ .../js/plugin/vendors/three/refactor/scale.js | 13 ++++ .../js/plugin/vendors/three/refactor/show.js | 17 +++++ 17 files changed, 247 insertions(+), 7 deletions(-) create mode 100644 src/3rd/js/plugin/vendors/README.md create mode 100644 src/3rd/js/plugin/vendors/spec.json create mode 100644 src/3rd/js/plugin/vendors/three/README.md create mode 100644 src/3rd/js/plugin/vendors/three/fragments.js create mode 100644 src/3rd/js/plugin/vendors/three/metadata.js create mode 100644 src/3rd/js/plugin/vendors/three/refactor/env.js create mode 100644 src/3rd/js/plugin/vendors/three/refactor/fov.js create mode 100644 src/3rd/js/plugin/vendors/three/refactor/macro.js create mode 100644 src/3rd/js/plugin/vendors/three/refactor/mov.js create mode 100644 src/3rd/js/plugin/vendors/three/refactor/pos.js create mode 100644 src/3rd/js/plugin/vendors/three/refactor/rot.js create mode 100644 src/3rd/js/plugin/vendors/three/refactor/scale.js create mode 100644 src/3rd/js/plugin/vendors/three/refactor/show.js diff --git a/make b/make index 8d991dd..2a9d3bc 100755 --- a/make +++ b/make @@ -116,7 +116,7 @@ build(){ for file in dist/xrfragment.{aframe,module,three,three.module,aframe.all}.js; do awk 'BEGIN{ print "/*" - print " * '"$(git tag)"' generated at '"$(date)"'" + print " * '"$(git tag | head -n1)"' generated at '"$(date)"'" print " * https://xrfragment.org" print " * SPDX-License-Identifier: MPL-2.0" print " */" diff --git a/src/3rd/js/plugin/frontend/$chat.js b/src/3rd/js/plugin/frontend/$chat.js index 6abd17c..ba3ff79 100644 --- a/src/3rd/js/plugin/frontend/$chat.js +++ b/src/3rd/js/plugin/frontend/$chat.js @@ -409,9 +409,13 @@ chatComponent.css = ` margin:0; } + .envelope{ + margin-right:15px; + max-width:80%; + } + .envelope, .envelope * { - overflow:hidden; transition:1s; pointer-events:none; } diff --git a/src/3rd/js/plugin/frontend/accessibility.js b/src/3rd/js/plugin/frontend/accessibility.js index 3d9f014..e93de4a 100644 --- a/src/3rd/js/plugin/frontend/accessibility.js +++ b/src/3rd/js/plugin/frontend/accessibility.js @@ -101,14 +101,50 @@ window.accessibility = (opts) => new Proxy({ setTimeout( () => this.initCommands(), 200 ) // auto-enable if previously enabled if( window.localStorage.getItem("accessibility") ){ - setTimeout( () => this.enabled = true, 100 ) + setTimeout( () => { + this.enabled = true + this.setFontSize() + }, 100 ) } }, initCommands(){ + document.addEventListener('chat.command.help', (e) => { e.detail.message += `
/fontsize set fontsize (default=14) ` }) + + document.addEventListener('chat.command', (e) => { + if( e.detail.message.match(/^fontsize/) ){ + try{ + let fontsize = parseInt( e.detail.message.replace(/^fontsize /,'').trim() ) + if( fontsize == NaN ) throw 'not a number' + this.setFontSize(fontsize) + $chat.send({message:'fontsize set to '+fontsize}) + }catch(e){ + console.error(e) + $chat.send({message:'example usage: /fontsize 20'}) + } + } + }) + + }, + + setFontSize(size){ + if( size ){ + window.localStorage.setItem("fontsize",size) + }else size = window.localStorage.getItem("fontsize") + if( !size ) return + document.head.innerHTML += ` + + ` + $messages = document.querySelector('#messages') + setTimeout( () => $messages.scrollTop = $messages.scrollHeight, 1000 ) }, posToMessage(opts){ @@ -182,9 +218,6 @@ document.querySelector('head').innerHTML += ` padding-top:15px; padding-bottom:15px; } - .accessibility .transcript { - max-height:unset; - } .accessibility #chatbar{ display: block !important; } diff --git a/src/3rd/js/plugin/frontend/css.js b/src/3rd/js/plugin/frontend/css.js index 644649f..ebdbe19 100644 --- a/src/3rd/js/plugin/frontend/css.js +++ b/src/3rd/js/plugin/frontend/css.js @@ -370,7 +370,7 @@ document.head.innerHTML += ` .transcript{ max-height:105px; - max-width:405px; + width:100%; overflow-y:auto; border: 1px solid var(--xrf-gray); border-radius: 5px; diff --git a/src/3rd/js/plugin/vendors/README.md b/src/3rd/js/plugin/vendors/README.md new file mode 100644 index 0000000..291fbed --- /dev/null +++ b/src/3rd/js/plugin/vendors/README.md @@ -0,0 +1,4 @@ +vendor specific macros are meta-dat mappings which translate to vendor specific features: + +'-three-fog' : '10,100' ==> three/fog.js ==> scene.fog = new THREE.Fog( scene.background, v.x, v.y ); + diff --git a/src/3rd/js/plugin/vendors/spec.json b/src/3rd/js/plugin/vendors/spec.json new file mode 100644 index 0000000..e9a6a9f --- /dev/null +++ b/src/3rd/js/plugin/vendors/spec.json @@ -0,0 +1,6 @@ +{ + "-{vendor}-fog": { + "near": "x", + "far": "y" + } +} diff --git a/src/3rd/js/plugin/vendors/three/README.md b/src/3rd/js/plugin/vendors/three/README.md new file mode 100644 index 0000000..8370beb --- /dev/null +++ b/src/3rd/js/plugin/vendors/three/README.md @@ -0,0 +1 @@ +currently broken diff --git a/src/3rd/js/plugin/vendors/three/fragments.js b/src/3rd/js/plugin/vendors/three/fragments.js new file mode 100644 index 0000000..16280c9 --- /dev/null +++ b/src/3rd/js/plugin/vendors/three/fragments.js @@ -0,0 +1,10 @@ +xrf.frag.clip = function(v, opts){ + let { frag, mesh, model, camera, scene, renderer, THREE} = opts + + if( v.x == 0 ) v.x = 1; // THREE.js .near restriction + console.log("└ clip "+v.x+","+v.y); + + camera.near = v.x + camera.far = v.y + camera.updateProjectionMatrix(); +} diff --git a/src/3rd/js/plugin/vendors/three/metadata.js b/src/3rd/js/plugin/vendors/three/metadata.js new file mode 100644 index 0000000..a68f4de --- /dev/null +++ b/src/3rd/js/plugin/vendors/three/metadata.js @@ -0,0 +1,16 @@ +xrf.addEventListener('-three-fog', (opts) => { + let { frag, mesh, model, camera, scene, renderer, THREE} = opts + let v = frag.fog + console.log("└ threejs fog "+v.x+","+v.y); + if( v.x == 0 && v.y == 0 ){ + if( scene.fog ) delete scene.fog + scene.fog = null; + }else scene.fog = new THREE.Fog( scene.background, v.x, v.y ); +}) + +xrf.addEventListener('bg', (opts) => { + let { frag, mesh, model, camera, scene, renderer, THREE} = opts + console.log("└ bg "+v.x+","+v.y+","+v.z); + if( scene.background ) delete scene.background + scene.background = new THREE.Color( v.x, v.y, v.z ) +}) diff --git a/src/3rd/js/plugin/vendors/three/refactor/env.js b/src/3rd/js/plugin/vendors/three/refactor/env.js new file mode 100644 index 0000000..04885f1 --- /dev/null +++ b/src/3rd/js/plugin/vendors/three/refactor/env.js @@ -0,0 +1,15 @@ +xrf.addEventListener('env', (opts) => { + let { frag, mesh, model, camera, scene, renderer, THREE} = opts + if( frag.env && !scene.environment ){ + //let env = scene.getObjectByName(frag.env.string) + //if( !env ) env = xrf.scene.getObjectByName(frag.env.string) // repurpose from parent scene + //if( !env ) return console.warn("xrf.env "+frag.env.string+" not found") + //env.material.map.mapping = THREE.EquirectangularReflectionMapping; + //scene.environment = env.material.map + //scene.texture = env.material.map + // renderer.toneMapping = THREE.ACESFilmicToneMapping; + // renderer.toneMappingExposure = 2; + // console.log(` └ applied image '${frag.env.string}' as environment map`) + } + +}) diff --git a/src/3rd/js/plugin/vendors/three/refactor/fov.js b/src/3rd/js/plugin/vendors/three/refactor/fov.js new file mode 100644 index 0000000..047cd7f --- /dev/null +++ b/src/3rd/js/plugin/vendors/three/refactor/fov.js @@ -0,0 +1,7 @@ +xrf.frag.fov = function(v, opts){ + let { frag, mesh, model, camera, scene, renderer, THREE} = opts + + console.log("└ fov "+v.int); + camera.fov = v.int; + camera.updateProjectionMatrix(); +} diff --git a/src/3rd/js/plugin/vendors/three/refactor/macro.js b/src/3rd/js/plugin/vendors/three/refactor/macro.js new file mode 100644 index 0000000..1cfb366 --- /dev/null +++ b/src/3rd/js/plugin/vendors/three/refactor/macro.js @@ -0,0 +1,71 @@ +xrf.macros = {} + +xrf.addEventListener('frag2mesh', (opts) => { + let { frag, mesh, model, camera, scene, renderer, THREE, hashbus} = opts + + for( let k in frag ){ + let id = mesh.name+"_"+k + let fragment = frag[k] + + if( k.match(/^!/) ){ + if( mesh.material) mesh.material = mesh.material.clone() + if( mesh.isSRC || scene.isSRC ) return; // dont allow recursion for now + + if( xrf.macros[k] ) return // already initialized + + console.log("└ initing xrmacro: "+k) + xrf.macros[k] = fragment + fragment.args = fragment.string.split("|") + + fragment.trigger = (e) => { + xrf + .emit('macro',{click:true,mesh,xrf:frag}) // let all listeners agree + .then( () => { + rrFrag = fragment.args[ xrf.roundrobin( fragment,model) ] + console.log("└ xrmacro: "+rrFrag) + if( xrf.macros[ rrFrag ] ){ + xrf.macros[ rrFrag ].trigger() + } else { + xrf.navigator.to( rrFrag,null,0) + } + }) + } + + let selected = (state) => () => { + if( mesh.selected == state ) return // nothing changed + if( mesh.material ){ + if( mesh.material.uniforms ) mesh.material.uniforms.selected.value = state + else mesh.material.color.r = mesh.material.color.g = mesh.material.color.b = state ? 2.0 : 1.0 + } + // update mouse cursor + if( !renderer.domElement.lastCursor ) + renderer.domElement.lastCursor = renderer.domElement.style.cursor + renderer.domElement.style.cursor = state ? 'pointer' : renderer.domElement.lastCursor + xrf + .emit('macro',{selected:state,mesh,xrf:frag}) // let all listeners agree + .then( () => mesh.selected = state ) + } + + mesh.addEventListener('click', fragment.trigger ) + mesh.addEventListener('mousemove', selected(true) ) + mesh.addEventListener('nocollide', selected(false) ) + + // lazy add mesh to interactive group (because we're inside a recursive traverse) + setTimeout( (mesh) => { + const world = { + pos: new THREE.Vector3(), + scale: new THREE.Vector3(), + quat: new THREE.Quaternion() + } + mesh.getWorldPosition(world.pos) + mesh.getWorldScale(world.scale) + mesh.getWorldQuaternion(world.quat); + mesh.position.copy(world.pos) + mesh.scale.copy(world.scale) + mesh.setRotationFromQuaternion(world.quat); + xrf.interactive.add(mesh) + xrf.emit('interactionReady', {mesh,xrf:fragment, clickHandler: fragment.trigger}) + }, 10, mesh ) + } + } +}) diff --git a/src/3rd/js/plugin/vendors/three/refactor/mov.js b/src/3rd/js/plugin/vendors/three/refactor/mov.js new file mode 100644 index 0000000..90431e4 --- /dev/null +++ b/src/3rd/js/plugin/vendors/three/refactor/mov.js @@ -0,0 +1,12 @@ +xrf.addEventListener('mov', (opts) => { + let { frag, mesh, model, camera, scene, renderer, THREE} = opts + if( frag.mov && frag.q ){ + + // let wait for the queried objects (as we're inside promise which traverses the graph) + setTimeout( (v) => { + frag.q.getObjects().map( (o) => { + o.position.add( new THREE.Vector3( v.x, v.y, v.z ) ) + }) + },10, frag.mov ) + } +}) diff --git a/src/3rd/js/plugin/vendors/three/refactor/pos.js b/src/3rd/js/plugin/vendors/three/refactor/pos.js new file mode 100644 index 0000000..493643a --- /dev/null +++ b/src/3rd/js/plugin/vendors/three/refactor/pos.js @@ -0,0 +1,14 @@ +xrf.addEventListener('pos', (opts) => { + let { frag, mesh, model, camera, scene, renderer, THREE} = opts + //if( frag.pos && frag.q ){ + // // apply roundrobin (if any) + // if( v.args ) v = v.args[ xrf.roundrobin(v,model) ] + + // frag.q.getObjects().map( (o) => { + // // if object has no parent (name == 'Scene') use absolute positioning, otherwise relative to parent + // o.position.x = o.parent.name == 'Scene' ? v.x : o.positionOriginal.x + v.x + // o.position.y = o.parent.name == 'Scene' ? v.z : o.positionOriginal.y + v.z + // o.position.z = o.parent.name == 'Scene' ? v.y : o.positionOriginal.z + v.y + // }) + //} +}) diff --git a/src/3rd/js/plugin/vendors/three/refactor/rot.js b/src/3rd/js/plugin/vendors/three/refactor/rot.js new file mode 100644 index 0000000..efb3e96 --- /dev/null +++ b/src/3rd/js/plugin/vendors/three/refactor/rot.js @@ -0,0 +1,17 @@ +xrf.addEventListener('rot', (opts) => { + let { frag, mesh, model, camera, scene, renderer, THREE} = opts + if( frag.rot && frag.q ){ + // apply roundrobin (if any) + if( v.args ) v = v.args[ xrf.roundrobin(v,model) ] + + if( frag.q ){ // only operate on queried object(s) + frag.q.getObjects().map( (o) => { + o.rotation.set( + v.x * Math.PI / 180, + v.y * Math.PI / 180, + v.z * Math.PI / 180 + ) + }) + } + } +}) diff --git a/src/3rd/js/plugin/vendors/three/refactor/scale.js b/src/3rd/js/plugin/vendors/three/refactor/scale.js new file mode 100644 index 0000000..35fb241 --- /dev/null +++ b/src/3rd/js/plugin/vendors/three/refactor/scale.js @@ -0,0 +1,13 @@ +xrf.addEventListener('scale', (opts) => { + let { frag, mesh, model, camera, scene, renderer, THREE} = opts + if( frag.scale && frag.q ){ + // apply roundrobin (if any) + if( v.args ) v = v.args[ xrf.roundrobin(v,model) ] + + frag.q.getObjects().map( (o) => { + o.scale.x = v.x + o.scale.y = v.y + o.scale.z = v.z + }) + } +}) diff --git a/src/3rd/js/plugin/vendors/three/refactor/show.js b/src/3rd/js/plugin/vendors/three/refactor/show.js new file mode 100644 index 0000000..8aa23f3 --- /dev/null +++ b/src/3rd/js/plugin/vendors/three/refactor/show.js @@ -0,0 +1,17 @@ +xrf.addEventListener('show', (opts) => { + let { frag, mesh, model, camera, scene, renderer, THREE} = opts + if( frag.show && frag.q ){ + let show = frag.show + + // apply roundrobin (if any) + if( show.args ) v = show.args[ xrf.roundrobin(show,model) ] + else v = show.int + + // let wait for the queried objects (as we're inside promise which traverses the graph) + setTimeout( (v) => { + frag.q.getObjects().map( (o) => { + o.visible = v.int == 1; + }) + }, 20, v) + } +})