mirror of
https://github.com/amwatson/CitraVR.git
synced 2024-09-19 19:01:38 +02:00
Keep positioning active even when cursor is not on panel.
This commit is contained in:
parent
cff2dc7ffc
commit
e486b927b2
2 changed files with 55 additions and 36 deletions
|
@ -30,8 +30,8 @@ License : Licensed under GPLv3 or any later version.
|
|||
|
||||
namespace {
|
||||
|
||||
constexpr float kSuperImmersiveRadius = 0.5f;
|
||||
|
||||
constexpr float kSuperImmersiveRadius = 0.5f;
|
||||
constexpr float kDistanceBetweenPanelsInMeters = 0.75f;
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local sysprops
|
||||
|
||||
|
@ -124,7 +124,7 @@ Panel CreateTopPanel(const XrVector3f& position, const float surfaceWidth,
|
|||
Panel CreateLowerPanelFromTopPanel(const Panel& topPanel, const float resolutionFactor) {
|
||||
// Note: the fact that two constants are 0.75 is purely coincidental.
|
||||
constexpr float kDefaultLowerPanelScaleFactor = 0.75f * 0.75f;
|
||||
constexpr float kLowerPanelYOffsetInMeters = -0.75f;
|
||||
constexpr float kLowerPanelYOffsetInMeters = -kDistanceBetweenPanelsInMeters;
|
||||
constexpr float kLowerPanelZOffsetInMeters = -1.5f;
|
||||
// Pitch the lower panel away from the viewer 45 degrees
|
||||
constexpr float kLowerPanelPitchInRadians = -MATH_FLOAT_PI / 4.0f;
|
||||
|
@ -420,8 +420,8 @@ bool GameSurfaceLayer::GetRayIntersectionWithPanel(const XrVector3f& start,
|
|||
void GameSurfaceLayer::SetTopPanelFromController(const XrVector3f& controllerPosition) {
|
||||
|
||||
static constexpr XrVector3f viewerPosition{0, 0, 0}; // Set viewer position
|
||||
const float sphereRadius = XrMath::Vector3f::Length(
|
||||
mTopPanel.mPanelFromWorld.position - viewerPosition); // Set the initial distance of the
|
||||
const float sphereRadius = XrMath::Vector3f::Length(
|
||||
mTopPanel.mPanelFromWorld.position - viewerPosition); // Set the initial distance of the
|
||||
|
||||
// window from the viewer
|
||||
static constexpr XrVector3f windowUpDirection{0, 1, 0}; // Y is up
|
||||
|
@ -430,17 +430,21 @@ void GameSurfaceLayer::SetTopPanelFromController(const XrVector3f& controllerPos
|
|||
CalculatePanelPosition(viewerPosition, controllerPosition, sphereRadius);
|
||||
const XrQuaternionf windowRotation =
|
||||
CalculatePanelRotation(windowPosition, viewerPosition, windowUpDirection);
|
||||
if (windowPosition.y < 0) { return; }
|
||||
if (windowPosition.y <
|
||||
(mLowerPanel.mPanelFromWorld.position.y + kDistanceBetweenPanelsInMeters)) {
|
||||
return;
|
||||
}
|
||||
if (XrMath::Quatf::GetYawInRadians(windowRotation) > MATH_FLOAT_PI / 3.0f) { return; }
|
||||
|
||||
mTopPanel.mPanelFromWorld = XrPosef{windowRotation, windowPosition};
|
||||
}
|
||||
|
||||
void GameSurfaceLayer::SetTopPanelFromThumbstick(const float thumbstickY) {
|
||||
static constexpr float kDepthSpeed = 0.05f;
|
||||
static constexpr float kMaxDepth = -10.0f;
|
||||
static constexpr float kThumbstickSpeed = 0.05f;
|
||||
|
||||
mTopPanel.mPanelFromWorld.position.z -= (thumbstickY * kDepthSpeed);
|
||||
void GameSurfaceLayer::SetTopPanelFromThumbstick(const float thumbstickY) {
|
||||
static constexpr float kMaxDepth = -10.0f;
|
||||
|
||||
mTopPanel.mPanelFromWorld.position.z -= (thumbstickY * kThumbstickSpeed);
|
||||
mTopPanel.mPanelFromWorld.position.z =
|
||||
std::min(mTopPanel.mPanelFromWorld.position.z, mLowerPanel.mPanelFromWorld.position.z);
|
||||
mTopPanel.mPanelFromWorld.position.z =
|
||||
|
@ -448,14 +452,14 @@ void GameSurfaceLayer::SetTopPanelFromThumbstick(const float thumbstickY) {
|
|||
}
|
||||
|
||||
XrPosef GameSurfaceLayer::SetLowerPanelFromThumbstick(const float thumbstickY) {
|
||||
static constexpr float kDepthSpeed = 0.05f;
|
||||
static constexpr float kMaxDepth = -10.0f;
|
||||
static constexpr float kMinY = -3.0f;
|
||||
|
||||
mLowerPanel.mPanelFromWorld.position.y += (thumbstickY * kDepthSpeed);
|
||||
mLowerPanel.mPanelFromWorld.position.y += (thumbstickY * kThumbstickSpeed);
|
||||
mLowerPanel.mPanelFromWorld.position.y =
|
||||
std::min(mLowerPanel.mPanelFromWorld.position.y, mTopPanel.mPanelFromWorld.position.y);
|
||||
std::min(mLowerPanel.mPanelFromWorld.position.y,
|
||||
mTopPanel.mPanelFromWorld.position.y - kDistanceBetweenPanelsInMeters);
|
||||
mLowerPanel.mPanelFromWorld.position.y =
|
||||
std::max(mLowerPanel.mPanelFromWorld.position.y, kMaxDepth);
|
||||
std::max(mLowerPanel.mPanelFromWorld.position.y, kMinY);
|
||||
|
||||
return mLowerPanel.mPanelFromWorld;
|
||||
}
|
||||
|
|
|
@ -650,7 +650,10 @@ private:
|
|||
XrPosef cursorPose3d = XrMath::Posef::Identity();
|
||||
XrVector2f cursorPos2d = {0, 0};
|
||||
float scaleFactor = 0.01f;
|
||||
CursorLayer::CursorType cursorType = appState.mLowerMenuType == LowerMenuType::POSITIONAL_MENU ? CursorLayer::CursorType::CURSOR_TYPE_TOP_PANEL : CursorLayer::CursorType::CURSOR_TYPE_NORMAL;
|
||||
CursorLayer::CursorType cursorType =
|
||||
appState.mLowerMenuType == LowerMenuType::POSITIONAL_MENU
|
||||
? CursorLayer::CursorType::CURSOR_TYPE_TOP_PANEL
|
||||
: CursorLayer::CursorType::CURSOR_TYPE_NORMAL;
|
||||
|
||||
[[maybe_unused]] const auto nonPreferredController =
|
||||
mInputStateFrame.mPreferredHand == InputStateFrame::LEFT_CONTROLLER
|
||||
|
@ -660,10 +663,15 @@ private:
|
|||
// unless neither controller is available.
|
||||
assert(mInputStateFrame.mIsHandActive[mInputStateFrame.mPreferredHand] ||
|
||||
!mInputStateFrame.mIsHandActive[nonPreferredController]);
|
||||
|
||||
{
|
||||
const bool isPreferredControllerActive =
|
||||
mInputStateFrame.mIsHandActive[mInputStateFrame.mPreferredHand];
|
||||
|
||||
static bool sIsLowerPanelBeingPositioned = false;
|
||||
|
||||
sIsLowerPanelBeingPositioned &=
|
||||
appState.mLowerMenuType == LowerMenuType::POSITIONAL_MENU &&
|
||||
isPreferredControllerActive;
|
||||
if (isPreferredControllerActive) {
|
||||
const XrPosef pose =
|
||||
mInputStateFrame.mHandPositions[mInputStateFrame.mPreferredHand].pose;
|
||||
|
@ -677,6 +685,8 @@ private:
|
|||
mInputStateFrame.mHandPositions[mInputStateFrame.mPreferredHand].pose,
|
||||
XrVector3f{0, 0, -3.5f});
|
||||
|
||||
sIsLowerPanelBeingPositioned &= triggerState.currentState > 0;
|
||||
|
||||
// Hit-test panels in order of priority (and known depth)
|
||||
|
||||
if (appState.mShouldShowErrorMessage) {
|
||||
|
@ -696,6 +706,7 @@ private:
|
|||
}
|
||||
// No dialogs/popups that should impede normal cursor interaction with
|
||||
// applicable panels
|
||||
|
||||
if (!shouldRenderCursor && appState.ShouldShowLowerPanel()) {
|
||||
shouldRenderCursor = mGameSurfaceLayer->GetRayIntersectionWithPanel(
|
||||
start, end, cursorPos2d, cursorPose3d);
|
||||
|
@ -713,13 +724,14 @@ private:
|
|||
cursorPos2d.x, cursorPos2d.y, 2);
|
||||
}
|
||||
}
|
||||
|
||||
if (!shouldRenderCursor) {
|
||||
shouldRenderCursor = mRibbonLayer->GetRayIntersectionWithPanel(
|
||||
start, end, cursorPos2d, cursorPose3d);
|
||||
if (shouldRenderCursor && triggerState.changedSinceLastSync) {
|
||||
mRibbonLayer->SendClickToUI(cursorPos2d, triggerState.currentState);
|
||||
}
|
||||
if (shouldRenderCursor &&
|
||||
if ((shouldRenderCursor || sIsLowerPanelBeingPositioned) &&
|
||||
appState.mLowerMenuType == LowerMenuType::POSITIONAL_MENU &&
|
||||
triggerState.currentState) {
|
||||
|
||||
|
@ -730,28 +742,15 @@ private:
|
|||
mInputStateFrame.mThumbStickState[mInputStateFrame.mPreferredHand];
|
||||
if (std::abs(thumbstickState.currentState.y) >
|
||||
kThumbStickDirectionThreshold) {
|
||||
const XrPosef lowerPanelPose = mGameSurfaceLayer->SetLowerPanelFromThumbstick(
|
||||
thumbstickState.currentState.y);
|
||||
const XrPosef lowerPanelPose =
|
||||
mGameSurfaceLayer->SetLowerPanelFromThumbstick(
|
||||
thumbstickState.currentState.y);
|
||||
mRibbonLayer->SetPanelWithPose(lowerPanelPose);
|
||||
sIsLowerPanelBeingPositioned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!shouldRenderCursor) {
|
||||
// Handling this here means L2/R2 are liable to
|
||||
// be slightly out of sync with the other
|
||||
// buttons (which are handled before
|
||||
// WaitFrame()). We'll see if that ends up being
|
||||
// a problem for any games.
|
||||
ForwardButtonStateIfNeeded(
|
||||
jni, mActivityObject, mForwardVRInputMethodID, 104 /* BUTTON_L2 */,
|
||||
mInputStateFrame.mIndexTriggerState[InputStateFrame::LEFT_CONTROLLER],
|
||||
"l2");
|
||||
ForwardButtonStateIfNeeded(
|
||||
jni, mActivityObject, mForwardVRInputMethodID, 105 /* BUTTON_R2 */,
|
||||
mInputStateFrame.mIndexTriggerState[InputStateFrame::RIGHT_CONTROLLER],
|
||||
"r2");
|
||||
}
|
||||
if (sIsLowerPanelBeingPositioned) { shouldRenderCursor = true; }
|
||||
|
||||
// Hit test the top panel if positional menu is active.
|
||||
if (!shouldRenderCursor &&
|
||||
|
@ -779,6 +778,22 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
if (!shouldRenderCursor) {
|
||||
// Handling this here means L2/R2 are liable to
|
||||
// be slightly out of sync with the other
|
||||
// buttons (which are handled before
|
||||
// WaitFrame()). We'll see if that ends up being
|
||||
// a problem for any games.
|
||||
ForwardButtonStateIfNeeded(
|
||||
jni, mActivityObject, mForwardVRInputMethodID, 104 /* BUTTON_L2 */,
|
||||
mInputStateFrame.mIndexTriggerState[InputStateFrame::LEFT_CONTROLLER],
|
||||
"l2");
|
||||
ForwardButtonStateIfNeeded(
|
||||
jni, mActivityObject, mForwardVRInputMethodID, 105 /* BUTTON_R2 */,
|
||||
mInputStateFrame.mIndexTriggerState[InputStateFrame::RIGHT_CONTROLLER],
|
||||
"r2");
|
||||
}
|
||||
|
||||
// Add a scale factor so the cursor doesn't scale as
|
||||
// quickly as the panel(s) with distance. This may be
|
||||
// mildly unsettling, but it helps to ensure the cursor
|
||||
|
|
Loading…
Reference in a new issue