Updated Readme and added files missing from last commit.
This commit is contained in:
@@ -6,25 +6,49 @@
|
||||
Adds an overlay to the OpenVR dashboard that allows access to advanced settings.
|
||||
|
||||
# Features
|
||||
## - SteamVR Settings Tab:
|
||||
|
||||
- **Supersampling**: Allows to change SteamVR's supersampling setting (Requires restart).
|
||||
- **Allow Reprojection**: Enable/disable reprojection (Requires restart).
|
||||
- **Force Reprojection**: Enable/disable forced reprojection (Requires restart).
|
||||
- **Restart SteamVR**: Restart SteamVR.
|
||||
|
||||
## - Chaperone Settings Tab:
|
||||
|
||||
- **Center Marker**: Displays a marker that represents the center of the playspace.
|
||||
- **Play Space Maker**: Displays the outlines of the rectangle representing the playspace.
|
||||
- **Force Bounds**: Force chaperone bounds always on.
|
||||
- **Flip Orientation**: Flips the orientation of the play space.
|
||||
- **Fade Distance**: Allows to configure the distance at which the chaperone bounds are shown. When set to 0 chaperone bounds are completely invisible.
|
||||
- **Chaperone Bounds Visibility**: Allows to configure the visibility of the chaperone bounds. Unlike the slider in the chaperone settings, this one is not capped at 30%. When set to 0 chaperone bounds are completely invisible.
|
||||
- **Reload from Disk**: Reloads the chaperone bounds from disk.
|
||||
|
||||
## - Move Center Tab:
|
||||
Allows to temporarily move the center of the playspace. This allows to reach interaction elements that are just inside our real-world walls or otherwise inaccessible (e.g. when your playspace is smaller than the recommended one). Can also be used to discover the terrors that lie outside of the intended playspace (ever wondered what's behind the door in The Lab?).
|
||||
|
||||
Allows to temporarily move and rotate the center of the playspace. This allows to reach interaction elements that are just inside our real-world walls or otherwise inaccessible (e.g. when your playspace is smaller than the recommended one). Can also be used to discover the terrors that lie outside of the intended playspace (ever wondered what's behind the door in The Lab?).
|
||||
|
||||
The chaperone bounds stay in place when the playspace is moved or rotated (I don't want anyone to get hurt. Unfortunately this does not work when moving up/down).
|
||||
|
||||
## - Fix Floor Tab:
|
||||
|
||||
Allows you to fix the height of your floor. Just place one controller on your floor and press the button.
|
||||
|
||||
## - Statistics Tab:
|
||||
|
||||
- **HMD Distance Moved**: Shows the distance the headset has moved on the xz-plane.
|
||||
- **HMD Rotations**: Shows the number of rotations around the y-axis (Useful for untangling the cord).
|
||||
- **Left Controller Max Speed**: Shows the max speed of the left controller.
|
||||
- **Right Controller Max Speed**: Shows the max speed of the right controller.
|
||||
- **Dropped Frames**: Number of frames dropped in the currently running application.
|
||||
- **Reprojected Frames**: Number of frames reprojected in the currently running application.
|
||||
- **Reprojected Frames**: Number of times the currently running application timed out.
|
||||
|
||||
## - Settings Tab:
|
||||
|
||||
- **Auto Start Toggle:** Allows you to enable/disable auto start.
|
||||
|
||||
# Notes:
|
||||
|
||||
- The center marker and the play space marker are provided by the chaperone subsystem, and therefore they will have the same color and visibility settings as the chaperone bounds.
|
||||
|
||||
# Usage
|
||||
|
||||
+15
-3
@@ -14,11 +14,23 @@ TEMPLATE = app
|
||||
|
||||
SOURCES += src/main.cpp\
|
||||
src/overlaywidget.cpp \
|
||||
src/overlaycontroller.cpp
|
||||
src/overlaycontroller.cpp \
|
||||
src/tabcontrollers/ChaperoneTabController.cpp \
|
||||
src/tabcontrollers/FixFloorTabController.cpp \
|
||||
src/tabcontrollers/MoveCenterTabController.cpp \
|
||||
src/tabcontrollers/SettingsTabController.cpp \
|
||||
src/tabcontrollers/StatisticsTabController.cpp \
|
||||
src/tabcontrollers/SteamVRTabController.cpp
|
||||
|
||||
HEADERS += src/overlaywidget.h \
|
||||
src/overlaycontroller.h
|
||||
src/logging.h
|
||||
src/overlaycontroller.h \
|
||||
src/logging.h \
|
||||
src/tabcontrollers/ChaperoneTabController.h \
|
||||
src/tabcontrollers/FixFloorTabController.h \
|
||||
src/tabcontrollers/MoveCenterTabController.h \
|
||||
src/tabcontrollers/SettingsTabController.h \
|
||||
src/tabcontrollers/StatisticsTabController.h \
|
||||
src/tabcontrollers/SteamVRTabController.h
|
||||
|
||||
FORMS += ui/overlaywidget.ui
|
||||
|
||||
|
||||
+154
-321
@@ -12,8 +12,11 @@
|
||||
#include <QtWidgets/QGraphicsEllipseItem>
|
||||
#include <QOpenGLExtraFunctions>
|
||||
#include <QCursor>
|
||||
#include <QProcess>
|
||||
#include <QMessageBox>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <openvr.h>
|
||||
#include "logging.h"
|
||||
|
||||
@@ -65,15 +68,20 @@ void OverlayController::SetWidget(OverlayWidget *pWidget, const std::string& nam
|
||||
pWidget->move(0, 0);
|
||||
m_pScene->addWidget(pWidget);
|
||||
m_pWidget = pWidget;
|
||||
pWidget->ui->VersionLabel->setText(OverlayController::applicationVersionString);
|
||||
|
||||
if (!vr::VROverlay()) {
|
||||
QMessageBox::critical(nullptr, "OpenVR Advanced Settings Overlay", "Is OpenVR running?");
|
||||
throw std::runtime_error(std::string("No Overlay interface"));
|
||||
}
|
||||
vr::VROverlayError overlayError = vr::VROverlay()->CreateDashboardOverlay(key.c_str(), name.c_str(), &m_ulOverlayHandle, &m_ulOverlayThumbnailHandle);
|
||||
if (overlayError != vr::VROverlayError_None) {
|
||||
if (overlayError == vr::VROverlayError_KeyInUse) {
|
||||
QMessageBox::critical(nullptr, "OpenVR Advanced Settings Overlay", "Another instance is already running.");
|
||||
}
|
||||
throw std::runtime_error(std::string("Failed to create Overlay: " + std::string(vr::VROverlay()->GetOverlayErrorNameFromEnum(overlayError))));
|
||||
}
|
||||
vr::VROverlay()->SetOverlayWidthInMeters(m_ulOverlayHandle, 2.0f);
|
||||
vr::VROverlay()->SetOverlayWidthInMeters(m_ulOverlayHandle, 2.5f);
|
||||
vr::VROverlay()->SetOverlayInputMethod(m_ulOverlayHandle, vr::VROverlayInputMethod_Mouse);
|
||||
std::string thumbIconPath = QApplication::applicationDirPath().toStdString() + "\\res\\thumbicon.png";
|
||||
if (QFile::exists(QString::fromStdString(thumbIconPath))) {
|
||||
@@ -95,9 +103,11 @@ void OverlayController::SetWidget(OverlayWidget *pWidget, const std::string& nam
|
||||
};
|
||||
vr::VROverlay()->SetOverlayMouseScale(m_ulOverlayHandle, &vecWindowSize);
|
||||
|
||||
steamVRTabController.init(this, pWidget);
|
||||
chaperoneTabController.init(this, pWidget);
|
||||
moveCenterTabController.init(this, pWidget);
|
||||
fixFloorTabController.init(this, pWidget);
|
||||
statisticsTabController.init(this, pWidget);
|
||||
settingsTabController.init(this, pWidget);
|
||||
}
|
||||
|
||||
@@ -144,7 +154,11 @@ void OverlayController::OnTimeoutPumpEvents() {
|
||||
}
|
||||
*/
|
||||
|
||||
fixFloorTabController.eventLoopTick();
|
||||
vr::TrackedDevicePose_t devicePoses[vr::k_unMaxTrackedDeviceCount];
|
||||
vr::VRSystem()->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, 0.0f, devicePoses, vr::k_unMaxTrackedDeviceCount);
|
||||
fixFloorTabController.eventLoopTick(devicePoses);
|
||||
statisticsTabController.eventLoopTick(devicePoses);
|
||||
moveCenterTabController.eventLoopTick(vr::VRCompositor()->GetTrackingSpace());
|
||||
|
||||
vr::VREvent_t vrEvent;
|
||||
while( vr::VROverlay()->PollNextOverlayEvent( m_ulOverlayHandle, &vrEvent, sizeof( vrEvent ) ) ) {
|
||||
@@ -198,7 +212,7 @@ void OverlayController::OnTimeoutPumpEvents() {
|
||||
}
|
||||
break;
|
||||
|
||||
case vr::VREvent_MouseButtonUp: {
|
||||
case vr::VREvent_MouseButtonUp: {
|
||||
Qt::MouseButton button = vrEvent.data.mouse.button == vr::VRMouseButton_Right ? Qt::RightButton : Qt::LeftButton;
|
||||
m_lastMouseButtons &= ~button;
|
||||
|
||||
@@ -220,18 +234,31 @@ void OverlayController::OnTimeoutPumpEvents() {
|
||||
}
|
||||
break;
|
||||
|
||||
case vr::VREvent_OverlayShown: {
|
||||
case vr::VREvent_OverlayShown: {
|
||||
m_pWidget->repaint();
|
||||
UpdateWidget();
|
||||
}
|
||||
break;
|
||||
|
||||
case vr::VREvent_Quit:
|
||||
LOG(INFO) << "Received quit request.";
|
||||
vr::VRSystem()->AcknowledgeQuit_Exiting(); // Let us buy some time just in case
|
||||
moveCenterTabController.MoveCenterResetClicked();
|
||||
QApplication::exit();
|
||||
break;
|
||||
case vr::VREvent_Quit: {
|
||||
LOG(INFO) << "Received quit request.";
|
||||
vr::VRSystem()->AcknowledgeQuit_Exiting(); // Let us buy some time just in case
|
||||
moveCenterTabController.MoveCenterResetClicked();
|
||||
QApplication::exit();
|
||||
}
|
||||
break;
|
||||
|
||||
case vr::VREvent_DashboardActivated: {
|
||||
LOG(INFO) << "Dashboard activated";
|
||||
dashboardVisible = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case vr::VREvent_DashboardDeactivated: {
|
||||
LOG(INFO) << "Dashboard deactivated";
|
||||
dashboardVisible = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,337 +276,143 @@ void OverlayController::OnTimeoutPumpEvents() {
|
||||
}
|
||||
|
||||
void OverlayController::UpdateWidget() {
|
||||
steamVRTabController.UpdateTab();
|
||||
chaperoneTabController.UpdateTab();
|
||||
moveCenterTabController.UpdateTab();
|
||||
fixFloorTabController.UpdateTab();
|
||||
statisticsTabController.UpdateTab();
|
||||
settingsTabController.UpdateTab();
|
||||
}
|
||||
|
||||
void OverlayController::AddOffsetToStandingPosition(unsigned axisId, float offset) {
|
||||
vr::VRChaperoneSetup()->RevertWorkingCopy();
|
||||
vr::HmdMatrix34_t curPos;
|
||||
vr::VRChaperoneSetup()->GetWorkingStandingZeroPoseToRawTrackingPose(&curPos);
|
||||
curPos.m[0][3] += curPos.m[0][axisId] * offset;
|
||||
curPos.m[1][3] += curPos.m[1][axisId] * offset;
|
||||
curPos.m[2][3] += curPos.m[2][axisId] * offset;
|
||||
vr::VRChaperoneSetup()->SetWorkingStandingZeroPoseToRawTrackingPose(&curPos);
|
||||
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
|
||||
}
|
||||
|
||||
void ChaperoneTabController::init(OverlayController * parent, OverlayWidget * widget) {
|
||||
this->parent = parent;
|
||||
this->widget = widget;
|
||||
|
||||
connect(widget->ui->CenterMarkerToggle, SIGNAL(toggled(bool)), this, SLOT(CenterMarkerToggled(bool)));
|
||||
connect(widget->ui->PlaySpaceToggle, SIGNAL(toggled(bool)), this, SLOT(PlaySpaceToggled(bool)));
|
||||
connect(widget->ui->ForceBoundsToggle, SIGNAL(toggled(bool)), this, SLOT(ForceBoundsToggled(bool)));
|
||||
connect(widget->ui->FadeDistanceSlider, SIGNAL(valueChanged(int)), this, SLOT(FadeDistanceChanged(int)));
|
||||
connect(widget->ui->ColorAlphaSlider, SIGNAL(valueChanged(int)), this, SLOT(ColorAlphaChanged(int)));
|
||||
connect(widget->ui->ResetDefaultsToggle, SIGNAL(clicked()), this, SLOT(ResetDefaultsClicked()));
|
||||
}
|
||||
|
||||
void ChaperoneTabController::UpdateTab() {
|
||||
if (widget && vr::VRSettings()) {
|
||||
widget->ui->CenterMarkerToggle->blockSignals(true);
|
||||
widget->ui->PlaySpaceToggle->blockSignals(true);
|
||||
widget->ui->ForceBoundsToggle->blockSignals(true);
|
||||
widget->ui->FadeDistanceSlider->blockSignals(true);
|
||||
widget->ui->ColorAlphaSlider->blockSignals(true);
|
||||
|
||||
auto centerMarkerOn = vr::VRSettings()->GetBool(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_CenterMarkerOn_Bool, false);
|
||||
widget->ui->CenterMarkerToggle->setChecked(centerMarkerOn);
|
||||
auto playSpaceOn = vr::VRSettings()->GetBool(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_PlaySpaceOn_Bool, false);
|
||||
widget->ui->PlaySpaceToggle->setChecked(playSpaceOn);
|
||||
widget->ui->ForceBoundsToggle->setChecked(forceBoundsFlag);
|
||||
auto fadeDistance = vr::VRSettings()->GetFloat(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_FadeDistance_Float, 0.7f);
|
||||
widget->ui->FadeDistanceSlider->setValue(fadeDistance*100);
|
||||
widget->ui->FadeDistanceLabel->setText(QString::asprintf("%.2f", fadeDistance));
|
||||
auto colorAlpha = vr::VRSettings()->GetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_ColorGammaA_Int32, 255);
|
||||
widget->ui->ColorAlphaSlider->setValue(colorAlpha*100/255);
|
||||
widget->ui->ColorAlphaLabel->setText(QString::asprintf("%i%%", colorAlpha*100/255));
|
||||
|
||||
widget->ui->CenterMarkerToggle->blockSignals(false);
|
||||
widget->ui->PlaySpaceToggle->blockSignals(false);
|
||||
widget->ui->ForceBoundsToggle->blockSignals(false);
|
||||
widget->ui->FadeDistanceSlider->blockSignals(false);
|
||||
widget->ui->ColorAlphaSlider->blockSignals(false);
|
||||
}
|
||||
}
|
||||
|
||||
void ChaperoneTabController::CenterMarkerToggled(bool value) {
|
||||
if (vr::VRSettings()) {
|
||||
vr::VRSettings()->SetBool(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_CenterMarkerOn_Bool, value);
|
||||
vr::VRSettings()->Sync();
|
||||
}
|
||||
}
|
||||
|
||||
void ChaperoneTabController::PlaySpaceToggled(bool value) {
|
||||
if (vr::VRSettings()) {
|
||||
vr::VRSettings()->SetBool(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_PlaySpaceOn_Bool, value);
|
||||
vr::VRSettings()->Sync();
|
||||
}
|
||||
}
|
||||
|
||||
void ChaperoneTabController::ForceBoundsToggled(bool value) {
|
||||
if (vr::VRChaperone()) {
|
||||
forceBoundsFlag = value;
|
||||
vr::VRChaperone()->ForceBoundsVisible(value);
|
||||
}
|
||||
}
|
||||
|
||||
void ChaperoneTabController::FadeDistanceChanged(int value) {
|
||||
if (vr::VRSettings()) {
|
||||
float fval= (float)value / 100;
|
||||
vr::VRSettings()->SetFloat(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_FadeDistance_Float, fval);
|
||||
vr::VRSettings()->Sync();
|
||||
widget->ui->FadeDistanceLabel->setText(QString::asprintf("%.2f", fval));
|
||||
}
|
||||
}
|
||||
|
||||
void ChaperoneTabController::ColorAlphaChanged(int value) {
|
||||
if (vr::VRSettings()) {
|
||||
float fval = (float)value / 100;
|
||||
vr::VRSettings()->SetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_ColorGammaA_Int32, 255*fval);
|
||||
vr::VRSettings()->Sync();
|
||||
widget->ui->ColorAlphaLabel->setText(QString::asprintf("%i%%", value));
|
||||
}
|
||||
}
|
||||
|
||||
void ChaperoneTabController::ResetDefaultsClicked() {
|
||||
widget->ui->CenterMarkerToggle->setChecked(false);
|
||||
widget->ui->PlaySpaceToggle->setChecked(false);
|
||||
widget->ui->ForceBoundsToggle->setChecked(false);
|
||||
widget->ui->FadeDistanceSlider->setValue(70);
|
||||
widget->ui->ColorAlphaSlider->setValue(100);
|
||||
}
|
||||
|
||||
void MoveCenterTabController::init(OverlayController * parent, OverlayWidget * widget) {
|
||||
this->parent = parent;
|
||||
this->widget = widget;
|
||||
xOffset = 0.0f;
|
||||
yOffset = 0.0f;
|
||||
zOffset = 0.0f;
|
||||
connect(widget->ui->XMinusButton, SIGNAL(clicked()), this, SLOT(XMinusClicked()));
|
||||
connect(widget->ui->XPlusButton, SIGNAL(clicked()), this, SLOT(XPlusClicked()));
|
||||
connect(widget->ui->YMinusButton, SIGNAL(clicked()), this, SLOT(YMinusClicked()));
|
||||
connect(widget->ui->YPlusButton, SIGNAL(clicked()), this, SLOT(YPlusClicked()));
|
||||
connect(widget->ui->ZMinusButton, SIGNAL(clicked()), this, SLOT(ZMinusClicked()));
|
||||
connect(widget->ui->ZPlusButton, SIGNAL(clicked()), this, SLOT(ZPlusClicked()));
|
||||
connect(widget->ui->MoveCenterResetButton, SIGNAL(clicked()), this, SLOT(MoveCenterResetClicked()));
|
||||
}
|
||||
|
||||
void MoveCenterTabController::UpdateTab() {
|
||||
if (widget) {
|
||||
widget->ui->XOffsetLabel->setText(QString::asprintf("%.1f", xOffset));
|
||||
widget->ui->YOffsetLabel->setText(QString::asprintf("%.1f", yOffset));
|
||||
widget->ui->ZOffsetLabel->setText(QString::asprintf("%.1f", zOffset));
|
||||
}
|
||||
}
|
||||
|
||||
void MoveCenterTabController::XMinusClicked() {
|
||||
if (widget) {
|
||||
parent->AddOffsetToStandingPosition(0, -0.5f);
|
||||
xOffset -= 0.5f;
|
||||
widget->ui->XOffsetLabel->setText(QString::asprintf("%.1f", xOffset));
|
||||
}
|
||||
}
|
||||
|
||||
void MoveCenterTabController::XPlusClicked() {
|
||||
if (widget) {
|
||||
parent->AddOffsetToStandingPosition(0, 0.5f);
|
||||
xOffset += 0.5f;
|
||||
widget->ui->XOffsetLabel->setText(QString::asprintf("%.1f", xOffset));
|
||||
}
|
||||
}
|
||||
|
||||
void MoveCenterTabController::YMinusClicked() {
|
||||
if (widget) {
|
||||
parent->AddOffsetToStandingPosition(1, -0.5f);
|
||||
yOffset -= 0.5f;
|
||||
widget->ui->YOffsetLabel->setText(QString::asprintf("%.1f", yOffset));
|
||||
}
|
||||
}
|
||||
|
||||
void MoveCenterTabController::YPlusClicked() {
|
||||
if (widget) {
|
||||
parent->AddOffsetToStandingPosition(1, 0.5f);
|
||||
yOffset += 0.5f;
|
||||
widget->ui->YOffsetLabel->setText(QString::asprintf("%.1f", yOffset));
|
||||
}
|
||||
}
|
||||
|
||||
void MoveCenterTabController::ZMinusClicked() {
|
||||
if (widget) {
|
||||
parent->AddOffsetToStandingPosition(2, -0.5f);
|
||||
zOffset -= 0.5f;
|
||||
widget->ui->ZOffsetLabel->setText(QString::asprintf("%.1f", zOffset));
|
||||
}
|
||||
}
|
||||
|
||||
void MoveCenterTabController::ZPlusClicked() {
|
||||
if (widget) {
|
||||
parent->AddOffsetToStandingPosition(2, 0.5f);
|
||||
zOffset += 0.5f;
|
||||
widget->ui->ZOffsetLabel->setText(QString::asprintf("%.1f", zOffset));
|
||||
}
|
||||
}
|
||||
|
||||
void MoveCenterTabController::MoveCenterResetClicked() {
|
||||
if (widget) {
|
||||
parent->AddOffsetToStandingPosition(0, -xOffset);
|
||||
parent->AddOffsetToStandingPosition(1, -yOffset);
|
||||
parent->AddOffsetToStandingPosition(2, -zOffset);
|
||||
xOffset = 0.0f;
|
||||
yOffset = 0.0f;
|
||||
zOffset = 0.0f;
|
||||
widget->ui->XOffsetLabel->setText(QString::asprintf("%.1f", xOffset));
|
||||
widget->ui->YOffsetLabel->setText(QString::asprintf("%.1f", yOffset));
|
||||
widget->ui->ZOffsetLabel->setText(QString::asprintf("%.1f", zOffset));
|
||||
}
|
||||
}
|
||||
|
||||
void FixFloorTabController::init(OverlayController * parent, OverlayWidget * widget) {
|
||||
this->parent = parent;
|
||||
this->widget = widget;
|
||||
connect(widget->ui->FixFloorButton, SIGNAL(clicked()), this, SLOT(FixFloorClicked()));
|
||||
connect(widget->ui->UndoFixFloorButton, SIGNAL(clicked()), this, SLOT(UndoFixFloorClicked()));
|
||||
}
|
||||
|
||||
void FixFloorTabController::UpdateTab() {
|
||||
if (widget) {
|
||||
if (state == 1) {
|
||||
widget->ui->FixFloorButton->setEnabled(false);
|
||||
} else {
|
||||
widget->ui->FixFloorButton->setEnabled(true);
|
||||
void OverlayController::AddOffsetToUniverseCenter(vr::ETrackingUniverseOrigin universe, unsigned axisId, float offset, bool adjustBounds, bool commit) {
|
||||
if (offset != 0.0f) {
|
||||
if (commit) {
|
||||
vr::VRChaperoneSetup()->RevertWorkingCopy();
|
||||
}
|
||||
if (floorOffset != 0.0f) {
|
||||
widget->ui->UndoFixFloorButton->setEnabled(true);
|
||||
vr::HmdMatrix34_t curPos;
|
||||
if (universe == vr::TrackingUniverseStanding) {
|
||||
vr::VRChaperoneSetup()->GetWorkingStandingZeroPoseToRawTrackingPose(&curPos);
|
||||
} else {
|
||||
widget->ui->UndoFixFloorButton->setEnabled(false);
|
||||
vr::VRChaperoneSetup()->GetWorkingSeatedZeroPoseToRawTrackingPose(&curPos);
|
||||
}
|
||||
curPos.m[0][3] += curPos.m[0][axisId] * offset;
|
||||
curPos.m[1][3] += curPos.m[1][axisId] * offset;
|
||||
curPos.m[2][3] += curPos.m[2][axisId] * offset;
|
||||
if (universe == vr::TrackingUniverseStanding) {
|
||||
vr::VRChaperoneSetup()->SetWorkingStandingZeroPoseToRawTrackingPose(&curPos);
|
||||
} else {
|
||||
vr::VRChaperoneSetup()->SetWorkingSeatedZeroPoseToRawTrackingPose(&curPos);
|
||||
}
|
||||
if (adjustBounds && universe == vr::TrackingUniverseStanding) {
|
||||
AddOffsetToCollisionBounds(axisId, -offset, false);
|
||||
}
|
||||
if (commit) {
|
||||
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FixFloorTabController::eventLoopTick() {
|
||||
if (state == 1) {
|
||||
if (measurementCount == 0) {
|
||||
// Get Controller ids for left/right hand
|
||||
auto leftId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_LeftHand);
|
||||
if (leftId == vr::k_unTrackedDeviceIndexInvalid) {
|
||||
widget->ui->FixFloorStatusLabel->setText("No left controller found.");
|
||||
statusMessageTimeout = 100;
|
||||
state = 2;
|
||||
UpdateTab();
|
||||
return;
|
||||
}
|
||||
auto rightId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_RightHand);
|
||||
if (rightId == vr::k_unTrackedDeviceIndexInvalid) {
|
||||
widget->ui->FixFloorStatusLabel->setText("No right controller found.");
|
||||
statusMessageTimeout = 100;
|
||||
state = 2;
|
||||
UpdateTab();
|
||||
return;
|
||||
}
|
||||
// Get poses
|
||||
vr::TrackedDevicePose_t devicePoses[vr::k_unMaxTrackedDeviceCount];
|
||||
vr::VRSystem()->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, 0.0f, devicePoses, vr::k_unMaxTrackedDeviceCount);
|
||||
vr::TrackedDevicePose_t* leftPose = devicePoses + leftId;
|
||||
vr::TrackedDevicePose_t* rightPose = devicePoses + rightId;
|
||||
if (!leftPose->bPoseIsValid || !leftPose->bDeviceIsConnected || leftPose->eTrackingResult != vr::TrackingResult_Running_OK) {
|
||||
widget->ui->FixFloorStatusLabel->setText("Left controller tracking problems.");
|
||||
statusMessageTimeout = 100;
|
||||
state = 2;
|
||||
UpdateTab();
|
||||
return;
|
||||
} else if (!rightPose->bPoseIsValid || !rightPose->bDeviceIsConnected || rightPose->eTrackingResult != vr::TrackingResult_Running_OK) {
|
||||
widget->ui->FixFloorStatusLabel->setText("Right controller tracking problems.");
|
||||
statusMessageTimeout = 100;
|
||||
state = 2;
|
||||
UpdateTab();
|
||||
return;
|
||||
} else {
|
||||
// The controller with the lowest y-pos is the floor fix reference
|
||||
if (leftPose->mDeviceToAbsoluteTracking.m[1][3] < rightPose->mDeviceToAbsoluteTracking.m[1][3]) {
|
||||
referenceController = leftId;
|
||||
} else {
|
||||
referenceController = rightId;
|
||||
void OverlayController::RotateUniverseCenter(vr::ETrackingUniverseOrigin universe, float yAngle, bool adjustBounds, bool commit) {
|
||||
if (yAngle != 0.0f) {
|
||||
if (commit) {
|
||||
vr::VRChaperoneSetup()->RevertWorkingCopy();
|
||||
}
|
||||
vr::HmdMatrix34_t curPos;
|
||||
if (universe == vr::TrackingUniverseStanding) {
|
||||
vr::VRChaperoneSetup()->GetWorkingStandingZeroPoseToRawTrackingPose(&curPos);
|
||||
} else {
|
||||
vr::VRChaperoneSetup()->GetWorkingSeatedZeroPoseToRawTrackingPose(&curPos);
|
||||
}
|
||||
vr::HmdMatrix34_t newPos;
|
||||
float yRot[3][3] = {
|
||||
{ std::cos(yAngle), 0, std::sin(yAngle) },
|
||||
{ 0, 1, 0 },
|
||||
{ -std::sin(yAngle), 0, std::cos(yAngle) }
|
||||
};
|
||||
for (unsigned i = 0; i < 3; i++) {
|
||||
for (unsigned j = 0; j < 3; j++) {
|
||||
newPos.m[i][j] = 0.0f;
|
||||
for (unsigned k = 0; k < 3; k++) {
|
||||
newPos.m[i][j] += yRot[i][k] * curPos.m[k][j];
|
||||
}
|
||||
tempOffset = (double)devicePoses[referenceController].mDeviceToAbsoluteTracking.m[1][3];
|
||||
measurementCount = 1;
|
||||
}
|
||||
|
||||
} else if (measurementCount >= 50) {
|
||||
floorOffset = -controllerUpOffsetCorrection + (float)(tempOffset / (double)measurementCount);
|
||||
LOG(INFO) << "Fix Floor: Floor Offset = " << floorOffset;
|
||||
parent->AddOffsetToStandingPosition(1, floorOffset);
|
||||
widget->ui->FixFloorStatusLabel->setText("Fixing ... OK");
|
||||
statusMessageTimeout = 50;
|
||||
state = 2;
|
||||
UpdateTab();
|
||||
} else {
|
||||
vr::TrackedDevicePose_t devicePoses[vr::k_unMaxTrackedDeviceCount];
|
||||
vr::VRSystem()->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, 0.0f, devicePoses, vr::k_unMaxTrackedDeviceCount);
|
||||
tempOffset += (double)devicePoses[referenceController].mDeviceToAbsoluteTracking.m[1][3];
|
||||
measurementCount++;
|
||||
}
|
||||
} else if (state == 2) {
|
||||
if (statusMessageTimeout == 0) {
|
||||
if (widget) {
|
||||
widget->ui->FixFloorStatusLabel->setText("");
|
||||
newPos.m[0][3] = curPos.m[0][3];
|
||||
newPos.m[1][3] = curPos.m[1][3];
|
||||
newPos.m[2][3] = curPos.m[2][3];
|
||||
vr::VRChaperoneSetup()->SetWorkingStandingZeroPoseToRawTrackingPose(&newPos);
|
||||
if (universe == vr::TrackingUniverseStanding) {
|
||||
vr::VRChaperoneSetup()->SetWorkingStandingZeroPoseToRawTrackingPose(&newPos);
|
||||
} else {
|
||||
vr::VRChaperoneSetup()->SetWorkingSeatedZeroPoseToRawTrackingPose(&newPos);
|
||||
}
|
||||
if (adjustBounds && universe == vr::TrackingUniverseStanding) {
|
||||
RotateCollisionBounds(-yAngle, false);
|
||||
}
|
||||
if (commit) {
|
||||
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OverlayController::AddOffsetToCollisionBounds(unsigned axisId, float offset, bool commit) {
|
||||
// Apparently Valve sanity-checks the y-coordinates of the collision bounds (and only the y-coordinates)
|
||||
// I can move the bounds on the xz-plane, I can make the "ceiling" of the chaperone cage lower/higher, but when I
|
||||
// dare to set one single lower corner to something non-zero, every corner gets its y-coordinates reset to the defaults.
|
||||
// I do it anyway, maybe it gets fixed in the future.
|
||||
if (commit) {
|
||||
vr::VRChaperoneSetup()->RevertWorkingCopy();
|
||||
}
|
||||
unsigned collisionBoundsCount = 0;
|
||||
vr::VRChaperoneSetup()->GetWorkingCollisionBoundsInfo(nullptr, &collisionBoundsCount);
|
||||
if (collisionBoundsCount > 0) {
|
||||
vr::HmdQuad_t* collisionBounds = new vr::HmdQuad_t[collisionBoundsCount];
|
||||
vr::VRChaperoneSetup()->GetWorkingCollisionBoundsInfo(collisionBounds, &collisionBoundsCount);
|
||||
for (unsigned b = 0; b < collisionBoundsCount; b++) {
|
||||
for (unsigned c = 0; c < 4; c++) {
|
||||
collisionBounds[b].vCorners[c].v[axisId] += offset;
|
||||
}
|
||||
state = 0;
|
||||
UpdateTab();
|
||||
} else {
|
||||
statusMessageTimeout--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FixFloorTabController::FixFloorClicked() {
|
||||
if (widget) {
|
||||
widget->ui->FixFloorStatusLabel->setText("Fixing ...");
|
||||
widget->ui->FixFloorButton->setEnabled(false);
|
||||
widget->ui->UndoFixFloorButton->setEnabled(false);
|
||||
measurementCount = 0;
|
||||
state = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void FixFloorTabController::UndoFixFloorClicked() {
|
||||
parent->AddOffsetToStandingPosition(1, -floorOffset);
|
||||
LOG(INFO) << "Fix Floor: Undo Floor Offset = " << -floorOffset;
|
||||
floorOffset = 0.0f;
|
||||
widget->ui->FixFloorStatusLabel->setText("Undo ... OK");
|
||||
statusMessageTimeout = 100;
|
||||
state = 2;
|
||||
UpdateTab();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SettingsTabController::init(OverlayController * parent, OverlayWidget * widget) {
|
||||
this->parent = parent;
|
||||
this->widget = widget;
|
||||
connect(widget->ui->AutoStartToggle, SIGNAL(toggled(bool)), this, SLOT(AutoStartToggled(bool)));
|
||||
}
|
||||
|
||||
void SettingsTabController::UpdateTab() {
|
||||
if (widget) {
|
||||
widget->ui->AutoStartToggle->blockSignals(true);
|
||||
if (vr::VRApplications()->GetApplicationAutoLaunch(OverlayController::applicationKey)) {
|
||||
widget->ui->AutoStartToggle->setChecked(true);
|
||||
} else {
|
||||
widget->ui->AutoStartToggle->setChecked(false);
|
||||
}
|
||||
widget->ui->AutoStartToggle->blockSignals(false);
|
||||
vr::VRChaperoneSetup()->SetWorkingCollisionBoundsInfo(collisionBounds, collisionBoundsCount);
|
||||
delete collisionBounds;
|
||||
}
|
||||
if (commit && collisionBoundsCount > 0) {
|
||||
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsTabController::AutoStartToggled(bool value) {
|
||||
LOG(INFO) << "Setting auto start: " << value;
|
||||
auto apperror = vr::VRApplications()->SetApplicationAutoLaunch(OverlayController::applicationKey, value);
|
||||
if (apperror != vr::VRApplicationError_None) {
|
||||
LOG(ERROR) << "Could not set auto start: " << vr::VRApplications()->GetApplicationsErrorNameFromEnum(apperror);
|
||||
void OverlayController::RotateCollisionBounds(float angle, bool commit) {
|
||||
if (commit) {
|
||||
vr::VRChaperoneSetup()->RevertWorkingCopy();
|
||||
}
|
||||
unsigned collisionBoundsCount = 0;
|
||||
vr::VRChaperoneSetup()->GetWorkingCollisionBoundsInfo(nullptr, &collisionBoundsCount);
|
||||
if (collisionBoundsCount > 0) {
|
||||
vr::HmdQuad_t* collisionBounds = new vr::HmdQuad_t[collisionBoundsCount];
|
||||
vr::VRChaperoneSetup()->GetWorkingCollisionBoundsInfo(collisionBounds, &collisionBoundsCount);
|
||||
float yRot[3][3] = {
|
||||
{ std::cos(angle), 0, std::sin(angle) },
|
||||
{ 0, 1, 0 },
|
||||
{ -std::sin(angle), 0, std::cos(angle) }
|
||||
};
|
||||
for (unsigned b = 0; b < collisionBoundsCount; b++) {
|
||||
for (unsigned c = 0; c < 4; c++) {
|
||||
auto& corner = collisionBounds[b].vCorners[c];
|
||||
vr::HmdVector3_t newVal;
|
||||
for (unsigned i = 0; i < 3; i++) {
|
||||
newVal.v[i] = 0.0f;
|
||||
for (unsigned k = 0; k < 3; k++) {
|
||||
newVal.v[i] += corner.v[k] * yRot[i][k];
|
||||
};
|
||||
}
|
||||
corner = newVal;
|
||||
}
|
||||
}
|
||||
vr::VRChaperoneSetup()->SetWorkingCollisionBoundsInfo(collisionBounds, collisionBoundsCount);
|
||||
delete collisionBounds;
|
||||
}
|
||||
if (commit && collisionBoundsCount > 0) {
|
||||
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+22
-102
@@ -1,7 +1,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "openvr.h"
|
||||
#include <openvr.h>
|
||||
#include <QtCore/QtCore>
|
||||
// because of incompatibilities with QtOpenGL and GLEW we need to cherry pick includes
|
||||
#include <QVector2D>
|
||||
@@ -14,111 +14,21 @@
|
||||
#include <QOffscreenSurface>
|
||||
#include <QOpenGLFramebufferObject>
|
||||
#include <memory>
|
||||
#include "logging.h"
|
||||
|
||||
#include "tabcontrollers/SteamVRTabController.h"
|
||||
#include "tabcontrollers/ChaperoneTabController.h"
|
||||
#include "tabcontrollers/MoveCenterTabController.h"
|
||||
#include "tabcontrollers/FixFloorTabController.h"
|
||||
#include "tabcontrollers/StatisticsTabController.h"
|
||||
#include "tabcontrollers/SettingsTabController.h"
|
||||
|
||||
|
||||
// application namespace
|
||||
namespace advsettings {
|
||||
|
||||
// forward declaration
|
||||
class OverlayWidget;
|
||||
class OverlayController;
|
||||
|
||||
|
||||
class ChaperoneTabController : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
OverlayController* parent;
|
||||
OverlayWidget* widget;
|
||||
|
||||
bool forceBoundsFlag = false;
|
||||
|
||||
public:
|
||||
void init(OverlayController* parent, OverlayWidget* widget);
|
||||
|
||||
public slots:
|
||||
void UpdateTab();
|
||||
|
||||
void CenterMarkerToggled(bool value);
|
||||
void PlaySpaceToggled(bool value);
|
||||
void ForceBoundsToggled(bool value);
|
||||
void FadeDistanceChanged(int value);
|
||||
void ColorAlphaChanged(int value);
|
||||
void ResetDefaultsClicked();
|
||||
};
|
||||
|
||||
|
||||
class MoveCenterTabController : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
OverlayController* parent;
|
||||
OverlayWidget* widget;
|
||||
|
||||
float xOffset = 0.0f;
|
||||
float yOffset = 0.0f;
|
||||
float zOffset = 0.0f;
|
||||
|
||||
public:
|
||||
void init(OverlayController* parent, OverlayWidget* widget);
|
||||
|
||||
public slots:
|
||||
void UpdateTab();
|
||||
|
||||
void XMinusClicked();
|
||||
void XPlusClicked();
|
||||
void YMinusClicked();
|
||||
void YPlusClicked();
|
||||
void ZMinusClicked();
|
||||
void ZPlusClicked();
|
||||
void MoveCenterResetClicked();
|
||||
};
|
||||
|
||||
|
||||
class FixFloorTabController : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
OverlayController* parent;
|
||||
OverlayWidget* widget;
|
||||
|
||||
float controllerUpOffsetCorrection = 0.06f; // Controller touchpad facing upwards
|
||||
float controllerDownOffsetCorrection = 0.0f; // Controller touchpad facing downwards (not implemented yet)
|
||||
|
||||
int state = 0; // 0 .. idle, 1 .. measurement in progress, 2 .. waiting for status message timeout
|
||||
vr::TrackedDeviceIndex_t referenceController = vr::k_unTrackedDeviceIndexInvalid;
|
||||
unsigned measurementCount = 0;
|
||||
double tempOffset = 0.0;
|
||||
unsigned statusMessageTimeout = 0;
|
||||
float floorOffset = 0.0f;
|
||||
|
||||
public:
|
||||
void init(OverlayController* parent, OverlayWidget* widget);
|
||||
|
||||
public slots:
|
||||
void UpdateTab();
|
||||
void eventLoopTick();
|
||||
|
||||
void FixFloorClicked();
|
||||
void UndoFixFloorClicked();
|
||||
};
|
||||
|
||||
|
||||
class SettingsTabController : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
OverlayController* parent;
|
||||
OverlayWidget* widget;
|
||||
|
||||
public:
|
||||
void init(OverlayController* parent, OverlayWidget* widget);
|
||||
|
||||
public slots:
|
||||
void UpdateTab();
|
||||
|
||||
void AutoStartToggled(bool value);
|
||||
};
|
||||
|
||||
|
||||
class OverlayController : public QObject {
|
||||
Q_OBJECT
|
||||
@@ -126,6 +36,7 @@ class OverlayController : public QObject {
|
||||
public:
|
||||
static constexpr const char* applicationKey = "matzman666.AdvancedSettings";
|
||||
static constexpr const char* applicationName = "Advanced Settings";
|
||||
static constexpr const char* applicationVersionString = "v1.1";
|
||||
|
||||
private:
|
||||
OverlayWidget *m_pWidget;
|
||||
@@ -139,13 +50,16 @@ private:
|
||||
std::unique_ptr<QOffscreenSurface> m_pOffscreenSurface;
|
||||
|
||||
std::unique_ptr<QTimer> m_pPumpEventsTimer;
|
||||
bool dashboardVisible = false;
|
||||
|
||||
QPointF m_ptLastMouse;
|
||||
Qt::MouseButtons m_lastMouseButtons = 0;
|
||||
|
||||
SteamVRTabController steamVRTabController;
|
||||
ChaperoneTabController chaperoneTabController;
|
||||
MoveCenterTabController moveCenterTabController;
|
||||
FixFloorTabController fixFloorTabController;
|
||||
StatisticsTabController statisticsTabController;
|
||||
SettingsTabController settingsTabController;
|
||||
|
||||
public:
|
||||
@@ -154,16 +68,22 @@ public:
|
||||
|
||||
void Init();
|
||||
|
||||
bool isDashboardVisible() {
|
||||
return dashboardVisible;
|
||||
}
|
||||
|
||||
void SetWidget(OverlayWidget *pWidget, const std::string& name, const std::string& key = "");
|
||||
|
||||
void AddOffsetToStandingPosition(unsigned axisId, float offset);
|
||||
void AddOffsetToUniverseCenter(vr::ETrackingUniverseOrigin universe, unsigned axisId, float offset, bool adjustBounds = true, bool commit = true);
|
||||
void RotateUniverseCenter(vr::ETrackingUniverseOrigin universe, float yAngle, bool adjustBounds = true, bool commit = true); // around y axis
|
||||
void AddOffsetToCollisionBounds(unsigned axisId, float offset, bool commit = true);
|
||||
void RotateCollisionBounds(float angle, bool commit = true); // around y axis
|
||||
|
||||
public slots:
|
||||
void OnSceneChanged( const QList<QRectF>& );
|
||||
void OnTimeoutPumpEvents();
|
||||
|
||||
void UpdateWidget();
|
||||
|
||||
};
|
||||
|
||||
} // namespace advsettings
|
||||
|
||||
+881
-25
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user