xrfragment-haxe/src/3rd/js/aframe/index.js

155 lines
6 KiB
JavaScript
Raw Normal View History

2023-05-09 17:42:29 +02:00
window.AFRAME.registerComponent('xrf', {
schema: {
2024-01-03 15:55:23 +00:00
http: { type:'string'},
https: { type:'string'},
2023-05-09 17:42:29 +02:00
},
init: function () {
2024-01-30 09:58:00 +00:00
// override this.data when URL has passed (`://....com/?https://foo.com/index.glb` e.g.)
if( typeof this.data == "string" ){
let searchIsUri = document.location.search &&
!document.location.search.match(/=/) &&
document.location.search.match("://")
if( searchIsUri || document.location.hash.length > 1 ){ // override url
this.data = `${document.location.search.substr(1)}${document.location.hash}`
}
}
if( !AFRAME.XRF ){
2023-11-08 18:28:18 +01:00
2023-11-29 16:45:21 +01:00
let camera = document.querySelector('[camera]')
2023-11-08 18:28:18 +01:00
// start with black
2023-11-29 16:45:21 +01:00
camera.setAttribute('xrf-fade','')
AFRAME.fade = camera.components['xrf-fade']
2023-11-08 18:28:18 +01:00
2024-01-03 15:55:23 +00:00
let aScene = AFRAME.scenes[0]
2024-01-03 15:55:23 +00:00
// enable XR fragments
let XRF = AFRAME.XRF = xrf.init({
THREE,
camera: aScene.camera,
scene: aScene.object3D,
renderer: aScene.renderer,
loaders: {
gltf: THREE.GLTFLoader, // which 3D assets (exts) to check for XR fragments?
glb: THREE.GLTFLoader,
obj: THREE.OBJLoader
}
})
2024-01-31 12:06:14 +00:00
aScene.renderer.toneMapping = THREE.ACESFilmicToneMapping;
aScene.renderer.toneMappingExposure = 1.5;
2024-01-03 15:55:23 +00:00
if( !XRF.camera ) throw 'xrfragment: no camera detected, please declare <a-entity camera..> ABOVE entities with xrf-attributes'
2024-01-03 15:55:23 +00:00
// this is just for convenience (not part of spec): hide/show stuff based on VR/AR tags in 3D model
ARbutton = document.querySelector('.a-enter-ar-button')
VRbutton = document.querySelector('.a-enter-vr-button')
if( ARbutton ) ARbutton.addEventListener('click', () => AFRAME.XRF.hashbus.pub( '#AR' ) )
if( VRbutton ) VRbutton.addEventListener('click', () => AFRAME.XRF.hashbus.pub( '#VR' ) )
aScene.addEventListener('enter-vr', () => {
// sometimes AFRAME resets the user position to 0,0,0 when entering VR (not sure why)
let pos = xrf.frag.pos.last
if( pos ){ AFRAME.XRF.camera.position.set(pos.x, pos.y, pos.z) }
})
xrf.addEventListener('navigateLoaded', (opts) => {
2024-01-03 15:55:23 +00:00
setTimeout( () => AFRAME.fade.out(),500)
let isLocal = opts.url.match(/^#/)
if( isLocal ) return
2024-01-03 15:55:23 +00:00
// *TODO* this does not really belong here perhaps
let blinkControls = document.querySelector('[blink-controls]')
if( blinkControls ){
let els = xrf.getCollisionMeshes()
let invisible = false
els.map( (mesh) => {
if( !invisible ){
invisible = mesh.material.clone()
invisible.visible = false
}
mesh.material = invisible
let el = document.createElement("a-entity")
el.setAttribute("xrf-get", mesh.name )
el.setAttribute("class","floor")
$('a-scene').appendChild(el)
})
2024-01-10 22:01:21 +01:00
let com = blinkControls.components['blink-controls']
if( com ) com.update({collisionEntities:true})
else console.warn("xrfragments: blink-controls is not mounted, please run manually: $('[blink-controls]).components['blink-controls'].update({collisionEntities:true})")
2024-01-03 15:55:23 +00:00
}
// give headset users way to debug without a cumbersome usb-tapdance
if( xrf.debug || document.location.hostname.match(/^(localhost|[1-9])/) && !aScene.getAttribute("vconsole") ){
aScene.setAttribute('vconsole','')
}
2024-01-03 15:55:23 +00:00
})
2023-11-08 18:28:18 +01:00
xrf.addEventListener('navigateLoading', (opts) => {
let p = opts.promise()
let url = opts.url
let isLocal = url.match(/^#/)
let hasPos = url.match(/pos=/)
let fastFadeMs = 200
if( isLocal ){
if( hasPos ){
2024-01-03 15:55:23 +00:00
// local teleports only
AFRAME.fade.in(fastFadeMs)
setTimeout( () => {
p.resolve()
}, fastFadeMs)
}
}else{
AFRAME.fade.in(fastFadeMs)
setTimeout( () => {
p.resolve()
}, AFRAME.fade.data.fadetime )
}
},{weight:-1000})
2024-01-03 15:55:23 +00:00
// convert href's to a-entity's so AFRAME
// raycaster can find & execute it
AFRAME.XRF.clickableMeshToEntity = (opts) => {
let {mesh,clickHandler} = opts;
let el = document.createElement("a-entity")
el.setAttribute("xrf-get",mesh.name ) // turn into AFRAME entity
el.setAttribute("class","ray") // expose to raycaster
el.setAttribute("pressable", '') // detect hand-controller click
// respond to cursor via laser-controls (https://aframe.io/docs/1.4.0/components/laser-controls.html)
el.addEventListener("click", clickHandler )
el.addEventListener("mouseenter", mesh.userData.XRF.href.selected(true) )
el.addEventListener("mouseleave", mesh.userData.XRF.href.selected(false) )
el.addEventListener("pressedstarted", clickHandler )
$('a-scene').appendChild(el)
}
xrf.addEventListener('interactionReady', AFRAME.XRF.clickableMeshToEntity )
2024-01-03 15:55:23 +00:00
// cleanup xrf-get objects when resetting scene
xrf.addEventListener('reset', (opts) => {
let els = [...document.querySelectorAll('[xrf-get]')]
els.map( (el) => document.querySelector('a-scene').removeChild(el) )
})
2024-01-03 15:55:23 +00:00
if( typeof this.data === 'string' || this.data.http || this.data.https ){
let url
if( typeof this.data === 'string' ) url = this.data
if( this.data.http ) url = `http:${this.data.http}`
if( this.data.https ) url = `https:${this.data.https}`
AFRAME.XRF.navigator.to( url )
.then( (model) => {
let gets = [ ...document.querySelectorAll('[xrf-get]') ]
gets.map( (g) => g.emit('update') )
})
}
aScene.emit('XRF',{})
// enable gaze-click on Mobile VR
aScene.setAttribute('xrf-gaze','')
2023-10-14 20:10:06 +02:00
}
},
})