hacky setting of lower menu based on ribbon press

This commit is contained in:
amwatson 2024-04-06 20:01:13 -05:00
parent 8a748b1e0d
commit d012252cb8
5 changed files with 61 additions and 26 deletions

View file

@ -28,6 +28,10 @@ class VrRibbonLayer(activity: VrActivity) : VrUILayer(activity, R.layout.vr_ribb
initializePositionalPanel() initializePositionalPanel()
} }
// Used in positional menu to know when background is selected, but not the buttons,
// in which case, move the panel.
private var isMenuBackgroundSelected = false
fun switchMenus(menuTypeNew: MenuType) { fun switchMenus(menuTypeNew: MenuType) {
if (menuTypeNew == menuTypeCurrent) if (menuTypeNew == menuTypeCurrent)
return return
@ -40,6 +44,10 @@ class VrRibbonLayer(activity: VrActivity) : VrUILayer(activity, R.layout.vr_ribb
VrMessageQueue.post(VrMessageQueue.MessageType.CHANGE_LOWER_MENU, 1) VrMessageQueue.post(VrMessageQueue.MessageType.CHANGE_LOWER_MENU, 1)
} }
fun isMenuBackgroundSelected(): Boolean {
return isMenuBackgroundSelected
}
private fun initializeLeftMenu() { private fun initializeLeftMenu() {
val radioGroup = window?.findViewById<RadioGroup>(R.id.vertical_tab) val radioGroup = window?.findViewById<RadioGroup>(R.id.vertical_tab)
radioGroup?.setOnCheckedChangeListener { group, checkedId -> radioGroup?.setOnCheckedChangeListener { group, checkedId ->
@ -77,6 +85,19 @@ class VrRibbonLayer(activity: VrActivity) : VrUILayer(activity, R.layout.vr_ribb
horizontalLockToggle?.isChecked = true; horizontalLockToggle?.isChecked = true;
VrMessageQueue.post(VrMessageQueue.MessageType.CHANGE_LOCK_HORIZONTAL_AXIS, if (horizontalLockToggle?.isChecked == true) 1 else 0) VrMessageQueue.post(VrMessageQueue.MessageType.CHANGE_LOCK_HORIZONTAL_AXIS, if (horizontalLockToggle?.isChecked == true) 1 else 0)
window?.findViewById<View>(R.id.frame)?.setOnTouchListener { _, motionEvent ->
/// set isMenuBackgroundSelected based on the motionEvent
when (motionEvent.action) {
KeyEvent.ACTION_DOWN -> {
isMenuBackgroundSelected = true
}
KeyEvent.ACTION_UP -> {
isMenuBackgroundSelected = false
}
}
false
}
} }
private fun initializeMainPanel() { private fun initializeMainPanel() {

View file

@ -214,7 +214,7 @@ bool UILayer::GetRayIntersectionWithPanel(const XrVector3f& start,
scale, start, end, result2d, result3d); scale, start, end, result2d, result3d);
} }
// Next error code: -8 // Next error code: -9
int32_t UILayer::Init(const std::string& className, const jobject activityObject, int32_t UILayer::Init(const std::string& className, const jobject activityObject,
const XrVector3f& position, const XrSession& session) { const XrVector3f& position, const XrSession& session) {
mVrUILayerClass = JniUtils::GetGlobalClassReference(mEnv, activityObject, className.c_str()); mVrUILayerClass = JniUtils::GetGlobalClassReference(mEnv, activityObject, className.c_str());
@ -238,7 +238,16 @@ int32_t UILayer::Init(const std::string& className, const jobject activityObject
BAIL_ON_COND(mSendClickToUIMethodID == nullptr, "could not find sendClickToUI()", -6); BAIL_ON_COND(mSendClickToUIMethodID == nullptr, "could not find sendClickToUI()", -6);
BAIL_ON_ERR(CreateSwapchain(), -7); if (className == "org/citra/citra_emu/vr/ui/VrRibbonLayer") {
ALOGD("UILayer: using companion class");
mIsMenuBackgroundSelectedMethodId =
mEnv->GetMethodID(mVrUILayerClass, "isMenuBackgroundSelected", "()Z");
BAIL_ON_COND(mIsMenuBackgroundSelectedMethodId == nullptr,
"could not find isMenuBackgroundSelected()", -7);
}
BAIL_ON_ERR(CreateSwapchain(), -8);
return 0; return 0;
} }
@ -327,3 +336,7 @@ void UILayer::SendClickToUI(const XrVector2f& pos2d, const int type) {
} }
void UILayer::SetPanelWithPose(const XrPosef& pose) { mPanelFromWorld = pose; } void UILayer::SetPanelWithPose(const XrPosef& pose) { mPanelFromWorld = pose; }
bool UILayer::IsMenuBackgroundSelected() const {
return mEnv->CallBooleanMethod(mVrUILayerObject, mIsMenuBackgroundSelectedMethodId);
}

View file

@ -125,6 +125,8 @@ public:
void SetPanelWithPose(const XrPosef& pose); void SetPanelWithPose(const XrPosef& pose);
bool IsMenuBackgroundSelected() const;
private: private:
int Init(const std::string& className, const jobject activityObject, const XrVector3f& position, int Init(const std::string& className, const jobject activityObject, const XrVector3f& position,
const XrSession& session); const XrSession& session);
@ -154,7 +156,8 @@ private:
// the decorView representing an entire window, it's important to accont for // the decorView representing an entire window, it's important to accont for
// the x, y offset of the view within the window, in case there are things // the x, y offset of the view within the window, in case there are things
// like window decorations or status bars. // like window decorations or status bars.
jmethodID mGetBoundsMethodID = nullptr; jmethodID mGetBoundsMethodID = nullptr;
jmethodID mSendClickToUIMethodID = nullptr; jmethodID mSendClickToUIMethodID = nullptr;
jmethodID mSetSurfaceMethodId = nullptr; jmethodID mSetSurfaceMethodId = nullptr;
jmethodID mIsMenuBackgroundSelectedMethodId = nullptr;
}; };

View file

@ -407,7 +407,7 @@ private:
// Super Immersive Mode update and computation. // Super Immersive Mode update and computation.
////////////////////////////////////////////////// //////////////////////////////////////////////////
bool showLowerPanel = true; bool showLowerPanel = appState.mLowerMenuType != LowerMenuType::POSITIONAL_MENU;
float immersiveModeFactor = (VRSettings::values.vr_immersive_mode < 2) float immersiveModeFactor = (VRSettings::values.vr_immersive_mode < 2)
? immersiveScaleFactor[VRSettings::values.vr_immersive_mode] ? immersiveScaleFactor[VRSettings::values.vr_immersive_mode]
: immersiveScaleFactor[2]; : immersiveScaleFactor[2];
@ -526,7 +526,7 @@ private:
// Cursor visibility will depend on hit-test but will be in front // Cursor visibility will depend on hit-test but will be in front
// of all other panels. This is because precedence lines up with depth order. // of all other panels. This is because precedence lines up with depth order.
HandleCursorLayer(jni, appState, layers, layerCount); HandleCursorLayer(jni, appState, showLowerPanel, layers, layerCount);
} }
std::vector<const XrCompositionLayerBaseHeader*> layerHeaders; std::vector<const XrCompositionLayerBaseHeader*> layerHeaders;
@ -665,7 +665,7 @@ private:
/** Handle the cursor and any hand-tracked/layer-dependent input /** Handle the cursor and any hand-tracked/layer-dependent input
* interactions. * interactions.
**/ **/
void HandleCursorLayer(JNIEnv* jni, const AppState& appState, void HandleCursorLayer(JNIEnv* jni, const AppState& appState, const bool showLowerPanel,
std::vector<XrCompositionLayer>& layers, uint32_t& layerCount) const { std::vector<XrCompositionLayer>& layers, uint32_t& layerCount) const {
bool shouldRenderCursor = false; bool shouldRenderCursor = false;
@ -690,7 +690,6 @@ private:
mInputStateFrame.mIsHandActive[mInputStateFrame.mPreferredHand]; mInputStateFrame.mIsHandActive[mInputStateFrame.mPreferredHand];
static bool sIsLowerPanelBeingPositioned = false; static bool sIsLowerPanelBeingPositioned = false;
const bool wasLowerPanelBeingPositioned = sIsLowerPanelBeingPositioned;
sIsLowerPanelBeingPositioned &= sIsLowerPanelBeingPositioned &=
appState.mLowerMenuType == LowerMenuType::POSITIONAL_MENU && appState.mLowerMenuType == LowerMenuType::POSITIONAL_MENU &&
@ -732,26 +731,11 @@ private:
// No dialogs/popups that should impede normal cursor interaction with // No dialogs/popups that should impede normal cursor interaction with
// applicable panels // applicable panels
// Lock ribbon in place when placement is complete
const bool needRibbonUpdate =
!sIsLowerPanelBeingPositioned && wasLowerPanelBeingPositioned;
if (needRibbonUpdate) {
mRibbonLayer->SetPanelWithPose(mGameSurfaceLayer->GetLowerPanelPose());
}
// 3. Lower panel // 3. Lower panel
if (!shouldRenderCursor) { if (!shouldRenderCursor && showLowerPanel) {
shouldRenderCursor = mGameSurfaceLayer->GetRayIntersectionWithPanel( shouldRenderCursor = mGameSurfaceLayer->GetRayIntersectionWithPanel(
start, end, cursorPos2d, cursorPose3d); start, end, cursorPos2d, cursorPose3d);
if ((shouldRenderCursor || sIsLowerPanelBeingPositioned) && if (appState.mLowerMenuType == LowerMenuType::MAIN_MENU) {
appState.mLowerMenuType == LowerMenuType::POSITIONAL_MENU &&
triggerState.currentState) {
mGameSurfaceLayer->SetLowerPanelFromController(
{appState.mIsHorizontalAxisLocked ? 0.0f : cursorPose3d.position.x,
cursorPose3d.position.y, cursorPose3d.position.z});
sIsLowerPanelBeingPositioned = true;
} else if (appState.mLowerMenuType == LowerMenuType::MAIN_MENU) {
SendTriggerStateToWindow(jni, mActivityObject, mSendClickToWindowMethodID, SendTriggerStateToWindow(jni, mActivityObject, mSendClickToWindowMethodID,
triggerState, cursorPos2d); triggerState, cursorPos2d);
} }
@ -764,6 +748,18 @@ private:
if (shouldRenderCursor && triggerState.changedSinceLastSync) { if (shouldRenderCursor && triggerState.changedSinceLastSync) {
mRibbonLayer->SendClickToUI(cursorPos2d, triggerState.currentState); mRibbonLayer->SendClickToUI(cursorPos2d, triggerState.currentState);
} }
if (appState.mLowerMenuType == LowerMenuType::POSITIONAL_MENU &&
(sIsLowerPanelBeingPositioned ||
(shouldRenderCursor && mRibbonLayer->IsMenuBackgroundSelected())) &&
triggerState.currentState) {
mGameSurfaceLayer->SetLowerPanelFromController(
{appState.mIsHorizontalAxisLocked ? 0.0f : cursorPose3d.position.x,
cursorPose3d.position.y, cursorPose3d.position.z});
mRibbonLayer->SetPanelWithPose(mGameSurfaceLayer->GetLowerPanelPose());
sIsLowerPanelBeingPositioned = true;
}
} }
// 5. Top panel (only if positional menu is active) // 5. Top panel (only if positional menu is active)

View file

@ -28,6 +28,8 @@
android:background="@drawable/vr_menu_background" android:background="@drawable/vr_menu_background"
android:backgroundTint="#011627" android:backgroundTint="#011627"
android:padding="50dp" android:padding="50dp"
android:clickable="true"
android:focusable="true"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">