From 78b9858ee0d25eb716adba35bbec4a7eac3c9846 Mon Sep 17 00:00:00 2001 From: Daosheng Mu Date: Tue, 12 May 2020 15:55:33 -0700 Subject: [PATCH] Add Vive Focus WebXR Interstitial (#3361) --- .../mozilla/vrbrowser/VRBrowserActivity.java | 2 +- .../ui/widgets/WebXRInterstitialWidget.java | 2 + .../mozilla/vrbrowser/utils/DeviceType.java | 12 +++-- app/src/wavevr/cpp/DeviceDelegateWaveVR.cpp | 12 +++++ app/src/wavevr/cpp/DeviceDelegateWaveVR.h | 1 + .../mozilla/vrbrowser/PlatformActivity.java | 1 - .../wavevr/res/drawable/controller_focus.png | Bin 0 -> 24642 bytes ...eft.png => controller_focus_plus_left.png} | Bin ...ht.png => controller_focus_plus_right.png} | Bin .../layout/webxr_interstitial_controller.xml | 46 ++++++++++++++++-- 10 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 app/src/wavevr/res/drawable/controller_focus.png rename app/src/wavevr/res/drawable/{controller_focus_left.png => controller_focus_plus_left.png} (100%) rename app/src/wavevr/res/drawable/{controller_focus_right.png => controller_focus_plus_right.png} (100%) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java index a01152b98..0602dbf6a 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java @@ -1162,7 +1162,7 @@ public int getPointerColor() { @Keep @SuppressWarnings("unused") private void setDeviceType(int aType) { - if (DeviceType.isOculusBuild()) { + if (DeviceType.isOculusBuild() || DeviceType.isWaveBuild()) { runOnUiThread(() -> DeviceType.setType(aType)); } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WebXRInterstitialWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WebXRInterstitialWidget.java index 461484b8b..713a143f9 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WebXRInterstitialWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WebXRInterstitialWidget.java @@ -93,6 +93,8 @@ private void initializeControllers() { addController(DeviceType.PicoNeo2, WebXRInterstitialController.HAND_RIGHT); } else if (deviceType == DeviceType.PicoG2) { addController(DeviceType.PicoG2, WebXRInterstitialController.HAND_NONE); + } else if (deviceType == DeviceType.ViveFocus) { + addController(DeviceType.ViveFocus, WebXRInterstitialController.HAND_NONE); } else if (deviceType == DeviceType.ViveFocusPlus) { addController(DeviceType.ViveFocusPlus, WebXRInterstitialController.HAND_LEFT); addController(DeviceType.ViveFocusPlus, WebXRInterstitialController.HAND_RIGHT); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/utils/DeviceType.java b/app/src/common/shared/org/mozilla/vrbrowser/utils/DeviceType.java index 9a43e6c14..55446b4a1 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/utils/DeviceType.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/utils/DeviceType.java @@ -8,14 +8,15 @@ public class DeviceType { // These values need to match those in Device.h - @IntDef(value = { Unknown, OculusGo, OculusQuest, ViveFocusPlus, PicoNeo2, PicoG2 }) + @IntDef(value = { Unknown, OculusGo, OculusQuest, ViveFocus, ViveFocusPlus, PicoNeo2, PicoG2 }) public @interface Type {} public static final int Unknown = 0; public static final int OculusGo = 1; public static final int OculusQuest = 2; - public static final int ViveFocusPlus = 3; - public static final int PicoNeo2 = 4; - public static final int PicoG2 = 5; + public static final int ViveFocus = 3; + public static final int ViveFocusPlus = 4; + public static final int PicoNeo2 = 6; + public static final int PicoG2 = 7; private static @Type int mType = Unknown; @@ -28,6 +29,9 @@ public static void setType(@Type int aType) { case OculusQuest: name = "Oculus Quest"; break; + case ViveFocus: + name = "Vive Focus"; + break; case ViveFocusPlus: name = "Vive Focus Plus"; break; diff --git a/app/src/wavevr/cpp/DeviceDelegateWaveVR.cpp b/app/src/wavevr/cpp/DeviceDelegateWaveVR.cpp index d7ef518a8..2351b98aa 100644 --- a/app/src/wavevr/cpp/DeviceDelegateWaveVR.cpp +++ b/app/src/wavevr/cpp/DeviceDelegateWaveVR.cpp @@ -90,6 +90,7 @@ struct DeviceDelegateWaveVR::State { GestureDelegatePtr gestures; std::array controllers; ImmersiveDisplayPtr immersiveDisplay; + device::DeviceType deviceType; bool lastSubmitDiscarded; bool recentered; vrb::Matrix reorientMatrix; @@ -110,6 +111,7 @@ struct DeviceDelegateWaveVR::State { , renderHeight(0) , devicePairs {} , controllers {} + , deviceType(device::UnknownType) , lastSubmitDiscarded(false) , recentered(false) , ignoreNextRecenter(false) @@ -132,6 +134,11 @@ struct DeviceDelegateWaveVR::State { sixDoFControllerCount++; } } + if (sixDoFControllerCount) { + deviceType = device::ViveFocusPlus; + } else { + deviceType = device::ViveFocus; + } reorientMatrix = vrb::Matrix::Identity(); } @@ -454,6 +461,11 @@ DeviceDelegateWaveVR::Create(vrb::RenderContextPtr& aContext) { return result; } +device::DeviceType +DeviceDelegateWaveVR::GetDeviceType() { + return m.deviceType; +} + void DeviceDelegateWaveVR::SetRenderMode(const device::RenderMode aMode) { if (aMode == m.renderMode) { diff --git a/app/src/wavevr/cpp/DeviceDelegateWaveVR.h b/app/src/wavevr/cpp/DeviceDelegateWaveVR.h index 9fd86bff1..f4e32e93b 100644 --- a/app/src/wavevr/cpp/DeviceDelegateWaveVR.h +++ b/app/src/wavevr/cpp/DeviceDelegateWaveVR.h @@ -15,6 +15,7 @@ class DeviceDelegateWaveVR : public DeviceDelegate { public: static DeviceDelegateWaveVRPtr Create(vrb::RenderContextPtr& aContext); // DeviceDelegate interface + device::DeviceType GetDeviceType() override; void SetRenderMode(const device::RenderMode aMode) override; device::RenderMode GetRenderMode() override; void RegisterImmersiveDisplay(ImmersiveDisplayPtr aDisplay) override; diff --git a/app/src/wavevr/java/org/mozilla/vrbrowser/PlatformActivity.java b/app/src/wavevr/java/org/mozilla/vrbrowser/PlatformActivity.java index ea353f3f4..6f27e0033 100644 --- a/app/src/wavevr/java/org/mozilla/vrbrowser/PlatformActivity.java +++ b/app/src/wavevr/java/org/mozilla/vrbrowser/PlatformActivity.java @@ -36,7 +36,6 @@ public PlatformActivity() { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - DeviceType.setType(DeviceType.ViveFocusPlus); queueRunnable(new Runnable() { @Override diff --git a/app/src/wavevr/res/drawable/controller_focus.png b/app/src/wavevr/res/drawable/controller_focus.png new file mode 100644 index 0000000000000000000000000000000000000000..2f005a538c8a48afe180195be70fbfbd9475696d GIT binary patch literal 24642 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%0A+w%bfJa6FM zws;i!@8j2I;s5=k=P!Q&J+V_}k8#a2i|12L^b-QZOx?_XkMwkfGi$;tO74q4Fl5-7 zwlM2lD~kpVL4k5EZVRDInS2{qztdfu>P-6cX`gIik_Y zd=hm2Lhqy(rbyy#(x4)6^)%0@(N-#2qr~&a^@yL>g%xi$9z)N3-24*vwG!QNMbqJX z$&;R}+lbH!$}@X@B}me^B>Fb-Wz`(=l&G7w0w(h23*pF8NzlQ;UHYFaqkd?M@&J(r|g$YSm&Pvbx99mRHGt=c}Di8f*q=2?+65$ZBo zM(WcT+hZnUO&{uUAh`ElhcK9ieX-vV{@53uv3W~8+`Al_LW(vS89yctTs-8fo&VI| z`7S+xD%BZx%HBMhTGp?Lp|HjCU7SZLMDF3StZ+rZcI!TvQ`&RFTwu~$N0tr#5+nGL z4=x|FnJEgU|GY&nv-Wg2mAUO!%tU(go - - + + - + + + + + + + \ No newline at end of file