bugfix: enter-vr (black screen) + fixed objects-leak when resetting scene

This commit is contained in:
Leon van Kammen 2024-06-04 17:00:48 +00:00
parent adf13e7f72
commit 18febc6b0f
16 changed files with 199074 additions and 135 deletions

View File

@ -1,5 +1,5 @@
/*
* v0.5.1 generated at Thu Apr 25 03:56:52 PM UTC 2024
* v0.5.1 generated at Tue Jun 4 04:54:19 PM UTC 2024
* https://xrfragment.org
* SPDX-License-Identifier: MPL-2.0
*/
@ -1593,15 +1593,17 @@ var xrf = {}
xrf.init = function(opts){
opts = opts || {}
xrf.debug = document.location.hostname.match(/^(localhost|[0-9])/) ? 0 : false
if( !xrf.debug ){
xrf.debug = document.location.hostname.match(/^(localhost|[0-9]\.[0-9])/) || document.location.port == '8080' ? 0 : false
if( xrf.debug === false ){
console.log("add #debug=[0-9] to URL to see XR Fragment debuglog")
xrf.debug = parseInt( ( document.location.hash.match(/debug=([0-9])/) || [0,'0'] )[1] )
}else{
xrf.stats()
}
xrf.Parser.debug = xrf.debug
xrf.detectCameraRig(opts)
for ( let i in opts ) xrf[i] = opts[i]
for ( let i in opts ) xrf[i] = opts[i]
xrf.emit('init',opts)
return xrf
}
@ -1628,10 +1630,9 @@ xrf.detectCameraRig = function(opts){
xrf.stats = () => {
// bookmarklet from https://github.com/zlgenuine/threejs_stats
(function(){
for( let i = 0; i < 4; i++ ){
var script=document.createElement('script');script.onload=function(){var stats=new Stats();stats.showPanel( i );
stats.dom.style.marginTop = `${i*48}px`; document.body.appendChild(stats.dom);requestAnimationFrame(function loop(){stats.update();requestAnimationFrame(loop)});};script.src='//rawgit.com/mrdoob/stats.js/master/build/stats.min.js';document.head.appendChild(script);
}
let i = 0;
var script=document.createElement('script');script.onload=function(){var stats=new Stats();stats.showPanel( i );
stats.dom.style.marginTop = `${i*48}px`; document.body.appendChild(stats.dom);requestAnimationFrame(function loop(){stats.update();requestAnimationFrame(loop)});};script.src='//rawgit.com/mrdoob/stats.js/master/build/stats.min.js';document.head.appendChild(script);
})()
}
@ -1907,14 +1908,17 @@ xrf.model = {}
xrf.mixers = []
xrf.init = ((init) => function(opts){
// operate in own subscene
let scene = new opts.THREE.Group()
opts.scene.add(scene)
opts.scene = scene
opts.sceneRoot = opts.scene
opts.scene = scene
init(opts)
//if( opts.loaders ) Object.values(opts.loaders).map( xrf.patchLoader )
xrf.patchRenderer(opts)
xrf.navigator.init()
xrf.interactive = xrf.interactiveGroup( xrf.THREE, xrf.renderer, xrf.camera)
// return xrfragment lib as 'xrf' query functor (like jquery)
for ( let i in xrf ) xrf.query[i] = xrf[i]
@ -1985,11 +1989,11 @@ xrf.reset = () => {
obj.removeFromParent()
return true
};
// also remove XRF objects from global scene
let nodes = []
xrf.scene.traverse( (child) => child.isXRF && (nodes.push(child)) )
nodes.map( disposeObject ) // leave non-XRF objects intact
xrf.interactive = xrf.interactiveGroup( xrf.THREE, xrf.renderer, xrf.camera)
xrf.add( xrf.interactive )
nodes.map( disposeObject )
xrf.interactive.clear()
xrf.layers = 0
}
@ -3026,7 +3030,6 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
if ( intersects.length > 0 ) {
console.log(object.name)
const intersection = intersects[ 0 ];
@ -3034,6 +3037,7 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
const uv = intersection.uv;
_event.type = eventsMapper[ event.type ];
console.log( (new Date()).getTime()+" "+event.type+":"+_event.type+" "+object.name)
if( uv ) _event.data.set( uv.x, 1 - uv.y );
object.dispatchEvent( _event );
@ -3068,6 +3072,11 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
this.objects.push(obj)
}
clear(){
while( this.children[0] != undefined ) this.children[0].remove()
this.objects = []
}
}
return new interactive(renderer,camera)
@ -3252,7 +3261,7 @@ xrf.filter.process = function(frag,scene,opts){
if( processed ) processed[n.uuid] == true
}
// spec 2: https://xrfragment.org/doc/RFC_XR_Macros.html#embedding-xr-content-using-src
// spec 3 @ https://xrfragment.org/doc/RFC_XR_Macros.html#embedding-xr-content-using-src
// reparent scene based on objectname in case it matches a (non-negating) selector
if( opts.reparent && firstFilter && !firstFilter.value && firstFilter.show === true ){
let obj
@ -4135,8 +4144,8 @@ window.AFRAME.registerComponent('xrf', {
let pos = xrf.frag.pos.last
if( pos ){ AFRAME.XRF.camera.position.set(pos.x, pos.y*scale, pos.z) }
}
aScene.addEventListener('enter-vr', repositionUser(1) )
aScene.addEventListener('enter-ar', repositionUser(2) )
aScene.addEventListener('enter-vr', () => setTimeout( () => repositionUser(1),100 ) )
aScene.addEventListener('enter-ar', () => setTimeout( () => repositionUser(2),100 ) )
xrf.addEventListener('navigateLoaded', (opts) => {
setTimeout( () => AFRAME.fade.out(),500)
@ -4223,12 +4232,6 @@ window.AFRAME.registerComponent('xrf', {
}
xrf.addEventListener('interactionReady', AFRAME.XRF.clickableMeshToEntity )
// 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) )
})
if( typeof this.data === 'string' || this.data.http || this.data.https ){
let url
if( typeof this.data === 'string' ) url = this.data
@ -4941,7 +4944,7 @@ window.AFRAME.registerComponent('xrf-get', {
setTimeout( () => {
if( !this.mesh ){
let scene = AFRAME.XRF.scene
let scene = xrf.scene
let mesh = this.mesh = scene.getObjectByName(meshname);
if( !this.el.className.match(/ray/) ) this.el.className += " ray"
if (!mesh){
@ -4980,17 +4983,6 @@ window.AFRAME.registerComponent('xrf-get', {
this.el.emit("update",{timeout:0})
AFRAME.XRF.addEventListener('reset', () => {
try{
if( this.el ){
while ( this.el.object3D.children.length ){
this.el.object3D.children[0].remove()
}
this.el.remove()
}
}catch(e){}
})
}
});
@ -5010,12 +5002,13 @@ window.AFRAME.registerComponent('xrf-pinchmove', {
// multiply the direction by a "speed" factor
direction.multiplyScalar(0.4)
// get the current position
var pos = player.getAttribute("position")
var pos = xrf.camera.position
//player.getAttribute("position")
// add the direction vector
pos.x += direction.x
pos.z += direction.z
// set the new position
this.data.rig.setAttribute("position", pos);
//this.data.rig.setAttribute("position", pos);
// !!! NOTE - it would be more efficient to do the
// position change on the players THREE.Object:
// `player.object3D.position.add(direction)`

View File

@ -1,5 +1,5 @@
/*
* v0.5.1 generated at Thu Apr 25 03:56:52 PM UTC 2024
* v0.5.1 generated at Tue Jun 4 04:54:19 PM UTC 2024
* https://xrfragment.org
* SPDX-License-Identifier: MPL-2.0
*/
@ -1591,15 +1591,17 @@ var xrf = {}
xrf.init = function(opts){
opts = opts || {}
xrf.debug = document.location.hostname.match(/^(localhost|[0-9])/) ? 0 : false
if( !xrf.debug ){
xrf.debug = document.location.hostname.match(/^(localhost|[0-9]\.[0-9])/) || document.location.port == '8080' ? 0 : false
if( xrf.debug === false ){
console.log("add #debug=[0-9] to URL to see XR Fragment debuglog")
xrf.debug = parseInt( ( document.location.hash.match(/debug=([0-9])/) || [0,'0'] )[1] )
}else{
xrf.stats()
}
xrf.Parser.debug = xrf.debug
xrf.detectCameraRig(opts)
for ( let i in opts ) xrf[i] = opts[i]
for ( let i in opts ) xrf[i] = opts[i]
xrf.emit('init',opts)
return xrf
}
@ -1626,10 +1628,9 @@ xrf.detectCameraRig = function(opts){
xrf.stats = () => {
// bookmarklet from https://github.com/zlgenuine/threejs_stats
(function(){
for( let i = 0; i < 4; i++ ){
var script=document.createElement('script');script.onload=function(){var stats=new Stats();stats.showPanel( i );
stats.dom.style.marginTop = `${i*48}px`; document.body.appendChild(stats.dom);requestAnimationFrame(function loop(){stats.update();requestAnimationFrame(loop)});};script.src='//rawgit.com/mrdoob/stats.js/master/build/stats.min.js';document.head.appendChild(script);
}
let i = 0;
var script=document.createElement('script');script.onload=function(){var stats=new Stats();stats.showPanel( i );
stats.dom.style.marginTop = `${i*48}px`; document.body.appendChild(stats.dom);requestAnimationFrame(function loop(){stats.update();requestAnimationFrame(loop)});};script.src='//rawgit.com/mrdoob/stats.js/master/build/stats.min.js';document.head.appendChild(script);
})()
}
@ -1905,14 +1906,17 @@ xrf.model = {}
xrf.mixers = []
xrf.init = ((init) => function(opts){
// operate in own subscene
let scene = new opts.THREE.Group()
opts.scene.add(scene)
opts.scene = scene
opts.sceneRoot = opts.scene
opts.scene = scene
init(opts)
//if( opts.loaders ) Object.values(opts.loaders).map( xrf.patchLoader )
xrf.patchRenderer(opts)
xrf.navigator.init()
xrf.interactive = xrf.interactiveGroup( xrf.THREE, xrf.renderer, xrf.camera)
// return xrfragment lib as 'xrf' query functor (like jquery)
for ( let i in xrf ) xrf.query[i] = xrf[i]
@ -1983,11 +1987,11 @@ xrf.reset = () => {
obj.removeFromParent()
return true
};
// also remove XRF objects from global scene
let nodes = []
xrf.scene.traverse( (child) => child.isXRF && (nodes.push(child)) )
nodes.map( disposeObject ) // leave non-XRF objects intact
xrf.interactive = xrf.interactiveGroup( xrf.THREE, xrf.renderer, xrf.camera)
xrf.add( xrf.interactive )
nodes.map( disposeObject )
xrf.interactive.clear()
xrf.layers = 0
}
@ -3024,7 +3028,6 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
if ( intersects.length > 0 ) {
console.log(object.name)
const intersection = intersects[ 0 ];
@ -3032,6 +3035,7 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
const uv = intersection.uv;
_event.type = eventsMapper[ event.type ];
console.log( (new Date()).getTime()+" "+event.type+":"+_event.type+" "+object.name)
if( uv ) _event.data.set( uv.x, 1 - uv.y );
object.dispatchEvent( _event );
@ -3066,6 +3070,11 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
this.objects.push(obj)
}
clear(){
while( this.children[0] != undefined ) this.children[0].remove()
this.objects = []
}
}
return new interactive(renderer,camera)
@ -3250,7 +3259,7 @@ xrf.filter.process = function(frag,scene,opts){
if( processed ) processed[n.uuid] == true
}
// spec 2: https://xrfragment.org/doc/RFC_XR_Macros.html#embedding-xr-content-using-src
// spec 3 @ https://xrfragment.org/doc/RFC_XR_Macros.html#embedding-xr-content-using-src
// reparent scene based on objectname in case it matches a (non-negating) selector
if( opts.reparent && firstFilter && !firstFilter.value && firstFilter.show === true ){
let obj
@ -4133,8 +4142,8 @@ window.AFRAME.registerComponent('xrf', {
let pos = xrf.frag.pos.last
if( pos ){ AFRAME.XRF.camera.position.set(pos.x, pos.y*scale, pos.z) }
}
aScene.addEventListener('enter-vr', repositionUser(1) )
aScene.addEventListener('enter-ar', repositionUser(2) )
aScene.addEventListener('enter-vr', () => setTimeout( () => repositionUser(1),100 ) )
aScene.addEventListener('enter-ar', () => setTimeout( () => repositionUser(2),100 ) )
xrf.addEventListener('navigateLoaded', (opts) => {
setTimeout( () => AFRAME.fade.out(),500)
@ -4221,12 +4230,6 @@ window.AFRAME.registerComponent('xrf', {
}
xrf.addEventListener('interactionReady', AFRAME.XRF.clickableMeshToEntity )
// 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) )
})
if( typeof this.data === 'string' || this.data.http || this.data.https ){
let url
if( typeof this.data === 'string' ) url = this.data
@ -4939,7 +4942,7 @@ window.AFRAME.registerComponent('xrf-get', {
setTimeout( () => {
if( !this.mesh ){
let scene = AFRAME.XRF.scene
let scene = xrf.scene
let mesh = this.mesh = scene.getObjectByName(meshname);
if( !this.el.className.match(/ray/) ) this.el.className += " ray"
if (!mesh){
@ -4978,17 +4981,6 @@ window.AFRAME.registerComponent('xrf-get', {
this.el.emit("update",{timeout:0})
AFRAME.XRF.addEventListener('reset', () => {
try{
if( this.el ){
while ( this.el.object3D.children.length ){
this.el.object3D.children[0].remove()
}
this.el.remove()
}
}catch(e){}
})
}
});
@ -5008,12 +5000,13 @@ window.AFRAME.registerComponent('xrf-pinchmove', {
// multiply the direction by a "speed" factor
direction.multiplyScalar(0.4)
// get the current position
var pos = player.getAttribute("position")
var pos = xrf.camera.position
//player.getAttribute("position")
// add the direction vector
pos.x += direction.x
pos.z += direction.z
// set the new position
this.data.rig.setAttribute("position", pos);
//this.data.rig.setAttribute("position", pos);
// !!! NOTE - it would be more efficient to do the
// position change on the players THREE.Object:
// `player.object3D.position.add(direction)`

198702
dist/xrfragment.module.js vendored

File diff suppressed because it is too large Load Diff

View File

@ -183,6 +183,7 @@ document.head.innerHTML += `
box-shadow: 0 0 4px 0 var(--xrf-box-shadow);
right: 20px;
position: fixed;
max-width:500px;
top: 18px;
}

View File

@ -869,4 +869,123 @@ chatComponent.css = `
top: 6px
}
</style>`
window.debug = (opts) => new Proxy({
opts,
enabled: false,
$console: false,
toggle(){ this.enabled = !this.enabled },
settings(){
this.toggle()
},
init(){
},
setupConsole(){
// add onscreen console
let $console = this.$console = document.createElement('pre')
$console.style.position = 'fixed'
$console.style.overflow = 'auto'
$console.style.top = $console.style.left = $console.style.bottom = $console.style.right = '0px'
$console.style.height = '98.5vh';
$console.style.width = '100%'
$console.style.pointerEvents = 'none'
$console.id = 'console'
document.body.appendChild($console)
const wrapper = (scope, fn, name) => {
return function(msg) {
$console.innerHTML += `[${name}] ${msg}<br>`;
if( name == 'err'){
let err = new Error()
String(err.stack).split("\n").slice(2).map( (l) => $console.innerHTML += ` └☑ ${l}\n` )
}
$console.scrollTop = $console.scrollHeight;
fn.call(scope,msg);
};
}
window.console.log = wrapper(console, console.log, "log");
window.console.warn = wrapper(console, console.warn, "wrn");
window.console.error = wrapper(console, console.error, "err");
}
},
{
// auto-trigger events on changes
get(data,k,receiver){ return data[k] },
set(data,k,v){
data[k] = v
switch( k ){
case "enabled": {
if( !data.$console ) data.setupConsole()
$('#debug.btn').style.filter= v ? 'brightness(1.0)' : 'brightness(0.5)'
data.$console.style.display = v ? 'block' : 'none'
data.enabled = v
}
}
}
})
document.addEventListener('$menu:ready', (e) => {
try{
debug = debug(e.detail)
debug.init()
document.dispatchEvent( new CustomEvent("debug:ready", e ) )
$menu.buttons = $menu.buttons.concat([`<a class="btn" style="background:var(--xrf-dark-gray);filter: brightness(0.5);" aria-label="button" aria-description="enable all debug features" id="debug" onclick="debug.enabled = !debug.enabled"><i class="gg-debug"></i>debug</a><br>`])
}catch(e){console.error(e)}
})
document.querySelector('head').innerHTML += `
<style type="text/css">
.gg-debug {
box-sizing: border-box;
position: relative;
display: block;
transform: scale(var(--ggs,1));
width: 12px;
height: 18px;
border: 2px solid;
border-radius: 22px;
display: inline-block;
transform: translate(0px,4px);
margin-right: 21px;
}
.gg-debug::after,
.gg-debug::before {
content: "";
display: block;
box-sizing: border-box;
position: absolute
}
.gg-debug::before {
width: 8px;
height: 4px;
border: 2px solid;
top: -4px;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
border-top: 0
}
.gg-debug::after {
background: currentColor;
width: 4px;
height: 2px;
border-radius: 5px;
top: 4px;
left: 2px;
box-shadow:
0 4px 0,
-6px -2px 0,
-6px 2px 0,
-6px 6px 0,
6px -2px 0,
6px 2px 0,
6px 6px 0
}
</style>
`
}).apply({})

View File

@ -1,5 +1,5 @@
/*
* v0.5.1 generated at Thu Apr 25 03:56:52 PM UTC 2024
* v0.5.1 generated at Tue Jun 4 04:54:19 PM UTC 2024
* https://xrfragment.org
* SPDX-License-Identifier: MPL-2.0
*/
@ -1591,15 +1591,17 @@ var xrf = {}
xrf.init = function(opts){
opts = opts || {}
xrf.debug = document.location.hostname.match(/^(localhost|[0-9])/) ? 0 : false
if( !xrf.debug ){
xrf.debug = document.location.hostname.match(/^(localhost|[0-9]\.[0-9])/) || document.location.port == '8080' ? 0 : false
if( xrf.debug === false ){
console.log("add #debug=[0-9] to URL to see XR Fragment debuglog")
xrf.debug = parseInt( ( document.location.hash.match(/debug=([0-9])/) || [0,'0'] )[1] )
}else{
xrf.stats()
}
xrf.Parser.debug = xrf.debug
xrf.detectCameraRig(opts)
for ( let i in opts ) xrf[i] = opts[i]
for ( let i in opts ) xrf[i] = opts[i]
xrf.emit('init',opts)
return xrf
}
@ -1626,10 +1628,9 @@ xrf.detectCameraRig = function(opts){
xrf.stats = () => {
// bookmarklet from https://github.com/zlgenuine/threejs_stats
(function(){
for( let i = 0; i < 4; i++ ){
var script=document.createElement('script');script.onload=function(){var stats=new Stats();stats.showPanel( i );
stats.dom.style.marginTop = `${i*48}px`; document.body.appendChild(stats.dom);requestAnimationFrame(function loop(){stats.update();requestAnimationFrame(loop)});};script.src='//rawgit.com/mrdoob/stats.js/master/build/stats.min.js';document.head.appendChild(script);
}
let i = 0;
var script=document.createElement('script');script.onload=function(){var stats=new Stats();stats.showPanel( i );
stats.dom.style.marginTop = `${i*48}px`; document.body.appendChild(stats.dom);requestAnimationFrame(function loop(){stats.update();requestAnimationFrame(loop)});};script.src='//rawgit.com/mrdoob/stats.js/master/build/stats.min.js';document.head.appendChild(script);
})()
}
@ -1905,14 +1906,17 @@ xrf.model = {}
xrf.mixers = []
xrf.init = ((init) => function(opts){
// operate in own subscene
let scene = new opts.THREE.Group()
opts.scene.add(scene)
opts.scene = scene
opts.sceneRoot = opts.scene
opts.scene = scene
init(opts)
//if( opts.loaders ) Object.values(opts.loaders).map( xrf.patchLoader )
xrf.patchRenderer(opts)
xrf.navigator.init()
xrf.interactive = xrf.interactiveGroup( xrf.THREE, xrf.renderer, xrf.camera)
// return xrfragment lib as 'xrf' query functor (like jquery)
for ( let i in xrf ) xrf.query[i] = xrf[i]
@ -1983,11 +1987,11 @@ xrf.reset = () => {
obj.removeFromParent()
return true
};
// also remove XRF objects from global scene
let nodes = []
xrf.scene.traverse( (child) => child.isXRF && (nodes.push(child)) )
nodes.map( disposeObject ) // leave non-XRF objects intact
xrf.interactive = xrf.interactiveGroup( xrf.THREE, xrf.renderer, xrf.camera)
xrf.add( xrf.interactive )
nodes.map( disposeObject )
xrf.interactive.clear()
xrf.layers = 0
}
@ -3024,7 +3028,6 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
if ( intersects.length > 0 ) {
console.log(object.name)
const intersection = intersects[ 0 ];
@ -3032,6 +3035,7 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
const uv = intersection.uv;
_event.type = eventsMapper[ event.type ];
console.log( (new Date()).getTime()+" "+event.type+":"+_event.type+" "+object.name)
if( uv ) _event.data.set( uv.x, 1 - uv.y );
object.dispatchEvent( _event );
@ -3066,6 +3070,11 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
this.objects.push(obj)
}
clear(){
while( this.children[0] != undefined ) this.children[0].remove()
this.objects = []
}
}
return new interactive(renderer,camera)
@ -3250,7 +3259,7 @@ xrf.filter.process = function(frag,scene,opts){
if( processed ) processed[n.uuid] == true
}
// spec 2: https://xrfragment.org/doc/RFC_XR_Macros.html#embedding-xr-content-using-src
// spec 3 @ https://xrfragment.org/doc/RFC_XR_Macros.html#embedding-xr-content-using-src
// reparent scene based on objectname in case it matches a (non-negating) selector
if( opts.reparent && firstFilter && !firstFilter.value && firstFilter.show === true ){
let obj

View File

@ -1,5 +1,5 @@
/*
* v0.5.1 generated at Thu Apr 25 03:56:52 PM UTC 2024
* v0.5.1 generated at Tue Jun 4 04:54:19 PM UTC 2024
* https://xrfragment.org
* SPDX-License-Identifier: MPL-2.0
*/
@ -1591,15 +1591,17 @@ var xrf = {}
xrf.init = function(opts){
opts = opts || {}
xrf.debug = document.location.hostname.match(/^(localhost|[0-9])/) ? 0 : false
if( !xrf.debug ){
xrf.debug = document.location.hostname.match(/^(localhost|[0-9]\.[0-9])/) || document.location.port == '8080' ? 0 : false
if( xrf.debug === false ){
console.log("add #debug=[0-9] to URL to see XR Fragment debuglog")
xrf.debug = parseInt( ( document.location.hash.match(/debug=([0-9])/) || [0,'0'] )[1] )
}else{
xrf.stats()
}
xrf.Parser.debug = xrf.debug
xrf.detectCameraRig(opts)
for ( let i in opts ) xrf[i] = opts[i]
for ( let i in opts ) xrf[i] = opts[i]
xrf.emit('init',opts)
return xrf
}
@ -1626,10 +1628,9 @@ xrf.detectCameraRig = function(opts){
xrf.stats = () => {
// bookmarklet from https://github.com/zlgenuine/threejs_stats
(function(){
for( let i = 0; i < 4; i++ ){
var script=document.createElement('script');script.onload=function(){var stats=new Stats();stats.showPanel( i );
stats.dom.style.marginTop = `${i*48}px`; document.body.appendChild(stats.dom);requestAnimationFrame(function loop(){stats.update();requestAnimationFrame(loop)});};script.src='//rawgit.com/mrdoob/stats.js/master/build/stats.min.js';document.head.appendChild(script);
}
let i = 0;
var script=document.createElement('script');script.onload=function(){var stats=new Stats();stats.showPanel( i );
stats.dom.style.marginTop = `${i*48}px`; document.body.appendChild(stats.dom);requestAnimationFrame(function loop(){stats.update();requestAnimationFrame(loop)});};script.src='//rawgit.com/mrdoob/stats.js/master/build/stats.min.js';document.head.appendChild(script);
})()
}
@ -1905,14 +1906,17 @@ xrf.model = {}
xrf.mixers = []
xrf.init = ((init) => function(opts){
// operate in own subscene
let scene = new opts.THREE.Group()
opts.scene.add(scene)
opts.scene = scene
opts.sceneRoot = opts.scene
opts.scene = scene
init(opts)
//if( opts.loaders ) Object.values(opts.loaders).map( xrf.patchLoader )
xrf.patchRenderer(opts)
xrf.navigator.init()
xrf.interactive = xrf.interactiveGroup( xrf.THREE, xrf.renderer, xrf.camera)
// return xrfragment lib as 'xrf' query functor (like jquery)
for ( let i in xrf ) xrf.query[i] = xrf[i]
@ -1983,11 +1987,11 @@ xrf.reset = () => {
obj.removeFromParent()
return true
};
// also remove XRF objects from global scene
let nodes = []
xrf.scene.traverse( (child) => child.isXRF && (nodes.push(child)) )
nodes.map( disposeObject ) // leave non-XRF objects intact
xrf.interactive = xrf.interactiveGroup( xrf.THREE, xrf.renderer, xrf.camera)
xrf.add( xrf.interactive )
nodes.map( disposeObject )
xrf.interactive.clear()
xrf.layers = 0
}
@ -3024,7 +3028,6 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
if ( intersects.length > 0 ) {
console.log(object.name)
const intersection = intersects[ 0 ];
@ -3032,6 +3035,7 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
const uv = intersection.uv;
_event.type = eventsMapper[ event.type ];
console.log( (new Date()).getTime()+" "+event.type+":"+_event.type+" "+object.name)
if( uv ) _event.data.set( uv.x, 1 - uv.y );
object.dispatchEvent( _event );
@ -3066,6 +3070,11 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
this.objects.push(obj)
}
clear(){
while( this.children[0] != undefined ) this.children[0].remove()
this.objects = []
}
}
return new interactive(renderer,camera)
@ -3250,7 +3259,7 @@ xrf.filter.process = function(frag,scene,opts){
if( processed ) processed[n.uuid] == true
}
// spec 2: https://xrfragment.org/doc/RFC_XR_Macros.html#embedding-xr-content-using-src
// spec 3 @ https://xrfragment.org/doc/RFC_XR_Macros.html#embedding-xr-content-using-src
// reparent scene based on objectname in case it matches a (non-negating) selector
if( opts.reparent && firstFilter && !firstFilter.value && firstFilter.show === true ){
let obj

2
make
View File

@ -119,7 +119,7 @@ build(){
example/assets/js/qr.js > dist/xrfragment.aframe.js
# plugins
jscat src/3rd/js/plugin/frontend/{network,\$connections,\$chat}.js > dist/xrfragment.plugin.network.js
jscat src/3rd/js/plugin/frontend/{network,\$connections,\$chat,debug}.js > dist/xrfragment.plugin.network.js
cp src/3rd/js/plugin/frontend/\$editor.js dist/xrfragment.plugin.editor.js
cp src/3rd/js/plugin/frontend/css.js dist/xrfragment.plugin.frontend.css.js

View File

@ -70,8 +70,8 @@ window.AFRAME.registerComponent('xrf', {
let pos = xrf.frag.pos.last
if( pos ){ AFRAME.XRF.camera.position.set(pos.x, pos.y*scale, pos.z) }
}
aScene.addEventListener('enter-vr', repositionUser(1) )
aScene.addEventListener('enter-ar', repositionUser(2) )
aScene.addEventListener('enter-vr', () => setTimeout( () => repositionUser(1),100 ) )
aScene.addEventListener('enter-ar', () => setTimeout( () => repositionUser(2),100 ) )
xrf.addEventListener('navigateLoaded', (opts) => {
setTimeout( () => AFRAME.fade.out(),500)
@ -158,12 +158,6 @@ window.AFRAME.registerComponent('xrf', {
}
xrf.addEventListener('interactionReady', AFRAME.XRF.clickableMeshToEntity )
// 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) )
})
if( typeof this.data === 'string' || this.data.http || this.data.https ){
let url
if( typeof this.data === 'string' ) url = this.data

View File

@ -17,7 +17,7 @@ window.AFRAME.registerComponent('xrf-get', {
setTimeout( () => {
if( !this.mesh ){
let scene = AFRAME.XRF.scene
let scene = xrf.scene
let mesh = this.mesh = scene.getObjectByName(meshname);
if( !this.el.className.match(/ray/) ) this.el.className += " ray"
if (!mesh){
@ -56,17 +56,6 @@ window.AFRAME.registerComponent('xrf-get', {
this.el.emit("update",{timeout:0})
AFRAME.XRF.addEventListener('reset', () => {
try{
if( this.el ){
while ( this.el.object3D.children.length ){
this.el.object3D.children[0].remove()
}
this.el.remove()
}
}catch(e){}
})
}
});

View File

@ -13,12 +13,13 @@ window.AFRAME.registerComponent('xrf-pinchmove', {
// multiply the direction by a "speed" factor
direction.multiplyScalar(0.4)
// get the current position
var pos = player.getAttribute("position")
var pos = xrf.camera.position
//player.getAttribute("position")
// add the direction vector
pos.x += direction.x
pos.z += direction.z
// set the new position
this.data.rig.setAttribute("position", pos);
//this.data.rig.setAttribute("position", pos);
// !!! NOTE - it would be more efficient to do the
// position change on the players THREE.Object:
// `player.object3D.position.add(direction)`

View File

@ -6,15 +6,17 @@ var xrf = {}
xrf.init = function(opts){
opts = opts || {}
xrf.debug = document.location.hostname.match(/^(localhost|[0-9])/) ? 0 : false
if( !xrf.debug ){
xrf.debug = document.location.hostname.match(/^(localhost|[0-9]\.[0-9])/) || document.location.port == '8080' ? 0 : false
if( xrf.debug === false ){
console.log("add #debug=[0-9] to URL to see XR Fragment debuglog")
xrf.debug = parseInt( ( document.location.hash.match(/debug=([0-9])/) || [0,'0'] )[1] )
}else{
xrf.stats()
}
xrf.Parser.debug = xrf.debug
xrf.detectCameraRig(opts)
for ( let i in opts ) xrf[i] = opts[i]
for ( let i in opts ) xrf[i] = opts[i]
xrf.emit('init',opts)
return xrf
}
@ -41,10 +43,9 @@ xrf.detectCameraRig = function(opts){
xrf.stats = () => {
// bookmarklet from https://github.com/zlgenuine/threejs_stats
(function(){
for( let i = 0; i < 4; i++ ){
var script=document.createElement('script');script.onload=function(){var stats=new Stats();stats.showPanel( i );
stats.dom.style.marginTop = `${i*48}px`; document.body.appendChild(stats.dom);requestAnimationFrame(function loop(){stats.update();requestAnimationFrame(loop)});};script.src='//rawgit.com/mrdoob/stats.js/master/build/stats.min.js';document.head.appendChild(script);
}
let i = 0;
var script=document.createElement('script');script.onload=function(){var stats=new Stats();stats.showPanel( i );
stats.dom.style.marginTop = `${i*48}px`; document.body.appendChild(stats.dom);requestAnimationFrame(function loop(){stats.update();requestAnimationFrame(loop)});};script.src='//rawgit.com/mrdoob/stats.js/master/build/stats.min.js';document.head.appendChild(script);
})()
}

View File

@ -0,0 +1,119 @@
window.debug = (opts) => new Proxy({
opts,
enabled: false,
$console: false,
toggle(){ this.enabled = !this.enabled },
settings(){
this.toggle()
},
init(){
},
setupConsole(){
// add onscreen console
let $console = this.$console = document.createElement('pre')
$console.style.position = 'fixed'
$console.style.overflow = 'auto'
$console.style.top = $console.style.left = $console.style.bottom = $console.style.right = '0px'
$console.style.height = '98.5vh';
$console.style.width = '100%'
$console.style.pointerEvents = 'none'
$console.id = 'console'
document.body.appendChild($console)
const wrapper = (scope, fn, name) => {
return function(msg) {
$console.innerHTML += `[${name}] ${msg}<br>`;
if( name == 'err'){
let err = new Error()
String(err.stack).split("\n").slice(2).map( (l) => $console.innerHTML += ` └☑ ${l}\n` )
}
$console.scrollTop = $console.scrollHeight;
fn.call(scope,msg);
};
}
window.console.log = wrapper(console, console.log, "log");
window.console.warn = wrapper(console, console.warn, "wrn");
window.console.error = wrapper(console, console.error, "err");
}
},
{
// auto-trigger events on changes
get(data,k,receiver){ return data[k] },
set(data,k,v){
data[k] = v
switch( k ){
case "enabled": {
if( !data.$console ) data.setupConsole()
$('#debug.btn').style.filter= v ? 'brightness(1.0)' : 'brightness(0.5)'
data.$console.style.display = v ? 'block' : 'none'
data.enabled = v
}
}
}
})
document.addEventListener('$menu:ready', (e) => {
try{
debug = debug(e.detail)
debug.init()
document.dispatchEvent( new CustomEvent("debug:ready", e ) )
$menu.buttons = $menu.buttons.concat([`<a class="btn" style="background:var(--xrf-dark-gray);filter: brightness(0.5);" aria-label="button" aria-description="enable all debug features" id="debug" onclick="debug.enabled = !debug.enabled"><i class="gg-debug"></i>debug</a><br>`])
}catch(e){console.error(e)}
})
document.querySelector('head').innerHTML += `
<style type="text/css">
.gg-debug {
box-sizing: border-box;
position: relative;
display: block;
transform: scale(var(--ggs,1));
width: 12px;
height: 18px;
border: 2px solid;
border-radius: 22px;
display: inline-block;
transform: translate(0px,4px);
margin-right: 21px;
}
.gg-debug::after,
.gg-debug::before {
content: "";
display: block;
box-sizing: border-box;
position: absolute
}
.gg-debug::before {
width: 8px;
height: 4px;
border: 2px solid;
top: -4px;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
border-top: 0
}
.gg-debug::after {
background: currentColor;
width: 4px;
height: 2px;
border-radius: 5px;
top: 4px;
left: 2px;
box-shadow:
0 4px 0,
-6px -2px 0,
-6px 2px 0,
-6px 6px 0,
6px -2px 0,
6px 2px 0,
6px 6px 0
}
</style>
`

View File

@ -182,6 +182,7 @@ document.head.innerHTML += `
box-shadow: 0 0 4px 0 var(--xrf-box-shadow);
right: 20px;
position: fixed;
max-width:500px;
top: 18px;
}

View File

@ -3,14 +3,17 @@ xrf.model = {}
xrf.mixers = []
xrf.init = ((init) => function(opts){
// operate in own subscene
let scene = new opts.THREE.Group()
opts.scene.add(scene)
opts.scene = scene
opts.sceneRoot = opts.scene
opts.scene = scene
init(opts)
//if( opts.loaders ) Object.values(opts.loaders).map( xrf.patchLoader )
xrf.patchRenderer(opts)
xrf.navigator.init()
xrf.interactive = xrf.interactiveGroup( xrf.THREE, xrf.renderer, xrf.camera)
// return xrfragment lib as 'xrf' query functor (like jquery)
for ( let i in xrf ) xrf.query[i] = xrf[i]
@ -81,11 +84,11 @@ xrf.reset = () => {
obj.removeFromParent()
return true
};
// also remove XRF objects from global scene
let nodes = []
xrf.scene.traverse( (child) => child.isXRF && (nodes.push(child)) )
nodes.map( disposeObject ) // leave non-XRF objects intact
xrf.interactive = xrf.interactiveGroup( xrf.THREE, xrf.renderer, xrf.camera)
xrf.add( xrf.interactive )
nodes.map( disposeObject )
xrf.interactive.clear()
xrf.layers = 0
}

View File

@ -110,7 +110,6 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
if ( intersects.length > 0 ) {
console.log(object.name)
const intersection = intersects[ 0 ];
@ -118,6 +117,7 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
const uv = intersection.uv;
_event.type = eventsMapper[ event.type ];
console.log( (new Date()).getTime()+" "+event.type+":"+_event.type+" "+object.name)
if( uv ) _event.data.set( uv.x, 1 - uv.y );
object.dispatchEvent( _event );
@ -152,6 +152,11 @@ xrf.interactiveGroup = function(THREE,renderer,camera){
this.objects.push(obj)
}
clear(){
while( this.children[0] != undefined ) this.children[0].remove()
this.objects = []
}
}
return new interactive(renderer,camera)