mirror of
https://github.com/amwatson/CitraVR.git
synced 2024-09-20 03:11:40 +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
|
@ -31,7 +31,7 @@ License : Licensed under GPLv3 or any later version.
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr float kSuperImmersiveRadius = 0.5f;
|
constexpr float kSuperImmersiveRadius = 0.5f;
|
||||||
|
constexpr float kDistanceBetweenPanelsInMeters = 0.75f;
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Local sysprops
|
// Local sysprops
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ Panel CreateTopPanel(const XrVector3f& position, const float surfaceWidth,
|
||||||
Panel CreateLowerPanelFromTopPanel(const Panel& topPanel, const float resolutionFactor) {
|
Panel CreateLowerPanelFromTopPanel(const Panel& topPanel, const float resolutionFactor) {
|
||||||
// Note: the fact that two constants are 0.75 is purely coincidental.
|
// Note: the fact that two constants are 0.75 is purely coincidental.
|
||||||
constexpr float kDefaultLowerPanelScaleFactor = 0.75f * 0.75f;
|
constexpr float kDefaultLowerPanelScaleFactor = 0.75f * 0.75f;
|
||||||
constexpr float kLowerPanelYOffsetInMeters = -0.75f;
|
constexpr float kLowerPanelYOffsetInMeters = -kDistanceBetweenPanelsInMeters;
|
||||||
constexpr float kLowerPanelZOffsetInMeters = -1.5f;
|
constexpr float kLowerPanelZOffsetInMeters = -1.5f;
|
||||||
// Pitch the lower panel away from the viewer 45 degrees
|
// Pitch the lower panel away from the viewer 45 degrees
|
||||||
constexpr float kLowerPanelPitchInRadians = -MATH_FLOAT_PI / 4.0f;
|
constexpr float kLowerPanelPitchInRadians = -MATH_FLOAT_PI / 4.0f;
|
||||||
|
@ -430,17 +430,21 @@ void GameSurfaceLayer::SetTopPanelFromController(const XrVector3f& controllerPos
|
||||||
CalculatePanelPosition(viewerPosition, controllerPosition, sphereRadius);
|
CalculatePanelPosition(viewerPosition, controllerPosition, sphereRadius);
|
||||||
const XrQuaternionf windowRotation =
|
const XrQuaternionf windowRotation =
|
||||||
CalculatePanelRotation(windowPosition, viewerPosition, windowUpDirection);
|
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; }
|
if (XrMath::Quatf::GetYawInRadians(windowRotation) > MATH_FLOAT_PI / 3.0f) { return; }
|
||||||
|
|
||||||
mTopPanel.mPanelFromWorld = XrPosef{windowRotation, windowPosition};
|
mTopPanel.mPanelFromWorld = XrPosef{windowRotation, windowPosition};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr float kThumbstickSpeed = 0.05f;
|
||||||
|
|
||||||
void GameSurfaceLayer::SetTopPanelFromThumbstick(const float thumbstickY) {
|
void GameSurfaceLayer::SetTopPanelFromThumbstick(const float thumbstickY) {
|
||||||
static constexpr float kDepthSpeed = 0.05f;
|
|
||||||
static constexpr float kMaxDepth = -10.0f;
|
static constexpr float kMaxDepth = -10.0f;
|
||||||
|
|
||||||
mTopPanel.mPanelFromWorld.position.z -= (thumbstickY * kDepthSpeed);
|
mTopPanel.mPanelFromWorld.position.z -= (thumbstickY * kThumbstickSpeed);
|
||||||
mTopPanel.mPanelFromWorld.position.z =
|
mTopPanel.mPanelFromWorld.position.z =
|
||||||
std::min(mTopPanel.mPanelFromWorld.position.z, mLowerPanel.mPanelFromWorld.position.z);
|
std::min(mTopPanel.mPanelFromWorld.position.z, mLowerPanel.mPanelFromWorld.position.z);
|
||||||
mTopPanel.mPanelFromWorld.position.z =
|
mTopPanel.mPanelFromWorld.position.z =
|
||||||
|
@ -448,14 +452,14 @@ void GameSurfaceLayer::SetTopPanelFromThumbstick(const float thumbstickY) {
|
||||||
}
|
}
|
||||||
|
|
||||||
XrPosef GameSurfaceLayer::SetLowerPanelFromThumbstick(const float thumbstickY) {
|
XrPosef GameSurfaceLayer::SetLowerPanelFromThumbstick(const float thumbstickY) {
|
||||||
static constexpr float kDepthSpeed = 0.05f;
|
static constexpr float kMinY = -3.0f;
|
||||||
static constexpr float kMaxDepth = -10.0f;
|
|
||||||
|
|
||||||
mLowerPanel.mPanelFromWorld.position.y += (thumbstickY * kDepthSpeed);
|
mLowerPanel.mPanelFromWorld.position.y += (thumbstickY * kThumbstickSpeed);
|
||||||
mLowerPanel.mPanelFromWorld.position.y =
|
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 =
|
mLowerPanel.mPanelFromWorld.position.y =
|
||||||
std::max(mLowerPanel.mPanelFromWorld.position.y, kMaxDepth);
|
std::max(mLowerPanel.mPanelFromWorld.position.y, kMinY);
|
||||||
|
|
||||||
return mLowerPanel.mPanelFromWorld;
|
return mLowerPanel.mPanelFromWorld;
|
||||||
}
|
}
|
||||||
|
|
|
@ -650,7 +650,10 @@ private:
|
||||||
XrPosef cursorPose3d = XrMath::Posef::Identity();
|
XrPosef cursorPose3d = XrMath::Posef::Identity();
|
||||||
XrVector2f cursorPos2d = {0, 0};
|
XrVector2f cursorPos2d = {0, 0};
|
||||||
float scaleFactor = 0.01f;
|
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 =
|
[[maybe_unused]] const auto nonPreferredController =
|
||||||
mInputStateFrame.mPreferredHand == InputStateFrame::LEFT_CONTROLLER
|
mInputStateFrame.mPreferredHand == InputStateFrame::LEFT_CONTROLLER
|
||||||
|
@ -660,10 +663,15 @@ private:
|
||||||
// unless neither controller is available.
|
// unless neither controller is available.
|
||||||
assert(mInputStateFrame.mIsHandActive[mInputStateFrame.mPreferredHand] ||
|
assert(mInputStateFrame.mIsHandActive[mInputStateFrame.mPreferredHand] ||
|
||||||
!mInputStateFrame.mIsHandActive[nonPreferredController]);
|
!mInputStateFrame.mIsHandActive[nonPreferredController]);
|
||||||
|
|
||||||
{
|
{
|
||||||
const bool isPreferredControllerActive =
|
const bool isPreferredControllerActive =
|
||||||
mInputStateFrame.mIsHandActive[mInputStateFrame.mPreferredHand];
|
mInputStateFrame.mIsHandActive[mInputStateFrame.mPreferredHand];
|
||||||
|
|
||||||
|
static bool sIsLowerPanelBeingPositioned = false;
|
||||||
|
|
||||||
|
sIsLowerPanelBeingPositioned &=
|
||||||
|
appState.mLowerMenuType == LowerMenuType::POSITIONAL_MENU &&
|
||||||
|
isPreferredControllerActive;
|
||||||
if (isPreferredControllerActive) {
|
if (isPreferredControllerActive) {
|
||||||
const XrPosef pose =
|
const XrPosef pose =
|
||||||
mInputStateFrame.mHandPositions[mInputStateFrame.mPreferredHand].pose;
|
mInputStateFrame.mHandPositions[mInputStateFrame.mPreferredHand].pose;
|
||||||
|
@ -677,6 +685,8 @@ private:
|
||||||
mInputStateFrame.mHandPositions[mInputStateFrame.mPreferredHand].pose,
|
mInputStateFrame.mHandPositions[mInputStateFrame.mPreferredHand].pose,
|
||||||
XrVector3f{0, 0, -3.5f});
|
XrVector3f{0, 0, -3.5f});
|
||||||
|
|
||||||
|
sIsLowerPanelBeingPositioned &= triggerState.currentState > 0;
|
||||||
|
|
||||||
// Hit-test panels in order of priority (and known depth)
|
// Hit-test panels in order of priority (and known depth)
|
||||||
|
|
||||||
if (appState.mShouldShowErrorMessage) {
|
if (appState.mShouldShowErrorMessage) {
|
||||||
|
@ -696,6 +706,7 @@ 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
|
||||||
|
|
||||||
if (!shouldRenderCursor && appState.ShouldShowLowerPanel()) {
|
if (!shouldRenderCursor && appState.ShouldShowLowerPanel()) {
|
||||||
shouldRenderCursor = mGameSurfaceLayer->GetRayIntersectionWithPanel(
|
shouldRenderCursor = mGameSurfaceLayer->GetRayIntersectionWithPanel(
|
||||||
start, end, cursorPos2d, cursorPose3d);
|
start, end, cursorPos2d, cursorPose3d);
|
||||||
|
@ -713,13 +724,14 @@ private:
|
||||||
cursorPos2d.x, cursorPos2d.y, 2);
|
cursorPos2d.x, cursorPos2d.y, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shouldRenderCursor) {
|
if (!shouldRenderCursor) {
|
||||||
shouldRenderCursor = mRibbonLayer->GetRayIntersectionWithPanel(
|
shouldRenderCursor = mRibbonLayer->GetRayIntersectionWithPanel(
|
||||||
start, end, cursorPos2d, cursorPose3d);
|
start, end, cursorPos2d, cursorPose3d);
|
||||||
if (shouldRenderCursor && triggerState.changedSinceLastSync) {
|
if (shouldRenderCursor && triggerState.changedSinceLastSync) {
|
||||||
mRibbonLayer->SendClickToUI(cursorPos2d, triggerState.currentState);
|
mRibbonLayer->SendClickToUI(cursorPos2d, triggerState.currentState);
|
||||||
}
|
}
|
||||||
if (shouldRenderCursor &&
|
if ((shouldRenderCursor || sIsLowerPanelBeingPositioned) &&
|
||||||
appState.mLowerMenuType == LowerMenuType::POSITIONAL_MENU &&
|
appState.mLowerMenuType == LowerMenuType::POSITIONAL_MENU &&
|
||||||
triggerState.currentState) {
|
triggerState.currentState) {
|
||||||
|
|
||||||
|
@ -730,28 +742,15 @@ private:
|
||||||
mInputStateFrame.mThumbStickState[mInputStateFrame.mPreferredHand];
|
mInputStateFrame.mThumbStickState[mInputStateFrame.mPreferredHand];
|
||||||
if (std::abs(thumbstickState.currentState.y) >
|
if (std::abs(thumbstickState.currentState.y) >
|
||||||
kThumbStickDirectionThreshold) {
|
kThumbStickDirectionThreshold) {
|
||||||
const XrPosef lowerPanelPose = mGameSurfaceLayer->SetLowerPanelFromThumbstick(
|
const XrPosef lowerPanelPose =
|
||||||
|
mGameSurfaceLayer->SetLowerPanelFromThumbstick(
|
||||||
thumbstickState.currentState.y);
|
thumbstickState.currentState.y);
|
||||||
mRibbonLayer->SetPanelWithPose(lowerPanelPose);
|
mRibbonLayer->SetPanelWithPose(lowerPanelPose);
|
||||||
|
sIsLowerPanelBeingPositioned = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (sIsLowerPanelBeingPositioned) { shouldRenderCursor = 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");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hit test the top panel if positional menu is active.
|
// Hit test the top panel if positional menu is active.
|
||||||
if (!shouldRenderCursor &&
|
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
|
// Add a scale factor so the cursor doesn't scale as
|
||||||
// quickly as the panel(s) with distance. This may be
|
// quickly as the panel(s) with distance. This may be
|
||||||
// mildly unsettling, but it helps to ensure the cursor
|
// mildly unsettling, but it helps to ensure the cursor
|
||||||
|
|
Loading…
Reference in a new issue