Complete GUI overhaul (from Qt Widgets to Qt Quick Controls 2)

Added chaperone profiles
Added separate supersampling sliders for applications/compositor
Added asynchronous reprojection on/off switch
Merged in Microphone Control Overlay
Added Push-to-Talk profiles
Updated to OpenVR 1.0.3
Requires at least SteamVR beta 1477423729.
This commit is contained in:
2016-10-28 18:38:05 +02:00
parent 8e815b0ce4
commit e39c240ff5
462 changed files with 64668 additions and 2760 deletions
+48 -5
View File
@@ -1,6 +1,10 @@
#include "overlaywidget.h"
#include "overlaycontroller.h"
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQuickView>
#include <QQmlEngine>
#include <QQmlComponent>
#include <QSettings>
#include <iostream>
#include "logging.h"
@@ -19,6 +23,25 @@ const char* logConfigDefault =
INITIALIZE_EASYLOGGINGPP
void myQtMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
QByteArray localMsg = msg.toLocal8Bit();
switch (type) {
case QtDebugMsg:
case QtInfoMsg:
LOG(INFO) << localMsg.constData() << "(" << context.file << ":" << context.line << ")";
break;
case QtWarningMsg:
LOG(WARNING) << localMsg.constData() << "(" << context.file << ":" << context.line << ")";
break;
case QtCriticalMsg:
LOG(ERROR) << localMsg.constData() << "(" << context.file << ":" << context.line << ")";
break;
case QtFatalMsg:
LOG(FATAL) << localMsg.constData() << "(" << context.file << ":" << context.line << ")";
break;
}
}
int main(int argc, char *argv[]) {
// Configure logger
@@ -36,11 +59,24 @@ int main(int argc, char *argv[]) {
LOG(INFO) << "Starting Application.";
try {
QApplication a(argc, argv);
advsettings::OverlayWidget *pOverlayWidget = new advsettings::OverlayWidget;
advsettings::OverlayController* controller = new advsettings::OverlayController();
qInstallMessageHandler(myQtMessageHandler);
controller->Init();
controller->SetWidget(pOverlayWidget, advsettings::OverlayController::applicationName, advsettings::OverlayController::applicationKey);
QSettings appSettings(QSettings::IniFormat, QSettings::UserScope, "matzman666", "OpenVRAdvancedSettings");
advsettings::OverlayController::setAppSettings(&appSettings);
LOG(INFO) << "Settings File: " << appSettings.fileName().toStdString();
QQmlEngine qmlEngine;
advsettings::OverlayController* controller = advsettings::OverlayController::getInstance();
controller->Init(&qmlEngine);
QQmlComponent component(&qmlEngine, QUrl::fromLocalFile("res/qml/mainwidget.qml"));
auto errors = component.errors();
for (auto& e : errors) {
LOG(ERROR) << "QML Error: " << e.toString().toStdString() << std::endl;
}
auto quickObj = component.create();
controller->SetWidget(qobject_cast<QQuickItem*>(quickObj), advsettings::OverlayController::applicationName, advsettings::OverlayController::applicationKey);
std::string manifestPath = QApplication::applicationDirPath().toStdString() + "\\advancedsettings.vrmanifest";
if (QFile::exists(QString::fromStdString(manifestPath))) {
@@ -61,6 +97,13 @@ int main(int argc, char *argv[]) {
LOG(ERROR) << "Could not find application manifest: " << manifestPath;
}
#ifdef DEBUG_DESKTOP_WINDOW
auto m_pWindow = new QQuickWindow();
qobject_cast<QQuickItem*>(quickObj)->setParentItem(m_pWindow->contentItem());
m_pWindow->setGeometry(0, 0, qobject_cast<QQuickItem*>(quickObj)->width(), qobject_cast<QQuickItem*>(quickObj)->height());
m_pWindow->show();
#endif
return a.exec();
} catch (const std::exception& e) {
+380 -332
View File
@@ -1,10 +1,11 @@
#include "overlaycontroller.h"
#include "overlaywidget.h"
#include "ui_overlaywidget.h"
#include <QOpenGLFramebufferObjectFormat>
#include <QOpenGLPaintDevice>
#include <QPainter>
#include <QQuickView>
#include <QApplication>
#include <QQmlEngine>
#include <QQmlContext>
#include <QtWidgets/QWidget>
#include <QMouseEvent>
#include <QtWidgets/QGraphicsSceneMouseEvent>
@@ -25,408 +26,455 @@
// application namespace
namespace advsettings {
OverlayController::~OverlayController() {
m_pPumpEventsTimer.reset();
vr::VR_Shutdown();
m_pScene.reset();
m_pFbo.reset();
m_pOffscreenSurface.reset();
m_pOpenGLContext.reset();
std::unique_ptr<OverlayController> OverlayController::singleton;
QSettings* OverlayController::_appSettings = nullptr;
OverlayController::~OverlayController() {
}
void OverlayController::Init(QQmlEngine* qmlEngine) {
// Loading the OpenVR Runtime
auto initError = vr::VRInitError_None;
vr::VR_Init(&initError, vr::VRApplication_Overlay);
if (initError != vr::VRInitError_None) {
throw std::runtime_error(std::string("Failed to initialize OpenVR: " + std::string(vr::VR_GetVRInitErrorAsEnglishDescription(initError))));
}
void OverlayController::Init() {
// Loading the OpenVR Runtime
auto initError = vr::VRInitError_None;
vr::VR_Init(&initError, vr::VRApplication_Overlay);
if (initError != vr::VRInitError_None) {
throw std::runtime_error(std::string("Failed to initialize OpenVR: " + std::string(vr::VR_GetVRInitErrorAsEnglishDescription(initError))));
}
m_runtimePathUrl = QUrl::fromLocalFile(vr::VR_RuntimePath());
LOG(INFO) << "VR Runtime Path: " << m_runtimePathUrl.toLocalFile();
QSurfaceFormat format;
// Qt's QOpenGLPaintDevice is not compatible with OpenGL versions >= 3.0
// NVIDIA does not care, but unfortunately AMD does
// Are subtle changes to the semantics of OpenGL functions actually covered by the compatibility profile,
// and this is an AMD bug?
format.setVersion(2, 1);
//format.setProfile( QSurfaceFormat::CompatibilityProfile );
format.setDepthBufferSize(16);
format.setStencilBufferSize(8);
format.setSamples(16);
QSurfaceFormat format;
// Qt's QOpenGLPaintDevice is not compatible with OpenGL versions >= 3.0
// NVIDIA does not care, but unfortunately AMD does
// Are subtle changes to the semantics of OpenGL functions actually covered by the compatibility profile,
// and this is an AMD bug?
format.setVersion(2, 1);
//format.setProfile( QSurfaceFormat::CompatibilityProfile );
format.setDepthBufferSize(16);
format.setStencilBufferSize(8);
format.setSamples(16);
m_pOpenGLContext.reset(new QOpenGLContext());
m_pOpenGLContext->setFormat(format);
if (!m_pOpenGLContext->create()) {
throw std::runtime_error("Could not create OpenGL context");
}
// create an offscreen surface to attach the context and FBO to
m_pOffscreenSurface.reset(new QOffscreenSurface());
m_pOffscreenSurface->setFormat(m_pOpenGLContext->format());
m_pOffscreenSurface->create();
m_pOpenGLContext->makeCurrent(m_pOffscreenSurface.get());
m_pScene.reset(new QGraphicsScene());
connect(m_pScene.get(), SIGNAL(changed(const QList<QRectF>&)), this, SLOT(OnSceneChanged(const QList<QRectF>&)));
m_pOpenGLContext.reset(new QOpenGLContext());
m_pOpenGLContext->setFormat(format);
if (!m_pOpenGLContext->create()) {
throw std::runtime_error("Could not create OpenGL context");
}
// create an offscreen surface to attach the context and FBO to
m_pOffscreenSurface.reset(new QOffscreenSurface());
m_pOffscreenSurface->setFormat(m_pOpenGLContext->format());
m_pOffscreenSurface->create();
m_pOpenGLContext->makeCurrent(m_pOffscreenSurface.get());
void OverlayController::SetWidget(OverlayWidget *pWidget, const std::string& name, const std::string& key) {
// all of the mouse handling stuff requires that the widget be at 0,0
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.5f);
vr::VROverlay()->SetOverlayInputMethod(m_ulOverlayHandle, vr::VROverlayInputMethod_Mouse);
std::string thumbIconPath = QApplication::applicationDirPath().toStdString() + "\\res\\thumbicon.png";
if (QFile::exists(QString::fromStdString(thumbIconPath))) {
vr::VROverlay()->SetOverlayFromFile(m_ulOverlayThumbnailHandle, thumbIconPath.c_str());
} else {
LOG(ERROR) << "Could not find thumbnail icon \"" << thumbIconPath << "\"";
}
m_pPumpEventsTimer.reset(new QTimer(this));
connect(m_pPumpEventsTimer.get(), SIGNAL(timeout()), this, SLOT(OnTimeoutPumpEvents()));
m_pPumpEventsTimer->setInterval(20);
m_pPumpEventsTimer->start();
QOpenGLFramebufferObjectFormat fboFormat;
fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
fboFormat.setTextureTarget(GL_TEXTURE_2D);
m_pFbo.reset(new QOpenGLFramebufferObject(pWidget->width(), pWidget->height(), fboFormat));
vr::HmdVector2_t vecWindowSize = {
(float)pWidget->width(),
(float)pWidget->height()
};
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);
if (!vr::VROverlay()) {
QMessageBox::critical(nullptr, "OpenVR Advanced Settings Overlay", "Is OpenVR running?");
throw std::runtime_error(std::string("No Overlay interface"));
}
// Init controllers
steamVRTabController.initStage1();
chaperoneTabController.initStage1();
moveCenterTabController.initStage1();
fixFloorTabController.initStage1();
audioTabController.initStage1();
statisticsTabController.initStage1();
settingsTabController.initStage1();
void OverlayController::OnSceneChanged(const QList<QRectF>&) {
// skip rendering if the overlay isn't visible
if (!vr::VROverlay() || !vr::VROverlay()->IsOverlayVisible(m_ulOverlayHandle) && !vr::VROverlay()->IsOverlayVisible(m_ulOverlayThumbnailHandle))
return;
// Set qml context
qmlEngine->rootContext()->setContextProperty("applicationVersion", getVersionString());
qmlEngine->rootContext()->setContextProperty("vrRuntimePath", getVRRuntimePathUrl());
m_pOpenGLContext->makeCurrent(m_pOffscreenSurface.get());
m_pFbo->bind();
// Register qml singletons
qmlRegisterSingletonType<OverlayController>("matzman666.advsettings", 1, 0, "OverlayController", [](QQmlEngine*, QJSEngine*) {
QObject* obj = getInstance();
QQmlEngine::setObjectOwnership(obj, QQmlEngine::CppOwnership);
return obj;
});
qmlRegisterSingletonType<SteamVRTabController>("matzman666.advsettings", 1, 0, "SteamVRTabController", [](QQmlEngine*, QJSEngine*) {
QObject* obj = &getInstance()->steamVRTabController;
QQmlEngine::setObjectOwnership(obj, QQmlEngine::CppOwnership);
return obj;
});
qmlRegisterSingletonType<SteamVRTabController>("matzman666.advsettings", 1, 0, "ChaperoneTabController", [](QQmlEngine*, QJSEngine*) {
QObject* obj = &getInstance()->chaperoneTabController;
QQmlEngine::setObjectOwnership(obj, QQmlEngine::CppOwnership);
return obj;
});
qmlRegisterSingletonType<SteamVRTabController>("matzman666.advsettings", 1, 0, "MoveCenterTabController", [](QQmlEngine*, QJSEngine*) {
QObject* obj = &getInstance()->moveCenterTabController;
QQmlEngine::setObjectOwnership(obj, QQmlEngine::CppOwnership);
return obj;
});
qmlRegisterSingletonType<SteamVRTabController>("matzman666.advsettings", 1, 0, "FixFloorTabController", [](QQmlEngine*, QJSEngine*) {
QObject* obj = &getInstance()->fixFloorTabController;
QQmlEngine::setObjectOwnership(obj, QQmlEngine::CppOwnership);
return obj;
});
qmlRegisterSingletonType<SteamVRTabController>("matzman666.advsettings", 1, 0, "AudioTabController", [](QQmlEngine*, QJSEngine*) {
QObject* obj = &getInstance()->audioTabController;
QQmlEngine::setObjectOwnership(obj, QQmlEngine::CppOwnership);
return obj;
});
qmlRegisterSingletonType<SteamVRTabController>("matzman666.advsettings", 1, 0, "StatisticsTabController", [](QQmlEngine*, QJSEngine*) {
QObject* obj = &getInstance()->statisticsTabController;
QQmlEngine::setObjectOwnership(obj, QQmlEngine::CppOwnership);
return obj;
});
qmlRegisterSingletonType<SteamVRTabController>("matzman666.advsettings", 1, 0, "SettingsTabController", [](QQmlEngine*, QJSEngine*) {
QObject* obj = &getInstance()->settingsTabController;
QQmlEngine::setObjectOwnership(obj, QQmlEngine::CppOwnership);
return obj;
});
}
QOpenGLPaintDevice device(m_pFbo->size());
QPainter painter(&device);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
m_pScene->render(&painter);
void OverlayController::SetWidget(QQuickItem* quickItem, const std::string& name, const std::string& key) {
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.5f);
vr::VROverlay()->SetOverlayInputMethod(m_ulOverlayHandle, vr::VROverlayInputMethod_Mouse);
vr::VROverlay()->SetOverlayFlag(m_ulOverlayHandle, vr::VROverlayFlags_SendVRScrollEvents, true);
std::string thumbIconPath = QApplication::applicationDirPath().toStdString() + "\\res\\thumbicon.png";
if (QFile::exists(QString::fromStdString(thumbIconPath))) {
vr::VROverlay()->SetOverlayFromFile(m_ulOverlayThumbnailHandle, thumbIconPath.c_str());
} else {
LOG(ERROR) << "Could not find thumbnail icon \"" << thumbIconPath << "\"";
}
m_pFbo->release();
m_pPumpEventsTimer.reset(new QTimer());
connect(m_pPumpEventsTimer.get(), SIGNAL(timeout()), this, SLOT(OnTimeoutPumpEvents()));
m_pPumpEventsTimer->setInterval(20);
m_pPumpEventsTimer->start();
GLuint unTexture = m_pFbo->texture();
if (unTexture != 0) {
#if defined _WIN64 || defined _LP64
// To avoid any compiler warning because of cast to a larger pointer type (warning C4312 on VC)
vr::Texture_t texture = { (void*)((uint64_t)unTexture), vr::API_OpenGL, vr::ColorSpace_Auto };
#else
vr::Texture_t texture = { (void*)unTexture, vr::API_OpenGL, vr::ColorSpace_Auto };
// Too many render calls in too short time overwhelm Qt and an assertion gets thrown.
// Therefore we use an timer to delay render calls
m_pRenderTimer.reset(new QTimer());
m_pRenderTimer->setSingleShot(true);
m_pRenderTimer->setInterval(5);
connect(m_pRenderTimer.get(), SIGNAL(timeout()), this, SLOT(renderOverlay()));
QOpenGLFramebufferObjectFormat fboFormat;
fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
fboFormat.setTextureTarget(GL_TEXTURE_2D);
m_pFbo.reset(new QOpenGLFramebufferObject(quickItem->width(), quickItem->height(), fboFormat));
#ifndef DEBUG_DESKTOP_WINDOW
m_pRenderControl.reset(new QQuickRenderControl());
m_pWindow.reset(new QQuickWindow(m_pRenderControl.get()));
m_pWindow->setRenderTarget(m_pFbo.get());
quickItem->setParentItem(m_pWindow->contentItem());
m_pWindow->setGeometry(0, 0, quickItem->width(), quickItem->height());
m_pRenderControl->initialize(m_pOpenGLContext.get());
vr::HmdVector2_t vecWindowSize = {
(float)quickItem->width(),
(float)quickItem->height()
};
vr::VROverlay()->SetOverlayMouseScale(m_ulOverlayHandle, &vecWindowSize);
connect(m_pRenderControl.get(), SIGNAL(renderRequested()), this, SLOT(OnRenderRequest()));
connect(m_pRenderControl.get(), SIGNAL(sceneChanged()), this, SLOT(OnRenderRequest()));
#endif
vr::VROverlay()->SetOverlayTexture(m_ulOverlayHandle, &texture);
}
m_pOpenGLContext->functions()->glFlush(); // We need to flush otherwise the texture may be empty.
steamVRTabController.initStage2(this, m_pWindow.get());
chaperoneTabController.initStage2(this, m_pWindow.get());
moveCenterTabController.initStage2(this, m_pWindow.get());
fixFloorTabController.initStage2(this, m_pWindow.get());
audioTabController.initStage2(this, m_pWindow.get());
statisticsTabController.initStage2(this, m_pWindow.get());
settingsTabController.initStage2(this, m_pWindow.get());
}
void OverlayController::OnRenderRequest() {
if (!m_pRenderTimer->isActive()) {
m_pRenderTimer->start();
}
}
void OverlayController::renderOverlay() {
// skip rendering if the overlay isn't visible
if (!vr::VROverlay() || !vr::VROverlay()->IsOverlayVisible(m_ulOverlayHandle) && !vr::VROverlay()->IsOverlayVisible(m_ulOverlayThumbnailHandle))
return;
#ifndef DEBUG_DESKTOP_WINDOW
m_pRenderControl->polishItems();
m_pRenderControl->sync();
m_pRenderControl->render();
GLuint unTexture = m_pFbo->texture();
if (unTexture != 0) {
#if defined _WIN64 || defined _LP64
// To avoid any compiler warning because of cast to a larger pointer type (warning C4312 on VC)
vr::Texture_t texture = { (void*)((uint64_t)unTexture), vr::API_OpenGL, vr::ColorSpace_Auto };
#else
vr::Texture_t texture = { (void*)unTexture, vr::API_OpenGL, vr::ColorSpace_Auto };
#endif
vr::VROverlay()->SetOverlayTexture(m_ulOverlayHandle, &texture);
}
m_pOpenGLContext->functions()->glFlush(); // We need to flush otherwise the texture may be empty.*/
#endif
}
void OverlayController::OnTimeoutPumpEvents() {
if (!vr::VRSystem())
return;
void OverlayController::OnTimeoutPumpEvents() {
if (!vr::VRSystem())
return;
/*
// tell OpenVR to make some events for us
for( vr::TrackedDeviceIndex_t unDeviceId = 1; unDeviceId < vr::k_unControllerStateAxisCount; unDeviceId++ ) {
// tell OpenVR to make some events for us
/*for( vr::TrackedDeviceIndex_t unDeviceId = 1; unDeviceId < vr::k_unControllerStateAxisCount; unDeviceId++ ) {
if( vr::VROverlay()->HandleControllerOverlayInteractionAsMouse( m_ulOverlayHandle, unDeviceId ) ) {
break;
break;
}
}
*/
}*/
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());
steamVRTabController.eventLoopTick();
chaperoneTabController.eventLoopTick();
settingsTabController.eventLoopTick();
audioTabController.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))) {
switch (vrEvent.eventType) {
vr::VREvent_t vrEvent;
while (vr::VROverlay()->PollNextOverlayEvent(m_ulOverlayHandle, &vrEvent, sizeof(vrEvent))) {
switch (vrEvent.eventType) {
case vr::VREvent_MouseMove: {
QPointF ptNewMouse(vrEvent.data.mouse.x, vrEvent.data.mouse.y);
QPoint ptGlobal = ptNewMouse.toPoint();
QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
mouseEvent.setWidget(NULL);
mouseEvent.setPos(ptNewMouse);
mouseEvent.setScenePos(ptGlobal);
mouseEvent.setScreenPos(ptGlobal);
mouseEvent.setLastPos(m_ptLastMouse);
mouseEvent.setLastScenePos(m_pWidget->mapToGlobal(m_ptLastMouse.toPoint()));
mouseEvent.setLastScreenPos(m_pWidget->mapToGlobal(m_ptLastMouse.toPoint()));
mouseEvent.setButtons(m_lastMouseButtons);
mouseEvent.setButton(Qt::NoButton);
mouseEvent.setModifiers(0);
mouseEvent.setAccepted(false);
m_ptLastMouse = ptNewMouse;
QApplication::sendEvent(m_pScene.get(), &mouseEvent);
OnSceneChanged(QList<QRectF>());
QPoint ptNewMouse(vrEvent.data.mouse.x, vrEvent.data.mouse.y);
if (ptNewMouse != m_ptLastMouse) {
QMouseEvent mouseEvent( QEvent::MouseMove, ptNewMouse, m_pWindow->mapToGlobal(ptNewMouse), Qt::NoButton, m_lastMouseButtons, 0 );
m_ptLastMouse = ptNewMouse;
QCoreApplication::sendEvent(m_pWindow.get(), &mouseEvent);
OnRenderRequest();
}
}
break;
break;
case vr::VREvent_MouseButtonDown: {
QPoint ptNewMouse(vrEvent.data.mouse.x, vrEvent.data.mouse.y);
Qt::MouseButton button = vrEvent.data.mouse.button == vr::VRMouseButton_Right ? Qt::RightButton : Qt::LeftButton;
m_lastMouseButtons |= button;
QPoint ptGlobal = m_ptLastMouse.toPoint();
QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMousePress);
mouseEvent.setWidget(NULL);
mouseEvent.setPos(m_ptLastMouse);
mouseEvent.setButtonDownPos(button, m_ptLastMouse);
mouseEvent.setButtonDownScenePos(button, ptGlobal);
mouseEvent.setButtonDownScreenPos(button, ptGlobal);
mouseEvent.setScenePos(ptGlobal);
mouseEvent.setScreenPos(ptGlobal);
mouseEvent.setLastPos(m_ptLastMouse);
mouseEvent.setLastScenePos(ptGlobal);
mouseEvent.setLastScreenPos(ptGlobal);
mouseEvent.setButtons(m_lastMouseButtons);
mouseEvent.setButton(button);
mouseEvent.setModifiers(0);
mouseEvent.setAccepted(false);
QApplication::sendEvent(m_pScene.get(), &mouseEvent);
QMouseEvent mouseEvent(QEvent::MouseButtonPress, ptNewMouse, m_pWindow->mapToGlobal(ptNewMouse), button, m_lastMouseButtons, 0);
QCoreApplication::sendEvent(m_pWindow.get(), &mouseEvent);
}
break;
break;
case vr::VREvent_MouseButtonUp: {
QPoint ptNewMouse(vrEvent.data.mouse.x, vrEvent.data.mouse.y);
Qt::MouseButton button = vrEvent.data.mouse.button == vr::VRMouseButton_Right ? Qt::RightButton : Qt::LeftButton;
m_lastMouseButtons &= ~button;
QPoint ptGlobal = m_ptLastMouse.toPoint();
QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseRelease);
mouseEvent.setWidget(NULL);
mouseEvent.setPos(m_ptLastMouse);
mouseEvent.setScenePos(ptGlobal);
mouseEvent.setScreenPos(ptGlobal);
mouseEvent.setLastPos(m_ptLastMouse);
mouseEvent.setLastScenePos(ptGlobal);
mouseEvent.setLastScreenPos(ptGlobal);
mouseEvent.setButtons(m_lastMouseButtons);
mouseEvent.setButton(button);
mouseEvent.setModifiers(0);
mouseEvent.setAccepted(false);
QApplication::sendEvent(m_pScene.get(), &mouseEvent);
QMouseEvent mouseEvent(QEvent::MouseButtonRelease, ptNewMouse, m_pWindow->mapToGlobal(ptNewMouse), button, m_lastMouseButtons, 0);
QCoreApplication::sendEvent(m_pWindow.get(), &mouseEvent);
}
break;
break;
case vr::VREvent_Scroll: {
// Wheel speed is defined as 1/8 of a degree
QWheelEvent wheelEvent(m_ptLastMouse, m_pWindow->mapToGlobal(m_ptLastMouse), QPoint(),
QPoint(vrEvent.data.scroll.xdelta * 360.0f * 8.0f, vrEvent.data.scroll.ydelta * 360.0f * 8.0f),
0, Qt::Vertical, m_lastMouseButtons, 0);
QCoreApplication::sendEvent(m_pWindow.get(), &wheelEvent);
}
break;
case vr::VREvent_OverlayShown: {
m_pWidget->repaint();
UpdateWidget();
m_pWindow->update();
}
break;
break;
case vr::VREvent_Quit: {
LOG(INFO) << "Received quit request.";
vr::VRSystem()->AcknowledgeQuit_Exiting(); // Let us buy some time just in case
moveCenterTabController.MoveCenterResetClicked();
moveCenterTabController.reset();
QApplication::exit();
}
break;
break;
case vr::VREvent_DashboardActivated: {
LOG(INFO) << "Dashboard activated";
LOG(DEBUG) << "Dashboard activated";
dashboardVisible = true;
}
break;
break;
case vr::VREvent_DashboardDeactivated: {
LOG(INFO) << "Dashboard deactivated";
LOG(DEBUG) << "Dashboard deactivated";
dashboardVisible = false;
}
break;
}
}
break;
if (m_ulOverlayThumbnailHandle != vr::k_ulOverlayHandleInvalid) {
while (vr::VROverlay()->PollNextOverlayEvent(m_ulOverlayThumbnailHandle, &vrEvent, sizeof(vrEvent))) {
switch (vrEvent.eventType) {
case vr::VREvent_KeyboardDone: {
char keyboardBuffer[1024];
vr::VROverlay()->GetKeyboardText(keyboardBuffer, 1024);
emit keyBoardInputSignal(QString(keyboardBuffer), vrEvent.data.keyboard.uUserValue);
}
break;
}
}
if (m_ulOverlayThumbnailHandle != vr::k_ulOverlayHandleInvalid) {
while (vr::VROverlay()->PollNextOverlayEvent(m_ulOverlayThumbnailHandle, &vrEvent, sizeof(vrEvent))) {
switch (vrEvent.eventType) {
case vr::VREvent_OverlayShown: {
m_pWidget->repaint();
UpdateWidget();
}
break;
m_pWindow->update();
}
break;
}
}
}
}
void OverlayController::UpdateWidget() {
steamVRTabController.UpdateTab();
chaperoneTabController.UpdateTab();
moveCenterTabController.UpdateTab();
fixFloorTabController.UpdateTab();
statisticsTabController.UpdateTab();
settingsTabController.UpdateTab();
}
void OverlayController::AddOffsetToUniverseCenter(vr::ETrackingUniverseOrigin universe, unsigned axisId, float offset, bool adjustBounds, bool commit) {
if (offset != 0.0f) {
if (commit) {
vr::VRChaperoneSetup()->RevertWorkingCopy();
}
vr::HmdMatrix34_t curPos;
if (universe == vr::TrackingUniverseStanding) {
vr::VRChaperoneSetup()->GetWorkingStandingZeroPoseToRawTrackingPose(&curPos);
} else {
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 OverlayController::AddOffsetToUniverseCenter(vr::ETrackingUniverseOrigin universe, unsigned axisId, float offset, bool adjustBounds, bool commit) {
if (offset != 0.0f) {
if (commit) {
vr::VRChaperoneSetup()->RevertWorkingCopy();
}
vr::HmdMatrix34_t curPos;
if (universe == vr::TrackingUniverseStanding) {
vr::VRChaperoneSetup()->GetWorkingStandingZeroPoseToRawTrackingPose(&curPos);
} else {
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 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];
}
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];
}
}
newPos.m[0][3] = curPos.m[0][3];
newPos.m[1][3] = curPos.m[1][3];
newPos.m[2][3] = curPos.m[2][3];
}
newPos.m[0][3] = curPos.m[0][3];
newPos.m[1][3] = curPos.m[1][3];
newPos.m[2][3] = curPos.m[2][3];
if (universe == vr::TrackingUniverseStanding) {
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);
}
} else {
vr::VRChaperoneSetup()->SetWorkingSeatedZeroPoseToRawTrackingPose(&newPos);
}
if (adjustBounds && universe == vr::TrackingUniverseStanding) {
RotateCollisionBounds(-yAngle, false);
}
}
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;
}
}
vr::VRChaperoneSetup()->SetWorkingCollisionBoundsInfo(collisionBounds, collisionBoundsCount);
delete collisionBounds;
}
if (commit && collisionBoundsCount > 0) {
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
}
}
}
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);
}
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;
}
}
vr::VRChaperoneSetup()->SetWorkingCollisionBoundsInfo(collisionBounds, collisionBoundsCount);
delete collisionBounds;
}
if (commit && collisionBoundsCount > 0) {
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
}
}
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);
}
}
QString OverlayController::getVersionString() {
return QString(applicationVersionString);
}
QUrl OverlayController::getVRRuntimePathUrl() {
return m_runtimePathUrl;
}
void OverlayController::showKeyboard(QString existingText, unsigned long userValue) {
vr::VROverlay()->ShowKeyboardForOverlay(m_ulOverlayHandle, vr::k_EGamepadTextInputModeNormal, vr::k_EGamepadTextInputLineModeSingleLine, "Advanced Settings Overlay", 1024, existingText.toStdString().c_str(), false, userValue);
}
} // namespace advconfig
+49 -13
View File
@@ -9,10 +9,16 @@
#include <QVector>
#include <QVector2D>
#include <QVector3D>
#include <QObject>
#include <QSettings>
#include <QQmlEngine>
#include <QtGui/QOpenGLContext>
#include <QtWidgets/QGraphicsScene>
#include <QOffscreenSurface>
#include <QOpenGLFramebufferObject>
#include <QQuickWindow>
#include <QQuickItem>
#include <QQuickRenderControl>
#include <memory>
#include "logging.h"
@@ -20,70 +26,100 @@
#include "tabcontrollers/ChaperoneTabController.h"
#include "tabcontrollers/MoveCenterTabController.h"
#include "tabcontrollers/FixFloorTabController.h"
#include "tabcontrollers/AudioTabController.h"
#include "tabcontrollers/StatisticsTabController.h"
#include "tabcontrollers/SettingsTabController.h"
// Show a window on the desktop instead of an overlay in vr
//#define DEBUG_DESKTOP_WINDOW
// application namespace
namespace advsettings {
// forward declaration
class OverlayWidget;
class OverlayController : public QObject {
Q_OBJECT
public:
static constexpr const char* applicationKey = "matzman666.AdvancedSettings";
static constexpr const char* applicationName = "Advanced Settings";
static constexpr const char* applicationVersionString = "v1.1";
static constexpr const char* applicationVersionString = "v2.0";
private:
OverlayWidget *m_pWidget;
vr::VROverlayHandle_t m_ulOverlayHandle = vr::k_ulOverlayHandleInvalid;
vr::VROverlayHandle_t m_ulOverlayThumbnailHandle = vr::k_ulOverlayHandleInvalid;
std::unique_ptr<QQuickWindow> m_pWindow;
std::unique_ptr<QOpenGLContext> m_pOpenGLContext;
std::unique_ptr<QGraphicsScene> m_pScene;
std::unique_ptr<QOpenGLFramebufferObject> m_pFbo;
std::unique_ptr<QQuickRenderControl> m_pRenderControl;
std::unique_ptr<QOffscreenSurface> m_pOffscreenSurface;
std::unique_ptr<QTimer> m_pPumpEventsTimer;
std::unique_ptr<QTimer> m_pRenderTimer;
bool dashboardVisible = false;
QPointF m_ptLastMouse;
QPoint m_ptLastMouse;
Qt::MouseButtons m_lastMouseButtons = 0;
QUrl m_runtimePathUrl;
SteamVRTabController steamVRTabController;
ChaperoneTabController chaperoneTabController;
MoveCenterTabController moveCenterTabController;
FixFloorTabController fixFloorTabController;
AudioTabController audioTabController;
StatisticsTabController statisticsTabController;
SettingsTabController settingsTabController;
public:
private:
OverlayController() : QObject() {}
public:
virtual ~OverlayController();
void Init();
void Init(QQmlEngine* qmlEngine);
bool isDashboardVisible() {
return dashboardVisible;
}
void SetWidget(OverlayWidget *pWidget, const std::string& name, const std::string& key = "");
void SetWidget(QQuickItem* quickItem, const std::string& name, const std::string& key = "");
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
Q_INVOKABLE QString getVersionString();
Q_INVOKABLE QUrl getVRRuntimePathUrl();
public slots:
void OnSceneChanged( const QList<QRectF>& );
void renderOverlay();
void OnRenderRequest();
void OnTimeoutPumpEvents();
void UpdateWidget();
void showKeyboard(QString existingText, unsigned long userValue = 0);
signals:
void keyBoardInputSignal(QString input, unsigned long userValue = 0);
private:
static QSettings* _appSettings;
static std::unique_ptr<OverlayController> singleton;
public:
static OverlayController* getInstance() {
if (!singleton) {
singleton.reset(new advsettings::OverlayController());
}
return singleton.get();
}
static QSettings* appSettings() { return _appSettings; }
static void setAppSettings(QSettings* settings) { _appSettings = settings; }
};
} // namespace advsettings
-12
View File
@@ -1,12 +0,0 @@
#include "overlaywidget.h"
#include "ui_overlaywidget.h"
// application namespace
namespace advsettings {
OverlayWidget::OverlayWidget(QWidget *parent) :
QWidget(parent), ui(new Ui::OverlayWidget) {
ui->setupUi(this);
}
} // namespace advsettings
-27
View File
@@ -1,27 +0,0 @@
#pragma once
#include <QWidget>
#include <memory>
// forward declaration
namespace Ui { class OverlayWidget; }
// application namespace
namespace advsettings {
class OverlayWidget : public QWidget {
Q_OBJECT
public:
std::unique_ptr<Ui::OverlayWidget> ui;
explicit OverlayWidget(QWidget *parent = 0);
private slots:
};
} // namespace advsettings
+35
View File
@@ -0,0 +1,35 @@
#pragma once
#include <string>
// application namespace
namespace advsettings {
class AudioTabController;
class AudioManager
{
public:
virtual ~AudioManager() {};
virtual void init(AudioTabController* controller) = 0;
virtual void setMirrorDevice(const std::string& id) = 0;
virtual void deleteMirrorDevice() = 0;
virtual bool isMirrorValid() = 0;
virtual std::string getMirrorDevName() = 0;
virtual float getMirrorVolume() = 0;
virtual bool setMirrorVolume(float value) = 0;
virtual bool getMirrorMuted() = 0;
virtual bool setMirrorMuted(bool value) = 0;
virtual bool isMicValid() = 0;
virtual std::string getMicDevName() = 0;
virtual float getMicVolume() = 0;
virtual bool setMicVolume(float value) = 0;
virtual bool getMicMuted() = 0;
virtual bool setMicMuted(bool value) = 0;
};
}
+680
View File
@@ -0,0 +1,680 @@
#include "AudioTabController.h"
#include <QQuickWindow>
#include <QApplication>
#include "../overlaycontroller.h"
#include "audiomanager/AudioManagerWindows.h"
// application namespace
namespace advsettings {
void AudioTabController::initStage1() {
vr::EVRSettingsError vrSettingsError;
audioManager.reset(new AudioManagerWindows());
audioManager->init(this);
char mirrorDeviceId[1024];
vr::VRSettings()->GetString(vr::k_pch_audio_Section, vr::k_pch_audio_OnPlaybackMirrorDevice_String, mirrorDeviceId, 1024, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not read \"" << vr::k_pch_audio_OnPlaybackMirrorDevice_String << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
}
audioManager->setMirrorDevice(mirrorDeviceId);
lastMirrorDevId = mirrorDeviceId;
m_micPresent = audioManager->isMicValid();
m_micVolume = audioManager->getMicVolume();
m_micMuted = audioManager->getMicMuted();
m_micDevName = QString::fromStdString(audioManager->getMicDevName());
m_mirrorPresent = audioManager->isMirrorValid();
m_mirrorVolume = audioManager->getMirrorVolume();
m_mirrorMuted = audioManager->getMirrorMuted();
m_mirrorDevName = QString::fromStdString(audioManager->getMirrorDevName());
reloadPttProfiles();
reloadPttConfig();
eventLoopTick();
}
void AudioTabController::initStage2(OverlayController * parent, QQuickWindow * widget) {
this->parent = parent;
this->widget = widget;
std::string notifKey = std::string(OverlayController::applicationKey) + ".pptnotification";
vr::VROverlayError overlayError = vr::VROverlay()->CreateOverlay(notifKey.c_str(), notifKey.c_str(), &m_ulNotificationOverlayHandle);
if (overlayError == vr::VROverlayError_None) {
std::string notifIconPath = QApplication::applicationDirPath().toStdString() + "/res/qml/ptt_notification.png";
if (QFile::exists(QString::fromStdString(notifIconPath))) {
vr::VROverlay()->SetOverlayFromFile(m_ulNotificationOverlayHandle, notifIconPath.c_str());
vr::VROverlay()->SetOverlayWidthInMeters(m_ulNotificationOverlayHandle, 0.02f);
vr::HmdMatrix34_t notificationTransform = {
1.0f, 0.0f, 0.0f, 0.12f,
0.0f, 1.0f, 0.0f, 0.08f,
0.0f, 0.0f, 1.0f, -0.3f
};
vr::VROverlay()->SetOverlayTransformTrackedDeviceRelative(m_ulNotificationOverlayHandle, vr::k_unTrackedDeviceIndex_Hmd, &notificationTransform);
} else {
LOG(ERROR) << "Could not find notification icon \"" << notifIconPath << "\"";
}
} else {
LOG(ERROR) << "Could not create ptt notification overlay: " << vr::VROverlay()->GetOverlayErrorNameFromEnum(overlayError);
}
}
bool AudioTabController::mirrorPresent() const {
return m_mirrorPresent;
}
QString AudioTabController::mirrorDevName() const {
return m_mirrorDevName;
}
float AudioTabController::mirrorVolume() const {
return m_mirrorVolume;
}
bool AudioTabController::mirrorMuted() const {
return m_mirrorMuted;
}
bool AudioTabController::micPresent() const {
return m_micPresent;
}
QString AudioTabController::micDevName() const {
return m_micDevName;
}
float AudioTabController::micVolume() const {
return m_micVolume;
}
bool AudioTabController::micMuted() const {
return m_micMuted;
}
bool AudioTabController::pttEnabled() const {
return m_pttEnabled;
}
bool AudioTabController::pttActive() const {
return m_pttActive;
}
bool AudioTabController::pttShowNotification() const {
return m_pttShowNotification;
}
bool AudioTabController::pttLeftControllerEnabled() const {
return m_pttLeftControllerEnabled;
}
bool AudioTabController::pttRightControllerEnabled() const {
return m_pttRightControllerEnabled;
}
void AudioTabController::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 AudioTabController::reloadPttProfiles() {
pttProfiles.clear();
auto settings = OverlayController::appSettings();
settings->beginGroup("audioSettings");
auto profileCount = settings->beginReadArray("pttProfiles");
for (int i = 0; i < profileCount; i++) {
settings->setArrayIndex(i);
pttProfiles.emplace_back();
auto& entry = pttProfiles[i];
entry.profileName = settings->value("profileName").toString().toStdString();
entry.showNotification = settings->value("showNotification", true).toBool();
entry.leftControllerEnabled = settings->value("leftControllerEnabled", false).toBool();
entry.rightControllerEnabled = settings->value("rightControllerEnabled", false).toBool();
entry.controllerConfigs[0].digitalButtons = settings->value("digitalButtons_0").toList();
uint64_t buttonMask = 0;
for (auto b : entry.controllerConfigs[0].digitalButtons) {
buttonMask |= vr::ButtonMaskFromId((vr::EVRButtonId)b.toInt());
}
entry.controllerConfigs[0].digitalButtonMask = buttonMask;
entry.controllerConfigs[0].triggerMode = settings->value("triggerMode_0", 0).toUInt();
entry.controllerConfigs[0].touchpadMode = settings->value("touchpadMode_0", 0).toUInt();
entry.controllerConfigs[0].touchpadAreas = settings->value("touchPadAreas_0", 0).toUInt();
entry.controllerConfigs[1].digitalButtons = settings->value("digitalButtons_1").toList();
buttonMask = 0;
for (auto b : entry.controllerConfigs[1].digitalButtons) {
buttonMask |= vr::ButtonMaskFromId((vr::EVRButtonId)b.toInt());
}
entry.controllerConfigs[1].digitalButtonMask = buttonMask;
entry.controllerConfigs[1].triggerMode = settings->value("triggerMode_1", 0).toUInt();
entry.controllerConfigs[1].touchpadMode = settings->value("touchpadMode_1", 0).toUInt();
entry.controllerConfigs[1].touchpadAreas = settings->value("touchPadAreas_1", 0).toUInt();
}
settings->endArray();
settings->endGroup();
}
void AudioTabController::savePttProfiles() {
auto settings = OverlayController::appSettings();
settings->beginGroup("audioSettings");
settings->beginWriteArray("pttProfiles");
unsigned i = 0;
for (auto& p : pttProfiles) {
settings->setArrayIndex(i);
settings->setValue("profileName", QString::fromStdString(p.profileName));
settings->setValue("showNotification", p.showNotification);
settings->setValue("leftControllerEnabled", p.leftControllerEnabled);
settings->setValue("rightControllerEnabled", p.rightControllerEnabled);
settings->setValue("digitalButtons_0", p.controllerConfigs[0].digitalButtons);
settings->setValue("triggerMode_0", p.controllerConfigs[0].triggerMode);
settings->setValue("touchpadMode_0", p.controllerConfigs[0].touchpadMode);
settings->setValue("touchPadAreas_0", p.controllerConfigs[0].touchpadAreas);
settings->setValue("digitalButtons_1", p.controllerConfigs[1].digitalButtons);
settings->setValue("triggerMode_1", p.controllerConfigs[1].triggerMode);
settings->setValue("touchpadMode_1", p.controllerConfigs[1].touchpadMode);
settings->setValue("touchPadAreas_1", p.controllerConfigs[1].touchpadAreas);
i++;
}
settings->endArray();
settings->endGroup();
}
void AudioTabController::reloadPttConfig() {
std::lock_guard<std::recursive_mutex> lock(eventLoopMutex);
auto settings = OverlayController::appSettings();
settings->beginGroup("audioSettings");
setPttEnabled(settings->value("pttEnabled", false).toBool(), true, false);
setPttLeftControllerEnabled(settings->value("pttLeftControllerEnabled", false).toBool(), true, false);
setPttRightControllerEnabled(settings->value("pttRightControllerEnabled", false).toBool(), true, false);
setPttShowNotification(settings->value("pttShowNotification", true).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 AudioTabController::savePttConfig() {
auto settings = OverlayController::appSettings();
settings->beginGroup("audioSettings");
settings->setValue("pttEnabled", pttEnabled());
settings->setValue("pttLeftControllerEnabled", pttLeftControllerEnabled());
settings->setValue("pttRightControllerEnabled", pttRightControllerEnabled());
settings->setValue("pttShowNotification", pttShowNotification());
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();
}
void logControllerState(const vr::VRControllerState_t& state, const std::string& prefix) {
if (state.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_ApplicationMenu)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_ApplicationMenu) << " pressed";
}
if (state.ulButtonTouched & vr::ButtonMaskFromId(vr::k_EButton_ApplicationMenu)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_ApplicationMenu) << " touched";
}
if (state.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_Grip)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Grip) << " pressed";
}
if (state.ulButtonTouched & vr::ButtonMaskFromId(vr::k_EButton_Grip)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Grip) << " touched";
}
if (state.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_DPad_Left)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_DPad_Left) << " pressed";
}
if (state.ulButtonTouched & vr::ButtonMaskFromId(vr::k_EButton_DPad_Left)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_DPad_Left) << " touched";
}
if (state.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_DPad_Up)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_DPad_Up) << " pressed";
}
if (state.ulButtonTouched & vr::ButtonMaskFromId(vr::k_EButton_DPad_Up)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_DPad_Up) << " touched";
}
if (state.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_DPad_Right)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_DPad_Right) << " pressed";
}
if (state.ulButtonTouched & vr::ButtonMaskFromId(vr::k_EButton_DPad_Right)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_DPad_Right) << " touched";
}
if (state.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_DPad_Down)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_DPad_Down) << " pressed";
}
if (state.ulButtonTouched & vr::ButtonMaskFromId(vr::k_EButton_DPad_Down)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_DPad_Down) << " touched";
}
if (state.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_A)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_A) << " pressed";
}
if (state.ulButtonTouched & vr::ButtonMaskFromId(vr::k_EButton_A)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_A) << " touched";
}
if (state.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_Axis0)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis0) << " pressed";
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis0) << " x: " << state.rAxis[0].x << " y: " << state.rAxis[0].y;
}
if (state.ulButtonTouched & vr::ButtonMaskFromId(vr::k_EButton_Axis0)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis0) << " touched";
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis0) << " x: " << state.rAxis[0].x << " y: " << state.rAxis[0].y;
}
if (state.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_Axis1)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis1) << " pressed";
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis1) << " x: " << state.rAxis[1].x << " y: " << state.rAxis[0].y;
}
if (state.ulButtonTouched & vr::ButtonMaskFromId(vr::k_EButton_Axis1)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis1) << " touched";
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis1) << " x: " << state.rAxis[1].x << " y: " << state.rAxis[0].y;
}
if (state.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_Axis2)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis2) << " pressed";
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis2) << " x: " << state.rAxis[2].x << " y: " << state.rAxis[0].y;
}
if (state.ulButtonTouched & vr::ButtonMaskFromId(vr::k_EButton_Axis2)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis2) << " touched";
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis2) << " x: " << state.rAxis[2].x << " y: " << state.rAxis[0].y;
}
if (state.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_Axis3)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis3) << " pressed";
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis3) << " x: " << state.rAxis[3].x << " y: " << state.rAxis[0].y;
}
if (state.ulButtonTouched & vr::ButtonMaskFromId(vr::k_EButton_Axis3)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis3) << " touched";
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis3) << " x: " << state.rAxis[3].x << " y: " << state.rAxis[0].y;
}
if (state.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_Axis4)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis4) << " pressed";
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis4) << " x: " << state.rAxis[4].x << " y: " << state.rAxis[0].y;
}
if (state.ulButtonTouched & vr::ButtonMaskFromId(vr::k_EButton_Axis4)) {
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis4) << " touched";
LOG(INFO) << prefix << vr::VRSystem()->GetButtonIdNameFromEnum(vr::k_EButton_Axis4) << " x: " << state.rAxis[4].x << " y: " << state.rAxis[0].y;
}
}
void AudioTabController::eventLoopTick() {
if (!eventLoopMutex.try_lock()) {
return;
}
if (settingsUpdateCounter >= 50) {
vr::EVRSettingsError vrSettingsError;
char mirrorDeviceId[1024];
vr::VRSettings()->GetString(vr::k_pch_audio_Section, vr::k_pch_audio_OnPlaybackMirrorDevice_String, mirrorDeviceId, 1024, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not read \"" << vr::k_pch_audio_OnPlaybackMirrorDevice_String << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
}
if (lastMirrorDevId.compare(mirrorDeviceId) != 0) {
audioManager->setMirrorDevice(mirrorDeviceId);
if (audioManager->isMirrorValid()) {
if (!m_mirrorPresent) {
m_mirrorPresent = true;
emit mirrorPresentChanged(m_mirrorPresent);
}
m_mirrorDevName = QString::fromStdString(audioManager->getMirrorDevName());
emit mirrorDevNameChanged(m_mirrorDevName);
} else if (m_mirrorPresent) {
m_mirrorPresent = false;
emit mirrorPresentChanged(m_mirrorPresent);
}
lastMirrorDevId = mirrorDeviceId;
}
if (m_mirrorPresent) {
setMirrorVolume(audioManager->getMirrorVolume());
setMirrorMuted(audioManager->getMirrorMuted());
}
if (m_micPresent) {
setMicVolume(audioManager->getMicVolume());
setMicMuted(audioManager->getMicMuted());
}
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)) {
//logControllerState(state, "Left ");
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)) {
//logControllerState(state, "Right ");
newState |= handleControllerState(state, m_pttControllerConfigs + 1);
}
}
}
if (newState && !m_pttActive) {
if (audioManager && audioManager->isMicValid()) {
m_pttActive = true;
setMicMuted(false);
if (m_pttShowNotification && m_ulNotificationOverlayHandle != vr::k_ulOverlayHandleInvalid) {
vr::VROverlay()->ShowOverlay(m_ulNotificationOverlayHandle);
}
emit pttActiveChanged(m_pttActive);
}
} else if (!newState && m_pttActive) {
if (audioManager && audioManager->isMicValid()) {
m_pttActive = false;
setMicMuted(true);
if (m_pttShowNotification && m_ulNotificationOverlayHandle != vr::k_ulOverlayHandleInvalid) {
vr::VROverlay()->HideOverlay(m_ulNotificationOverlayHandle);
}
emit pttActiveChanged(m_pttActive);
}
}
}
eventLoopMutex.unlock();
}
void AudioTabController::addPttProfile(QString name) {
auto i = pttProfiles.size();
pttProfiles.emplace_back();
auto& profile = pttProfiles[i];
profile.profileName = name.toStdString();
profile.showNotification = m_pttShowNotification;
profile.leftControllerEnabled = m_pttLeftControllerEnabled;
profile.rightControllerEnabled = m_pttRightControllerEnabled;
profile.controllerConfigs[0].digitalButtons = m_pttControllerConfigs[0].digitalButtons;
profile.controllerConfigs[0].digitalButtonMask = m_pttControllerConfigs[0].digitalButtonMask;
profile.controllerConfigs[0].triggerMode = m_pttControllerConfigs[0].triggerMode;
profile.controllerConfigs[0].touchpadMode = m_pttControllerConfigs[0].touchpadMode;
profile.controllerConfigs[0].touchpadAreas = m_pttControllerConfigs[0].touchpadAreas;
profile.controllerConfigs[1].digitalButtons = m_pttControllerConfigs[1].digitalButtons;
profile.controllerConfigs[1].digitalButtonMask = m_pttControllerConfigs[1].digitalButtonMask;
profile.controllerConfigs[1].triggerMode = m_pttControllerConfigs[1].triggerMode;
profile.controllerConfigs[1].touchpadMode = m_pttControllerConfigs[1].touchpadMode;
profile.controllerConfigs[1].touchpadAreas = m_pttControllerConfigs[1].touchpadAreas;
savePttProfiles();
OverlayController::appSettings()->sync();
emit pttProfilesUpdated();
}
void AudioTabController::applyPttProfile(unsigned index) {
std::lock_guard<std::recursive_mutex> lock(eventLoopMutex);
if (index < pttProfiles.size()) {
auto& profile = pttProfiles[index];
setPttShowNotification(profile.showNotification);
setPttLeftControllerEnabled(profile.leftControllerEnabled);
setPttRightControllerEnabled(profile.rightControllerEnabled);
m_pttControllerConfigs[0].digitalButtons = profile.controllerConfigs[0].digitalButtons;
m_pttControllerConfigs[0].digitalButtonMask = profile.controllerConfigs[0].digitalButtonMask;
m_pttControllerConfigs[0].triggerMode = profile.controllerConfigs[0].triggerMode;
m_pttControllerConfigs[0].touchpadMode = profile.controllerConfigs[0].touchpadMode;
m_pttControllerConfigs[0].touchpadAreas = profile.controllerConfigs[0].touchpadAreas;
m_pttControllerConfigs[1].digitalButtons = profile.controllerConfigs[1].digitalButtons;
m_pttControllerConfigs[1].digitalButtonMask = profile.controllerConfigs[1].digitalButtonMask;
m_pttControllerConfigs[1].triggerMode = profile.controllerConfigs[1].triggerMode;
m_pttControllerConfigs[1].touchpadMode = profile.controllerConfigs[1].touchpadMode;
m_pttControllerConfigs[1].touchpadAreas = profile.controllerConfigs[1].touchpadAreas;
}
}
void AudioTabController::deletePttProfile(unsigned index) {
if (index < pttProfiles.size()) {
auto pos = pttProfiles.begin() + index;
pttProfiles.erase(pos);
savePttProfiles();
OverlayController::appSettings()->sync();
emit pttProfilesUpdated();
}
}
QVariantList AudioTabController::pttDigitalButtons(unsigned controller) {
if (controller < 2) {
return m_pttControllerConfigs[controller].digitalButtons;
}
return QVariantList();
}
unsigned long AudioTabController::pttDigitalButtonMask(unsigned controller) {
if (controller < 2) {
return m_pttControllerConfigs[controller].digitalButtonMask;
}
return 0;
}
unsigned AudioTabController::pttTouchpadMode(unsigned controller) {
if (controller < 2) {
return m_pttControllerConfigs[controller].touchpadMode;
}
return 0;
}
unsigned AudioTabController::pttTriggerMode(unsigned controller) {
if (controller < 2) {
return m_pttControllerConfigs[controller].triggerMode;
}
return 0;
}
unsigned AudioTabController::pttTouchpadArea(unsigned controller) {
if (controller < 2) {
return m_pttControllerConfigs[controller].touchpadAreas;
}
return 0;
}
unsigned AudioTabController::getPttProfileCount() {
return (unsigned)pttProfiles.size();
}
QString AudioTabController::getPttProfileName(unsigned index) {
if (index < pttProfiles.size()) {
return QString::fromStdString(pttProfiles[index].profileName);
}
return "";
}
void AudioTabController::setMirrorVolume(float value, bool notify) {
std::lock_guard<std::recursive_mutex> lock(eventLoopMutex);
if (value != m_mirrorVolume) {
m_mirrorVolume = value;
if (audioManager->isMirrorValid()) {
audioManager->setMirrorVolume(value);
}
if (notify) {
emit mirrorVolumeChanged(value);
}
}
}
void AudioTabController::setMirrorMuted(bool value, bool notify) {
std::lock_guard<std::recursive_mutex> lock(eventLoopMutex);
if (value != m_mirrorMuted) {
m_mirrorMuted = value;
if (audioManager->isMirrorValid()) {
audioManager->setMirrorMuted(value);
}
if (notify) {
emit mirrorMutedChanged(value);
}
}
}
void AudioTabController::setMicVolume(float value, bool notify) {
std::lock_guard<std::recursive_mutex> lock(eventLoopMutex);
if (value != m_micVolume) {
m_micVolume = value;
if (audioManager->isMicValid()) {
audioManager->setMicVolume(value);
}
if (notify) {
emit micVolumeChanged(value);
}
}
}
void AudioTabController::setMicMuted(bool value, bool notify) {
std::lock_guard<std::recursive_mutex> lock(eventLoopMutex);
if (value != m_micMuted) {
m_micMuted = value;
if (audioManager->isMicValid()) {
audioManager->setMicMuted(value);
}
if (notify) {
emit micMutedChanged(value);
}
}
}
void AudioTabController::setPttEnabled(bool value, bool notify, bool save) {
std::lock_guard<std::recursive_mutex> lock(eventLoopMutex);
if (value != m_pttEnabled) {
m_pttEnabled = value;
if (value) {
setMicMuted(true);
} else {
setMicMuted(false);
}
if (notify) {
emit pttEnabledChanged(value);
}
if (save) {
savePttConfig();
}
}
}
void AudioTabController::setPttShowNotification(bool value, bool notify, bool save) {
std::lock_guard<std::recursive_mutex> lock(eventLoopMutex);
if (value != m_pttShowNotification) {
m_pttShowNotification = value;
if (notify) {
emit pttShowNotificationChanged(value);
}
if (save) {
savePttConfig();
}
}
}
void AudioTabController::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();
}
}
}
void AudioTabController::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 AudioTabController::onNewRecordingDevice() {
if (audioManager->isMicValid()) {
if (!m_micPresent) {
m_micPresent = true;
emit micPresentChanged(m_micPresent);
}
setMicVolume(audioManager->getMicVolume());
setMicMuted(audioManager->getMicMuted());
m_micDevName = QString::fromStdString(audioManager->getMicDevName());
emit micDevNameChanged(m_micDevName);
} else {
if (m_micPresent) {
m_micPresent = false;
emit micPresentChanged(m_micPresent);
}
}
}
} // namespace advconfig
+169
View File
@@ -0,0 +1,169 @@
#pragma once
#include "AudioManager.h"
#include <QObject>
#include <QString>
#include <QVariant>
#include <string>
#include <memory>
#include <mutex>
#include <openvr.h>
class QQuickWindow;
// application namespace
namespace advsettings {
// forward declaration
class OverlayController;
enum TouchPadArea {
PAD_AREA_LEFT = (1 << 0),
PAD_AREA_TOP = (1 << 1),
PAD_AREA_RIGHT = (1 << 2),
PAD_AREA_BOTTOM = (1 << 3),
};
struct PttControllerConfig {
QVariantList digitalButtons;
uint64_t digitalButtonMask = 0;
unsigned triggerMode = 0; // 0 .. disabled, 1 .. enabled
unsigned touchpadMode = 0; // 0 .. disabled, 1 .. only touch, 2 .. only press, 3 .. both
unsigned touchpadAreas = 0;
};
struct PttProfile {
std::string profileName;
bool showNotification = false;
bool leftControllerEnabled = false;
bool rightControllerEnabled = false;
PttControllerConfig controllerConfigs[2];
};
class AudioTabController : public QObject {
Q_OBJECT
Q_PROPERTY(bool mirrorPresent READ mirrorPresent NOTIFY mirrorPresentChanged)
Q_PROPERTY(QString mirrorDevName READ mirrorDevName NOTIFY mirrorDevNameChanged)
Q_PROPERTY(float mirrorVolume READ mirrorVolume WRITE setMirrorVolume NOTIFY mirrorVolumeChanged)
Q_PROPERTY(bool mirrorMuted READ mirrorMuted WRITE setMirrorMuted NOTIFY mirrorMutedChanged)
Q_PROPERTY(bool micPresent READ micPresent NOTIFY micPresentChanged)
Q_PROPERTY(QString micDevName READ micDevName NOTIFY micDevNameChanged)
Q_PROPERTY(float micVolume READ micVolume WRITE setMicVolume NOTIFY micVolumeChanged)
Q_PROPERTY(bool micMuted READ micMuted WRITE setMicMuted NOTIFY micMutedChanged)
Q_PROPERTY(bool pttEnabled READ pttEnabled WRITE setPttEnabled NOTIFY pttEnabledChanged)
Q_PROPERTY(bool pttActive READ pttActive NOTIFY pttActiveChanged)
Q_PROPERTY(bool pttShowNotification READ pttShowNotification WRITE setPttShowNotification NOTIFY pttShowNotificationChanged)
Q_PROPERTY(bool pttLeftControllerEnabled READ pttLeftControllerEnabled WRITE setPttLeftControllerEnabled NOTIFY pttLeftControllerEnabledChanged)
Q_PROPERTY(bool pttRightControllerEnabled READ pttRightControllerEnabled WRITE setPttRightControllerEnabled NOTIFY pttRightControllerEnabledChanged)
private:
OverlayController* parent;
QQuickWindow* widget;
vr::VROverlayHandle_t m_ulNotificationOverlayHandle = vr::k_ulOverlayHandleInvalid;
bool m_mirrorPresent = false;
QString m_mirrorDevName = "<None>";
float m_mirrorVolume = 1.0;
bool m_mirrorMuted = false;
bool m_micPresent = false;
QString m_micDevName = "<None>";
float m_micVolume = 1.0;
bool m_micMuted = false;
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::vector<PttProfile> pttProfiles;
std::unique_ptr<AudioManager> audioManager;
std::string lastMirrorDevId;
std::recursive_mutex eventLoopMutex;
public:
void initStage1();
void initStage2(OverlayController* parent, QQuickWindow* widget);
void eventLoopTick();
bool mirrorPresent() const;
QString mirrorDevName() const;
float mirrorVolume() const;
bool mirrorMuted() const;
bool micPresent() const;
QString micDevName() const;
float micVolume() const;
bool micMuted() const;
bool pttEnabled() const;
bool pttActive() const;
bool pttShowNotification() const;
bool pttLeftControllerEnabled() const;
bool pttRightControllerEnabled() const;
void reloadPttProfiles();
void reloadPttConfig();
void savePttProfiles();
void savePttConfig();
void onNewRecordingDevice();
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);
Q_INVOKABLE unsigned getPttProfileCount();
Q_INVOKABLE QString getPttProfileName(unsigned index);
public slots:
void setMirrorVolume(float value, bool notify = true);
void setMirrorMuted(bool value, bool notify = true);
void setMicVolume(float value, bool notify = true);
void setMicMuted(bool value, bool notify = true);
void setPttEnabled(bool value, bool notify = true, bool save = true);
void setPttShowNotification(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);
void addPttProfile(QString name);
void applyPttProfile(unsigned index);
void deletePttProfile(unsigned index);
signals:
void mirrorPresentChanged(bool value);
void mirrorDevNameChanged(QString value);
void mirrorVolumeChanged(float value);
void mirrorMutedChanged(bool value);
void micPresentChanged(bool value);
void micDevNameChanged(QString value);
void micVolumeChanged(float value);
void micMutedChanged(bool value);
void pttEnabledChanged(bool value);
void pttActiveChanged(bool value);
void pttShowNotificationChanged(bool value);
void pttLeftControllerEnabledChanged(bool value);
void pttRightControllerEnabledChanged(bool value);
void pttProfilesUpdated();
};
} // namespace advsettings
+387 -64
View File
@@ -1,108 +1,431 @@
#include "ChaperoneTabController.h"
#include <QQuickWindow>
#include "../overlaycontroller.h"
#include "../overlaywidget.h"
#include "ui_overlaywidget.h"
// application namespace
namespace advsettings {
void ChaperoneTabController::init(OverlayController * parent, OverlayWidget * widget) {
void ChaperoneTabController::initStage1() {
reloadChaperoneProfiles();
eventLoopTick();
}
void ChaperoneTabController::initStage2(OverlayController * parent, QQuickWindow * 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->FlipOrientationButton, SIGNAL(clicked()), this, SLOT(FlipOrientationClicked()));
connect(widget->ui->ReloadChaperoneButton, SIGNAL(clicked()), this, SLOT(ReloadClicked()));
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::reloadChaperoneProfiles() {
chaperoneProfiles.clear();
auto settings = OverlayController::appSettings();
settings->beginGroup("chaperoneSettings");
auto profileCount = settings->beginReadArray("chaperoneProfiles");
for (int i = 0; i < profileCount; i++) {
settings->setArrayIndex(i);
chaperoneProfiles.emplace_back();
auto& entry = chaperoneProfiles[i];
entry.profileName = settings->value("profileName").toString().toStdString();
entry.includesChaperoneGeometry = settings->value("includesChaperoneGeometry", false).toBool();
if (entry.includesChaperoneGeometry) {
entry.chaperoneGeometryQuadCount = settings->value("chaperoneGeometryQuadCount", 0).toUInt();
entry.chaperoneGeometryQuads.reset(new vr::HmdQuad_t[entry.chaperoneGeometryQuadCount]);
unsigned qi = 0;
for (auto q : settings->value("chaperoneGeometryQuads").toList()) {
unsigned ci = 0;
for (auto c : q.toList()) {
unsigned cci = 0;
for (auto cc : c.toList()) {
entry.chaperoneGeometryQuads.get()[qi].vCorners[ci].v[cci] = cc.toFloat();
cci++;
}
ci++;
}
qi++;
}
unsigned i1 = 0;
for (auto l1 : settings->value("standingCenter").toList()) {
unsigned i2 = 0;
for (auto l2 : l1.toList()) {
entry.standingCenter.m[i1][i2] = l2.toFloat();
i2++;
}
i1++;
}
entry.playSpaceAreaX = settings->value("playSpaceAreaX", 0.0f).toFloat();
entry.playSpaceAreaZ = settings->value("playSpaceAreaZ", 0.0f).toFloat();
}
entry.includesVisibility = settings->value("includesVisibility", false).toBool();
if (entry.includesVisibility) {
entry.visibility = settings->value("visibility", 0.6).toFloat();
}
entry.includesFadeDistance = settings->value("includesFadeDistance", false).toBool();
if (entry.includesFadeDistance) {
entry.fadeDistance = settings->value("fadeDistance", 0.7).toFloat();
}
entry.includesCenterMarker = settings->value("includesCenterMarker", false).toBool();
if (entry.includesCenterMarker) {
entry.centerMarker = settings->value("centerMarker", false).toBool();
}
entry.includesPlaySpaceMarker = settings->value("includesPlaySpaceMarker", false).toBool();
if (entry.includesPlaySpaceMarker) {
entry.playSpaceMarker = settings->value("playSpaceMarker", false).toBool();
}
entry.includesFloorBoundsMarker = settings->value("includesFloorBoundsMarker", false).toBool();
if (entry.includesFloorBoundsMarker) {
entry.floorBoundsMarker = settings->value("floorBoundsMarker", false).toBool();
}
entry.includesBoundsColor = settings->value("includesBoundsColor", false).toBool();
if (entry.includesBoundsColor) {
auto color = settings->value("boundsColor").toList();
entry.boundsColor[0] = color[0].toInt();
entry.boundsColor[1] = color[1].toInt();
entry.boundsColor[2] = color[2].toInt();
}
entry.includesChaperoneStyle = settings->value("includesChaperoneStyle", false).toBool();
if (entry.includesChaperoneStyle) {
entry.chaperoneStyle = settings->value("chaperoneStyle", 0).toInt();
}
entry.includesForceBounds = settings->value("includesForceBounds", false).toBool();
if (entry.includesForceBounds) {
entry.forceBounds = settings->value("forceBounds", false).toBool();
}
}
settings->endArray();
settings->endGroup();
}
void ChaperoneTabController::saveChaperoneProfiles() {
auto settings = OverlayController::appSettings();
settings->beginGroup("chaperoneSettings");
settings->beginWriteArray("chaperoneProfiles");
unsigned i = 0;
for (auto& p : chaperoneProfiles) {
settings->setArrayIndex(i);
settings->setValue("profileName", QString::fromStdString(p.profileName));
settings->setValue("includesChaperoneGeometry", p.includesChaperoneGeometry);
if (p.includesChaperoneGeometry) {
settings->setValue("chaperoneGeometryQuadCount", p.chaperoneGeometryQuadCount);
QVariantList quadList;
for (unsigned qi = 0; qi < p.chaperoneGeometryQuadCount; qi++) {
QVariantList cornerList;
for (unsigned ci = 0; ci < 4; ci++) {
QVariantList coordVector;
for (unsigned cci = 0; cci < 3; cci++) {
coordVector.push_back(p.chaperoneGeometryQuads.get()[qi].vCorners[ci].v[cci]);
}
cornerList.push_back(coordVector);
}
quadList.push_back(cornerList);
}
settings->setValue("chaperoneGeometryQuads", quadList);
QVariantList l1;
for (unsigned i1 = 0; i1 < 3; i1++) {
QVariantList l2;
for (unsigned i2 = 0; i2 < 4; i2++) {
l2.push_back(p.standingCenter.m[i1][i2]);
}
l1.push_back(l2);
}
settings->setValue("standingCenter", l1);
settings->setValue("playSpaceAreaX", p.playSpaceAreaX);
settings->setValue("playSpaceAreaZ", p.playSpaceAreaZ);
}
settings->setValue("includesVisibility", p.includesVisibility);
if (p.includesVisibility) {
settings->setValue("visibility", p.visibility);
}
settings->setValue("includesFadeDistance", p.includesFadeDistance);
if (p.includesFadeDistance) {
settings->setValue("fadeDistance", p.fadeDistance);
}
settings->setValue("includesCenterMarker", p.includesCenterMarker);
if (p.includesCenterMarker) {
settings->setValue("centerMarker", p.centerMarker);
}
settings->setValue("includesPlaySpaceMarker", p.includesPlaySpaceMarker);
if (p.includesPlaySpaceMarker) {
settings->setValue("playSpaceMarker", p.playSpaceMarker);
}
settings->setValue("includesFloorBoundsMarker", p.includesFloorBoundsMarker);
if (p.includesFloorBoundsMarker) {
settings->setValue("floorBoundsMarker", p.floorBoundsMarker);
}
settings->setValue("includesBoundsColor", p.includesBoundsColor);
if (p.includesBoundsColor) {
QVariantList color;
color.push_back(p.boundsColor[0]);
color.push_back(p.boundsColor[1]);
color.push_back(p.boundsColor[2]);
settings->setValue("boundsColor", color);
}
settings->setValue("includesChaperoneStyle", p.includesChaperoneStyle);
if (p.includesChaperoneStyle) {
settings->setValue("chaperoneStyle", p.chaperoneStyle);
}
settings->setValue("includesForceBounds", p.includesForceBounds);
if (p.includesForceBounds) {
settings->setValue("forceBounds", p.forceBounds);
}
i++;
}
settings->endArray();
settings->endGroup();
}
void ChaperoneTabController::eventLoopTick() {
if (settingsUpdateCounter >= 50) {
vr::EVRSettingsError vrSettingsError;
float vis = vr::VRSettings()->GetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_ColorGammaA_Int32, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not read \"" << vr::k_pch_CollisionBounds_ColorGammaA_Int32 << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
}
setBoundsVisibility(vis/255.0f);
auto fd = vr::VRSettings()->GetFloat(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_FadeDistance_Float, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not read \"" << vr::k_pch_CollisionBounds_FadeDistance_Float << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
}
setFadeDistance(fd);
auto cm = vr::VRSettings()->GetBool(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_CenterMarkerOn_Bool, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not read \"" << vr::k_pch_CollisionBounds_CenterMarkerOn_Bool << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
}
setCenterMarker(cm);
auto ps = vr::VRSettings()->GetBool(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_PlaySpaceOn_Bool, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not read \"" << vr::k_pch_CollisionBounds_PlaySpaceOn_Bool << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
}
setPlaySpaceMarker(ps);
settingsUpdateCounter = 0;
} else {
settingsUpdateCounter++;
}
}
void ChaperoneTabController::CenterMarkerToggled(bool value) {
if (vr::VRSettings()) {
vr::VRSettings()->SetBool(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_CenterMarkerOn_Bool, value);
float ChaperoneTabController::boundsVisibility() const {
return m_visibility;
}
void ChaperoneTabController::setBoundsVisibility(float value, bool notify) {
if (m_visibility != value) {
m_visibility = value;
vr::VRSettings()->SetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_ColorGammaA_Int32, 255 * m_visibility);
vr::VRSettings()->Sync();
if (notify) {
emit boundsVisibilityChanged(m_visibility);
}
}
}
void ChaperoneTabController::PlaySpaceToggled(bool value) {
if (vr::VRSettings()) {
vr::VRSettings()->SetBool(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_PlaySpaceOn_Bool, value);
float ChaperoneTabController::fadeDistance() const {
return m_fadeDistance;
}
void ChaperoneTabController::setFadeDistance(float value, bool notify) {
if (m_fadeDistance != value) {
m_fadeDistance = value;
vr::VRSettings()->SetFloat(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_FadeDistance_Float, m_fadeDistance);
vr::VRSettings()->Sync();
if (notify) {
emit fadeDistanceChanged(m_fadeDistance);
}
}
}
void ChaperoneTabController::ForceBoundsToggled(bool value) {
if (vr::VRChaperone()) {
forceBoundsFlag = value;
vr::VRChaperone()->ForceBoundsVisible(value);
}
bool ChaperoneTabController::centerMarker() const {
return m_centerMarker;
}
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);
void ChaperoneTabController::setCenterMarker(bool value, bool notify) {
if (m_centerMarker != value) {
m_centerMarker = value;
vr::VRSettings()->SetBool(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_CenterMarkerOn_Bool, m_centerMarker);
vr::VRSettings()->Sync();
widget->ui->FadeDistanceLabel->setText(QString::asprintf("%.2f", fval));
if (notify) {
emit centerMarkerChanged(m_centerMarker);
}
}
}
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);
bool ChaperoneTabController::playSpaceMarker() const {
return m_playSpaceMarker;
}
void ChaperoneTabController::setPlaySpaceMarker(bool value, bool notify) {
if (m_playSpaceMarker != value) {
m_playSpaceMarker = value;
vr::VRSettings()->SetBool(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_PlaySpaceOn_Bool, m_playSpaceMarker);
vr::VRSettings()->Sync();
widget->ui->ColorAlphaLabel->setText(QString::asprintf("%i%%", value));
if (notify) {
emit playSpaceMarkerChanged(m_playSpaceMarker);
}
}
}
void ChaperoneTabController::FlipOrientationClicked() {
bool ChaperoneTabController::forceBounds() const {
return m_forceBounds;
}
Q_INVOKABLE unsigned ChaperoneTabController::getChaperoneProfileCount() {
return (unsigned)chaperoneProfiles.size();
}
Q_INVOKABLE QString ChaperoneTabController::getChaperoneProfileName(unsigned index) {
if (index >= chaperoneProfiles.size()) {
return QString();
} else {
return QString::fromStdString(chaperoneProfiles[index].profileName);
}
}
void ChaperoneTabController::setForceBounds(bool value, bool notify) {
if (m_forceBounds != value) {
m_forceBounds = value;
vr::VRChaperone()->ForceBoundsVisible(m_forceBounds);
if (notify) {
emit forceBoundsChanged(m_forceBounds);
}
}
}
void ChaperoneTabController::flipOrientation() {
parent->RotateUniverseCenter(vr::TrackingUniverseStanding, (float)M_PI);
}
void ChaperoneTabController::ReloadClicked() {
void ChaperoneTabController::reloadFromDisk() {
vr::VRChaperoneSetup()->ReloadFromDisk(vr::EChaperoneConfigFile_Live);
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
}
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 ChaperoneTabController::addChaperoneProfile(QString name, bool includeGeometry, bool includeVisbility, bool includeFadeDistance, bool includeCenterMarker,
bool includePlaySpaceMarker, bool includeFloorBounds, bool includeBoundsColor, bool includeChaperoneStyle, bool includeForceBounds) {
vr::EVRSettingsError vrSettingsError;
auto i = chaperoneProfiles.size();
chaperoneProfiles.emplace_back();
auto& profile = chaperoneProfiles[i];
profile.profileName = name.toStdString();
profile.includesChaperoneGeometry = includeGeometry;
if (includeGeometry) {
vr::VRChaperoneSetup()->RevertWorkingCopy();
uint32_t quadCount = 0;
vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo(nullptr, &quadCount);
profile.chaperoneGeometryQuadCount = quadCount;
profile.chaperoneGeometryQuads.reset(new vr::HmdQuad_t[quadCount]);
vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo(profile.chaperoneGeometryQuads.get(), &quadCount);
vr::VRChaperoneSetup()->GetWorkingStandingZeroPoseToRawTrackingPose(&profile.standingCenter);
vr::VRChaperoneSetup()->GetWorkingPlayAreaSize(&profile.playSpaceAreaX, &profile.playSpaceAreaZ);
}
profile.includesVisibility = includeVisbility;
if (includeVisbility) {
profile.visibility = m_visibility;
}
profile.includesFadeDistance = includeFadeDistance;
if (includeFadeDistance) {
profile.fadeDistance = m_fadeDistance;
}
profile.includesCenterMarker = includeCenterMarker;
if (includeCenterMarker) {
profile.centerMarker = m_centerMarker;
}
profile.includesPlaySpaceMarker = includePlaySpaceMarker;
if (includePlaySpaceMarker) {
profile.playSpaceMarker = m_playSpaceMarker;
}
profile.includesFloorBoundsMarker = includeFloorBounds;
if (includeFloorBounds) {
profile.floorBoundsMarker = vr::VRSettings()->GetBool(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_GroundPerimeterOn_Bool, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not read \"" << vr::k_pch_CollisionBounds_GroundPerimeterOn_Bool << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
}
}
profile.includesBoundsColor = includeBoundsColor;
if (includeBoundsColor) {
profile.boundsColor[0] = vr::VRSettings()->GetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_ColorGammaR_Int32, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not read \"" << vr::k_pch_CollisionBounds_ColorGammaR_Int32 << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
}
profile.boundsColor[1] = vr::VRSettings()->GetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_ColorGammaG_Int32, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not read \"" << vr::k_pch_CollisionBounds_ColorGammaG_Int32 << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
}
profile.boundsColor[2] = vr::VRSettings()->GetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_ColorGammaB_Int32, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not read \"" << vr::k_pch_CollisionBounds_ColorGammaB_Int32 << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
}
}
profile.includesChaperoneStyle = includeChaperoneStyle;
if (includeChaperoneStyle) {
profile.chaperoneStyle = vr::VRSettings()->GetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_Style_Int32, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not read \"" << vr::k_pch_CollisionBounds_Style_Int32 << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
}
}
profile.includesForceBounds = includeForceBounds;
if (includeForceBounds) {
profile.forceBounds = m_forceBounds;
}
saveChaperoneProfiles();
OverlayController::appSettings()->sync();
emit chaperoneProfilesUpdated();
}
void ChaperoneTabController::applyChaperoneProfile(unsigned index) {
if (index < chaperoneProfiles.size()) {
auto& profile = chaperoneProfiles[index];
if (profile.includesChaperoneGeometry) {
vr::VRChaperoneSetup()->RevertWorkingCopy();
vr::VRChaperoneSetup()->SetWorkingCollisionBoundsInfo(profile.chaperoneGeometryQuads.get(), profile.chaperoneGeometryQuadCount);
vr::VRChaperoneSetup()->SetWorkingStandingZeroPoseToRawTrackingPose(&profile.standingCenter);
vr::VRChaperoneSetup()->SetWorkingPlayAreaSize(profile.playSpaceAreaX, profile.playSpaceAreaZ);
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
}
if (profile.includesVisibility) {
setBoundsVisibility(profile.visibility);
}
if (profile.includesFadeDistance) {
setFadeDistance(profile.fadeDistance);
}
if (profile.includesCenterMarker) {
setCenterMarker(profile.centerMarker);
}
if (profile.includesPlaySpaceMarker) {
setPlaySpaceMarker(profile.playSpaceMarker);
}
if (profile.includesFloorBoundsMarker) {
vr::VRSettings()->SetBool(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_GroundPerimeterOn_Bool, profile.floorBoundsMarker);
}
if (profile.includesBoundsColor) {
vr::VRSettings()->SetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_ColorGammaR_Int32, profile.boundsColor[0]);
vr::VRSettings()->SetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_ColorGammaG_Int32, profile.boundsColor[1]);
vr::VRSettings()->SetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_ColorGammaB_Int32, profile.boundsColor[2]);
}
if (profile.includesChaperoneStyle) {
vr::VRSettings()->SetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_Style_Int32, profile.chaperoneStyle);
}
if (profile.includesForceBounds) {
setForceBounds(profile.forceBounds);
}
vr::VRSettings()->Sync();
}
}
void ChaperoneTabController::deleteChaperoneProfile(unsigned index) {
if (index < chaperoneProfiles.size()) {
auto pos = chaperoneProfiles.begin() + index;
chaperoneProfiles.erase(pos);
saveChaperoneProfiles();
OverlayController::appSettings()->sync();
emit chaperoneProfilesUpdated();
}
}
} // namespace advconfig
+91 -13
View File
@@ -2,38 +2,116 @@
#pragma once
#include <QObject>
#include <memory>
#include <openvr.h>
class QQuickWindow;
// application namespace
namespace advsettings {
// forward declaration
class OverlayWidget;
class OverlayController;
struct ChaperoneProfile {
std::string profileName;
bool includesChaperoneGeometry = false;
unsigned chaperoneGeometryQuadCount = 0;
std::unique_ptr<vr::HmdQuad_t> chaperoneGeometryQuads = nullptr;
vr::HmdMatrix34_t standingCenter;
float playSpaceAreaX = 0.0f;
float playSpaceAreaZ = 0.0f;
bool includesVisibility = false;
float visibility = 0.6f;
bool includesFadeDistance = false;
float fadeDistance = 0.7f;
bool includesCenterMarker = false;
bool centerMarker = false;
bool includesPlaySpaceMarker = false;
bool playSpaceMarker = false;
bool includesFloorBoundsMarker = false;
bool floorBoundsMarker = false;
bool includesBoundsColor = false;
int boundsColor[3] = {0, 0, 0};
bool includesChaperoneStyle = false;
int chaperoneStyle = 0;
bool includesForceBounds = false;
bool forceBounds = false;
};
class ChaperoneTabController : public QObject {
Q_OBJECT
Q_PROPERTY(float boundsVisibility READ boundsVisibility WRITE setBoundsVisibility NOTIFY boundsVisibilityChanged)
Q_PROPERTY(float fadeDistance READ fadeDistance WRITE setFadeDistance NOTIFY fadeDistanceChanged)
Q_PROPERTY(float centerMarker READ centerMarker WRITE setCenterMarker NOTIFY centerMarkerChanged)
Q_PROPERTY(float playSpaceMarker READ playSpaceMarker WRITE setPlaySpaceMarker NOTIFY playSpaceMarkerChanged)
Q_PROPERTY(float forceBounds READ forceBounds WRITE setForceBounds NOTIFY forceBoundsChanged)
private:
OverlayController* parent;
OverlayWidget* widget;
QQuickWindow* widget;
bool forceBoundsFlag = false;
float m_visibility = 0.6f;
float m_fadeDistance = 0.7f;
bool m_centerMarker = false;
bool m_playSpaceMarker = false;
bool m_forceBounds = false;
unsigned settingsUpdateCounter = 0;
std::vector<ChaperoneProfile> chaperoneProfiles;
public:
void init(OverlayController* parent, OverlayWidget* widget);
void initStage1();
void initStage2(OverlayController* parent, QQuickWindow* widget);
void eventLoopTick();
float boundsVisibility() const;
float fadeDistance() const;
bool centerMarker() const;
bool playSpaceMarker() const;
bool forceBounds() const;
void reloadChaperoneProfiles();
void saveChaperoneProfiles();
Q_INVOKABLE unsigned getChaperoneProfileCount();
Q_INVOKABLE QString getChaperoneProfileName(unsigned index);
public slots:
void UpdateTab();
void setBoundsVisibility(float value, bool notify = true);
void setFadeDistance(float value, bool notify = true);
void setCenterMarker(bool value, bool notify = true);
void setPlaySpaceMarker(bool value, bool notify = true);
void setForceBounds(bool value, bool notify = true);
void CenterMarkerToggled(bool value);
void PlaySpaceToggled(bool value);
void ForceBoundsToggled(bool value);
void FadeDistanceChanged(int value);
void ColorAlphaChanged(int value);
void FlipOrientationClicked();
void ReloadClicked();
void ResetDefaultsClicked();
void flipOrientation();
void reloadFromDisk();
void addChaperoneProfile(QString name, bool includeGeometry, bool includeVisbility, bool includeFadeDistance, bool includeCenterMarker,
bool includePlaySpaceMarker, bool includeFloorBounds, bool includeBoundsColor, bool includeChaperoneStyle, bool includeForceBounds);
void applyChaperoneProfile(unsigned index);
void deleteChaperoneProfile(unsigned index);
signals:
void boundsVisibilityChanged(float value);
void fadeDistanceChanged(float value);
void centerMarkerChanged(bool value);
void playSpaceMarkerChanged(bool value);
void forceBoundsChanged(bool value);
void chaperoneProfilesUpdated();
};
} // namespace advsettings
+63 -62
View File
@@ -1,32 +1,17 @@
#include "FixFloorTabController.h"
#include <QQuickWindow>
#include "../overlaycontroller.h"
#include "../overlaywidget.h"
#include "ui_overlaywidget.h"
// application namespace
namespace advsettings {
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::initStage1() {
}
void FixFloorTabController::UpdateTab() {
if (widget) {
if (state == 1) {
widget->ui->FixFloorButton->setEnabled(false);
} else {
widget->ui->FixFloorButton->setEnabled(true);
}
if (floorOffset != 0.0f) {
widget->ui->UndoFixFloorButton->setEnabled(true);
} else {
widget->ui->UndoFixFloorButton->setEnabled(false);
}
}
void FixFloorTabController::initStage2(OverlayController * parent, QQuickWindow * widget) {
this->parent = parent;
this->widget = widget;
}
void FixFloorTabController::eventLoopTick(vr::TrackedDevicePose_t* devicePoses) {
@@ -35,34 +20,38 @@ void FixFloorTabController::eventLoopTick(vr::TrackedDevicePose_t* devicePoses)
// 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();
statusMessage = "No left controller found.";
statusMessageTimeout = 2.0;
emit statusMessageSignal();
emit measureEndSignal();
state = 0;
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();
statusMessage = "No right controller found.";
statusMessageTimeout = 2.0;
emit statusMessageSignal();
emit measureEndSignal();
state = 0;
return;
}
// Get poses
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();
statusMessage = "Left controller tracking problems.";
statusMessageTimeout = 2.0;
emit statusMessageSignal();
emit measureEndSignal();
state = 0;
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();
statusMessage = "Right controller tracking problems.";
statusMessageTimeout = 2.0;
emit statusMessageSignal();
emit measureEndSignal();
state = 0;
return;
} else {
// The controller with the lowest y-pos is the floor fix reference
@@ -79,45 +68,57 @@ void FixFloorTabController::eventLoopTick(vr::TrackedDevicePose_t* devicePoses)
floorOffset = -controllerUpOffsetCorrection + (float)(tempOffset / (double)measurementCount);
LOG(INFO) << "Fix Floor: Floor Offset = " << floorOffset;
parent->AddOffsetToUniverseCenter(vr::TrackingUniverseStanding, 1, floorOffset);
widget->ui->FixFloorStatusLabel->setText("Fixing ... OK");
statusMessageTimeout = 50;
state = 2;
UpdateTab();
statusMessage = "Fixing ... OK";
statusMessageTimeout = 1.0;
emit statusMessageSignal();
emit measureEndSignal();
setCanUndo(true);
state = 0;
} else {
tempOffset += (double)devicePoses[referenceController].mDeviceToAbsoluteTracking.m[1][3];
measurementCount++;
}
} else if (state == 2) {
if (statusMessageTimeout == 0) {
if (widget) {
widget->ui->FixFloorStatusLabel->setText("");
}
state = 0;
UpdateTab();
} else {
statusMessageTimeout--;
}
}
QString FixFloorTabController::currentStatusMessage() {
return statusMessage;
}
float FixFloorTabController::currentStatusMessageTimeout() {
return statusMessageTimeout;
}
bool FixFloorTabController::canUndo() const {
return m_canUndo;
}
void FixFloorTabController::setCanUndo(bool value, bool notify) {
if (m_canUndo != value) {
m_canUndo = value;
if (notify) {
emit canUndoChanged(m_canUndo);
}
}
}
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::fixFloorClicked() {
statusMessage = "Fixing ...";
statusMessageTimeout = 1.0;
emit statusMessageSignal();
emit measureStartSignal();
measurementCount = 0;
state = 1;
}
void FixFloorTabController::UndoFixFloorClicked() {
void FixFloorTabController::undoFixFloorClicked() {
parent->AddOffsetToUniverseCenter(vr::TrackingUniverseStanding, 1, -floorOffset);
LOG(INFO) << "Fix Floor: Undo Floor Offset = " << -floorOffset;
floorOffset = 0.0f;
widget->ui->FixFloorStatusLabel->setText("Undo ... OK");
statusMessageTimeout = 100;
state = 2;
UpdateTab();
statusMessage = "Undo ... OK";
statusMessageTimeout = 1.0;
emit statusMessageSignal();
setCanUndo(false);
}
} // namespace advconfig
+26 -9
View File
@@ -4,39 +4,56 @@
#include <QObject>
#include <openvr.h>
class QQuickWindow;
// application namespace
namespace advsettings {
// forward declaration
class OverlayWidget;
class OverlayController;
class FixFloorTabController : public QObject {
Q_OBJECT
Q_PROPERTY(bool canUndo READ canUndo WRITE setCanUndo NOTIFY canUndoChanged)
private:
OverlayController* parent;
OverlayWidget* widget;
QQuickWindow* 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
int state = 0; // 0 .. idle, 1 .. measurement in progress
vr::TrackedDeviceIndex_t referenceController = vr::k_unTrackedDeviceIndexInvalid;
unsigned measurementCount = 0;
double tempOffset = 0.0;
unsigned statusMessageTimeout = 0;
float floorOffset = 0.0f;
QString statusMessage = "";
float statusMessageTimeout = 0.0f;
bool m_canUndo = false;
public:
void init(OverlayController* parent, OverlayWidget* widget);
void initStage1();
void initStage2(OverlayController* parent, QQuickWindow* widget);
public slots:
void UpdateTab();
void eventLoopTick(vr::TrackedDevicePose_t* devicePoses);
void FixFloorClicked();
void UndoFixFloorClicked();
Q_INVOKABLE QString currentStatusMessage();
Q_INVOKABLE float currentStatusMessageTimeout();
bool canUndo() const;
public slots:
void fixFloorClicked();
void undoFixFloorClicked();
void setCanUndo(bool value, bool notify = true);
signals:
void statusMessageSignal();
void measureStartSignal();
void measureEndSignal();
void canUndoChanged(bool value);
};
} // namespace advsettings
+100 -156
View File
@@ -1,201 +1,145 @@
#include "MoveCenterTabController.h"
#include <QQuickWindow>
#include "../overlaycontroller.h"
#include "../overlaywidget.h"
#include "ui_overlaywidget.h"
// application namespace
namespace advsettings {
void MoveCenterTabController::init(OverlayController * parent, OverlayWidget * widget) {
void MoveCenterTabController::initStage1() {
setTrackingUniverse(vr::VRCompositor()->GetTrackingSpace());
}
void MoveCenterTabController::initStage2(OverlayController * parent, QQuickWindow * widget) {
this->parent = parent;
this->widget = widget;
trackingUniverse = vr::VRCompositor()->GetTrackingSpace();
xOffset = 0.0f;
yOffset = 0.0f;
zOffset = 0.0f;
widget->ui->MoveCenterStandingSwitch->setChecked(true);
widget->ui->MoveCenterStandingSwitch->setEnabled(false);
widget->ui->MoveCenterSeatedSwitch->setChecked(false);
widget->ui->MoveCenterSeatedSwitch->setEnabled(true);
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->RotateCenterSlider, SIGNAL(valueChanged(int)), this, SLOT(RotateSliderChanged(int)));
connect(widget->ui->RotateCenterButton, SIGNAL(clicked()), this, SLOT(RotateApplyClicked()));
connect(widget->ui->MoveCenterResetButton, SIGNAL(clicked()), this, SLOT(MoveCenterResetClicked()));
/*connect(widget->ui->MoveCenterStandingSwitch, SIGNAL(toggled(bool)), this, SLOT(StandingToggled(bool)));
connect(widget->ui->MoveCenterSeatedSwitch, SIGNAL(toggled(bool)), this, SLOT(SeatedToggled(bool)));*/
}
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));
widget->ui->MoveCenterStandingSwitch->blockSignals(true);
widget->ui->MoveCenterSeatedSwitch->blockSignals(true);
widget->ui->RotateCenterSlider->blockSignals(true);
if (trackingUniverse == vr::TrackingUniverseStanding) {
widget->ui->MoveCenterStandingSwitch->setChecked(true);
widget->ui->MoveCenterSeatedSwitch->setChecked(false);
widget->ui->MoveCenterStandingSwitch->setEnabled(false);
widget->ui->MoveCenterSeatedSwitch->setEnabled(false);
widget->ui->RotateCenterButton->setEnabled(true);
widget->ui->RotateCenterSlider->setEnabled(true);
widget->ui->RotateCenterLabel->setText(QString::asprintf("%i", rotation));
} else {
widget->ui->MoveCenterStandingSwitch->setChecked(false);
widget->ui->MoveCenterSeatedSwitch->setChecked(true);
widget->ui->MoveCenterStandingSwitch->setEnabled(false);
widget->ui->MoveCenterSeatedSwitch->setEnabled(false);
widget->ui->RotateCenterButton->setEnabled(false);
widget->ui->RotateCenterSlider->setEnabled(false);
widget->ui->RotateCenterLabel->setText("-");
int MoveCenterTabController::trackingUniverse() const {
return (int)m_trackingUniverse;
}
void MoveCenterTabController::setTrackingUniverse(int value, bool notify) {
if (m_trackingUniverse != value) {
reset();
m_trackingUniverse = value;
if (notify) {
emit trackingUniverseChanged(m_trackingUniverse);
}
widget->ui->RotateCenterSlider->setValue(rotation);
widget->ui->MoveCenterStandingSwitch->blockSignals(false);
widget->ui->MoveCenterSeatedSwitch->blockSignals(false);
widget->ui->RotateCenterSlider->blockSignals(false);
}
}
void MoveCenterTabController::XMinusClicked() {
if (widget) {
if (rotation == 0) {
parent->AddOffsetToUniverseCenter(trackingUniverse, 0, -0.5f);
} else {
auto angle = rotation * 2 * M_PI / 360.0;
vr::VRChaperoneSetup()->RevertWorkingCopy();
parent->AddOffsetToUniverseCenter(trackingUniverse, 0, -0.5f * std::cos(angle), true, false);
parent->AddOffsetToUniverseCenter(trackingUniverse, 2, -0.5f * std::sin(angle), true, false);
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
float MoveCenterTabController::offsetX() const {
return m_offsetX;
}
void MoveCenterTabController::setOffsetX(float value, bool notify) {
if (m_offsetX != value) {
m_offsetX = value;
if (notify) {
emit offsetXChanged(m_offsetX);
}
xOffset -= 0.5f;
widget->ui->XOffsetLabel->setText(QString::asprintf("%.1f", xOffset));
}
}
void MoveCenterTabController::XPlusClicked() {
if (widget) {
if (rotation == 0) {
parent->AddOffsetToUniverseCenter(trackingUniverse, 0, 0.5f);
} else {
auto angle = rotation * 2 * M_PI / 360.0;
vr::VRChaperoneSetup()->RevertWorkingCopy();
parent->AddOffsetToUniverseCenter(trackingUniverse, 0, 0.5f * std::cos(angle), true, false);
parent->AddOffsetToUniverseCenter(trackingUniverse, 2, 0.5f * std::sin(angle), true, false);
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
float MoveCenterTabController::offsetY() const {
return m_offsetY;
}
void MoveCenterTabController::setOffsetY(float value, bool notify) {
if (m_offsetY != value) {
m_offsetY = value;
if (notify) {
emit offsetYChanged(m_offsetY);
}
xOffset += 0.5f;
widget->ui->XOffsetLabel->setText(QString::asprintf("%.1f", xOffset));
}
}
void MoveCenterTabController::YMinusClicked() {
if (widget) {
parent->AddOffsetToUniverseCenter(trackingUniverse, 1, -0.5f);
yOffset -= 0.5f;
widget->ui->YOffsetLabel->setText(QString::asprintf("%.1f", yOffset));
}
float MoveCenterTabController::offsetZ() const {
return m_offsetZ;
}
void MoveCenterTabController::YPlusClicked() {
if (widget) {
parent->AddOffsetToUniverseCenter(trackingUniverse, 1, 0.5f);
yOffset += 0.5f;
widget->ui->YOffsetLabel->setText(QString::asprintf("%.1f", yOffset));
}
}
void MoveCenterTabController::ZMinusClicked() {
if (widget) {
if (rotation == 0) {
parent->AddOffsetToUniverseCenter(trackingUniverse, 2, -0.5f);
} else {
auto angle = rotation * 2 * M_PI / 360.0;
vr::VRChaperoneSetup()->RevertWorkingCopy();
parent->AddOffsetToUniverseCenter(trackingUniverse, 2, -0.5f * std::cos(angle), true, false);
parent->AddOffsetToUniverseCenter(trackingUniverse, 0, 0.5f * std::sin(angle), true, false);
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
void MoveCenterTabController::setOffsetZ(float value, bool notify) {
if (m_offsetZ != value) {
m_offsetZ = value;
if (notify) {
emit offsetZChanged(m_offsetZ);
}
zOffset -= 0.5f;
widget->ui->ZOffsetLabel->setText(QString::asprintf("%.1f", zOffset));
}
}
void MoveCenterTabController::ZPlusClicked() {
if (widget) {
if (rotation == 0) {
parent->AddOffsetToUniverseCenter(trackingUniverse, 2, 0.5f);
} else {
auto angle = rotation * 2 * M_PI / 360.0;
vr::VRChaperoneSetup()->RevertWorkingCopy();
parent->AddOffsetToUniverseCenter(trackingUniverse, 2, 0.5f * std::cos(angle), true, false);
parent->AddOffsetToUniverseCenter(trackingUniverse, 0, -0.5f * std::sin(angle), true, false);
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
int MoveCenterTabController::rotation() const {
return m_rotation;
}
void MoveCenterTabController::setRotation(int value, bool notify) {
if (m_rotation != value) {
float angle = (value - m_rotation) * 2 * M_PI / 360.0;
parent->RotateUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, angle);
m_rotation = value;
if (notify) {
emit rotationChanged(m_rotation);
}
zOffset += 0.5f;
widget->ui->ZOffsetLabel->setText(QString::asprintf("%.1f", zOffset));
}
}
void MoveCenterTabController::RotateApplyClicked() {
int value = widget->ui->RotateCenterSlider->value();
float angle = (value - rotation) * 2 * M_PI / 360.0;
parent->RotateUniverseCenter(trackingUniverse, angle);
rotation = value;
}
void MoveCenterTabController::RotateSliderChanged(int value) {
widget->ui->RotateCenterLabel->setText(QString::asprintf("%i", value));
}
void MoveCenterTabController::MoveCenterResetClicked() {
if (widget) {
void MoveCenterTabController::modOffsetX(float value) {
if (m_rotation == 0) {
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 0, value);
} else {
auto angle = m_rotation * 2 * M_PI / 360.0;
vr::VRChaperoneSetup()->RevertWorkingCopy();
parent->RotateUniverseCenter(trackingUniverse, -rotation * 2 * M_PI / 360.0);
parent->AddOffsetToUniverseCenter(trackingUniverse, 0, -xOffset, true, false);
parent->AddOffsetToUniverseCenter(trackingUniverse, 1, -yOffset, true, false);
parent->AddOffsetToUniverseCenter(trackingUniverse, 2, -zOffset, true, false);
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 0, value * std::cos(angle), true, false);
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 2, value * std::sin(angle), true, false);
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
xOffset = 0.0f;
yOffset = 0.0f;
zOffset = 0.0f;
rotation = 0;
widget->ui->XOffsetLabel->setText(QString::asprintf("%.1f", xOffset));
widget->ui->YOffsetLabel->setText(QString::asprintf("%.1f", yOffset));
widget->ui->ZOffsetLabel->setText(QString::asprintf("%.1f", zOffset));
widget->ui->RotateCenterSlider->setValue(rotation);
if (trackingUniverse == vr::TrackingUniverseStanding) {
widget->ui->RotateCenterLabel->setText(QString::asprintf("%i", rotation));
} else {
widget->ui->RotateCenterLabel->setText("-");
}
}
m_offsetX += value;
emit offsetXChanged(m_offsetX);
}
void MoveCenterTabController::StandingToggled(bool) {
MoveCenterResetClicked();
trackingUniverse = vr::TrackingUniverseStanding;
UpdateTab();
void MoveCenterTabController::modOffsetY(float value) {
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 1, value);
m_offsetY += value;
emit offsetYChanged(m_offsetY);
}
void MoveCenterTabController::SeatedToggled(bool) {
MoveCenterResetClicked();
trackingUniverse = vr::TrackingUniverseSeated;
UpdateTab();
void MoveCenterTabController::modOffsetZ(float value) {
if (m_rotation == 0) {
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 2, value);
} else {
auto angle = m_rotation * 2 * M_PI / 360.0;
vr::VRChaperoneSetup()->RevertWorkingCopy();
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 2, value * std::cos(angle), true, false);
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 0, -value * std::sin(angle), true, false);
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
}
m_offsetZ += value;
emit offsetZChanged(m_offsetZ);
}
void MoveCenterTabController::reset() {
vr::VRChaperoneSetup()->RevertWorkingCopy();
parent->RotateUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, -m_rotation * 2 * M_PI / 360.0);
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 0, -m_offsetX, true, false);
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 1, -m_offsetY, true, false);
parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 2, -m_offsetZ, true, false);
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
m_offsetX = 0.0f;
m_offsetY = 0.0f;
m_offsetZ = 0.0f;
m_rotation = 0;
emit offsetXChanged(m_offsetX);
emit offsetYChanged(m_offsetY);
emit offsetZChanged(m_offsetZ);
emit rotationChanged(m_rotation);
}
void MoveCenterTabController::eventLoopTick(vr::ETrackingUniverseOrigin universe) {
if (trackingUniverse != universe) {
if (universe == vr::TrackingUniverseStanding) {
StandingToggled(true);
} else if (universe == vr::TrackingUniverseSeated) {
SeatedToggled(true);
}
if (settingsUpdateCounter >= 50) {
setTrackingUniverse((int)universe);
settingsUpdateCounter = 0;
} else {
settingsUpdateCounter++;
}
}
+44 -22
View File
@@ -4,44 +4,66 @@
#include <QObject>
#include <openvr.h>
class QQuickWindow;
// application namespace
namespace advsettings {
// forward declaration
class OverlayWidget;
class OverlayController;
class MoveCenterTabController : public QObject {
Q_OBJECT
Q_PROPERTY(int trackingUniverse READ trackingUniverse WRITE setTrackingUniverse NOTIFY trackingUniverseChanged)
Q_PROPERTY(float offsetX READ offsetX WRITE setOffsetX NOTIFY offsetXChanged)
Q_PROPERTY(float offsetY READ offsetY WRITE setOffsetY NOTIFY offsetYChanged)
Q_PROPERTY(float offsetZ READ offsetZ WRITE setOffsetZ NOTIFY offsetZChanged)
Q_PROPERTY(int rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
private:
OverlayController* parent;
OverlayWidget* widget;
QQuickWindow* widget;
vr::ETrackingUniverseOrigin trackingUniverse = vr::TrackingUniverseStanding;
float xOffset = 0.0f;
float yOffset = 0.0f;
float zOffset = 0.0f;
int rotation = 0;
int m_trackingUniverse = (int)vr::TrackingUniverseStanding;
float m_offsetX = 0.0f;
float m_offsetY = 0.0f;
float m_offsetZ = 0.0f;
int m_rotation = 0;
unsigned settingsUpdateCounter = 0;
public:
void init(OverlayController* parent, OverlayWidget* widget);
void initStage1();
void initStage2(OverlayController* parent, QQuickWindow* widget);
public slots:
void UpdateTab();
void XMinusClicked();
void XPlusClicked();
void YMinusClicked();
void YPlusClicked();
void ZMinusClicked();
void ZPlusClicked();
void RotateApplyClicked();
void RotateSliderChanged(int value);
void MoveCenterResetClicked();
void StandingToggled(bool value);
void SeatedToggled(bool value);
void eventLoopTick(vr::ETrackingUniverseOrigin universe);
float offsetX() const;
float offsetY() const;
float offsetZ() const;
int rotation() const;
public slots:
int trackingUniverse() const;
void setTrackingUniverse(int value, bool notify = true);
void setOffsetX(float value, bool notify = true);
void setOffsetY(float value, bool notify = true);
void setOffsetZ(float value, bool notify = true);
void setRotation(int value, bool notify = true);
void modOffsetX(float value);
void modOffsetY(float value);
void modOffsetZ(float value);
void reset();
signals:
void trackingUniverseChanged(int value);
void offsetXChanged(float value);
void offsetYChanged(float value);
void offsetZChanged(float value);
void rotationChanged(int value);
};
} // namespace advsettings
+28 -21
View File
@@ -1,37 +1,44 @@
#include "SettingsTabController.h"
#include <QQuickWindow>
#include "../overlaycontroller.h"
#include "../overlaywidget.h"
#include "ui_overlaywidget.h"
// application namespace
namespace advsettings {
void SettingsTabController::init(OverlayController * parent, OverlayWidget * widget) {
void SettingsTabController::initStage1() {
m_autoStartEnabled = vr::VRApplications()->GetApplicationAutoLaunch(OverlayController::applicationKey);
}
void SettingsTabController::initStage2(OverlayController * parent, QQuickWindow * 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);
void SettingsTabController::eventLoopTick() {
if (settingsUpdateCounter >= 50) {
setAutoStartEnabled(vr::VRApplications()->GetApplicationAutoLaunch(OverlayController::applicationKey));
settingsUpdateCounter = 0;
} else {
settingsUpdateCounter++;
}
}
bool SettingsTabController::autoStartEnabled() const {
return m_autoStartEnabled;
}
void SettingsTabController::setAutoStartEnabled(bool value, bool notify) {
if (m_autoStartEnabled != value) {
m_autoStartEnabled = value;
auto apperror = vr::VRApplications()->SetApplicationAutoLaunch(OverlayController::applicationKey, m_autoStartEnabled);
if (apperror != vr::VRApplicationError_None) {
LOG(ERROR) << "Could not set auto start: " << vr::VRApplications()->GetApplicationsErrorNameFromEnum(apperror);
}
if (notify) {
emit autoStartEnabledChanged(m_autoStartEnabled);
}
widget->ui->AutoStartToggle->blockSignals(false);
}
}
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);
}
}
} // namespace advconfig
+17 -6
View File
@@ -3,28 +3,39 @@
#include <QObject>
class QQuickWindow;
// application namespace
namespace advsettings {
// forward declaration
class OverlayWidget;
class OverlayController;
class SettingsTabController : public QObject {
Q_OBJECT
Q_PROPERTY(bool autoStartEnabled READ autoStartEnabled WRITE setAutoStartEnabled NOTIFY autoStartEnabledChanged)
private:
OverlayController* parent;
OverlayWidget* widget;
QQuickWindow* widget;
unsigned settingsUpdateCounter = 0;
bool m_autoStartEnabled = false;
public:
void init(OverlayController* parent, OverlayWidget* widget);
void initStage1();
void initStage2(OverlayController* parent, QQuickWindow* widget);
public slots:
void UpdateTab();
void eventLoopTick();
void AutoStartToggled(bool value);
bool autoStartEnabled() const;
public slots:
void setAutoStartEnabled(bool value, bool notify = true);
signals:
void autoStartEnabledChanged(bool value);
};
} // namespace advsettings
+104 -101
View File
@@ -1,45 +1,28 @@
#include "StatisticsTabController.h"
#include <QQuickWindow>
#include "../overlaycontroller.h"
#include "../overlaywidget.h"
#include "ui_overlaywidget.h"
// application namespace
namespace advsettings {
void StatisticsTabController::init(OverlayController * parent, OverlayWidget * widget) {
this->parent = parent;
this->widget = widget;
connect(widget->ui->StatsDistanceResetButton, SIGNAL(clicked()), this, SLOT(StatsDistanceResetClicked()));
connect(widget->ui->StatsRotationResetButton, SIGNAL(clicked()), this, SLOT(StatsRotationResetClicked()));
connect(widget->ui->StatsLeftMaxSpeedResetButton, SIGNAL(clicked()), this, SLOT(StatsLeftControllerSpeedResetClicked()));
connect(widget->ui->StatsRightMaxSpeedResetButton, SIGNAL(clicked()), this, SLOT(StatsRightControllerSpeedResetClicked()));
connect(widget->ui->DroppedFramesResetButton, SIGNAL(clicked()), this, SLOT(DroppedFramesResetClicked()));
connect(widget->ui->ReprojectedFramesResetButton, SIGNAL(clicked()), this, SLOT(ReprojectedFramesResetClicked()));
connect(widget->ui->TimedOutResetButton, SIGNAL(clicked()), this, SLOT(TimedOutResetClicked()));
void StatisticsTabController::initStage1() {
}
void StatisticsTabController::UpdateTab() {
if (widget) {
widget->ui->StatsDistanceLabel->setText(QString::asprintf("%.1f m", hmdDistance));
widget->ui->StatsLeftMaxSpeedLabel->setText(QString::asprintf("%.1f m/s", leftControllerMaxSpeed));
widget->ui->StatsRightMaxSpeedLabel->setText(QString::asprintf("%.1f m/s", rightControllerMaxSpeed));
vr::Compositor_CumulativeStats pStats;
vr::VRCompositor()->GetCumulativeStats(&pStats, sizeof(vr::Compositor_CumulativeStats));
if (pStats.m_nPid != compositorStatsPid) {
droppedFramesOffset = 0;
reprojectedFramesOffset = 0;
timedOutOffset = 0;
compositorStatsPid = pStats.m_nPid;
}
widget->ui->DroppedFramesLabel->setText(QString::asprintf("%i", pStats.m_nNumDroppedFrames - droppedFramesOffset));
widget->ui->ReprojectedFramesLabel->setText(QString::asprintf("%i", pStats.m_nNumReprojectedFrames - reprojectedFramesOffset));
widget->ui->TimedOutLabel->setText(QString::asprintf("%i", pStats.m_nNumTimedOut - timedOutOffset));
}
void StatisticsTabController::initStage2(OverlayController * parent, QQuickWindow * widget) {
this->parent = parent;
this->widget = widget;
}
void StatisticsTabController::eventLoopTick(vr::TrackedDevicePose_t* devicePoses) {
vr::Compositor_CumulativeStats pStats;
vr::VRCompositor()->GetCumulativeStats(&pStats, sizeof(vr::Compositor_CumulativeStats));
if (pStats.m_nPid != compositorStatsPid) {
m_droppedFramesOffset = 0;
m_reprojectedFramesOffset = 0;
m_timedOutOffset = 0;
compositorStatsPid = pStats.m_nPid;
}
auto& m = devicePoses->mDeviceToAbsoluteTracking.m;
// Hmd Distance //
@@ -50,7 +33,7 @@ void StatisticsTabController::eventLoopTick(vr::TrackedDevicePose_t* devicePoses
} else {
auto delta = std::sqrt(std::pow(m[0][3] - lastHmdPos[0], 2) /*+ std::pow(m[1][3] - lastHmdPos[1], 2)*/ + std::pow(m[2][3] - lastHmdPos[2], 2));
if (delta >= 0.01f) {
hmdDistance += delta;
m_hmdDistanceMoved += delta;
}
}
lastHmdPos[0] = m[0][3];
@@ -61,14 +44,13 @@ void StatisticsTabController::eventLoopTick(vr::TrackedDevicePose_t* devicePoses
}
}
// Controller speeds //
auto leftId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_LeftHand);
if (leftId != vr::k_unTrackedDeviceIndexInvalid && devicePoses[leftId].bPoseIsValid && devicePoses[leftId].eTrackingResult == vr::TrackingResult_Running_OK) {
auto& vel = devicePoses[leftId].vVelocity.v;
auto lspeed = std::sqrt(std::pow(vel[0], 2) + std::pow(vel[1], 2) + std::pow(vel[2], 2));
if (lspeed > leftControllerMaxSpeed) {
leftControllerMaxSpeed = lspeed;
if (lspeed > m_leftControllerMaxSpeed) {
m_leftControllerMaxSpeed = lspeed;
}
}
@@ -76,8 +58,8 @@ void StatisticsTabController::eventLoopTick(vr::TrackedDevicePose_t* devicePoses
if (rightId != vr::k_unTrackedDeviceIndexInvalid && devicePoses[rightId].bPoseIsValid && devicePoses[rightId].eTrackingResult == vr::TrackingResult_Running_OK) {
auto& vel = devicePoses[rightId].vVelocity.v;
auto rspeed = std::sqrt(std::pow(vel[0], 2) + std::pow(vel[1], 2) + std::pow(vel[2], 2));
if (rspeed > rightControllerMaxSpeed) {
rightControllerMaxSpeed = rspeed;
if (rspeed > m_rightControllerMaxSpeed) {
m_rightControllerMaxSpeed = rspeed;
}
}
@@ -94,33 +76,46 @@ void StatisticsTabController::eventLoopTick(vr::TrackedDevicePose_t* devicePoses
roll = atan2(cp*sr, cp*cr) [pi, -pi], CW
*/
auto yaw = 0.0;
double yawRaw = 0.0;
double yaw = 0.0;
bool rotationChanged = false;
if (devicePoses[0].bPoseIsValid && devicePoses[0].eTrackingResult == vr::TrackingResult_Running_OK) {
yaw = std::atan2(m[0][2], m[2][2]);
if (yaw < 0.0f) {
yaw += 2 * M_PI; // map to [0, 2*pi], CCW
yawRaw = std::atan2(m[0][2], m[2][2]);
if (yawRaw < 0.0f) {
yawRaw += 2 * M_PI; // map to [0, 2*pi], CCW
}
yaw = yawRaw - rotationOffset;
if (yaw < 0.0) {
yaw = 2 * M_PI + yaw;
}
if (rotationResetFlag) {
rotationDir = 0;
rotationCounter = 0;
rotationMarker = yaw;
rotationOffset = yawRaw;
rotationResetFlag = false;
lastYaw = -1.0f;
} else if (lastYaw < 0.0f && yaw != rotationMarker) {
rotationChanged = true;
} else if (lastYaw < 0.0f && yaw > 0.0) {
lastYaw = yaw;
} else if (lastYaw != yaw && yaw != rotationMarker) {
rotationChanged = true;
if (yaw <= M_PI) {
rotationDir = 1;
} else {
rotationDir = -1;
}
} else if (std::abs(lastYaw - yaw) >= 0.01 && yaw > 0.0) {
auto diff = yaw - lastYaw;
int mode = 0;
if (std::abs(diff) > M_PI) {
if (diff < -M_PI && (rotationMarker < yaw || rotationMarker > lastYaw)) { // CCW overflow
if (diff < -M_PI) { // CCW overflow
mode = 1;
} else if (diff > M_PI && (rotationMarker > yaw || rotationMarker < lastYaw)) { // CW overflow
} else if (diff > M_PI) { // CW overflow
mode = -1;
}
} else {
if (lastYaw < rotationMarker && yaw > rotationMarker) {
if (lastYaw < 0.0 && yaw > 0.0) {
mode = 1;
} else if (lastYaw > rotationMarker && yaw < rotationMarker) {
} else if (lastYaw > 0.0 && yaw < 0.0) {
mode = -1;
}
}
@@ -138,48 +133,19 @@ void StatisticsTabController::eventLoopTick(vr::TrackedDevicePose_t* devicePoses
}
}
lastYaw = yaw;
rotationChanged = true;
}
} else {
lastYaw = -1;
}
if (parent->isDashboardVisible()) {
if (lastPosTimer == 0) {
widget->ui->StatsDistanceLabel->setText(QString::asprintf("%.1f m", hmdDistance));
if (rotationChanged) {
m_hmdRotation = (float)rotationCounter;
if (rotationDir > 0) {
m_hmdRotation += yaw / (2 * M_PI);
} else if (rotationDir < 0) {
m_hmdRotation += -1.0f + yaw / (2 * M_PI);
}
widget->ui->StatsLeftMaxSpeedLabel->setText(QString::asprintf("%.1f m/s", leftControllerMaxSpeed));
widget->ui->StatsRightMaxSpeedLabel->setText(QString::asprintf("%.1f m/s", rightControllerMaxSpeed));
float displayCounter = rotationCounter;
std::string dirStr;
if (rotationDir == 0) {
dirStr = "CCW";
} else if (rotationDir > 0) {
if (yaw > rotationMarker) {
displayCounter += (yaw - rotationMarker) / (2 * M_PI);
} else {
displayCounter += 1.0f + (yaw - rotationMarker) / (2 * M_PI);
}
dirStr = "CCW";
} else {
if (yaw > rotationMarker) {
displayCounter = -displayCounter + 1.0f - (yaw - rotationMarker) / (2 * M_PI);
} else {
displayCounter = -displayCounter - (yaw - rotationMarker) / (2 * M_PI);
}
dirStr = "CW";
}
widget->ui->StatsRotationLabel->setText(QString::asprintf("%.1f %s", displayCounter, dirStr.c_str()));
vr::Compositor_CumulativeStats pStats;
vr::VRCompositor()->GetCumulativeStats(&pStats, sizeof(vr::Compositor_CumulativeStats));
if (pStats.m_nPid != compositorStatsPid) {
droppedFramesOffset = 0;
reprojectedFramesOffset = 0;
timedOutOffset = 0;
compositorStatsPid = pStats.m_nPid;
}
widget->ui->DroppedFramesLabel->setText(QString::asprintf("%i", pStats.m_nNumDroppedFrames - droppedFramesOffset));
widget->ui->ReprojectedFramesLabel->setText(QString::asprintf("%i", pStats.m_nNumReprojectedFrames - reprojectedFramesOffset));
widget->ui->TimedOutLabel->setText(QString::asprintf("%i", pStats.m_nNumTimedOut - timedOutOffset));
}
if (lastPosTimer == 0) {
lastPosTimer = 10;
@@ -188,42 +154,79 @@ void StatisticsTabController::eventLoopTick(vr::TrackedDevicePose_t* devicePoses
}
}
void StatisticsTabController::StatsDistanceResetClicked() {
lastHmdPosValid = false;
hmdDistance = 0.0f;
widget->ui->StatsDistanceLabel->setText(QString::asprintf("%.1f m", hmdDistance));
float StatisticsTabController::hmdDistanceMoved() const {
return m_hmdDistanceMoved;
}
void StatisticsTabController::StatsRotationResetClicked() {
float StatisticsTabController::hmdRotations() const {
return m_hmdRotation;
}
float StatisticsTabController::rightControllerMaxSpeed() const {
return m_rightControllerMaxSpeed;
}
float StatisticsTabController::leftControllerMaxSpeed() const {
return m_leftControllerMaxSpeed;
}
unsigned StatisticsTabController::droppedFrames() const {
vr::Compositor_CumulativeStats pStats;
vr::VRCompositor()->GetCumulativeStats(&pStats, sizeof(vr::Compositor_CumulativeStats));
return pStats.m_nNumDroppedFrames - m_droppedFramesOffset;
}
unsigned StatisticsTabController::reprojectedFrames() const {
vr::Compositor_CumulativeStats pStats;
vr::VRCompositor()->GetCumulativeStats(&pStats, sizeof(vr::Compositor_CumulativeStats));
return pStats.m_nNumReprojectedFrames - m_reprojectedFramesOffset;
}
unsigned StatisticsTabController::timedOut() const {
vr::Compositor_CumulativeStats pStats;
vr::VRCompositor()->GetCumulativeStats(&pStats, sizeof(vr::Compositor_CumulativeStats));
return pStats.m_nNumTimedOut - m_timedOutOffset;
}
void StatisticsTabController::statsDistanceResetClicked() {
lastHmdPosValid = false;
if (m_hmdDistanceMoved != 0.0) {
m_hmdDistanceMoved = 0.0;
}
}
void StatisticsTabController::statsRotationResetClicked() {
rotationResetFlag = true;
}
void StatisticsTabController::StatsLeftControllerSpeedResetClicked() {
leftControllerMaxSpeed = 0;
widget->ui->StatsLeftMaxSpeedLabel->setText(QString::asprintf("%.1f m/s", leftControllerMaxSpeed));
void StatisticsTabController::statsLeftControllerSpeedResetClicked() {
if (m_leftControllerMaxSpeed != 0.0) {
m_leftControllerMaxSpeed = 0.0;
}
}
void StatisticsTabController::StatsRightControllerSpeedResetClicked() {
rightControllerMaxSpeed = 0;
widget->ui->StatsRightMaxSpeedLabel->setText(QString::asprintf("%.1f m/s", rightControllerMaxSpeed));
void StatisticsTabController::statsRightControllerSpeedResetClicked() {
if (m_rightControllerMaxSpeed != 0.0) {
m_rightControllerMaxSpeed = 0.0;
}
}
void StatisticsTabController::DroppedFramesResetClicked() {
void StatisticsTabController::droppedFramesResetClicked() {
vr::Compositor_CumulativeStats pStats;
vr::VRCompositor()->GetCumulativeStats(&pStats, sizeof(vr::Compositor_CumulativeStats));
droppedFramesOffset = pStats.m_nNumDroppedFrames;
m_droppedFramesOffset = pStats.m_nNumDroppedFrames;
}
void StatisticsTabController::ReprojectedFramesResetClicked() {
void StatisticsTabController::reprojectedFramesResetClicked() {
vr::Compositor_CumulativeStats pStats;
vr::VRCompositor()->GetCumulativeStats(&pStats, sizeof(vr::Compositor_CumulativeStats));
reprojectedFramesOffset = pStats.m_nNumReprojectedFrames;
m_reprojectedFramesOffset = pStats.m_nNumReprojectedFrames;
}
void StatisticsTabController::TimedOutResetClicked() {
void StatisticsTabController::timedOutResetClicked() {
vr::Compositor_CumulativeStats pStats;
vr::VRCompositor()->GetCumulativeStats(&pStats, sizeof(vr::Compositor_CumulativeStats));
timedOutOffset = pStats.m_nNumTimedOut;
m_timedOutOffset = pStats.m_nNumTimedOut;
}
} // namespace advconfig
+43 -19
View File
@@ -4,51 +4,75 @@
#include <QObject>
#include <openvr.h>
class QQuickWindow;
// application namespace
namespace advsettings {
// forward declaration
class OverlayWidget;
class OverlayController;
class StatisticsTabController : public QObject {
Q_OBJECT
Q_PROPERTY(float hmdDistanceMoved READ hmdDistanceMoved)
Q_PROPERTY(float hmdRotations READ hmdRotations)
Q_PROPERTY(float leftControllerMaxSpeed READ leftControllerMaxSpeed)
Q_PROPERTY(float rightControllerMaxSpeed READ rightControllerMaxSpeed)
Q_PROPERTY(int droppedFrames READ droppedFrames)
Q_PROPERTY(int reprojectedFrames READ reprojectedFrames)
Q_PROPERTY(int timedOut READ timedOut)
private:
OverlayController* parent;
OverlayWidget* widget;
QQuickWindow* widget;
bool rotationResetFlag = false;
float rotationMarker = 0.0f;
float rotationOffset = 0.0f;
int rotationDir = 0;
int64_t rotationCounter = 0;
float lastYaw = -1.0f;
unsigned lastPosTimer = 0;
float lastHmdPos[3];
bool lastHmdPosValid = false;
double hmdDistance = 0.0;
float leftControllerMaxSpeed = 0.0;
float rightControllerMaxSpeed = 0.0;
unsigned compositorStatsPid = 0;
unsigned droppedFramesOffset = 0;
unsigned reprojectedFramesOffset = 0;
unsigned timedOutOffset = 0;
float m_hmdRotation = 0.0f;
double m_hmdDistanceMoved = 0.0;
float m_leftControllerMaxSpeed = 0.0f;
float m_rightControllerMaxSpeed = 0.0f;
unsigned m_droppedFramesOffset = 0;
unsigned m_reprojectedFramesOffset = 0;
unsigned m_timedOutOffset = 0;
public:
void init(OverlayController* parent, OverlayWidget* widget);
void initStage1();
void initStage2(OverlayController* parent, QQuickWindow* widget);
public slots:
void UpdateTab();
void eventLoopTick(vr::TrackedDevicePose_t* devicePoses);
void StatsDistanceResetClicked();
void StatsRotationResetClicked();
void StatsLeftControllerSpeedResetClicked();
void StatsRightControllerSpeedResetClicked();
void DroppedFramesResetClicked();
void ReprojectedFramesResetClicked();
void TimedOutResetClicked();
float hmdDistanceMoved() const;
float hmdRotations() const;
float rightControllerMaxSpeed() const;
float leftControllerMaxSpeed() const;
unsigned droppedFrames() const;
unsigned reprojectedFrames() const;
unsigned timedOut() const;
public slots:
void statsDistanceResetClicked();
void statsRotationResetClicked();
void statsLeftControllerSpeedResetClicked();
void statsRightControllerSpeedResetClicked();
void droppedFramesResetClicked();
void reprojectedFramesResetClicked();
void timedOutResetClicked();
};
+126 -43
View File
@@ -1,68 +1,151 @@
#include "SteamVRTabController.h"
#include <QQuickWindow>
#include "../overlaycontroller.h"
#include "../overlaywidget.h"
#include "ui_overlaywidget.h"
// application namespace
namespace advsettings {
void SteamVRTabController::init(OverlayController * parent, OverlayWidget * widget) {
this->parent = parent;
this->widget = widget;
connect(widget->ui->SupersamplingSlider, SIGNAL(valueChanged(int)), this, SLOT(SupersamplingChanged(int)));
connect(widget->ui->ReprojectionToggle, SIGNAL(toggled(bool)), this, SLOT(ReprojectionToggled(bool)));
connect(widget->ui->ForceReprojectionToggle, SIGNAL(toggled(bool)), this, SLOT(ForceReprojectionToggled(bool)));
connect(widget->ui->SteamVRResetButton, SIGNAL(clicked()), this, SLOT(ResetClicked()));
connect(widget->ui->SteamVRRestartButton, SIGNAL(clicked()), this, SLOT(RestartClicked()));
void SteamVRTabController::initStage1() {
eventLoopTick();
}
void SteamVRTabController::UpdateTab() {
if (widget) {
widget->ui->SupersamplingSlider->blockSignals(true);
widget->ui->ReprojectionToggle->blockSignals(true);
widget->ui->ForceReprojectionToggle->blockSignals(true);
widget->ui->SteamVRResetButton->blockSignals(true);
widget->ui->SteamVRRestartButton->blockSignals(true);
auto ss = vr::VRSettings()->GetFloat(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_RenderTargetMultiplier_Float, 1.0);
widget->ui->SupersamplingSlider->setValue(ss * 10);
widget->ui->SupersamplingLabel->setText(QString::asprintf("%.1f", ss));
widget->ui->ReprojectionToggle->setChecked(vr::VRSettings()->GetBool(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_AllowReprojection_Bool, true));
widget->ui->ForceReprojectionToggle->setChecked(vr::VRSettings()->GetBool(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_ForceReprojection_Bool, false));
void SteamVRTabController::initStage2(OverlayController * parent, QQuickWindow * widget) {
this->parent = parent;
this->widget = widget;
}
widget->ui->SupersamplingSlider->blockSignals(false);
widget->ui->ReprojectionToggle->blockSignals(false);
widget->ui->ForceReprojectionToggle->blockSignals(false);
widget->ui->SteamVRResetButton->blockSignals(false);
widget->ui->SteamVRRestartButton->blockSignals(false);
void SteamVRTabController::eventLoopTick() {
if (settingsUpdateCounter >= 50) {
vr::EVRSettingsError vrSettingsError;
auto ss = vr::VRSettings()->GetFloat(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_RenderTargetMultiplier_Float, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not read \"" << vr::k_pch_SteamVR_RenderTargetMultiplier_Float << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
setSuperSampling(1.0);
} else {
setSuperSampling(ss);
}
auto css = vr::VRSettings()->GetFloat(vrsettings_compositor_category, vr::k_pch_SteamVR_RenderTargetMultiplier_Float, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
if (vrSettingsError != vr::VRSettingsError_UnsetSettingHasNoDefault) { // does not appear in the default settings file as of beta 1477423729
LOG(WARNING) << "Could not read \"compositor::" << vr::k_pch_SteamVR_RenderTargetMultiplier_Float << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
}
setCompositorSuperSampling(1.0);
} else {
setCompositorSuperSampling(css);
}
auto air = vr::VRSettings()->GetBool(vr::k_pch_SteamVR_Section, vrsettings_steamvr_allowInterleavedReprojection, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not read \"" << vrsettings_steamvr_allowInterleavedReprojection << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
}
setAllowInterleavedReprojection(air);
auto aar = vr::VRSettings()->GetBool(vr::k_pch_SteamVR_Section, vrsettings_steamvr_allowAsyncReprojection, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not read \"" << vrsettings_steamvr_allowAsyncReprojection << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
}
setAllowAsyncReprojection(aar);
auto fr = vr::VRSettings()->GetBool(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_ForceReprojection_Bool, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not read \"" << vr::k_pch_SteamVR_ForceReprojection_Bool << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
}
setForceReprojection(fr);
settingsUpdateCounter = 0;
} else {
settingsUpdateCounter++;
}
}
void SteamVRTabController::SupersamplingChanged(int value) {
float fval = (float)value / 10.0f;
widget->ui->SupersamplingLabel->setText(QString::asprintf("%.1f", fval));
vr::VRSettings()->SetFloat(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_RenderTargetMultiplier_Float, fval);
vr::VRSettings()->Sync();
void SteamVRTabController::setSuperSampling(float value, bool notify) {
if (m_superSampling != value) {
m_superSampling = value;
vr::VRSettings()->SetFloat(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_RenderTargetMultiplier_Float, m_superSampling);
vr::VRSettings()->Sync();
if (notify) {
emit superSamplingChanged(m_superSampling);
}
}
}
void SteamVRTabController::ReprojectionToggled(bool value) {
vr::VRSettings()->SetBool(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_AllowReprojection_Bool, value);
vr::VRSettings()->Sync();
void SteamVRTabController::setCompositorSuperSampling(float value, bool notify) {
if (m_compositorSuperSampling != value) {
m_compositorSuperSampling = value;
vr::VRSettings()->SetFloat(vrsettings_compositor_category, vr::k_pch_SteamVR_RenderTargetMultiplier_Float, m_compositorSuperSampling);
vr::VRSettings()->Sync();
if (notify) {
emit compositorSuperSamplingChanged(m_compositorSuperSampling);
}
}
}
void SteamVRTabController::ForceReprojectionToggled(bool value) {
vr::VRSettings()->SetBool(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_ForceReprojection_Bool, value);
vr::VRSettings()->Sync();
float SteamVRTabController::superSampling() const {
return m_superSampling;
}
void SteamVRTabController::ResetClicked() {
widget->ui->SupersamplingSlider->setValue(10);
widget->ui->ReprojectionToggle->setChecked(true);
widget->ui->ForceReprojectionToggle->setChecked(false);
float SteamVRTabController::compositorSuperSampling() const {
return m_compositorSuperSampling;
}
void SteamVRTabController::RestartClicked() {
bool SteamVRTabController::allowInterleavedReprojection() const {
return m_allowInterleavedReprojection;
}
bool SteamVRTabController::allowAsyncReprojection() const {
return m_allowAsyncReprojection;
}
void SteamVRTabController::setAllowInterleavedReprojection(bool value, bool notify) {
if (m_allowInterleavedReprojection != value) {
m_allowInterleavedReprojection = value;
vr::VRSettings()->SetBool(vr::k_pch_SteamVR_Section, vrsettings_steamvr_allowInterleavedReprojection, m_allowInterleavedReprojection);
vr::VRSettings()->Sync();
if (notify) {
emit allowInterleavedReprojectionChanged(m_allowInterleavedReprojection);
}
}
}
void SteamVRTabController::setAllowAsyncReprojection(bool value, bool notify) {
if (m_allowAsyncReprojection != value) {
m_allowAsyncReprojection = value;
vr::VRSettings()->SetBool(vr::k_pch_SteamVR_Section, vrsettings_steamvr_allowAsyncReprojection, m_allowAsyncReprojection);
vr::VRSettings()->Sync();
if (notify) {
emit allowAsyncReprojectionChanged(m_allowAsyncReprojection);
}
}
}
bool SteamVRTabController::forceReprojection() const {
return m_forceReprojection;
}
void SteamVRTabController::setForceReprojection(bool value, bool notify) {
if (m_forceReprojection != value) {
m_forceReprojection = value;
vr::VRSettings()->SetBool(vr::k_pch_SteamVR_Section, vr::k_pch_SteamVR_ForceReprojection_Bool, m_forceReprojection);
vr::VRSettings()->Sync();
if (notify) {
emit forceReprojectionChanged(m_forceReprojection);
}
}
}
void SteamVRTabController::restartSteamVR() {
QProcess::startDetached("cmd.exe /C restartvrserver.bat");
}
} // namespace advconfig
+44 -9
View File
@@ -3,32 +3,67 @@
#include <QObject>
// openvr's github repo hasn't been updated yet to reflect changes in beta 1477423729.
static const char* vrsettings_steamvr_allowAsyncReprojection = "allowAsyncReprojection";
static const char* vrsettings_steamvr_allowInterleavedReprojection = "allowInterleavedReprojection";
static const char* vrsettings_compositor_category = "compositor";
class QQuickWindow;
// application namespace
namespace advsettings {
// forward declaration
class OverlayWidget;
class OverlayController;
class SteamVRTabController : public QObject {
Q_OBJECT
Q_PROPERTY(float superSampling READ superSampling WRITE setSuperSampling NOTIFY superSamplingChanged)
Q_PROPERTY(float compositorSuperSampling READ compositorSuperSampling WRITE setCompositorSuperSampling NOTIFY compositorSuperSamplingChanged)
Q_PROPERTY(bool allowInterleavedReprojection READ allowInterleavedReprojection WRITE setAllowInterleavedReprojection NOTIFY allowInterleavedReprojectionChanged)
Q_PROPERTY(bool allowAsyncReprojection READ allowAsyncReprojection WRITE setAllowAsyncReprojection NOTIFY allowAsyncReprojectionChanged)
Q_PROPERTY(bool forceReprojection READ forceReprojection WRITE setForceReprojection NOTIFY forceReprojectionChanged)
private:
OverlayController* parent;
OverlayWidget* widget;
QQuickWindow* widget;
float m_superSampling = 1.0;
float m_compositorSuperSampling = 1.0;
bool m_allowInterleavedReprojection = true;
bool m_allowAsyncReprojection = true;
bool m_forceReprojection = false;
unsigned settingsUpdateCounter = 0;
public:
void init(OverlayController* parent, OverlayWidget* widget);
void initStage1();
void initStage2(OverlayController* parent, QQuickWindow* widget);
void eventLoopTick();
float superSampling() const;
float compositorSuperSampling() const;
bool allowInterleavedReprojection() const;
bool allowAsyncReprojection() const;
bool forceReprojection() const;
public slots:
void UpdateTab();
void setSuperSampling(float value, bool notify = true);
void setCompositorSuperSampling(float value, bool notify = true);
void setAllowInterleavedReprojection(bool value, bool notify = true);
void setAllowAsyncReprojection(bool value, bool notify = true);
void setForceReprojection(bool value, bool notify = true);
void SupersamplingChanged(int value);
void ReprojectionToggled(bool value);
void ForceReprojectionToggled(bool value);
void ResetClicked();
void RestartClicked();
void restartSteamVR();
signals:
void superSamplingChanged(float value);
void compositorSuperSamplingChanged(float value);
void allowInterleavedReprojectionChanged(bool value);
void allowAsyncReprojectionChanged(bool value);
void forceReprojectionChanged(bool value);
};
} // namespace advsettings
@@ -0,0 +1,305 @@
#include "audiomanagerwindows.h"
#include <exception>
#include "../../logging.h"
#include "../AudioTabController.h"
#include <locale>
#include <codecvt>
// application namespace
namespace advsettings {
AudioManagerWindows::~AudioManagerWindows() {
audioDeviceEnumerator->UnregisterEndpointNotificationCallback((IMMNotificationClient*)this);
if (mirrorAudioEndpointVolume) {
mirrorAudioEndpointVolume->Release();
}
if (micAudioEndpointVolume) {
micAudioEndpointVolume->Release();
}
if (mirrorAudioDevice) {
mirrorAudioDevice->Release();
}
if (micAudioDevice) {
micAudioDevice->Release();
}
audioDeviceEnumerator->Release();
}
void AudioManagerWindows::init(AudioTabController* controller) {
audioDeviceEnumerator = getAudioDeviceEnumerator();
if (!audioDeviceEnumerator) {
throw std::exception("Could not create audio device enumerator");
}
micAudioDevice = getDefaultRecordingDevice(audioDeviceEnumerator);
if (micAudioDevice) {
micAudioEndpointVolume = getAudioEndpointVolume(micAudioDevice);
} else {
LOG(WARNING) << "Could not find a default recording device.";
}
this->controller = controller;
audioDeviceEnumerator->RegisterEndpointNotificationCallback((IMMNotificationClient*)this);
}
void AudioManagerWindows::setMirrorDevice(const std::string& id) {
if (id.empty()) {
deleteMirrorDevice();
} else {
mirrorAudioDevice = getDevice(audioDeviceEnumerator, id);
if (mirrorAudioDevice) {
mirrorAudioEndpointVolume = getAudioEndpointVolume(mirrorAudioDevice);
} else {
LOG(WARNING) << "Could not find mirror device \"" << id << "\".";
}
}
}
void AudioManagerWindows::deleteMirrorDevice() {
if (mirrorAudioEndpointVolume) {
mirrorAudioEndpointVolume->Release();
mirrorAudioEndpointVolume = nullptr;
}
if (mirrorAudioDevice) {
mirrorAudioDevice->Release();
mirrorAudioDevice = nullptr;
}
}
bool AudioManagerWindows::isMirrorValid() {
return mirrorAudioEndpointVolume != nullptr;
}
std::string AudioManagerWindows::getMirrorDevName() {
if (mirrorAudioDevice) {
return getDeviceName(mirrorAudioDevice);
}
return "";
}
float AudioManagerWindows::getMirrorVolume() {
float value;
if (mirrorAudioEndpointVolume && mirrorAudioEndpointVolume->GetMasterVolumeLevelScalar(&value) >= 0) {
return value;
} else {
return 0.0;
}
}
bool AudioManagerWindows::setMirrorVolume(float value) {
if (mirrorAudioEndpointVolume) {
if (mirrorAudioEndpointVolume->SetMasterVolumeLevelScalar(value, nullptr) >= 0) {
return true;
}
}
return false;
}
bool AudioManagerWindows::getMirrorMuted() {
BOOL value;
if (mirrorAudioEndpointVolume && mirrorAudioEndpointVolume->GetMute(&value) >= 0) {
return value;
} else {
return false;
}
}
bool AudioManagerWindows::setMirrorMuted(bool value) {
if (mirrorAudioEndpointVolume) {
if (mirrorAudioEndpointVolume->SetMute(value, nullptr) >= 0) {
return true;
}
}
return false;
}
bool AudioManagerWindows::isMicValid() {
return micAudioEndpointVolume != nullptr;
}
std::string AudioManagerWindows::getMicDevName() {
if (micAudioDevice) {
return getDeviceName(micAudioDevice);
}
return "";
}
float AudioManagerWindows::getMicVolume() {
float value;
if (micAudioEndpointVolume && micAudioEndpointVolume->GetMasterVolumeLevelScalar(&value) >= 0) {
return value;
} else {
return 0.0;
}
}
bool AudioManagerWindows::setMicVolume(float value) {
if (micAudioEndpointVolume) {
if (micAudioEndpointVolume->SetMasterVolumeLevelScalar(value, nullptr) >= 0) {
return true;
}
}
return false;
}
bool AudioManagerWindows::getMicMuted() {
BOOL value;
if (micAudioEndpointVolume && micAudioEndpointVolume->GetMute(&value) >= 0) {
return value;
} else {
return false;
}
}
bool AudioManagerWindows::setMicMuted(bool value) {
if (micAudioEndpointVolume) {
if (micAudioEndpointVolume->SetMute(value, nullptr) >= 0) {
return true;
}
}
return false;
}
IMMDeviceEnumerator* AudioManagerWindows::getAudioDeviceEnumerator() {
IMMDeviceEnumerator* pEnumerator;
if (CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator) < 0) {
return nullptr;
}
return pEnumerator;
}
IMMDevice* AudioManagerWindows::getDefaultRecordingDevice(IMMDeviceEnumerator* deviceEnumerator) {
IMMDevice* pDevice;
if (deviceEnumerator->GetDefaultAudioEndpoint(eCapture, eCommunications, &pDevice) < 0) {
return nullptr;
}
return pDevice;
}
IMMDevice* AudioManagerWindows::getDevice(IMMDeviceEnumerator* deviceEnumerator, const std::string& id) {
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::wstring wid = converter.from_bytes(id);
return getDevice(deviceEnumerator, wid.c_str());
}
IMMDevice * AudioManagerWindows::getDevice(IMMDeviceEnumerator * deviceEnumerator, LPCWSTR id) {
IMMDevice* pDevice;
if (deviceEnumerator->GetDevice(id, &pDevice) < 0) {
return nullptr;
}
return pDevice;
}
IAudioEndpointVolume * AudioManagerWindows::getAudioEndpointVolume(IMMDevice* device) {
IAudioEndpointVolume * pEndpointVolume;
if (device->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_INPROC_SERVER, NULL, (void**)&pEndpointVolume) < 0) {
return nullptr;
}
return pEndpointVolume;
}
std::string AudioManagerWindows::getDeviceName(IMMDevice* device) {
IPropertyStore *pProps = nullptr;
PROPVARIANT varString;
if (device->OpenPropertyStore(STGM_READ, &pProps) >= 0 && pProps->GetValue(PKEY_Device_FriendlyName, &varString) >= 0) {
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::string name = converter.to_bytes(varString.pwszVal);
return name;
}
return "";
}
HRESULT AudioManagerWindows::QueryInterface(REFIID riid, void ** ppvObject) {
if (IID_IUnknown == riid) {
AddRef();
*ppvObject = (IUnknown*)this;
} else if (__uuidof(IMMNotificationClient) == riid) {
AddRef();
*ppvObject = (IMMNotificationClient*)this;
} else {
*ppvObject = NULL;
return E_NOINTERFACE;
}
return S_OK;
}
ULONG AudioManagerWindows::AddRef(void) {
return 1; // We don't need reference counting
}
ULONG AudioManagerWindows::Release(void) {
return 1; // We don't need reference counting
}
HRESULT AudioManagerWindows::OnDeviceStateChanged(LPCWSTR, DWORD) {
return S_OK;
}
HRESULT AudioManagerWindows::OnDeviceAdded(LPCWSTR) {
return S_OK;
}
HRESULT AudioManagerWindows::OnDeviceRemoved(LPCWSTR) {
return S_OK;
}
HRESULT AudioManagerWindows::OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId) {
if (flow == eCapture && role == eMultimedia) {
if (audioDeviceEnumerator) {
auto device = getDevice(audioDeviceEnumerator, pwstrDefaultDeviceId);
if (device != micAudioDevice) {
if (micAudioDevice) {
micAudioDevice->Release();
}
micAudioDevice = device;
if (micAudioDevice) {
micAudioEndpointVolume = getAudioEndpointVolume(micAudioDevice);
} else {
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::string name = converter.to_bytes(pwstrDefaultDeviceId);
LOG(WARNING) << "Could not find recording device \"" << name << "\".";
}
controller->onNewRecordingDevice();
}
}
}
/*char* pszFlow = (char*)"?????";
char* pszRole = (char*)"?????";
switch (flow) {
case eRender:
pszFlow = (char*)"eRender";
break;
case eCapture:
pszFlow = (char*)"eCapture";
break;
}
switch (role) {
case eConsole:
pszRole = (char*)"eConsole";
break;
case eMultimedia:
pszRole = (char*)"eMultimedia";
break;
case eCommunications:
pszRole = (char*)"eCommunications";
break;
}
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::string name = converter.to_bytes(pwstrDefaultDeviceId);
printf(" %s -->New default device: flow = %s, role = %s\n", name.c_str(), pszFlow, pszRole);
fflush(stdout);*/
return S_OK;
}
HRESULT AudioManagerWindows::OnPropertyValueChanged(LPCWSTR, const PROPERTYKEY) {
return S_OK;
}
}
@@ -0,0 +1,64 @@
#pragma once
#include "../audiomanager.h"
#include <Mmdeviceapi.h>
#include <Functiondiscoverykeys_devpkey.h>
#include <Endpointvolume.h>
// application namespace
namespace advsettings {
class AudioManagerWindows : public AudioManager, IMMNotificationClient {
friend class AudioNotificationClient;
private:
AudioTabController* controller = nullptr;
IMMDeviceEnumerator* audioDeviceEnumerator = nullptr;
IMMDevice* mirrorAudioDevice = nullptr;
IAudioEndpointVolume* mirrorAudioEndpointVolume = nullptr;
IMMDevice* micAudioDevice = nullptr;
IAudioEndpointVolume* micAudioEndpointVolume = nullptr;
public:
~AudioManagerWindows();
virtual void init(AudioTabController* controller) override;
virtual void setMirrorDevice(const std::string& id) override;
virtual void deleteMirrorDevice() override;
virtual bool isMirrorValid() override;
virtual std::string getMirrorDevName() override;
virtual float getMirrorVolume() override;
virtual bool setMirrorVolume(float value) override;
virtual bool getMirrorMuted() override;
virtual bool setMirrorMuted(bool value) override;
virtual bool isMicValid() override;
virtual std::string getMicDevName() override;
virtual float getMicVolume() override;
virtual bool setMicVolume(float value) override;
virtual bool getMicMuted() override;
virtual bool setMicMuted(bool value) override;
// from IMMNotificationClient
virtual HRESULT QueryInterface(REFIID riid, void ** ppvObject) override;
virtual ULONG AddRef(void) override;
virtual ULONG Release(void) override;
virtual HRESULT OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) override;
virtual HRESULT OnDeviceAdded(LPCWSTR pwstrDeviceId) override;
virtual HRESULT OnDeviceRemoved(LPCWSTR pwstrDeviceId) override;
virtual HRESULT OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId) override;
virtual HRESULT OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) override;
private:
IMMDeviceEnumerator* getAudioDeviceEnumerator();
IMMDevice* getDefaultRecordingDevice(IMMDeviceEnumerator* deviceEnumerator);
IMMDevice* getDevice(IMMDeviceEnumerator* deviceEnumerator, const std::string& id);
IMMDevice* getDevice(IMMDeviceEnumerator* deviceEnumerator, LPCWSTR id);
IAudioEndpointVolume* getAudioEndpointVolume(IMMDevice* device);
std::string getDeviceName(IMMDevice* device);
};
}