diff --git a/dist/xrfragment.aframe.js b/dist/xrfragment.aframe.js
index d5a0959..f22d6e3 100644
--- a/dist/xrfragment.aframe.js
+++ b/dist/xrfragment.aframe.js
@@ -1227,7 +1227,7 @@ window.AFRAME.registerComponent('xrf', {
// override the camera-related XR Fragments so the camera-rig is affected
let camOverride = (xrf,v,opts) => {
- opts.camera = $('[camera]').object3D.parent
+ opts.camera = document.querySelector('[camera]').object3D.parent
console.dir(opts.camera)
xrf(v,opts)
}
@@ -1240,7 +1240,7 @@ window.AFRAME.registerComponent('xrf', {
let {mesh,camera} = opts;
let el = document.createElement("a-entity")
el.setAttribute("xrf-get",mesh.name )
- el.setAttribute("class","collidable")
+ el.setAttribute("class","ray")
el.addEventListener("click", mesh.userData.XRF.href.exec )
$('a-scene').appendChild(el)
}
@@ -1253,22 +1253,118 @@ window.AFRAME.registerComponent('xrf', {
els.map( (el) => document.querySelector('a-scene').removeChild(el) )
})(XRF.reset)
- // disable cam-controls (which will block updating camerarig position)
- let coms = ['look-controls','wasd-controls']
- const setComponents = (com,state) => () => {
- coms.forEach( (com) => {
- let el = document.querySelector('['+com+']')
- if(!el) return
- el.components[com].enabled = state
- })
- }
- aScene.addEventListener('enter-vr', setComponents(coms,false) )
- aScene.addEventListener('enter-ar', setComponents(coms,false) )
- aScene.addEventListener('exit-vr', setComponents(coms,true) )
- aScene.addEventListener('exit-ar', setComponents(coms,true) )
+ // undo lookup-control shenanigans (which blocks updating camerarig position in VR)
+ aScene.addEventListener('enter-vr', () => document.querySelector('[camera]').object3D.parent.matrixAutoUpdate = true )
},
})
+window.AFRAME.registerComponent('xrf-button', {
+ schema: {
+ label: {
+ default: 'label'
+ },
+ width: {
+ default: 0.11
+ },
+ toggable: {
+ default: false
+ },
+ textSize: {
+ default: 0.66
+ },
+ color:{
+ default: '#111'
+ },
+ textColor:{
+ default: '#fff'
+ },
+ hicolor:{
+ default: '#555555'
+ },
+ action:{
+ default: ''
+ }
+ },
+ init: function() {
+ var el = this.el;
+ var labelEl = this.labelEl = document.createElement('a-entity');
+ this.color = this.data.color
+ el.setAttribute('geometry', {
+ primitive: 'box',
+ width: this.data.width,
+ height: 0.05,
+ depth: 0.005
+ });
+ el.setAttribute('material', {
+ color: this.color,
+ transparent:true,
+ opacity:0.3
+ });
+ el.setAttribute('pressable', '');
+ labelEl.setAttribute('position', '0 0 0.01');
+ labelEl.setAttribute('text', {
+ value: this.data.label,
+ color: this.data.textColor,
+ align: 'center'
+ });
+ labelEl.setAttribute('scale', `${this.data.textSize} ${this.data.textSize} ${this.data.textSize}`);
+ this.el.appendChild(labelEl);
+ this.bindMethods();
+ this.el.addEventListener('stateadded', this.stateChanged);
+ this.el.addEventListener('stateremoved', this.stateChanged);
+ this.el.addEventListener('pressedstarted', this.onPressedStarted);
+ this.el.addEventListener('pressedended', this.onPressedEnded);
+ this.el.addEventListener('mouseenter', (e) => this.onMouseEnter(e) );
+ this.el.addEventListener('mouseleave', (e) => this.onMouseLeave(e) );
+ if( this.data.action ){
+ this.el.addEventListener('click', new Function(this.data.action) )
+ }
+ },
+ bindMethods: function() {
+ this.stateChanged = this.stateChanged.bind(this);
+ this.onPressedStarted = this.onPressedStarted.bind(this);
+ this.onPressedEnded = this.onPressedEnded.bind(this);
+ },
+ update: function(oldData) {
+ if (oldData.label !== this.data.label) {
+ this.labelEl.setAttribute('text', 'value', this.data.label);
+ }
+ },
+ stateChanged: function() {
+ var color = this.el.is('pressed') ? this.data.hicolor : this.color;
+ this.el.setAttribute('material', {
+ color: color
+ });
+ },
+ onMouseEnter: function(){
+ this.el.setAttribute('material', { color: this.data.hicolor });
+ },
+ onMouseLeave: function(){
+ this.el.setAttribute('material', { color: this.color });
+ },
+ onPressedStarted: function() {
+ var el = this.el;
+ el.setAttribute('material', {
+ color: this.data.hicolor
+ });
+ el.emit('click');
+ if (this.data.togabble) {
+ if (el.is('pressed')) {
+ el.removeState('pressed');
+ } else {
+ el.addState('pressed');
+ }
+ }
+ },
+ onPressedEnded: function() {
+ if (this.el.is('pressed')) {
+ return;
+ }
+ this.el.setAttribute('material', {
+ color: this.color
+ });
+ }
+});
window.AFRAME.registerComponent('xrf-get', {
schema: {
name: {type: 'string'},
@@ -1298,9 +1394,35 @@ window.AFRAME.registerComponent('xrf-get', {
})
- if( this.el.className == "collidable" ) this.el.emit("update")
+ if( this.el.className == "ray" ) this.el.emit("update")
}
});
+window.AFRAME.registerComponent('xrf-wear', {
+ schema:{
+ el: {type:"selector"},
+ position: {type:"vec3"},
+ rotation: {type:"vec3"}
+ },
+ init: function(){
+ $('a-scene').addEventListener('enter-vr', (e) => this.wear(e) )
+ $('a-scene').addEventListener('exit-vr', (e) => this.unwear(e) )
+ },
+ wear: function(){
+ if( !this.wearable ){
+ let d = this.data
+ this.wearable = new THREE.Group()
+ this.el.object3D.children.map( (c) => this.wearable.add(c) )
+ this.wearable.position.set( d.position.x, d.position.y, d.position.z)
+ this.wearable.rotation.set( d.rotation.x, d.rotation.y, d.rotation.z)
+ }
+ this.data.el.object3D.add(this.wearable)
+ },
+ unwear: function(){
+ this.data.el.remove(this.wearable)
+ this.wearable.children.map( (c) => this.el.object3D.add(c) )
+ delete this.wearable
+ }
+})
diff --git a/example/aframe/sandbox/index.html b/example/aframe/sandbox/index.html
index 00f21a1..367f4f9 100644
--- a/example/aframe/sandbox/index.html
+++ b/example/aframe/sandbox/index.html
@@ -1,37 +1,43 @@
-
- AFRAME - xrfragment sandbox
-
-
+
+ AFRAME - xrfragment sandbox
+
+
-
+
-
-
-
+
+
+
-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
+ })
+
+
diff --git a/src/3rd/aframe/index.js b/src/3rd/aframe/index.js
index f4918f6..fb5ad06 100644
--- a/src/3rd/aframe/index.js
+++ b/src/3rd/aframe/index.js
@@ -31,7 +31,7 @@ window.AFRAME.registerComponent('xrf', {
// override the camera-related XR Fragments so the camera-rig is affected
let camOverride = (xrf,v,opts) => {
- opts.camera = $('[camera]').object3D.parent
+ opts.camera = document.querySelector('[camera]').object3D.parent
console.dir(opts.camera)
xrf(v,opts)
}
@@ -44,7 +44,7 @@ window.AFRAME.registerComponent('xrf', {
let {mesh,camera} = opts;
let el = document.createElement("a-entity")
el.setAttribute("xrf-get",mesh.name )
- el.setAttribute("class","collidable")
+ el.setAttribute("class","ray")
el.addEventListener("click", mesh.userData.XRF.href.exec )
$('a-scene').appendChild(el)
}
@@ -57,54 +57,7 @@ window.AFRAME.registerComponent('xrf', {
els.map( (el) => document.querySelector('a-scene').removeChild(el) )
})(XRF.reset)
- // disable cam-controls (which block updating camerarig position)
- let coms = ['look-controls','wasd-controls']
- const setComponents = (com,state) => () => {
- coms.forEach( (com) => {
- let el = document.querySelector('['+com+']')
- if(!el) return
- el.components[com].enabled = state
- })
- }
- aScene.addEventListener('enter-vr', setComponents(coms,false) )
- aScene.addEventListener('enter-ar', setComponents(coms,false) )
- aScene.addEventListener('exit-vr', setComponents(coms,true) )
- aScene.addEventListener('exit-ar', setComponents(coms,true) )
+ // undo lookup-control shenanigans (which blocks updating camerarig position in VR)
+ aScene.addEventListener('enter-vr', () => document.querySelector('[camera]').object3D.parent.matrixAutoUpdate = true )
},
})
-
-window.AFRAME.registerComponent('xrf-get', {
- schema: {
- name: {type: 'string'},
- clone: {type: 'boolean', default:false}
- },
-
- init: function () {
-
- var el = this.el;
- var meshname = this.data.name || this.data;
-
- this.el.addEventListener('update', (evt) => {
-
- let scene = AFRAME.XRF.scene
- let mesh = scene.getObjectByName(meshname);
- if (!mesh){
- console.error("mesh with name '"+meshname+"' not found in model")
- return;
- }
- if( !this.data.clone ) mesh.parent.remove(mesh)
- ////mesh.updateMatrixWorld();
- this.el.object3D.position.setFromMatrixPosition(scene.matrixWorld);
- this.el.object3D.quaternion.setFromRotationMatrix(scene.matrixWorld);
- mesh.xrf = true // mark for deletion by xrf
- this.el.setObject3D('mesh', mesh );
- if( !this.el.id ) this.el.setAttribute("id",`xrf-${mesh.name}`)
-
- })
-
- if( this.el.className == "collidable" ) this.el.emit("update")
-
- }
-
-});
-
diff --git a/src/3rd/aframe/xrf-button.js b/src/3rd/aframe/xrf-button.js
new file mode 100644
index 0000000..43ea9d6
--- /dev/null
+++ b/src/3rd/aframe/xrf-button.js
@@ -0,0 +1,108 @@
+window.AFRAME.registerComponent('xrf-button', {
+ schema: {
+ label: {
+ default: 'label'
+ },
+ width: {
+ default: 0.11
+ },
+ toggable: {
+ default: false
+ },
+ textSize: {
+ default: 0.66
+ },
+ color:{
+ default: '#111'
+ },
+ textColor:{
+ default: '#fff'
+ },
+ hicolor:{
+ default: '#555555'
+ },
+ action:{
+ default: ''
+ }
+ },
+ init: function() {
+ var el = this.el;
+ var labelEl = this.labelEl = document.createElement('a-entity');
+ this.color = this.data.color
+ el.setAttribute('geometry', {
+ primitive: 'box',
+ width: this.data.width,
+ height: 0.05,
+ depth: 0.005
+ });
+ el.setAttribute('material', {
+ color: this.color,
+ transparent:true,
+ opacity:0.3
+ });
+ el.setAttribute('pressable', '');
+ labelEl.setAttribute('position', '0 0 0.01');
+ labelEl.setAttribute('text', {
+ value: this.data.label,
+ color: this.data.textColor,
+ align: 'center'
+ });
+ labelEl.setAttribute('scale', `${this.data.textSize} ${this.data.textSize} ${this.data.textSize}`);
+ this.el.appendChild(labelEl);
+ this.bindMethods();
+ this.el.addEventListener('stateadded', this.stateChanged);
+ this.el.addEventListener('stateremoved', this.stateChanged);
+ this.el.addEventListener('pressedstarted', this.onPressedStarted);
+ this.el.addEventListener('pressedended', this.onPressedEnded);
+ this.el.addEventListener('mouseenter', (e) => this.onMouseEnter(e) );
+ this.el.addEventListener('mouseleave', (e) => this.onMouseLeave(e) );
+
+ if( this.data.action ){
+ this.el.addEventListener('click', new Function(this.data.action) )
+ }
+ },
+ bindMethods: function() {
+ this.stateChanged = this.stateChanged.bind(this);
+ this.onPressedStarted = this.onPressedStarted.bind(this);
+ this.onPressedEnded = this.onPressedEnded.bind(this);
+ },
+ update: function(oldData) {
+ if (oldData.label !== this.data.label) {
+ this.labelEl.setAttribute('text', 'value', this.data.label);
+ }
+ },
+ stateChanged: function() {
+ var color = this.el.is('pressed') ? this.data.hicolor : this.color;
+ this.el.setAttribute('material', {
+ color: color
+ });
+ },
+ onMouseEnter: function(){
+ this.el.setAttribute('material', { color: this.data.hicolor });
+ },
+ onMouseLeave: function(){
+ this.el.setAttribute('material', { color: this.color });
+ },
+ onPressedStarted: function() {
+ var el = this.el;
+ el.setAttribute('material', {
+ color: this.data.hicolor
+ });
+ el.emit('click');
+ if (this.data.togabble) {
+ if (el.is('pressed')) {
+ el.removeState('pressed');
+ } else {
+ el.addState('pressed');
+ }
+ }
+ },
+ onPressedEnded: function() {
+ if (this.el.is('pressed')) {
+ return;
+ }
+ this.el.setAttribute('material', {
+ color: this.color
+ });
+ }
+});
diff --git a/src/3rd/aframe/xrf-get.js b/src/3rd/aframe/xrf-get.js
new file mode 100644
index 0000000..eab5c00
--- /dev/null
+++ b/src/3rd/aframe/xrf-get.js
@@ -0,0 +1,35 @@
+window.AFRAME.registerComponent('xrf-get', {
+ schema: {
+ name: {type: 'string'},
+ clone: {type: 'boolean', default:false}
+ },
+
+ init: function () {
+
+ var el = this.el;
+ var meshname = this.data.name || this.data;
+
+ this.el.addEventListener('update', (evt) => {
+
+ let scene = AFRAME.XRF.scene
+ let mesh = scene.getObjectByName(meshname);
+ if (!mesh){
+ console.error("mesh with name '"+meshname+"' not found in model")
+ return;
+ }
+ if( !this.data.clone ) mesh.parent.remove(mesh)
+ ////mesh.updateMatrixWorld();
+ this.el.object3D.position.setFromMatrixPosition(scene.matrixWorld);
+ this.el.object3D.quaternion.setFromRotationMatrix(scene.matrixWorld);
+ mesh.xrf = true // mark for deletion by xrf
+ this.el.setObject3D('mesh', mesh );
+ if( !this.el.id ) this.el.setAttribute("id",`xrf-${mesh.name}`)
+
+ })
+
+ if( this.el.className == "ray" ) this.el.emit("update")
+
+ }
+
+});
+
diff --git a/src/3rd/aframe/xrf-wear.js b/src/3rd/aframe/xrf-wear.js
new file mode 100644
index 0000000..0babf4c
--- /dev/null
+++ b/src/3rd/aframe/xrf-wear.js
@@ -0,0 +1,26 @@
+window.AFRAME.registerComponent('xrf-wear', {
+ schema:{
+ el: {type:"selector"},
+ position: {type:"vec3"},
+ rotation: {type:"vec3"}
+ },
+ init: function(){
+ $('a-scene').addEventListener('enter-vr', (e) => this.wear(e) )
+ $('a-scene').addEventListener('exit-vr', (e) => this.unwear(e) )
+ },
+ wear: function(){
+ if( !this.wearable ){
+ let d = this.data
+ this.wearable = new THREE.Group()
+ this.el.object3D.children.map( (c) => this.wearable.add(c) )
+ this.wearable.position.set( d.position.x, d.position.y, d.position.z)
+ this.wearable.rotation.set( d.rotation.x, d.rotation.y, d.rotation.z)
+ }
+ this.data.el.object3D.add(this.wearable)
+ },
+ unwear: function(){
+ this.data.el.remove(this.wearable)
+ this.wearable.children.map( (c) => this.el.object3D.add(c) )
+ delete this.wearable
+ }
+})