|
| 1 | +/* |
| 2 | + *Usage: |
| 3 | + * <a-entity wearable="el: #leftHand; class: foo"></a-entity> |
| 4 | + * <a-entity id="leftHand"> |
| 5 | + * <a-entity class="foo" position="0 0 0" rotation="0 0 0" scale="0 0 0"></a-entity> |
| 6 | + * <a-entity> |
| 7 | + * |
| 8 | + * NOTE: you can hint different position/rotation-offsets by adding controller-specific entities to the target: |
| 9 | + * |
| 10 | + * <a-entity id="leftHand"> |
| 11 | + * <a-entity class="foo" position="0 0 0" rotation="0 0 0" scale="0 0 0"></a-entity> |
| 12 | + * <a-entity class="foo hand-tracking-controls" position="0 0 0" rotation="0 0 0" scale="0 0 0"></a-entity> |
| 13 | + * <a-entity> |
| 14 | + * |
| 15 | + * The controllernames are hinted by the 'controllermodelready' event: |
| 16 | + * |
| 17 | + * 'hand-tracking-controls', |
| 18 | + * 'meta-touch-controls', |
| 19 | + * 'valve-index-controls', |
| 20 | + * 'logitech-mx-ink-controls', |
| 21 | + * 'windows-motion-controls', |
| 22 | + * 'hp-mixed-reality-controls', |
| 23 | + * 'generic-tracked-controller-controls', |
| 24 | + * 'pico-controls', |
| 25 | + * (and more in the future) |
| 26 | + */ |
| 27 | + |
| 28 | +AFRAME.registerComponent('wearable', { |
| 29 | + schema:{ |
| 30 | + el: {type:"selector"}, |
| 31 | + class: {type:"string"} |
| 32 | + }, |
| 33 | + init: function(){ |
| 34 | + if( !this.data.el ) return console.warn(`wearable.js: cannot find ${this.data.el}`) |
| 35 | + this.controllers = {} |
| 36 | + this.remember() |
| 37 | + this.data.el.addEventListener('controllermodelready', this.bindPlaceHolders.bind(this,["controllermodelready"]) ) |
| 38 | + this.data.el.addEventListener('controllerconnected', this.bindPlaceHolders.bind(this,["controllerconnected"] ) ) |
| 39 | + }, |
| 40 | + |
| 41 | + bindPlaceHolders: function(type,e){ |
| 42 | + let controllerName = e.detail.name |
| 43 | + let selector = `.${this.data.class}.${controllerName}` |
| 44 | + let placeholder = this.data.el.querySelector(selector) || this.data.el.querySelector(`${this.data.class}`) |
| 45 | + if( !placeholder ) return console.warn("wearable.js: could not find placeholder to attach to") |
| 46 | + this.attachPlaceHolder(type,e,placeholder, controllerName) |
| 47 | + }, |
| 48 | + |
| 49 | + attachPlaceHolder: function(type, el, placeholder, controllerName){ |
| 50 | + this.el.object3DMap = {} // unsync THREE <-> AFRAME entity |
| 51 | + placeholder.object3D.add( this.obj ) |
| 52 | + if( controllerName != 'hand-tracking-controls' ){ |
| 53 | + // re-add for controller-models which don't re-add children ('meta-touch-controls' e.g.) |
| 54 | + if( this.data.el.getObject3D("mesh") ){ |
| 55 | + this.data.el.getObject3D("mesh").add(placeholder.object3D) |
| 56 | + } |
| 57 | + } |
| 58 | + // these are handled by the placeholder entity |
| 59 | + this.obj.position.set(0,0,0); |
| 60 | + this.obj.rotation.set(0,0,0); |
| 61 | + this.obj.scale.set(1,1,1); |
| 62 | + }, |
| 63 | + |
| 64 | + detach: function(){ |
| 65 | + this.el.setObject3D( this.obj.uuid, this.obj ) |
| 66 | + this.el.object3D.position.copy( this.position ) |
| 67 | + this.el.object3D.rotation.copy( this.rotation ) |
| 68 | + this.el.object3D.scale.copy( this.scale ) |
| 69 | + }, |
| 70 | + |
| 71 | + remember: function(){ |
| 72 | + this.obj = this.el.object3D |
| 73 | + this.position = this.el.object3D.position.clone() |
| 74 | + this.rotation = this.el.object3D.rotation.clone() |
| 75 | + this.scale = this.el.object3D.scale.clone() |
| 76 | + this.parent = this.el.object3D.parent |
| 77 | + } |
| 78 | + |
| 79 | +}) |
| 80 | + |
0 commit comments