Support keyboard suppresion, control suppresion while in keyboard mode

This commit is contained in:
Bradley Austin Davis 2016-06-14 18:25:01 -07:00
parent 71bf9384ce
commit 0b0977f362
9 changed files with 206 additions and 57 deletions

View file

@ -4,15 +4,24 @@
{ "from": "Vive.LY", "when": "Vive.LSY", "filters": ["invert"], "to": "Standard.LY" }, { "from": "Vive.LY", "when": "Vive.LSY", "filters": ["invert"], "to": "Standard.LY" },
{ "from": "Vive.LX", "when": "Vive.LSX", "to": "Standard.LX" }, { "from": "Vive.LX", "when": "Vive.LSX", "to": "Standard.LX" },
{ "from": "Vive.LT", "to": "Standard.LT" }, {
"from": "Vive.LT", "to": "Standard.LT",
"filters": [
{ "type": "deadZone", "min": 0.05 },
]
},
{ "from": "Vive.LeftGrip", "to": "Standard.LeftGrip" }, { "from": "Vive.LeftGrip", "to": "Standard.LeftGrip" },
{ "from": "Vive.LS", "to": "Standard.LS" }, { "from": "Vive.LS", "to": "Standard.LS" },
{ "from": "Vive.LSTouch", "to": "Standard.LSTouch" }, { "from": "Vive.LSTouch", "to": "Standard.LSTouch" },
{ "from": "Vive.RY", "when": "Vive.RSY", "filters": ["invert"], "to": "Standard.RY" }, { "from": "Vive.RY", "when": "Vive.RSY", "filters": ["invert"], "to": "Standard.RY" },
{ "from": "Vive.RX", "when": "Vive.RSX", "to": "Standard.RX" }, { "from": "Vive.RX", "when": "Vive.RSX", "to": "Standard.RX" },
{
{ "from": "Vive.RT", "to": "Standard.RT" }, "from": "Vive.RT", "to": "Standard.RT",
"filters": [
{ "type": "deadZone", "min": 0.05 },
]
},
{ "from": "Vive.RightGrip", "to": "Standard.RightGrip" }, { "from": "Vive.RightGrip", "to": "Standard.RightGrip" },
{ "from": "Vive.RS", "to": "Standard.RS" }, { "from": "Vive.RS", "to": "Standard.RS" },
{ "from": "Vive.RSTouch", "to": "Standard.RSTouch" }, { "from": "Vive.RSTouch", "to": "Standard.RSTouch" },

View file

