Compare commits

..

No commits in common. "2bc664af0291d33747745ee847836d5bbb004d7b" and "777966a435d4646b4b07d0a8d57bc2b54fe06f1d" have entirely different histories.

16 changed files with 100 additions and 29604 deletions

File diff suppressed because one or more lines are too long

View file

@ -1,73 +1,3 @@
/*
* v0.5.1 generated at Tue Feb 11 11:52:02 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:50:30 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:48:23 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:47:08 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:46:37 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:44:59 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:44:48 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:44:30 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:44:14 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:43:32 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:42:47 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:27:52 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Mon Feb 10 08:18:55 PM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Mon Feb 10 08:05:14 PM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/* /*
* v0.5.1 generated at Sun Feb 9 12:52:39 PM CET 2025 * v0.5.1 generated at Sun Feb 9 12:52:39 PM CET 2025
* https://xrfragment.org * https://xrfragment.org
@ -2115,6 +2045,7 @@ var xrf = {}
xrf.init = function(opts){ xrf.init = function(opts){
opts = opts || {} opts = opts || {}
xrf.debug = document.location.hostname.match(/^(localhost|[0-9]\.[0-9])/) || document.location.port == '8080' ? 0 : false xrf.debug = document.location.hostname.match(/^(localhost|[0-9]\.[0-9])/) || document.location.port == '8080' ? 0 : false
if( document.location.hash.match(/debug=([0-9])/) ){ if( document.location.hash.match(/debug=([0-9])/) ){
xrf.debug = parseInt( ( document.location.hash.match(/debug=([0-9])/) || [0,'0'] )[1] ) xrf.debug = parseInt( ( document.location.hash.match(/debug=([0-9])/) || [0,'0'] )[1] )
@ -3772,28 +3703,16 @@ xrf.optimize.removeDuplicateLights = () => {
xrf.addEventListener('parseModel', (opts) => { xrf.addEventListener('parseModel', (opts) => {
xrf.optimize(opts) xrf.optimize(opts)
}) })
xrf.sceneToTranscript = (scene, node, currentPosition ) => { xrf.sceneToTranscript = (scene, ignoreMesh ) => {
let items = [] let transcript = ''
scene = currentPosition && xrf.frag.pos.last ? xrf.scene.getObjectByName(xrf.frag.pos.last) : (scene || xrf.scene)
scene.traverse( (n) => { scene.traverse( (n) => {
let isSRC = false let isSRC = false
n.traverseAncestors( (m) => m.userData.src ? isSRC = true : false ) n.traverseAncestors( (m) => m.userData.src ? isSRC = true : false )
if( !isSRC && n.userData['aria-description'] && (!node || n.uuid != node.uuid) ){ if( !isSRC && n.userData['aria-description'] && (!ignoreMesh || n.uuid != ignoreMesh.uuid) ){
items.push({name: n.name, description: n.userData['aria-description']}) transcript += `<b>#${n.name}</b> ${n.userData['aria-description']}. `
} }
}) })
return items return transcript
}
xrf.listExits = (scene, currentPosition ) => {
let destinations = []
scene = currentPosition && xrf.frag.pos.last ? xrf.scene.getObjectByName(xrf.frag.pos.last) : scene || xrf.scene
scene.traverse( (n) => {
if( n.userData && n.userData.href && n.userData.href.match(/pos=/) ){
destinations.push({name: n.name, destination: n.userData['aria-label'] || n.userData.href})
}
})
return destinations
} }
// switch camera when multiple cameras for url #mycameraname // switch camera when multiple cameras for url #mycameraname
@ -5676,7 +5595,6 @@ AFRAME.registerSystem('xrf-hands',{
// wait for bones get initialized // wait for bones get initialized
setTimeout( () => { setTimeout( () => {
let bones = handEl.components['hand-tracking-controls'].bones let bones = handEl.components['hand-tracking-controls'].bones
if( !bones ) return // dont bother
let indexFinger let indexFinger
for( let j = 0; j < bones.length; j++){ for( let j = 0; j < bones.length; j++){
if( bones[j].name == "index-finger-tip" ){ if( bones[j].name == "index-finger-tip" ){

70
dist/xrfragment.js vendored
View file

@ -1,73 +1,3 @@
/*
* v0.5.1 generated at Tue Feb 11 11:52:02 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:50:30 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:48:23 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:47:08 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:46:37 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:44:59 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:44:48 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:44:30 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:44:14 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:43:32 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:42:47 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:27:52 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Mon Feb 10 08:18:55 PM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Mon Feb 10 08:05:14 PM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/* /*
* v0.5.1 generated at Sun Feb 9 12:52:39 PM CET 2025 * v0.5.1 generated at Sun Feb 9 12:52:39 PM CET 2025
* https://xrfragment.org * https://xrfragment.org

File diff suppressed because one or more lines are too long

28973
dist/xrfragment.module.js vendored

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/* /*
* v0.5.1 generated at Tue Feb 11 11:52:02 AM CET 2025 * v0.5.1 generated at Sun Feb 9 12:52:39 PM CET 2025
* https://xrfragment.org * https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later * SPDX-License-Identifier: AGPL-3.0-or-later
*/ */

