remove thumbstick code (for now) and use main menu layout for traditional menu (temporary)

This commit is contained in:
amwatson 2024-03-24 18:20:20 -05:00
parent a5dcfc0e37
commit 5fe11a8be5
5 changed files with 83 additions and 77 deletions

View file

@ -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
*/

View file

@ -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;

View file

@ -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) {

View file

@ -72,7 +72,7 @@
android:layout_weight="1"
android:minHeight="0dp"
android:padding="0dp"
android:paddingVertical="12dp"
android:paddingVertical="20dp"
android:text="<" />
<Button
@ -83,7 +83,7 @@
android:layout_weight="1"
android:minHeight="0dp"
android:padding="0dp"
android:paddingVertical="12dp"
android:paddingVertical="20dp"
android:text="&gt;" />
</LinearLayout>
</LinearLayout>

View file

@ -2,39 +2,68 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/position_panel"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/linearLayout"
<FrameLayout
android:layout_width="1000dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_height="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.textview.MaterialTextView
android:layout_width="wrap_content"
<FrameLayout
android:id="@+id/lowerPanelPlaceHolder"
android:layout_width="900dp"
android:layout_height="675dp"
android:layout_marginTop="18dp"
android:background="#093A60"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:layout_width="100dp"
android:layout_height="400dp"
android:layout_gravity="center"
android:layout_marginStart="50dp"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="@+id/lowerPanelPlaceHolder"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/lowerPanelPlaceHolder"
app:layout_constraintTop_toTopOf="@+id/lowerPanelPlaceHolder">
<Button
android:id="@+id/buttonSelect"
style="@style/VrRibbonButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Press and hold trigger on panel to move it"
android:textAlignment="center"
android:textColor="@color/citra_onBackground" />
android:layout_marginBottom="10dp"
android:text="@string/button_select" />
<androidx.appcompat.widget.AppCompatToggleButton
android:id="@+id/toggle"
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<Button
android:id="@+id/buttonStart"
style="@style/VrRibbonButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Lock Horizontal Axis"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
android:text="@string/button_start" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<Button
android:id="@+id/buttonExit"
style="@style/VrRibbonButtonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/emulation_close_game" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>