diff --git a/src/android/app/src/main/jni/vr/layers/CursorLayer.h b/src/android/app/src/main/jni/vr/layers/CursorLayer.h
index 2f48b3655..b8d75e985 100644
--- a/src/android/app/src/main/jni/vr/layers/CursorLayer.h
+++ b/src/android/app/src/main/jni/vr/layers/CursorLayer.h
@@ -37,7 +37,7 @@ public:
/** The type of cursor to render.
* Determines the color of the cursor.
**/
- enum class CursorType { CURSOR_TYPE_NORMAL, CURSOR_TYPE_TOP_PANEL, NUM_CURSOR_TYPES };
+ enum class CursorType { CURSOR_TYPE_NORMAL, CURSOR_TYPE_POSITIONAL_MENU, NUM_CURSOR_TYPES };
/**
* @param session a valid XR Session
*/
diff --git a/src/android/app/src/main/jni/vr/layers/GameSurfaceLayer.cpp b/src/android/app/src/main/jni/vr/layers/GameSurfaceLayer.cpp
index ae0aa3aff..719477cfe 100644
--- a/src/android/app/src/main/jni/vr/layers/GameSurfaceLayer.cpp
+++ b/src/android/app/src/main/jni/vr/layers/GameSurfaceLayer.cpp
@@ -31,7 +31,6 @@ License : Licensed under GPLv3 or any later version.
namespace {
constexpr float kSuperImmersiveRadius = 0.5f;
-constexpr float kDistanceBetweenPanelsInMeters = 0.75f;
constexpr float kInitialLowerPanelPitchInRadians = -MATH_FLOAT_PI / 4.0f; // -45 degrees in radians
//-----------------------------------------------------------------------------
@@ -485,7 +484,7 @@ void GameSurfaceLayer::SetLowerPanelFromController(const XrVector3f& controllerP
// Construct a quaternion for the pitch adjustment
const XrQuaternionf pitchAdjustmentQuat =
- XrMath::FromAxisAngle({1.0f, 0.0f, 0.0f}, newPitchRadians / 2.0f);
+ XrMath::Quatf::FromAxisAngle({1.0f, 0.0f, 0.0f}, newPitchRadians / 2.0f);
// Combine the base rotation with the pitch adjustment
mLowerPanel.mPanelFromWorld = {baseRotation * pitchAdjustmentQuat, windowPosition};
@@ -503,19 +502,6 @@ void GameSurfaceLayer::SetTopPanelFromThumbstick(const float thumbstickY) {
std::max(mTopPanel.mPanelFromWorld.position.z, kMaxDepth);
}
-XrPosef GameSurfaceLayer::SetLowerPanelFromThumbstick(const float thumbstickY) {
- static constexpr float kMinY = -3.0f;
-
- mLowerPanel.mPanelFromWorld.position.y += (thumbstickY * kThumbstickSpeed);
- mLowerPanel.mPanelFromWorld.position.y =
- std::min(mLowerPanel.mPanelFromWorld.position.y,
- mTopPanel.mPanelFromWorld.position.y - kDistanceBetweenPanelsInMeters);
- mLowerPanel.mPanelFromWorld.position.y =
- std::max(mLowerPanel.mPanelFromWorld.position.y, kMinY);
-
- return mLowerPanel.mPanelFromWorld;
-}
-
XrPosef GameSurfaceLayer::GetTopPanelFromHeadPose(uint32_t eye, const XrPosef& headPose) {
XrVector3f panelPosition = headPose.position;
diff --git a/src/android/app/src/main/jni/vr/vr_main.cpp b/src/android/app/src/main/jni/vr/vr_main.cpp
index e6d0b970a..c177a3b2c 100644
--- a/src/android/app/src/main/jni/vr/vr_main.cpp
+++ b/src/android/app/src/main/jni/vr/vr_main.cpp
@@ -98,6 +98,22 @@ void ForwardButtonStateIfNeeded(JNIEnv* jni, jobject activityObject,
}
}
+void SendTriggerStateToWindow(JNIEnv* jni, jobject activityObject,
+ jmethodID sendClickToWindowMethodID,
+ const XrActionStateBoolean& triggerState,
+ const XrVector2f& cursorPos2d) {
+ if (triggerState.currentState == 0 && triggerState.changedSinceLastSync) {
+ jni->CallVoidMethod(activityObject, sendClickToWindowMethodID, cursorPos2d.x, cursorPos2d.y,
+ 0);
+ } else if (triggerState.changedSinceLastSync && triggerState.currentState == 1) {
+ jni->CallVoidMethod(activityObject, sendClickToWindowMethodID, cursorPos2d.x, cursorPos2d.y,
+ 1);
+ } else if (triggerState.currentState == 1 && !triggerState.changedSinceLastSync) {
+ jni->CallVoidMethod(activityObject, sendClickToWindowMethodID, cursorPos2d.x, cursorPos2d.y,
+ 2);
+ }
+}
+
[[maybe_unused]] const char* XrSessionStateToString(const XrSessionState state) {
switch (state) {
case XR_SESSION_STATE_UNKNOWN:
@@ -652,7 +668,7 @@ private:
float scaleFactor = 0.01f;
CursorLayer::CursorType cursorType =
appState.mLowerMenuType == LowerMenuType::POSITIONAL_MENU
- ? CursorLayer::CursorType::CURSOR_TYPE_TOP_PANEL
+ ? CursorLayer::CursorType::CURSOR_TYPE_POSITIONAL_MENU
: CursorLayer::CursorType::CURSOR_TYPE_NORMAL;
[[maybe_unused]] const auto nonPreferredController =
@@ -690,6 +706,7 @@ private:
// Hit-test panels in order of priority (and known depth)
+ // 1. Error message layer
if (appState.mShouldShowErrorMessage) {
shouldRenderCursor = mErrorMessageLayer->GetRayIntersectionWithPanel(
start, end, cursorPos2d, cursorPose3d);
@@ -697,7 +714,8 @@ private:
mErrorMessageLayer->SendClickToUI(cursorPos2d, triggerState.currentState);
}
}
- // Don't test for cursor intersection if error message is shown
+
+ // 2. Keyboard layer
if (!shouldRenderCursor && appState.mIsKeyboardActive) {
shouldRenderCursor = mKeyboardLayer->GetRayIntersectionWithPanel(
start, end, cursorPos2d, cursorPose3d);
@@ -715,6 +733,7 @@ private:
mRibbonLayer->SetPanelWithPose(mGameSurfaceLayer->GetLowerPanelPose());
}
+ // 3. Lower panel
if (!shouldRenderCursor) {
shouldRenderCursor = mGameSurfaceLayer->GetRayIntersectionWithPanel(
start, end, cursorPos2d, cursorPose3d);
@@ -726,50 +745,21 @@ private:
sIsLowerPanelBeingPositioned = true;
} else if (appState.mLowerMenuType == LowerMenuType::MAIN_MENU) {
- if (triggerState.currentState == 0 && triggerState.changedSinceLastSync) {
- jni->CallVoidMethod(mActivityObject, mSendClickToWindowMethodID,
- cursorPos2d.x, cursorPos2d.y, 0);
- } else if (triggerState.changedSinceLastSync &&
- triggerState.currentState == 1) {
- jni->CallVoidMethod(mActivityObject, mSendClickToWindowMethodID,
- cursorPos2d.x, cursorPos2d.y, 1);
- } else if (triggerState.currentState == 1 &&
- !triggerState.changedSinceLastSync) {
-
- jni->CallVoidMethod(mActivityObject, mSendClickToWindowMethodID,
- cursorPos2d.x, cursorPos2d.y, 2);
- }
+ SendTriggerStateToWindow(jni, mActivityObject, mSendClickToWindowMethodID,
+ triggerState, cursorPos2d);
}
}
+ // 4. Ribbon layer
if (!shouldRenderCursor) {
shouldRenderCursor = mRibbonLayer->GetRayIntersectionWithPanel(
start, end, cursorPos2d, cursorPose3d);
if (shouldRenderCursor && triggerState.changedSinceLastSync) {
mRibbonLayer->SendClickToUI(cursorPos2d, triggerState.currentState);
}
- if ((shouldRenderCursor || sIsLowerPanelBeingPositioned) &&
- appState.mLowerMenuType == LowerMenuType::POSITIONAL_MENU &&
- triggerState.currentState) {
-
- static constexpr float kThumbStickDirectionThreshold = 0.5f;
- // If trigger is pressed, thumbstick controls
- // the depth
- const XrActionStateVector2f& thumbstickState =
- mInputStateFrame.mThumbStickState[mInputStateFrame.mPreferredHand];
-
- if (std::abs(thumbstickState.currentState.y) >
- kThumbStickDirectionThreshold) {
- const XrPosef lowerPanelPose =
- mGameSurfaceLayer->SetLowerPanelFromThumbstick(
- thumbstickState.currentState.y);
- mRibbonLayer->SetPanelWithPose(lowerPanelPose);
- }
- }
}
- if (sIsLowerPanelBeingPositioned) { shouldRenderCursor = true; }
- // Hit test the top panel if positional menu is active.
+ // 5. Hit test the top panel if positional menu is active.
if (!shouldRenderCursor &&
appState.mLowerMenuType == LowerMenuType::POSITIONAL_MENU) {
shouldRenderCursor = mGameSurfaceLayer->GetRayIntersectionWithPanelTopPanel(
@@ -822,6 +812,7 @@ private:
scaleFactor = 0.01f + 0.003f * distance;
}
}
+ if (sIsLowerPanelBeingPositioned) { shouldRenderCursor = true; }
}
if (shouldRenderCursor) {
diff --git a/src/android/app/src/main/res/layout/vr_ribbon.xml b/src/android/app/src/main/res/layout/vr_ribbon.xml
index f53f788c9..8f71064b9 100644
--- a/src/android/app/src/main/res/layout/vr_ribbon.xml
+++ b/src/android/app/src/main/res/layout/vr_ribbon.xml
@@ -72,7 +72,7 @@
android:layout_weight="1"
android:minHeight="0dp"
android:padding="0dp"
- android:paddingVertical="12dp"
+ android:paddingVertical="20dp"
android:text="<" />
diff --git a/src/android/app/src/main/res/layout/vr_ribbon_position_panel.xml b/src/android/app/src/main/res/layout/vr_ribbon_position_panel.xml
index 8ffd6c371..6be4ebcb0 100644
--- a/src/android/app/src/main/res/layout/vr_ribbon_position_panel.xml
+++ b/src/android/app/src/main/res/layout/vr_ribbon_position_panel.xml
@@ -2,39 +2,68 @@
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
-
+ app:layout_constraintTop_toTopOf="parent" />
-
+
+
+
+
+ android:layout_marginBottom="10dp"
+ android:text="@string/button_select" />
-
+
+
-
+ android:text="@string/button_start" />
+
+
-
\ No newline at end of file