View file

@ -1,5 +1,5 @@
/* /*
* v0.5.1 generated at Tue Feb 11 11:52:02 AM CET 2025 * v0.5.1 generated at Sun Feb 9 12:52:39 PM CET 2025
* https://xrfragment.org * https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later * SPDX-License-Identifier: AGPL-3.0-or-later
*/ */

View file

@ -1,5 +1,5 @@
/* /*
* v0.5.1 generated at Tue Feb 11 11:52:02 AM CET 2025 * v0.5.1 generated at Sun Feb 9 12:52:39 PM CET 2025
* https://xrfragment.org * https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later * SPDX-License-Identifier: AGPL-3.0-or-later
*/ */
@ -374,9 +374,9 @@ window.accessibility = (opts) => new Proxy({
notify(`${n.userData['aria-description']||''}` + (n.userData.href ? `<br><b>name:</b> ${n.name}<br><b>href:</b> ${n.userData['href']}` :'') ) notify(`${n.userData['aria-description']||''}` + (n.userData.href ? `<br><b>name:</b> ${n.name}<br><b>href:</b> ${n.userData['href']}` :'') )
} }
//if( e.key == 'Enter' && objects[cache.current]?.userData.href ){ if( e.key == 'Enter' && objects[cache.current].userData.href ){
// xrf.navigator.to( objects[cache.current].userData.href ) xrf.navigator.to( objects[cache.current].userData.href )
//} }
// increment to next // increment to next
cache.current = (cache.current + 1) % objects.length cache.current = (cache.current + 1) % objects.length
@ -770,13 +770,7 @@ window.frontend = (opts) => new Proxy({
} }
let root = data.mesh.portal ? data.mesh.portal.stencilObject : data.mesh let root = data.mesh.portal ? data.mesh.portal.stencilObject : data.mesh
let transcript = xrf.sceneToTranscript(root,data.mesh) let transcript = xrf.sceneToTranscript(root,data.mesh)
console.dir(transcript) if( transcript.length ) html += `<br><b>transcript:</b><br><div class="transcript">${transcript}</div>`
if( transcript.length ){
transcript = xrf.sceneToTranscript(false,false,true)
.map( (n) => `<b>${n.name}</b> ${n.description}` )
.join(". ")
html += `<br><b>transcript:</b><br><div class="transcript">${transcript}</div>`
}
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>` 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>`
if( !html ) return if( !html ) return
@ -1055,7 +1049,12 @@ document.addEventListener('chat.command.help', (e) => {
const listExits = (scene) => { const listExits = (scene) => {
let message = '' let message = ''
let destinations = xrf.sceneListExits(scene, true) let destinations = {}
scene.traverse( (n) => {
if( n.userData && n.userData.href && n.userData.href.match(/pos=/) ){
destinations[n.name] = n.userData['aria-label'] || n.userData.href
}
})
for( let destination in destinations ){ for( let destination in destinations ){
message += `<br><b class="badge">${destination}</b> ${destinations[destination]}` message += `<br><b class="badge">${destination}</b> ${destinations[destination]}`
} }
@ -1086,13 +1085,8 @@ document.addEventListener('chat.input', (e) => {
} }
if( e.detail.message.trim() == 'look' ){ if( e.detail.message.trim() == 'look' ){
let transcript = xrf.sceneToTranscript(false,false,true) let scene = xrf.frag.pos.last ? xrf.scene.getObjectByName(xrf.frag.pos.last) : xrf.scene
.map( (n) => `<b>${n.name}</b> ${n.description}` ) let message = `<div class="transcript">${xrf.sceneToTranscript(scene)}</div><br>possible destinations in this area:${listExits(scene)}`
.join(". ")
let exits = xrf.listExits(false,true)
.map( (n) => `<b>${n.name}</b>` )
.join("<br>")
let message = `<div class="transcript">${transcript}</div><br>possible destinations in this area:<br>${exits}`
e.detail.halt = true // dont print command to screen e.detail.halt = true // dont print command to screen
$chat.send({message}) $chat.send({message})
} }
@ -1282,56 +1276,4 @@ function createJoystick() {
} }
} }
}); });
window.hrefCycle = (e) => {
if( !xrf || !xrf.scene || e.key != "Tab" && e.key != "Enter" ) return
console.log("ja")
let subScene = xrf.scene.getObjectByName( xrf.frag.pos.last )
if( !subScene ) subScene = xrf.scene
let cache = window.hrefCycle.cache = window.hrefCycle.cache || {current: -1}
let objects = []
subScene.traverse( (n) => (n.userData.href || n.userData['aria-description']) && objects.push(n) )
const highlight = (n) => {
if( this.helper){
if( this.helper.selected == n.uuid ) return // already selected
xrf.scene.remove(this.helper)
}
this.selected = n
this.helper = new THREE.BoxHelper( n, 0xFF00FF )
this.helper.computeLineDistances()
this.helper.material.linewidth = 8
this.helper.material.color = xrf.focusLine.material.color
this.helper.material.dashSize = xrf.focusLine.material.dashSize
this.helper.material.gapSize = xrf.focusLine.material.gapSize
this.helper.selected = n.uuid
xrf.scene.add(this.helper)
const isAction = n.userData.href
if( typeof notify != 'undefined'){
notify(`${n.userData['aria-description']||''}` + (n.userData.href ? `<br><b>name:</b> ${n.name}<br><b>href:</b> ${n.userData['href']}` :'') )
}
if( typeof term != 'undefined'){
term.send(`\n\r${isAction?'press enter for option ':''}${n.userData['aria-description']||n.userData['aria-label']||n.name}`)
}
}
if( e.key == 'Enter' && objects[cache.current]?.userData.href ){
xrf.navigator.to( objects[cache.current].userData.href )
}
// increment to next
cache.current = (cache.current + 1) % objects.length
if( e.key == 'Tab'){
highlight( objects[cache.current] )
}
e.preventDefault()
return false
}
window.addEventListener('keydown', window.hrefCycle )
}).apply({}) }).apply({})

