Bug 1356452 - Part 5: Detect hand changing at runtime for OpenVR controllers; r?kip draft
authorDaosheng Mu <daoshengmu@gmail.com>
Tue, 18 Apr 2017 15:58:34 +0800
changeset 565715 94bdeece0658a99a602a867f9ebdc45498ad75c5
parent 565714 8a8ea263bff0fc0d94a887a8a2c5bf81478a71fd
child 625093 ffbbd615f8dccb5ca75d0c884a814965e85147e6
push id54979
push userbmo:dmu@mozilla.com
push dateThu, 20 Apr 2017 09:28:49 +0000
reviewerskip
bugs1356452
milestone55.0a1
Bug 1356452 - Part 5: Detect hand changing at runtime for OpenVR controllers; r?kip MozReview-Commit-ID: AR5zpxryIw6
gfx/vr/gfxVR.cpp
gfx/vr/gfxVR.h
gfx/vr/gfxVROpenVR.cpp
gfx/vr/gfxVROpenVR.h
--- a/gfx/vr/gfxVR.cpp
+++ b/gfx/vr/gfxVR.cpp
@@ -110,8 +110,20 @@ VRSystemManager::NewPoseState(uint32_t a
                               const dom::GamepadPoseState& aPose)
 {
   dom::GamepadPoseInformation a(aIndex, dom::GamepadServiceType::VR,
                                 aPose);
 
   VRManager* vm = VRManager::Get();
   vm->NotifyGamepadChange<dom::GamepadPoseInformation>(a);
 }
+
+void
+VRSystemManager::NewHandChangeEvent(uint32_t aIndex,
+                                    const dom::GamepadHand aHand)
+{
+  dom::GamepadHandInformation a(aIndex, dom::GamepadServiceType::VR,
+                                aHand);
+
+  VRManager* vm = VRManager::Get();
+  vm->NotifyGamepadChange<dom::GamepadHandInformation>(a);
+}
+
--- a/gfx/vr/gfxVR.h
+++ b/gfx/vr/gfxVR.h
@@ -265,16 +265,17 @@ public:
   virtual void RemoveControllers() = 0;
   virtual void VibrateHaptic(uint32_t aControllerIdx, uint32_t aHapticIndex,
                              double aIntensity, double aDuration, uint32_t aPromiseID) = 0;
   virtual void StopVibrateHaptic(uint32_t aControllerIdx) = 0;
   void NewButtonEvent(uint32_t aIndex, uint32_t aButton, bool aPressed, bool aTouched,
                       double aValue);
   void NewAxisMove(uint32_t aIndex, uint32_t aAxis, double aValue);
   void NewPoseState(uint32_t aIndex, const dom::GamepadPoseState& aPose);
+  void NewHandChangeEvent(uint32_t aIndex, const dom::GamepadHand aHand);
   void AddGamepad(const VRControllerInfo& controllerInfo);
   void RemoveGamepad(uint32_t aIndex);
 
 protected:
   VRSystemManager() : mControllerCount(0) { }
   virtual ~VRSystemManager() { }
 
   uint32_t mControllerCount;
