mirror of
https://github.com/amwatson/CitraVR.git
synced 2024-09-20 03:11:40 +02:00
new Ribbon layer -- width is right, need height adjustment
This commit is contained in:
parent
44d4c2d609
commit
a558068642
7 changed files with 172 additions and 60 deletions
1
src/android/app/proguard-rules.pro
vendored
1
src/android/app/proguard-rules.pro
vendored
|
@ -28,4 +28,5 @@
|
||||||
-keep class org.citra.citra_emu.vr.ui.VrUILayer { *; }
|
-keep class org.citra.citra_emu.vr.ui.VrUILayer { *; }
|
||||||
-keep class org.citra.citra_emu.vr.ui.VrKeyboardLayer { *; }
|
-keep class org.citra.citra_emu.vr.ui.VrKeyboardLayer { *; }
|
||||||
-keep class org.citra.citra_emu.vr.ui.VrErrorMessageLayer { *; }
|
-keep class org.citra.citra_emu.vr.ui.VrErrorMessageLayer { *; }
|
||||||
|
-keep class org.citra.citra_emu.vr.ui.VrRibbonLayer { *; }
|
||||||
-keepattributes SourceFile,LineNumberTable
|
-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package org.citra.citra_emu.vr.ui
|
||||||
|
|
||||||
|
import org.citra.citra_emu.R
|
||||||
|
import org.citra.citra_emu.vr.VrActivity
|
||||||
|
|
||||||
|
class VrRibbonLayer(activity: VrActivity) : VrUILayer(activity, R.layout.vr_ribbon) {
|
||||||
|
override fun onSurfaceCreated() {
|
||||||
|
super.onSurfaceCreated()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -163,7 +163,7 @@ UILayer::UILayer(const std::string& className, const XrVector3f&& position,
|
||||||
const XrQuaternionf&& orientation, JNIEnv* env, jobject activityObject,
|
const XrQuaternionf&& orientation, JNIEnv* env, jobject activityObject,
|
||||||
const XrSession& session)
|
const XrSession& session)
|
||||||
: mSession(session)
|
: mSession(session)
|
||||||
, mPanelFromWorld(XrPosef{XrMath::Quatf::Identity(), position})
|
, mPanelFromWorld(XrPosef{orientation, position})
|
||||||
, mEnv(env) {
|
, mEnv(env) {
|
||||||
const int32_t initializationStatus = Init(className, activityObject, position, session);
|
const int32_t initializationStatus = Init(className, activityObject, position, session);
|
||||||
if (initializationStatus < 0) {
|
if (initializationStatus < 0) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ jclass JniUtils::GetGlobalClassReference(JNIEnv* env, jobject activityObject,
|
||||||
VR::JniGlobalRef::gClassLoader, VR::JniGlobalRef::gFindClassMethodID, classNameJString));
|
VR::JniGlobalRef::gClassLoader, VR::JniGlobalRef::gFindClassMethodID, classNameJString));
|
||||||
if (clazz == nullptr) {
|
if (clazz == nullptr) {
|
||||||
// Class not found
|
// Class not found
|
||||||
ALOGE("Class not found: %s", correctedClassName.c_str());
|
ALOGE("Class not found: {}", correctedClassName.c_str());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -143,6 +143,40 @@ uint32_t GetDefaultGameResolutionFactorForHmd(const VRSettings::HMDType& hmdType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called whenever a session is started/resumed. Creates the head space based on the
|
||||||
|
// current pose of the HMD.
|
||||||
|
void CreateRuntimeInitatedReferenceSpaces(const XrTime predictedDisplayTime) {
|
||||||
|
// Create a reference space with the forward direction from the
|
||||||
|
// starting frame.
|
||||||
|
{
|
||||||
|
const XrReferenceSpaceCreateInfo sci = {XR_TYPE_REFERENCE_SPACE_CREATE_INFO, nullptr,
|
||||||
|
XR_REFERENCE_SPACE_TYPE_LOCAL,
|
||||||
|
XrMath::Posef::Identity()};
|
||||||
|
OXR(xrCreateReferenceSpace(gOpenXr->mSession, &sci, &gOpenXr->mForwardDirectionSpace));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const XrReferenceSpaceCreateInfo sci = {XR_TYPE_REFERENCE_SPACE_CREATE_INFO, nullptr,
|
||||||
|
XR_REFERENCE_SPACE_TYPE_VIEW,
|
||||||
|
XrMath::Posef::Identity()};
|
||||||
|
OXR(xrCreateReferenceSpace(gOpenXr->mSession, &sci, &gOpenXr->mViewSpace));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the pose of the local space.
|
||||||
|
XrSpaceLocation lsl = {XR_TYPE_SPACE_LOCATION};
|
||||||
|
OXR(xrLocateSpace(gOpenXr->mForwardDirectionSpace, gOpenXr->mLocalSpace, predictedDisplayTime,
|
||||||
|
&lsl));
|
||||||
|
|
||||||
|
// Set the forward direction of the new space.
|
||||||
|
const XrPosef forwardDirectionPose = lsl.pose;
|
||||||
|
|
||||||
|
// Create a reference space with the same position and rotation as
|
||||||
|
// local.
|
||||||
|
const XrReferenceSpaceCreateInfo sci = {XR_TYPE_REFERENCE_SPACE_CREATE_INFO, nullptr,
|
||||||
|
XR_REFERENCE_SPACE_TYPE_LOCAL, forwardDirectionPose};
|
||||||
|
OXR(xrCreateReferenceSpace(gOpenXr->mSession, &sci, &gOpenXr->mHeadSpace));
|
||||||
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -239,18 +273,22 @@ private:
|
||||||
XrVector3f{0, 0, -2.0f}, jni, mActivityObject, gOpenXr->mSession, resolutionFactor);
|
XrVector3f{0, 0, -2.0f}, jni, mActivityObject, gOpenXr->mSession, resolutionFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the cursor layer.
|
mRibbonLayer = std::make_unique<UILayer>(
|
||||||
mCursorLayer = std::make_unique<CursorLayer>(gOpenXr->mSession);
|
"org/citra/citra_emu/vr/ui/VrRibbonLayer", XrVector3f{0, -0.75f, -1.51f},
|
||||||
|
XrMath::Quatf::FromEuler(0.0f, -MATH_FLOAT_PI / 4.0f, 0.0f), jni, mActivityObject, gOpenXr->mSession);
|
||||||
mErrorMessageLayer = std::make_unique<UILayer>(
|
|
||||||
"org/citra/citra_emu/vr/ui/VrErrorMessageLayer", XrVector3f{0, -0.1f, -1.0f},
|
|
||||||
XrQuaternionf{0, 0, 0, 1}, jni, mActivityObject, gOpenXr->mSession);
|
|
||||||
|
|
||||||
mKeyboardLayer = std::make_unique<UILayer>(
|
mKeyboardLayer = std::make_unique<UILayer>(
|
||||||
"org/citra/citra_emu/vr/ui/VrKeyboardLayer", XrVector3f{0, -0.4f, -0.5f},
|
"org/citra/citra_emu/vr/ui/VrKeyboardLayer", XrVector3f{0, -0.4f, -0.5f},
|
||||||
XrMath::Quatf::FromEuler(0.0f, -MATH_FLOAT_PI / 4.0f, 0.0f), jni, mActivityObject,
|
XrMath::Quatf::FromEuler(0.0f, -MATH_FLOAT_PI / 4.0f, 0.0f), jni, mActivityObject,
|
||||||
gOpenXr->mSession);
|
gOpenXr->mSession);
|
||||||
|
|
||||||
|
mErrorMessageLayer = std::make_unique<UILayer>(
|
||||||
|
"org/citra/citra_emu/vr/ui/VrErrorMessageLayer", XrVector3f{0, -0.1f, -1.0f},
|
||||||
|
XrQuaternionf{0, 0, 0, 1}, jni, mActivityObject, gOpenXr->mSession);
|
||||||
|
|
||||||
|
// Create the cursor layer.
|
||||||
|
mCursorLayer = std::make_unique<CursorLayer>(gOpenXr->mSession);
|
||||||
|
|
||||||
//////////////////////////////////////////////////
|
//////////////////////////////////////////////////
|
||||||
// Intialize JNI methods
|
// Intialize JNI methods
|
||||||
//////////////////////////////////////////////////
|
//////////////////////////////////////////////////
|
||||||
|
@ -451,6 +489,9 @@ private:
|
||||||
layers[layerCount++].mPassthrough = passthroughLayer;
|
layers[layerCount++].mPassthrough = passthroughLayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mRibbonLayer->Frame(gOpenXr->mLocalSpace, layers, layerCount);
|
||||||
|
|
||||||
|
|
||||||
// Game surface (upper and lower panels) are in front of the passthrough layer.
|
// Game surface (upper and lower panels) are in front of the passthrough layer.
|
||||||
mGameSurfaceLayer->Frame(gOpenXr->mLocalSpace, layers, layerCount,
|
mGameSurfaceLayer->Frame(gOpenXr->mLocalSpace, layers, layerCount,
|
||||||
gOpenXr->headLocation.pose, immersiveModeFactor,
|
gOpenXr->headLocation.pose, immersiveModeFactor,
|
||||||
|
@ -604,41 +645,6 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called whenever a session is started/resumed. Creates the head space based on the
|
|
||||||
// current pose of the HMD.
|
|
||||||
void CreateRuntimeInitatedReferenceSpaces(const XrTime predictedDisplayTime) const {
|
|
||||||
// Create a reference space with the forward direction from the
|
|
||||||
// starting frame.
|
|
||||||
{
|
|
||||||
const XrReferenceSpaceCreateInfo sci = {XR_TYPE_REFERENCE_SPACE_CREATE_INFO, nullptr,
|
|
||||||
XR_REFERENCE_SPACE_TYPE_LOCAL,
|
|
||||||
XrMath::Posef::Identity()};
|
|
||||||
OXR(xrCreateReferenceSpace(gOpenXr->mSession, &sci, &gOpenXr->mForwardDirectionSpace));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const XrReferenceSpaceCreateInfo sci = {XR_TYPE_REFERENCE_SPACE_CREATE_INFO, nullptr,
|
|
||||||
XR_REFERENCE_SPACE_TYPE_VIEW,
|
|
||||||
XrMath::Posef::Identity()};
|
|
||||||
OXR(xrCreateReferenceSpace(gOpenXr->mSession, &sci, &gOpenXr->mViewSpace));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the pose of the local space.
|
|
||||||
XrSpaceLocation lsl = {XR_TYPE_SPACE_LOCATION};
|
|
||||||
OXR(xrLocateSpace(gOpenXr->mForwardDirectionSpace, gOpenXr->mLocalSpace,
|
|
||||||
predictedDisplayTime, &lsl));
|
|
||||||
|
|
||||||
// Set the forward direction of the new space.
|
|
||||||
const XrPosef forwardDirectionPose = lsl.pose;
|
|
||||||
|
|
||||||
// Create a reference space with the same position and rotation as
|
|
||||||
// local.
|
|
||||||
const XrReferenceSpaceCreateInfo sci = {XR_TYPE_REFERENCE_SPACE_CREATE_INFO, nullptr,
|
|
||||||
XR_REFERENCE_SPACE_TYPE_LOCAL,
|
|
||||||
forwardDirectionPose};
|
|
||||||
OXR(xrCreateReferenceSpace(gOpenXr->mSession, &sci, &gOpenXr->mHeadSpace));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Handle the cursor and any hand-tracked/layer-dependent input
|
/** Handle the cursor and any hand-tracked/layer-dependent input
|
||||||
* interactions.
|
* interactions.
|
||||||
**/
|
**/
|
||||||
|
@ -798,22 +804,22 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
AppState HandleEvents(JNIEnv* jni) const {
|
AppState HandleEvents(JNIEnv* jni) const {
|
||||||
AppState newState = mLastAppState;
|
AppState newState = mLastAppState;
|
||||||
OXRPollEvents(jni, newState);
|
OXRPollEvents(jni, newState);
|
||||||
HandleMessageQueueEvents(jni, newState);
|
HandleMessageQueueEvents(jni, newState);
|
||||||
return newState;
|
return newState;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleStateChanges(JNIEnv* jni, const AppState& newState) const {
|
void HandleStateChanges(JNIEnv* jni, const AppState& newState) const {
|
||||||
if (newState.mIsEmulationPaused != mLastAppState.mIsEmulationPaused) {
|
if (newState.mIsEmulationPaused != mLastAppState.mIsEmulationPaused) {
|
||||||
ALOGI("State change: Emulation paused: {} -> {}", mLastAppState.mIsEmulationPaused,
|
ALOGI("State change: Emulation paused: {} -> {}", mLastAppState.mIsEmulationPaused,
|
||||||
newState.mIsEmulationPaused);
|
newState.mIsEmulationPaused);
|
||||||
if (newState.mIsEmulationPaused) {
|
if (newState.mIsEmulationPaused) {
|
||||||
PauseEmulation(jni);
|
PauseEmulation(jni);
|
||||||
} else {
|
} else {
|
||||||
ResumeEmulation(jni);
|
ResumeEmulation(jni);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OXRPollEvents(JNIEnv* jni, AppState& newAppState) const {
|
void OXRPollEvents(JNIEnv* jni, AppState& newAppState) const {
|
||||||
|
@ -881,8 +887,8 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void OXRHandleSessionStateChangedEvent(JNIEnv* jni,
|
void OXRHandleSessionStateChangedEvent(JNIEnv* jni,
|
||||||
AppState& newAppState,
|
AppState& newAppState,
|
||||||
const XrEventDataSessionStateChanged& newState) const {
|
const XrEventDataSessionStateChanged& newState) const {
|
||||||
static XrSessionState lastState = XR_SESSION_STATE_UNKNOWN;
|
static XrSessionState lastState = XR_SESSION_STATE_UNKNOWN;
|
||||||
if (newState.state != lastState) {
|
if (newState.state != lastState) {
|
||||||
ALOGV("{}(): Received XR_SESSION_STATE_CHANGED state {}->{} "
|
ALOGV("{}(): Received XR_SESSION_STATE_CHANGED state {}->{} "
|
||||||
|
@ -901,9 +907,7 @@ private:
|
||||||
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) {
|
if (mLastAppState.mHasFocus) { newAppState.mIsEmulationPaused = true; }
|
||||||
newAppState.mIsEmulationPaused = true;
|
|
||||||
}
|
|
||||||
newAppState.mHasFocus = false;
|
newAppState.mHasFocus = false;
|
||||||
break;
|
break;
|
||||||
case XR_SESSION_STATE_READY:
|
case XR_SESSION_STATE_READY:
|
||||||
|
@ -1066,6 +1070,7 @@ private:
|
||||||
std::unique_ptr<GameSurfaceLayer> mGameSurfaceLayer;
|
std::unique_ptr<GameSurfaceLayer> mGameSurfaceLayer;
|
||||||
std::unique_ptr<PassthroughLayer> mPassthroughLayer;
|
std::unique_ptr<PassthroughLayer> mPassthroughLayer;
|
||||||
std::unique_ptr<UILayer> mKeyboardLayer;
|
std::unique_ptr<UILayer> mKeyboardLayer;
|
||||||
|
std::unique_ptr<UILayer> mRibbonLayer;
|
||||||
|
|
||||||
std::unique_ptr<InputStateStatic> mInputStateStatic;
|
std::unique_ptr<InputStateStatic> mInputStateStatic;
|
||||||
InputStateFrame mInputStateFrame;
|
InputStateFrame mInputStateFrame;
|
||||||
|
|
87
src/android/app/src/main/res/layout/vr_ribbon.xml
Normal file
87
src/android/app/src/main/res/layout/vr_ribbon.xml
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="1540dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/vr_menu_background"
|
||||||
|
android:padding="20dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="1200dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/frameLayout"
|
||||||
|
android:layout_width="900dp"
|
||||||
|
android:layout_height="900dp"
|
||||||
|
android:background="@android:color/black"
|
||||||
|
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="20dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/frameLayout"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/frameLayout"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/frameLayout">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/buttonSelect"
|
||||||
|
style="@style/VrRibbonButtonStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:text="@string/button_select" />
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/buttonHome"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:background="@null"
|
||||||
|
android:src="@drawable/button_home" />
|
||||||
|
|
||||||
|
<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="@string/button_start" />
|
||||||
|
</LinearLayout>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -37,4 +37,10 @@
|
||||||
<item name="colorControlNormal">@color/citra_primary</item>
|
<item name="colorControlNormal">@color/citra_primary</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="VrRibbonButtonStyle" parent="@style/VrKeyboardButtonStyle">
|
||||||
|
<item name="android:alpha">0.5</item>
|
||||||
|
<item name="android:background">#80eaeaea</item>
|
||||||
|
<item name="android:textColor">@android:color/black</item>
|
||||||
|
<item name="android:textAlignment">center</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue