better gyroscope + touchsupport

This commit is contained in:
Leon van Kammen 2024-06-15 17:33:08 +02:00
parent 720b17f75c
commit f508d1e262
13 changed files with 45909 additions and 146 deletions

View File

@ -1,5 +1,5 @@
/*
* v0.5.1 generated at Wed Jun 12 08:50:44 AM UTC 2024
* v0.5.1 generated at Sat Jun 15 05:22:38 PM CEST 2024
* https://xrfragment.org
* SPDX-License-Identifier: MPL-2.0
*/
@ -1942,6 +1942,39 @@ xrf.parseModel = function(model,url){
xrf.emit('parseModel',{model,url,file})
}
xrf.loadModel = function(model,url,noadd){
let URI = xrfragment.URI.toAbsolute( xrf.navigator.URI, url )
let {directory,file,fragment,fileExt} = URI;
model.file = URI.file
xrf.model = model
if( !model.isXRF ) xrf.parseModel(model,url.replace(directory,"")) // this marks the model as an XRF model
if(xrf.debug ) model.animations.map( (a) => console.log("anim: "+a.name) )
// spec: 1. generate the XRWG
xrf.XRWG.generate({model,scene:model.scene})
// spec: 2. init metadata inside model for non-SRC data
if( !model.isSRC ){
model.scene.traverse( (mesh) => xrf.parseModel.metadataInMesh(mesh,model) )
}
// spec: 1. execute the default predefined view '#' (if exist) (https://xrfragment.org/#predefined_view)
const defaultFragment = xrf.frag.defaultPredefinedViews({model,scene:model.scene})
// spec: predefined view(s) & objects-of-interest-in-XRWG from URI (https://xrfragment.org/#predefined_view)
let frag = xrf.hashbus.pub( url, model) // and eval URI XR fragments
if( !noadd ) xrf.add( model.scene )
// only change url when loading *another* file
fragment = fragment || defaultFragment || ''
xrf.navigator.pushState( URI.external ? URI.URN + URI.file : URI.file, fragment.replace(/^#/,'') )
//if( fragment ) xrf.navigator.updateHash(fragment)
xrf.emit('navigateLoaded',{url,model})
}
xrf.parseModel.metadataInMesh = (mesh,model) => {
if( mesh.userData ){
let frag = {}
@ -2065,34 +2098,7 @@ xrf.navigator.to = (url,flags,loader,data) => {
loader = loader || new Loader().setPath( URI.URN )
const onLoad = (model) => {
model.file = URI.file
xrf.model = model
if( !model.isXRF ) xrf.parseModel(model,url.replace(directory,"")) // this marks the model as an XRF model
if(xrf.debug ) model.animations.map( (a) => console.log("anim: "+a.name) )
// spec: 1. generate the XRWG
xrf.XRWG.generate({model,scene:model.scene})
// spec: 2. init metadata inside model for non-SRC data
if( !model.isSRC ){
model.scene.traverse( (mesh) => xrf.parseModel.metadataInMesh(mesh,model) )
}
// spec: 1. execute the default predefined view '#' (if exist) (https://xrfragment.org/#predefined_view)
const defaultFragment = xrf.frag.defaultPredefinedViews({model,scene:model.scene})
// spec: predefined view(s) & objects-of-interest-in-XRWG from URI (https://xrfragment.org/#predefined_view)
let frag = xrf.hashbus.pub( url, model) // and eval URI XR fragments
xrf.add( model.scene )
// only change url when loading *another* file
fragment = fragment || defaultFragment || ''
xrf.navigator.pushState( URI.external ? URI.URN + URI.file : URI.file, fragment.replace(/^#/,'') )
//if( fragment ) xrf.navigator.updateHash(fragment)
xrf.emit('navigateLoaded',{url,model})
xrf.loadModel(model,url)
resolve(model)
}
@ -2996,6 +3002,7 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
element.addEventListener( 'mousemove', onPointerEvent );
element.addEventListener( 'click', onPointerEvent );
element.addEventListener( 'mouseup', onPointerEvent );
element.addEventListener( 'touchstart', onPointerEvent );
// WebXR Controller Events
// TODO: Dispatch pointerevents too
@ -3003,6 +3010,7 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
const eventsMapper = {
'move': 'mousemove',
'select': 'click',
'touchstart': 'click',
'selectstart': 'mousedown',
'selectend': 'mouseup'
};
@ -3951,7 +3959,7 @@ xrf.portalNonEuclidian = function(opts){
if( mesh.userData.XRF.href ){
raycaster.far = 0.35
raycaster.set(cameraPosition, cameraDirection )
intersects = raycaster.intersectObjects([mesh], false)
let intersects = raycaster.intersectObjects([mesh], false)
if (intersects.length > 0 && !mesh.portal.teleporting ){
mesh.portal.teleporting = true
mesh.userData.XRF.href.exec({nocommit:true})
@ -4847,7 +4855,7 @@ AFRAME.registerComponent('xrf-gaze',{
}
},
setGazer: function(state, fuse){
if( !AFRAME.utils.device.isMobile() ) return
if( this.el.sceneEl.getAttribute("xrf-gaze-always") == undefined && !AFRAME.utils.device.isMobile() ) return
let cam = document.querySelector("[camera]")
if( state ){
if( cam.innerHTML.match(/cursor/) ) return; // avoid duplicate calls

View File

@ -1,5 +1,5 @@
/*
* v0.5.1 generated at Wed Jun 12 08:50:44 AM UTC 2024
* v0.5.1 generated at Sat Jun 15 05:22:37 PM CEST 2024
* https://xrfragment.org
* SPDX-License-Identifier: MPL-2.0
*/
@ -1940,6 +1940,39 @@ xrf.parseModel = function(model,url){
xrf.emit('parseModel',{model,url,file})
}
xrf.loadModel = function(model,url,noadd){
let URI = xrfragment.URI.toAbsolute( xrf.navigator.URI, url )
let {directory,file,fragment,fileExt} = URI;
model.file = URI.file
xrf.model = model
if( !model.isXRF ) xrf.parseModel(model,url.replace(directory,"")) // this marks the model as an XRF model
if(xrf.debug ) model.animations.map( (a) => console.log("anim: "+a.name) )
// spec: 1. generate the XRWG
xrf.XRWG.generate({model,scene:model.scene})
// spec: 2. init metadata inside model for non-SRC data
if( !model.isSRC ){
model.scene.traverse( (mesh) => xrf.parseModel.metadataInMesh(mesh,model) )
}
// spec: 1. execute the default predefined view '#' (if exist) (https://xrfragment.org/#predefined_view)
const defaultFragment = xrf.frag.defaultPredefinedViews({model,scene:model.scene})
// spec: predefined view(s) & objects-of-interest-in-XRWG from URI (https://xrfragment.org/#predefined_view)
let frag = xrf.hashbus.pub( url, model) // and eval URI XR fragments
if( !noadd ) xrf.add( model.scene )
// only change url when loading *another* file
fragment = fragment || defaultFragment || ''
xrf.navigator.pushState( URI.external ? URI.URN + URI.file : URI.file, fragment.replace(/^#/,'') )
//if( fragment ) xrf.navigator.updateHash(fragment)
xrf.emit('navigateLoaded',{url,model})
}
xrf.parseModel.metadataInMesh = (mesh,model) => {
if( mesh.userData ){
let frag = {}
@ -2063,34 +2096,7 @@ xrf.navigator.to = (url,flags,loader,data) => {
loader = loader || new Loader().setPath( URI.URN )
const onLoad = (model) => {
model.file = URI.file
xrf.model = model
if( !model.isXRF ) xrf.parseModel(model,url.replace(directory,"")) // this marks the model as an XRF model
if(xrf.debug ) model.animations.map( (a) => console.log("anim: "+a.name) )
// spec: 1. generate the XRWG
xrf.XRWG.generate({model,scene:model.scene})
// spec: 2. init metadata inside model for non-SRC data
if( !model.isSRC ){
model.scene.traverse( (mesh) => xrf.parseModel.metadataInMesh(mesh,model) )
}
// spec: 1. execute the default predefined view '#' (if exist) (https://xrfragment.org/#predefined_view)
const defaultFragment = xrf.frag.defaultPredefinedViews({model,scene:model.scene})
// spec: predefined view(s) & objects-of-interest-in-XRWG from URI (https://xrfragment.org/#predefined_view)
let frag = xrf.hashbus.pub( url, model) // and eval URI XR fragments
xrf.add( model.scene )
// only change url when loading *another* file
fragment = fragment || defaultFragment || ''
xrf.navigator.pushState( URI.external ? URI.URN + URI.file : URI.file, fragment.replace(/^#/,'') )
//if( fragment ) xrf.navigator.updateHash(fragment)
xrf.emit('navigateLoaded',{url,model})
xrf.loadModel(model,url)
resolve(model)
}
@ -2994,6 +3000,7 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
element.addEventListener( 'mousemove', onPointerEvent );
element.addEventListener( 'click', onPointerEvent );
element.addEventListener( 'mouseup', onPointerEvent );
element.addEventListener( 'touchstart', onPointerEvent );
// WebXR Controller Events
// TODO: Dispatch pointerevents too
@ -3001,6 +3008,7 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
const eventsMapper = {
'move': 'mousemove',
'select': 'click',
'touchstart': 'click',
'selectstart': 'mousedown',
'selectend': 'mouseup'
};
@ -3949,7 +3957,7 @@ xrf.portalNonEuclidian = function(opts){
if( mesh.userData.XRF.href ){
raycaster.far = 0.35
raycaster.set(cameraPosition, cameraDirection )
intersects = raycaster.intersectObjects([mesh], false)
let intersects = raycaster.intersectObjects([mesh], false)
if (intersects.length > 0 && !mesh.portal.teleporting ){
mesh.portal.teleporting = true
mesh.userData.XRF.href.exec({nocommit:true})
@ -4845,7 +4853,7 @@ AFRAME.registerComponent('xrf-gaze',{
}
},
setGazer: function(state, fuse){
if( !AFRAME.utils.device.isMobile() ) return
if( this.el.sceneEl.getAttribute("xrf-gaze-always") == undefined && !AFRAME.utils.device.isMobile() ) return
let cam = document.querySelector("[camera]")
if( state ){
if( cam.innerHTML.match(/cursor/) ) return; // avoid duplicate calls

45733
dist/xrfragment.module.js vendored

File diff suppressed because it is too large Load Diff

View File

@ -357,7 +357,7 @@ window.accessibility = (opts) => new Proxy({
setTimeout( () => this.initCommands(), 200 )
// auto-enable if previously enabled
if( window.localStorage.getItem("accessibility") === 'true' ){
if( window.localStorage.getItem("accessibility") === 'true' || xrf.navigator.URI.XRF.accessible ){
setTimeout( () => {
this.enabled = true
this.setFontSize()
@ -437,7 +437,6 @@ window.accessibility = (opts) => new Proxy({
switch( k ){
case "enabled": {
let message = "accessibility mode has been "+(v?"activated":"disabled")+".<br>Type /help for help."
if( v ) message = "<img src='https://i.imgur.com/wedtUSs.png' style='width:100%;border-radius:6px'/><br>" + message
$('#accessibility.btn').style.filter= v ? 'brightness(1.0)' : 'brightness(0.5)'
if( v ) $chat.visible = true
$chat.send({message,class:['info']})
@ -467,8 +466,8 @@ document.addEventListener('$menu:ready', (e) => {
document.querySelector('head').innerHTML += `
<style type="text/css">
.accessibility #messages * {
font-size:24px !important;
line-height:40px;
font-size:20px !important;
line-height:35px;
}
.accessibility #messages .msg.self {
background:var(--xrf-gray);
@ -682,8 +681,7 @@ window.frontend = (opts) => new Proxy({
let root = data.mesh.portal ? data.mesh.portal.stencilObject : data.mesh
let transcript = xrf.sceneToTranscript(root,data.mesh)
if( transcript.length ) html += `<br><b>transcript:</b><br><div class="transcript">${transcript}</div>`
if (hasMeta && !data.mesh.portal ) html += `<br><br><a class="btn" style="float:right" onclick="xrf.navigator.to('${data.mesh.userData.href}')">Visit embedded scene</a>`
if (hasMeta && !data.mesh.portal && metadata.XRF.src ) html += `<br><br><a class="btn" style="float:right" onclick="xrf.navigator.to('${data.mesh.userData.href}')">Visit embedded scene</a>`
window.notify(html,{timeout: 7000 * (hasMeta ? 1.5 : 1) })
})
@ -694,7 +692,6 @@ window.frontend = (opts) => new Proxy({
setupNetworkListeners(){
document.addEventListener('network.connect', (e) => {
console.log("network.connect")
window.notify("🪐 connecting to awesomeness..")
$chat.send({message:`🪐 connecting to awesomeness..`,class:['info'], timeout:5000})
})

View File

@ -660,8 +660,8 @@ chatComponent.css = `
/*
display: flex;
flex-direction: column;
width: 91%;
max-width: 500px;
width: 100%;
max-width: 40%;
*/
width:100%;
box-sizing:border-box;
@ -816,8 +816,8 @@ chatComponent.css = `
.envelope{
margin-right:15px;
width:50%;
max-width:700px;
width:100%;
max-width:40%;
}
.envelope,

View File

@ -1,5 +1,5 @@
/*
* v0.5.1 generated at Wed Jun 12 08:50:44 AM UTC 2024
* v0.5.1 generated at Sat Jun 15 05:22:38 PM CEST 2024
* https://xrfragment.org
* SPDX-License-Identifier: MPL-2.0
*/
@ -1940,6 +1940,39 @@ xrf.parseModel = function(model,url){
xrf.emit('parseModel',{model,url,file})
}
xrf.loadModel = function(model,url,noadd){
let URI = xrfragment.URI.toAbsolute( xrf.navigator.URI, url )
let {directory,file,fragment,fileExt} = URI;
model.file = URI.file
xrf.model = model
if( !model.isXRF ) xrf.parseModel(model,url.replace(directory,"")) // this marks the model as an XRF model
if(xrf.debug ) model.animations.map( (a) => console.log("anim: "+a.name) )
// spec: 1. generate the XRWG
xrf.XRWG.generate({model,scene:model.scene})
// spec: 2. init metadata inside model for non-SRC data
if( !model.isSRC ){
model.scene.traverse( (mesh) => xrf.parseModel.metadataInMesh(mesh,model) )
}
// spec: 1. execute the default predefined view '#' (if exist) (https://xrfragment.org/#predefined_view)
const defaultFragment = xrf.frag.defaultPredefinedViews({model,scene:model.scene})
// spec: predefined view(s) & objects-of-interest-in-XRWG from URI (https://xrfragment.org/#predefined_view)
let frag = xrf.hashbus.pub( url, model) // and eval URI XR fragments
if( !noadd ) xrf.add( model.scene )
// only change url when loading *another* file
fragment = fragment || defaultFragment || ''
xrf.navigator.pushState( URI.external ? URI.URN + URI.file : URI.file, fragment.replace(/^#/,'') )
//if( fragment ) xrf.navigator.updateHash(fragment)
xrf.emit('navigateLoaded',{url,model})
}
xrf.parseModel.metadataInMesh = (mesh,model) => {
if( mesh.userData ){
let frag = {}
@ -2063,34 +2096,7 @@ xrf.navigator.to = (url,flags,loader,data) => {
loader = loader || new Loader().setPath( URI.URN )
const onLoad = (model) => {
model.file = URI.file
xrf.model = model
if( !model.isXRF ) xrf.parseModel(model,url.replace(directory,"")) // this marks the model as an XRF model
if(xrf.debug ) model.animations.map( (a) => console.log("anim: "+a.name) )
// spec: 1. generate the XRWG
xrf.XRWG.generate({model,scene:model.scene})
// spec: 2. init metadata inside model for non-SRC data
if( !model.isSRC ){
model.scene.traverse( (mesh) => xrf.parseModel.metadataInMesh(mesh,model) )
}
// spec: 1. execute the default predefined view '#' (if exist) (https://xrfragment.org/#predefined_view)
const defaultFragment = xrf.frag.defaultPredefinedViews({model,scene:model.scene})
// spec: predefined view(s) & objects-of-interest-in-XRWG from URI (https://xrfragment.org/#predefined_view)
let frag = xrf.hashbus.pub( url, model) // and eval URI XR fragments
xrf.add( model.scene )
// only change url when loading *another* file
fragment = fragment || defaultFragment || ''
xrf.navigator.pushState( URI.external ? URI.URN + URI.file : URI.file, fragment.replace(/^#/,'') )
//if( fragment ) xrf.navigator.updateHash(fragment)
xrf.emit('navigateLoaded',{url,model})
xrf.loadModel(model,url)
resolve(model)
}
@ -2994,6 +3000,7 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
element.addEventListener( 'mousemove', onPointerEvent );
element.addEventListener( 'click', onPointerEvent );
element.addEventListener( 'mouseup', onPointerEvent );
element.addEventListener( 'touchstart', onPointerEvent );
// WebXR Controller Events
// TODO: Dispatch pointerevents too
@ -3001,6 +3008,7 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
const eventsMapper = {
'move': 'mousemove',
'select': 'click',
'touchstart': 'click',
'selectstart': 'mousedown',
'selectend': 'mouseup'
};
@ -3949,7 +3957,7 @@ xrf.portalNonEuclidian = function(opts){
if( mesh.userData.XRF.href ){
raycaster.far = 0.35
raycaster.set(cameraPosition, cameraDirection )
intersects = raycaster.intersectObjects([mesh], false)
let intersects = raycaster.intersectObjects([mesh], false)
if (intersects.length > 0 && !mesh.portal.teleporting ){
mesh.portal.teleporting = true
mesh.userData.XRF.href.exec({nocommit:true})

View File

@ -1,5 +1,5 @@
/*
* v0.5.1 generated at Wed Jun 12 08:50:44 AM UTC 2024
* v0.5.1 generated at Sat Jun 15 05:22:38 PM CEST 2024
* https://xrfragment.org
* SPDX-License-Identifier: MPL-2.0
*/
@ -1940,6 +1940,39 @@ xrf.parseModel = function(model,url){
xrf.emit('parseModel',{model,url,file})
}
xrf.loadModel = function(model,url,noadd){
let URI = xrfragment.URI.toAbsolute( xrf.navigator.URI, url )
let {directory,file,fragment,fileExt} = URI;
model.file = URI.file
xrf.model = model
if( !model.isXRF ) xrf.parseModel(model,url.replace(directory,"")) // this marks the model as an XRF model
if(xrf.debug ) model.animations.map( (a) => console.log("anim: "+a.name) )
// spec: 1. generate the XRWG
xrf.XRWG.generate({model,scene:model.scene})
// spec: 2. init metadata inside model for non-SRC data
if( !model.isSRC ){
model.scene.traverse( (mesh) => xrf.parseModel.metadataInMesh(mesh,model) )
}
// spec: 1. execute the default predefined view '#' (if exist) (https://xrfragment.org/#predefined_view)
const defaultFragment = xrf.frag.defaultPredefinedViews({model,scene:model.scene})
// spec: predefined view(s) & objects-of-interest-in-XRWG from URI (https://xrfragment.org/#predefined_view)
let frag = xrf.hashbus.pub( url, model) // and eval URI XR fragments
if( !noadd ) xrf.add( model.scene )
// only change url when loading *another* file
fragment = fragment || defaultFragment || ''
xrf.navigator.pushState( URI.external ? URI.URN + URI.file : URI.file, fragment.replace(/^#/,'') )
//if( fragment ) xrf.navigator.updateHash(fragment)
xrf.emit('navigateLoaded',{url,model})
}
xrf.parseModel.metadataInMesh = (mesh,model) => {
if( mesh.userData ){
let frag = {}
@ -2063,34 +2096,7 @@ xrf.navigator.to = (url,flags,loader,data) => {
loader = loader || new Loader().setPath( URI.URN )
const onLoad = (model) => {
model.file = URI.file
xrf.model = model
if( !model.isXRF ) xrf.parseModel(model,url.replace(directory,"")) // this marks the model as an XRF model
if(xrf.debug ) model.animations.map( (a) => console.log("anim: "+a.name) )
// spec: 1. generate the XRWG
xrf.XRWG.generate({model,scene:model.scene})
// spec: 2. init metadata inside model for non-SRC data
if( !model.isSRC ){
model.scene.traverse( (mesh) => xrf.parseModel.metadataInMesh(mesh,model) )
}
// spec: 1. execute the default predefined view '#' (if exist) (https://xrfragment.org/#predefined_view)
const defaultFragment = xrf.frag.defaultPredefinedViews({model,scene:model.scene})
// spec: predefined view(s) & objects-of-interest-in-XRWG from URI (https://xrfragment.org/#predefined_view)
let frag = xrf.hashbus.pub( url, model) // and eval URI XR fragments
xrf.add( model.scene )
// only change url when loading *another* file
fragment = fragment || defaultFragment || ''
xrf.navigator.pushState( URI.external ? URI.URN + URI.file : URI.file, fragment.replace(/^#/,'') )
//if( fragment ) xrf.navigator.updateHash(fragment)
xrf.emit('navigateLoaded',{url,model})
xrf.loadModel(model,url)
resolve(model)
}
@ -2994,6 +3000,7 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
element.addEventListener( 'mousemove', onPointerEvent );
element.addEventListener( 'click', onPointerEvent );
element.addEventListener( 'mouseup', onPointerEvent );
element.addEventListener( 'touchstart', onPointerEvent );
// WebXR Controller Events
// TODO: Dispatch pointerevents too
@ -3001,6 +3008,7 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
const eventsMapper = {
'move': 'mousemove',
'select': 'click',
'touchstart': 'click',
'selectstart': 'mousedown',
'selectend': 'mouseup'
};
@ -3949,7 +3957,7 @@ xrf.portalNonEuclidian = function(opts){
if( mesh.userData.XRF.href ){
raycaster.far = 0.35
raycaster.set(cameraPosition, cameraDirection )
intersects = raycaster.intersectObjects([mesh], false)
let intersects = raycaster.intersectObjects([mesh], false)
if (intersects.length > 0 && !mesh.portal.teleporting ){
mesh.portal.teleporting = true
mesh.userData.XRF.href.exec({nocommit:true})

View File

@ -16,8 +16,9 @@
<body>
<a-scene xr-mode-ui="XRMode: xr"
renderer="colorManagement: false; antialias:true; highRefreshRate:true; foveationLevel: 0.5; toneMapping: ACESFilmic; exposure: 3.0"
device-orientation-permission-ui
light="defaultLightsEnabled: false">
<a-entity id="player" movement-controls touch-controls wasd-controls="fly:false" look-controls>
<a-entity id="player" movement-controls touch-controls wasd-controls="fly:false" look-controls="magicWindowTrackingEnabled:true">
<a-entity camera="fov:90" position="0 1.6 0" id="camera"></a-entity>
<a-entity id="left-hand" hand-tracking-grab-controls="hand:left;modelColor:#cccccc" raycaster="objects:.ray" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: .floor">
<a-entity rotation="-35 0 0" position="0 0.1 0" id="navigator">
@ -69,6 +70,7 @@
<br><br>
`,{timeout:false})
})
</script>

View File

@ -12,7 +12,7 @@ AFRAME.registerComponent('xrf-gaze',{
}
},
setGazer: function(state, fuse){
if( !AFRAME.utils.device.isMobile() ) return
if( this.el.sceneEl.getAttribute("xrf-gaze-always") == undefined && !AFRAME.utils.device.isMobile() ) return
let cam = document.querySelector("[camera]")
if( state ){
if( cam.innerHTML.match(/cursor/) ) return; // avoid duplicate calls

View File

@ -275,8 +275,8 @@ chatComponent.css = `
/*
display: flex;
flex-direction: column;
width: 91%;
max-width: 500px;
width: 100%;
max-width: 40%;
*/
width:100%;
box-sizing:border-box;
@ -431,8 +431,8 @@ chatComponent.css = `
.envelope{
margin-right:15px;
width:50%;
max-width:700px;
width:100%;
max-width:40%;
}
.envelope,

View File

@ -105,7 +105,7 @@ window.accessibility = (opts) => new Proxy({
setTimeout( () => this.initCommands(), 200 )
// auto-enable if previously enabled
if( window.localStorage.getItem("accessibility") === 'true' ){
if( window.localStorage.getItem("accessibility") === 'true' || xrf.navigator.URI.XRF.accessible ){
setTimeout( () => {
this.enabled = true
this.setFontSize()
@ -185,7 +185,6 @@ window.accessibility = (opts) => new Proxy({
switch( k ){
case "enabled": {
let message = "accessibility mode has been "+(v?"activated":"disabled")+".<br>Type /help for help."
if( v ) message = "<img src='https://i.imgur.com/wedtUSs.png' style='width:100%;border-radius:6px'/><br>" + message
$('#accessibility.btn').style.filter= v ? 'brightness(1.0)' : 'brightness(0.5)'
if( v ) $chat.visible = true
$chat.send({message,class:['info']})
@ -215,8 +214,8 @@ document.addEventListener('$menu:ready', (e) => {
document.querySelector('head').innerHTML += `
<style type="text/css">
.accessibility #messages * {
font-size:24px !important;
line-height:40px;
font-size:20px !important;
line-height:35px;
}
.accessibility #messages .msg.self {
background:var(--xrf-gray);

View File

@ -122,8 +122,7 @@ window.frontend = (opts) => new Proxy({
let root = data.mesh.portal ? data.mesh.portal.stencilObject : data.mesh
let transcript = xrf.sceneToTranscript(root,data.mesh)
if( transcript.length ) html += `<br><b>transcript:</b><br><div class="transcript">${transcript}</div>`
if (hasMeta && !data.mesh.portal ) html += `<br><br><a class="btn" style="float:right" onclick="xrf.navigator.to('${data.mesh.userData.href}')">Visit embedded scene</a>`
if (hasMeta && !data.mesh.portal && metadata.XRF.src ) html += `<br><br><a class="btn" style="float:right" onclick="xrf.navigator.to('${data.mesh.userData.href}')">Visit embedded scene</a>`
window.notify(html,{timeout: 7000 * (hasMeta ? 1.5 : 1) })
})
@ -134,7 +133,6 @@ window.frontend = (opts) => new Proxy({
setupNetworkListeners(){
document.addEventListener('network.connect', (e) => {
console.log("network.connect")
window.notify("🪐 connecting to awesomeness..")
$chat.send({message:`🪐 connecting to awesomeness..`,class:['info'], timeout:5000})
})

View File

@ -85,6 +85,7 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
element.addEventListener( 'mousemove', onPointerEvent );
element.addEventListener( 'click', onPointerEvent );
element.addEventListener( 'mouseup', onPointerEvent );
element.addEventListener( 'touchstart', onPointerEvent );
// WebXR Controller Events
// TODO: Dispatch pointerevents too
@ -92,6 +93,7 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
const eventsMapper = {
'move': 'mousemove',
'select': 'click',
'touchstart': 'click',
'selectstart': 'mousedown',
'selectend': 'mouseup'
};