@ -115,3 +115,15 @@ bool HMDScriptingInterface::setHandLasers(int hands, bool enabled, const glm::ve
void HMDScriptingInterface::disableHandLasers(int hands) const { void HMDScriptingInterface::disableHandLasers(int hands) const {
qApp->getActiveDisplayPlugin()->setHandLaser(hands, DisplayPlugin::HandLaserMode::None); qApp->getActiveDisplayPlugin()->setHandLaser(hands, DisplayPlugin::HandLaserMode::None);
} }
bool HMDScriptingInterface::suppressKeyboard() {
return qApp->getActiveDisplayPlugin()->suppressKeyboard();
}
void HMDScriptingInterface::unsuppressKeyboard() {
qApp->getActiveDisplayPlugin()->unsuppressKeyboard();
}
bool HMDScriptingInterface::isKeyboardVisible() {
return qApp->getActiveDisplayPlugin()->isKeyboardVisible();
}

View file

@ -1,4 +1,4 @@
//
// HMDScriptingInterface.h // HMDScriptingInterface.h
// interface/src/scripting // interface/src/scripting
// //
@ -12,6 +12,8 @@
#ifndef hifi_HMDScriptingInterface_h #ifndef hifi_HMDScriptingInterface_h
#define hifi_HMDScriptingInterface_h #define hifi_HMDScriptingInterface_h
#include <atomic>
#include <QtScript/QScriptValue> #include <QtScript/QScriptValue>
class QScriptContext; class QScriptContext;
class QScriptEngine; class QScriptEngine;
@ -38,6 +40,19 @@ public:
Q_INVOKABLE QString preferredAudioOutput() const; Q_INVOKABLE QString preferredAudioOutput() const;
Q_INVOKABLE bool setHandLasers(int hands, bool enabled, const glm::vec4& color, const glm::vec3& direction) const; Q_INVOKABLE bool setHandLasers(int hands, bool enabled, const glm::vec4& color, const glm::vec3& direction) const;
Q_INVOKABLE void disableHandLasers(int hands) const; Q_INVOKABLE void disableHandLasers(int hands) const;
/// Suppress the activation of any on-screen keyboard so that a script operation will
/// not be interrupted by a keyboard popup
/// Returns false if there is already an active keyboard displayed.
/// Clients should re-enable the keyboard when the operation is complete and ensure
/// that they balance any call to suppressKeyboard() that returns true with a corresponding
/// call to unsuppressKeyboard() within a reasonable amount of time
Q_INVOKABLE bool suppressKeyboard();
/// Enable the keyboard following a suppressKeyboard call
Q_INVOKABLE void unsuppressKeyboard();
/// Query the display plugin to determine the current VR keyboard visibility
Q_INVOKABLE bool isKeyboardVisible();
public: public:
HMDScriptingInterface(); HMDScriptingInterface();

View file

@ -16,16 +16,18 @@
#include <QtCore/QSize> #include <QtCore/QSize>
#include <QtCore/QPoint> #include <QtCore/QPoint>
#include <QtCore/QElapsedTimer> #include <QtCore/QElapsedTimer>
class QImage;
#include <GLMHelpers.h> #include <GLMHelpers.h>
#include <RegisteredMetaTypes.h> #include <RegisteredMetaTypes.h>
#include <shared/Bilateral.h>
#include "Plugin.h" #include "Plugin.h"
class QImage;
enum Eye { enum Eye {
Left, Left = bilateral::Side::Left,
Right Right = bilateral::Side::Right
}; };
/* /*
@ -56,7 +58,73 @@ namespace gpu {
using TexturePointer = std::shared_ptr<Texture>; using TexturePointer = std::shared_ptr<Texture>;
} }
class DisplayPlugin : public Plugin { // Stereo display functionality
// TODO move out of this file don't derive DisplayPlugin from this. Instead use dynamic casting when
// displayPlugin->isStereo returns true
class StereoDisplay {
public:
// Stereo specific methods
virtual glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const {
return baseProjection;
}
virtual glm::mat4 getCullingProjection(const glm::mat4& baseProjection) const {
return baseProjection;
}
virtual float getIPD() const { return AVERAGE_HUMAN_IPD; }
};
// HMD display functionality
// TODO move out of this file don't derive DisplayPlugin from this. Instead use dynamic casting when
// displayPlugin->isHmd returns true
class HmdDisplay : public StereoDisplay {
public:
// HMD specific methods
// TODO move these into another class?
virtual glm::mat4 getEyeToHeadTransform(Eye eye) const {
static const glm::mat4 transform; return transform;
}
// returns a copy of the most recent head pose, computed via updateHeadPose
virtual glm::mat4 getHeadPose() const {
return glm::mat4();
}
// Needed for timewarp style features
virtual void setEyeRenderPose(uint32_t frameIndex, Eye eye, const glm::mat4& pose) {
// NOOP
}
virtual void abandonCalibration() {}
virtual void resetSensors() {}
enum Hand {
LeftHand = 0x01,
RightHand = 0x02,
};
enum class HandLaserMode {
None, // Render no hand lasers
Overlay, // Render hand lasers only if they intersect with the UI layer, and stop at the UI layer
};
virtual bool setHandLaser(
uint32_t hands, // Bits from the Hand enum
HandLaserMode mode, // Mode in which to render
const vec4& color = vec4(1), // The color of the rendered laser
const vec3& direction = vec3(0, 0, -1) // The direction in which to render the hand lasers
) {
return false;
}
virtual bool suppressKeyboard() { return false; }
virtual void unsuppressKeyboard() {};
virtual bool isKeyboardVisible() { return false; }
};
class DisplayPlugin : public Plugin, public HmdDisplay {
Q_OBJECT Q_OBJECT
using Parent = Plugin; using Parent = Plugin;
public: public:
@ -117,42 +185,12 @@ public:
return QRect(0, 0, recommendedSize.x, recommendedSize.y); return QRect(0, 0, recommendedSize.x, recommendedSize.y);
} }
// Stereo specific methods
virtual glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const {
return baseProjection;
}
virtual glm::mat4 getCullingProjection(const glm::mat4& baseProjection) const {
return baseProjection;
}
// Fetch the most recently displayed image as a QImage // Fetch the most recently displayed image as a QImage
virtual QImage getScreenshot() const = 0; virtual QImage getScreenshot() const = 0;
// HMD specific methods
// TODO move these into another class?
virtual glm::mat4 getEyeToHeadTransform(Eye eye) const {
static const glm::mat4 transform; return transform;
}
// will query the underlying hmd api to compute the most recent head pose // will query the underlying hmd api to compute the most recent head pose
virtual bool beginFrameRender(uint32_t frameIndex) { return true; } virtual bool beginFrameRender(uint32_t frameIndex) { return true; }
// returns a copy of the most recent head pose, computed via updateHeadPose
virtual glm::mat4 getHeadPose() const {
return glm::mat4();
}
// Needed for timewarp style features
virtual void setEyeRenderPose(uint32_t frameIndex, Eye eye, const glm::mat4& pose) {
// NOOP
}
virtual float getIPD() const { return AVERAGE_HUMAN_IPD; }
virtual void abandonCalibration() {}
virtual void resetSensors() {}
virtual float devicePixelRatio() { return 1.0f; } virtual float devicePixelRatio() { return 1.0f; }
// Rate at which we present to the display device // Rate at which we present to the display device
virtual float presentRate() const { return -1.0f; } virtual float presentRate() const { return -1.0f; }
@ -160,6 +198,7 @@ public:
virtual float newFramePresentRate() const { return -1.0f; } virtual float newFramePresentRate() const { return -1.0f; }
// Rate at which rendered frames are being skipped // Rate at which rendered frames are being skipped
virtual float droppedFrameRate() const { return -1.0f; } virtual float droppedFrameRate() const { return -1.0f; }
uint32_t presentCount() const { return _presentedFrameIndex; } uint32_t presentCount() const { return _presentedFrameIndex; }
// Time since last call to incrementPresentCount (only valid if DEBUG_PAINT_DELAY is defined) // Time since last call to incrementPresentCount (only valid if DEBUG_PAINT_DELAY is defined)
int64_t getPaintDelayUsecs() const; int64_t getPaintDelayUsecs() const;
@ -168,25 +207,6 @@ public:
static const QString& MENU_PATH(); static const QString& MENU_PATH();
enum Hand {
LeftHand = 0x01,
RightHand = 0x02,
};
enum class HandLaserMode {
None, // Render no hand lasers
Overlay, // Render hand lasers only if they intersect with the UI layer, and stop at the UI layer
};
virtual bool setHandLaser(
uint32_t hands, // Bits from the Hand enum
HandLaserMode mode, // Mode in which to render
const vec4& color = vec4(1), // The color of the rendered laser
const vec3& direction = vec3(0, 0, -1) // The direction in which to render the hand lasers
) {
return false;
}
signals: signals:
void recommendedFramebufferSizeChanged(const QSize & size); void recommendedFramebufferSizeChanged(const QSize & size);

View file

@ -0,0 +1,49 @@
//
// Created by Bradley Austin Davis 2015/10/09
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#pragma once
namespace bilateral {
enum class Side {
Left = 0,
Right = 1
};
using Indices = Side;
enum class Bits {
Left = 0x01,
Right = 0x02
};
inline uint8_t bit(Side side) {
switch (side) {
case Side::Left:
return 0x01;
case Side::Right:
return 0x02;
}
return UINT8_MAX;
}
inline uint8_t index(Side side) {
switch (side) {
case Side::Left:
return 0;
case Side::Right:
return 1;
}
return UINT8_MAX;
}
template <typename F>
void for_each_side(F f) {
f(Side::Left);
f(Side::Right);
}
}

View file

@ -14,6 +14,7 @@
#include <QtCore/QLoggingCategory> #include <QtCore/QLoggingCategory>
#include <QtCore/QFile> #include <QtCore/QFile>
#include <QtCore/QDir> #include <QtCore/QDir>
#include <QtCore/QProcessEnvironment>
#include <controllers/Input.h> #include <controllers/Input.h>
#include <controllers/Pose.h> #include <controllers/Pose.h>
@ -53,6 +54,13 @@ bool oculusAvailable() {
static std::once_flag once; static std::once_flag once;
static bool result { false }; static bool result { false };
std::call_once(once, [&] { std::call_once(once, [&] {
static const QString DEBUG_FLAG("HIFI_DEBUG_OPENVR");
static bool enableDebugOpenVR = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
if (enableDebugOpenVR) {
return;
}
ovrDetectResult detect = ovr_Detect(0); ovrDetectResult detect = ovr_Detect(0);
if (!detect.IsOculusServiceRunning || !detect.IsOculusHMDConnected) { if (!detect.IsOculusServiceRunning || !detect.IsOculusHMDConnected) {
return; return;

View file

@ -253,3 +253,27 @@ void OpenVrDisplayPlugin::updatePresentPose() {
mat3 presentRotation(_currentPresentFrameInfo.rawPresentPose); mat3 presentRotation(_currentPresentFrameInfo.rawPresentPose);
_currentPresentFrameInfo.presentReprojection = glm::mat3(glm::inverse(renderRotation) * presentRotation); _currentPresentFrameInfo.presentReprojection = glm::mat3(glm::inverse(renderRotation) * presentRotation);
} }
bool OpenVrDisplayPlugin::suppressKeyboard() {
if (isOpenVrKeyboardShown()) {
return false;
}
if (!_keyboardSupressionCount.fetch_add(1)) {
disableOpenVrKeyboard();
}
return true;
}
void OpenVrDisplayPlugin::unsuppressKeyboard() {
if (_keyboardSupressionCount == 0) {
qWarning() << "Attempted to unsuppress a keyboard that was not suppressed";
return;
}
if (1 == _keyboardSupressionCount.fetch_sub(1)) {
enableOpenVrKeyboard();
}
}
bool OpenVrDisplayPlugin::isKeyboardVisible() {
return isOpenVrKeyboardShown();
}

View file

@ -30,6 +30,10 @@ public:
bool beginFrameRender(uint32_t frameIndex) override; bool beginFrameRender(uint32_t frameIndex) override;
void cycleDebugOutput() override { _lockCurrentTexture = !_lockCurrentTexture; } void cycleDebugOutput() override { _lockCurrentTexture = !_lockCurrentTexture; }
bool suppressKeyboard() override;
void unsuppressKeyboard() override;
bool isKeyboardVisible() override;
protected: protected:
bool internalActivate() override; bool internalActivate() override;
void internalDeactivate() override; void internalDeactivate() override;
@ -39,8 +43,10 @@ protected:
bool isHmdMounted() const override; bool isHmdMounted() const override;
void postPreview() override; void postPreview() override;
private: private:
vr::IVRSystem* _system { nullptr }; vr::IVRSystem* _system { nullptr };
std::atomic<vr::EDeviceActivityLevel> _hmdActivityLevel { vr::k_EDeviceActivityLevel_Unknown }; std::atomic<vr::EDeviceActivityLevel> _hmdActivityLevel { vr::k_EDeviceActivityLevel_Unknown };
std::atomic<uint32_t> _keyboardSupressionCount{ 0 };
static const QString NAME; static const QString NAME;
}; };

View file

@ -240,6 +240,12 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle
_poseStateMap.clear(); _poseStateMap.clear();
_buttonPressedMap.clear(); _buttonPressedMap.clear();
// While the keyboard is open, we defer strictly to the keyboard values
if (isOpenVrKeyboardShown()) {
_axisStateMap.clear();
return;
}
PerformanceTimer perfTimer("ViveControllerManager::update"); PerformanceTimer perfTimer("ViveControllerManager::update");
auto leftHandDeviceIndex = _system->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_LeftHand); auto leftHandDeviceIndex = _system->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_LeftHand);