From 1392acf1fb4b9a622ad23759b2de0a21f5e290f6 Mon Sep 17 00:00:00 2001
From: johnshaughnessy <johnfshaughnessy@gmail.com>
Date: Mon, 22 Oct 2018 14:11:59 -0700
Subject: [PATCH] Change handControls2 to use userinput frame, not event
 listeners

---
 src/components/hand-controls2.js              | 160 +++++-------------
 .../userinput/bindings/oculus-touch-user.js   |  46 +++++
 src/systems/userinput/bindings/vive-user.js   |  46 +++++
 src/systems/userinput/paths.js                |   6 +
 4 files changed, 138 insertions(+), 120 deletions(-)

diff --git a/src/components/hand-controls2.js b/src/components/hand-controls2.js
index cdafd23c4..e2d7461d3 100644
--- a/src/components/hand-controls2.js
+++ b/src/components/hand-controls2.js
@@ -1,3 +1,5 @@
+import { paths } from "../systems/userinput/paths";
+
 const POSES = {
   open: "open",
   point: "point",
@@ -10,6 +12,8 @@ const POSES = {
   mrpDown: "mrpDown"
 };
 
+// TODO: If the hands or controllers are mispositioned, then rightHand.controllerPose and rightHand.pose
+//       should be bound differently.
 export const CONTROLLER_OFFSETS = {
   default: new THREE.Matrix4(),
   "oculus-touch-controls": new THREE.Matrix4().makeTranslation(0, -0.015, 0.04),
@@ -29,160 +33,76 @@ export const CONTROLLER_OFFSETS = {
 };
 
 /**
- * Converts events from various 6DoF and 3DoF controllers into hand-pose events.
+ * Emits events indicating that avatar hands should be posed differently.
  * @namespace user-input
  * @component hand-controls2
  */
 AFRAME.registerComponent("hand-controls2", {
   schema: { default: "left" },
 
-  init() {
-    const el = this.el;
-
-    this.pose = POSES.open;
-
-    this.fingersDown = {
-      thumb: false,
-      index: false,
-      middle: false,
-      ring: false,
-      pinky: false
-    };
-
-    this.onMiddleRingPinkyDown = this.updatePose.bind(this, {
-      middle: true,
-      ring: true,
-      pinky: true
-    });
-
-    this.onMiddleRingPinkyUp = this.updatePose.bind(this, {
-      middle: false,
-      ring: false,
-      pinky: false
-    });
-
-    this.onIndexDown = this.updatePose.bind(this, {
-      index: true
-    });
-
-    this.onIndexUp = this.updatePose.bind(this, {
-      index: false
-    });
-
-    this.onThumbDown = this.updatePose.bind(this, {
-      thumb: true
-    });
-
-    this.onThumbUp = this.updatePose.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);
+  getControllerOffset() {
+    if (CONTROLLER_OFFSETS[this.connectedController] === undefined) {
+      return CONTROLLER_OFFSETS.default;
+    }
+    return CONTROLLER_OFFSETS[this.connectedController];
   },
 
-  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);
+  init() {
+    this.pose = POSES.open;
+    this.el.setAttribute("visible", false);
   },
 
-  // Attach the platform specific tracked controllers.
   update(prevData) {
-    const el = this.el;
     const hand = this.data;
 
     const controlConfiguration = {
       hand: hand,
-      orientationOffset: { x: 0, y: 0, z: 0 }
+      orientationOffset: { x: 0, y: 0, z: 0 },
+      model: false
     };
 
     if (hand !== prevData) {
-      el.setAttribute("tracked-controls", controlConfiguration);
-    }
-  },
-
-  remove() {
-    const el = this.el;
-    el.removeEventListener("controllerconnected", this.onControllerConnected);
-    el.removeEventListener("controllerdisconnected", this.onControllerDisconnected);
-  },
-
-  updatePose(nextFingersDown) {
-    Object.assign(this.fingersDown, nextFingersDown);
-    const pose = this.determinePose();
-
-    if (pose !== this.pose) {
-      const previous = this.pose;
-      this.pose = pose;
-      this.el.emit("hand-pose", { previous: previous, current: this.pose });
+      this.el.setAttribute("tracked-controls", controlConfiguration);
+      this.el.setAttribute("oculus-touch-controls", controlConfiguration);
     }
   },
 
-  determinePose() {
-    const { thumb, index, middle, ring, pinky } = this.fingersDown;
-
-    if (!thumb && !index && !middle && !ring && !pinky) {
+  poseForFingers(thumb, index, middleRingPinky) {
+    if (!thumb && !index && !middleRingPinky) {
       return POSES.open;
-    } else if (thumb && index && middle && ring && pinky) {
+    } else if (thumb && index && middleRingPinky) {
       return POSES.fist;
-    } else if (!thumb && index && middle && ring && pinky) {
+    } else if (!thumb && index && middleRingPinky) {
       return POSES.thumbUp;
-    } else if (!thumb && !index && middle && ring && pinky) {
+    } else if (!thumb && !index && middleRingPinky) {
       return POSES.mrpDown;
-    } else if (!thumb && index && !middle && !ring && !pinky) {
+    } else if (!thumb && index && !middleRingPinky) {
       return POSES.indexDown;
-    } else if (thumb && !index && !middle && !ring && !pinky) {
+    } else if (thumb && !index && !middleRingPinky) {
       return POSES.thumbDown;
-    } else if (thumb && index && !middle && !ring && !pinky) {
+    } else if (thumb && index && !middleRingPinky) {
       return POSES.pinch;
-    } else if (thumb && !index && middle && ring && pinky) {
+    } else if (thumb && !index && middleRingPinky) {
       return POSES.point;
     }
 
-    console.warn("Did not find matching pose for ", this.fingersDown);
-
+    console.warn(`Did not find matching pose for thumb ${thumb}, index ${index}, middleRingPinky ${middleRingPinky}`);
     return POSES.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;
+  tick() {
+    const hand = this.data;
+    const userinput = AFRAME.scenes[0].systems.userinput;
+    const subpath = hand === "left" ? paths.actions.leftHand : paths.actions.rightHand;
+    const hasPose = userinput.readFrameValueAtPath(subpath.pose);
+    const thumb = userinput.readFrameValueAtPath(subpath.thumb);
+    const index = userinput.readFrameValueAtPath(subpath.index);
+    const middleRingPinky = userinput.readFrameValueAtPath(subpath.middleRingPinky);
+    const pose = this.poseForFingers(thumb, index, middleRingPinky);
+    if (pose !== this.pose) {
+      this.el.emit("hand-pose", { previous: this.pose, current: pose });
+      this.pose = pose;
     }
-
-    return CONTROLLER_OFFSETS[this.connectedController];
+    this.el.setAttribute("visible", hasPose);
   }
 });
diff --git a/src/systems/userinput/bindings/oculus-touch-user.js b/src/systems/userinput/bindings/oculus-touch-user.js
index d7e39357d..d386016c2 100644
--- a/src/systems/userinput/bindings/oculus-touch-user.js
+++ b/src/systems/userinput/bindings/oculus-touch-user.js
@@ -57,6 +57,52 @@ const keyboardSnapLeft = `${name}/keyboard/snap-left`;
 
 export const oculusTouchUserBindings = {
   [sets.global]: [
+    {
+      src: {
+        value: leftButton("grip").pressed
+      },
+      dest: {
+        value: paths.actions.leftHand.middleRingPinky
+      },
+      xform: xforms.copy
+    },
+    {
+      src: [leftButton("x").touched, leftButton("y").touched, leftButton("thumbStick").touched],
+      dest: {
+        value: paths.actions.leftHand.thumb
+      },
+      xform: xforms.any
+    },
+    {
+      src: { value: leftButton("trigger").pressed },
+      dest: {
+        value: paths.actions.leftHand.index
+      },
+      xform: xforms.copy
+    },
+    {
+      src: {
+        value: rightButton("grip").pressed
+      },
+      dest: {
+        value: paths.actions.rightHand.middleRingPinky
+      },
+      xform: xforms.copy
+    },
+    {
+      src: [rightButton("x").touched, rightButton("y").touched, rightButton("thumbStick").touched],
+      dest: {
+        value: paths.actions.rightHand.thumb
+      },
+      xform: xforms.any
+    },
+    {
+      src: { value: rightButton("trigger").pressed },
+      dest: {
+        value: paths.actions.rightHand.index
+      },
+      xform: xforms.copy
+    },
     {
       src: {
         value: paths.device.keyboard.key("b")
diff --git a/src/systems/userinput/bindings/vive-user.js b/src/systems/userinput/bindings/vive-user.js
index d276867e3..0e20233c7 100644
--- a/src/systems/userinput/bindings/vive-user.js
+++ b/src/systems/userinput/bindings/vive-user.js
@@ -118,6 +118,52 @@ const teleportRight = [
 
 export const viveUserBindings = {
   [sets.global]: [
+    {
+      src: {
+        value: lButton("grip").touched
+      },
+      dest: {
+        value: paths.actions.leftHand.middleRingPinky
+      },
+      xform: xforms.copy
+    },
+    {
+      src: [lButton("touchpad").touched, lButton("top").touched],
+      dest: {
+        value: paths.actions.leftHand.thumb
+      },
+      xform: xforms.any
+    },
+    {
+      src: { value: lButton("trigger").pressed },
+      dest: {
+        value: paths.actions.leftHand.index
+      },
+      xform: xforms.copy
+    },
+    {
+      src: {
+        value: rButton("grip").touched
+      },
+      dest: {
+        value: paths.actions.rightHand.middleRingPinky
+      },
+      xform: xforms.copy
+    },
+    {
+      src: [rButton("touchpad").touched, rButton("top").touched],
+      dest: {
+        value: paths.actions.rightHand.thumb
+      },
+      xform: xforms.any
+    },
+    {
+      src: { value: rButton("trigger").pressed },
+      dest: {
+        value: paths.actions.rightHand.index
+      },
+      xform: xforms.copy
+    },
     {
       src: {
         value: paths.device.keyboard.key("b")
diff --git a/src/systems/userinput/paths.js b/src/systems/userinput/paths.js
index 28a8fa911..d4cc4994c 100644
--- a/src/systems/userinput/paths.js
+++ b/src/systems/userinput/paths.js
@@ -42,6 +42,9 @@ paths.actions.rightHand.scalePenTip = "/actions/rightHandScalePenTip";
 paths.actions.rightHand.startTeleport = "/actions/rightHandStartTeleport";
 paths.actions.rightHand.stopTeleport = "/actions/rightHandStopTeleport";
 paths.actions.rightHand.takeSnapshot = "/actions/rightHandTakeSnapshot";
+paths.actions.rightHand.thumb = "/actions/rightHand/thumbDown";
+paths.actions.rightHand.index = "/actions/rightHand/indexDown";
+paths.actions.rightHand.middleRingPinky = "/actions/rightHand/middleRingPinkyDown";
 paths.actions.leftHand = {};
 paths.actions.leftHand.pose = "/actions/leftHandPose";
 paths.actions.leftHand.grab = "/actions/leftHandGrab";
@@ -55,6 +58,9 @@ paths.actions.leftHand.scalePenTip = "/actions/leftHandScalePenTip";
 paths.actions.leftHand.startTeleport = "/actions/leftHandStartTeleport";
 paths.actions.leftHand.stopTeleport = "/actions/leftHandStopTeleport";
 paths.actions.leftHand.takeSnapshot = "/actions/leftHandTakeSnapshot";
+paths.actions.leftHand.thumb = "/actions/leftHand/thumbDown";
+paths.actions.leftHand.index = "/actions/leftHand/indexDown";
+paths.actions.leftHand.middleRingPinky = "/actions/leftHand/middleRingPinkyDown";
 
 paths.device = {};
 paths.device.mouse = {};
-- 
GitLab