From e38dea5c215155a4ebbeb7a9fe0a556709a7b2b8 Mon Sep 17 00:00:00 2001
From: Kevin Lee <kevin@infinite-lee.com>
Date: Fri, 20 Apr 2018 16:36:36 -0700
Subject: [PATCH] switch the super-hands on the controllers back to using
 action_grab/action_release and support that properly in cursor-controller.

---
 src/components/cursor-controller.js | 27 +++++++++++++++++++--------
 src/components/super-spawner.js     |  1 +
 src/hub.html                        | 14 +++++++++-----
 src/input-mappings.js               | 12 ++++++------
 4 files changed, 35 insertions(+), 19 deletions(-)

diff --git a/src/components/cursor-controller.js b/src/components/cursor-controller.js
index 1c8c3a032..9c62eebb8 100644
--- a/src/components/cursor-controller.js
+++ b/src/components/cursor-controller.js
@@ -20,6 +20,8 @@ AFRAME.registerComponent("cursor-controller", {
     cursorColorUnhovered: { default: "#FFFFFF" },
     controllerEvent: { type: "string", default: "action_primary_down" },
     controllerEndEvent: { type: "string", default: "action_primary_up" },
+    grabEvent: { type: "string", default: "action_grab" },
+    releaseEvent: { type: "string", default: "action_release" },
     teleportEvent: { type: "string", default: "action_teleport_down" },
     teleportEndEvent: { type: "string", default: "action_teleport_up" }
   },
@@ -31,6 +33,7 @@ AFRAME.registerComponent("cursor-controller", {
     this.hasPointingDevice = false;
     this.currentTargetType = TARGET_TYPE_NONE;
     this.isGrabbing = false;
+    this.grabStarting = false;
     this.wasOtherHandGrabbing = false;
     this.wasIntersecting = false;
     this.currentDistance = this.data.maxDistance;
@@ -74,6 +77,8 @@ AFRAME.registerComponent("cursor-controller", {
       if (!!this.controller) {
         this.controller.removeEventListener(this.data.controllerEvent, this.controllerEventListener);
         this.controller.removeEventListener(this.data.controllerEndEvent, this.controllerEndEventListener);
+        this.controller.removeEventListener(this.data.grabEvent, this.controllerEventListener);
+        this.controller.removeEventListener(this.data.releaseEvent, this.controllerEndEventListener);
       }
 
       this.controller = document.querySelector(this.data.controller);
@@ -81,6 +86,8 @@ AFRAME.registerComponent("cursor-controller", {
       if (!!this.controller) {
         this.controller.addEventListener(this.data.controllerEvent, this.controllerEventListener);
         this.controller.addEventListener(this.data.controllerEndEvent, this.controllerEndEventListener);
+        this.controller.addEventListener(this.data.grabEvent, this.controllerEventListener);
+        this.controller.addEventListener(this.data.releaseEvent, this.controllerEndEventListener);
       }
     }
 
@@ -113,6 +120,7 @@ AFRAME.registerComponent("cursor-controller", {
       const hasPointingDevice = this.inVR && !!controller && !!controller.hand;
       if (this.hasPointingDevice != hasPointingDevice) {
         this.el.setAttribute("line", { visible: hasPointingDevice });
+        this.data.cursor.setAttribute("visible", hasPointingDevice);
       }
 
       if (hasPointingDevice && (this.data.hand != controller.hand || this.hasPointingDevice != hasPointingDevice)) {
@@ -143,6 +151,8 @@ AFRAME.registerComponent("cursor-controller", {
     if (!!this.controller) {
       this.controller.removeEventListener(this.data.controllerEvent, this.controllerEventListener);
       this.controller.removeEventListener(this.data.controllerEndEvent, this.controllerEndEventListener);
+      this.controller.removeEventListener(this.data.grabEvent, this.controllerEventListener);
+      this.controller.removeEventListener(this.data.releaseEvent, this.controllerEndEventListener);
     }
 
     this.data.playerRig.removeEventListener("model-loaded", this.modelLoadedListener);
@@ -153,11 +163,14 @@ AFRAME.registerComponent("cursor-controller", {
   tick: function() {
     this.isGrabbing = this.data.cursor.components["super-hands"].state.has("grab-start");
 
+    //handle physical hand
     if (this.otherHand) {
       const state = this.otherHand.components["super-hands"].state;
       const isOtherHandGrabbing = state.has("grab-start") || state.has("hover-start");
       if (this.wasOtherHandGrabbing != isOtherHandGrabbing) {
         this.data.cursor.setAttribute("visible", !isOtherHandGrabbing);
+        this.el.setAttribute("line", { visible: !isOtherHandGrabbing });
+        this.currentTargetType = TARGET_TYPE_NONE;
       }
       this.wasOtherHandGrabbing = isOtherHandGrabbing;
     }
@@ -216,7 +229,7 @@ AFRAME.registerComponent("cursor-controller", {
     if (this.isGrabbing && !intersection) {
       this.currentTargetType = TARGET_TYPE_INTERACTABLE;
     } else if (intersection) {
-      if (this._isInteractableAllowed() && this._isClass("interactable", intersection.object.el)) {
+      if (this._isClass("interactable", intersection.object.el)) {
         this.currentTargetType = TARGET_TYPE_INTERACTABLE;
       } else if (this._isClass("ui", intersection.object.el)) {
         this.currentTargetType = TARGET_TYPE_UI;
@@ -248,10 +261,6 @@ AFRAME.registerComponent("cursor-controller", {
     );
   },
 
-  _isInteractableAllowed: function() {
-    return !this.hasPointingDevice || this.isMobile;
-  },
-
   _isTargetOfType: function(mask) {
     return (this.currentTargetType & mask) === this.currentTargetType;
   },
@@ -345,18 +354,20 @@ AFRAME.registerComponent("cursor-controller", {
   },
 
   _handleControllerEvent: function(e) {
-    const isInteractable = this._isTargetOfType(TARGET_TYPE_INTERACTABLE) && this._isInteractableAllowed();
+    const isInteractable = this._isTargetOfType(TARGET_TYPE_INTERACTABLE) && !this.grabStarting;
     if (isInteractable || this._isTargetOfType(TARGET_TYPE_UI)) {
+      this.grabStarting = true;
       this.data.cursor.emit(this.data.controllerEvent, e.detail);
-    } else {
+    } else if (e.type !== this.data.grabEvent) {
       this._startTeleport();
     }
   },
 
   _handleControllerEndEvent: function(e) {
     if (this.isGrabbing || this._isTargetOfType(TARGET_TYPE_UI)) {
+      this.grabStarting = false;
       this.data.cursor.emit(this.data.controllerEndEvent, e.detail);
-    } else {
+    } else if (e.type !== this.data.releaseEvent) {
       this._endTeleport();
     }
   },
diff --git a/src/components/super-spawner.js b/src/components/super-spawner.js
index b67f60651..ae058484c 100644
--- a/src/components/super-spawner.js
+++ b/src/components/super-spawner.js
@@ -68,6 +68,7 @@ AFRAME.registerComponent("super-spawner", {
     const data = this.entities.get(entity);
     if (data.componentInitialized && data.bodyLoaded) {
       data.hand.emit("action_primary_down", { targetEntity: entity });
+      data.hand.emit("action_grab", { targetEntity: entity });
       const eventData = { bubbles: true, cancelable: true, detail: { hand: data.hand, target: entity } };
       const event = new CustomEvent("grab-start", eventData);
       entity.dispatchEvent(event);
diff --git a/src/hub.html b/src/hub.html
index 4c1186977..ad88e577d 100644
--- a/src/hub.html
+++ b/src/hub.html
@@ -119,9 +119,9 @@
                 super-hands="
                     colliderEvent: collisions; colliderEventProperty: els;
                     colliderEndEvent: collisions; colliderEndEventProperty: clearedEls;
-                    grabStartButtons: action_primary_down; grabEndButtons: action_primary_up;
-                    stretchStartButtons: action_primary_down; stretchEndButtons: action_primary_up;
-                    dragDropStartButtons: action_primary_down; dragDropEndButtons: action_primary_up;"
+                    grabStartButtons: action_grab; grabEndButtons: action_release;
+                    stretchStartButtons: action_grab; stretchEndButtons: action_release;
+                    dragDropStartButtons: action_grab; dragDropEndButtons: action_release;"
                 collision-filter="collisionForces: false"
                 physics-collider
             ></a-mixin>
@@ -263,7 +263,9 @@
                     <a-entity bone-visibility>
                         <a-entity
                             id="left-super-hand"
-                            event-repeater="events: action_primary_down, action_primary_up; eventSource: #player-left-controller"
+                            event-repeater="
+                            events: action_grab, action_release, action_primary_down, action_primary_up; 
+                            eventSource: #player-left-controller"
                             static-body="shape: sphere; sphereRadius: 0.02"
                             mixin="super-hands"
                             position="0 0.05 0"
@@ -275,7 +277,9 @@
                     <a-entity bone-visibility>
                         <a-entity
                             id="right-super-hand"
-                            event-repeater="events: action_primary_down, action_primary_up; eventSource: #player-right-controller"
+                            event-repeater="
+                            events: action_grab, action_release, action_primary_down, action_primary_up; 
+                            eventSource: #player-right-controller"
                             static-body="shape: sphere; sphereRadius: 0.02"
                             mixin="super-hands"
                             position="0 -0.05 0"
diff --git a/src/input-mappings.js b/src/input-mappings.js
index b692e173f..3a5c53cb1 100644
--- a/src/input-mappings.js
+++ b/src/input-mappings.js
@@ -46,12 +46,12 @@ const config = {
         trackpadup: { right: "action_primary_up" },
         menudown: "thumb_down",
         menuup: "thumb_up",
-        gripdown: ["action_primary_down", "middle_ring_pinky_down", "index_down"],
-        gripup: ["action_primary_up", "middle_ring_pinky_up", "index_up"],
+        gripdown: ["action_grab", "middle_ring_pinky_down", "index_down"],
+        gripup: ["action_release", "middle_ring_pinky_up", "index_up"],
         trackpadtouchstart: "thumb_down",
         trackpadtouchend: "thumb_up",
-        triggerdown: ["action_primary_down", "index_down"],
-        triggerup: ["action_primary_up", "index_up"]
+        triggerdown: ["action_primary_down", "action_grab", "index_down"],
+        triggerup: ["action_primary_up", "action_release", "index_up"]
       },
       "oculus-touch-controls": {
         joystick_dpad4_west: {
@@ -60,8 +60,8 @@ const config = {
         joystick_dpad4_east: {
           right: "snap_rotate_right"
         },
-        gripdown: ["action_primary_down", "middle_ring_pinky_down"],
-        gripup: ["action_primary_up", "middle_ring_pinky_up"],
+        gripdown: ["action_grab", "middle_ring_pinky_down"],
+        gripup: ["action_release", "middle_ring_pinky_up"],
         abuttontouchstart: "thumb_down",
         abuttontouchend: "thumb_up",
         bbuttontouchstart: "thumb_down",
-- 
GitLab