This commit is contained in:
Leon van Kammen 2024-04-24 10:18:57 +00:00
parent d8b77a39ed
commit 4917791455
17 changed files with 247 additions and 7 deletions

2
make
View File

@ -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 " */"

View File

@ -409,9 +409,13 @@ chatComponent.css = `
margin:0;
}
.envelope{
margin-right:15px;
max-width:80%;
}
.envelope,
.envelope * {
overflow:hidden;
transition:1s;
pointer-events:none;
}

View File

@ -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 += `<br><b class="badge">/fontsize <number></b> 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 += `
<style type="text/css">
.accessibility #messages * {
font-size: ${size}px !important;
line-height: ${size*2}px !important;
}
</style>
`
$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;
}

View File

@ -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;

4
src/3rd/js/plugin/vendors/README.md vendored Normal file
View File

@ -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 );

6
src/3rd/js/plugin/vendors/spec.json vendored Normal file
View File

@ -0,0 +1,6 @@
{
"-{vendor}-fog": {
"near": "x",
"far": "y"
}
}

View File

@ -0,0 +1 @@
currently broken

View File

@ -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();
}

View File

@ -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 )
})

View File

@ -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`)
}
})

View File

@ -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();
}

View File

@ -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 )
}
}
})

View File

@ -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 )
}
})

View File

@ -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
// })
//}
})

View File

@ -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
)
})
}
}
})

View File

@ -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
})
}
})

View File

@ -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)
}
})