[UI Ribbon] pause/resume game, show/hide lower panel based on lower menu selected

This commit is contained in:
amwatson 2024-03-20 17:38:24 -05:00
parent a75f5b7afd
commit e9eb4a30fd
6 changed files with 48 additions and 20 deletions

View file

@ -6,6 +6,7 @@ import android.widget.Button
import org.citra.citra_emu.NativeLibrary import org.citra.citra_emu.NativeLibrary
import org.citra.citra_emu.R import org.citra.citra_emu.R
import org.citra.citra_emu.vr.VrActivity import org.citra.citra_emu.vr.VrActivity
import org.citra.citra_emu.vr.utils.VrMessageQueue
class VrRibbonLayer(activity: VrActivity) : VrUILayer(activity, R.layout.vr_ribbon) { class VrRibbonLayer(activity: VrActivity) : VrUILayer(activity, R.layout.vr_ribbon) {
@ -26,6 +27,10 @@ class VrRibbonLayer(activity: VrActivity) : VrUILayer(activity, R.layout.vr_ribb
window?.findViewById<View>(menuTypeCurrent.resId)?.visibility = View.GONE window?.findViewById<View>(menuTypeCurrent.resId)?.visibility = View.GONE
menuTypeCurrent = menuTypeNew menuTypeCurrent = menuTypeNew
window?.findViewById<View>(menuTypeCurrent.resId)?.visibility = View.VISIBLE window?.findViewById<View>(menuTypeCurrent.resId)?.visibility = View.VISIBLE
if (menuTypeCurrent == MenuType.MAIN)
VrMessageQueue.post(VrMessageQueue.MessageType.CHANGE_LOWER_MENU, 0)
else if (menuTypeCurrent == MenuType.POSITION)
VrMessageQueue.post(VrMessageQueue.MessageType.CHANGE_LOWER_MENU, 1)
} }
fun initializeMainView() { fun initializeMainView() {
@ -62,15 +67,23 @@ class VrRibbonLayer(activity: VrActivity) : VrUILayer(activity, R.layout.vr_ribb
false false
} }
window?.findViewById<Button>(R.id.buttonNextMenu)?.setOnClickListener{ _ -> val btnNext = window?.findViewById<Button>(R.id.buttonNextMenu)
val btnPrev = window?.findViewById<Button>(R.id.buttonPrevMenu)
btnNext?.setOnClickListener{ _ ->
val nextIdx = (menuTypeCurrent.ordinal + 1) % MenuType.values().size val nextIdx = (menuTypeCurrent.ordinal + 1) % MenuType.values().size
switchMenus(MenuType.values()[nextIdx]) switchMenus(MenuType.values()[nextIdx])
if ((nextIdx + 1) >= MenuType.values().size)
btnNext.visibility = View.INVISIBLE
btnPrev?.visibility = View.VISIBLE
false false
} }
window?.findViewById<Button>(R.id.buttonPrevMenu)?.setOnClickListener { _ -> btnPrev?.setOnClickListener { _ ->
val prevIdx = (menuTypeCurrent.ordinal - 1 + MenuType.values().size) % MenuType.values().size val prevIdx = (menuTypeCurrent.ordinal - 1 + MenuType.values().size) % MenuType.values().size
switchMenus(MenuType.values()[prevIdx]) switchMenus(MenuType.values()[prevIdx])
if ((prevIdx - 1) <= 0)
btnPrev.visibility = View.INVISIBLE
btnNext?.visibility = View.VISIBLE
false false
} }
} }

View file

@ -4,7 +4,9 @@ object VrMessageQueue {
// Keep consistent with MessageQueue.h // Keep consistent with MessageQueue.h
enum class MessageType(val jniVal: Int) { enum class MessageType(val jniVal: Int) {
SHOW_KEYBOARD(0), SHOW_KEYBOARD(0),
SHOW_ERROR_MESSAGE(1) SHOW_ERROR_MESSAGE(1),
EXIT_NEEDED(2),
CHANGE_LOWER_MENU(3)
} }
@JvmStatic @JvmStatic
fun post(messageType: MessageType, payload: Long) { fun post(messageType: MessageType, payload: Long) {

View file

@ -450,8 +450,7 @@ XrPosef GameSurfaceLayer::GetTopPanelFromHeadPose(uint32_t eye, const XrPosef& h
panelPosition.y -= up.z / 25.f; panelPosition.y -= up.z / 25.f;
panelPosition.x += up.y / 25.f; panelPosition.x += up.y / 25.f;
if (mImmersiveMode == 3) if (mImmersiveMode == 3) {
{
panelPosition.z += right.x * (0.065f / 2.f) * (1 - 2.f * eye); panelPosition.z += right.x * (0.065f / 2.f) * (1 - 2.f * eye);
panelPosition.y -= right.z * (0.065f / 2.f) * (1 - 2.f * eye); panelPosition.y -= right.z * (0.065f / 2.f) * (1 - 2.f * eye);
panelPosition.x += right.y * (0.065f / 2.f) * (1 - 2.f * eye); panelPosition.x += right.y * (0.065f / 2.f) * (1 - 2.f * eye);

View file

@ -15,6 +15,8 @@ License : Licensed under GPLv3 or any later version.
#include <cstdint> #include <cstdint>
enum LowerMenuType : uint16_t { MAIN_MENU = 0, POSITIONAL_MENU = 1 };
/** /**
* Message class * Message class
* *
@ -28,7 +30,8 @@ struct Message {
enum Type { enum Type {
SHOW_KEYBOARD = 0, // payload 0 = hide keyboard, 1 = show keyboard SHOW_KEYBOARD = 0, // payload 0 = hide keyboard, 1 = show keyboard
SHOW_ERROR_MESSAGE = 1, // payload 0 = show error message, 1 = hide error message SHOW_ERROR_MESSAGE = 1, // payload 0 = show error message, 1 = hide error message
EXIT_NEEDED = 2 // payload ignored EXIT_NEEDED = 2, // payload ignored
CHANGE_LOWER_MENU = 3 // payload indicates menu ID
}; };
Message() {} Message() {}

View file

@ -207,7 +207,7 @@ public:
while (true) { while (true) {
// Handle events/state-changes. // Handle events/state-changes.
const AppState appState = HandleEvents(jni); AppState appState = HandleEvents(jni);
if (appState.mIsStopRequested) { break; } if (appState.mIsStopRequested) { break; }
HandleStateChanges(jni, appState); HandleStateChanges(jni, appState);
if (appState.mIsXrSessionActive) { if (appState.mIsXrSessionActive) {
@ -385,7 +385,7 @@ private:
// Super Immersive Mode update and computation. // Super Immersive Mode update and computation.
////////////////////////////////////////////////// //////////////////////////////////////////////////
bool showLowerPanel = true; bool showLowerPanel = appState.ShouldShowLowerPanel();
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];
@ -454,8 +454,8 @@ private:
invertedOrientation, gOpenXr->headLocation.pose.position); invertedOrientation, gOpenXr->headLocation.pose.position);
const float gamePosScaler = const float gamePosScaler =
powf(10.f, VRSettings::values.vr_immersive_positional_game_scaler) * powf(10.f, VRSettings::values.vr_immersive_positional_game_scaler) *
VRSettings::values.vr_factor_3d; VRSettings::values.vr_factor_3d;
inv_transform[3].x = -position.x * gamePosScaler; inv_transform[3].x = -position.x * gamePosScaler;
inv_transform[3].y = -position.y * gamePosScaler; inv_transform[3].y = -position.y * gamePosScaler;
@ -815,14 +815,18 @@ private:
return newState; return newState;
} }
void HandleStateChanges(JNIEnv* jni, const AppState& newState) const { void HandleStateChanges(JNIEnv* jni, AppState& newState) const {
if (newState.mIsEmulationPaused != mLastAppState.mIsEmulationPaused) { const bool shouldPauseEmulation = !newState.mHasFocus || newState.mShouldShowErrorMessage ||
newState.mLowerMenuType == LowerMenuType::POSITIONAL_MENU;
if (shouldPauseEmulation != mLastAppState.mIsEmulationPaused) {
ALOGI("State change: Emulation paused: {} -> {}", mLastAppState.mIsEmulationPaused, ALOGI("State change: Emulation paused: {} -> {}", mLastAppState.mIsEmulationPaused,
newState.mIsEmulationPaused); newState.mIsEmulationPaused);
if (newState.mIsEmulationPaused) { if (shouldPauseEmulation) {
PauseEmulation(jni); PauseEmulation(jni);
newState.mIsEmulationPaused = true;
} else { } else {
ResumeEmulation(jni); ResumeEmulation(jni);
newState.mIsEmulationPaused = false;
} }
} }
} }
@ -905,14 +909,10 @@ private:
switch (newState.state) { switch (newState.state) {
case XR_SESSION_STATE_FOCUSED: case XR_SESSION_STATE_FOCUSED:
ALOGV("{}(): Received XR_SESSION_STATE_FOCUSED event", __func__); ALOGV("{}(): Received XR_SESSION_STATE_FOCUSED event", __func__);
if (!mLastAppState.mHasFocus && !mLastAppState.mShouldShowErrorMessage) {
newAppState.mIsEmulationPaused = false;
}
newAppState.mHasFocus = true; newAppState.mHasFocus = true;
break; break;
case XR_SESSION_STATE_VISIBLE: case XR_SESSION_STATE_VISIBLE:
ALOGV("{}(): Received XR_SESSION_STATE_VISIBLE event", __func__); ALOGV("{}(): Received XR_SESSION_STATE_VISIBLE event", __func__);
if (mLastAppState.mHasFocus) { newAppState.mIsEmulationPaused = true; }
newAppState.mHasFocus = false; newAppState.mHasFocus = false;
break; break;
case XR_SESSION_STATE_READY: case XR_SESSION_STATE_READY:
@ -1022,12 +1022,10 @@ private:
newAppState.mShouldShowErrorMessage = shouldShowErrorMessage; newAppState.mShouldShowErrorMessage = shouldShowErrorMessage;
if (newAppState.mShouldShowErrorMessage && !newAppState.mIsEmulationPaused) { if (newAppState.mShouldShowErrorMessage && !newAppState.mIsEmulationPaused) {
ALOGD("Pausing emulation due to error message"); ALOGD("Pausing emulation due to error message");
newAppState.mIsEmulationPaused = true;
} }
if (!newAppState.mShouldShowErrorMessage && newAppState.mIsEmulationPaused && if (!newAppState.mShouldShowErrorMessage && newAppState.mIsEmulationPaused &&
newAppState.mHasFocus) { newAppState.mHasFocus) {
ALOGD("Resuming emulation after error message"); ALOGD("Resuming emulation after error message");
newAppState.mIsEmulationPaused = false;
} }
break; break;
} }
@ -1036,6 +1034,13 @@ private:
newAppState.mIsStopRequested = true; newAppState.mIsStopRequested = true;
break; break;
} }
case Message::Type::CHANGE_LOWER_MENU: {
newAppState.mLowerMenuType = static_cast<LowerMenuType>(message.mPayload);
ALOGI("Received CHANGE_LOWER_MENU message: {}, state change {} -> {}",
message.mPayload, mLastAppState.mLowerMenuType,
newAppState.mLowerMenuType);
break;
}
default: default:
ALOGE("Unknown message type: %d", message.mType); ALOGE("Unknown message type: %d", message.mType);
@ -1060,6 +1065,12 @@ private:
class AppState { class AppState {
public: public:
bool ShouldShowLowerPanel() const {
return mLowerMenuType == LowerMenuType::MAIN_MENU;
}
LowerMenuType mLowerMenuType = LowerMenuType::MAIN_MENU;
bool mIsKeyboardActive = false; bool mIsKeyboardActive = false;
bool mShouldShowErrorMessage = false; bool mShouldShowErrorMessage = false;
bool mIsEmulationPaused = false; bool mIsEmulationPaused = false;

View file

@ -45,7 +45,7 @@ struct Values {
int32_t vr_immersive_mode = 0; int32_t vr_immersive_mode = 0;
bool extra_performance_mode_enabled = false; bool extra_performance_mode_enabled = false;
int32_t vr_si_mode_register_offset = -1; int32_t vr_si_mode_register_offset = -1;
int32_t vr_factor_3d = 100; int32_t vr_factor_3d = 100;
int32_t vr_immersive_positional_game_scaler = 0; int32_t vr_immersive_positional_game_scaler = 0;
std::string vr_immersive_eye_indicator; std::string vr_immersive_eye_indicator;
} extern values; } extern values;