View file

@ -1,5 +1,5 @@
/* /*
* v0.5.1 generated at Tue Feb 11 11:52:03 AM CET 2025 * v0.5.1 generated at Sun Feb 9 12:52:39 PM CET 2025
* https://xrfragment.org * https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later * SPDX-License-Identifier: AGPL-3.0-or-later
*/ */

View file

@ -1,5 +1,5 @@
/* /*
* v0.5.1 generated at Tue Feb 11 11:52:03 AM CET 2025 * v0.5.1 generated at Sun Feb 9 12:52:39 PM CET 2025
* https://xrfragment.org * https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later * SPDX-License-Identifier: AGPL-3.0-or-later
*/ */
@ -652,7 +652,6 @@ chatComponent.css = `
max-width: 20px; max-width: 20px;
border-radius: 20px 0px 0px 20px; border-radius: 20px 0px 0px 20px;
overflow: hidden; overflow: hidden;
margin:0;
} }
#chatbar input{ #chatbar input{
border:none; border:none;

View file

@ -1,5 +1,5 @@
/* /*
* v0.5.1 generated at Tue Feb 11 11:52:03 AM CET 2025 * v0.5.1 generated at Sun Feb 9 12:52:39 PM CET 2025
* https://xrfragment.org * https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later * SPDX-License-Identifier: AGPL-3.0-or-later
*/ */

View file

@ -1,73 +1,3 @@
/*
* v0.5.1 generated at Tue Feb 11 11:52:03 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:50:30 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:48:23 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:47:08 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:46:37 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:44:59 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:44:48 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:44:30 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:44:14 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:43:32 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:42:47 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:27:52 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Mon Feb 10 08:18:55 PM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Mon Feb 10 08:05:14 PM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/* /*
* v0.5.1 generated at Sun Feb 9 12:52:39 PM CET 2025 * v0.5.1 generated at Sun Feb 9 12:52:39 PM CET 2025
* https://xrfragment.org * https://xrfragment.org
@ -2115,6 +2045,7 @@ var xrf = {}
xrf.init = function(opts){ xrf.init = function(opts){
opts = opts || {} opts = opts || {}
xrf.debug = document.location.hostname.match(/^(localhost|[0-9]\.[0-9])/) || document.location.port == '8080' ? 0 : false xrf.debug = document.location.hostname.match(/^(localhost|[0-9]\.[0-9])/) || document.location.port == '8080' ? 0 : false
if( document.location.hash.match(/debug=([0-9])/) ){ if( document.location.hash.match(/debug=([0-9])/) ){
xrf.debug = parseInt( ( document.location.hash.match(/debug=([0-9])/) || [0,'0'] )[1] ) xrf.debug = parseInt( ( document.location.hash.match(/debug=([0-9])/) || [0,'0'] )[1] )
@ -3772,28 +3703,16 @@ xrf.optimize.removeDuplicateLights = () => {
xrf.addEventListener('parseModel', (opts) => { xrf.addEventListener('parseModel', (opts) => {
xrf.optimize(opts) xrf.optimize(opts)
}) })
xrf.sceneToTranscript = (scene, node, currentPosition ) => { xrf.sceneToTranscript = (scene, ignoreMesh ) => {
let items = [] let transcript = ''
scene = currentPosition && xrf.frag.pos.last ? xrf.scene.getObjectByName(xrf.frag.pos.last) : (scene || xrf.scene)
scene.traverse( (n) => { scene.traverse( (n) => {
let isSRC = false let isSRC = false
n.traverseAncestors( (m) => m.userData.src ? isSRC = true : false ) n.traverseAncestors( (m) => m.userData.src ? isSRC = true : false )
if( !isSRC && n.userData['aria-description'] && (!node || n.uuid != node.uuid) ){ if( !isSRC && n.userData['aria-description'] && (!ignoreMesh || n.uuid != ignoreMesh.uuid) ){
items.push({name: n.name, description: n.userData['aria-description']}) transcript += `<b>#${n.name}</b> ${n.userData['aria-description']}. `
} }
}) })
return items return transcript
}
xrf.listExits = (scene, currentPosition ) => {
let destinations = []
scene = currentPosition && xrf.frag.pos.last ? xrf.scene.getObjectByName(xrf.frag.pos.last) : scene || xrf.scene
scene.traverse( (n) => {
if( n.userData && n.userData.href && n.userData.href.match(/pos=/) ){
destinations.push({name: n.name, destination: n.userData['aria-label'] || n.userData.href})
}
})
return destinations
} }
// switch camera when multiple cameras for url #mycameraname // switch camera when multiple cameras for url #mycameraname