--- a/gfx/vr/gfxVROpenVR.cpp
+++ b/gfx/vr/gfxVROpenVR.cpp
@@ -399,16 +399,21 @@ VRControllerOpenVR::SetTrigger(float aVa
 
 float
 VRControllerOpenVR::GetTrigger()
 {
   return mTrigger;
 }
 
 void
+VRControllerOpenVR::SetHand(dom::GamepadHand aHand)
+{
+  mControllerInfo.mHand = aHand;
+}
+
 void
 VRControllerOpenVR::UpdateVibrateHaptic(::vr::IVRSystem* aVRSystem,
                                         uint32_t aHapticIndex,
                                         double aIntensity,
                                         double aDuration,
                                         uint64_t aVibrateIndex,
                                         uint32_t aPromiseID)
 {
@@ -603,16 +608,29 @@ VRSystemManagerOpenVR::HandleInput()
     controller = mOpenVRController[i];
     const uint32_t trackedIndex = controller->GetTrackedIndex();
 
     MOZ_ASSERT(mVRSystem->GetTrackedDeviceClass(trackedIndex)
                == ::vr::TrackedDeviceClass_Controller ||
                mVRSystem->GetTrackedDeviceClass(trackedIndex)
                == ::vr::TrackedDeviceClass_GenericTracker);
 
+    // Sometimes, OpenVR controllers are not located by HMD at the initial time.
+    // That makes us have to update the hand info at runtime although switching controllers
+    // to the other hand does not have new changes at the current OpenVR SDK. But, it makes sense
+    // to detect hand changing at runtime.
+    const ::vr::ETrackedControllerRole role = mVRSystem->
+                                                GetControllerRoleForTrackedDeviceIndex(
+                                                trackedIndex);
+    const dom::GamepadHand hand = GetGamepadHandFromControllerRole(role);
+    if (hand != controller->GetHand()) {
+      controller->SetHand(hand);
+      NewHandChangeEvent(i, hand);
+    }
+
     if (mVRSystem->GetControllerState(trackedIndex, &state, sizeof(state))) {
       for (uint32_t j = 0; j < ::vr::k_unControllerStateAxisCount; ++j) {
         const uint32_t axisType = mVRSystem->GetInt32TrackedDeviceProperty(
                                    trackedIndex,
                                    static_cast<::vr::TrackedDeviceProperty>(
                                    ::vr::Prop_Axis0Type_Int32 + j));
         switch (axisType) {
           case ::vr::EVRControllerAxisType::k_eControllerAxis_Joystick:
@@ -805,16 +823,40 @@ VRSystemManagerOpenVR::HandlePoseTrackin
 {
   MOZ_ASSERT(aController);
   if (aPose != aController->GetPose()) {
     aController->SetPose(aPose);
     NewPoseState(aControllerIdx, aPose);
   }
 }
 
+dom::GamepadHand
+VRSystemManagerOpenVR::GetGamepadHandFromControllerRole(
+                                          ::vr::ETrackedControllerRole aRole)
+{
+  dom::GamepadHand hand;
+
+  switch(aRole) {
+    case ::vr::ETrackedControllerRole::TrackedControllerRole_Invalid:
+      hand = dom::GamepadHand::_empty;
+      break;
+    case ::vr::ETrackedControllerRole::TrackedControllerRole_LeftHand:
+      hand = dom::GamepadHand::Left;
+      break;
+    case ::vr::ETrackedControllerRole::TrackedControllerRole_RightHand:
+      hand = dom::GamepadHand::Right;
+      break;
+    default:
+      MOZ_ASSERT(false);
+      break;
+  }
+
+  return hand;
+}
+
 void
 VRSystemManagerOpenVR::VibrateHaptic(uint32_t aControllerIdx,
                                      uint32_t aHapticIndex,
                                      double aIntensity,
                                      double aDuration,
                                      uint32_t aPromiseID)
 {
   // mVRSystem is available after VRDisplay is created
--- a/gfx/vr/gfxVROpenVR.h
+++ b/gfx/vr/gfxVROpenVR.h
@@ -66,16 +66,17 @@ class VRControllerOpenVR : public VRCont
 {
 public:
   explicit VRControllerOpenVR(dom::GamepadHand aHand, uint32_t aNumButtons,
                               uint32_t aNumAxes, ::vr::ETrackedDeviceClass aDeviceType);
   void SetTrackedIndex(uint32_t aTrackedIndex);
   uint32_t GetTrackedIndex();
   void SetTrigger(float aValue);
   float GetTrigger();
+  void SetHand(dom::GamepadHand aHand);
   void VibrateHaptic(::vr::IVRSystem* aVRSystem,
                      uint32_t aHapticIndex,
                      double aIntensity,
                      double aDuration,
                      uint32_t aPromiseID);
   void StopVibrateHaptic();
 
 protected: