const GESTURES = { open: "open", // point: grip active, trackpad surface active, trigger inactive. point: "point", // pointThumb: grip active, trigger inactive, trackpad surface inactive. pointThumb: "pointThumb", // fist: grip active, trigger active, trackpad surface active. fist: "fist", // hold: trigger active, grip inactive. hold: "hold", // thumbUp: grip active, trigger active, trackpad surface inactive. thumbUp: "thumbUp" }; const CONTROLLER_OFFSETS = { default: new THREE.Matrix4(), "oculus-touch-controls": new THREE.Matrix4().makeTranslation(0, -0.015, 0.04), "vive-controls": new THREE.Matrix4().compose( new THREE.Vector3(0, -0.017, 0.13), new THREE.Quaternion().setFromEuler(new THREE.Euler(-40 * THREE.Math.DEG2RAD, 0, 0)), new THREE.Vector3(1, 1, 1) ), "daydream-controls": new THREE.Matrix4().makeTranslation(0, 0, -0.04) }; AFRAME.registerComponent("hand-controls2", { schema: { default: "left" }, init() { const el = this.el; this.gesture = GESTURES.open; this.fingersDown = { thumb: false, index: false, middle: false, ring: false, pinky: false }; this.onMiddleRingPinkyDown = this.updateGesture.bind(this, { middle: true, ring: true, pinky: true }); this.onMiddleRingPinkyUp = this.updateGesture.bind(this, { middle: false, ring: false, pinky: false }); this.onIndexDown = this.updateGesture.bind(this, { index: true }); this.onIndexUp = this.updateGesture.bind(this, { index: false }); this.onThumbDown = this.updateGesture.bind(this, { thumb: true }); this.onThumbUp = this.updateGesture.bind(this, { thumb: false }); this.onControllerConnected = this.onControllerConnected.bind(this); this.onControllerDisconnected = this.onControllerDisconnected.bind(this); this.connectedController = null; el.addEventListener("controllerconnected", this.onControllerConnected); el.addEventListener("controllerdisconnected", this.onControllerDisconnected); el.setAttribute("visible", false); }, play() { const el = this.el; el.addEventListener("middle_ring_pinky_down", this.onMiddleRingPinkyDown); el.addEventListener("middle_ring_pinky_up", this.onMiddleRingPinkyUp); el.addEventListener("thumb_down", this.onThumbDown); el.addEventListener("thumb_up", this.onThumbUp); el.addEventListener("index_down", this.onIndexDown); el.addEventListener("index_up", this.onIndexUp); }, pause() { const el = this.el; el.removeEventListener("middle_ring_pinky_down", this.onMiddleRingPinkyDown); el.removeEventListener("middle_ring_pinky_up", this.onMiddleRingPinkyUp); el.removeEventListener("thumb_down", this.onThumbDown); el.removeEventListener("thumb_up", this.onThumbUp); el.removeEventListener("index_down", this.onIndexDown); el.removeEventListener("index_up", this.onIndexUp); }, // Attach the platform specific tracked controllers. update(prevData) { const el = this.el; const hand = this.data; const controlConfiguration = { hand: hand, model: false, rotationOffset: 0 }; if (hand !== prevData) { el.setAttribute("vive-controls", controlConfiguration); el.setAttribute("oculus-touch-controls", controlConfiguration); el.setAttribute("windows-motion-controls", controlConfiguration); el.setAttribute("daydream-controls", controlConfiguration); } }, remove() { const el = this.el; el.removeEventListener("controllerconnected", this.onControllerConnected); el.removeEventListener("controllerdisconnected", this.onControllerDisconnected); }, updateGesture(nextFingersDown) { Object.assign(this.fingersDown, nextFingersDown); const gesture = this.determineGesture(); if (gesture !== this.gesture) { this.gesture = gesture; this.el.emit(this.last + "end"); this.el.emit(this.gesture + "start"); } }, determineGesture() { const { thumb, index, middle, ring, pinky } = this.fingersDown; if (!thumb && !index && !middle && !ring && !pinky) { return GESTURES.open; } else if (thumb && index && middle && ring && pinky) { return GESTURES.fist; } else if (!thumb && index && middle && ring && pinky) { return GESTURES.thumbUp; } else if (!thumb && !index && middle && ring && pinky) { return GESTURES.pointThumb; } else if (!thumb && index && !middle && !ring && !pinky) { return GESTURES.hold; } else if (thumb && !index && !middle && !ring && !pinky) { return GESTURES.hold; } else if (thumb && index && !middle && !ring && !pinky) { return GESTURES.hold; } else if (thumb && !index && middle && ring && pinky) { return GESTURES.point; } console.warn("Did not find matching gesture for ", this.fingersDown); return GESTURES.open; }, // Show controller when connected onControllerConnected(e) { this.connectedController = e.detail.name; this.el.setAttribute("visible", true); }, // Hide controller on disconnect onControllerDisconnected() { this.connectedController = null; this.el.setAttribute("visible", false); }, getControllerOffset() { if (CONTROLLER_OFFSETS[this.connectedController] === undefined) { return CONTROLLER_OFFSETS.default; } return CONTROLLER_OFFSETS[this.connectedController]; } });