View file

@ -1,73 +1,3 @@
/*
* v0.5.1 generated at Tue Feb 11 11:52:03 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:50:30 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:48:23 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:47:08 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:46:37 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:44:59 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:44:48 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:44:30 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:44:14 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:43:32 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:42:47 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Tue Feb 11 11:27:52 AM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Mon Feb 10 08:18:55 PM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/*
* v0.5.1 generated at Mon Feb 10 08:05:14 PM CET 2025
* https://xrfragment.org
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/* /*
* v0.5.1 generated at Sun Feb 9 12:52:39 PM CET 2025 * v0.5.1 generated at Sun Feb 9 12:52:39 PM CET 2025
* https://xrfragment.org * https://xrfragment.org
@ -2115,6 +2045,7 @@ var xrf = {}
xrf.init = function(opts){ xrf.init = function(opts){
opts = opts || {} opts = opts || {}
xrf.debug = document.location.hostname.match(/^(localhost|[0-9]\.[0-9])/) || document.location.port == '8080' ? 0 : false xrf.debug = document.location.hostname.match(/^(localhost|[0-9]\.[0-9])/) || document.location.port == '8080' ? 0 : false
if( document.location.hash.match(/debug=([0-9])/) ){ if( document.location.hash.match(/debug=([0-9])/) ){
xrf.debug = parseInt( ( document.location.hash.match(/debug=([0-9])/) || [0,'0'] )[1] ) xrf.debug = parseInt( ( document.location.hash.match(/debug=([0-9])/) || [0,'0'] )[1] )
@ -3772,28 +3703,16 @@ xrf.optimize.removeDuplicateLights = () => {
xrf.addEventListener('parseModel', (opts) => { xrf.addEventListener('parseModel', (opts) => {
xrf.optimize(opts) xrf.optimize(opts)
}) })
xrf.sceneToTranscript = (scene, node, currentPosition ) => { xrf.sceneToTranscript = (scene, ignoreMesh ) => {
let items = [] let transcript = ''
scene = currentPosition && xrf.frag.pos.last ? xrf.scene.getObjectByName(xrf.frag.pos.last) : (scene || xrf.scene)
scene.traverse( (n) => { scene.traverse( (n) => {
let isSRC = false let isSRC = false
n.traverseAncestors( (m) => m.userData.src ? isSRC = true : false ) n.traverseAncestors( (m) => m.userData.src ? isSRC = true : false )
if( !isSRC && n.userData['aria-description'] && (!node || n.uuid != node.uuid) ){ if( !isSRC && n.userData['aria-description'] && (!ignoreMesh || n.uuid != ignoreMesh.uuid) ){
items.push({name: n.name, description: n.userData['aria-description']}) transcript += `<b>#${n.name}</b> ${n.userData['aria-description']}. `
} }
}) })
return items return transcript
}
xrf.listExits = (scene, currentPosition ) => {
let destinations = []
scene = currentPosition && xrf.frag.pos.last ? xrf.scene.getObjectByName(xrf.frag.pos.last) : scene || xrf.scene
scene.traverse( (n) => {
if( n.userData && n.userData.href && n.userData.href.match(/pos=/) ){
destinations.push({name: n.name, destination: n.userData['aria-label'] || n.userData.href})
}
})
return destinations
} }
// switch camera when multiple cameras for url #mycameraname // switch camera when multiple cameras for url #mycameraname

View file

@ -31,12 +31,10 @@
</a-entity> </a-entity>
</a-entity> </a-entity>
<a-entity id="right-hand" hand-tracking-grab-controls="hand:right;modelColor:#cccccc" laser-controls="hand: right" raycaster="objects:.ray" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: .floor" xrf-pinchmove="rig: #player"></a-entity> <a-entity id="right-hand" hand-tracking-grab-controls="hand:right;modelColor:#cccccc" laser-controls="hand: right" raycaster="objects:.ray" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: .floor" xrf-pinchmove="rig: #player"></a-entity>
<a-entity isoterminal="width: 600; height:300" position="0 1.0 0.03"></a-entity>
</a-entity> </a-entity>
<a-entity id="home" xrf="./../../assets/elearning.glb"></a-entity> <a-entity id="home" xrf="./../../assets/elearning.glb"></a-entity>
<a-entity isoterminal="width: 600; height:300" position="0 1.6 -0.3"></a-entity>
</a-scene> </a-scene>
<!-- initialize XRSH --> <!-- initialize XRSH -->
@ -45,17 +43,23 @@
const isoterminal = document.querySelector('[isoterminal]').components.isoterminal const isoterminal = document.querySelector('[isoterminal]').components.isoterminal
const sanitizeTranscript = (str) => {
return str
.replaceAll("<[^>]*>", "") // strip html
.split('\n')
.map( (l) => String(l+'.').replace(/(^|:|;|!|\?|\.)\.$/g,'\$1') ) // add dot if needed
.join('. ')
}
const transcriptToText = (t) => t.map( (o) => `${o.name} ${o.description}`).join(" ") const transcriptToText = (t) => t.map( (o) => `${o.name} ${o.description}`).join(" ")
const describeScene = () => { // describe current scene
xrf.addEventListener('navigateLoaded', () => {
let subscene = xrf.frag.pos.last || xrf.navigator.URI.XRF?.pos?.string let subscene = xrf.frag.pos.last || xrf.navigator.URI.XRF?.pos?.string
subscene = subscene ? subscene = xrf.scene.getObjectByName( subscene ) : false subscene = subscene ? subscene = xrf.scene.getObjectByName( subscene ) : false
let transcript = transcriptToText( xrf.sceneToTranscript(subscene) ) let transcript = transcriptToText( xrf.sceneToTranscript(subscene) )
term.send(`\r${transcript}\n\n\r`) term.send(`\r${transcript}\n\r`)
} })
// describe current scene
xrf.addEventListener('navigateLoaded', () => setTimeout( () => describeScene(),100) )
isoterminal.el.addEventListener('init', () => { isoterminal.el.addEventListener('init', () => {
// clear bootmenu-array // clear bootmenu-array
@ -67,32 +71,25 @@
// describe mouseover button (and scene to be teleported to, if any) // describe mouseover button (and scene to be teleported to, if any)
xrf.addEventListener('href', (e) => { xrf.addEventListener('href', (e) => {
if( !e.selected || !e.mesh ) return; // only process mouse-overs if( typeof e.selected == 'undefined' || !e.mesh ) return; // only process mouse-overs
let name = "object" let name = "object"
let info = "" let info = ""
let subscene = false let subscene = false
if( e.click ){
return setTimeout( () => {
if( lastPos != xrf.frag.pos.last ) return
describeScene()
}, 100 )
lastPos = xrf.frag.pos.last
}
if( e.mesh.userData ){ if( e.mesh.userData ){
if( e.mesh.userData.href && e.mesh.userData.href.match("pos=") ){ if( e.mesh.userData.href && e.mesh.userData.href.match("pos=") ){
name = "action: " name = "action: "
subscene = xrfragment.URI.parse( e.mesh.userData.href ).XRF.pos.string subscene = xrfragment.URI.parse( e.mesh.userData.href ).XRF.pos.string
info = "to "+ subscene
} }
if( e.mesh.userData['aria-label'] ){ if( e.mesh.userData['aria-description'] ){
info = e.mesh.userData['aria-label'] info += "\n\r"+sanitizeTranscript(e.mesh.userData['aria-description'])
}else if( e.mesh.userData['aria-description'] ){ }
info = e.mesh.userData['aria-description'] if( subscene ){
}else if( subscene ){ info += `\n\r${transcriptToText( xrf.sceneToTranscript(subscene,false,true) )}`
info = `${transcriptToText( xrf.sceneToTranscript(subscene,false,true) )}`
} }
if( !info && e.mesh.name ) name = e.mesh.name if( !info && e.mesh.name ) name = e.mesh.name
} }
term.send(`${name} ${info}\n\r`) term.send(`\r\n${name} ${info}\n\r`)
}) })
}) })

Binary file not shown.

File diff suppressed because one or more lines are too long