Add optional toggle of the Y offset to MoveCenterTabController. Allows short players and wheelchair users to fully interact with height-limited applications by both boosting their height and being able to touch the in-game floor when necessary.

This commit is contained in:
Mel Klimushyn
2017-01-28 10:39:24 -08:00
parent 6c7240fcf6
commit 39f81f39ab
3 changed files with 528 additions and 13 deletions
@@ -14,6 +14,8 @@ void MoveCenterTabController::initStage1() {
if (value.isValid() && !value.isNull()) {
m_adjustChaperone = value.toBool();
}
reloadPttConfig();
}
void MoveCenterTabController::initStage2(OverlayController * parent, QQuickWindow * widget) {
@@ -135,6 +137,72 @@ void MoveCenterTabController::setAdjustChaperone(bool value, bool notify) {
}
}
bool MoveCenterTabController::pttEnabled() const {
return m_pttEnabled;
}
void MoveCenterTabController::setPttEnabled(bool value, bool notify, bool save) {
std::lock_guard<std::recursive_mutex> lock(eventLoopMutex);
if (value != m_pttEnabled) {
m_pttEnabled = value;
if (notify) {
emit pttEnabledChanged(value);
}
if (save) {
savePttConfig();
}
}
}
void MoveCenterTabController::offsetYToggle(bool enabled) {
float delta;
if (enabled) {
m_toggleOffsetY = m_offsetY;
delta = -m_toggleOffsetY;
} else {
delta = m_toggleOffsetY;
}
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 1, delta, m_adjustChaperone);
}
bool MoveCenterTabController::pttActive() const {
return m_pttActive;
}
bool MoveCenterTabController::pttLeftControllerEnabled() const {
return m_pttLeftControllerEnabled;
}
void MoveCenterTabController::setPttLeftControllerEnabled(bool value, bool notify, bool save) {
std::lock_guard<std::recursive_mutex> lock(eventLoopMutex);
if (value != m_pttLeftControllerEnabled) {
m_pttLeftControllerEnabled = value;
if (notify) {
emit pttLeftControllerEnabledChanged(value);
}
if (save) {
savePttConfig();
}
}
}
bool MoveCenterTabController::pttRightControllerEnabled() const {
return m_pttRightControllerEnabled;
}
void MoveCenterTabController::setPttRightControllerEnabled(bool value, bool notify, bool save) {
std::lock_guard<std::recursive_mutex> lock(eventLoopMutex);
if (value != m_pttRightControllerEnabled) {
m_pttRightControllerEnabled = value;
if (notify) {
emit pttRightControllerEnabledChanged(value);
}
if (save) {
savePttConfig();
}
}
}
void MoveCenterTabController::modOffsetX(float value, bool notify) {
if (m_rotation == 0) {
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 0, value, m_adjustChaperone);
@@ -184,6 +252,7 @@ void MoveCenterTabController::reset() {
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
m_offsetX = 0.0f;
m_offsetY = 0.0f;
m_toggleOffsetY = 0.0f;
m_offsetZ = 0.0f;
m_rotation = 0;
emit offsetXChanged(m_offsetX);
@@ -193,12 +262,179 @@ void MoveCenterTabController::reset() {
}
void MoveCenterTabController::eventLoopTick(vr::ETrackingUniverseOrigin universe) {
if (!eventLoopMutex.try_lock()) {
return;
}
if (settingsUpdateCounter >= 50) {
setTrackingUniverse((int)universe);
settingsUpdateCounter = 0;
} else {
settingsUpdateCounter++;
}
static auto handleControllerState = [](const vr::VRControllerState_t& state, PttControllerConfig* config) -> bool {
if (state.ulButtonPressed & config->digitalButtonMask) {
return true;
}
if (config->triggerMode) {
if (state.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_SteamVR_Trigger)
|| state.ulButtonTouched & vr::ButtonMaskFromId(vr::k_EButton_SteamVR_Trigger)) {
return true;
}
}
if (config->touchpadMode) {
if (((config->touchpadMode & 1) && (state.ulButtonTouched & vr::ButtonMaskFromId(vr::k_EButton_SteamVR_Touchpad)))
|| ((config->touchpadMode & 2) && (state.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_SteamVR_Touchpad)))) {
if (config->touchpadAreas == (PAD_AREA_LEFT + PAD_AREA_TOP + PAD_AREA_RIGHT + PAD_AREA_BOTTOM)) {
return true;
} else {
float x = state.rAxis[0].x;
float y = state.rAxis[0].y;
if (std::abs(x) >= 0.2 || std::abs(y) >= 0.2) { // deadzone in the middle
if (x < 0 && std::abs(y) < -x && (config->touchpadAreas & PAD_AREA_LEFT)) {
return true;
} else if (y > 0 && std::abs(x) < y && (config->touchpadAreas & PAD_AREA_TOP)) {
return true;
} else if (x > 0 && std::abs(y) < x && (config->touchpadAreas & PAD_AREA_RIGHT)) {
return true;
} else if (y < 0 && std::abs(x) < -y && (config->touchpadAreas & PAD_AREA_BOTTOM)) {
return true;
}
}
}
}
}
return false;
};
if (m_pttEnabled) {
bool newState = false;
if (m_pttLeftControllerEnabled) {
auto leftId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_LeftHand);
if (leftId != vr::k_unTrackedDeviceIndexInvalid) {
vr::VRControllerState_t state;
if (vr::VRSystem()->GetControllerState(leftId, &state, sizeof(vr::VRControllerState_t))) {
newState |= handleControllerState(state, m_pttControllerConfigs);
}
}
}
if (m_pttRightControllerEnabled) {
auto rightId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_RightHand);
if (rightId != vr::k_unTrackedDeviceIndexInvalid) {
vr::VRControllerState_t state;
if (vr::VRSystem()->GetControllerState(rightId, &state, sizeof(vr::VRControllerState_t))) {
newState |= handleControllerState(state, m_pttControllerConfigs + 1);
}
}
}
if (newState && !m_pttActive) {
m_pttActive = true;
offsetYToggle(true);
emit pttActiveChanged(m_pttActive);
} else if (!newState && m_pttActive) {
m_pttActive = false;
offsetYToggle(false);
emit pttActiveChanged(m_pttActive);
}
}
eventLoopMutex.unlock();
}
void MoveCenterTabController::setPttControllerConfig(unsigned controller, QVariantList buttons, unsigned triggerMode, unsigned padMode, unsigned padAreas) {
std::lock_guard<std::recursive_mutex> lock(eventLoopMutex);
if (controller < 2) {
uint64_t buttonMask = 0;
for (auto b : buttons) {
buttonMask |= vr::ButtonMaskFromId((vr::EVRButtonId)b.toInt());
}
m_pttControllerConfigs[controller].digitalButtons = buttons;
m_pttControllerConfigs[controller].digitalButtonMask = buttonMask;
m_pttControllerConfigs[controller].triggerMode = triggerMode;
m_pttControllerConfigs[controller].touchpadMode = padMode;
m_pttControllerConfigs[controller].touchpadAreas = padAreas;
savePttConfig();
}
}
void MoveCenterTabController::reloadPttConfig() {
std::lock_guard<std::recursive_mutex> lock(eventLoopMutex);
auto settings = OverlayController::appSettings();
settings->beginGroup("playspaceSettings");
setPttEnabled(settings->value("pttEnabled", false).toBool(), true, false);
setPttLeftControllerEnabled(settings->value("pttLeftControllerEnabled", false).toBool(), true, false);
setPttRightControllerEnabled(settings->value("pttRightControllerEnabled", false).toBool(), true, false);
m_pttControllerConfigs[0].digitalButtons = settings->value("pttDigitalButtons_0").toList();
uint64_t buttonMask = 0;
for (auto b : m_pttControllerConfigs[0].digitalButtons) {
buttonMask |= vr::ButtonMaskFromId((vr::EVRButtonId)b.toInt());
}
m_pttControllerConfigs[0].digitalButtonMask = buttonMask;
m_pttControllerConfigs[0].triggerMode = settings->value("pttTriggerMode_0", 0).toUInt();
m_pttControllerConfigs[0].touchpadMode = settings->value("pttTouchpadMode_0", 0).toUInt();
m_pttControllerConfigs[0].touchpadAreas = settings->value("pttTouchPadAreas_0", 0).toUInt();
m_pttControllerConfigs[1].digitalButtons = settings->value("pttDigitalButtons_1").toList();
buttonMask = 0;
for (auto b : m_pttControllerConfigs[0].digitalButtons) {
buttonMask |= vr::ButtonMaskFromId((vr::EVRButtonId)b.toInt());
}
m_pttControllerConfigs[1].digitalButtonMask = buttonMask;
m_pttControllerConfigs[1].triggerMode = settings->value("pttTriggerMode_1", 0).toUInt();
m_pttControllerConfigs[1].touchpadMode = settings->value("pttTouchpadMode_1", 0).toUInt();
m_pttControllerConfigs[1].touchpadAreas = settings->value("pttTouchPadAreas_1", 0).toUInt();
settings->endGroup();
}
void MoveCenterTabController::savePttConfig() {
auto settings = OverlayController::appSettings();
settings->beginGroup("playspaceSettings");
settings->setValue("pttEnabled", pttEnabled());
settings->setValue("pttLeftControllerEnabled", pttLeftControllerEnabled());
settings->setValue("pttRightControllerEnabled", pttRightControllerEnabled());
settings->setValue("pttDigitalButtons_0", m_pttControllerConfigs[0].digitalButtons);
settings->setValue("pttTriggerMode_0", m_pttControllerConfigs[0].triggerMode);
settings->setValue("pttTouchpadMode_0", m_pttControllerConfigs[0].touchpadMode);
settings->setValue("pttTouchPadAreas_0", m_pttControllerConfigs[0].touchpadAreas);
settings->setValue("pttDigitalButtons_1", m_pttControllerConfigs[1].digitalButtons);
settings->setValue("pttTriggerMode_1", m_pttControllerConfigs[1].triggerMode);
settings->setValue("pttTouchpadMode_1", m_pttControllerConfigs[1].touchpadMode);
settings->setValue("pttTouchPadAreas_1", m_pttControllerConfigs[1].touchpadAreas);
settings->endGroup();
}
QVariantList MoveCenterTabController::pttDigitalButtons(unsigned controller) {
if (controller < 2) {
return m_pttControllerConfigs[controller].digitalButtons;
}
return QVariantList();
}
unsigned long MoveCenterTabController::pttDigitalButtonMask(unsigned controller) {
if (controller < 2) {
return m_pttControllerConfigs[controller].digitalButtonMask;
}
return 0;
}
unsigned MoveCenterTabController::pttTouchpadMode(unsigned controller) {
if (controller < 2) {
return m_pttControllerConfigs[controller].touchpadMode;
}
return 0;
}
unsigned MoveCenterTabController::pttTriggerMode(unsigned controller) {
if (controller < 2) {
return m_pttControllerConfigs[controller].triggerMode;
}
return 0;
}
unsigned MoveCenterTabController::pttTouchpadArea(unsigned controller) {
if (controller < 2) {
return m_pttControllerConfigs[controller].touchpadAreas;
}
return 0;
}
} // namespace advconfig
@@ -1,8 +1,11 @@
#pragma once
#include "AudioTabController.h"
#include <QObject>
#include <QVariant>
#include <openvr.h>
#include <mutex>
class QQuickWindow;
// application namespace
@@ -20,20 +23,36 @@ class MoveCenterTabController : public QObject {
Q_PROPERTY(float offsetZ READ offsetZ WRITE setOffsetZ NOTIFY offsetZChanged)
Q_PROPERTY(int rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
Q_PROPERTY(bool adjustChaperone READ adjustChaperone WRITE setAdjustChaperone NOTIFY adjustChaperoneChanged)
Q_PROPERTY(bool pttEnabled READ pttEnabled WRITE setPttEnabled NOTIFY pttEnabledChanged)
Q_PROPERTY(bool pttActive READ pttActive NOTIFY pttActiveChanged)
Q_PROPERTY(bool pttLeftControllerEnabled READ pttLeftControllerEnabled WRITE setPttLeftControllerEnabled NOTIFY pttLeftControllerEnabledChanged)
Q_PROPERTY(bool pttRightControllerEnabled READ pttRightControllerEnabled WRITE setPttRightControllerEnabled NOTIFY pttRightControllerEnabledChanged)
private:
void offsetYToggle(bool enabled);
OverlayController* parent;
QQuickWindow* widget;
int m_trackingUniverse = (int)vr::TrackingUniverseStanding;
float m_offsetX = 0.0f;
float m_offsetY = 0.0f;
float m_toggleOffsetY = 0.0f;
float m_offsetZ = 0.0f;
int m_rotation = 0;
bool m_adjustChaperone = true;
bool m_pttEnabled = false;
bool m_pttActive = false;
bool m_pttShowNotification = false;
bool m_pttLeftControllerEnabled = false;
bool m_pttRightControllerEnabled = false;
PttControllerConfig m_pttControllerConfigs[2];
unsigned settingsUpdateCounter = 0;
std::recursive_mutex eventLoopMutex;
public:
void initStage1();
void initStage2(OverlayController* parent, QQuickWindow* widget);
@@ -46,6 +65,19 @@ public:
int rotation() const;
bool adjustChaperone() const;
bool pttEnabled() const;
bool pttActive() const;
bool pttLeftControllerEnabled() const;
bool pttRightControllerEnabled() const;
void reloadPttConfig();
void savePttConfig();
Q_INVOKABLE QVariantList pttDigitalButtons(unsigned controller);
Q_INVOKABLE unsigned long pttDigitalButtonMask(unsigned controller);
Q_INVOKABLE unsigned pttTouchpadMode(unsigned controller);
Q_INVOKABLE unsigned pttTriggerMode(unsigned controller);
Q_INVOKABLE unsigned pttTouchpadArea(unsigned controller);
public slots:
int trackingUniverse() const;
void setTrackingUniverse(int value, bool notify = true);
@@ -63,6 +95,12 @@ public slots:
void modOffsetZ(float value, bool notify = true);
void reset();
void setPttEnabled(bool value, bool notify = true, bool save = true);
void setPttLeftControllerEnabled(bool value, bool notify = true, bool save = true);
void setPttRightControllerEnabled(bool value, bool notify = true, bool save = true);
void setPttControllerConfig(unsigned controller, QVariantList buttons, unsigned triggerMode, unsigned padMode, unsigned padAreas);
signals:
void trackingUniverseChanged(int value);
void offsetXChanged(float value);
@@ -70,6 +108,11 @@ signals:
void offsetZChanged(float value);
void rotationChanged(int value);
void adjustChaperoneChanged(bool value);
void pttEnabledChanged(bool value);
void pttActiveChanged(bool value);
void pttLeftControllerEnabledChanged(bool value);
void pttRightControllerEnabledChanged(bool value);
};
} // namespace advsettings