better AR support (auto-publishes #AR to the hashbus)

This commit is contained in:
Leon van Kammen 2023-12-08 13:35:19 +01:00
parent f18acea3ff
commit 77d820212e
13 changed files with 21680 additions and 77 deletions

View File

@ -41,7 +41,7 @@ jobs:
- name: create index.gltf
run: cp example/assets/query.gltf index.gltf
- name: copy gltfs
run: cp example/assets/*.gltf .
run: cp example/assets/*.{gltf,glb} .
# working-directory: ./
- name: Upload artifact
uses: actions/upload-pages-artifact@v1

View File

@ -1,5 +1,5 @@
/*
* v0.5.1 generated at Thu Dec 7 10:14:06 PM CET 2023
* v0.5.1 generated at Fri Dec 8 01:31:41 PM CET 2023
* https://xrfragment.org
* SPDX-License-Identifier: MPL-2.0
*/
@ -784,7 +784,8 @@ let pub = function( url, model, flags ){ // evaluate fragments in url
return frag
}
pub.mesh = (mesh,model) => { // evaluate embedded fragments (metadata) inside mesh of model
// deprecated: (XR Macros) evaluate embedded fragments (metadata) inside mesh of model *REMOVEME*
pub.mesh = (mesh,model) => {
if( mesh.userData ){
let frag = {}
for( let k in mesh.userData ) xrf.Parser.parse( k, mesh.userData[k], frag )
@ -792,7 +793,7 @@ pub.mesh = (mesh,model) => { // evaluate embedded fragments (metadata) insid
let opts = {frag, mesh, model, camera: xrf.camera, scene: model.scene, renderer: xrf.renderer, THREE: xrf.THREE, hashbus: xrf.hashbus }
mesh.userData.XRF = frag // allow fragment impl to access XRF obj already
xrf.emit('frag2mesh',opts)
.then( () => pub.fragment(k,opts) )
.then( () => pub.fragment(k, {...opts, skipXRWG:true}) )
}
}
}
@ -800,7 +801,7 @@ pub.mesh = (mesh,model) => { // evaluate embedded fragments (metadata) insid
pub.fragment = (k, opts ) => { // evaluate one fragment
let frag = opts.frag[k];
if( frag.is( xrf.XRF.PV_EXECUTE ) ) pub.XRWG({...opts,frag})
if( !opts.skipXRWG && frag.is( xrf.XRF.PV_EXECUTE ) ) pub.XRWG(opts)
// call native function (xrf/env.js e.g.), or pass it to user decorator
xrf.emit(k,opts)
@ -992,9 +993,8 @@ xrf.navigator.to = (url,flags,loader,data) => {
// spec: 1. execute the default predefined view '#' (if exist) (https://xrfragment.org/#predefined_view)
xrf.frag.defaultPredefinedViews({model,scene:model.scene})
// spec: 2. init metadata
// spec: predefined view(s) from URL (https://xrfragment.org/#predefined_view)
// spec: predefined view(s) & objects-of-interest-in-XRWG from URL (https://xrfragment.org/#predefined_view)
let frag = hashbus.pub( url, model) // and eval URI XR fragments
hashbus.pub.XRWG({model,scene:model.scene,frag})
xrf.add( model.scene )
xrf.navigator.updateHash(hash)
@ -1789,22 +1789,17 @@ xrf.frag.defaultPredefinedViews = (opts) => {
if( n.userData && n.userData['#'] ){
let frag = xrf.URI.parse( n.userData['#'] )
xrf.hashbus.pub( n.userData['#'] ) // evaluate static XR fragments
xrf.hashbus.pub.XRWG({frag,model,scene}) // evaluate dynamic XR fragment using XRWG (see spec)
}
})
}
// react to enduser typing url
xrf.addEventListener('hash', (opts) => {
let frag = xrf.URI.parse( opts.hash )
xrf.hashbus.pub.XRWG({frag,scene:xrf.scene})
})
xrf.addEventListener('hash', (opts) => xrf.hashbus.pub( opts.hash ) )
// clicking href url with predefined view
xrf.addEventListener('href', (opts) => {
if( !opts.click || opts.xrf.string[0] != '#' ) return
let frag = xrf.URI.parse( opts.xrf.string, xrf.XRF.NAVIGATOR | xrf.XRF.PV_OVERRIDE | xrf.XRF.METADATA )
xrf.hashbus.pub.XRWG({frag,scene:xrf.scene,href:opts.xrf})
xrf.hashbus.pub( opts.xrf.string )
})
xrf.addEventListener('dynamicKeyValue', (opts) => {
let {scene,match,v} = opts
@ -2642,10 +2637,10 @@ window.AFRAME.registerComponent('xrf', {
if( document.location.host.match(/localhost/) ) document.querySelector('a-scene').setAttribute("stats",'')
document.querySelector('a-scene').addEventListener('loaded', () => {
let aScene = document.querySelector('a-scene')
aScene.addEventListener('loaded', () => {
// enable XR fragments
let aScene = document.querySelector('a-scene')
let XRF = AFRAME.XRF = xrf.init({
THREE,
camera: aScene.camera,
@ -2658,6 +2653,12 @@ window.AFRAME.registerComponent('xrf', {
})
if( !XRF.camera ) throw 'xrfragment: no camera detected, please declare <a-entity camera..> ABOVE entities with xrf-attributes'
// 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' ) )
xrf.addEventListener('navigateLoaded', () => {
setTimeout( () => AFRAME.fade.out(),500)

View File

@ -1,5 +1,5 @@
/*
* v0.5.1 generated at Thu Dec 7 10:14:06 PM CET 2023
* v0.5.1 generated at Fri Dec 8 01:31:41 PM CET 2023
* https://xrfragment.org
* SPDX-License-Identifier: MPL-2.0
*/
@ -778,7 +778,8 @@ let pub = function( url, model, flags ){ // evaluate fragments in url
return frag
}
pub.mesh = (mesh,model) => { // evaluate embedded fragments (metadata) inside mesh of model
// deprecated: (XR Macros) evaluate embedded fragments (metadata) inside mesh of model *REMOVEME*
pub.mesh = (mesh,model) => {
if( mesh.userData ){
let frag = {}
for( let k in mesh.userData ) xrf.Parser.parse( k, mesh.userData[k], frag )
@ -786,7 +787,7 @@ pub.mesh = (mesh,model) => { // evaluate embedded fragments (metadata) insid
let opts = {frag, mesh, model, camera: xrf.camera, scene: model.scene, renderer: xrf.renderer, THREE: xrf.THREE, hashbus: xrf.hashbus }
mesh.userData.XRF = frag // allow fragment impl to access XRF obj already
xrf.emit('frag2mesh',opts)
.then( () => pub.fragment(k,opts) )
.then( () => pub.fragment(k, {...opts, skipXRWG:true}) )
}
}
}
@ -794,7 +795,7 @@ pub.mesh = (mesh,model) => { // evaluate embedded fragments (metadata) insid
pub.fragment = (k, opts ) => { // evaluate one fragment
let frag = opts.frag[k];
if( frag.is( xrf.XRF.PV_EXECUTE ) ) pub.XRWG({...opts,frag})
if( !opts.skipXRWG && frag.is( xrf.XRF.PV_EXECUTE ) ) pub.XRWG(opts)
// call native function (xrf/env.js e.g.), or pass it to user decorator
xrf.emit(k,opts)
@ -986,9 +987,8 @@ xrf.navigator.to = (url,flags,loader,data) => {
// spec: 1. execute the default predefined view '#' (if exist) (https://xrfragment.org/#predefined_view)
xrf.frag.defaultPredefinedViews({model,scene:model.scene})
// spec: 2. init metadata
// spec: predefined view(s) from URL (https://xrfragment.org/#predefined_view)
// spec: predefined view(s) & objects-of-interest-in-XRWG from URL (https://xrfragment.org/#predefined_view)
let frag = hashbus.pub( url, model) // and eval URI XR fragments
hashbus.pub.XRWG({model,scene:model.scene,frag})
xrf.add( model.scene )
xrf.navigator.updateHash(hash)
@ -1783,22 +1783,17 @@ xrf.frag.defaultPredefinedViews = (opts) => {
if( n.userData && n.userData['#'] ){
let frag = xrf.URI.parse( n.userData['#'] )
xrf.hashbus.pub( n.userData['#'] ) // evaluate static XR fragments
xrf.hashbus.pub.XRWG({frag,model,scene}) // evaluate dynamic XR fragment using XRWG (see spec)
}
})
}
// react to enduser typing url
xrf.addEventListener('hash', (opts) => {
let frag = xrf.URI.parse( opts.hash )
xrf.hashbus.pub.XRWG({frag,scene:xrf.scene})
})
xrf.addEventListener('hash', (opts) => xrf.hashbus.pub( opts.hash ) )
// clicking href url with predefined view
xrf.addEventListener('href', (opts) => {
if( !opts.click || opts.xrf.string[0] != '#' ) return
let frag = xrf.URI.parse( opts.xrf.string, xrf.XRF.NAVIGATOR | xrf.XRF.PV_OVERRIDE | xrf.XRF.METADATA )
xrf.hashbus.pub.XRWG({frag,scene:xrf.scene,href:opts.xrf})
xrf.hashbus.pub( opts.xrf.string )
})
xrf.addEventListener('dynamicKeyValue', (opts) => {
let {scene,match,v} = opts
@ -2636,10 +2631,10 @@ window.AFRAME.registerComponent('xrf', {
if( document.location.host.match(/localhost/) ) document.querySelector('a-scene').setAttribute("stats",'')
document.querySelector('a-scene').addEventListener('loaded', () => {
let aScene = document.querySelector('a-scene')
aScene.addEventListener('loaded', () => {
// enable XR fragments
let aScene = document.querySelector('a-scene')
let XRF = AFRAME.XRF = xrf.init({
THREE,
camera: aScene.camera,
@ -2652,6 +2647,12 @@ window.AFRAME.registerComponent('xrf', {
})
if( !XRF.camera ) throw 'xrfragment: no camera detected, please declare <a-entity camera..> ABOVE entities with xrf-attributes'
// 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' ) )
xrf.addEventListener('navigateLoaded', () => {
setTimeout( () => AFRAME.fade.out(),500)

21606
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 Thu Dec 7 10:14:06 PM CET 2023
* v0.5.1 generated at Fri Dec 8 01:31:41 PM CET 2023
* https://xrfragment.org
* SPDX-License-Identifier: MPL-2.0
*/
@ -778,7 +778,8 @@ let pub = function( url, model, flags ){ // evaluate fragments in url
return frag
}
pub.mesh = (mesh,model) => { // evaluate embedded fragments (metadata) inside mesh of model
// deprecated: (XR Macros) evaluate embedded fragments (metadata) inside mesh of model *REMOVEME*
pub.mesh = (mesh,model) => {
if( mesh.userData ){
let frag = {}
for( let k in mesh.userData ) xrf.Parser.parse( k, mesh.userData[k], frag )
@ -786,7 +787,7 @@ pub.mesh = (mesh,model) => { // evaluate embedded fragments (metadata) insid
let opts = {frag, mesh, model, camera: xrf.camera, scene: model.scene, renderer: xrf.renderer, THREE: xrf.THREE, hashbus: xrf.hashbus }
mesh.userData.XRF = frag // allow fragment impl to access XRF obj already
xrf.emit('frag2mesh',opts)
.then( () => pub.fragment(k,opts) )
.then( () => pub.fragment(k, {...opts, skipXRWG:true}) )
}
}
}
@ -794,7 +795,7 @@ pub.mesh = (mesh,model) => { // evaluate embedded fragments (metadata) insid
pub.fragment = (k, opts ) => { // evaluate one fragment
let frag = opts.frag[k];
if( frag.is( xrf.XRF.PV_EXECUTE ) ) pub.XRWG({...opts,frag})
if( !opts.skipXRWG && frag.is( xrf.XRF.PV_EXECUTE ) ) pub.XRWG(opts)
// call native function (xrf/env.js e.g.), or pass it to user decorator
xrf.emit(k,opts)
@ -986,9 +987,8 @@ xrf.navigator.to = (url,flags,loader,data) => {
// spec: 1. execute the default predefined view '#' (if exist) (https://xrfragment.org/#predefined_view)
xrf.frag.defaultPredefinedViews({model,scene:model.scene})
// spec: 2. init metadata
// spec: predefined view(s) from URL (https://xrfragment.org/#predefined_view)
// spec: predefined view(s) & objects-of-interest-in-XRWG from URL (https://xrfragment.org/#predefined_view)
let frag = hashbus.pub( url, model) // and eval URI XR fragments
hashbus.pub.XRWG({model,scene:model.scene,frag})
xrf.add( model.scene )
xrf.navigator.updateHash(hash)
@ -1783,22 +1783,17 @@ xrf.frag.defaultPredefinedViews = (opts) => {
if( n.userData && n.userData['#'] ){
let frag = xrf.URI.parse( n.userData['#'] )
xrf.hashbus.pub( n.userData['#'] ) // evaluate static XR fragments
xrf.hashbus.pub.XRWG({frag,model,scene}) // evaluate dynamic XR fragment using XRWG (see spec)
}
})
}
// react to enduser typing url
xrf.addEventListener('hash', (opts) => {
let frag = xrf.URI.parse( opts.hash )
xrf.hashbus.pub.XRWG({frag,scene:xrf.scene})
})
xrf.addEventListener('hash', (opts) => xrf.hashbus.pub( opts.hash ) )
// clicking href url with predefined view
xrf.addEventListener('href', (opts) => {
if( !opts.click || opts.xrf.string[0] != '#' ) return
let frag = xrf.URI.parse( opts.xrf.string, xrf.XRF.NAVIGATOR | xrf.XRF.PV_OVERRIDE | xrf.XRF.METADATA )
xrf.hashbus.pub.XRWG({frag,scene:xrf.scene,href:opts.xrf})
xrf.hashbus.pub( opts.xrf.string )
})
xrf.addEventListener('dynamicKeyValue', (opts) => {
let {scene,match,v} = opts

View File

@ -1,5 +1,5 @@
/*
* v0.5.1 generated at Thu Dec 7 10:14:06 PM CET 2023
* v0.5.1 generated at Fri Dec 8 01:31:41 PM CET 2023
* https://xrfragment.org
* SPDX-License-Identifier: MPL-2.0
*/
@ -778,7 +778,8 @@ let pub = function( url, model, flags ){ // evaluate fragments in url
return frag
}
pub.mesh = (mesh,model) => { // evaluate embedded fragments (metadata) inside mesh of model
// deprecated: (XR Macros) evaluate embedded fragments (metadata) inside mesh of model *REMOVEME*
pub.mesh = (mesh,model) => {
if( mesh.userData ){
let frag = {}
for( let k in mesh.userData ) xrf.Parser.parse( k, mesh.userData[k], frag )
@ -786,7 +787,7 @@ pub.mesh = (mesh,model) => { // evaluate embedded fragments (metadata) insid
let opts = {frag, mesh, model, camera: xrf.camera, scene: model.scene, renderer: xrf.renderer, THREE: xrf.THREE, hashbus: xrf.hashbus }
mesh.userData.XRF = frag // allow fragment impl to access XRF obj already
xrf.emit('frag2mesh',opts)
.then( () => pub.fragment(k,opts) )
.then( () => pub.fragment(k, {...opts, skipXRWG:true}) )
}
}
}
@ -794,7 +795,7 @@ pub.mesh = (mesh,model) => { // evaluate embedded fragments (metadata) insid
pub.fragment = (k, opts ) => { // evaluate one fragment
let frag = opts.frag[k];
if( frag.is( xrf.XRF.PV_EXECUTE ) ) pub.XRWG({...opts,frag})
if( !opts.skipXRWG && frag.is( xrf.XRF.PV_EXECUTE ) ) pub.XRWG(opts)
// call native function (xrf/env.js e.g.), or pass it to user decorator
xrf.emit(k,opts)
@ -986,9 +987,8 @@ xrf.navigator.to = (url,flags,loader,data) => {
// spec: 1. execute the default predefined view '#' (if exist) (https://xrfragment.org/#predefined_view)
xrf.frag.defaultPredefinedViews({model,scene:model.scene})
// spec: 2. init metadata
// spec: predefined view(s) from URL (https://xrfragment.org/#predefined_view)
// spec: predefined view(s) & objects-of-interest-in-XRWG from URL (https://xrfragment.org/#predefined_view)
let frag = hashbus.pub( url, model) // and eval URI XR fragments
hashbus.pub.XRWG({model,scene:model.scene,frag})
xrf.add( model.scene )
xrf.navigator.updateHash(hash)
@ -1783,22 +1783,17 @@ xrf.frag.defaultPredefinedViews = (opts) => {
if( n.userData && n.userData['#'] ){
let frag = xrf.URI.parse( n.userData['#'] )
xrf.hashbus.pub( n.userData['#'] ) // evaluate static XR fragments
xrf.hashbus.pub.XRWG({frag,model,scene}) // evaluate dynamic XR fragment using XRWG (see spec)
}
})
}
// react to enduser typing url
xrf.addEventListener('hash', (opts) => {
let frag = xrf.URI.parse( opts.hash )
xrf.hashbus.pub.XRWG({frag,scene:xrf.scene})
})
xrf.addEventListener('hash', (opts) => xrf.hashbus.pub( opts.hash ) )
// clicking href url with predefined view
xrf.addEventListener('href', (opts) => {
if( !opts.click || opts.xrf.string[0] != '#' ) return
let frag = xrf.URI.parse( opts.xrf.string, xrf.XRF.NAVIGATOR | xrf.XRF.PV_OVERRIDE | xrf.XRF.METADATA )
xrf.hashbus.pub.XRWG({frag,scene:xrf.scene,href:opts.xrf})
xrf.hashbus.pub( opts.xrf.string )
})
xrf.addEventListener('dynamicKeyValue', (opts) => {
let {scene,match,v} = opts

View File

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>AFRAME - xrfragment sandbox</title>
<title>XR Fragments aframe viewer</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
@ -28,7 +28,7 @@
<textarea style="display:none"></textarea>
<canvas id="qrcode" style="display:none" width="300" height="300"></canvas>
<a-scene renderer="colorManagement: true; highRefreshRate:true" light="defaultLightsEnabled: false">
<a-scene xr-mode-ui="XRMode: xr" renderer="colorManagement: true; highRefreshRate:true" light="defaultLightsEnabled: false">
<a-entity id="player">
<a-entity camera="fov:90" position="0 1.6 0" wasd-controls look-controls id="camera"></a-entity>
<a-entity id="left-hand" laser-controls="hand: left" raycaster="objects:.ray" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: .floor">

7
make
View File

@ -140,13 +140,14 @@ repos(){
echo " "
}
release_dir aframe xrfragment-aframe-helloworld aframe
release_dir three xrfragment-three-helloworld three.module
release_dir aframe xrfragment-helloworld aframe.all
release_dir aframe xrfragment-aframe-helloworld
release_dir three xrfragment-three-helloworld
release_dir aframe xrfragment-helloworld
# remove aframe reference
sed -i 's|<script src="https:\/\/aframe.*||g' ../xrfragment-helloworld/index.html
sed -i 's|<script src=".*blink-controls.*||g' ../xrfragment-helloworld/index.html
sed -i 's|aframe\.js|aframe.all.js|g' ../xrfragment-helloworld/index.html
}
test -z $1 && build

View File

@ -11,10 +11,10 @@ window.AFRAME.registerComponent('xrf', {
if( document.location.host.match(/localhost/) ) document.querySelector('a-scene').setAttribute("stats",'')
document.querySelector('a-scene').addEventListener('loaded', () => {
let aScene = document.querySelector('a-scene')
aScene.addEventListener('loaded', () => {
// enable XR fragments
let aScene = document.querySelector('a-scene')
let XRF = AFRAME.XRF = xrf.init({
THREE,
camera: aScene.camera,
@ -27,6 +27,12 @@ window.AFRAME.registerComponent('xrf', {
})
if( !XRF.camera ) throw 'xrfragment: no camera detected, please declare <a-entity camera..> ABOVE entities with xrf-attributes'
// 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' ) )
xrf.addEventListener('navigateLoaded', () => {
setTimeout( () => AFRAME.fade.out(),500)

View File

@ -19,7 +19,8 @@ let pub = function( url, model, flags ){ // evaluate fragments in url
return frag
}
pub.mesh = (mesh,model) => { // evaluate embedded fragments (metadata) inside mesh of model
// deprecated: (XR Macros) evaluate embedded fragments (metadata) inside mesh of model *REMOVEME*
pub.mesh = (mesh,model) => {
if( mesh.userData ){
let frag = {}
for( let k in mesh.userData ) xrf.Parser.parse( k, mesh.userData[k], frag )
@ -27,7 +28,7 @@ pub.mesh = (mesh,model) => { // evaluate embedded fragments (metadata) insid
let opts = {frag, mesh, model, camera: xrf.camera, scene: model.scene, renderer: xrf.renderer, THREE: xrf.THREE, hashbus: xrf.hashbus }
mesh.userData.XRF = frag // allow fragment impl to access XRF obj already
xrf.emit('frag2mesh',opts)
.then( () => pub.fragment(k,opts) )
.then( () => pub.fragment(k, {...opts, skipXRWG:true}) )
}
}
}
@ -35,7 +36,7 @@ pub.mesh = (mesh,model) => { // evaluate embedded fragments (metadata) insid
pub.fragment = (k, opts ) => { // evaluate one fragment
let frag = opts.frag[k];
if( frag.is( xrf.XRF.PV_EXECUTE ) ) pub.XRWG({...opts,frag})
if( !opts.skipXRWG && frag.is( xrf.XRF.PV_EXECUTE ) ) pub.XRWG(opts)
// call native function (xrf/env.js e.g.), or pass it to user decorator
xrf.emit(k,opts)

View File

@ -36,9 +36,8 @@ xrf.navigator.to = (url,flags,loader,data) => {
// spec: 1. execute the default predefined view '#' (if exist) (https://xrfragment.org/#predefined_view)
xrf.frag.defaultPredefinedViews({model,scene:model.scene})
// spec: 2. init metadata
// spec: predefined view(s) from URL (https://xrfragment.org/#predefined_view)
// spec: predefined view(s) & objects-of-interest-in-XRWG from URL (https://xrfragment.org/#predefined_view)
let frag = hashbus.pub( url, model) // and eval URI XR fragments
hashbus.pub.XRWG({model,scene:model.scene,frag})
xrf.add( model.scene )
xrf.navigator.updateHash(hash)

View File

@ -4,20 +4,15 @@ xrf.frag.defaultPredefinedViews = (opts) => {
if( n.userData && n.userData['#'] ){
let frag = xrf.URI.parse( n.userData['#'] )
xrf.hashbus.pub( n.userData['#'] ) // evaluate static XR fragments
xrf.hashbus.pub.XRWG({frag,model,scene}) // evaluate dynamic XR fragment using XRWG (see spec)
}
})
}
// react to enduser typing url
xrf.addEventListener('hash', (opts) => {
let frag = xrf.URI.parse( opts.hash )
xrf.hashbus.pub.XRWG({frag,scene:xrf.scene})
})
xrf.addEventListener('hash', (opts) => xrf.hashbus.pub( opts.hash ) )
// clicking href url with predefined view
xrf.addEventListener('href', (opts) => {
if( !opts.click || opts.xrf.string[0] != '#' ) return
let frag = xrf.URI.parse( opts.xrf.string, xrf.XRF.NAVIGATOR | xrf.XRF.PV_OVERRIDE | xrf.XRF.METADATA )
xrf.hashbus.pub.XRWG({frag,scene:xrf.scene,href:opts.xrf})
xrf.hashbus.pub( opts.xrf.string )
})

View File

@ -1,7 +1,10 @@
xrf.frag.t = function(v, opts){
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
if( !model.mixer ) return
if( !model.animations || model.animations[0] == undefined ) return console.warn('no animation in scene')
if( !model.animations || model.animations[0] == undefined ){
console.warn('no animations found in model')
return xrf.emit( v.x == 0 ? 'stop' : 'play',{isPlaying: v.x != 0 })
}
xrf.mixers.map ( (mixer) => {