added xrf-gaze for mobile (AR/VR)
This commit is contained in:
parent
94f06d8c2d
commit
b3c8d06955
8 changed files with 200 additions and 33 deletions
90
dist/xrfragment.aframe.js
vendored
90
dist/xrfragment.aframe.js
vendored
|
|
@ -922,6 +922,7 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
const _pointer = new Vector2();
|
||||
const _event = { type: '', data: _pointer };
|
||||
let object = {selected:false}
|
||||
|
||||
class InteractiveGroup extends Group {
|
||||
|
||||
|
|
@ -944,7 +945,7 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
if( nocollide.tid ) return // ratelimit
|
||||
_event.type = "nocollide"
|
||||
scope.objects.map( (c) => c.dispatchEvent(_event) )
|
||||
nocollide.tid = setTimeout( () => nocollide.tid = null, 100 )
|
||||
nocollide.tid = setTimeout( () => nocollide.tid = null, 10 )
|
||||
}
|
||||
|
||||
// Pointer Events
|
||||
|
|
@ -968,15 +969,19 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
const intersection = intersects[ 0 ];
|
||||
|
||||
const object = intersection.object;
|
||||
object = intersection.object;
|
||||
const uv = intersection.uv;
|
||||
|
||||
_event.type = event.type;
|
||||
_event.data.set( uv.x, 1 - uv.y );
|
||||
|
||||
object.dispatchEvent( _event );
|
||||
|
||||
}else nocollide()
|
||||
}else{
|
||||
if( object.selected ) {
|
||||
_event.type = 'mouseleave'
|
||||
object.dispatchEvent(_event)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1013,7 +1018,7 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
const intersection = intersections[ 0 ];
|
||||
|
||||
const object = intersection.object;
|
||||
object = intersection.object;
|
||||
const uv = intersection.uv;
|
||||
|
||||
_event.type = events[ event.type ];
|
||||
|
|
@ -1021,7 +1026,12 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
object.dispatchEvent( _event );
|
||||
|
||||
}else nocollide()
|
||||
}else{
|
||||
if( object.selected ) {
|
||||
_event.type = 'mouseleave'
|
||||
object.dispatchEvent(_event)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1435,7 +1445,7 @@ xrf.frag.href = function(v, opts){
|
|||
.catch( console.error )
|
||||
}
|
||||
|
||||
let selected = (state) => () => {
|
||||
let selected = mesh.userData.XRF.href.selected = (state) => () => {
|
||||
if( mesh.selected == state ) return // nothing changed
|
||||
xrf.interactive.objects.map( (o) => {
|
||||
let newState = o.name == mesh.name ? state : false
|
||||
|
|
@ -1456,7 +1466,7 @@ xrf.frag.href = function(v, opts){
|
|||
|
||||
mesh.addEventListener('click', click )
|
||||
mesh.addEventListener('mousemove', selected(true) )
|
||||
mesh.addEventListener('nocollide', selected(false) )
|
||||
mesh.addEventListener('mouseleave', selected(false) )
|
||||
|
||||
// lazy add mesh (because we're inside a recursive traverse)
|
||||
setTimeout( (mesh) => {
|
||||
|
|
@ -2020,6 +2030,10 @@ window.AFRAME.registerComponent('xrf', {
|
|||
})
|
||||
|
||||
aScene.emit('XRF',{})
|
||||
|
||||
// enable gaze-click on Mobile VR
|
||||
aScene.setAttribute('xrf-gaze','')
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -2139,6 +2153,66 @@ window.AFRAME.registerComponent('xrf-button', {
|
|||
});
|
||||
}
|
||||
});
|
||||
// gaze click on mobile VR
|
||||
|
||||
AFRAME.registerComponent('xrf-gaze',{
|
||||
schema:{
|
||||
spawn:{type:'boolean',default:false},
|
||||
},
|
||||
setGazer: function(state){
|
||||
let cam = document.querySelector("[camera]")
|
||||
if( state ){
|
||||
if( cam.innerHTML.match(/cursor/) ) return; // avoid duplicate calls
|
||||
cam.innerHTML = `<a-entity id="cursor" cursor="fuse: true; fuseTimeout: 1500"
|
||||
animation__click="property: scale; startEvents: click; easing: easeInCubic; dur: 150; from: 0.1 0.1 0.1; to: 1 1 1"
|
||||
animation__fusing="property: scale; startEvents: fusing; easing: easeInCubic; dur: 1500; from: 1 1 1; to: 0.1 0.1 0.1"
|
||||
animation__mouseleave="property: scale; startEvents: mouseleave; easing: easeInCubic; dur: 500; to: 1 1 1"
|
||||
raycaster="objects: .ray"
|
||||
visible="true"
|
||||
position="0 0 -1"
|
||||
geometry="primitive: ring; radiusInner: 0.02; radiusOuter: 0.03"
|
||||
material="color: #BBBBBB; shader: flat">
|
||||
</a-entity>`
|
||||
}else{
|
||||
cam.innerHTML = ''
|
||||
}
|
||||
},
|
||||
init:function(data){
|
||||
this.immersive = false;
|
||||
let enabled = () => AFRAME.utils.device.isMobile()
|
||||
let setVisible = () => this.el.setAttribute('visible', enabled() )
|
||||
this.setGazer(enabled())
|
||||
setVisible();
|
||||
|
||||
document.querySelector("a-scene").addEventListener('exit-vr', () => {
|
||||
this.immersive = false;
|
||||
setVisible()
|
||||
})
|
||||
document.querySelector("a-scene").addEventListener('enter-vr', () => {
|
||||
this.immersive = true;
|
||||
setVisible()
|
||||
if( !document.querySelector("#cursor") ) return
|
||||
})
|
||||
|
||||
|
||||
let highlightMesh = (state) => (e) => {
|
||||
if( !e.target.object3D ) return
|
||||
let obj = e.target.object3D.children[0]
|
||||
if( obj.userData && obj.userData.XRF && obj.userData.XRF.href )
|
||||
obj.userData.XRF.href.selected( state )()
|
||||
}
|
||||
this.el.addEventListener("mouseenter", highlightMesh(true) )
|
||||
this.el.addEventListener("mouseleave", highlightMesh(false ) )
|
||||
|
||||
//this.el.addEventListener('click',function(evt){
|
||||
// document.querySelector('a-scene').querySelector('#player').setAttribute('position',{
|
||||
// x:this.getAttribute('position').x,
|
||||
// y:this.getAttribute('position').y,
|
||||
// z:this.getAttribute('position').z
|
||||
// });
|
||||
//});
|
||||
}
|
||||
});
|
||||
window.AFRAME.registerComponent('xrf-get', {
|
||||
schema: {
|
||||
name: {type: 'string'},
|
||||
|
|
|
|||
26
dist/xrfragment.three.js
vendored
26
dist/xrfragment.three.js
vendored
|
|
@ -922,6 +922,7 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
const _pointer = new Vector2();
|
||||
const _event = { type: '', data: _pointer };
|
||||
let object = {selected:false}
|
||||
|
||||
class InteractiveGroup extends Group {
|
||||
|
||||
|
|
@ -944,7 +945,7 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
if( nocollide.tid ) return // ratelimit
|
||||
_event.type = "nocollide"
|
||||
scope.objects.map( (c) => c.dispatchEvent(_event) )
|
||||
nocollide.tid = setTimeout( () => nocollide.tid = null, 100 )
|
||||
nocollide.tid = setTimeout( () => nocollide.tid = null, 10 )
|
||||
}
|
||||
|
||||
// Pointer Events
|
||||
|
|
@ -968,15 +969,19 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
const intersection = intersects[ 0 ];
|
||||
|
||||
const object = intersection.object;
|
||||
object = intersection.object;
|
||||
const uv = intersection.uv;
|
||||
|
||||
_event.type = event.type;
|
||||
_event.data.set( uv.x, 1 - uv.y );
|
||||
|
||||
object.dispatchEvent( _event );
|
||||
|
||||
}else nocollide()
|
||||
}else{
|
||||
if( object.selected ) {
|
||||
_event.type = 'mouseleave'
|
||||
object.dispatchEvent(_event)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1013,7 +1018,7 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
const intersection = intersections[ 0 ];
|
||||
|
||||
const object = intersection.object;
|
||||
object = intersection.object;
|
||||
const uv = intersection.uv;
|
||||
|
||||
_event.type = events[ event.type ];
|
||||
|
|
@ -1021,7 +1026,12 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
object.dispatchEvent( _event );
|
||||
|
||||
}else nocollide()
|
||||
}else{
|
||||
if( object.selected ) {
|
||||
_event.type = 'mouseleave'
|
||||
object.dispatchEvent(_event)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1435,7 +1445,7 @@ xrf.frag.href = function(v, opts){
|
|||
.catch( console.error )
|
||||
}
|
||||
|
||||
let selected = (state) => () => {
|
||||
let selected = mesh.userData.XRF.href.selected = (state) => () => {
|
||||
if( mesh.selected == state ) return // nothing changed
|
||||
xrf.interactive.objects.map( (o) => {
|
||||
let newState = o.name == mesh.name ? state : false
|
||||
|
|
@ -1456,7 +1466,7 @@ xrf.frag.href = function(v, opts){
|
|||
|
||||
mesh.addEventListener('click', click )
|
||||
mesh.addEventListener('mousemove', selected(true) )
|
||||
mesh.addEventListener('nocollide', selected(false) )
|
||||
mesh.addEventListener('mouseleave', selected(false) )
|
||||
|
||||
// lazy add mesh (because we're inside a recursive traverse)
|
||||
setTimeout( (mesh) => {
|
||||
|
|
|
|||
26
dist/xrfragment.three.module.js
vendored
26
dist/xrfragment.three.module.js
vendored
|
|
@ -922,6 +922,7 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
const _pointer = new Vector2();
|
||||
const _event = { type: '', data: _pointer };
|
||||
let object = {selected:false}
|
||||
|
||||
class InteractiveGroup extends Group {
|
||||
|
||||
|
|
@ -944,7 +945,7 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
if( nocollide.tid ) return // ratelimit
|
||||
_event.type = "nocollide"
|
||||
scope.objects.map( (c) => c.dispatchEvent(_event) )
|
||||
nocollide.tid = setTimeout( () => nocollide.tid = null, 100 )
|
||||
nocollide.tid = setTimeout( () => nocollide.tid = null, 10 )
|
||||
}
|
||||
|
||||
// Pointer Events
|
||||
|
|
@ -968,15 +969,19 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
const intersection = intersects[ 0 ];
|
||||
|
||||
const object = intersection.object;
|
||||
object = intersection.object;
|
||||
const uv = intersection.uv;
|
||||
|
||||
_event.type = event.type;
|
||||
_event.data.set( uv.x, 1 - uv.y );
|
||||
|
||||
object.dispatchEvent( _event );
|
||||
|
||||
}else nocollide()
|
||||
}else{
|
||||
if( object.selected ) {
|
||||
_event.type = 'mouseleave'
|
||||
object.dispatchEvent(_event)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1013,7 +1018,7 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
const intersection = intersections[ 0 ];
|
||||
|
||||
const object = intersection.object;
|
||||
object = intersection.object;
|
||||
const uv = intersection.uv;
|
||||
|
||||
_event.type = events[ event.type ];
|
||||
|
|
@ -1021,7 +1026,12 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
object.dispatchEvent( _event );
|
||||
|
||||
}else nocollide()
|
||||
}else{
|
||||
if( object.selected ) {
|
||||
_event.type = 'mouseleave'
|
||||
object.dispatchEvent(_event)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1435,7 +1445,7 @@ xrf.frag.href = function(v, opts){
|
|||
.catch( console.error )
|
||||
}
|
||||
|
||||
let selected = (state) => () => {
|
||||
let selected = mesh.userData.XRF.href.selected = (state) => () => {
|
||||
if( mesh.selected == state ) return // nothing changed
|
||||
xrf.interactive.objects.map( (o) => {
|
||||
let newState = o.name == mesh.name ? state : false
|
||||
|
|
@ -1456,7 +1466,7 @@ xrf.frag.href = function(v, opts){
|
|||
|
||||
mesh.addEventListener('click', click )
|
||||
mesh.addEventListener('mousemove', selected(true) )
|
||||
mesh.addEventListener('nocollide', selected(false) )
|
||||
mesh.addEventListener('mouseleave', selected(false) )
|
||||
|
||||
// lazy add mesh (because we're inside a recursive traverse)
|
||||
setTimeout( (mesh) => {
|
||||
|
|
|
|||
|
|
@ -209,7 +209,6 @@ function SnackBar(userOptions) {
|
|||
if (userOptions.status !== undefined) {
|
||||
_Options.status = userOptions.status;
|
||||
}
|
||||
console.dir(_Options)
|
||||
}
|
||||
|
||||
snackbar.Open = function() {
|
||||
|
|
|
|||
|
|
@ -85,6 +85,10 @@ window.AFRAME.registerComponent('xrf', {
|
|||
})
|
||||
|
||||
aScene.emit('XRF',{})
|
||||
|
||||
// enable gaze-click on Mobile VR
|
||||
aScene.setAttribute('xrf-gaze','')
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
60
src/3rd/js/aframe/xrf-gaze.js
Normal file
60
src/3rd/js/aframe/xrf-gaze.js
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// gaze click on mobile VR
|
||||
|
||||
AFRAME.registerComponent('xrf-gaze',{
|
||||
schema:{
|
||||
spawn:{type:'boolean',default:false},
|
||||
},
|
||||
setGazer: function(state){
|
||||
let cam = document.querySelector("[camera]")
|
||||
if( state ){
|
||||
if( cam.innerHTML.match(/cursor/) ) return; // avoid duplicate calls
|
||||
cam.innerHTML = `<a-entity id="cursor" cursor="fuse: true; fuseTimeout: 1500"
|
||||
animation__click="property: scale; startEvents: click; easing: easeInCubic; dur: 150; from: 0.1 0.1 0.1; to: 1 1 1"
|
||||
animation__fusing="property: scale; startEvents: fusing; easing: easeInCubic; dur: 1500; from: 1 1 1; to: 0.1 0.1 0.1"
|
||||
animation__mouseleave="property: scale; startEvents: mouseleave; easing: easeInCubic; dur: 500; to: 1 1 1"
|
||||
raycaster="objects: .ray"
|
||||
visible="true"
|
||||
position="0 0 -1"
|
||||
geometry="primitive: ring; radiusInner: 0.02; radiusOuter: 0.03"
|
||||
material="color: #BBBBBB; shader: flat">
|
||||
</a-entity>`
|
||||
}else{
|
||||
cam.innerHTML = ''
|
||||
}
|
||||
},
|
||||
init:function(data){
|
||||
this.immersive = false;
|
||||
let enabled = () => AFRAME.utils.device.isMobile()
|
||||
let setVisible = () => this.el.setAttribute('visible', enabled() )
|
||||
this.setGazer(enabled())
|
||||
setVisible();
|
||||
|
||||
document.querySelector("a-scene").addEventListener('exit-vr', () => {
|
||||
this.immersive = false;
|
||||
setVisible()
|
||||
})
|
||||
document.querySelector("a-scene").addEventListener('enter-vr', () => {
|
||||
this.immersive = true;
|
||||
setVisible()
|
||||
if( !document.querySelector("#cursor") ) return
|
||||
})
|
||||
|
||||
|
||||
let highlightMesh = (state) => (e) => {
|
||||
if( !e.target.object3D ) return
|
||||
let obj = e.target.object3D.children[0]
|
||||
if( obj.userData && obj.userData.XRF && obj.userData.XRF.href )
|
||||
obj.userData.XRF.href.selected( state )()
|
||||
}
|
||||
this.el.addEventListener("mouseenter", highlightMesh(true) )
|
||||
this.el.addEventListener("mouseleave", highlightMesh(false ) )
|
||||
|
||||
//this.el.addEventListener('click',function(evt){
|
||||
// document.querySelector('a-scene').querySelector('#player').setAttribute('position',{
|
||||
// x:this.getAttribute('position').x,
|
||||
// y:this.getAttribute('position').y,
|
||||
// z:this.getAttribute('position').z
|
||||
// });
|
||||
//});
|
||||
}
|
||||
});
|
||||
|
|
@ -11,6 +11,7 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
const _pointer = new Vector2();
|
||||
const _event = { type: '', data: _pointer };
|
||||
let object = {selected:false}
|
||||
|
||||
class InteractiveGroup extends Group {
|
||||
|
||||
|
|
@ -33,7 +34,7 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
if( nocollide.tid ) return // ratelimit
|
||||
_event.type = "nocollide"
|
||||
scope.objects.map( (c) => c.dispatchEvent(_event) )
|
||||
nocollide.tid = setTimeout( () => nocollide.tid = null, 100 )
|
||||
nocollide.tid = setTimeout( () => nocollide.tid = null, 10 )
|
||||
}
|
||||
|
||||
// Pointer Events
|
||||
|
|
@ -57,15 +58,19 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
const intersection = intersects[ 0 ];
|
||||
|
||||
const object = intersection.object;
|
||||
object = intersection.object;
|
||||
const uv = intersection.uv;
|
||||
|
||||
_event.type = event.type;
|
||||
_event.data.set( uv.x, 1 - uv.y );
|
||||
|
||||
object.dispatchEvent( _event );
|
||||
|
||||
}else nocollide()
|
||||
}else{
|
||||
if( object.selected ) {
|
||||
_event.type = 'mouseleave'
|
||||
object.dispatchEvent(_event)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -102,7 +107,7 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
const intersection = intersections[ 0 ];
|
||||
|
||||
const object = intersection.object;
|
||||
object = intersection.object;
|
||||
const uv = intersection.uv;
|
||||
|
||||
_event.type = events[ event.type ];
|
||||
|
|
@ -110,7 +115,12 @@ xrf.InteractiveGroup = function(THREE,renderer,camera){
|
|||
|
||||
object.dispatchEvent( _event );
|
||||
|
||||
}else nocollide()
|
||||
}else{
|
||||
if( object.selected ) {
|
||||
_event.type = 'mouseleave'
|
||||
object.dispatchEvent(_event)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ xrf.frag.href = function(v, opts){
|
|||
.catch( console.error )
|
||||
}
|
||||
|
||||
let selected = (state) => () => {
|
||||
let selected = mesh.userData.XRF.href.selected = (state) => () => {
|
||||
if( mesh.selected == state ) return // nothing changed
|
||||
xrf.interactive.objects.map( (o) => {
|
||||
let newState = o.name == mesh.name ? state : false
|
||||
|
|
@ -127,7 +127,7 @@ xrf.frag.href = function(v, opts){
|
|||
|
||||
mesh.addEventListener('click', click )
|
||||
mesh.addEventListener('mousemove', selected(true) )
|
||||
mesh.addEventListener('nocollide', selected(false) )
|
||||
mesh.addEventListener('mouseleave', selected(false) )
|
||||
|
||||
// lazy add mesh (because we're inside a recursive traverse)
|
||||
setTimeout( (mesh) => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue