diff --git a/README.md b/README.md index b0560e1..29756ae 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Component to make an [A-Frame](https://aframe.io) scene compatible with [Altspac Live examples: http://altspacevr.github.io/aframe/examples/ (forked from [aframevr/aframe](https://github.com/aframevr/aframe)) -Note that when running in Altspace, the scene will not be synchronized between users. In addition, some A-Frame features are currently not supported in Altspace, such as lighting and video. For details, see the [Three.js Feature Support](http://github.com/AltspaceVR/AltspaceSDK#threejs-feature-support) section in the [AltspaceSDK](http://github.com/AltspaceVR/AltspaceSDK) repo. +Note that when running in Altspace, the scene will not be synchronized between users. In addition, some A-Frame features are currently not supported in Altspace, such as lighting and video. For details, see the [Three.js Feature Support](http://github.com/AltspaceVR/AltspaceSDK#threejs-feature-support) section in the [AltspaceSDK](http://github.com/AltspaceVR/AltspaceSDK) repo. ### Properties @@ -14,8 +14,8 @@ Note that when running in Altspace, the scene will not be synchronized between u | `verticalAlign` | Puts the scene origin at the bottom, middle, or top of the Altspace enclosure. If your scene seems to be floating in midair, try setting this to 'bottom'. | `middle` ### Usage -Add the "altspace" parameter on your `` like so: `` +Add the "altspace" attribute on your `` like so: `` #### Example @@ -24,8 +24,8 @@ Install and use by directly including the [browser files](dist): ```html My A-Frame Scene - - + + @@ -34,3 +34,16 @@ Install and use by directly including the [browser files](dist): ``` + +## altspace-tracked-controls + +This library also includes an `altspace-tracked-controls` component that enables tracked control support for A-Frame +applications that use the built-in `tracked-controls`, `vive-controls` or `hand-controls` components. + +### Usage + +Add the "altspace-tracked-controls" attribute to your tracked entity. For example: + +```html + +``` diff --git a/dist/aframe-altspace-component.js b/dist/aframe-altspace-component.js index e2b7ccf..b60ae58 100644 --- a/dist/aframe-altspace-component.js +++ b/dist/aframe-altspace-component.js @@ -49,14 +49,16 @@ } /** - * aframe-altspace-component component for A-Frame. + * The altspace component makes A-Frame apps compatible with AltspaceVR. */ AFRAME.registerComponent('altspace', { /** - * usePixelScale will allow you to use A-Frame units as CSS pixels. This is the default behavior for three.js apps, but not for A-Frame apps. verticalAlign puts the origin at the bottom, middle (default), or top of the Altspace enclosure. + * usePixelScale will allow you to use A-Frame units as CSS pixels. + * This is the default behavior for three.js apps, but not for A-Frame apps. + * verticalAlign puts the origin at the bottom, middle (default), or top of the Altspace enclosure. */ - schema: { + schema: { usePixelScale: { type: 'boolean', default: 'false'}, verticalAlign: { type: 'string', default: 'middle'} }, @@ -71,6 +73,7 @@ } if (window.altspace && window.altspace.inClient) { + this.el.setAttribute('vr-mode-ui', {enabled: false}); this.initRenderer(); this.initCursorEvents(); } @@ -82,7 +85,6 @@ * Generally modifies the entity based on the data. */ update: function (oldData) { - }, /** @@ -137,7 +139,7 @@ } }); } - var renderer = this.el.renderer = altspace.getThreeJSRenderer(); + var renderer = this.el.renderer = this.el.effect = altspace.getThreeJSRenderer(); var noop = function() {}; renderer.setSize = noop; renderer.setPixelRatio = noop; @@ -152,7 +154,7 @@ renderer.context = {canvas: {}}; renderer.shadowMap = {}; - }, + }, /** * Emulate A-Frame cursor events when running in altspaceVR. @@ -161,7 +163,7 @@ var scene = this.el.object3D; var cursorEl = document.querySelector('a-cursor') || document.querySelector('a-entity[cursor]'); - if (cursorEl) { + if (cursorEl) { // Hide A-Frame cursor mesh. cursorEl.setAttribute('material', 'transparent', true); cursorEl.setAttribute('material', 'opacity', 0.0); @@ -169,8 +171,8 @@ var emit = function(eventName, targetEl) { // Fire events on intersected object and A-Frame cursor. - if (targetEl) targetEl.emit(eventName, {target: targetEl}); if (cursorEl) cursorEl.emit(eventName, {target: targetEl}); + if (targetEl) targetEl.emit(eventName, {target: targetEl}); } ; var cursordownObj = null; @@ -188,12 +190,14 @@ }); scene.addEventListener('cursorenter', function(event) { + if (!event.target.el) { return; } event.target.el.addState('hovered'); if (cursorEl) cursorEl.addState('hovering'); emit('mouseenter', event.target.el); }); scene.addEventListener('cursorleave', function(event) { + if (!event.target.el) { return; } event.target.el.removeState('hovered'); if (cursorEl) cursorEl.removeState('hovering'); emit('mouseleave', event.target.el); @@ -203,6 +207,39 @@ }); + AFRAME.registerComponent('altspace-tracked-controls', { + init: function () { + this.gamepadIndex = null; + this.trackedControlsSystem = document.querySelector('a-scene').systems['tracked-controls']; + this.systemGamepads = 0; + altspace.getGamepads(); + }, + tick: function () { + if ( + this.trackedControlsSystem && + this.systemGamepads !== this.trackedControlsSystem.controllers.length && + window.altspace && altspace.getGamepads && altspace.getGamepads().length + ) { + var components = this.el.components; + if (components['paint-controls']) { + this.gamepadIndex = components['paint-controls'].data.hand === 'left' ? 2 : 1; + } + if (this.gamepadIndex === null && components['hand-controls']) { + this.gamepadIndex = components['hand-controls'].data === 'left' ? 2 : 1; + } + if (this.gamepadIndex === null && components['vive-controls']) { + this.gamepadIndex = components['vive-controls'].data.hand === 'left' ? 2 : 1; + } + if (this.gamepadIndex === null && components['tracked-controls']) { + this.gamepadIndex = components['tracked-controls'].data.controller; + } + this.el.setAttribute('tracked-controls', 'id', altspace.getGamepads()[this.gamepadIndex].id); + this.el.setAttribute('tracked-controls', 'controller', 0); + this.systemGamepads = this.trackedControlsSystem.controllers.length; + } + } + }); + /***/ } /******/ ]); \ No newline at end of file diff --git a/dist/aframe-altspace-component.min.js b/dist/aframe-altspace-component.min.js index 7df37c7..c11c359 100644 --- a/dist/aframe-altspace-component.min.js +++ b/dist/aframe-altspace-component.min.js @@ -1 +1 @@ -!function(e){function t(r){if(n[r])return n[r].exports;var a=n[r]={exports:{},id:r,loaded:!1};return e[r].call(a.exports,a,a.exports,t),a.loaded=!0,a.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t){if("undefined"==typeof AFRAME)throw new Error("Component attempted to register before AFRAME was available.");AFRAME.registerComponent("altspace",{schema:{usePixelScale:{type:"boolean","default":"false"},verticalAlign:{type:"string","default":"middle"}},init:function(){return this.el.object3D instanceof THREE.Scene?void(window.altspace&&window.altspace.inClient&&(this.initRenderer(),this.initCursorEvents())):void console.warn("aframe-altspace-component can only be attached to a-scene")},update:function(e){},remove:function(){},pause:function(){},play:function(){},initRenderer:function(){var e=this.el.object3D;this.data.usePixelScale||altspace.getEnclosure().then(function(t){e.scale.multiplyScalar(t.pixelsPerMeter)});var t=this.data.verticalAlign;"center"!==t&&altspace.getEnclosure().then(function(n){switch(t){case"bottom":e.position.y-=n.innerHeight/2;break;case"top":e.position.y+=n.innerHeight/2;break;default:console.warn("Unexpected value for verticalAlign: ",this.data.verticalAlign)}});var n=this.el.renderer=altspace.getThreeJSRenderer(),r=function(){};n.setSize=r,n.setPixelRatio=r,n.setClearColor=r,n.clear=r,n.enableScissorTest=r,n.setScissor=r,n.setViewport=r,n.getPixelRatio=r,n.getMaxAnisotropy=r,n.setFaceCulling=r,n.context={canvas:{}},n.shadowMap={}},initCursorEvents:function(){var e=this.el.object3D,t=document.querySelector("a-cursor")||document.querySelector("a-entity[cursor]");t&&(t.setAttribute("material","transparent",!0),t.setAttribute("material","opacity",0));var n=function(e,n){n&&n.emit(e,{target:n}),t&&t.emit(e,{target:n})},r=null;e.addEventListener("cursordown",function(e){r=e.target,n("mousedown",e.target.el)}),e.addEventListener("cursorup",function(e){n("mouseup",e.target.el),e.target.uuid===r.uuid&&n("click",e.target.el),r=null}),e.addEventListener("cursorenter",function(e){e.target.el.addState("hovered"),t&&t.addState("hovering"),n("mouseenter",e.target.el)}),e.addEventListener("cursorleave",function(e){e.target.el.removeState("hovered"),t&&t.removeState("hovering"),n("mouseleave",e.target.el)})}})}]); \ No newline at end of file +!function(e){function t(n){if(a[n])return a[n].exports;var r=a[n]={exports:{},id:n,loaded:!1};return e[n].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var a={};return t.m=e,t.c=a,t.p="",t(0)}([function(e,t){if("undefined"==typeof AFRAME)throw new Error("Component attempted to register before AFRAME was available.");AFRAME.registerComponent("altspace",{schema:{usePixelScale:{type:"boolean","default":"false"},verticalAlign:{type:"string","default":"middle"}},init:function(){return this.el.object3D instanceof THREE.Scene?void(window.altspace&&window.altspace.inClient&&(this.el.setAttribute("vr-mode-ui",{enabled:!1}),this.initRenderer(),this.initCursorEvents())):void console.warn("aframe-altspace-component can only be attached to a-scene")},update:function(e){},remove:function(){},pause:function(){},play:function(){},initRenderer:function(){var e=this.el.object3D;this.data.usePixelScale||altspace.getEnclosure().then(function(t){e.scale.multiplyScalar(t.pixelsPerMeter)});var t=this.data.verticalAlign;"center"!==t&&altspace.getEnclosure().then(function(a){switch(t){case"bottom":e.position.y-=a.innerHeight/2;break;case"top":e.position.y+=a.innerHeight/2;break;default:console.warn("Unexpected value for verticalAlign: ",this.data.verticalAlign)}});var a=this.el.renderer=this.el.effect=altspace.getThreeJSRenderer(),n=function(){};a.setSize=n,a.setPixelRatio=n,a.setClearColor=n,a.clear=n,a.enableScissorTest=n,a.setScissor=n,a.setViewport=n,a.getPixelRatio=n,a.getMaxAnisotropy=n,a.setFaceCulling=n,a.context={canvas:{}},a.shadowMap={}},initCursorEvents:function(){var e=this.el.object3D,t=document.querySelector("a-cursor")||document.querySelector("a-entity[cursor]");t&&(t.setAttribute("material","transparent",!0),t.setAttribute("material","opacity",0));var a=function(e,a){t&&t.emit(e,{target:a}),a&&a.emit(e,{target:a})},n=null;e.addEventListener("cursordown",function(e){n=e.target,a("mousedown",e.target.el)}),e.addEventListener("cursorup",function(e){a("mouseup",e.target.el),e.target.uuid===n.uuid&&a("click",e.target.el),n=null}),e.addEventListener("cursorenter",function(e){e.target.el&&(e.target.el.addState("hovered"),t&&t.addState("hovering"),a("mouseenter",e.target.el))}),e.addEventListener("cursorleave",function(e){e.target.el&&(e.target.el.removeState("hovered"),t&&t.removeState("hovering"),a("mouseleave",e.target.el))})}}),AFRAME.registerComponent("altspace-tracked-controls",{init:function(){this.gamepadIndex=null,this.trackedControlsSystem=document.querySelector("a-scene").systems["tracked-controls"],this.systemGamepads=0,altspace.getGamepads()},tick:function(){if(this.trackedControlsSystem&&this.systemGamepads!==this.trackedControlsSystem.controllers.length&&window.altspace&&altspace.getGamepads&&altspace.getGamepads().length){var e=this.el.components;e["paint-controls"]&&(this.gamepadIndex="left"===e["paint-controls"].data.hand?2:1),null===this.gamepadIndex&&e["hand-controls"]&&(this.gamepadIndex="left"===e["hand-controls"].data?2:1),null===this.gamepadIndex&&e["vive-controls"]&&(this.gamepadIndex="left"===e["vive-controls"].data.hand?2:1),null===this.gamepadIndex&&e["tracked-controls"]&&(this.gamepadIndex=e["tracked-controls"].data.controller),this.el.setAttribute("tracked-controls","id",altspace.getGamepads()[this.gamepadIndex].id),this.el.setAttribute("tracked-controls","controller",0),this.systemGamepads=this.trackedControlsSystem.controllers.length}}})}]); \ No newline at end of file diff --git a/index.js b/index.js index 73070f1..a83cc64 100644 --- a/index.js +++ b/index.js @@ -3,14 +3,16 @@ if (typeof AFRAME === 'undefined') { } /** - * aframe-altspace-component component for A-Frame. + * The altspace component makes A-Frame apps compatible with AltspaceVR. */ AFRAME.registerComponent('altspace', { /** - * usePixelScale will allow you to use A-Frame units as CSS pixels. This is the default behavior for three.js apps, but not for A-Frame apps. verticalAlign puts the origin at the bottom, middle (default), or top of the Altspace enclosure. + * usePixelScale will allow you to use A-Frame units as CSS pixels. + * This is the default behavior for three.js apps, but not for A-Frame apps. + * verticalAlign puts the origin at the bottom, middle (default), or top of the Altspace enclosure. */ - schema: { + schema: { usePixelScale: { type: 'boolean', default: 'false'}, verticalAlign: { type: 'string', default: 'middle'} }, @@ -25,6 +27,7 @@ AFRAME.registerComponent('altspace', { } if (window.altspace && window.altspace.inClient) { + this.el.setAttribute('vr-mode-ui', {enabled: false}); this.initRenderer(); this.initCursorEvents(); } @@ -36,7 +39,6 @@ AFRAME.registerComponent('altspace', { * Generally modifies the entity based on the data. */ update: function (oldData) { - }, /** @@ -91,7 +93,7 @@ AFRAME.registerComponent('altspace', { } }); } - var renderer = this.el.renderer = altspace.getThreeJSRenderer(); + var renderer = this.el.renderer = this.el.effect = altspace.getThreeJSRenderer(); var noop = function() {}; renderer.setSize = noop; renderer.setPixelRatio = noop; @@ -106,7 +108,7 @@ AFRAME.registerComponent('altspace', { renderer.context = {canvas: {}}; renderer.shadowMap = {}; - }, + }, /** * Emulate A-Frame cursor events when running in altspaceVR. @@ -115,7 +117,7 @@ AFRAME.registerComponent('altspace', { var scene = this.el.object3D; var cursorEl = document.querySelector('a-cursor') || document.querySelector('a-entity[cursor]'); - if (cursorEl) { + if (cursorEl) { // Hide A-Frame cursor mesh. cursorEl.setAttribute('material', 'transparent', true); cursorEl.setAttribute('material', 'opacity', 0.0); @@ -123,8 +125,8 @@ AFRAME.registerComponent('altspace', { var emit = function(eventName, targetEl) { // Fire events on intersected object and A-Frame cursor. - if (targetEl) targetEl.emit(eventName, {target: targetEl}); if (cursorEl) cursorEl.emit(eventName, {target: targetEl}); + if (targetEl) targetEl.emit(eventName, {target: targetEl}); } ; var cursordownObj = null; @@ -142,12 +144,14 @@ AFRAME.registerComponent('altspace', { }); scene.addEventListener('cursorenter', function(event) { + if (!event.target.el) { return; } event.target.el.addState('hovered'); if (cursorEl) cursorEl.addState('hovering'); emit('mouseenter', event.target.el); }); scene.addEventListener('cursorleave', function(event) { + if (!event.target.el) { return; } event.target.el.removeState('hovered'); if (cursorEl) cursorEl.removeState('hovering'); emit('mouseleave', event.target.el); @@ -156,3 +160,36 @@ AFRAME.registerComponent('altspace', { }, }); + +AFRAME.registerComponent('altspace-tracked-controls', { + init: function () { + this.gamepadIndex = null; + this.trackedControlsSystem = document.querySelector('a-scene').systems['tracked-controls']; + this.systemGamepads = 0; + altspace.getGamepads(); + }, + tick: function () { + if ( + this.trackedControlsSystem && + this.systemGamepads !== this.trackedControlsSystem.controllers.length && + window.altspace && altspace.getGamepads && altspace.getGamepads().length + ) { + var components = this.el.components; + if (components['paint-controls']) { + this.gamepadIndex = components['paint-controls'].data.hand === 'left' ? 2 : 1; + } + if (this.gamepadIndex === null && components['hand-controls']) { + this.gamepadIndex = components['hand-controls'].data === 'left' ? 2 : 1; + } + if (this.gamepadIndex === null && components['vive-controls']) { + this.gamepadIndex = components['vive-controls'].data.hand === 'left' ? 2 : 1; + } + if (this.gamepadIndex === null && components['tracked-controls']) { + this.gamepadIndex = components['tracked-controls'].data.controller; + } + this.el.setAttribute('tracked-controls', 'id', altspace.getGamepads()[this.gamepadIndex].id); + this.el.setAttribute('tracked-controls', 'controller', 0); + this.systemGamepads = this.trackedControlsSystem.controllers.length; + } + } +}); diff --git a/package.json b/package.json index 9bf1f13..ed3d60e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "aframe-altspace-component", - "version": "0.2.2", - "description": "aframe-altspace-component component for A-Frame.", + "version": "0.3.0", + "description": "aframe-altspace-component makes A-frame apps compatible with AltspaceVR.", "main": "index.js", "scripts": { "build": "browserify examples/main.js -o examples/build.js", @@ -23,7 +23,9 @@ "vr", "aframe-layout", "mozvr", - "webvr" + "webvr", + "altspacevr", + "altspace" ], "author": "Amber Roy ", "license": "MIT", @@ -32,13 +34,11 @@ }, "homepage": "https://github.com/AltspaceVR/aframe-altspace-component#readme", "devDependencies": { - "aframe": "0.2.0", - "browserify": "12.0.1", - "browserify-css": "0.8.3", - "budo": "7.1.0", + "aframe": "0.3.0", + "browserify": "13.1.0", + "browserify-css": "0.9.2", + "budo": "9.2.0", "ghpages": "0.0.3", - "inquirer": "0.12.0", - "shelljs": "0.6.0", - "webpack": "1.12.9" + "webpack": "1.13.2" } }