2023-05-09 17:42:29 +02:00
|
|
|
window.AFRAME.registerComponent('xrf', {
|
|
|
|
|
schema: {
|
|
|
|
|
},
|
|
|
|
|
init: function () {
|
2023-09-15 19:42:37 +02:00
|
|
|
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
|
|
|
|
2023-12-08 13:35:19 +01:00
|
|
|
let aScene = document.querySelector('a-scene')
|
|
|
|
|
aScene.addEventListener('loaded', () => {
|
2023-05-12 22:06:21 +02:00
|
|
|
|
2023-09-15 19:42:37 +02:00
|
|
|
// enable XR fragments
|
|
|
|
|
let XRF = AFRAME.XRF = xrf.init({
|
|
|
|
|
THREE,
|
2023-10-12 17:04:46 +02:00
|
|
|
camera: aScene.camera,
|
|
|
|
|
scene: aScene.object3D,
|
|
|
|
|
renderer: aScene.renderer,
|
2023-09-15 19:42:37 +02:00
|
|
|
loaders: {
|
|
|
|
|
gltf: THREE.GLTFLoader, // which 3D assets (exts) to check for XR fragments?
|
2023-12-19 20:40:40 +01:00
|
|
|
glb: THREE.GLTFLoader,
|
|
|
|
|
obj: THREE.OBJLoader
|
2023-09-15 19:42:37 +02:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
if( !XRF.camera ) throw 'xrfragment: no camera detected, please declare <a-entity camera..> ABOVE entities with xrf-attributes'
|
2023-05-17 21:31:28 +02:00
|
|
|
|
2023-12-08 13:35:19 +01: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' ) )
|
|
|
|
|
|
2023-11-24 17:32:53 +01:00
|
|
|
xrf.addEventListener('navigateLoaded', () => {
|
|
|
|
|
setTimeout( () => AFRAME.fade.out(),500)
|
|
|
|
|
|
|
|
|
|
// *TODO* this does not really belong here perhaps
|
|
|
|
|
let blinkControls = document.querySelector('[blink-controls]')
|
|
|
|
|
if( blinkControls ){
|
2023-12-06 12:54:47 +01:00
|
|
|
let els = xrf.getCollisionMeshes()
|
|
|
|
|
let invisible = false
|
2023-11-29 19:39:31 +01:00
|
|
|
els.map( (mesh) => {
|
2023-12-06 12:54:47 +01:00
|
|
|
if( !invisible ){
|
|
|
|
|
invisible = mesh.material.clone()
|
|
|
|
|
invisible.visible = false
|
|
|
|
|
}
|
|
|
|
|
mesh.material = invisible
|
2023-11-29 19:39:31 +01:00
|
|
|
let el = document.createElement("a-entity")
|
2023-11-30 13:25:27 +01:00
|
|
|
el.setAttribute("xrf-get", mesh.name )
|
2023-11-30 17:51:01 +01:00
|
|
|
el.setAttribute("class","floor")
|
2023-11-29 19:39:31 +01:00
|
|
|
$('a-scene').appendChild(el)
|
|
|
|
|
})
|
2023-11-30 17:51:01 +01:00
|
|
|
blinkControls.components['blink-controls'].update({collisionEntities:true})
|
2023-11-24 17:32:53 +01:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
2023-11-08 18:28:18 +01:00
|
|
|
xrf.addEventListener('href', (opts) => {
|
|
|
|
|
if( opts.click){
|
2023-11-09 21:43:18 +01:00
|
|
|
let p = opts.promise()
|
|
|
|
|
let url = opts.xrf.string
|
|
|
|
|
let isLocal = url.match(/^#/)
|
|
|
|
|
let hasPos = url.match(/pos=/)
|
2023-12-28 09:22:54 +00:00
|
|
|
if( !isLocal && !url.match(/^http/) ) return // dont fade/load for custom protocol handlers
|
2023-11-09 21:43:18 +01:00
|
|
|
if( isLocal && hasPos ){
|
|
|
|
|
// local teleports only
|
2023-11-08 18:28:18 +01:00
|
|
|
let fastFadeMs = 200
|
|
|
|
|
AFRAME.fade.in(fastFadeMs)
|
|
|
|
|
setTimeout( () => {
|
|
|
|
|
p.resolve()
|
|
|
|
|
AFRAME.fade.out(fastFadeMs)
|
|
|
|
|
}, fastFadeMs)
|
2023-11-17 18:15:22 +01:00
|
|
|
}else if( !isLocal ){
|
2023-11-08 18:28:18 +01:00
|
|
|
AFRAME.fade.in()
|
|
|
|
|
setTimeout( () => {
|
|
|
|
|
p.resolve()
|
|
|
|
|
setTimeout( () => AFRAME.fade.out(), 1000 ) // allow one second to load textures e.g.
|
|
|
|
|
}, AFRAME.fade.data.fadetime )
|
2023-11-17 18:15:22 +01:00
|
|
|
}else p.resolve()
|
2023-11-08 18:28:18 +01:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
2023-10-11 13:46:38 +02:00
|
|
|
// convert href's to a-entity's so AFRAME
|
2023-09-15 19:42:37 +02:00
|
|
|
// raycaster can find & execute it
|
2023-10-11 13:46:38 +02:00
|
|
|
AFRAME.XRF.clickableMeshToEntity = (opts) => {
|
|
|
|
|
let {mesh,clickHandler} = opts;
|
2023-09-15 19:42:37 +02:00
|
|
|
let el = document.createElement("a-entity")
|
2023-10-11 13:46:38 +02:00
|
|
|
el.setAttribute("xrf-get",mesh.name ) // turn into AFRAME entity
|
|
|
|
|
el.setAttribute("class","ray") // expose to raycaster
|
|
|
|
|
el.setAttribute("pressable", '') // detect hand-controller click
|
2023-11-08 18:28:18 +01:00
|
|
|
// respond to cursor via laser-controls (https://aframe.io/docs/1.4.0/components/laser-controls.html)
|
2023-10-11 13:46:38 +02:00
|
|
|
el.addEventListener("click", clickHandler )
|
2023-11-08 18:28:18 +01:00
|
|
|
el.addEventListener("mouseenter", mesh.userData.XRF.href.selected(true) )
|
|
|
|
|
el.addEventListener("mouseleave", mesh.userData.XRF.href.selected(false) )
|
|
|
|
|
el.addEventListener("pressedstarted", clickHandler )
|
2023-09-15 19:42:37 +02:00
|
|
|
$('a-scene').appendChild(el)
|
|
|
|
|
}
|
2023-10-11 13:46:38 +02:00
|
|
|
xrf.addEventListener('interactionReady', AFRAME.XRF.clickableMeshToEntity )
|
2023-05-23 14:41:24 +02:00
|
|
|
|
2023-09-15 19:42:37 +02:00
|
|
|
// cleanup xrf-get objects when resetting scene
|
2023-10-25 11:43:44 +02:00
|
|
|
xrf.addEventListener('reset', (opts) => {
|
2023-09-15 19:42:37 +02:00
|
|
|
let els = [...document.querySelectorAll('[xrf-get]')]
|
|
|
|
|
els.map( (el) => document.querySelector('a-scene').removeChild(el) )
|
2023-10-25 11:43:44 +02:00
|
|
|
})
|
2023-05-18 12:32:57 +02:00
|
|
|
|
2023-09-15 19:42:37 +02:00
|
|
|
AFRAME.XRF.navigator.to(this.data)
|
|
|
|
|
.then( (model) => {
|
|
|
|
|
let gets = [ ...document.querySelectorAll('[xrf-get]') ]
|
|
|
|
|
gets.map( (g) => g.emit('update') )
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
aScene.emit('XRF',{})
|
2023-10-14 20:10:06 +02:00
|
|
|
|
|
|
|
|
// enable gaze-click on Mobile VR
|
|
|
|
|
aScene.setAttribute('xrf-gaze','')
|
|
|
|
|
|
2023-09-15 19:42:37 +02:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if( typeof this.data == "string" ){
|
|
|
|
|
if( document.location.search || document.location.hash.length > 1 ){ // override url
|
|
|
|
|
this.data = `${document.location.search.substr(1)}${document.location.hash}`
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-05-12 22:06:21 +02:00
|
|
|
},
|
2023-09-15 19:42:37 +02:00
|
|
|
|
2023-05-12 22:06:21 +02:00
|
|
|
})
|