From 96513c6d0799e60769a7159a9a4d4642af599cdd Mon Sep 17 00:00:00 2001 From: Vasily Date: Sun, 31 Mar 2019 13:25:43 +0200 Subject: [PATCH 01/15] Fix null pointer dereference in QtMessageHandler function The `QMessageLogContext` is only filled out in debug builds. Release builds will have null pointers in `file` and `line`. This causes any error attempted to be logged to result in a null pointer dereference. Since we never use debug builds anyway, simply removing the uses of `file` and `line` makes sense. Github issue https://github.com/OpenVR-Advanced-Settings/OpenVR-AdvancedSettings/issues/139 --- src/utils/setup.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/utils/setup.cpp b/src/utils/setup.cpp index 95c7e59..a5ea435 100644 --- a/src/utils/setup.cpp +++ b/src/utils/setup.cpp @@ -7,28 +7,27 @@ void mainQtMessageHandler( QtMsgType type, const QMessageLogContext& context, const QString& msg ) { + // context contains null pointers on release builds. Cast to get rid of + // unreferenced formal parameter warnings. + static_cast( context ); + QByteArray localMsg = msg.toLocal8Bit(); switch ( type ) { case QtDebugMsg: - LOG( DEBUG ) << localMsg.constData() << " (" << context.file << ":" - << context.line << ")"; + LOG( DEBUG ) << localMsg.constData(); break; case QtInfoMsg: - LOG( INFO ) << localMsg.constData() << " (" << context.file << ":" - << context.line << ")"; + LOG( INFO ) << localMsg.constData(); break; case QtWarningMsg: - LOG( WARNING ) << localMsg.constData() << " (" << context.file << ":" - << context.line << ")"; + LOG( WARNING ) << localMsg.constData(); break; case QtCriticalMsg: - LOG( ERROR ) << localMsg.constData() << " (" << context.file << ":" - << context.line << ")"; + LOG( ERROR ) << localMsg.constData(); break; case QtFatalMsg: - LOG( FATAL ) << localMsg.constData() << " (" << context.file << ":" - << context.line << ")"; + LOG( FATAL ) << localMsg.constData(); break; } } From 2e42773529445aa8872f5e88ed7125eaf1948c12 Mon Sep 17 00:00:00 2001 From: Vasily Date: Sun, 31 Mar 2019 13:53:20 +0200 Subject: [PATCH 02/15] Add special message to Qt handler This makes it more obvious where an error came from. --- src/utils/setup.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/utils/setup.cpp b/src/utils/setup.cpp index a5ea435..6485fd9 100644 --- a/src/utils/setup.cpp +++ b/src/utils/setup.cpp @@ -15,19 +15,19 @@ void mainQtMessageHandler( QtMsgType type, switch ( type ) { case QtDebugMsg: - LOG( DEBUG ) << localMsg.constData(); + LOG( DEBUG ) << "QTMSGH: " << localMsg.constData(); break; case QtInfoMsg: - LOG( INFO ) << localMsg.constData(); + LOG( INFO ) << "QTMSGH: " << localMsg.constData(); break; case QtWarningMsg: - LOG( WARNING ) << localMsg.constData(); + LOG( WARNING ) << "QTMSGH: " << localMsg.constData(); break; case QtCriticalMsg: - LOG( ERROR ) << localMsg.constData(); + LOG( ERROR ) << "QTMSGH: " << localMsg.constData(); break; case QtFatalMsg: - LOG( FATAL ) << localMsg.constData(); + LOG( FATAL ) << "QTMSGH: " << localMsg.constData(); break; } } From 760d262a570ff22ff730c662a94248c1b145eefc Mon Sep 17 00:00:00 2001 From: Vasily Date: Wed, 20 Mar 2019 20:14:24 +0100 Subject: [PATCH 03/15] Add page to change desktop overlay translation The implementation is simple 3D vector scaling and addition. The HmdMatrix34_t consists of a 3x3 rotation matrix and a 3D vector for position. The overlay position is only updated whenever a new overlay is changed because we need the old overlay position in order to modify it. The openvr call to get the position is only updated whenever you open the menu. A new page was created due to lack of space on the utilities page. --- build_scripts/qt/resources.pri | 6 +- build_scripts/qt/sources.pri | 6 +- src/openvr/overlay_utils.cpp | 177 ++++++++++++++++++ src/openvr/overlay_utils.h | 64 +++++++ src/overlaycontroller.cpp | 12 ++ src/overlaycontroller.h | 2 + src/res/qml/RootPage.qml | 11 ++ src/res/qml/common/mainwidget.qml | 6 + .../DesktopOverlayPage.qml | 34 ++++ .../desktop_size/SteamDesktopGroupBox.qml | 12 +- .../SteamDesktopTranslationBackForwards.qml | 78 ++++++++ .../SteamDesktopTranslationLeftRight.qml | 80 ++++++++ .../SteamDesktopTranslationUpDown.qml | 78 ++++++++ src/res/qml/utilities_page/UtilitiesPage.qml | 4 - 14 files changed, 557 insertions(+), 13 deletions(-) create mode 100644 src/openvr/overlay_utils.cpp create mode 100644 src/openvr/overlay_utils.h create mode 100644 src/res/qml/desktop_overlay_page/DesktopOverlayPage.qml rename src/res/qml/{utilities_page => desktop_overlay_page}/desktop_size/SteamDesktopGroupBox.qml (98%) create mode 100644 src/res/qml/desktop_overlay_page/translation_back_forwards/SteamDesktopTranslationBackForwards.qml create mode 100644 src/res/qml/desktop_overlay_page/translation_left_right/SteamDesktopTranslationLeftRight.qml create mode 100644 src/res/qml/desktop_overlay_page/translation_up_down/SteamDesktopTranslationUpDown.qml diff --git a/build_scripts/qt/resources.pri b/build_scripts/qt/resources.pri index ab0e706..c1f669f 100644 --- a/build_scripts/qt/resources.pri +++ b/build_scripts/qt/resources.pri @@ -32,7 +32,7 @@ DISTFILES += \ src/res/qml/utilities_page/* \ src/res/qml/utilities_page/media_keys/* \ src/res/qml/utilities_page/keyboard_utils/* \ - src/res/qml/utilities_page/desktop_size/* \ + src/res/qml/desktop_overlay_page/desktop_size/* \ src/res/qml/utilities_page/alarm_clock/* \ src/res/qml/audio_page/dialog_boxes/* \ src/res/qml/audio_page/device_selector/* \ @@ -40,5 +40,9 @@ DISTFILES += \ src/res/qml/audio_page/push_to_talk/* \ src/res/qml/audio_page/profiles/* \ src/res/qml/common/* \ + src/res/qml/desktop_overlay_page/* \ + src/res/qml/desktop_overlay_page/translation_left_right/SteamDesktopTranslationLeftRight.qml \ + src/res/qml/desktop_overlay_page/translation_back_forwards/SteamDesktopTranslationBackForwards.qml \ + src/res/qml/desktop_overlay_page/translation_up_down/SteamDesktopTranslationUpDown.qml \ RC_FILE = src/res/icon.rc diff --git a/build_scripts/qt/sources.pri b/build_scripts/qt/sources.pri index 3cf35c7..9a3ea30 100644 --- a/build_scripts/qt/sources.pri +++ b/build_scripts/qt/sources.pri @@ -16,7 +16,8 @@ SOURCES += src/main.cpp\ src/openvr/openvr_init.cpp \ src/openvr/ivrinput.cpp \ src/utils/setup.cpp \ - src/utils/paths.cpp + src/utils/paths.cpp \ + src/openvr/overlay_utils.cpp HEADERS += src/overlaycontroller.h \ src/tabcontrollers/AudioTabController.h \ @@ -43,7 +44,8 @@ HEADERS += src/overlaycontroller.h \ src/openvr/ivrinput_input_source.h \ src/openvr/ivrinput.h \ src/utils/setup.h \ - src/utils/paths.h + src/utils/paths.h \ + src/openvr/overlay_utils.h win32 { SOURCES += src/tabcontrollers/audiomanager/AudioManagerWindows.cpp \ diff --git a/src/openvr/overlay_utils.cpp b/src/openvr/overlay_utils.cpp new file mode 100644 index 0000000..6f563ee --- /dev/null +++ b/src/openvr/overlay_utils.cpp @@ -0,0 +1,177 @@ +#include "overlay_utils.h" + +namespace overlay +{ +vr::VROverlayHandle_t getOverlayHandle() +{ + vr::VROverlayHandle_t pOverlayHandle; + vr::VROverlay()->FindOverlay( strings::overlaykey, &pOverlayHandle ); + return pOverlayHandle; +} + +vr::HmdMatrix34_t getDesktopOverlayPositions() +{ + vr::HmdMatrix34_t currentPosition = {}; + + const auto overlayHandle = getOverlayHandle(); + + vr::ETrackingUniverseOrigin origin + = vr::ETrackingUniverseOrigin::TrackingUniverseStanding; + + vr::VROverlay()->GetOverlayTransformAbsolute( + overlayHandle, &origin, ¤tPosition ); + + return currentPosition; +} + +void setDesktopOverlayPositions( vr::HmdMatrix34_t& positions ) +{ + const auto overlayHandle = getOverlayHandle(); + + // We need to make sure we get the same Universe Origin as before. + vr::HmdMatrix34_t currentPosition = {}; + vr::ETrackingUniverseOrigin origin + = vr::ETrackingUniverseOrigin::TrackingUniverseStanding; + vr::VROverlay()->GetOverlayTransformAbsolute( + overlayHandle, &origin, ¤tPosition ); + + vr::VROverlay()->SetOverlayTransformAbsolute( + overlayHandle, origin, &positions ); +} + +void setDesktopOverlayWidth( double width ) +{ + const auto overlayHandle = getOverlayHandle(); + auto error = vr::VROverlay()->SetOverlayWidthInMeters( + overlayHandle, static_cast( width ) ); + if ( error != vr::VROverlayError_None ) + { + LOG( ERROR ) << "Could not modify overlay width of \"" + << strings::overlaykey << "\": " + << vr::VROverlay()->GetOverlayErrorNameFromEnum( error ); + } +} + +void setSettingsToValue( const std::string setting, const double value ) +{ + QSettings settings; + settings.beginGroup( strings::settingsGroupName ); + settings.setValue( setting.c_str(), value ); + settings.endGroup(); +} + +overlay::DesktopOverlay::DesktopOverlay() +{ + QSettings settings; + settings.beginGroup( strings::settingsGroupName ); + m_width = settings.value( strings::widthSettingsName, defaultOverlayWidth ) + .toDouble(); + m_forwardsMovement + = settings.value( strings::forwardsSettingsName, defaultMovement ) + .toDouble(); + m_rightMovement + = settings.value( strings::rightMovementSettingsName, defaultMovement ) + .toDouble(); + settings.endGroup(); +} + +void DesktopOverlay::update() +{ + auto positionMatrix = getDesktopOverlayPositions(); + + auto position = QVector3D( positionMatrix.m[0][3], + positionMatrix.m[1][3], + positionMatrix.m[2][3] ); + + const auto screenRight = QVector3D( positionMatrix.m[0][0], + positionMatrix.m[1][0], + positionMatrix.m[2][0] ); + + const auto screenForwards = QVector3D( positionMatrix.m[0][2], + positionMatrix.m[1][2], + positionMatrix.m[2][2] ); + + const auto screenUp = QVector3D( positionMatrix.m[0][1], + positionMatrix.m[1][1], + positionMatrix.m[2][1] ); + + position += ( static_cast( m_rightMovement ) * screenRight ); + + position += ( static_cast( m_forwardsMovement ) * screenForwards ); + + position += ( static_cast( m_upMovement ) * screenUp ); + + positionMatrix.m[0][3] = position.x(); + positionMatrix.m[1][3] = position.y(); + positionMatrix.m[2][3] = position.z(); + + setDesktopOverlayPositions( positionMatrix ); + + setDesktopOverlayWidth( m_width ); +} + +bool DesktopOverlay::isAvailable() const +{ + vr::VROverlayHandle_t pOverlayHandle = 0; + auto error + = vr::VROverlay()->FindOverlay( strings::overlaykey, &pOverlayHandle ); + if ( error != vr::VROverlayError_None ) + { + LOG( INFO ) << "Could not find overlay \"" << strings::overlaykey + << "\": " + << vr::VROverlay()->GetOverlayErrorNameFromEnum( error ); + return false; + } + return true; +} + +void overlay::DesktopOverlay::setWidth( double width ) +{ + if ( width < 0.01 ) + { + width = 0.01; + } + + setSettingsToValue( strings::widthSettingsName, width ); + m_width = width; +} + +double DesktopOverlay::getCurrentWidth() const noexcept +{ + return m_width; +} + +void DesktopOverlay::setRightMovement( double distance ) +{ + setSettingsToValue( strings::rightMovementSettingsName, distance ); + m_rightMovement = distance; +} + +double DesktopOverlay::getCurrentRightMovement() const noexcept +{ + return m_rightMovement; +} + +void DesktopOverlay::setForwardsMovement( double distance ) +{ + setSettingsToValue( strings::forwardsSettingsName, distance ); + m_forwardsMovement = distance; +} + +double DesktopOverlay::getCurrentForwardsMovement() const noexcept +{ + return m_forwardsMovement; +} + +void DesktopOverlay::setHeight( double height ) +{ + setSettingsToValue( strings::upMovementSettingsName, height ); + m_upMovement = height; +} + +double DesktopOverlay::getCurrentHeight() const noexcept +{ + return m_upMovement; +} + +} // namespace overlay diff --git a/src/openvr/overlay_utils.h b/src/openvr/overlay_utils.h new file mode 100644 index 0000000..22875a9 --- /dev/null +++ b/src/openvr/overlay_utils.h @@ -0,0 +1,64 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +void outputMat(); +void transformMat(); + +namespace overlay +{ +namespace strings +{ + constexpr auto overlaykey = "valve.steam.desktop"; + constexpr auto settingsGroupName = "utilitiesSettings"; + constexpr auto widthSettingsName = "desktopWidth"; + constexpr auto forwardsSettingsName = "desktopForwardsMovement"; + constexpr auto rightMovementSettingsName = "desktopRightMovement"; + constexpr auto upMovementSettingsName = "desktopUpMovement"; + constexpr auto positionSettingsName = "desktopOverlayPosition"; +} // namespace strings + +constexpr auto defaultOverlayWidth = 4.0; +constexpr auto defaultMovement = 0.0; + +class DesktopOverlay : public QObject +{ + Q_OBJECT +public: + Q_PROPERTY( double rightMovement READ getCurrentRightMovement() + WRITE setRightMovement ) + Q_PROPERTY( double forwardsMovement READ getCurrentForwardsMovement WRITE + setForwardsMovement ) + Q_PROPERTY( double width READ getCurrentWidth WRITE setWidth ) + Q_PROPERTY( double height READ getCurrentHeight WRITE setHeight ) + + DesktopOverlay(); + + Q_INVOKABLE void update(); + + bool isAvailable() const; + + void setWidth( double width ); + double getCurrentWidth() const noexcept; + + void setRightMovement( double distance ); + double getCurrentRightMovement() const noexcept; + + void setForwardsMovement( double distance ); + double getCurrentForwardsMovement() const noexcept; + + void setHeight( double height ); + double getCurrentHeight() const noexcept; + +private: + double m_width = defaultOverlayWidth; + double m_forwardsMovement = defaultMovement; + double m_rightMovement = defaultMovement; + double m_upMovement = defaultMovement; +}; + +} // namespace overlay diff --git a/src/overlaycontroller.cpp b/src/overlaycontroller.cpp index 263760d..d5ceeb8 100644 --- a/src/overlaycontroller.cpp +++ b/src/overlaycontroller.cpp @@ -20,6 +20,7 @@ #include #include #include "utils/Matrix.h" +#include "openvr/overlay_utils.h" // application namespace namespace advsettings @@ -251,6 +252,16 @@ OverlayController::OverlayController( bool desktopMode, QQmlEngine::setObjectOwnership( obj, QQmlEngine::CppOwnership ); return obj; } ); + qmlRegisterSingletonType( + qmlSingletonImportName, + 1, + 0, + "DesktopOverlay", + []( QQmlEngine*, QJSEngine* ) { + QObject* obj = &( objectAddress->m_desktopOverlay ); + QQmlEngine::setObjectOwnership( obj, QQmlEngine::CppOwnership ); + return obj; + } ); } OverlayController::~OverlayController() @@ -715,6 +726,7 @@ void OverlayController::mainEventLoop() case vr::VREvent_DashboardActivated: { LOG( DEBUG ) << "Dashboard activated"; + m_desktopOverlay.update(); m_dashboardVisible = true; } break; diff --git a/src/overlaycontroller.h b/src/overlaycontroller.h index f7c6190..d9427cc 100644 --- a/src/overlaycontroller.h +++ b/src/overlaycontroller.h @@ -39,6 +39,7 @@ #include "tabcontrollers/UtilitiesTabController.h" #include "openvr/ivrinput.h" +#include "openvr/overlay_utils.h" namespace application_strings { @@ -121,6 +122,7 @@ public: // I know it's an ugly hack to make them public to enable external SettingsTabController m_settingsTabController; ReviveTabController m_reviveTabController; UtilitiesTabController m_utilitiesTabController; + overlay::DesktopOverlay m_desktopOverlay; private: QPoint getMousePositionForEvent( vr::VREvent_Mouse_t mouse ); diff --git a/src/res/qml/RootPage.qml b/src/res/qml/RootPage.qml index c891262..6bcd0b8 100644 --- a/src/res/qml/RootPage.qml +++ b/src/res/qml/RootPage.qml @@ -114,6 +114,17 @@ MyStackViewPage { } } + MyPushButton { + id: desktopOverlayButton + activationSoundEnabled: false + text: "Desktop Overlay" + Layout.fillWidth: true + onClicked: { + MyResources.playFocusChangedSound() + mainView.push(desktopOverlayPage) + } + } + MyPushButton { id: statisticsButton activationSoundEnabled: false diff --git a/src/res/qml/common/mainwidget.qml b/src/res/qml/common/mainwidget.qml index a6b2fd2..cf81618 100644 --- a/src/res/qml/common/mainwidget.qml +++ b/src/res/qml/common/mainwidget.qml @@ -5,6 +5,7 @@ import ".." import "../utilities_page" import "../audio_page" import "../motion_page" +import "../desktop_overlay_page" Rectangle { id: root @@ -71,6 +72,11 @@ Rectangle { visible: false } + property DesktopOverlayPage desktopOverlayPage: DesktopOverlayPage { + stackView: mainView + visible: false + } + StackView { id: mainView anchors.fill: parent diff --git a/src/res/qml/desktop_overlay_page/DesktopOverlayPage.qml b/src/res/qml/desktop_overlay_page/DesktopOverlayPage.qml new file mode 100644 index 0000000..b8cff3e --- /dev/null +++ b/src/res/qml/desktop_overlay_page/DesktopOverlayPage.qml @@ -0,0 +1,34 @@ +import QtQuick 2.7 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.3 +import ovras.advsettings 1.0 +import "translation_left_right" +import "translation_back_forwards" +import "translation_up_down" +import "desktop_size" +import "../common" + +MyStackViewPage { + headerText: "Desktop Overlay" + + content: ColumnLayout { + spacing: 18 + + SteamDesktopGroupBox { + } + + SteamDesktopTranslationUpDown { + } + + SteamDesktopTranslationBackForwards { + } + + SteamDesktopTranslationLeftRight { + } + + Item { + Layout.fillHeight: true + } + + } +} diff --git a/src/res/qml/utilities_page/desktop_size/SteamDesktopGroupBox.qml b/src/res/qml/desktop_overlay_page/desktop_size/SteamDesktopGroupBox.qml similarity index 98% rename from src/res/qml/utilities_page/desktop_size/SteamDesktopGroupBox.qml rename to src/res/qml/desktop_overlay_page/desktop_size/SteamDesktopGroupBox.qml index b811785..0bdf3ea 100644 --- a/src/res/qml/utilities_page/desktop_size/SteamDesktopGroupBox.qml +++ b/src/res/qml/desktop_overlay_page/desktop_size/SteamDesktopGroupBox.qml @@ -7,7 +7,7 @@ import "../../common" GroupBox { id: steamDesktopGroupBox Layout.fillWidth: true - + label: MyText { leftPadding: 10 text: "Steam Desktop Overlay Width" @@ -20,14 +20,14 @@ GroupBox { } ColumnLayout { anchors.fill: parent - + Rectangle { color: "#ffffff" height: 1 Layout.fillWidth: true Layout.bottomMargin: 5 } - + ColumnLayout { RowLayout { MyPushButton2 { @@ -38,7 +38,7 @@ GroupBox { steamDesktopWidthSlider.value -= 1.0 } } - + MySlider { id: steamDesktopWidthSlider from: 0.1 @@ -55,7 +55,7 @@ GroupBox { steamDesktopWidthText.text = value.toFixed(1) } } - + MyPushButton2 { id: steamDesktopWidthPlusButton Layout.preferredWidth: 40 @@ -64,7 +64,7 @@ GroupBox { steamDesktopWidthSlider.value += 1.0 } } - + MyTextField { id: steamDesktopWidthText text: "0.0" diff --git a/src/res/qml/desktop_overlay_page/translation_back_forwards/SteamDesktopTranslationBackForwards.qml b/src/res/qml/desktop_overlay_page/translation_back_forwards/SteamDesktopTranslationBackForwards.qml new file mode 100644 index 0000000..6596567 --- /dev/null +++ b/src/res/qml/desktop_overlay_page/translation_back_forwards/SteamDesktopTranslationBackForwards.qml @@ -0,0 +1,78 @@ +import QtQuick 2.7 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.3 +import ovras.advsettings 1.0 +import "../../common" + +GroupBox { + id: steamDesktopGroupBox + Layout.fillWidth: true + + label: MyText { + leftPadding: 10 + text: "Backwards/Forwards Translation" + bottomPadding: -10 + } + background: Rectangle { + color: "transparent" + border.color: "#ffffff" + radius: 8 + } + property real sliderStepSize: 0.10 + property real rightLeftLimit: 4.0 + + ColumnLayout { + anchors.fill: parent + + LineSeparator { + } + + ColumnLayout { + RowLayout { + MyPushButton2 { + Layout.preferredWidth: 40 + text: "-" + onClicked: { + steamDesktopForwardSlider.value -= sliderStepSize + } + } + + MySlider { + id: steamDesktopForwardSlider + from: -rightLeftLimit + to: rightLeftLimit + stepSize: sliderStepSize + value: 0.0 + Layout.fillWidth: true + onValueChanged: { + DesktopOverlay.forwardsMovement = this.value + steamDesktopForwardText.text = this.value.toFixed(2) + } + } + + MyPushButton2 { + Layout.preferredWidth: 40 + text: "+" + onClicked: { + steamDesktopForwardSlider.value += sliderStepSize + } + } + + MyTextField { + id: steamDesktopForwardText + text: "0.0" + keyBoardUID: 611 + Layout.preferredWidth: 100 + Layout.leftMargin: 10 + horizontalAlignment: Text.AlignHCenter + onAcceptableInputChanged: { + steamDesktopForwardSlider.value = this.value + } + } + } + } + } + Component.onCompleted: { + steamDesktopForwardSlider.value = DesktopOverlay.forwardsMovement + } +} diff --git a/src/res/qml/desktop_overlay_page/translation_left_right/SteamDesktopTranslationLeftRight.qml b/src/res/qml/desktop_overlay_page/translation_left_right/SteamDesktopTranslationLeftRight.qml new file mode 100644 index 0000000..5b523bc --- /dev/null +++ b/src/res/qml/desktop_overlay_page/translation_left_right/SteamDesktopTranslationLeftRight.qml @@ -0,0 +1,80 @@ +import QtQuick 2.7 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.3 +import ovras.advsettings 1.0 +import "../../common" + +GroupBox { + id: steamDesktopGroupBox + Layout.fillWidth: true + + label: MyText { + leftPadding: 10 + text: "Left/Right Translation" + bottomPadding: -10 + } + background: Rectangle { + color: "transparent" + border.color: "#ffffff" + radius: 8 + } + property real sliderStepSize: 0.10 + property real rightLeftLimit: 4.0 + + ColumnLayout { + anchors.fill: parent + + LineSeparator { + } + + ColumnLayout { + RowLayout { + MyPushButton2 { + id: steamDesktopWidthMinusButton + Layout.preferredWidth: 40 + text: "-" + onClicked: { + steamDesktopWidthSlider.value -= sliderStepSize + } + } + + MySlider { + id: steamDesktopWidthSlider + from: -rightLeftLimit + to: rightLeftLimit + stepSize: sliderStepSize + value: 0.0 + Layout.fillWidth: true + onValueChanged: { + DesktopOverlay.rightMovement = this.value + steamDesktopWidthText.text = this.value.toFixed(2) + } + } + + MyPushButton2 { + id: steamDesktopWidthPlusButton + Layout.preferredWidth: 40 + text: "+" + onClicked: { + steamDesktopWidthSlider.value += sliderStepSize + } + } + + MyTextField { + id: steamDesktopWidthText + text: "0.0" + keyBoardUID: 611 + Layout.preferredWidth: 100 + Layout.leftMargin: 10 + horizontalAlignment: Text.AlignHCenter + onAcceptableInputChanged: { + steamDesktopWidthSlider.value = this.value + } + } + } + } + } + Component.onCompleted: { + steamDesktopWidthSlider.value = DesktopOverlay.rightMovement + } +} diff --git a/src/res/qml/desktop_overlay_page/translation_up_down/SteamDesktopTranslationUpDown.qml b/src/res/qml/desktop_overlay_page/translation_up_down/SteamDesktopTranslationUpDown.qml new file mode 100644 index 0000000..91b3488 --- /dev/null +++ b/src/res/qml/desktop_overlay_page/translation_up_down/SteamDesktopTranslationUpDown.qml @@ -0,0 +1,78 @@ +import QtQuick 2.7 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.3 +import ovras.advsettings 1.0 +import "../../common" + +GroupBox { + id: steamDesktopGroupBox + Layout.fillWidth: true + + label: MyText { + leftPadding: 10 + text: "Up/Down Translation" + bottomPadding: -10 + } + background: Rectangle { + color: "transparent" + border.color: "#ffffff" + radius: 8 + } + property real sliderStepSize: 0.10 + property real rightLeftLimit: 4.0 + + ColumnLayout { + anchors.fill: parent + + LineSeparator { + } + + ColumnLayout { + RowLayout { + MyPushButton2 { + Layout.preferredWidth: 40 + text: "-" + onClicked: { + steamDesktopUpSlider.value -= sliderStepSize + } + } + + MySlider { + id: steamDesktopUpSlider + from: -rightLeftLimit + to: rightLeftLimit + stepSize: sliderStepSize + value: 0.0 + Layout.fillWidth: true + onValueChanged: { + DesktopOverlay.height = this.value + steamDesktopUpText.text = this.value.toFixed(2) + } + } + + MyPushButton2 { + Layout.preferredWidth: 40 + text: "+" + onClicked: { + steamDesktopUpSlider.value += sliderStepSize + } + } + + MyTextField { + id: steamDesktopUpText + text: "0.0" + keyBoardUID: 611 + Layout.preferredWidth: 100 + Layout.leftMargin: 10 + horizontalAlignment: Text.AlignHCenter + onAcceptableInputChanged: { + steamDesktopUpSlider.value = this.value + } + } + } + } + } + Component.onCompleted: { + steamDesktopUpSlider.value = DesktopOverlay.height + } +} diff --git a/src/res/qml/utilities_page/UtilitiesPage.qml b/src/res/qml/utilities_page/UtilitiesPage.qml index f7ae438..2945d68 100644 --- a/src/res/qml/utilities_page/UtilitiesPage.qml +++ b/src/res/qml/utilities_page/UtilitiesPage.qml @@ -22,10 +22,6 @@ MyStackViewPage { id: alarmGroupBox } - SteamDesktopGroupBox { - id: steamDesktopGroupBox - } - MediaControllerKeys { id: mediaKeysGroupBox } From ab901e90fc294024ba16dd9617d2c37f5cfcd00f Mon Sep 17 00:00:00 2001 From: Vasily Date: Sat, 30 Mar 2019 13:21:49 +0100 Subject: [PATCH 04/15] Implement new way of handling Desktop Overlay width --- src/openvr/overlay_utils.cpp | 3 ++ src/openvr/overlay_utils.h | 1 + .../desktop_size/SteamDesktopGroupBox.qml | 45 +++++-------------- .../SteamDesktopTranslationBackForwards.qml | 1 - .../SteamDesktopTranslationLeftRight.qml | 17 +++---- .../SteamDesktopTranslationUpDown.qml | 1 - src/res/qml/utilities_page/UtilitiesPage.qml | 1 - 7 files changed, 23 insertions(+), 46 deletions(-) diff --git a/src/openvr/overlay_utils.cpp b/src/openvr/overlay_utils.cpp index 6f563ee..d70ec0d 100644 --- a/src/openvr/overlay_utils.cpp +++ b/src/openvr/overlay_utils.cpp @@ -72,6 +72,9 @@ overlay::DesktopOverlay::DesktopOverlay() m_rightMovement = settings.value( strings::rightMovementSettingsName, defaultMovement ) .toDouble(); + m_upMovement + = settings.value( strings::upMovementSettingsName, defaultMovement ) + .toDouble(); settings.endGroup(); } diff --git a/src/openvr/overlay_utils.h b/src/openvr/overlay_utils.h index 22875a9..e882b53 100644 --- a/src/openvr/overlay_utils.h +++ b/src/openvr/overlay_utils.h @@ -24,6 +24,7 @@ namespace strings constexpr auto defaultOverlayWidth = 4.0; constexpr auto defaultMovement = 0.0; +constexpr auto defaultWidth = 1.0; class DesktopOverlay : public QObject { diff --git a/src/res/qml/desktop_overlay_page/desktop_size/SteamDesktopGroupBox.qml b/src/res/qml/desktop_overlay_page/desktop_size/SteamDesktopGroupBox.qml index 0bdf3ea..f5321ed 100644 --- a/src/res/qml/desktop_overlay_page/desktop_size/SteamDesktopGroupBox.qml +++ b/src/res/qml/desktop_overlay_page/desktop_size/SteamDesktopGroupBox.qml @@ -5,7 +5,6 @@ import ovras.advsettings 1.0 import "../../common" GroupBox { - id: steamDesktopGroupBox Layout.fillWidth: true label: MyText { @@ -18,24 +17,23 @@ GroupBox { border.color: "#ffffff" radius: 8 } + + property real sliderStepSize: 1.0 + property real sliderStartingValue: 1.0 + ColumnLayout { anchors.fill: parent - Rectangle { - color: "#ffffff" - height: 1 - Layout.fillWidth: true - Layout.bottomMargin: 5 + LineSeparator { } ColumnLayout { RowLayout { MyPushButton2 { - id: steamDesktopWidthMinusButton Layout.preferredWidth: 40 text: "-" onClicked: { - steamDesktopWidthSlider.value -= 1.0 + steamDesktopWidthSlider.value -= sliderStepSize } } @@ -44,24 +42,22 @@ GroupBox { from: 0.1 to: 32.0 stepSize: 0.1 - value: 1.0 + value: sliderStartingValue Layout.fillWidth: true onPositionChanged: { - var val = this.from + ( this.position * (this.to - this.from)) - steamDesktopWidthText.text = val.toFixed(1) + // } onValueChanged: { - UtilitiesTabController.setSteamDesktopOverlayWidth(value, false) - steamDesktopWidthText.text = value.toFixed(1) + DesktopOverlay.width = this.value + steamDesktopWidthText.text = this.value.toFixed(2) } } MyPushButton2 { - id: steamDesktopWidthPlusButton Layout.preferredWidth: 40 text: "+" onClicked: { - steamDesktopWidthSlider.value += 1.0 + steamDesktopWidthSlider.value += sliderStepSize } } @@ -79,30 +75,13 @@ GroupBox { val = 0.1 } steamDesktopWidthSlider.value = val - UtilitiesTabController.setSteamDesktopOverlayWidth(val, false) } - text = UtilitiesTabController.steamDesktopOverlayWidth.toFixed(1) } } } } } Component.onCompleted: { - steamDesktopGroupBox.visible = UtilitiesTabController.steamDesktopOverlayAvailable - if (steamDesktopGroupBox.visible) { - steamDesktopWidthSlider.value = UtilitiesTabController.steamDesktopOverlayWidth - } - } - Connections { - target: UtilitiesTabController - onSteamDesktopOverlayAvailableChanged: { - steamDesktopGroupBox.visible = UtilitiesTabController.steamDesktopOverlayAvailable - if (steamDesktopGroupBox.visible) { - steamDesktopWidthSlider.value = UtilitiesTabController.steamDesktopOverlayWidth - } - } - onSteamDesktopOverlayWidthChanged: { - steamDesktopWidthSlider.value = UtilitiesTabController.steamDesktopOverlayWidth - } + steamDesktopWidthSlider.value = DesktopOverlay.width } } diff --git a/src/res/qml/desktop_overlay_page/translation_back_forwards/SteamDesktopTranslationBackForwards.qml b/src/res/qml/desktop_overlay_page/translation_back_forwards/SteamDesktopTranslationBackForwards.qml index 6596567..c3f7ddd 100644 --- a/src/res/qml/desktop_overlay_page/translation_back_forwards/SteamDesktopTranslationBackForwards.qml +++ b/src/res/qml/desktop_overlay_page/translation_back_forwards/SteamDesktopTranslationBackForwards.qml @@ -5,7 +5,6 @@ import ovras.advsettings 1.0 import "../../common" GroupBox { - id: steamDesktopGroupBox Layout.fillWidth: true label: MyText { diff --git a/src/res/qml/desktop_overlay_page/translation_left_right/SteamDesktopTranslationLeftRight.qml b/src/res/qml/desktop_overlay_page/translation_left_right/SteamDesktopTranslationLeftRight.qml index 5b523bc..8d4d865 100644 --- a/src/res/qml/desktop_overlay_page/translation_left_right/SteamDesktopTranslationLeftRight.qml +++ b/src/res/qml/desktop_overlay_page/translation_left_right/SteamDesktopTranslationLeftRight.qml @@ -5,7 +5,6 @@ import ovras.advsettings 1.0 import "../../common" GroupBox { - id: steamDesktopGroupBox Layout.fillWidth: true label: MyText { @@ -30,16 +29,15 @@ GroupBox { ColumnLayout { RowLayout { MyPushButton2 { - id: steamDesktopWidthMinusButton Layout.preferredWidth: 40 text: "-" onClicked: { - steamDesktopWidthSlider.value -= sliderStepSize + steamDesktopRightSlider.value -= sliderStepSize } } MySlider { - id: steamDesktopWidthSlider + id: steamDesktopRightSlider from: -rightLeftLimit to: rightLeftLimit stepSize: sliderStepSize @@ -47,34 +45,33 @@ GroupBox { Layout.fillWidth: true onValueChanged: { DesktopOverlay.rightMovement = this.value - steamDesktopWidthText.text = this.value.toFixed(2) + steamDesktopRightText.text = this.value.toFixed(2) } } MyPushButton2 { - id: steamDesktopWidthPlusButton Layout.preferredWidth: 40 text: "+" onClicked: { - steamDesktopWidthSlider.value += sliderStepSize + steamDesktopRightSlider.value += sliderStepSize } } MyTextField { - id: steamDesktopWidthText + id: steamDesktopRightText text: "0.0" keyBoardUID: 611 Layout.preferredWidth: 100 Layout.leftMargin: 10 horizontalAlignment: Text.AlignHCenter onAcceptableInputChanged: { - steamDesktopWidthSlider.value = this.value + steamDesktopRightSlider.value = this.value } } } } } Component.onCompleted: { - steamDesktopWidthSlider.value = DesktopOverlay.rightMovement + steamDesktopRightSlider.value = DesktopOverlay.rightMovement } } diff --git a/src/res/qml/desktop_overlay_page/translation_up_down/SteamDesktopTranslationUpDown.qml b/src/res/qml/desktop_overlay_page/translation_up_down/SteamDesktopTranslationUpDown.qml index 91b3488..7b56435 100644 --- a/src/res/qml/desktop_overlay_page/translation_up_down/SteamDesktopTranslationUpDown.qml +++ b/src/res/qml/desktop_overlay_page/translation_up_down/SteamDesktopTranslationUpDown.qml @@ -5,7 +5,6 @@ import ovras.advsettings 1.0 import "../../common" GroupBox { - id: steamDesktopGroupBox Layout.fillWidth: true label: MyText { diff --git a/src/res/qml/utilities_page/UtilitiesPage.qml b/src/res/qml/utilities_page/UtilitiesPage.qml index 2945d68..bce8d48 100644 --- a/src/res/qml/utilities_page/UtilitiesPage.qml +++ b/src/res/qml/utilities_page/UtilitiesPage.qml @@ -4,7 +4,6 @@ import QtQuick.Layouts 1.3 import ovras.advsettings 1.0 import "media_keys" import "alarm_clock" -import "desktop_size" import "keyboard_utils" import "../common" From cba76f68464bc3bcadc502f542a07c48ad8a07c5 Mon Sep 17 00:00:00 2001 From: Vasily Date: Sat, 30 Mar 2019 14:33:33 +0100 Subject: [PATCH 05/15] Remove old desktop width C++ code --- src/tabcontrollers/UtilitiesTabController.cpp | 141 ------------------ src/tabcontrollers/UtilitiesTabController.h | 21 +-- 2 files changed, 1 insertion(+), 161 deletions(-) diff --git a/src/tabcontrollers/UtilitiesTabController.cpp b/src/tabcontrollers/UtilitiesTabController.cpp index 8cec8d4..093ff7d 100644 --- a/src/tabcontrollers/UtilitiesTabController.cpp +++ b/src/tabcontrollers/UtilitiesTabController.cpp @@ -13,8 +13,6 @@ // application namespace namespace advsettings { -constexpr auto steamDesktopOverlaykey = "valve.steam.desktop"; - void UtilitiesTabController::initStage1() { #ifdef _WIN32 @@ -28,13 +26,10 @@ void UtilitiesTabController::initStage1() auto qAlarmIsModal = settings->value( "alarmIsModal", m_alarmIsModal ); auto qAlarmHour = settings->value( "alarmHour", 0 ); auto qAlarmMinute = settings->value( "alarmMinute", 0 ); - auto qDesktopWidth = settings->value( "desktopWidth", 4.0 ); settings->endGroup(); m_alarmEnabled = qAlarmEnabled.toBool(); m_alarmIsModal = qAlarmIsModal.toBool(); m_alarmTime = QTime( qAlarmHour.toInt(), qAlarmMinute.toInt() ); - - setUpDesktopOverlay( qDesktopWidth.toFloat() ); } void UtilitiesTabController::initStage2( OverlayController* var_parent, @@ -311,42 +306,6 @@ void UtilitiesTabController::eventLoopTick() { if ( settingsUpdateCounter >= k_utilitiesSettingsUpdateCounter ) { - vr::VROverlayHandle_t pOverlayHandle; - auto error = vr::VROverlay()->FindOverlay( steamDesktopOverlaykey, - &pOverlayHandle ); - if ( error == vr::VROverlayError_None ) - { - if ( !m_steamDesktopOverlayAvailable ) - { - m_steamDesktopOverlayAvailable = true; - emit steamDesktopOverlayAvailableChanged( - m_steamDesktopOverlayAvailable ); - } - float width; - error = vr::VROverlay()->GetOverlayWidthInMeters( pOverlayHandle, - &width ); - if ( error != vr::VROverlayError_None ) - { - LOG( ERROR ) - << "Could not read overlay width of \"" - << steamDesktopOverlaykey << "\": " - << vr::VROverlay()->GetOverlayErrorNameFromEnum( error ); - } - else - { - setSteamDesktopOverlayWidth( width, true, false ); - } - } - else - { - if ( m_steamDesktopOverlayAvailable ) - { - m_steamDesktopOverlayAvailable = false; - emit steamDesktopOverlayAvailableChanged( - m_steamDesktopOverlayAvailable ); - } - } - if ( m_alarmEnabled && m_alarmTime.isValid() ) { auto now = QTime::currentTime(); @@ -558,104 +517,4 @@ void UtilitiesTabController::eventLoopTick() } } -bool steamDesktopOverlayExists() -{ - vr::VROverlayHandle_t pOverlayHandle = 0; - auto error = vr::VROverlay()->FindOverlay( steamDesktopOverlaykey, - &pOverlayHandle ); - if ( error != vr::VROverlayError_None ) - { - LOG( DEBUG ) << "Could not find overlay \"" << steamDesktopOverlaykey - << "\": " - << vr::VROverlay()->GetOverlayErrorNameFromEnum( error ); - return false; - } - return true; -} - -void UtilitiesTabController::setUpDesktopOverlay( float desktopWidthInMeters ) -{ - auto setOverlayVariablesSuccess = [this, desktopWidthInMeters]() { - m_steamDesktopOverlayAvailable = true; - setSteamDesktopOverlayWidth( desktopWidthInMeters, true, true ); - LOG( INFO ) << "Found overlay \"" << steamDesktopOverlaykey << "\"."; - }; - - if ( steamDesktopOverlayExists() ) - { - setOverlayVariablesSuccess(); - return; - } - - constexpr auto timeBetweenAdditionalAttempts = std::chrono::seconds( 1 ); - constexpr auto maxAttempts = 7; - for ( int attempts = 0; attempts < maxAttempts; ++attempts ) - { - std::this_thread::sleep_for( timeBetweenAdditionalAttempts ); - if ( steamDesktopOverlayExists() ) - { - setOverlayVariablesSuccess(); - return; - } - } - LOG( INFO ) << "Could not find overlay \"" << steamDesktopOverlaykey - << "\" after " << maxAttempts << " extra attempts."; -} - -bool UtilitiesTabController::steamDesktopOverlayAvailable() const -{ - return m_steamDesktopOverlayAvailable; -} - -float UtilitiesTabController::steamDesktopOverlayWidth() const -{ - return m_steamDesktopOverlayWidth; -} - -void UtilitiesTabController::setSteamDesktopOverlayWidth( float width, - bool notify, - bool notifyOpenVr ) -{ - if ( std::abs( m_steamDesktopOverlayWidth - width ) > 0.01f ) - { - m_steamDesktopOverlayWidth = width; - - auto settings = OverlayController::appSettings(); - settings->beginGroup( "utilitiesSettings" ); - settings->setValue( "desktopWidth", m_steamDesktopOverlayWidth ); - settings->endGroup(); - - if ( notifyOpenVr ) - { - vr::VROverlayHandle_t pOverlayHandle; - auto error = vr::VROverlay()->FindOverlay( steamDesktopOverlaykey, - &pOverlayHandle ); - if ( error != vr::VROverlayError_None ) - { - LOG( ERROR ) - << "Could not find overlay \"" << steamDesktopOverlaykey - << "\": " - << vr::VROverlay()->GetOverlayErrorNameFromEnum( error ); - } - else - { - error = vr::VROverlay()->SetOverlayWidthInMeters( - pOverlayHandle, m_steamDesktopOverlayWidth ); - if ( error != vr::VROverlayError_None ) - { - LOG( ERROR ) - << "Could not modify overlay width of \"" - << steamDesktopOverlaykey << "\": " - << vr::VROverlay()->GetOverlayErrorNameFromEnum( - error ); - } - } - } - if ( notify ) - { - emit steamDesktopOverlayWidthChanged( m_steamDesktopOverlayWidth ); - } - } -} - } // namespace advsettings diff --git a/src/tabcontrollers/UtilitiesTabController.h b/src/tabcontrollers/UtilitiesTabController.h index 7f05e3b..14c2b5e 100644 --- a/src/tabcontrollers/UtilitiesTabController.h +++ b/src/tabcontrollers/UtilitiesTabController.h @@ -25,16 +25,8 @@ class UtilitiesTabController : public QObject NOTIFY alarmTimeHourChanged ) Q_PROPERTY( int alarmTimeMinute READ alarmTimeMinute WRITE setAlarmTimeMinute NOTIFY alarmTimeMinuteChanged ) - Q_PROPERTY( - bool steamDesktopOverlayAvailable READ steamDesktopOverlayAvailable - NOTIFY steamDesktopOverlayAvailableChanged ) - Q_PROPERTY( - float steamDesktopOverlayWidth READ steamDesktopOverlayWidth WRITE - setSteamDesktopOverlayWidth NOTIFY steamDesktopOverlayWidthChanged ) private: - void setUpDesktopOverlay( float desktopWidthInMeters ); - OverlayController* m_parent; QQuickWindow* m_widget; @@ -44,8 +36,7 @@ private: bool m_alarmIsModal = true; QTime m_alarmTime; QTime m_alarmLastCheckTime; - bool m_steamDesktopOverlayAvailable = false; - float m_steamDesktopOverlayWidth = 4.0f; + vr::VROverlayHandle_t m_batteryOverlayHandles[vr::k_unMaxTrackedDeviceCount] = { 0 }; int m_batteryState[vr::k_unMaxTrackedDeviceCount]; @@ -64,9 +55,6 @@ public: int alarmTimeHour() const; int alarmTimeMinute() const; - bool steamDesktopOverlayAvailable() const; - float steamDesktopOverlayWidth() const; - public slots: void sendKeyboardInput( QString input ); void sendKeyboardEnter(); @@ -86,18 +74,11 @@ public slots: void modAlarmTimeHour( int value, bool notify = true ); void modAlarmTimeMinute( int value, bool notify = true ); - void setSteamDesktopOverlayWidth( float width, - bool notify = true, - bool notifyOpenVr = true ); - signals: void alarmEnabledChanged( bool enabled ); void alarmIsModalChanged( bool modal ); void alarmTimeHourChanged( int hour ); void alarmTimeMinuteChanged( int min ); - - void steamDesktopOverlayAvailableChanged( bool available ); - void steamDesktopOverlayWidthChanged( float width ); }; } // namespace advsettings From e0ea7e3083215da3af758c8ef699d16c83784f97 Mon Sep 17 00:00:00 2001 From: Vasily Date: Sat, 30 Mar 2019 18:20:40 +0100 Subject: [PATCH 06/15] Fix incorrect behavior in QML --- src/openvr/overlay_utils.cpp | 13 ++- src/res/qml/common/FullWidthSliderBox.qml | 95 +++++++++++++++++++ .../desktop_size/SteamDesktopGroupBox.qml | 89 +++-------------- .../SteamDesktopTranslationBackForwards.qml | 78 +++------------ .../SteamDesktopTranslationLeftRight.qml | 78 +++------------ .../SteamDesktopTranslationUpDown.qml | 78 +++------------ 6 files changed, 151 insertions(+), 280 deletions(-) create mode 100644 src/res/qml/common/FullWidthSliderBox.qml diff --git a/src/openvr/overlay_utils.cpp b/src/openvr/overlay_utils.cpp index d70ec0d..c2dc164 100644 --- a/src/openvr/overlay_utils.cpp +++ b/src/openvr/overlay_utils.cpp @@ -1,4 +1,5 @@ #include "overlay_utils.h" +#include "../overlaycontroller.h" namespace overlay { @@ -54,7 +55,10 @@ void setDesktopOverlayWidth( double width ) void setSettingsToValue( const std::string setting, const double value ) { - QSettings settings; + QSettings settings( QSettings::Format::IniFormat, + QSettings::Scope::UserScope, + application_strings::applicationOrganizationName, + application_strings::applicationName ); settings.beginGroup( strings::settingsGroupName ); settings.setValue( setting.c_str(), value ); settings.endGroup(); @@ -62,7 +66,12 @@ void setSettingsToValue( const std::string setting, const double value ) overlay::DesktopOverlay::DesktopOverlay() { - QSettings settings; + QSettings settings( QSettings::Format::IniFormat, + QSettings::Scope::UserScope, + application_strings::applicationOrganizationName, + application_strings::applicationName ); + + LOG( INFO ) << settings.fileName(); settings.beginGroup( strings::settingsGroupName ); m_width = settings.value( strings::widthSettingsName, defaultOverlayWidth ) .toDouble(); diff --git a/src/res/qml/common/FullWidthSliderBox.qml b/src/res/qml/common/FullWidthSliderBox.qml new file mode 100644 index 0000000..5a231ec --- /dev/null +++ b/src/res/qml/common/FullWidthSliderBox.qml @@ -0,0 +1,95 @@ +import QtQuick 2.7 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.3 +import ovras.advsettings 1.0 + +GroupBox { + // Public properties + // Overload + property alias headerMessage: headerText.text + property alias sliderText: steamDesktopForwardText.text + property alias sliderValue: steamDesktopForwardSlider.value + property alias lowerLimit: steamDesktopForwardSlider.from + property alias upperLimit: steamDesktopForwardSlider.to + + + function onValueChanged(value) { + + } + + function onComponentComplete() { + + } + + + // Private properties + id: sliderBox + Layout.fillWidth: true + label: MyText { + id: headerText + leftPadding: 10 + text: "MISSING HEADER TEXT" + bottomPadding: -10 + } + background: Rectangle { + color: "transparent" + border.color: "#ffffff" + radius: 8 + } + + property real sliderStepSize: 0.10 + readonly property real rightLeftLimit: 4.0 + + ColumnLayout { + anchors.fill: parent + + LineSeparator { + } + + ColumnLayout { + RowLayout { + MyPushButton2 { + Layout.preferredWidth: 40 + text: "-" + onClicked: { + steamDesktopForwardSlider.value -= sliderStepSize + } + } + + MySlider { + id: steamDesktopForwardSlider + from: -rightLeftLimit + to: rightLeftLimit + stepSize: sliderStepSize + Layout.fillWidth: true + onValueChanged: { + sliderBox.onValueChanged(this.value) + } + } + + MyPushButton2 { + Layout.preferredWidth: 40 + text: "+" + onClicked: { + steamDesktopForwardSlider.value += sliderStepSize + } + } + + MyTextField { + id: steamDesktopForwardText + text: "0.0" + keyBoardUID: 611 + Layout.preferredWidth: 100 + Layout.leftMargin: 10 + horizontalAlignment: Text.AlignHCenter + onAcceptableInputChanged: { + steamDesktopForwardSlider.value = this.value + } + } + } + } + } + Component.onCompleted: { + sliderBox.onComponentComplete() + } +} diff --git a/src/res/qml/desktop_overlay_page/desktop_size/SteamDesktopGroupBox.qml b/src/res/qml/desktop_overlay_page/desktop_size/SteamDesktopGroupBox.qml index f5321ed..a9b7b95 100644 --- a/src/res/qml/desktop_overlay_page/desktop_size/SteamDesktopGroupBox.qml +++ b/src/res/qml/desktop_overlay_page/desktop_size/SteamDesktopGroupBox.qml @@ -4,84 +4,19 @@ import QtQuick.Layouts 1.3 import ovras.advsettings 1.0 import "../../common" -GroupBox { - Layout.fillWidth: true +FullWidthSliderBox { + headerMessage: "Overlay Width" - label: MyText { - leftPadding: 10 - text: "Steam Desktop Overlay Width" - bottomPadding: -10 + lowerLimit: 0.0 + upperLimit: 32.0 + sliderStepSize: 0.5 + + function onValueChanged(value) { + DesktopOverlay.width = value + sliderText = value.toFixed(2) } - background: Rectangle { - color: "transparent" - border.color: "#ffffff" - radius: 8 - } - - property real sliderStepSize: 1.0 - property real sliderStartingValue: 1.0 - - ColumnLayout { - anchors.fill: parent - - LineSeparator { - } - - ColumnLayout { - RowLayout { - MyPushButton2 { - Layout.preferredWidth: 40 - text: "-" - onClicked: { - steamDesktopWidthSlider.value -= sliderStepSize - } - } - - MySlider { - id: steamDesktopWidthSlider - from: 0.1 - to: 32.0 - stepSize: 0.1 - value: sliderStartingValue - Layout.fillWidth: true - onPositionChanged: { - // - } - onValueChanged: { - DesktopOverlay.width = this.value - steamDesktopWidthText.text = this.value.toFixed(2) - } - } - - MyPushButton2 { - Layout.preferredWidth: 40 - text: "+" - onClicked: { - steamDesktopWidthSlider.value += sliderStepSize - } - } - - MyTextField { - id: steamDesktopWidthText - text: "0.0" - keyBoardUID: 611 - Layout.preferredWidth: 100 - Layout.leftMargin: 10 - horizontalAlignment: Text.AlignHCenter - function onInputEvent(input) { - var val = parseFloat(input) - if (!isNaN(val)) { - if (val < 0.1) { - val = 0.1 - } - steamDesktopWidthSlider.value = val - } - } - } - } - } - } - Component.onCompleted: { - steamDesktopWidthSlider.value = DesktopOverlay.width + function onComponentComplete() { + sliderValue = DesktopOverlay.width } } + diff --git a/src/res/qml/desktop_overlay_page/translation_back_forwards/SteamDesktopTranslationBackForwards.qml b/src/res/qml/desktop_overlay_page/translation_back_forwards/SteamDesktopTranslationBackForwards.qml index c3f7ddd..be88c06 100644 --- a/src/res/qml/desktop_overlay_page/translation_back_forwards/SteamDesktopTranslationBackForwards.qml +++ b/src/res/qml/desktop_overlay_page/translation_back_forwards/SteamDesktopTranslationBackForwards.qml @@ -4,74 +4,18 @@ import QtQuick.Layouts 1.3 import ovras.advsettings 1.0 import "../../common" -GroupBox { - Layout.fillWidth: true +FullWidthSliderBox { + headerMessage: "Forwards/Backwards Translation" - label: MyText { - leftPadding: 10 - text: "Backwards/Forwards Translation" - bottomPadding: -10 + lowerLimit: -4.0 + upperLimit: 4.0 + sliderStepSize: 0.10 + + function onValueChanged(value) { + DesktopOverlay.forwardsMovement = value + sliderText = value.toFixed(2) } - background: Rectangle { - color: "transparent" - border.color: "#ffffff" - radius: 8 - } - property real sliderStepSize: 0.10 - property real rightLeftLimit: 4.0 - - ColumnLayout { - anchors.fill: parent - - LineSeparator { - } - - ColumnLayout { - RowLayout { - MyPushButton2 { - Layout.preferredWidth: 40 - text: "-" - onClicked: { - steamDesktopForwardSlider.value -= sliderStepSize - } - } - - MySlider { - id: steamDesktopForwardSlider - from: -rightLeftLimit - to: rightLeftLimit - stepSize: sliderStepSize - value: 0.0 - Layout.fillWidth: true - onValueChanged: { - DesktopOverlay.forwardsMovement = this.value - steamDesktopForwardText.text = this.value.toFixed(2) - } - } - - MyPushButton2 { - Layout.preferredWidth: 40 - text: "+" - onClicked: { - steamDesktopForwardSlider.value += sliderStepSize - } - } - - MyTextField { - id: steamDesktopForwardText - text: "0.0" - keyBoardUID: 611 - Layout.preferredWidth: 100 - Layout.leftMargin: 10 - horizontalAlignment: Text.AlignHCenter - onAcceptableInputChanged: { - steamDesktopForwardSlider.value = this.value - } - } - } - } - } - Component.onCompleted: { - steamDesktopForwardSlider.value = DesktopOverlay.forwardsMovement + function onComponentComplete() { + sliderValue = DesktopOverlay.forwardsMovement } } diff --git a/src/res/qml/desktop_overlay_page/translation_left_right/SteamDesktopTranslationLeftRight.qml b/src/res/qml/desktop_overlay_page/translation_left_right/SteamDesktopTranslationLeftRight.qml index 8d4d865..8938bdd 100644 --- a/src/res/qml/desktop_overlay_page/translation_left_right/SteamDesktopTranslationLeftRight.qml +++ b/src/res/qml/desktop_overlay_page/translation_left_right/SteamDesktopTranslationLeftRight.qml @@ -4,74 +4,18 @@ import QtQuick.Layouts 1.3 import ovras.advsettings 1.0 import "../../common" -GroupBox { - Layout.fillWidth: true +FullWidthSliderBox { + headerMessage: "Left/Right Translation" - label: MyText { - leftPadding: 10 - text: "Left/Right Translation" - bottomPadding: -10 + lowerLimit: -4.0 + upperLimit: 4.0 + sliderStepSize: 0.10 + + function onValueChanged(value) { + DesktopOverlay.rightMovement = value + sliderText = value.toFixed(2) } - background: Rectangle { - color: "transparent" - border.color: "#ffffff" - radius: 8 - } - property real sliderStepSize: 0.10 - property real rightLeftLimit: 4.0 - - ColumnLayout { - anchors.fill: parent - - LineSeparator { - } - - ColumnLayout { - RowLayout { - MyPushButton2 { - Layout.preferredWidth: 40 - text: "-" - onClicked: { - steamDesktopRightSlider.value -= sliderStepSize - } - } - - MySlider { - id: steamDesktopRightSlider - from: -rightLeftLimit - to: rightLeftLimit - stepSize: sliderStepSize - value: 0.0 - Layout.fillWidth: true - onValueChanged: { - DesktopOverlay.rightMovement = this.value - steamDesktopRightText.text = this.value.toFixed(2) - } - } - - MyPushButton2 { - Layout.preferredWidth: 40 - text: "+" - onClicked: { - steamDesktopRightSlider.value += sliderStepSize - } - } - - MyTextField { - id: steamDesktopRightText - text: "0.0" - keyBoardUID: 611 - Layout.preferredWidth: 100 - Layout.leftMargin: 10 - horizontalAlignment: Text.AlignHCenter - onAcceptableInputChanged: { - steamDesktopRightSlider.value = this.value - } - } - } - } - } - Component.onCompleted: { - steamDesktopRightSlider.value = DesktopOverlay.rightMovement + function onComponentComplete() { + sliderValue = DesktopOverlay.rightMovement } } diff --git a/src/res/qml/desktop_overlay_page/translation_up_down/SteamDesktopTranslationUpDown.qml b/src/res/qml/desktop_overlay_page/translation_up_down/SteamDesktopTranslationUpDown.qml index 7b56435..f2d9997 100644 --- a/src/res/qml/desktop_overlay_page/translation_up_down/SteamDesktopTranslationUpDown.qml +++ b/src/res/qml/desktop_overlay_page/translation_up_down/SteamDesktopTranslationUpDown.qml @@ -4,74 +4,18 @@ import QtQuick.Layouts 1.3 import ovras.advsettings 1.0 import "../../common" -GroupBox { - Layout.fillWidth: true +FullWidthSliderBox { + headerMessage: "Up/Down Translation" - label: MyText { - leftPadding: 10 - text: "Up/Down Translation" - bottomPadding: -10 + lowerLimit: -4.0 + upperLimit: 4.0 + sliderStepSize: 0.10 + + function onValueChanged(value) { + DesktopOverlay.height = value + sliderText = value.toFixed(2) } - background: Rectangle { - color: "transparent" - border.color: "#ffffff" - radius: 8 - } - property real sliderStepSize: 0.10 - property real rightLeftLimit: 4.0 - - ColumnLayout { - anchors.fill: parent - - LineSeparator { - } - - ColumnLayout { - RowLayout { - MyPushButton2 { - Layout.preferredWidth: 40 - text: "-" - onClicked: { - steamDesktopUpSlider.value -= sliderStepSize - } - } - - MySlider { - id: steamDesktopUpSlider - from: -rightLeftLimit - to: rightLeftLimit - stepSize: sliderStepSize - value: 0.0 - Layout.fillWidth: true - onValueChanged: { - DesktopOverlay.height = this.value - steamDesktopUpText.text = this.value.toFixed(2) - } - } - - MyPushButton2 { - Layout.preferredWidth: 40 - text: "+" - onClicked: { - steamDesktopUpSlider.value += sliderStepSize - } - } - - MyTextField { - id: steamDesktopUpText - text: "0.0" - keyBoardUID: 611 - Layout.preferredWidth: 100 - Layout.leftMargin: 10 - horizontalAlignment: Text.AlignHCenter - onAcceptableInputChanged: { - steamDesktopUpSlider.value = this.value - } - } - } - } - } - Component.onCompleted: { - steamDesktopUpSlider.value = DesktopOverlay.height + function onComponentComplete() { + sliderValue = DesktopOverlay.height } } From c0f6f2f62164f546de982c1346efe10a5928ff0b Mon Sep 17 00:00:00 2001 From: Vasily Date: Sat, 30 Mar 2019 18:29:59 +0100 Subject: [PATCH 07/15] Remove faulty function to set value with keyboard --- src/res/qml/common/FullWidthSliderBox.qml | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/res/qml/common/FullWidthSliderBox.qml b/src/res/qml/common/FullWidthSliderBox.qml index 5a231ec..7129008 100644 --- a/src/res/qml/common/FullWidthSliderBox.qml +++ b/src/res/qml/common/FullWidthSliderBox.qml @@ -82,9 +82,6 @@ GroupBox { Layout.preferredWidth: 100 Layout.leftMargin: 10 horizontalAlignment: Text.AlignHCenter - onAcceptableInputChanged: { - steamDesktopForwardSlider.value = this.value - } } } } From 1f7e731de1b7a9c594958603c11a5688c5d5a3dd Mon Sep 17 00:00:00 2001 From: Vasily Date: Sat, 30 Mar 2019 18:52:08 +0100 Subject: [PATCH 08/15] Improve abstraction in update function --- src/openvr/overlay_utils.cpp | 59 +++++++++++++++++++----------------- src/openvr/overlay_utils.h | 3 ++ 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/openvr/overlay_utils.cpp b/src/openvr/overlay_utils.cpp index c2dc164..7d71315 100644 --- a/src/openvr/overlay_utils.cpp +++ b/src/openvr/overlay_utils.cpp @@ -89,37 +89,13 @@ overlay::DesktopOverlay::DesktopOverlay() void DesktopOverlay::update() { + setDesktopOverlayWidth( m_width ); + auto positionMatrix = getDesktopOverlayPositions(); - auto position = QVector3D( positionMatrix.m[0][3], - positionMatrix.m[1][3], - positionMatrix.m[2][3] ); + auto changedPositions = getChangedMatrix( positionMatrix ); - const auto screenRight = QVector3D( positionMatrix.m[0][0], - positionMatrix.m[1][0], - positionMatrix.m[2][0] ); - - const auto screenForwards = QVector3D( positionMatrix.m[0][2], - positionMatrix.m[1][2], - positionMatrix.m[2][2] ); - - const auto screenUp = QVector3D( positionMatrix.m[0][1], - positionMatrix.m[1][1], - positionMatrix.m[2][1] ); - - position += ( static_cast( m_rightMovement ) * screenRight ); - - position += ( static_cast( m_forwardsMovement ) * screenForwards ); - - position += ( static_cast( m_upMovement ) * screenUp ); - - positionMatrix.m[0][3] = position.x(); - positionMatrix.m[1][3] = position.y(); - positionMatrix.m[2][3] = position.z(); - - setDesktopOverlayPositions( positionMatrix ); - - setDesktopOverlayWidth( m_width ); + setDesktopOverlayPositions( changedPositions ); } bool DesktopOverlay::isAvailable() const @@ -186,4 +162,31 @@ double DesktopOverlay::getCurrentHeight() const noexcept return m_upMovement; } +vr::HmdMatrix34_t + DesktopOverlay::getChangedMatrix( vr::HmdMatrix34_t& matrix ) const noexcept +{ + auto position = QVector3D( matrix.m[0][3], matrix.m[1][3], matrix.m[2][3] ); + + const auto screenRight + = QVector3D( matrix.m[0][0], matrix.m[1][0], matrix.m[2][0] ); + + const auto screenForwards + = QVector3D( matrix.m[0][2], matrix.m[1][2], matrix.m[2][2] ); + + const auto screenUp + = QVector3D( matrix.m[0][1], matrix.m[1][1], matrix.m[2][1] ); + + position += ( static_cast( m_rightMovement ) * screenRight ); + + position += ( static_cast( m_forwardsMovement ) * screenForwards ); + + position += ( static_cast( m_upMovement ) * screenUp ); + + matrix.m[0][3] = position.x(); + matrix.m[1][3] = position.y(); + matrix.m[2][3] = position.z(); + + return matrix; +} + } // namespace overlay diff --git a/src/openvr/overlay_utils.h b/src/openvr/overlay_utils.h index e882b53..03981b3 100644 --- a/src/openvr/overlay_utils.h +++ b/src/openvr/overlay_utils.h @@ -56,6 +56,9 @@ public: double getCurrentHeight() const noexcept; private: + vr::HmdMatrix34_t getChangedMatrix( vr::HmdMatrix34_t& matrix ) const + noexcept; + double m_width = defaultOverlayWidth; double m_forwardsMovement = defaultMovement; double m_rightMovement = defaultMovement; From 3cb04f4b90e25b5177c9739a1a1c54febf0acf48 Mon Sep 17 00:00:00 2001 From: Vasily Date: Sat, 30 Mar 2019 18:59:52 +0100 Subject: [PATCH 09/15] Update documentation for the desktop overlay page --- Readme.md | 15 +++++++++++++++ docs/screenshots/DesktopOverlayPage.png | Bin 0 -> 36772 bytes docs/screenshots/UtilitiesPage.png | Bin 43489 -> 38179 bytes 3 files changed, 15 insertions(+) create mode 100644 docs/screenshots/DesktopOverlayPage.png diff --git a/Readme.md b/Readme.md index d4ec599..a96964f 100644 --- a/Readme.md +++ b/Readme.md @@ -1,3 +1,4 @@ + ![language](https://img.shields.io/badge/Language-C%2B%2B17%2C%20QML-green.svg) ![dependencies](https://img.shields.io/badge/Dependencies-OpenVR%2C%20Qt5%2C%20Python3-green.svg) ![license_gpl3](https://img.shields.io/badge/License-GPL%203.0-green.svg) @@ -23,6 +24,7 @@ > * [Space Fix Page](#space_fix_page) > * [Audio Page](#audio_page) > * [Utilities Page](#utilities_page) + > * [Desktop Overlay Page](#desktop_overlay_page) > * [Statistics Page](#statistics_page) > * [Settings Page](#settings_page) > * [How To Compile](#how_to_compile) @@ -329,6 +331,19 @@ Allows users to temporarily move and rotate the center of the playspace. This al - **Media Control Keys:** Allows controlling a media player through the media keys. This is the same as having a keyboard with media keys and then pressing them. Should support most common media players. + +## - Desktop Overlay Page + +![Desktop Overlay Page](docs/screenshots/DesktopOverlayPage.png) + +-**Overlay Width:** The width of the overlay in meters. Multi screen setups need larger values to see any difference. + +-**Up/Down Translation:** Moves the overlay up and down. + +-**Forwards/Backwards Translation:** Moves the overlay forwards and backwards. + +-**Left/Right Translation:** Moves the overlay left or right. + ## - Statistics Page: diff --git a/docs/screenshots/DesktopOverlayPage.png b/docs/screenshots/DesktopOverlayPage.png new file mode 100644 index 0000000000000000000000000000000000000000..03208de30987d010c51f77744587a3676afb47ab GIT binary patch literal 36772 zcmbTdbx@m4*f-ju!GlY2io3fc6xX7~U5dLDD-g7}JH_3L7bp%yXtY$L)aGtE07ZC-MhM2v}Y4U*mo2sSsmAR?=XA+z26TwmYTnN7b__D38dj= zc(R7*g)8>~`P>&d$!2vev0pRstZy zho%G4Tz3TLm%SJnNqyLQ3Q&-ehtE@y6kKG3hH4vLU!D9gWFZ&ITI zP>nM1^p%R2JmQ`XHy(ROYClj&BEo+PT^-jFdM^@~3QX~q*9d`oO=uuwd7*%B`1d4q z?uoj~VmmlNIoBwv`4k)G0osrWcD1koT5Ug8>FKwd5y1 zm(5pA)aDW~1;!{Ad^e3i@qPN-eog+@s9a+X$t|7tr{ZvT+ZQf%%NRCDL5S?QY)(n} z;Gby-nvz{3y(So2t=2U4u>J0YDN|UlUT08qso;|(K_%Nzr6Xl%#V-p}CgMl^2WFm9 z{ff`?f4#Xlldw%c{H~KjEy0upeRGSKt7xvt5YsJgG$Wvfyef1u!N%itKvgv0mGsi? zCR7P8gW4IvW$tuTe~=zW(m_E4El0id(xPJisevPkf_2hw)A$EtOf{cfW>*emU|TPB zPw|0!e0vDWAK)jViny$d#wO8duh2J@l=HncF6h*yYCti^u+7+z>zjC1=CbJlTvf3| zBI`c+Q}gxOc3)A-#x5Z}r*V&7G&eBTZJy~I)88}bY0e}`AZW&9fEFwtdg5wmos4|UDbE}4B zhO#!e0A^{_9sB$7ovbvNFCD*K7s#WR-6%NxIUnR8l;brN6F4MYQt}{Rs7z|>ITlEN zz4#9-@LrmIHG!{CjchR=^0xo-%;-Snv>%D}4k1}SS4cw2mv!d5ZKEQ7(^+VQL{I4C z7>Lz|?byRg#S-!on3@O8m`v$6J{a;zs2SM(3vaPy%$LU$oyoW(k9?ynwR9S6v))8% zXn1J5GBV+#@7q-#NC-9Uf?Bb`xSFQB)`P7>h$iUTUrXewSdxVk3K-_h5J$;Ye-5hH z!7G|GWWCOz{Bmf6l8(n>Zhy#!YE{o?0u#--&0iA?Q&vepd@B;k%MTO*xCl1LYdR-6 zjs=c}b6#l#o(fYct<9t~}RWxfbc10vFC5kGEGfFBYB77_c@V;e(_T zuR}8HxRK(?VBbs&JZj-5FmU{Ah7wE~kPxG~UxdOlYB#q2$i$x5H>4W>zF&RGe@oED zos`dSYMJ+#KkCIyL#sqs5l$gqv+m=RqHTn7F#V{0i)l|Gm)8pe!LGA#zK&hFFmy0{J%uL--KY}WeV)&tezsz-H;q+&72gsssH z1IIt~&B!)rp74I#t9Q>NWH($bbLS3~n3(s%O|76kNnGSv%Y8f&{F7xM3^?3=M1CE@WkU&;^RzKS}R)acW)zIpo7)@XB?bk-18 z<59X@-gLrQ>awJ!KMIDZay(p8nlt^~wdD=zyz9FnBu--rNJVxgqUGBNIFI|Agkm~8 z`hbVZ3$LCXUnCb*?Zpi%iU-R+@zb;130&fY zQy;veRjRGk_Q85bW{bONO$yQ|NEVvOid8nHxbH89ttvhjLJ=LlpK^tRdsqth2$YPo z1azGO^|F+_An}8l0AQ_3@wf909z$U2C?3 z3ubkM>8;C^xJoHIvGky$2{wB zG|@AvzgAo&oaY<++Diq(UC0Gfpn=~F(X(u|_rEP$#xMv4b3ConpKoaH z5R?2QWZQ2wT2;`XNh9r$94CkD z+&qQC-p2HM3~;5pA;>uAN#P^^0~c>7+vMEU*ok(t7eHpaiXSP*XhYPfAS#r#X!0g{ zzz)LLUhG+NSwK^n>?pDKK%R=}K=!i#ODtP2)HX6ZfDoeC%37^8;am{r)v-i#|Lxwq zfOYY2)|taM%}etM=rm8J2T@L}tvW3n9|B2@v+9ZFpkH$;-w6II9jybb!YL|Z#{v(s z%CaA<&O5G>oTBw`beinvz;hs~O}>5K9}=_ScNmLH-0o5}{PmV%*ZZ1=$H+xnEgm9< z4FN~f%<9i9i07(bnhUOs2U`_nB?7)sjli9IGRAH+o0Y#`? zxET_eIVbHXy=&2R?5Uoj^JXTyXiq`q|~Ol*pizdBF-pk!1dtdD`OmjMo8m z$6M**3Q ze)}#gv|P^PQQ{Vzd5PC9k)qTxs=-zpewnWYwGDP13a2`}Hn1p%jYH&{>(joeH+StX zY%qf)lhlJof_Z^*od=FUkPhUz(kb8#oC5_YS;*z1 z{mO<{-@7e6+wdcs^n%rdl17}=Nne&dsAM3*cYp6<0aWk^LT6Wm?8elE{~a&X)EKs3 zB>9RcpzqCFPbM%nOVXmy^yI)x7e0oomb!;pkHl}QZv{cv$ba2Xp(Br2PSDlu%?h}@ z51BeHlUYYKUK=!GoZ=k{ay;Xy`TR;>&VtLI!PI#1D=wT91+-Z1v3Eq3ry0)j% z?TJCjZTzW$tFuAcjJkEIz*m^_cyBDB_Cs7vy|c?3DsC>RJ{0?FFPS-5T(CBchVwxs z4*N)-xF|&Bk7`WIPE?btn8+NWbn~*y+E5=B`!;Qa+@Ayzv|l;z5iwcGNyg)L9puD} z-egu7;*%?Ct>ryKQhluMqIPVSoRy5NJx#XFTgNLdJFrM(lyjIyTGs9WTh3IeGzDci zQR{|TUr>6j2SpYYz3Ab`N${=p^Xzzg<7!M3$GdKbIjye?d3^@4Z)V3EsXsQ22BldL z8q-dUn2+?Rwt~HtHyl>lTeGW;+Zf-20r8z%M0u-*Wy;(KPn0WMwOg^+^+}jS3LSn| zDP9Vv08#-{(vY6(>{M%6AR9-m=0(Y8)zVAkPWVXo%tnUx2nCNz9}L0(+`m>|-uja2XqUDkR!5JK|; zD!mJJ)*q?)1F;GrRZe-MOn3AmaVV1}=lxwLNj(>`G(_q9&6-i$CQ>|F{cLD-qCV&M zhvQ%o5AElvMo&r^Da4gOB3mM@z1->8c>-;ASeLaMdqW0gzLM5%f|t@B&7RCjdw}Yu zhp2+{a>GDUZ0dqKQ^)$8SdsF6Z*C%HFtAgoLph)0NgL1U0YS#1xvh6{)fssZqwt0TrKrs@NSap@*0kT}IqxZ#ZZ`N*0|eEA z3&gxR{_gEXBuySP?zED4RwP#^b=g(*?5;EG);Tn_`07V9N7*v0wrm__(+?s&P)sNb zxTUC8_ftTgv?rE)14-+n9kp3^)@X@QKt$ryvp$mEIdkTyqQhoNco1Eyv^pF?k&X_% z+jtlTvbxDub)g?WLI;3doFx%Alyqxa^6md(4gAPINMopOnlZgpOF=m)|0GWqPwLm4 zY_7`7ileZ(FNVHdHxi&=PM0!jSG7)2Oku#y>A5K%g42N&GBU@e)fuXL258oL)c}@9 zQ3a(vlnjbO>0b?1f2nd7LnR{ccI}l;pR-Uw4DJ9P%#4Od11~>!;au8sE^}^?6OGn5 zN22VOB^biH?Gyn}A^Dq@v*~{v5PJ!I#irtU41WI_QkT7+h*kVVQSh3T@fSnNB;Mg= zupnx|VO8-K+?#a&1&HeIAg^(qwY}rN-06<0M%|bg3zm6p`u>@at*#C)1}d;K2LVnP z7LVdkaX_5hj`VpKa_KxBt4Wss27I1w>NF_8aLHf@WqRc{Jti0?prU2Z4MWoStHNh& zepTN|85Qwg1|9iF*L=&Y%+q!|_&;$mIUStniALF9hJ2cBd7OdZMe{hq_II>7q*FGP z@2!&J;FYTF=TYAF@KEluA(#Hu^EZhfH$Gq1{YuJJ95<|TiQ2Xo{|9GdMNs*>JhylZ?ZAvj&n6oX?JDs^ENfOuMpv^KD8K zIgrhvq#5eC;{>fP^O`d9yngj3^!CLp4jV>`ga5Q;=ujcple(%Jp}KD(KNfHL!3Z97 zUxuCcDW6M=+OwM6P(&c;ch(f)w4&U4)0K&-FHm~GX@}0U%7kNg*!!|dkGE2)@ZiNB z1IF5T!C)iUDm$>q`?wuw-#x7vamI_PvM5g<_3+%%=_o6^iltV1DTubsZUIA%U3-QF zuasFcCD<}#1ulDIYK7l=F(onAKk7;S?o3*<3BgW~I7XjIrMeTwfz~$Na8H@zg+}7g zrdm~q*bWq#bm1*%5&J%z7x%Po8Ji-dL?-Ag+f6$#h~z0rp(>qXfj8VC4n(qZA5_M_ zxqD#5)>z1nH7)ND^EZ1;#Qcn8&`72fq8rwl^W>h~cmJ_p_-T+4+w}9Pk*`tzeUn>d z7+bTHkZnS$%c|&SE+Yq2P3b(Q=)M)u^Pd8bS35V_-v)ttOtU^*SAW&95=KNtyE-JA zzF0Gb(2Y>KHIv?@I!-NExI&@q6?X<)oR(pZLeBOhJWY$9zL@>T)P9FK6~-5)Pp_p3u|9>IdMmt~YmBkme1WG=_At-1{TauIQA){oOC^ohCF&jWxV z%8wH-LzN7*XPu5r7cE}%M0=iXjDlc*Urr4w_)pwQq(>_>B~$z^Kqc~1CB!4 zt9WR=1^uPkd#|Lbsc^QJ%Q`p&lR2s#3luquu=xqjQj8t%%+7blBT>sZWP^2aXBRsW zXXTLMz zU%K&#xltPIsj$L3eDw8IEaXMRVNL7_58sWY#sD>N^#C@aAu3cO1 z&CaBwB(~9$ched-Jn1UWE~W|ZItO}}rLOKh6#Cgmw3qI^b?^5vO0}n(S5mSt14)=_ zJ+oyD54L=M``-@dnw|^T&XRzu=8S*I>#woE)&lI%OLOIowGy>V8n4je#Jk7gt^iU| z(CNqAD<84|V9y6-+yk3v%Cnwt?kngqi}w-j12FQ8WI+4HqH-6#>S!|)%If(*VF zsk}M}Y7{AkcS20pM-h{eQS9LsE%=hk<@&q(!>gy;zZpW#`rWIoU%8O=EaUe}`OJqC zs-9G`+MS&5Zdv_=U*ritx&AV2TGhQy?dIMaXHKG-55Pq8UQtoMpi10R%oMHpw64z* z!U|5VSZP5Fu;1vi7}GKkvCmB$XC zvO7J~i7T;bCsyFITj_v}i+2&)4hA9J8e_(nD2Zd#-6L0xGamb;Vj3$pqxNqW`}0b{ zKAzYk=o$~mj_s;vMe-d=$cpJ){w-SjioTQB^&&wf&3Lw4mgB=@$SPR^-Y&fvbE5vX z^b3oNHiRRpKlc|~gTMVEEE`&hejMR0K)Zf)9Y1)#R-{W$K|q)`(oEKI^WWhQ!igF~ zF8Y#{GR9Tk;b*DF5dt4i{wX37BW-tpceejVu7Y&u4-*IwmCxt{e*&NLBHdkaFSG1+8sJw~I zTfW-K65EkM?h&J}l_54|`S&(u_4j%?;1CpyAHa-fWXd7S-)KE0$b>Tj0@W*v{G`FuO}D`=(LA8u7!&@PDjy>TIk*b-?5k?x*Tv!vDT@}c{XoXJ1;vU zRO!S>ZVZcO(G?zSIJ$iXX>ApLMFSU)dSpy!a!I)lS>C5gQA1SEWkVZa(?;G z1D1U%avGN}P|rRbLpnv2w6xm$C(7$=-Xn1xI_E$OoNen*vF8g`l_1MDay-KE%k24iA=hkYPmkyKikyf!$e+lk;Rd5g&8C?AGd#^RZD& zR>tGe!Kr6|jt=L3!(#qT67o%@MPP+wqobL5|8i}QRgM@otT<%^kat1R1umhN`4~CR z!7?!$p8uU6FI@0DhSEP_krVS-=67d`CzZTGLC|Z7Qr89+TIn%ev2qpq9Hv)+)qn_z zV;rk09*@(=Dfl)NO^Uy!Qh+?;#0<~@GK!2papE8;BbU_sy7W)v$~4_93~@Q?lVQKd zV|`%=2Jc7GC zPmIW;fcrn`4^QQkJLPNWtr%3WYT5SoJ4C(}hPY+BgDh;^PIzm#&-{R}w!dbY^>Vw7 zvO-|xG}td{F;3HRn2xs(rWk;~%36-!_TBw`E;lHM3pr!Mg=qnhX*CIO5or!f@c$oW z1-MUQ77G4`IUZ*u-T7o3( zpw7%b=6Q$Zwvmh~0JoAu8wQu_O~W3${Zt;krfCdLCVUVH>>eMBOL2ZI=eSP1_Riad zbb0CD?}7$Dw_c`{qJoHerchuE02$rrmaRT|dNN%d2OcIU|IjFumOJc6Rm8DM9Z~gg z_viMI$9u*}j+E(S)ntid6UJ=csxZc8XWqcOGBbIlc%1ftC5RM6$WuT(qv-WAbNSz+ z#h>JcZyILgGhgd?Q*HSJRHY1oRnuS9Mt;U`lR5W^0ZjbRm3~_2MDiYr{PgL{!#H|X z+%6|(isi`rV-(PS#JNz$T--?(WT%hVSo3f#WAl#|vZ%J2d035O-`b6yde z>OFVi!`xADX<(AM&`&h?G0SY)81_iKj2GrhLS_9u8dGbqK{KysxGS?YH8=DNp2|$X zmAZ9?g4v$6*`k_RXUq@47SDnXvaVqHSGn?@+ynC$jlia-44=CuWq`%t$c>InmeEAA z4y8QzafQUDR$s$RGP#igP7O9}KHMQ0I2R7`_;hpK^BZfS`e_1{Gdsc=n`xmq+9sb< zPp||zYeDJ2YB8|!;Gn0X;A5nhyDH^mh;t+M*)0!vQ5CVxiL;eO(sUFi@Lb#w>j)JO zV>k~2KY&9lQ&tnw3&sZ3_|v~_-Q;-#A$IA4H0sHLMK2L$sGGzBy6h@nN1*ePWPyZ!Zq7mgX-ao~xdB>$2mT|J*2k-GgSQG4?Dt%b{Ek^_^`jO)uwWQJ6U!AomN&%^=JHz|0OH_4;uY;yeW=r~F2z+>>(`$wyx+0{&f9F~S~3F2 z11Zr>7*Ky@kQyaWvYi;1sM=s?B6s?^3s#K7=>Ql9ht{6^GM{KoS6^B1tV#1ybX8j{ z>MB3upov;BZ_USmn5!M03oHr;6C$?PRDkL$$wjh1a=kAr<>~~=p-^}2b&n8qg{`qQ zvjxK}T_IV`Xa0@j=Ga^j`gMJGp68^%Di$AxtB_ zpcIt0)GFTs#TLJu@sT9z$B2!{Hp|#Qt_$>X4Ii4iY8*$uOo*c%yCQM*&<6qUPxd>len%M(~Uwu)ARHC6;cd$jZADN&G$tilGZPG9bh(V9_%z)Z>=*+mt8ZT{>N)DMM;n6dQXjpC7l~>>*jm33;xv!x) z2X}wrvmlf7I3Gt*ixevp_jgK%<6Y^~cFEB1H2fp1S)qfH2-N;*f7eTVOV6o`pc8%F5S?Rn-l3EO~>~Pd52N% zc~s>@R5`zJWm76!Y!OlwjFcBJF#k!E_9px6LTGgSUL=}1sKSBwZna@;h8iIv==?uB zdB_a|h}1|Rj+Ha44nL&5in`h{9}R;_aptHUI=s%i%-Zg5V{+z{N82eX_Kyz#L|#~F zSj~Ac;oUfj*FS~6cH#RiOjp4HXJ%PD5>Jn-Y&*Di`QQcG*XR~64&d!#RRHuvLzAQb zegfUwPT9F7heiCeEr2MkgE)kcg7P%Fx=^<4W327zIwRN`U-1~(1dVZbRBx@}^-f@N zno}(09{cL~?M^+w!40s|xy@U561$fKpq(XP3?Kh^8;<{&;+lZ48Ay!x-up|P;jK05 zz&UIVUjJc*-gF&;aVvjGq!vMgKd7MOYh?-lCxk%-SR56}8M)s*LF!6qbFh8ANG+W6His$g)v!k8#46*%HG-=(zS$ znxJ0X4{>pZlnk$(t=&z{CmbDytsrgV%O!hzq1&vkM7#Yt3^N)5CX2(IbKm93z%^tn zwI!zBtNFf$r{LPX(zUn&(tmd*FATzial!5(D0bp^8EwZfA$gzO?#;(Oq{q8g>Vk0X zO4GypwYWl?ouhnAf8z!py>3dia4Em*j$G8+^6ZrCMX1^Q$2IM8ROVzenfmE>IJ?#& z>mTBDSbr4>KM35`H@t~?z4kn`23(J8zTBmoJ=X4e$Znv!J;i84uWys73wNkdqA#|~ z{`PONrqrycQd?=IEHlsgP~$rX?^lyO_$avG3-N2}Szngl6uI)cyHjYp5i^v}Y@o&-G_+MV)N)P~|qV360IDsf_0lK}<14xr+^h*A)- zK8}fcVOLKIoku|4JjggWRh3K4yjX7ZGY+$)P4Vy`1YWU>xEQ{=|E8K_i7#fFfVOed z>3_1oBw`*GF}eTHIBHs&>SBP`#G8n*!`40uq`R;G*vDQ$LPP{o(l_DO)nff7vrRq!gsK0{q46K z8RT7kT$Pg(Cn7eOp+o-cf6PYNXw{TErTRQ&`2SM~U)iuE|Y zC~rly0qmJW1P~In96>iIf`F(tlkw9<^MN$4`b{>yzx$Zs+g1yI78urfn6+2?^@j8p z1{|t>aKp5k$U^0#kD*Y>3hBm&UzD|MEX_ACqTjj z=g+h6Wlneu2KKv0jZb$Jiw&Mea9*v}hc4RsoS2qWU~#y6;Uak!SHddm)p9hqD#k-d z84kDh?h&Uk^qezsGuTlg1PEa%+TOciR!ttwVr59H=iF(MxjQr8I>1>*`GCU$0<2k# zQz!4S8xZ$Qb+4o*RO1dy$T5h2-Fr60KdRLn{|U zHaj7!4yL$HcY96TCjcTVplVp0pF+&Tg+V3vQaP>W26B;4$ZC|y8=!N5fin>zZ~Vz? zdpQ}MMQO|Sewx6};2eoc$>v1dE=$;R=zH^}(FKo#`g{;gzf#}?*ZYRaW~44n8=vu+ z5*6`p*9V3P1Bvu19w-0ec=L?P7z9zR4P?8HMd7|a{Vg(vypZ|EOa$3sG`wjx3_j%2 z+d6!ugkV#lYvZV>NX7|lf+b<6Q%n~^D~1NN`VNC00C~>iJ-bG~i4T5&faP}1^eQ=z zvOux*IHR5C`llH3)Pt46~RUI*ynpD6&+W|u4)JSF8`ueJeGUd6N4uPQEPmb@?}q)p(4Zp72&MqWE`ExEciv-M`K5 z_AS}IaC+1##w!x|!%{`=M1n5!T~2`i3QOJ>ivAx>+9!Tjm#>v{Xfhutkii|Pbahxd z?rs-x^QwB5fv(Wy0<=fokx_mI)aDNF6VhG@CLWTlW#Mh@12F?L7!n>8+37VL9h3+pf{x5ewljWag7C}NYTGR4NvA$#qk#n7_yN|QIZSrxl5B9+NSdD+9k?r9kX4e9=K zFwh^pEi2iU*G{L%;ff@B*?b~}`zrz6S`;AuYj-}aOf0FGm$CR`F)YHokFI5c&ky1Y zd~W|@enFs0+WYB~#b>5mc;JUjz8Igtcu==jp;m13lD}J?`sfY^(r427WjZDAuAp7z z=xnYu*i(bqLsUGfRkrZ_Vc?A|iJM<0vrq4LcZOd{zk6wBoRx2*LDJm<^FqvSWBSrE zQO-qlTmaN@k z?@Jjc-@nAM9CV8PC>J+rkK|EkF1B|-@T#;vbr$^{f>Rqqga98EKh43Oj^J8TC5v`w(_PeH)_LJ?NN$4#uWPZ=a2+1o3{ z)@-VV(Ars;OSJQsE1Qw|j?L=cDt@GPY4xmNzWGuLY3FK(#|6xqN2L99RXZ0(fH4G} zh4PVmU!ALADoCYfNV*rrZnWr%vZw!ifAjS62XtT4>B2op2y;Cjh;QSPF&bGUr; zrs7fE4Ffq#n5*L?w&lKUq|5@qSPGerqtjhlRbM#2{vG_QQ$MwV5 z>Bg5cu8`VV?nYE+KDUfNLhzlEIF1d9UbC%*hqaCyEp0%5qN z+s_ACd?tcykP$;}vr1I_{@SLIpFwL(zz4{i6Yy=b8I!Cfz-xG2?HrQ;#eBaxPVl8y zq0#i=dv>{q;g2~vUZ!fQl%>JIo=V%ZyaxsCFn+eYFY-W>{n4Os)$?GY4_r1u^qz9#R{o4E>L%>!RVEeV9YikA zVm%Y_JODr8B^PoL7ZI328vC>hN%%Y0IsC{U4abd+4HCVy3c1%Dp@Wq`iuVRKwzKuy ztqoS>>s_92>)8nBm(Yl9i}G13M)m8NPk+k+xhtMLsZBvZiAZ|w6rZQ?Es)PKy)PS{bPz_{9AY8_*T7`3Fw4R6MkTz1r2Pz)$ zh?u;!`Ji33KJEN#W0Bl38wV+Loloh{3TD@_sU$&J#BZlpQFWHl5S@Eh&_UR{fbz-s zro&aA!{M8l7E`w}-r9v1pxYEn5lyvIUsv;KrA7&{0YQrjCajcP?eHsrnTO|&c(HIS z%IC0-D6ij$>i5{W&96UM&;Jb>843{Z=l5Jp8*-LnGC?h7^}6!Y_C_+S&b&|1gNYu& z;$H^4e2dCsiG(d~djifNR^vuOPCL0dtF(vpSVC8jWn*(e=c7^Mt9|I#I1tJSIt;wL z^2gBCNo1n_;0%h66|u0oy~z`H*K1hp3tzCSQa)@J}d$ z_P?D6;0<+Mq|Ix=ADadL<|=H3L%j zXpD@`%oJ(0jfVcK<@teu@zmQr7PiCl)(E`~-?RSb=>Nof{SV7;)U8;bJI-oj){x!) ziosA2@DWqU?E{Asw8dWdPOEAmh>0)YqH_pF?!N=cChA6WBG&IPC&J3re;4``&Z;_} z-p~R~OO9WaietQM1Obe1fMNR4AO7`}qXvs|*g_41D3h^h|M%S$FgXtFhc0RPL-BHs z{9hwaAT8Gg&*^u&M;0S|NL&y$*la|(gMiI|+wo%f-tpT%MWZt~WMrS!kkfMtHJka2 zaKi`#W*rDcL8s|gKIGoPl7-^=qkR0gBZJBKBho`^m2oSX59Yy|_y4OfXttYPr5ZHZ zNCIRA7QQ_U``Uo=7uY^^2pt*6rwf(1k z;TPKw;7;L!qIUDdBY?_mw?=<--Q}}`o1I$a=G6H18UxdTg^)$*p$L)=v9~)bzwEV1 zd@*og^*p~_6u%>5%<^t79HaHP0jEl5zJ9bg8WrN&I`v$~(&f2WdPrQ*I8zrp(LyYf zvlY7`t#%z#YoyjS6yG$mKr)1&lZ}`AP*fIV-$Y7VzRRX1s9iTK_(LO#Sq&xU&+-*M zJN=Zm8Z)d%G(IvhA4T!b;T*ecyH>%5Kc9*_$47W~88r*OD$Zw#jQ%4d-iP;c_+OX1 z2b6$-(h*}bmh6^H>l;T&bd&CSeqjPa?25*h$R+|Szc)GS{PZ&cb)tECVV5XB?xCM9 zc;K5mgajHzLvoHuKtM;sPTw1n*RX;53%^!sQSD6C9R1tgKJ}03Mc1dQI(ajW&&McU zSDk`;k~3aFX)T;_K~l?OzrBrHWi56q$TS@N zzPu#eCYQOSo{?QGWR1#;^O3=rJNyF_8mVGIwA9|N_YG@BJ5x46vjn{yAEv16?30p64N!PuR2_Kq6xN;b zk5IM`(``0fJLrQ-tV%^#%22fAaXbdG&W^8=$gmMrV5~p?ciMDFT}3!w z;kt{Hz5Fq&p*4X4Zg%1niz8n>Rw*yxlwHS-kYQb{#uTzmJpC8?#AH;Ha|F!VN2 zI2}=l9Ub^UVkMxGnofwpthCrLoRZ!PpOgZRyb?Gujh#Ba&GgvVYy(v7+txT7Q^*pjS{;S$X}?p{Ete-fFJ?Z z|7_pr2eCi`l_r}`5!ofqGYGm4r+liu#xGl&VE745=cT+4J6mreB#Xrk2-@_+GtWJZ zxUKdcP0RSjOieG(A@Z%i6_c6u6Kwk;D!P)QSQq@Jj>;rSZjB@`IgHkhRV(Z?BnWIo zYxA9&$|sDlPVLf(hWO)}xwVCDcs~Ad#ExbM1EtV8%)>mZ;R1%0|gC$F@BowYEaDYxc+P3 z$ox^)IY5N{w66PI4BKo|n$PQKzP|~anKTtKgocDLI^n?s{m2Y_kU?w};q&3`Cx@8| z4z#GN*kb5&=>fZ>$whouQeLf#C?u^?oid7|s)7qhS55kiCQ@Sg6=}kisR)CPEQB7J zpM}Ao+Omsw0I-!O-D!&Ssc$@4IHZzqC=~LgcN-2@!X}jW(-$J&h=LE8v}w<95W~5aq@@*&UZUrewc2f z4x~7=-Tn!DPC1b8ZIT2|dmo8Jhbj{BmP*9e>nQLn`s509xd^BycC7sEfOc%p+45J< z)uN~v;WU-XB#Yqr$Jk>OuZ7yc&P2)Wydb z2+sC(AD~@`FmuhqC;>vH>5Lr~CfUloFG8^n(@ZV?e1gUDHAjSLHqz(>F zheoi#Wed|7NavM@?2$&Y@aDzC+w2z&j&x9mH_&P*&zA7a+!SC{+DBT(ISr1dw3@vN=YT&1Ok zd=RF}+_cP2IDsn;RaEkpSZ0jFSc|eE!ae))6|svKx6j`Qw6STq)HI4r^cM?s-bil67 zp`b1<)S%;IMuj^qN)OESTEG8@9NQdKC3^eL*+ouZ0|4ra&#V-Wr49FCiYfHkxPgXf zCONI>Y~?OmUw$$3Z`?`M*;i&IKJSv1YalMkImyJQ!sDy_Lr zq0HEc4eSAT@XMQ5%-bUsj*CxFWDB~!hjTYxgTvDi1dJG=4S zgn`@^SgJf!1tL-@{j_gBKy`L8p<_cZiIP1VQ{;E}rff%ai$*IijkFmvWCG>_^y(Zj z(wn3$Y}02{ZcUzGH7fyd(}o%>VOS||UdrTK3=Z_tkoPD`91cW8caE4hYF;Ib8N{Jm zXu5ZXo@X|;v3Jtg#T|-@bmk>iCiRd`7!j`&33KZ3<~lzwfq^y<bE!<^zoM~ZdNTrb^8 zQ;glO>a+l2YQJqcnF#I?2JC5oH9jkIrL!y-s3k<8E0oqVa&AwN^hAY+F(i>tx-{4Z znoM4Mb5gb|9)T)KAC5`efv4prT`piW&<9=X(9fxKO0|Hl8L)I_F!5Q&4V;lgR|}Ga zemAstgFsW#sVX>}xG(GAoZXid)s5A!W>XNrWG$lmT&RzEv^CJlJWnX&0()`itMQI@Psg+M+CejSE)DVwi51KBRvG%H@fEN0;hRjKdG^{5 zCmeetOa4^OHgX6X2p2TdKGYW8#rCTWt`m8pPgwR#_3mG~94ss7<&V0CdxqVUbGuG< zPTKDr^+h)-q{zw_!KZY|dM>=gt)6S>fwRL4K3~DEVTUWlH;%n=OFCSx4;xnOPYs0X z4q=;?g~gN89bpytgX5P5wrR5H>ZUdvZgbC{yBhL7BIJ#e;TyQzbiVAm^wskiZg7Hq zg1diIuladxUoOqxe26h>E^$u(oetY-c)DanrNUPV%=mo1PZ<;l9I+(U2m*_$y2t-Qp6<@hz6e&CHUu6MC;}_&RAEL(*Kz$$ z?~_r?u&V$5+CLrRjVUGS3N$6C&r|$%-(MfIB@A1^(mkpCHl@Ua%ehLC558r}*?L7d0vAwxHj3 z*rwC`%%LUqGLfvL$uwZ=d<9l)YOawymr_1?(+He&0UN^E!>-Dl8fR%hv|VE+BW-h! zcEakStdVA?^tXJ7bUm$H6AWoi#~P!7aTG7sJ|N;y`x79Tq|V)i_crvv3~n|Fer@#N z_<)sNW+{VPXlnO^Wjs#tN2Hmdj3Ky);(#w=7h4gzT|UHbA`%iqp6X&=ha33_abunI z5hGnjj=q~Jqw+jcT_}Yg-I45Sy3*br+EXtkU<#ohYCol7WW_J5n(6A#*(7$!BOA_% zq5^_zAb)--RGWY5U&4(U0@ZgGbEa+eNi2fvvr~n%pntHxnu6|s?1he0EkSV=9^5+~ z{~-H{$?yqED|`?GfC}*nuV%U2^=$8?4Tjdi8=sy|?c1*9vO-|Wv~SfwMwL@{J?~X& zdCb4wXkZ&w_DVN4WIu)n0VN2)+pr(=9GU*V=!-*1D|sNsfjF}anA!B``)LwY1EO0) zE)3gq;-7W7P=1#n#O>!t$b&{hssOMk--p5cUV>~Z_Wy^nw+f4EYu9aO2vTSW?(Xg` zp@2Yech}(V7Tnz(g1ZH`1b26L4eovh^IvDJz0S>k&NWq(kI_ee+uJ@Z4x351?~6sF z+HD56UAv>pF2PGo@bbu8#o9o{`yrBw&`*%NatU7!E0>LO!VT!fAFn@-s8?tF)r-Gw z`LOrMbF?JA^t;M&N(M_ICeQv9p`(AUVj0C$A6WS`{a&zHNZB-`7#>+PQ-EhXo(A~C z9;{`XgN04QqTiAuU^Jx#nj%iw!NF;h3Y}K(-qQLDm8!sGREqIxQ^qd&O;wUSA_#3N zX#;FtyRVJj-MvBON}=3#KIwF6Go`h=&xTtOmF>Y@!$07NRn#T=D{xhn8@NohYKU^3 zcD)_nWGJE-ax*6`^RMv0H8rX%p1M>!VK`jjKn zP2EsIv$!0*_Gr820t@3Ge4ym^BP~<`zd?6-PL6Z;9Fz@mmuuVI#$*lDkhgW#pP)qt zG<+U+63-;qlt4KRUvEeOC_--g>x=FFyEwiqKDS!aGl5iQT-~SFWwy@}no6O@Kv`>4 z9S+<8HS);TFeP6tH45w|F&Q=VOuq=ZUOl2?tpQu0K}2?4fk7LH;1m|)IdH?!MRRs+ zF0`66@VNr*1NxnIEKt1`E#Nxy-oWA8Pt|tG!ntv zMF%88UhJQ27mf&BJ{L7aM%04tx095fyCy^lM+(RR9!wy4xd$L=gpf6hlw2i3J8HvA zjIXf25V+)o`1WVMX_1Cf>;xm9i`_ebC<9jL01y?teZUGh2)^pYr^XIwm_Y#h&WS4a z?a(Qgi3H+6hX+?8tSG}X|4GnLQkO)p0@f*D@)Q(!LE}HZLLn1({z4(%T-m4M#2E)H ztzQVa@bj(Ti&ZTYcTLKzpH5eP8LTFu!Zap@gd3OgpTQp(a@kv0o~-rD5NNg=>{bek zVMe}Y5;x=)z7e1kq*#R_);591#Q7|Nn%nmM z00Ie*@4AL)rP+d0+Z?bbz|aA&0_co^DN~!qpG64Hl~v3xydmv`|IA->0zu`QY&_4` zN`8(ShgG?n%%a*0dyZE38(R+l(7ecK=#HU6y2-=60&SD#sJxr6uo0c(%dJMXWwwJb z>%7_Jgj^sf4bHZ7??D1C=@#tskEaV2<84skremqmayTjcHjg9R{n5ZF?p)vVk=*@v zPq$cO}($2Ge;6akT%~wxxWF-kGG^SO-=eNJ#@O=Rl zgs!$aXY#on{qcvnI7~kHAmsY@zGk)61&YoOK%rN+Gu+@&UDAE=OU|OmA1%op&`Yq= zt3<|HNMX0YW0rvi@X7UP$LqeqG0~> zjnlvC28igR@IT$MKu^bKB%EoOxU1@(i@4f0rla!M2j`lx0=l(uBAK!RiW=(ll{jHM{CL|W6LaX?HOYA6)Yd!C?4aGBI}E;k zgN`#?PA6KamJC32N1A@JNn@GS;%`HsN&Ok?{t>ICXJse)rq$#c5%a~xB@!TI7Q8$2 zsX;(w22@gA=cpbx$);l;YmvQExhKXk-xE7BEkvhE=ZAWy_qQ6Jo8ah0bxQgJ*~Q5o|e4 z1wmWn*D`>I2vER>CVt%X{7Jf7R$d$T0=w0qaBek@6L_#oeKKjxqtohH?!60_1u?s4 zEm;5Eb{JF>N#PXndi=LQI{rHZs`3_2?c@2Lx^O#pc(M)u(c`W#_la}E-uheGJ80p} z1e*M`kBVO+xBpoK9)ng@z1SJH(+v5sHjKCq(|XEgbzPIgYK_lL?NjK~(6n2s{eG43 z{wUT3ucE=eg_f3NtbUz})mocz_tNgHBwGGpyqTJUAYc{I7BBXqbZyf&XCBCE`kOj-nFlI@IacC4?W~m|E}g_PIGs*`Vz8<%g*O zUj1-<(ai79K2!N~Kh!}5=;B-@)XwX#FXP$#t=T&lTfJ9S%g*=XA|N&7++Pr+VE|#Z z?0~jgDtPt;Qil_(33FO@J{gYLzWeMQl`k|f-2|NItXG>UftZa@SOQEi^jiU2J&oPR zYA~*mErQ}B98rSGMshrH9lOo)?o@%KEP8zkn{DnZ;|bO!BRBGo3C=Eg zZeVG}>@!#@g+~t{Nq+;lX;gvG$L%TWyR1Ogo`0*?qyKqdJuO-b%2zHSp~I1ZIY=Ai zN6LoRio1+JS}Aq7DdPt5Tv&};SjQ6dwa1b=Oy@)XfX4@2iqHv8sLq)4V9b*-i%5E- zK@Fx4Z8NP`zX{1+`+&E(Gls3C{w_y;n__&f`Ks$5=A2=~e;!~6_wcyGz|I_ItL%E6 zRKOM}HNK0r&UjjtV=fE3pU@u`_F7CD%o!ojxW0P{4dQDCiwD34P1MS!*L{BoFms@t zdEA9}HYdHt|6N7y`E{>!^@AP>@PI^+lTaTcN^dl!GB_}K7Je{rV#6m#r}LGGKky7X zcQHZrg%7Kg!*PTs(M2P7M7M7MQ4`~4JPX2Ejx_a$8_z{_%=cBU-)RDXf6e1eEP5j- z8<>;{w0L|h?EcMs?-}D(jSgU9z>OyE5|V_t-rErfE@nXJCLxLJ3p7on{fU4|myc9N zZo~eL#oG&S;Jr%x&zvYJyJ`1Yu9}ULpCQx~-zI z{kqg<8z`^Cx5IFxlHuF)D{{Is?dC!^H}Yxpy#=LO!JBd@+|-iWT@*!FHtMh z=&ohQd5;3u#hP&4Kp)Dp%A6n0Jb?laknG_l9v{mtNCmzt&H}u( z{_j?^rzIjZ@4Y*(_h(T;9`=kwJ*=uDbfGK+q6S44Yn;uO)M1RN{~~#{Ao%w^vH?C~ z);)S`X6LYx1fWs{MW!?alsdpTE+_m(Ti0$pssw2>XxAEBma*b*`)Ec>x<5U*xin2d?isn}M=@Y!L7*=>=)Qo>ux4?dW4sXVKjh zxk*D`dhw`rRv+p8$kVkg8b|5KE4$0xgDPHNB87vex#mXZJXFV(H(v!O`npf-!{Pc{(}M=582($hFYwxsS};N2w4SX|MRUO6Wp>UkL(qyq>z(1+9 zp)%}x@wm5|?GtB~4Lf}>0N&D!wMFwdh^|+xR_@bTX6sGy;_l@>n#Lv1Rv7no*m4~v zN0Y;30CeF{d>6DZ++NwbjqRN?A35YK=ivo0R5%;{O6znL->g_2vVxq+_}P&1%3T9y zy)mP~UHjWu2D#KJmp6?uaXyiDdgF2mc4F9$tN{E?mbeg`_NL#g5S)2k(ui_(g4)?1 zz}x1<9REv;Ub=Z0M&@R3GQ^dr_^?vTPBjw9>Nc9`S=y1g}+DQvSR-5Yu3c>l#SnBFS zt%+~c+PacY9V&(=rMKn*$qVDO>}ONe>Yl=JT!}(gO`t0j+&iB|m^MtIDkLMjMAopP zmH%RSdE$NN`o!@%*kXr|h2k;Q$ZtmO{jKP!C`M2yleVt(p56~@vDz_V_)*mN9v-+VmV@OIJLaVzk-4gOdoRWM3x{SNhv z%S0Op*v^VZb$Vi!QCgS^xmqr(PkOFCQkd#s!M8XhM+~a=9Sn@ky93TSlS+Yzs!ynC z%^e@$u1hyPKT7VJh>vcPz-wDZ#PvnHF0e@ElXYldeF_XOXWGhzLnOx2HpvoTWlYO; zjMd%`X8(c&`-=f9HsB(UI<>j8qRqj0lnRLE(?nqN^iNWod5Y%L~bfZ<9w!0B5SY@Um?NcI*o5i3Yx zW2UO5FIj>V%lpG}@a0E-S}NWR>_HFngio?DMpV2^AwkQI(rwvhN7&27Rv{Ocky}6!Par;_D#(IjR5QYhTQ+lQkTx$-0GsXI&gxDUFs< z5CyjZJg9yrB&MReON?V7L(VrAk&xy39Daj%nY2+14v~ppO3yFpo)g$c5`Y)k_zN{W zMF&a^BNMv+Zc#|Zt!!TKWXm?Oo(liM^7p#l1AqV*xP01FER4%ClpG#zJY05fTrHf_ z+YBD7lk!xePu4OR>gtRNe_BzD;Vvdp)Yt6JH9-q=j1l5946ry}%+)2^taLc+?`-1F zhNI^XSt=l>(dx?`u7Dzwj`$bMpK#`(@l93-LN}Va^7aO+2QdZ z>k(aI%1EWOrpIq|d3bM7x$@-TMzW}6W{*nx^utxds`vT94nW!6t+uro!zmUQl{nmH zbX@eUKFwEYWiYoyYn;hs1Zvg8&tYv+h_!U0jeTaQcbH)ano-K%Z3^6eGBX^GR&OhD zXlHrsqJQPFJz5&&oww1_WH$WuXCvp^C{$Wh%FTX`f;4nSll$4&ENg{@@{bS$3HmYn zlZNaz_x;n%Jdeg12Gzfmc7Lvr1DwL&$j+U!sxM~(EvnH?qt9$~^1xKf3yw2K^N@BY zGk-c=@KX4ywQoyTF=Ytp=NF0%9Fk}{Px!oEHoJp?{o4>HQ++BtN3TDE$(1&0?YA+a zt!ILsO%AgNb(4dWdO(sYpcwT~!|tlD-ru6g$V4q!hayB12A9+P z)!|8heht|)8L=RMR_x5{cI!HbW!FOG`_l2usAOP;FPp&^3 zm$E+??oLX_x6a_yT=m8V3I>J)E*%NvDw@4(w6k_!*Ctge)}UI%ZKMv8kY$;6_J|_0 z&ikVmd{kE3I>v>DR@LOO0$R=kW(P{4HtJI+Ii+2K&pnwIoHlE1b_Z45bRAYho2ET^ ziu7sq#j7S8i$y)N((zyt^!B-RR|jLUf}#3hjwA1l%ZD(##RWo&;4ddRrX`=~pX=4E z)20v=frC3vcLPe#v1a3$R+DRu=8HnjO;DvePmxS};V$m8^Ch>P$!sww=+|XVr+&$C z(d{p@S^beCRLBde#?ijPHIRm&pg_-b5J_x5|oRI(_lWZimz-j9o`icnZ8>MyDduzqYT z+g`d!Qd{jL2+S>#M0lH44hqE|?vYDS-WdE1ZLBW^9YF3boc%q%m^HtEZ8|J9B+IZTv%l5_l zn|b}R*}{#VHrx6w9GDZVlV-laVw!Gg>M^OB&LC|)7DjwdGv*B0hIcp3F9T5jrr$k^ zi#Sn&wm$s{mN#FKd#-36>;o?IprCk#NcLFLyr)##?Czd(HEm#?wE|GgwA_MICQHoo zdy+zl^F*itOl4JW562SR4n{L835H}YQCyY7Xr^xod&wp4UAY~BaG*$Qx|oS~ahAyy zX^uke`74u1mD*EHua6Qu^5qmy_CEB75zt|a8SUxLV^$G^P70!NsWGOI2;d?e?@?Kx zxz!Qn<09LUq(!(-Z>m=$Q3$-aK{NjLUFt5Z*&t1ZG-Q~@Hvz0_YGl#ek}@(xvQs(P zLY`+7H6q1LE+M4Kg+19D)k$2~P$m+3{nuOOd9jTx5FdYRI^m$juc_XDa7vp0VefiM zC^Z!)t>-$voJi!bd~BAw3xcT$Z@!i#uw+yuIgzkBw5eUQfaPK>(hk^t5A?GX;j+ZN z_}-|MEqXR;bH2yvb|oSb?>paConCkya=nHeWc*}dAeya#W+s}VL*FN&>K4eO3T^j? z5^|C)nz?Yas}9~n8LQ=Z=9vIZ9-B&W!V)l-qSb>OZ_xTD zcpPa%-N=W>vRvX?I`D=PSPF6vX#^H$+Ul%vD7k-IPkGRm+wF|YbbZ)URuK|$_ndVd zT=sX60N0M90g+gM>?g7GI`h>B1ZGi~ie~XPzS7u3>^_q1c>?eI`-{lqc^iH=VJ)?{ zc%nB$@emp}60f4S5Is={s~6_hwT>TyJt2JsRCw_K5JffyW4KglT&IC6#nb3)bVy(^ zR)sJ08O`^(GHw*LixcxZ+j&p@)2Gw*)}7@f{m3vdvH)oaP;wKaUYW=r^5^*M;(S@~ zwIhm8z3?WZ4)|6KODQ|5*`f>)F0@p79jmB#M4YJ|!U!e+Uy8?StE%zxy)eX`T(QV_ zD=IF_!PBQ`g7r4L?Y(Z*o(eCL++SNcqi-3SlmYDK+QhYBQ&c9Pgi4VRqC;CT}% zEX7xq0>)YDA-MX8TEi})^UH+|0$UvUX!`r5FL(nxdXFjry-HlNah|({_+mJ zXVl8^+lrYV)_N^CV1|0eqnmrr4kkNWV@$j8BR|LTt*h1q#Ey$IjWVhy}V?7dRtmI#J<}7m~Sj zj)^b|MUGYV!0C`L*0;jBjttsdOOi@$@Fd{2jjz4KHkJh^zEy3$peJ$^y9a1kyDN?2 z?tbd}&Qfp`y(+fCyWle>ur=C?m51)f5m!doyuW+oi|DQEVLK(w9b*Uf+v=*`kK2kL| zI!+7FHWK=pAloqRJ9#M9TA=xzk2X7zq=r^qeTBnAMG_#dJf%~vZ5!JfUAD)$I1gFC z46tFaL>9)b;H_&Tg50bQA{TC&46{V{h|=|ZM!^ojrF6_azxvHo=@SXz=Xat%l;E9d zV2@!!V{h&KkAIuF5po9^MSTfm>YV_{xLGe&FfH*4Mjx`D&Hb#djuu+J$p{&#R22^R zj7QXpPx!W8g#dni0u$6h{YV`fm*g=1xqnZgD_{QScR2Q2 z4x#I3CXl|keA6$eiLfvz>7|Y;HmDafw6RD9u6I&N-ZAuaxQcMa?QkO3;k{>!otOWa&$xc@&=(dC!oo( zX=EXFvqLKi1K=d@bcFc?`{Z|cgpu26_i3iQ=c5|u`D6zjb`X)}{gT&V0YTxw%&KhD z3;j*yWKrFeIC=dcN5()$2>zVR=XN8Kx8zj2LoL6P%*<31Bd>fsP716IqtMiIc98>& z-K$7L%Ic3f%I1Gcj@N|ej>JOwQ^_}2$%exFNDszVIR>hbTK~4ad{n_v)M&aQp<*f) zzAAqho;_prcpX4;>i_HEVNab|6!uFgAcDJ1k0`Tfch3r{m*6yW6fIp(T-D*8!hAB}Ad8OHS@1d_8DjN$C8W{;n3;N#ZPT=vKW>h5VW_=MSI1$)kO}6~>K8CIcg599D<8+AD>>AF@4x zINLI{*|msU)n(N1vGV9j7Dxm?lX!$PTV%IC?(ZJY&qrBBI=CIcdF0n@9ky}~^|YvU zWO{%zd8M*^h7(~{j}!9;wfPdI)qi!LJYimHlv_sfg8v>i>v1BG>k9fzG+MRJQdV-% zq9+R}?k!Xtqi?ktAwFUy^`z8~{ji80PMfts_X;xML%5y0UAbTD9Kd{L*)52-DJFIT9P^uPU93(QnNk z_>VxRsq!>|V$?IcBoVN6P@dQ-)%<$Cc(u<+u+p;d3!FRE$+*()$|hzVIR0U7sNH6z zd9K(p7ojVIR%Qijs+LB2Z>QvM?Q^G2n^TFB3Zvvn6k02f)Y|nW{l$2AaCeKddefO! z(NQ2PRrpDpZL`i~hEzRFLm)jn(9z*_!9t{CD&ywmdja;m}K zRO8kt_{mD0F4jEUDW%zGREgOW4*;8#ACd{17b@*P*flI!AnCY2{#}eWWt2Hp+pFgl z-hooVZ=Gnc-;ChXtdlRxdJ%rUy1cmeZZEXqUTgd&dQYFQU*32#a^kbrrY%^bdFoDz zWTlfM*PU)sHsiFENy(_w?(Vg}wK*huHJ#r;rM)>THdbGvl~C#EfHs$bC`Pc_Ad*){ zu7wQH6x3)ULLk|kWkmF}kM5=e;8Lcv(sOadHCr7vw`mM748YXiH(kfR7BJ0E1mEq( zgX8AQ-4@|XH!>1w(y!}v7K(Ae{^uTt2;O*4JXNvWCHNvz z9xR;S!!YAvMk3slVoCOkSi#81$Oe$5(9xjYt)9pb!RzN>KyWP~TeB&f+}-tR6#%RY z>LEX{*9Dk_udFbY24b+f12D4sphkbpbx90Lz79%9`6BVpbo%nRKC$wC+CoeKHEbRB368LAjZ zICW)kBWOGq`k*B6_3)K}*9@^51HU;bfMrLd9WyB~8Lzonu86x|6-e*4&ThBTado+J zJt5SX%&a;NjSQa^1u||r^3T3`KI}9GN`*ux-eF2QYoe?Le}bdjVtn(K*y=?sgq+DZ zC(HfO3GKRNVgB4l!AaW@*8>$NL#By-55K{<;d5Grp@>X;P3}hv^2ZYiUx-P}bB^VA zifew~nHRwd$PUKC-x~M`%$5*-KS=>INPx_OuOhg@@!xik68Q87(5x31lFd>`JYu6& zt%H4U?b9bzE#?o6kD{9DGePC{;cMosj7u-iS^|Ls06l*_Vn6<^z=Lv0^)HlDi-rVj z>mT4sB=`|E`Tbkw8T+rt`d`U_#sm~`n-OiMQVsS}0*c%x$;01l01&M7VU=2P^G79n zPTdRELFFRNem{?X3IPKfbUG-P*^X477NCYUxuqDj>;K%BIPB4BApy;Q?(ihp6pluN zOcN#8hm#+$H$-S;O*ov-65YDmzX^$-`!3mbI0Z=1lpuK+waqK$a&~(T9di8<5A5S> zY#*Aa>%vs-xff-y3V}M@F0BewdatA^*;p5FElw3%BAqM%NW?geslOyIk_7q^@++xFJO8_{K+-9+MQaKb10zSV}U&gm-6Y?L)UNDgnw>#UV%m6Lq%Yeo+ zE8s5{oyjJ-KO`Kl2GO$ePYgLi^JrH40pK7=Z#a}lgf#ikLnC?EHa`-QZS9?SAY^&+ zAwC4I!4iQMCEhU|Do1k7T?9A@)2|H_u7E(l&iPD`#B@?(VlKdd`hy^}Y*ySyv1iz9 zV+a#q;>^89^bm&2&cGyPG~v4BrR(F)U{?E+QJitEzt# zxWbgnmm4f}v4|+LfXk-z`KkaiiOgS6p{NXOK+@QiK+THzyBKM$_5HEfeF zf)OhIwa4XnKd>zpy*14^xeb6p{{!lr@BX=Dh6~cGDel{Cwj&lgxM?) zqzim;@PXc-3jYsb_N^(RI>j#-4HhDQQc_Z@@?;Op)OM=_e2mQ=Xl|3-BPT39r*Q*op4ml_T4IzDQu z?p?a8r``Eb$9&cb9Mx%fsq7YWv0C@OKZw2H*PQ5?OE7`~K;QLG|CQkfqMck22Tf8Q1SK(_IPiYE^j@`y{5@@j{(EI|eS764)l@8P&-6w8ZnFl&J)i$|P zR%%zq3gRl_bJTZ- zuwSiiZdKB`h8AtHp2FjzFc=8;?BL5kdt}EjNPt%4qgNQ=+p0&b+SKR|G|QEr-A%BH zVv(64avCX2_9OR({ZWFR_e=sWDEtKco~{Syo1c9mf(^c5h#aKj@>_2$z$zYbSfz8p z#}9sdgQdpd)HFds`wNuzdo9t!`2>42?^Co&p>u;Nh8ylD3bGJ~6m}VW=e{+naC@JC zcUK4smpY%wf=C-pZ1^twVs{O4W2>U|#pw{gmJ2ZX$TdySJXbg50~PlGw1mYg5Bp@> zK6ICThJwakiqWq8^v?`zmD-K32eHC1pZ#Acot5~EHF9f^D+_ChQe4&23krEUn1y~1sk2#wOi-O3zJEGcBs&;_R`1^ySl z;$t&jyD4IDDOHasw1ux{NXxzU9ZtqYi#F`ZWS94fea*DiH%EM{p=zZ zpb@>IP9(WDb-F@sc$vt|Q%l}nPPRDugAUNqfC^v>R~VR$_<;}lzYv|A8y57acYetF zKQ((`@gGPUJ(;d+F>XyWA5AotazjwTn@wE!V~mY zKR=c@zG+g@KB1R2*Db$baP*1XB@zw+pt7_Ltohtmv(#U@Mc-Dn^MEuw&-sDe!*2IK zKl*VTQNau&9t8lN&N{=&t&TavA{HA}Y1JR%;Os%Wl|_dH#CnCU5a)-l2pk)i|5M>R`z#4xnuR01#jwVKzG-hep3p z&FUlnBpjpUnQ}3WTzj4~jRaqV#}>UNm=8>GST2ae) z^jGZ2c5$ymeN#vjx1 ztX0`d*VpI8DE!u*jx3UY&saSR19kvh3V+F#{ooZKAqGGwypDvwV>bT- zzJH!{p>SJ|BL^)IYGeRhXliE`sU?m}%LR1c-|yxRTXxE~)C7naXtH8Kkd0RBrC?Cn zb4UKhKbn|rLLicWz7F9xEC7pGiOZy@|57J_D9|Y$S@RMcjmu%e($*sY1%-Y9wb7kQ zsT!IgO0z?yB=Dilai0zezsK}sN(hhzF(gpbM5Hq10mKrDA)RA&=+m;%WPwUO|9;9h z)|P7m2*!^z0fHZ}=+;{7(1)7rF+QR2xMbxZ0rn+g7WVsk)L&+6Khe+606ZGOIEm9@ z{^Wn?8weml{U7>fajw+Crq*Bj8)e(~-g2m6b9U>G)N$9U8ad&c#TmTLe-St|8!Qn~ zu~3$?7u;LQlY86|1fUJ14x)4nfhSAXjvkl0RM)&rRL ze~~vde+q-kDs@x2?pZJx1mBFNZkq zcW{ZRQo1=p)L_uA?--9^{tVv6JWGEr1&1SyB zd7EP_qqma+>d!nhG4g@I0u5ykQ1l_b<_Cr(jJMaAEBybgx${3*DN{c@iUI3&Dkss< zQO8v2oGWOfY14;N;OrIv8d0rXI=BFO*a*)Z?>9PFPOY$U@+l5 zJADZTNF0ET14taKY_Ot&eHm`<+OW!ko|0rdcaGIc zKXm9zj^Agsa-1nNDettG^%w+s=28lBhBB0Yyqk9kVem~%Dy?7EHAx}YU!FkvOq@=0 z;HV{7{(2ucMT24@oAu`i*S2_i_NV#8 z;#WFw1#4X{^vrsj9)h-L)KP%DJzxi3DGV4GczBFZw%Bi9{(Xm1as094@YRW2JOx7Ymu(K)B~)%-M$+bHvPuxdipqcM<^7ImHT_Y~|V*qSv>Ae4NB zVzD!nK@ka7U`A8PT83oK6BAa=vUeM1Q}cKQ_MGez0pTkTof|DCokmy@1xyHDAib6z zXj@DycE2jE*<8%TiyagP-JFTd<(>jXO5ec{)Tf$w)S24UKuoHPv8Rc-2v*a=O)rzG z00h}4<&s%AYFf<{2u7tLkQ_V478!G zyv20tRO`QI`gdtHmruvWrrlp`^sv;|-k{?WyD7xJS<*G5&w;Rp?%SsU{lwZA$T6L2 zx>3KFl6xXh8N&KEzNOfAG+s5It#EdrS4<|8-~GEyd}#p-%XMThgNHD3>pVkN`*-6! z6RTH&n;)+BZkHp0!%3qxqRZS8w3I%keoeU;7Sw*vE+B*N{(gX#C{1pdZUJhm!o*oD ze?co}GAEXQnR(Y4ge$h#fP0(C<-VgAUD^Jc!A=@JnQ4%>)zJf&NpHWapxK6vnV<7agengugl#6uh34oU#hl?WXAC(6^R-z z*{nO4%dWjbr`kIcIpg^^jHG#p|J0r+^;;e4UP>*?#=30(sAPV-SY zuYI_yoyXqaK*^*LJFd&SEVd%4wG64i%+e4me*4KyR8yqWMU_qi>e3!)#9_s%vk4vi zI#u(xyVv;OTgwWKUqr&bzz z4}|%EAxrQTpxe$OA7el?9+Xae>h9^>mwqnLt}=$P?z&<@A{AA9pcZQLx-r=HGh6*i z?-$C-qrC4*%ed$f>FTJz!DO$^5&zV^n#C;dX|*2t>C`$?3N_Y)F;K%aqyx_Ab`ceG z4cX?5Ku0KkXAP(Z^~iUp|2pDvx)SwsMKfhqWJA~e4Y$^|^2^BNP9A>a@MlNltC+Hj zx?QNN>rdlw=TY}(x3k%95}@NO+#rNJ#TB-dxsSJ4pR2fUP46Dz1xDtjaNgq?8d-FX zb#-?-2(dHli&RLH0QAo~vzLl$QG>x*$kF4!ELL-eo0R3;qTLIG)k-x;UAnF)8^;g{ zm>hdIThE(``~Gft9)42pq~=tzYo04+VwOwI)3$79$4-A$@g`aC8Jfdo(B!$5d9<&QDr+QDJOA72>tSc5@Q*gx}c zDDX&5|L#JgY z=u8QxM15Y}OszkOSh=(D64PW8A}DSh**=(&;-W(B+ba3-zD};LVfm(|FR!M6u^Y7#K}lL#pQj5 zy0z(D!IxHW(Fe1ctB$4*E1ow;UMuG%gtcjw!3DzIy^0f}nw$4i&d~S_zJl3&97pUj z5jDsq$eJppUqvj< z@ZrdJpVIP6hlCs3`Riy{m0$WhD0}?3Z+xsbqC#memcd)6Yj;9aoaAs|*}z=h&|x1t zV+s}!I)>H58sr6E_*ZSWg|Yb})r$fnYgt!>+c7Co7;x;~2g`ph5TNi?0H36BP3?-RVJRWcZi zszsg^h3Mw&6$*Elsr3iaeq41&vSqx%bUAm@OvKEu@4&X$3qMygDfhz4QLw# zoui4YPqyHdlhV2YZ+PUED88Gd!*zk4eWOG(^<@_(tijs~v4%y%fhS@mYR{e^Z{UPc z{ns<{u`2X?e>r(b0X2j!?L1(JIyI0)Kz}iAVRU;L7o0ex9!lRlbFaUpxs z2Iw3yaa4?dx8N?DGLskD+9gfmjz7*h2^RH^J#2KaGCRs&+rW<#=rV^<*LOL?I#t>V zKUmo4a8e~imfUi(4-echL6Q^Ji6Jf8y{O-%K~a}Zsp_;_s&T;x@9KY(-gU2NYB%+U zT%R=E6!7`x8gVkkl~7Q*U^9B7eWeDGn0sy0=sEwlv&Fk<|A4$PsywlDWYgg6_pX>% z?^$n47@_-ftykdlXRtpog~IS|?YQXlM&hkL*<}Qs=3OA8rR@6Fj@da+ z1@4XqnwW>OfO&+^7i*wr&d8`2n05h1x=^|uv7{G9C7o;)Ucf2MXe$)RC@Xl95hTV8 z__29-AhG|}b>Gg(|6(Ch2dY{1;l#*Y!-pm(hT687N9j&V1qNkEC8kp|2f-0Tw{0Dy zAOnU6b@5y#cJ^1I5DSgw&@#IqFmpX7#x*CM(gE(yA>U_Der+M0=dnrGkEc4&R={O6KhPbAJm-U5r}L8f{nGT}@G`y)|9v(0 z=ZY!lr-=-u@XM=v6L55wEKY?Cjce`g0VcT0X0jL#k=PR+*7}Z;kjLb`LR?5b==RNT zSRi1BU7&k!_{W_Ud7j5r-NZEhbCY)a+nYH8y=twNCYyhDk10HAWM5ggk(I8f?qNneFXz5&EpH)WgOO;HIDMr z*=36Bk?}y6rvTGHR-dS}Dz-8Jx@9!>!hsMTu?GD*dl#e071+zC&J)+Iy%Z!w4UqWr`DUQFNz zbT~&HD%-o;NR&kHN{vSK7%J`hwY(=67CT4SlK?B&B%*-vF+kM)F*rKV_80ZaGORI| zxhiy$`|{~agJs~y(=>lM96w!|!Y*c)KR;C&b=$meE@y}TVWg1G98`$Wy+^Mm0-Hg# zO#cm}Dc9+wCe{2%+6-(|S{9&^7>)aq!dXQ9c)>#sV7lw8A4V(nE3k$9h-L8dub30) z3BG#>V(`|Q-lMz{Y|Uz|&RoNdI;r1uKq`0*qS0K5B^Ar&bMs^z+&-M9^te5Z$F94m zKkMX0&HW`BuND-MwlSy;fx@f@$k$sED(9+|_jM2+U@%Lc{LcYtI&r81rIpZD06gL! z+yExy%LpjG3f%t+4!?wqX;jl4Nxr9k|CjJ^|HI4GC)PhUt#gT{3xx4R68{w*LT>_j z?`C}O{wub@g{_?~O^YKQr9?^v)!mwPU=l6r$^FoW#rBwJkBG^Ux`=3eimolept z(EXj#Mg|~&dtl}x#rs5sKCg|9T)+T6rroM;FBWiiDh^~i2R5j8so4V`JBDaznSnto zwD&x(jR@d_H#3Fh-^RfvH{TP!ecuH{I}ldZT5HEsSj}fh7?-oo-+bpdD+z3A>gggW z{Y(#9ug^0CIz_|<7cz_h?J!k@AjuK0ZJL%8#VUgMAHY_6i_7=Z^eq?U<-`Ao=<5@W z&-;45`5)Kx^}*&J;b8Y`{HbYGgxs@o)wf(Av8U3_li#9~qWE;p{Cb-F@x^nK0MbsT zYt}X{BRj5C=%8TG0F$6?rc9r^bcK9^=dhuavNE$OW%|YXH;nLC3(M}$oKclAAjE&O zBr`6+x6}NwOK;|0-|E{-u@FcQI+j>Pe~^LII9}6U{HI}@iT>0mFq?qWYRz-!Jl7xQ zmNbFF`E1GQa;F656G2ar?oXKf?V9a==d(5RY7lsRbdoe!wNeL_*mM0|irs;RhFvQW zp$>)9+NLJ!$CZbM4LQj~u9EMQ9SCIEJfEafT~-H&GtDvbs8_%h;U-iL8<)F}z4lB> zuVpueKqD=eBfj!)=J<9x5mJhRWaNi%*-8RQbhXzyp@G=c|EIk(4`wqDFDL$GVRSl`3r= zOW0r1?#%AY&g}m?oBuPDdFP#9p7;Ge-_HjeDCe6Z5_fCRk(Z3@c)lKomc3;4SmxV( ziZ3c*fE^53y-90YXVCQQ`t(slr}uCUG~ub8Ks@(`HqWHfH(Wf;Ys>nc3j5XPV99J zzRClh`l!o&E_2H2qOzJh70!4dMVR)$00}xsbtu_w3J^dXSToise`!1XsH9$5y`^!< z5pghl*{`;K21Jo`S1Q>@^+@96sqhN7=99bj1yEZ$4BLzCUUVWgn;o8_mRd`TwD^T) z8l8J5)u!40Gh zyd+KLXNt!Y$^%TfwSE@+5R&j4(c|v()*rK73`QrLnmR}){L#3C6WOl`X~gP;wc7e% z)V-Xe6F+i!%!o(FI@F*&1-y?g700N=cpp+@W zPm;#RV9ZhK6@eqK8BY)L!iF~7c>B-6rGIUwM8v*z4)rvwrxpj!&Cry;JBiR0uu6G~ zl!Fj^Vij^^@Mb#Z?palzqeCEo*4kN>8>G#y_I+`L6C6gnD>QZef>aWJ&7lo%i%Gww*{5u0I^1a=tiNn6oQ!~Ps(~@# z#U!ycWp*l0-!w-j355F(Kzzs=tFgUC?cD2Dk z*=5{#ws(DzAGEC}FFX@GY{qjn3pQtse9sR6()K8*(1McPL}3t? zX=5?4-$LHCY;-(eiV7&?LU07HB7V}B+3j>5Lhn=_iHkj>+` zW58M4?;r z6Cg~?JGbCM^(OY>raUlcQX0`u(2fO~#-L!$*}emk(2sz6wWzi!W|aR0js4t8Q=4oe zs}=SHS0!2odfV1QgsMZ_pU3BX>Gn=hNw0OiSL??xryZusgvJ(V&&vq|Tm)$Uhl@zj zL#PB`uHcG!;%@18)b2G$C$~y|2@mCbv~zv?imVXn+_gUueb?==M%!a)LL3nggkAqn z`+8DbV0fU&zZ10ow&wT$*TDU9<3Dmq3J6(A)2nF@?|{cUvxcJ@d&ql)aov;XzGfcq NxoB|Ze3_nO>>ueCYRmut literal 0 HcmV?d00001 diff --git a/docs/screenshots/UtilitiesPage.png b/docs/screenshots/UtilitiesPage.png index 6cbe38f330dcf63ffb39d187c3ac9a29764cd9d1..40d1fab4dfffb0b7775cbd2b0e679d9baa823c5c 100644 GIT binary patch literal 38179 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 F=C26Mu!H~r literal 43489 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 CXDhz| From 70381ea6808283b9e691cdf000d1d0c5f273bfdc Mon Sep 17 00:00:00 2001 From: Vasily Date: Sun, 31 Mar 2019 22:01:39 +0200 Subject: [PATCH 10/15] Add instruction to desktop overlay page It is not apparent that reopening the overlay applies the changes. The text will make that apparent. Centered to improve visibility. --- docs/screenshots/DesktopOverlayPage.png | Bin 36772 -> 40776 bytes .../DesktopOverlayPage.qml | 6 ++++++ 2 files changed, 6 insertions(+) diff --git a/docs/screenshots/DesktopOverlayPage.png b/docs/screenshots/DesktopOverlayPage.png index 03208de30987d010c51f77744587a3676afb47ab..326d4e41b2d3541105cf2441f9094320fb6579c4 100644 GIT binary patch literal 40776 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
TxBe2i!jnVKA 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 literal 36772 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 NxoB|Ze3_nO>>ueCYRmut diff --git a/src/res/qml/desktop_overlay_page/DesktopOverlayPage.qml b/src/res/qml/desktop_overlay_page/DesktopOverlayPage.qml index b8cff3e..ff84e79 100644 --- a/src/res/qml/desktop_overlay_page/DesktopOverlayPage.qml +++ b/src/res/qml/desktop_overlay_page/DesktopOverlayPage.qml @@ -14,6 +14,12 @@ MyStackViewPage { content: ColumnLayout { spacing: 18 + MyText { + Layout.alignment: Qt.AlignHCenter + horizontalAlignment: Text.AlignHCenter + text: "Reopen overlay to apply." + } + SteamDesktopGroupBox { } From c8f4ea4ea0b07ae2045d11ca14148ae86e0951c4 Mon Sep 17 00:00:00 2001 From: Vasily Date: Sun, 31 Mar 2019 11:16:27 +0200 Subject: [PATCH 11/15] Convert KeyboardInput to non-virtual class --- src/tabcontrollers/UtilitiesTabController.cpp | 23 ++++++++----------- src/tabcontrollers/UtilitiesTabController.h | 12 ++++++++-- .../keyboardinput/KeyboardInputDummy.h | 20 ++++++++-------- .../keyboardinput/KeyboardInputWindows.h | 20 ++++++++-------- 4 files changed, 39 insertions(+), 36 deletions(-) diff --git a/src/tabcontrollers/UtilitiesTabController.cpp b/src/tabcontrollers/UtilitiesTabController.cpp index 093ff7d..be8f770 100644 --- a/src/tabcontrollers/UtilitiesTabController.cpp +++ b/src/tabcontrollers/UtilitiesTabController.cpp @@ -15,11 +15,6 @@ namespace advsettings { void UtilitiesTabController::initStage1() { -#ifdef _WIN32 - keyboardInput.reset( new KeyboardInputWindows() ); -#else - keyboardInput.reset( new KeyboardInputDummy() ); -#endif auto settings = OverlayController::appSettings(); settings->beginGroup( "utilitiesSettings" ); auto qAlarmEnabled = settings->value( "alarmEnabled", m_alarmEnabled ); @@ -41,44 +36,44 @@ void UtilitiesTabController::initStage2( OverlayController* var_parent, void UtilitiesTabController::sendKeyboardInput( QString input ) { - keyboardInput->sendKeyboardInput( input ); + keyboardInput.sendKeyboardInput( input ); } void UtilitiesTabController::sendKeyboardEnter() { - keyboardInput->sendKeyboardEnter(); + keyboardInput.sendKeyboardEnter(); } void UtilitiesTabController::sendKeyboardAltEnter() { - keyboardInput->sendKeyboardAltEnter(); + keyboardInput.sendKeyboardAltEnter(); } void UtilitiesTabController::sendKeyboardAltTab() { - keyboardInput->sendKeyboardAltTab(); + keyboardInput.sendKeyboardAltTab(); } void UtilitiesTabController::sendKeyboardBackspace( const int count ) { - keyboardInput->sendKeyboardBackspace( count ); + keyboardInput.sendKeyboardBackspace( count ); } void UtilitiesTabController::sendMediaNextSong() { - keyboardInput->sendMediaNextSong(); + keyboardInput.sendMediaNextSong(); } void UtilitiesTabController::sendMediaPreviousSong() { - keyboardInput->sendMediaPreviousSong(); + keyboardInput.sendMediaPreviousSong(); } void UtilitiesTabController::sendMediaPausePlay() { - keyboardInput->sendMediaPausePlay(); + keyboardInput.sendMediaPausePlay(); } void UtilitiesTabController::sendMediaStopSong() { - keyboardInput->sendMediaStopSong(); + keyboardInput.sendMediaStopSong(); } bool UtilitiesTabController::alarmEnabled() const diff --git a/src/tabcontrollers/UtilitiesTabController.h b/src/tabcontrollers/UtilitiesTabController.h index 14c2b5e..aabaad2 100644 --- a/src/tabcontrollers/UtilitiesTabController.h +++ b/src/tabcontrollers/UtilitiesTabController.h @@ -5,7 +5,11 @@ #include #include #include -#include "KeyboardInput.h" +#ifdef WIN32 +# include "keyboardinput/KeyboardInputWindows.h" +#else +# include "keyboardinput/KeyboardInputDummy.h" +#endif class QQuickWindow; // application namespace @@ -42,7 +46,11 @@ private: int m_batteryState[vr::k_unMaxTrackedDeviceCount]; bool m_batteryVisible[vr::k_unMaxTrackedDeviceCount]; - std::unique_ptr keyboardInput; +#ifdef WIN32 + KeyboardInputWindows keyboardInput; +#else + KeyboardInputDummy keyboardInput; +#endif public: void initStage1(); diff --git a/src/tabcontrollers/keyboardinput/KeyboardInputDummy.h b/src/tabcontrollers/keyboardinput/KeyboardInputDummy.h index f67882e..94d9513 100644 --- a/src/tabcontrollers/keyboardinput/KeyboardInputDummy.h +++ b/src/tabcontrollers/keyboardinput/KeyboardInputDummy.h @@ -6,18 +6,18 @@ // application namespace namespace advsettings { -class KeyboardInputDummy : public KeyboardInput +class KeyboardInputDummy { public: - virtual void sendKeyboardInput( QString input ) override; - virtual void sendKeyboardEnter() override; - virtual void sendKeyboardBackspace( const int count ) override; - virtual void sendKeyboardAltTab() override; - virtual void sendKeyboardAltEnter() override; - virtual void sendMediaNextSong() override; - virtual void sendMediaPreviousSong() override; - virtual void sendMediaPausePlay() override; - virtual void sendMediaStopSong() override; + void sendKeyboardInput( QString input ); + void sendKeyboardEnter(); + void sendKeyboardBackspace( const int count ); + void sendKeyboardAltTab(); + void sendKeyboardAltEnter(); + void sendMediaNextSong(); + void sendMediaPreviousSong(); + void sendMediaPausePlay(); + void sendMediaStopSong(); }; } // namespace advsettings diff --git a/src/tabcontrollers/keyboardinput/KeyboardInputWindows.h b/src/tabcontrollers/keyboardinput/KeyboardInputWindows.h index cfed120..f877e1f 100644 --- a/src/tabcontrollers/keyboardinput/KeyboardInputWindows.h +++ b/src/tabcontrollers/keyboardinput/KeyboardInputWindows.h @@ -6,18 +6,18 @@ // application namespace namespace advsettings { -class KeyboardInputWindows : public KeyboardInput +class KeyboardInputWindows { public: - virtual void sendKeyboardInput( QString input ) override; - virtual void sendKeyboardEnter() override; - virtual void sendKeyboardBackspace( const int count ) override; - virtual void sendKeyboardAltTab() override; - virtual void sendKeyboardAltEnter() override; - virtual void sendMediaNextSong() override; - virtual void sendMediaPreviousSong() override; - virtual void sendMediaPausePlay() override; - virtual void sendMediaStopSong() override; + void sendKeyboardInput( QString input ); + void sendKeyboardEnter(); + void sendKeyboardBackspace( const int count ); + void sendKeyboardAltTab(); + void sendKeyboardAltEnter(); + void sendMediaNextSong(); + void sendMediaPreviousSong(); + void sendMediaPausePlay(); + void sendMediaStopSong(); }; } // namespace advsettings From 82d44b4ab5b2ec206589baf78cbf0301d676c2cf Mon Sep 17 00:00:00 2001 From: Vasily Date: Sun, 31 Mar 2019 11:17:58 +0200 Subject: [PATCH 12/15] Move KeyboardInput file into keyboardinput folder --- build_scripts/qt/sources.pri | 2 +- src/tabcontrollers/{ => keyboardinput}/KeyboardInput.h | 0 src/tabcontrollers/keyboardinput/KeyboardInputDummy.h | 2 +- src/tabcontrollers/keyboardinput/KeyboardInputWindows.h | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename src/tabcontrollers/{ => keyboardinput}/KeyboardInput.h (100%) diff --git a/build_scripts/qt/sources.pri b/build_scripts/qt/sources.pri index 9a3ea30..3d882a5 100644 --- a/build_scripts/qt/sources.pri +++ b/build_scripts/qt/sources.pri @@ -31,7 +31,7 @@ HEADERS += src/overlaycontroller.h \ src/tabcontrollers/UtilitiesTabController.h \ src/tabcontrollers/AudioManager.h \ src/tabcontrollers/PttController.h \ - src/tabcontrollers/KeyboardInput.h \ + src/tabcontrollers/keyboardinput/KeyboardInput.h \ src/utils/Matrix.h \ src/utils/ChaperoneUtils.h \ src/quaternion/quaternion.h \ diff --git a/src/tabcontrollers/KeyboardInput.h b/src/tabcontrollers/keyboardinput/KeyboardInput.h similarity index 100% rename from src/tabcontrollers/KeyboardInput.h rename to src/tabcontrollers/keyboardinput/KeyboardInput.h diff --git a/src/tabcontrollers/keyboardinput/KeyboardInputDummy.h b/src/tabcontrollers/keyboardinput/KeyboardInputDummy.h index 94d9513..14a5be5 100644 --- a/src/tabcontrollers/keyboardinput/KeyboardInputDummy.h +++ b/src/tabcontrollers/keyboardinput/KeyboardInputDummy.h @@ -1,7 +1,7 @@ #ifndef KEYBOARDINPUTDUMMY_H #define KEYBOARDINPUTDUMMY_H -#include "../KeyboardInput.h" +#include "KeyboardInput.h" // application namespace namespace advsettings diff --git a/src/tabcontrollers/keyboardinput/KeyboardInputWindows.h b/src/tabcontrollers/keyboardinput/KeyboardInputWindows.h index f877e1f..1221025 100644 --- a/src/tabcontrollers/keyboardinput/KeyboardInputWindows.h +++ b/src/tabcontrollers/keyboardinput/KeyboardInputWindows.h @@ -1,7 +1,7 @@ #ifndef KEYBOARDINPUTWINDOWS_H #define KEYBOARDINPUTWINDOWS_H -#include "../KeyboardInput.h" +#include "KeyboardInput.h" // application namespace namespace advsettings From e7df60311c3df89f6cd30b2f3754e70897e0f750 Mon Sep 17 00:00:00 2001 From: Vasily Date: Sun, 31 Mar 2019 11:36:44 +0200 Subject: [PATCH 13/15] Convert keyboardinput from class to regular header No consistent state is needed so it doesn't make sense for it to be a class. --- build_scripts/qt/sources.pri | 8 +++-- src/tabcontrollers/UtilitiesTabController.cpp | 18 +++++----- src/tabcontrollers/UtilitiesTabController.h | 6 ---- .../keyboardinput/KeyboardInputDummy.cpp | 22 ++++++------ .../keyboardinput/KeyboardInputDummy.h | 35 ++++++++----------- .../keyboardinput/KeyboardInputWindows.cpp | 22 ++++++------ .../keyboardinput/KeyboardInputWindows.h | 35 ++++++++----------- 7 files changed, 64 insertions(+), 82 deletions(-) diff --git a/build_scripts/qt/sources.pri b/build_scripts/qt/sources.pri index 3d882a5..23e9cb3 100644 --- a/build_scripts/qt/sources.pri +++ b/build_scripts/qt/sources.pri @@ -12,7 +12,6 @@ SOURCES += src/main.cpp\ src/tabcontrollers/PttController.cpp \ src/utils/ChaperoneUtils.cpp \ src/tabcontrollers/audiomanager/AudioManagerDummy.cpp \ - src/tabcontrollers/keyboardinput/KeyboardInputDummy.cpp \ src/openvr/openvr_init.cpp \ src/openvr/ivrinput.cpp \ src/utils/setup.cpp \ @@ -31,12 +30,10 @@ HEADERS += src/overlaycontroller.h \ src/tabcontrollers/UtilitiesTabController.h \ src/tabcontrollers/AudioManager.h \ src/tabcontrollers/PttController.h \ - src/tabcontrollers/keyboardinput/KeyboardInput.h \ src/utils/Matrix.h \ src/utils/ChaperoneUtils.h \ src/quaternion/quaternion.h \ src/tabcontrollers/audiomanager/AudioManagerDummy.h \ - src/tabcontrollers/keyboardinput/KeyboardInputDummy.h \ src/openvr/openvr_init.h \ src/openvr/ivrinput_action.h \ src/openvr/ivrinput_manifest.h \ @@ -54,6 +51,11 @@ win32 { src/tabcontrollers/keyboardinput/KeyboardInputWindows.h } +!win32 { + SOURCES += src/tabcontrollers/keyboardinput/KeyboardInputDummy.cpp + HEADERS += src/tabcontrollers/keyboardinput/KeyboardInputDummy.h +} + win32-msvc { INCLUDEPATH += third-party/openvr/headers \ third-party/easylogging++ \ diff --git a/src/tabcontrollers/UtilitiesTabController.cpp b/src/tabcontrollers/UtilitiesTabController.cpp index be8f770..06e28aa 100644 --- a/src/tabcontrollers/UtilitiesTabController.cpp +++ b/src/tabcontrollers/UtilitiesTabController.cpp @@ -36,44 +36,44 @@ void UtilitiesTabController::initStage2( OverlayController* var_parent, void UtilitiesTabController::sendKeyboardInput( QString input ) { - keyboardInput.sendKeyboardInput( input ); + keyboardinput::sendKeyboardInput( input ); } void UtilitiesTabController::sendKeyboardEnter() { - keyboardInput.sendKeyboardEnter(); + keyboardinput::sendKeyboardEnter(); } void UtilitiesTabController::sendKeyboardAltEnter() { - keyboardInput.sendKeyboardAltEnter(); + keyboardinput::sendKeyboardAltEnter(); } void UtilitiesTabController::sendKeyboardAltTab() { - keyboardInput.sendKeyboardAltTab(); + keyboardinput::sendKeyboardAltTab(); } void UtilitiesTabController::sendKeyboardBackspace( const int count ) { - keyboardInput.sendKeyboardBackspace( count ); + keyboardinput::sendKeyboardBackspace( count ); } void UtilitiesTabController::sendMediaNextSong() { - keyboardInput.sendMediaNextSong(); + keyboardinput::sendMediaNextSong(); } void UtilitiesTabController::sendMediaPreviousSong() { - keyboardInput.sendMediaPreviousSong(); + keyboardinput::sendMediaPreviousSong(); } void UtilitiesTabController::sendMediaPausePlay() { - keyboardInput.sendMediaPausePlay(); + keyboardinput::sendMediaPausePlay(); } void UtilitiesTabController::sendMediaStopSong() { - keyboardInput.sendMediaStopSong(); + keyboardinput::sendMediaStopSong(); } bool UtilitiesTabController::alarmEnabled() const diff --git a/src/tabcontrollers/UtilitiesTabController.h b/src/tabcontrollers/UtilitiesTabController.h index aabaad2..d31862a 100644 --- a/src/tabcontrollers/UtilitiesTabController.h +++ b/src/tabcontrollers/UtilitiesTabController.h @@ -46,12 +46,6 @@ private: int m_batteryState[vr::k_unMaxTrackedDeviceCount]; bool m_batteryVisible[vr::k_unMaxTrackedDeviceCount]; -#ifdef WIN32 - KeyboardInputWindows keyboardInput; -#else - KeyboardInputDummy keyboardInput; -#endif - public: void initStage1(); void initStage2( OverlayController* var_parent, QQuickWindow* var_widget ); diff --git a/src/tabcontrollers/keyboardinput/KeyboardInputDummy.cpp b/src/tabcontrollers/keyboardinput/KeyboardInputDummy.cpp index bb3f750..bd92747 100644 --- a/src/tabcontrollers/keyboardinput/KeyboardInputDummy.cpp +++ b/src/tabcontrollers/keyboardinput/KeyboardInputDummy.cpp @@ -4,53 +4,53 @@ // parameter. The cast is to get GCC to shut up about it. #define UNREFERENCED_PARAMETER( P ) static_cast( ( P ) ) -namespace advsettings +namespace keyboardinput { -void KeyboardInputDummy::sendKeyboardInput( QString input ) +void sendKeyboardInput( QString input ) { // noop UNREFERENCED_PARAMETER( input ); } -void KeyboardInputDummy::sendKeyboardEnter() +void sendKeyboardEnter() { // noop } -void KeyboardInputDummy::sendKeyboardBackspace( const int count ) +void sendKeyboardBackspace( const int count ) { // noop UNREFERENCED_PARAMETER( count ); } -void KeyboardInputDummy::sendKeyboardAltTab() +void sendKeyboardAltTab() { // noop } -void KeyboardInputDummy::sendKeyboardAltEnter() +void sendKeyboardAltEnter() { // noop } -void KeyboardInputDummy::sendMediaNextSong() +void sendMediaNextSong() { // noop } -void KeyboardInputDummy::sendMediaPreviousSong() +void sendMediaPreviousSong() { // noop } -void KeyboardInputDummy::sendMediaPausePlay() +void sendMediaPausePlay() { // noop } -void KeyboardInputDummy::sendMediaStopSong() +void sendMediaStopSong() { // noop } -} // namespace advsettings +} // namespace keyboardinput diff --git a/src/tabcontrollers/keyboardinput/KeyboardInputDummy.h b/src/tabcontrollers/keyboardinput/KeyboardInputDummy.h index 14a5be5..d1bff88 100644 --- a/src/tabcontrollers/keyboardinput/KeyboardInputDummy.h +++ b/src/tabcontrollers/keyboardinput/KeyboardInputDummy.h @@ -1,25 +1,18 @@ -#ifndef KEYBOARDINPUTDUMMY_H -#define KEYBOARDINPUTDUMMY_H +#pragma once -#include "KeyboardInput.h" +#include +#include -// application namespace -namespace advsettings +namespace keyboardinput { -class KeyboardInputDummy -{ -public: - void sendKeyboardInput( QString input ); - void sendKeyboardEnter(); - void sendKeyboardBackspace( const int count ); - void sendKeyboardAltTab(); - void sendKeyboardAltEnter(); - void sendMediaNextSong(); - void sendMediaPreviousSong(); - void sendMediaPausePlay(); - void sendMediaStopSong(); -}; +void sendKeyboardInput( QString input ); +void sendKeyboardEnter(); +void sendKeyboardBackspace( const int count ); +void sendKeyboardAltTab(); +void sendKeyboardAltEnter(); +void sendMediaNextSong(); +void sendMediaPreviousSong(); +void sendMediaPausePlay(); +void sendMediaStopSong(); -} // namespace advsettings - -#endif // KEYBOARDINPUTDUMMY_H +} // namespace keyboardinput diff --git a/src/tabcontrollers/keyboardinput/KeyboardInputWindows.cpp b/src/tabcontrollers/keyboardinput/KeyboardInputWindows.cpp index b43d91e..0276e6d 100644 --- a/src/tabcontrollers/keyboardinput/KeyboardInputWindows.cpp +++ b/src/tabcontrollers/keyboardinput/KeyboardInputWindows.cpp @@ -2,7 +2,7 @@ #include #include "easylogging++.h" -namespace advsettings +namespace keyboardinput { /*! Represents the state of a keyboard button press. Can be either Up or Down. @@ -127,7 +127,7 @@ void sendKeyPressAndRelease( const WORD virtualKeyCode ) sendKeyboardInputRaw( numberOfActions, actions ); } -void KeyboardInputWindows::sendKeyboardInput( QString input ) +void sendKeyboardInput( QString input ) { int len = input.length(); if ( len > 0 ) @@ -202,7 +202,7 @@ void KeyboardInputWindows::sendKeyboardInput( QString input ) /*! Sends a single Enter keypress to Windows. */ -void KeyboardInputWindows::sendKeyboardEnter() +void sendKeyboardEnter() { sendKeyPressAndRelease( VK_RETURN ); } @@ -211,7 +211,7 @@ void KeyboardInputWindows::sendKeyboardEnter() Sends count amount of backspaces to Windows. count of 0 or below will do nothing. */ -void KeyboardInputWindows::sendKeyboardBackspace( const int count ) +void sendKeyboardBackspace( const int count ) { // We can only send a positive amount of key presses. if ( count <= 0 ) @@ -232,7 +232,7 @@ Used for tabbing out of game windows blocking other programs on desktop while in VR. At least one use case was tabbing out of a fullscreen game to be able to use a music player. */ -void KeyboardInputWindows::sendKeyboardAltTab() +void sendKeyboardAltTab() { constexpr auto altKey = VK_MENU; constexpr auto tabKey = VK_TAB; @@ -256,7 +256,7 @@ Sends an Alt + Tab combination to Windows. Used for toggling full screen on games and various applications that appear on the desktop. */ -void KeyboardInputWindows::sendKeyboardAltEnter() +void sendKeyboardAltEnter() { constexpr auto altKey = VK_MENU; constexpr auto enterKey = VK_RETURN; @@ -277,7 +277,7 @@ void KeyboardInputWindows::sendKeyboardAltEnter() /*! Sends a media key Next Song button to Windows. */ -void KeyboardInputWindows::sendMediaNextSong() +void sendMediaNextSong() { sendKeyPressAndRelease( VK_MEDIA_NEXT_TRACK ); } @@ -285,7 +285,7 @@ void KeyboardInputWindows::sendMediaNextSong() /*! Sends a media key Previous Song button to Windows. */ -void KeyboardInputWindows::sendMediaPreviousSong() +void sendMediaPreviousSong() { sendKeyPressAndRelease( VK_MEDIA_PREV_TRACK ); } @@ -293,7 +293,7 @@ void KeyboardInputWindows::sendMediaPreviousSong() /*! Sends a media key Play/Pause button to Windows. */ -void KeyboardInputWindows::sendMediaPausePlay() +void sendMediaPausePlay() { sendKeyPressAndRelease( VK_MEDIA_PLAY_PAUSE ); } @@ -301,9 +301,9 @@ void KeyboardInputWindows::sendMediaPausePlay() /*! Sends a media key Stop button to Windows. */ -void KeyboardInputWindows::sendMediaStopSong() +void sendMediaStopSong() { sendKeyPressAndRelease( VK_MEDIA_STOP ); } -} // namespace advsettings +} // namespace keyboardinput diff --git a/src/tabcontrollers/keyboardinput/KeyboardInputWindows.h b/src/tabcontrollers/keyboardinput/KeyboardInputWindows.h index 1221025..d1bff88 100644 --- a/src/tabcontrollers/keyboardinput/KeyboardInputWindows.h +++ b/src/tabcontrollers/keyboardinput/KeyboardInputWindows.h @@ -1,25 +1,18 @@ -#ifndef KEYBOARDINPUTWINDOWS_H -#define KEYBOARDINPUTWINDOWS_H +#pragma once -#include "KeyboardInput.h" +#include +#include -// application namespace -namespace advsettings +namespace keyboardinput { -class KeyboardInputWindows -{ -public: - void sendKeyboardInput( QString input ); - void sendKeyboardEnter(); - void sendKeyboardBackspace( const int count ); - void sendKeyboardAltTab(); - void sendKeyboardAltEnter(); - void sendMediaNextSong(); - void sendMediaPreviousSong(); - void sendMediaPausePlay(); - void sendMediaStopSong(); -}; +void sendKeyboardInput( QString input ); +void sendKeyboardEnter(); +void sendKeyboardBackspace( const int count ); +void sendKeyboardAltTab(); +void sendKeyboardAltEnter(); +void sendMediaNextSong(); +void sendMediaPreviousSong(); +void sendMediaPausePlay(); +void sendMediaStopSong(); -} // namespace advsettings - -#endif // KEYBOARDINPUTWINDOWS_H +} // namespace keyboardinput From b53ebb699f271f846f56255e0f56c6f98327b628 Mon Sep 17 00:00:00 2001 From: Vasily Date: Sun, 31 Mar 2019 11:45:02 +0200 Subject: [PATCH 14/15] Remove version specific header files for KeyboardInput The headers were identical after no longer using the abstract class for platform independence. --- build_scripts/qt/sources.pri | 5 ++- src/tabcontrollers/UtilitiesTabController.cpp | 5 --- src/tabcontrollers/UtilitiesTabController.h | 6 +--- .../keyboardinput/KeyboardInput.h | 31 +++++++------------ .../keyboardinput/KeyboardInputDummy.cpp | 2 +- .../keyboardinput/KeyboardInputDummy.h | 18 ----------- .../keyboardinput/KeyboardInputWindows.cpp | 2 +- .../keyboardinput/KeyboardInputWindows.h | 18 ----------- 8 files changed, 16 insertions(+), 71 deletions(-) delete mode 100644 src/tabcontrollers/keyboardinput/KeyboardInputDummy.h delete mode 100644 src/tabcontrollers/keyboardinput/KeyboardInputWindows.h diff --git a/build_scripts/qt/sources.pri b/build_scripts/qt/sources.pri index 23e9cb3..8a66f83 100644 --- a/build_scripts/qt/sources.pri +++ b/build_scripts/qt/sources.pri @@ -30,6 +30,7 @@ HEADERS += src/overlaycontroller.h \ src/tabcontrollers/UtilitiesTabController.h \ src/tabcontrollers/AudioManager.h \ src/tabcontrollers/PttController.h \ + src/tabcontrollers/keyboardinput/KeyboardInput.h \ src/utils/Matrix.h \ src/utils/ChaperoneUtils.h \ src/quaternion/quaternion.h \ @@ -47,13 +48,11 @@ HEADERS += src/overlaycontroller.h \ win32 { SOURCES += src/tabcontrollers/audiomanager/AudioManagerWindows.cpp \ src/tabcontrollers/keyboardinput/KeyboardInputWindows.cpp - HEADERS += src/tabcontrollers/audiomanager/AudioManagerWindows.h \ - src/tabcontrollers/keyboardinput/KeyboardInputWindows.h + HEADERS += src/tabcontrollers/audiomanager/AudioManagerWindows.h } !win32 { SOURCES += src/tabcontrollers/keyboardinput/KeyboardInputDummy.cpp - HEADERS += src/tabcontrollers/keyboardinput/KeyboardInputDummy.h } win32-msvc { diff --git a/src/tabcontrollers/UtilitiesTabController.cpp b/src/tabcontrollers/UtilitiesTabController.cpp index 06e28aa..6b70ea4 100644 --- a/src/tabcontrollers/UtilitiesTabController.cpp +++ b/src/tabcontrollers/UtilitiesTabController.cpp @@ -4,11 +4,6 @@ #include "../overlaycontroller.h" #include #include -#ifdef _WIN32 -# include "keyboardinput/KeyboardInputWindows.h" -#else -# include "keyboardinput/KeyboardInputDummy.h" -#endif // application namespace namespace advsettings diff --git a/src/tabcontrollers/UtilitiesTabController.h b/src/tabcontrollers/UtilitiesTabController.h index d31862a..e97cb60 100644 --- a/src/tabcontrollers/UtilitiesTabController.h +++ b/src/tabcontrollers/UtilitiesTabController.h @@ -5,11 +5,7 @@ #include #include #include -#ifdef WIN32 -# include "keyboardinput/KeyboardInputWindows.h" -#else -# include "keyboardinput/KeyboardInputDummy.h" -#endif +#include "keyboardinput/KeyboardInput.h" class QQuickWindow; // application namespace diff --git a/src/tabcontrollers/keyboardinput/KeyboardInput.h b/src/tabcontrollers/keyboardinput/KeyboardInput.h index a4e1ba7..d1bff88 100644 --- a/src/tabcontrollers/keyboardinput/KeyboardInput.h +++ b/src/tabcontrollers/keyboardinput/KeyboardInput.h @@ -3,25 +3,16 @@ #include #include -// application namespace -namespace advsettings +namespace keyboardinput { -class AudioTabController; +void sendKeyboardInput( QString input ); +void sendKeyboardEnter(); +void sendKeyboardBackspace( const int count ); +void sendKeyboardAltTab(); +void sendKeyboardAltEnter(); +void sendMediaNextSong(); +void sendMediaPreviousSong(); +void sendMediaPausePlay(); +void sendMediaStopSong(); -class KeyboardInput -{ -public: - virtual ~KeyboardInput() {} - - virtual void sendKeyboardInput( QString input ) = 0; - virtual void sendKeyboardEnter() = 0; - virtual void sendKeyboardBackspace( const int count ) = 0; - virtual void sendKeyboardAltTab() = 0; - virtual void sendKeyboardAltEnter() = 0; - virtual void sendMediaNextSong() = 0; - virtual void sendMediaPreviousSong() = 0; - virtual void sendMediaPausePlay() = 0; - virtual void sendMediaStopSong() = 0; -}; - -} // namespace advsettings +} // namespace keyboardinput diff --git a/src/tabcontrollers/keyboardinput/KeyboardInputDummy.cpp b/src/tabcontrollers/keyboardinput/KeyboardInputDummy.cpp index bd92747..8bfa9bb 100644 --- a/src/tabcontrollers/keyboardinput/KeyboardInputDummy.cpp +++ b/src/tabcontrollers/keyboardinput/KeyboardInputDummy.cpp @@ -1,4 +1,4 @@ -#include "KeyboardInputDummy.h" +#include "KeyboardInput.h" // Used to get the compiler to shut up about C4100: unreferenced formal // parameter. The cast is to get GCC to shut up about it. diff --git a/src/tabcontrollers/keyboardinput/KeyboardInputDummy.h b/src/tabcontrollers/keyboardinput/KeyboardInputDummy.h deleted file mode 100644 index d1bff88..0000000 --- a/src/tabcontrollers/keyboardinput/KeyboardInputDummy.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include -#include - -namespace keyboardinput -{ -void sendKeyboardInput( QString input ); -void sendKeyboardEnter(); -void sendKeyboardBackspace( const int count ); -void sendKeyboardAltTab(); -void sendKeyboardAltEnter(); -void sendMediaNextSong(); -void sendMediaPreviousSong(); -void sendMediaPausePlay(); -void sendMediaStopSong(); - -} // namespace keyboardinput diff --git a/src/tabcontrollers/keyboardinput/KeyboardInputWindows.cpp b/src/tabcontrollers/keyboardinput/KeyboardInputWindows.cpp index 0276e6d..586bef5 100644 --- a/src/tabcontrollers/keyboardinput/KeyboardInputWindows.cpp +++ b/src/tabcontrollers/keyboardinput/KeyboardInputWindows.cpp @@ -1,4 +1,4 @@ -#include "KeyboardInputWindows.h" +#include "KeyboardInput.h" #include #include "easylogging++.h" diff --git a/src/tabcontrollers/keyboardinput/KeyboardInputWindows.h b/src/tabcontrollers/keyboardinput/KeyboardInputWindows.h deleted file mode 100644 index d1bff88..0000000 --- a/src/tabcontrollers/keyboardinput/KeyboardInputWindows.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include -#include - -namespace keyboardinput -{ -void sendKeyboardInput( QString input ); -void sendKeyboardEnter(); -void sendKeyboardBackspace( const int count ); -void sendKeyboardAltTab(); -void sendKeyboardAltEnter(); -void sendMediaNextSong(); -void sendMediaPreviousSong(); -void sendMediaPausePlay(); -void sendMediaStopSong(); - -} // namespace keyboardinput From b32d621994187060e5f49dd958ae17bba54c44bf Mon Sep 17 00:00:00 2001 From: Kung-vr <38249782+Kung-vr@users.noreply.github.com> Date: Sat, 13 Apr 2019 03:46:06 +0900 Subject: [PATCH 15/15] Implement Seated Universe and Raw (Room Setup) Universe Support (#150) * Add checks for seated improve shutdown state Seated mode chaperone update is still broken. Normal standing mode space motion needs testing on WMR and Rift * Fix updating chaperone on room setup completion * Implement seated universe recenter/offsets/motion Addresses #145 * Add Option "Allow External App Chaperone Edits" This option is added to the settings tab. It allows external apps to modify the chaperone but only if the current offset is 0,0,0 and rotation is 0. The option is disabled by default. --- src/overlaycontroller.cpp | 9 +- src/overlaycontroller.h | 2 +- src/res/qml/PlayspacePage.qml | 45 +- src/res/qml/SettingsPage.qml | 16 + .../MoveCenterTabController.cpp | 399 ++++++++++++++++-- src/tabcontrollers/MoveCenterTabController.h | 22 + src/utils/ChaperoneUtils.cpp | 28 +- src/utils/ChaperoneUtils.h | 2 +- 8 files changed, 460 insertions(+), 63 deletions(-) diff --git a/src/overlaycontroller.cpp b/src/overlaycontroller.cpp index d5ceeb8..28a6e71 100644 --- a/src/overlaycontroller.cpp +++ b/src/overlaycontroller.cpp @@ -710,7 +710,7 @@ void OverlayController::mainEventLoop() LOG( INFO ) << "Received quit request."; vr::VRSystem()->AcknowledgeQuit_Exiting(); // Let us buy some // time just in case - m_moveCenterTabController.reset(); + m_moveCenterTabController.shutdown(); // Un-mute mic before Exiting VR, as it is set at system level Not // Vr level. m_audioTabController.setMicMuted( false, false ); @@ -748,6 +748,13 @@ void OverlayController::mainEventLoop() } break; + case vr::VREvent_SeatedZeroPoseReset: + { + m_moveCenterTabController.incomingSeatedReset(); + LOG( INFO ) << "Game Triggered Seated Zero-Position Reset"; + } + break; + // Multiple ChaperoneUniverseHasChanged are often emitted at the // same time (some with a little bit of delay) There is no sure way // to recognize redundant events, we can only exclude redundant diff --git a/src/overlaycontroller.h b/src/overlaycontroller.h index d9427cc..1cd94ab 100644 --- a/src/overlaycontroller.h +++ b/src/overlaycontroller.h @@ -61,7 +61,7 @@ namespace advsettings // Avoid setting values to the same numbers. constexpr int k_audioSettingsUpdateCounter = 89; constexpr int k_chaperoneSettingsUpdateCounter = 101; -constexpr int k_moveCenterSettingsUpdateCounter = 149; +constexpr int k_moveCenterSettingsUpdateCounter = 83; constexpr int k_reviveSettingsUpdateCounter = 139; constexpr int k_settingsTabSettingsUpdateCounter = 157; constexpr int k_steamVrSettingsUpdateCounter = 97; diff --git a/src/res/qml/PlayspacePage.qml b/src/res/qml/PlayspacePage.qml index a762f4f..f0b6e9c 100644 --- a/src/res/qml/PlayspacePage.qml +++ b/src/res/qml/PlayspacePage.qml @@ -340,6 +340,30 @@ MyStackViewPage { } } + Item { + Layout.fillWidth: true + } + + MyPushButton { + id: spaceLogMatrices + Layout.preferredWidth: 250 + visible: MoveCenterTabController.showLogMatricesButton + text: "Log Matrices" + onClicked: { + MoveCenterTabController.outputLogPoses() + } + } + + MyPushButton { + id: spaceSeatedRecenter + Layout.preferredWidth: 250 + visible: false + text: "Seated Recenter" + onClicked: { + MoveCenterTabController.updateSeatedResetData() + } + } + } } @@ -356,19 +380,14 @@ MyStackViewPage { lockXToggle.checked = MoveCenterTabController.lockXToggle lockYToggle.checked = MoveCenterTabController.lockYToggle lockZToggle.checked = MoveCenterTabController.lockZToggle + spaceLogMatrices.visible = MoveCenterTabController.showLogMatricesButton if (MoveCenterTabController.trackingUniverse === 0) { spaceModeText.text = "Sitting" - spaceRotationPlusButton.enabled = false - spaceRotationMinusButton.enabled = false - spaceRotationSlider.enabled = false - spaceRotationText.text = "-" + spaceSeatedRecenter.visible = true } else if (MoveCenterTabController.trackingUniverse === 1) { spaceModeText.text = "Standing" - spaceRotationPlusButton.enabled = true - spaceRotationMinusButton.enabled = true - spaceRotationSlider.enabled = true - spaceRotationText.text = "0°" + spaceSeatedRecenter.visible = false } else { spaceModeText.text = "Unknown(" + MoveCenterTabController.trackingUniverse + ")" } @@ -407,16 +426,10 @@ MyStackViewPage { onTrackingUniverseChanged: { if (MoveCenterTabController.trackingUniverse === 0) { spaceModeText.text = "Sitting" - spaceRotationPlusButton.enabled = false - spaceRotationMinusButton.enabled = false - spaceRotationSlider.enabled = false - spaceRotationText.text = "-" + spaceSeatedRecenter.visible = true } else if (MoveCenterTabController.trackingUniverse === 1) { spaceModeText.text = "Standing" - spaceRotationPlusButton.enabled = true - spaceRotationMinusButton.enabled = true - spaceRotationSlider.enabled = true - spaceRotationText.text = "0°" + spaceSeatedRecenter.visible = false } else { spaceModeText.text = "Unknown(" + MoveCenterTabController.trackingUniverse + ")" } diff --git a/src/res/qml/SettingsPage.qml b/src/res/qml/SettingsPage.qml index 79eb375..6fd4b17 100644 --- a/src/res/qml/SettingsPage.qml +++ b/src/res/qml/SettingsPage.qml @@ -26,6 +26,14 @@ MyStackViewPage { } } + MyToggleButton { + id: allowExternalEditsToggle + text: "Allow External App Chaperone Edits (Danger)" + onCheckedChanged: { + MoveCenterTabController.setAllowExternalEdits(checked, true) + } + } + Item { Layout.fillHeight: true } @@ -33,6 +41,7 @@ MyStackViewPage { Component.onCompleted: { settingsAutoStartToggle.checked = SettingsTabController.autoStartEnabled forceReviveToggle.checked = SettingsTabController.forceRevivePage + allowExternalEditsToggle.checked = MoveCenterTabController.allowExternalEdits } Connections { @@ -44,5 +53,12 @@ MyStackViewPage { forceReviveToggle.checked = SettingsTabController.forceRevivePage } } + + Connections { + target: MoveCenterTabController + onAllowExternalEditsChanged: { + allowExternalEditsToggle.checked = MoveCenterTabController.allowExternalEdits + } + } } } diff --git a/src/tabcontrollers/MoveCenterTabController.cpp b/src/tabcontrollers/MoveCenterTabController.cpp index c900d56..500b42f 100644 --- a/src/tabcontrollers/MoveCenterTabController.cpp +++ b/src/tabcontrollers/MoveCenterTabController.cpp @@ -118,6 +118,16 @@ void MoveCenterTabController::initStage1() { m_lockZToggle = value.toBool(); } + value = settings->value( "showLogMatricesButton", m_showLogMatricesButton ); + if ( value.isValid() && !value.isNull() ) + { + m_showLogMatricesButton = value.toBool(); + } + value = settings->value( "allowExternalEdits", m_allowExternalEdits ); + if ( value.isValid() && !value.isNull() ) + { + m_allowExternalEdits = value.toBool(); + } settings->endGroup(); m_lastDragUpdateTimePoint = std::chrono::steady_clock::now(); m_lastGravityUpdateTimePoint = std::chrono::steady_clock::now(); @@ -131,6 +141,109 @@ void MoveCenterTabController::initStage2( OverlayController* var_parent, this->widget = var_widget; } +void MoveCenterTabController::outputLogPoses() +{ + vr::TrackedDevicePose_t devicePosesStanding[vr::k_unMaxTrackedDeviceCount]; + + vr::VRSystem()->GetDeviceToAbsoluteTrackingPose( + vr::TrackingUniverseStanding, + 0.0f, + devicePosesStanding, + vr::k_unMaxTrackedDeviceCount ); + + vr::HmdMatrix34_t hmdStanding + = devicePosesStanding[0].mDeviceToAbsoluteTracking; + + LOG( INFO ) << "HMD POSE (standing universe)"; + outputLogHmdMatrix( hmdStanding ); + + vr::TrackedDevicePose_t devicePosesSeated[vr::k_unMaxTrackedDeviceCount]; + + vr::VRSystem()->GetDeviceToAbsoluteTrackingPose( + vr::TrackingUniverseSeated, + 0.0f, + devicePosesSeated, + vr::k_unMaxTrackedDeviceCount ); + + vr::HmdMatrix34_t hmdSeated + = devicePosesSeated[0].mDeviceToAbsoluteTracking; + + LOG( INFO ) << "HMD POSE (seated universe)"; + outputLogHmdMatrix( hmdSeated ); + + auto leftHand = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole( + vr::TrackedControllerRole_LeftHand ); + auto rightHand = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole( + vr::TrackedControllerRole_RightHand ); + + vr::HmdMatrix34_t leftHandMatrix + = devicePosesStanding[leftHand].mDeviceToAbsoluteTracking; + vr::HmdMatrix34_t rightHandMatrix + = devicePosesStanding[rightHand].mDeviceToAbsoluteTracking; + + LOG( INFO ) << "LEFT Hand Controller Pose (standing universe)"; + outputLogHmdMatrix( leftHandMatrix ); + + LOG( INFO ) << "RIGHT Hand Controller Pose (standing universe)"; + outputLogHmdMatrix( rightHandMatrix ); + + vr::HmdMatrix34_t standingZero; + vr::VRChaperoneSetup()->GetWorkingStandingZeroPoseToRawTrackingPose( + &standingZero ); + LOG( INFO ) << "GetWorkingStandingZeroPoseToRawTrackingPose"; + outputLogHmdMatrix( standingZero ); + + vr::HmdMatrix34_t seatedZero; + vr::VRChaperoneSetup()->GetWorkingSeatedZeroPoseToRawTrackingPose( + &seatedZero ); + LOG( INFO ) << "GetWorkingSeatedZeroPoseToRawTrackingPose"; + outputLogHmdMatrix( seatedZero ); + + vr::HmdMatrix34_t seatedZeroLive; + vr::VRChaperoneSetup()->GetLiveSeatedZeroPoseToRawTrackingPose( + &seatedZeroLive ); + LOG( INFO ) << "GetLiveSeatedZeroPoseToRawTrackingPose"; + outputLogHmdMatrix( seatedZeroLive ); + + vr::HmdMatrix34_t seatedToStandingAbsolute + = vr::VRSystem()->GetSeatedZeroPoseToStandingAbsoluteTrackingPose(); + LOG( INFO ) << "GetSeatedZeroPoseToStandingAbsoluteTrackingPose"; + outputLogHmdMatrix( seatedToStandingAbsolute ); + + LOG( INFO ) << "m_universeCenterForReset"; + outputLogHmdMatrix( m_universeCenterForReset ); + + LOG( INFO ) << "m_seatedCenterForReset"; + outputLogHmdMatrix( m_seatedCenterForReset ); +} + +void MoveCenterTabController::outputLogHmdMatrix( vr::HmdMatrix34_t hmdMatrix ) +{ + LOG( INFO ) << hmdMatrix.m[0][0] << "\t\t\t" << hmdMatrix.m[0][1] + << "\t\t\t" << hmdMatrix.m[0][2] << "\t\t\t" + << hmdMatrix.m[0][3]; + LOG( INFO ) << hmdMatrix.m[1][0] << "\t\t\t" << hmdMatrix.m[1][1] + << "\t\t\t" << hmdMatrix.m[1][2] << "\t\t\t" + << hmdMatrix.m[1][3]; + LOG( INFO ) << hmdMatrix.m[2][0] << "\t\t\t" << hmdMatrix.m[2][1] + << "\t\t\t" << hmdMatrix.m[2][2] << "\t\t\t" + << hmdMatrix.m[2][3]; + + float atan2Yaw = std::atan2( hmdMatrix.m[0][2], hmdMatrix.m[2][2] ); + LOG( INFO ) << "atan2 Yaw Calculation: " << atan2Yaw << "radians " + << ( ( static_cast( atan2Yaw ) + * k_radiansToCentidegrees ) + / 100 ) + << "degrees"; + + vr::HmdQuaternion_t hmdQuat = quaternion::fromHmdMatrix34( hmdMatrix ); + double hmdQuatYaw = quaternion::getYaw( hmdQuat ); + LOG( INFO ) << "Quaternion Yaw Calculation: " << hmdQuatYaw << "radians " + << ( ( hmdQuatYaw * k_radiansToCentidegrees ) / 100 ) + << "degrees"; + LOG( INFO ) << ""; +} + int MoveCenterTabController::trackingUniverse() const { return static_cast( m_trackingUniverse ); @@ -140,7 +253,12 @@ void MoveCenterTabController::setTrackingUniverse( int value, bool notify ) { if ( m_trackingUniverse != value ) { - reset(); + vr::VRChaperoneSetup()->HideWorkingSetPreview(); + if ( !m_roomSetupModeDetected && value == vr::TrackingUniverseStanding ) + { + reset(); + } + m_trackingUniverse = value; if ( notify ) { @@ -207,11 +325,25 @@ void MoveCenterTabController::setRotation( int value, bool notify ) // Get hmd pose matrix. vr::TrackedDevicePose_t devicePosesForRot[vr::k_unMaxTrackedDeviceCount]; - vr::VRSystem()->GetDeviceToAbsoluteTrackingPose( - vr::TrackingUniverseStanding, - 0.0f, - devicePosesForRot, - vr::k_unMaxTrackedDeviceCount ); + + // source must be current universe + if ( m_trackingUniverse == vr::TrackingUniverseSeated ) + { + vr::VRSystem()->GetDeviceToAbsoluteTrackingPose( + vr::TrackingUniverseSeated, + 0.0f, + devicePosesForRot, + vr::k_unMaxTrackedDeviceCount ); + } + else + { + vr::VRSystem()->GetDeviceToAbsoluteTrackingPose( + vr::TrackingUniverseStanding, + 0.0f, + devicePosesForRot, + vr::k_unMaxTrackedDeviceCount ); + } + vr::HmdMatrix34_t oldHmdPos = devicePosesForRot[0].mDeviceToAbsoluteTracking; @@ -626,6 +758,45 @@ void MoveCenterTabController::setLockZ( bool value, bool notify ) } } +bool MoveCenterTabController::showLogMatricesButton() const +{ + return m_showLogMatricesButton; +} + +void MoveCenterTabController::setShowLogMatricesButton( bool value, + bool notify ) +{ + m_showLogMatricesButton = value; + auto settings = OverlayController::appSettings(); + settings->beginGroup( "playspaceSettings" ); + settings->setValue( "showLogMatricesButton", m_showLogMatricesButton ); + settings->endGroup(); + settings->sync(); + if ( notify ) + { + emit showLogMatricesButtonChanged( m_showLogMatricesButton ); + } +} + +bool MoveCenterTabController::allowExternalEdits() const +{ + return m_allowExternalEdits; +} + +void MoveCenterTabController::setAllowExternalEdits( bool value, bool notify ) +{ + m_allowExternalEdits = value; + auto settings = OverlayController::appSettings(); + settings->beginGroup( "playspaceSettings" ); + settings->setValue( "allowExternalEdits", m_allowExternalEdits ); + settings->endGroup(); + settings->sync(); + if ( notify ) + { + emit allowExternalEditsChanged( m_allowExternalEdits ); + } +} + void MoveCenterTabController::modOffsetX( float value, bool notify ) { if ( !m_lockXToggle ) @@ -662,11 +833,22 @@ void MoveCenterTabController::modOffsetZ( float value, bool notify ) } } +void MoveCenterTabController::shutdown() +{ + reset(); + vr::VRChaperoneSetup()->HideWorkingSetPreview(); +} + +void MoveCenterTabController::incomingSeatedReset() +{ + updateSeatedResetData(); +} + void MoveCenterTabController::reset() { + vr::VRChaperoneSetup()->HideWorkingSetPreview(); m_heightToggle = false; emit heightToggleChanged( m_heightToggle ); - applyChaperoneResetData(); m_oldOffsetX = 0.0f; m_oldOffsetY = 0.0f; m_oldOffsetZ = 0.0f; @@ -675,6 +857,7 @@ void MoveCenterTabController::reset() m_offsetY = 0.0f; m_offsetZ = 0.0f; m_rotation = 0; + applyChaperoneResetData(); emit offsetXChanged( m_offsetX ); emit offsetYChanged( m_offsetY ); emit offsetZChanged( m_offsetZ ); @@ -700,9 +883,20 @@ void MoveCenterTabController::zeroOffsets() emit rotationChanged( m_rotation ); updateChaperoneResetData(); m_pendingZeroOffsets = false; + if ( m_roomSetupModeDetected ) + { + LOG( INFO ) << "room setup EXIT detected"; + m_roomSetupModeDetected = false; + } + + LOG( INFO ) << "SUCCESS: Chaperone Data Updated and Offsets zeroed out"; } else { + if ( !m_pendingZeroOffsets ) + { + LOG( INFO ) << "PENDING: Chaperone Data Update and Offsets zeroing"; + } m_pendingZeroOffsets = true; } } @@ -729,6 +923,46 @@ void MoveCenterTabController::clampVelocity( double* velocity ) } } +void MoveCenterTabController::updateSeatedResetData() +{ + reset(); + vr::VRChaperoneSetup()->RevertWorkingCopy(); + vr::TrackedDevicePose_t devicePosesStanding[vr::k_unMaxTrackedDeviceCount]; + vr::VRSystem()->GetDeviceToAbsoluteTrackingPose( + vr::TrackingUniverseStanding, + 0.0f, + devicePosesStanding, + vr::k_unMaxTrackedDeviceCount ); + vr::HmdMatrix34_t hmdMatrix + = devicePosesStanding[0].mDeviceToAbsoluteTracking; + + vr::HmdQuaternion_t hmdQuat = quaternion::fromHmdMatrix34( hmdMatrix ); + double hmdYaw = quaternion::getYaw( hmdQuat ); + int hmdYawCentideg = static_cast( hmdYaw * k_radiansToCentidegrees ); + // Keep angle within -18000 ~ 18000 centidegrees + if ( hmdYawCentideg > 18000 ) + { + hmdYawCentideg -= 36000; + } + else if ( hmdYawCentideg < -18000 ) + { + hmdYawCentideg += 36000; + } + + m_seatedCenterForReset = m_universeCenterForReset; + m_seatedHeight = hmdMatrix.m[1][3]; + m_seatedCenterForReset.m[1][3] += m_seatedHeight; + + m_offsetX = hmdMatrix.m[0][3]; + m_offsetY = 0.0f; + m_offsetZ = hmdMatrix.m[2][3]; + m_rotation = hmdYawCentideg; + emit offsetXChanged( m_offsetX ); + emit offsetYChanged( m_offsetY ); + emit offsetZChanged( m_offsetZ ); + emit rotationChanged( m_rotation ); +} + void MoveCenterTabController::updateChaperoneResetData() { vr::VRChaperoneSetup()->HideWorkingSetPreview(); @@ -741,50 +975,76 @@ void MoveCenterTabController::updateChaperoneResetData() m_collisionBoundsCountForReset = currentQuadCount; vr::VRChaperoneSetup()->GetWorkingCollisionBoundsInfo( m_collisionBoundsForReset, ¤tQuadCount ); + vr::VRChaperoneSetup()->GetWorkingStandingZeroPoseToRawTrackingPose( &m_universeCenterForReset ); - float universeCenterForResetYaw = std::atan2( - m_universeCenterForReset.m[0][2], m_universeCenterForReset.m[2][2] ); - // we want to store m_collisionBoundsForOffset as spacially relative to - // m_universeCenterForReset, so: + // update seated center to standing offset by current hmd Y value. + m_seatedCenterForReset = m_universeCenterForReset; + vr::TrackedDevicePose_t devicePosesStanding[vr::k_unMaxTrackedDeviceCount]; + vr::VRSystem()->GetDeviceToAbsoluteTrackingPose( + vr::TrackingUniverseStanding, + 0.0f, + devicePosesStanding, + vr::k_unMaxTrackedDeviceCount ); + vr::HmdMatrix34_t hmdMatrix + = devicePosesStanding[0].mDeviceToAbsoluteTracking; + m_seatedHeight = hmdMatrix.m[1][3]; + m_seatedCenterForReset.m[1][3] += m_seatedHeight; - // for every quad in the chaperone bounds... - for ( unsigned quad = 0; quad < m_collisionBoundsCountForReset; quad++ ) + if ( m_collisionBoundsCountForReset > 0 ) { - // at every corner in that quad... - for ( unsigned corner = 0; corner < 4; corner++ ) - { - // copy from m_collisionBoundsForReset - m_collisionBoundsForOffset[quad].vCorners[corner].v[0] - = m_collisionBoundsForReset[quad].vCorners[corner].v[0]; - m_collisionBoundsForOffset[quad].vCorners[corner].v[1] - = m_collisionBoundsForReset[quad].vCorners[corner].v[1]; - m_collisionBoundsForOffset[quad].vCorners[corner].v[2] - = m_collisionBoundsForReset[quad].vCorners[corner].v[2]; + float universeCenterForResetYaw + = std::atan2( m_universeCenterForReset.m[0][2], + m_universeCenterForReset.m[2][2] ); - // unrotate by universe center's yaw - rotateFloatCoordinates( - m_collisionBoundsForOffset[quad].vCorners[corner].v, - -universeCenterForResetYaw ); + // we want to store m_collisionBoundsForOffset as spacially relative to + // m_universeCenterForReset, so: + + // for every quad in the chaperone bounds... + for ( unsigned quad = 0; quad < m_collisionBoundsCountForReset; quad++ ) + { + // at every corner in that quad... + for ( unsigned corner = 0; corner < 4; corner++ ) + { + // copy from m_collisionBoundsForReset + m_collisionBoundsForOffset[quad].vCorners[corner].v[0] + = m_collisionBoundsForReset[quad].vCorners[corner].v[0]; + m_collisionBoundsForOffset[quad].vCorners[corner].v[1] + = m_collisionBoundsForReset[quad].vCorners[corner].v[1]; + m_collisionBoundsForOffset[quad].vCorners[corner].v[2] + = m_collisionBoundsForReset[quad].vCorners[corner].v[2]; + + // unrotate by universe center's yaw + rotateFloatCoordinates( + m_collisionBoundsForOffset[quad].vCorners[corner].v, + -universeCenterForResetYaw ); + } } } + // update the working set preview for potential Oculus and WMR issues - vr::VRChaperoneSetup()->ShowWorkingSetPreview(); + // vr::VRChaperoneSetup()->ShowWorkingSetPreview(); } void MoveCenterTabController::applyChaperoneResetData() { vr::VRChaperoneSetup()->HideWorkingSetPreview(); vr::VRChaperoneSetup()->RevertWorkingCopy(); - vr::VRChaperoneSetup()->SetWorkingCollisionBoundsInfo( - m_collisionBoundsForReset, m_collisionBoundsCountForReset ); + if ( m_collisionBoundsCountForReset > 0 ) + { + vr::VRChaperoneSetup()->SetWorkingCollisionBoundsInfo( + m_collisionBoundsForReset, m_collisionBoundsCountForReset ); + } vr::VRChaperoneSetup()->SetWorkingStandingZeroPoseToRawTrackingPose( &m_universeCenterForReset ); + vr::VRChaperoneSetup()->SetWorkingSeatedZeroPoseToRawTrackingPose( + &m_seatedCenterForReset ); + vr::VRChaperoneSetup()->CommitWorkingCopy( vr::EChaperoneConfigFile_Live ); // update the working set preview otherwise Oculus and WMR users may not see // results of the reset - vr::VRChaperoneSetup()->ShowWorkingSetPreview(); + // vr::VRChaperoneSetup()->ShowWorkingSetPreview(); } // START of drag bindings: @@ -1492,10 +1752,14 @@ void MoveCenterTabController::saveUncommittedChaperone() { if ( !m_chaperoneCommitted ) { + // double commit... once to ensure before we HideWorkingSetPreview the + // working set is synced. Commit a second time as a workaround for WMR + // and Rift not getting the commit during active ShowWorkingSetPreview + vr::VRChaperoneSetup()->CommitWorkingCopy( + vr::EChaperoneConfigFile_Live ); + vr::VRChaperoneSetup()->HideWorkingSetPreview(); vr::VRChaperoneSetup()->CommitWorkingCopy( vr::EChaperoneConfigFile_Live ); - // test removal for oculus and WMR users - // vr::VRChaperoneSetup()->HideWorkingSetPreview(); m_chaperoneCommitted = true; } } @@ -1855,6 +2119,15 @@ void MoveCenterTabController::updateSpace() return; } + if ( m_allowExternalEdits && m_oldOffsetX == 0.0f && m_oldOffsetY == 0.0f + && m_oldOffsetZ == 0.0f && m_oldRotation == 0 ) + { + vr::VRChaperoneSetup()->ReloadFromDisk( vr::EChaperoneConfigFile_Live ); + vr::VRChaperoneSetup()->CommitWorkingCopy( + vr::EChaperoneConfigFile_Live ); + updateChaperoneResetData(); + } + vr::HmdMatrix34_t offsetUniverseCenter; // set offsetUniverseCenter to the current angle @@ -1892,6 +2165,17 @@ void MoveCenterTabController::updateSpace() offsetUniverseCenter.m[2][3] += m_universeCenterForReset.m[2][2] * m_offsetZ; + // keep the seated origin synced with offsets if in seated mode + if ( m_trackingUniverse == vr::TrackingUniverseSeated ) + { + vr::HmdMatrix34_t offsetSeatedCenter = offsetUniverseCenter; + + offsetSeatedCenter.m[1][3] += m_seatedHeight; + + vr::VRChaperoneSetup()->SetWorkingSeatedZeroPoseToRawTrackingPose( + &offsetSeatedCenter ); + } + if ( m_adjustChaperone ) { // make a copy of our bounds and @@ -1950,9 +2234,14 @@ void MoveCenterTabController::updateSpace() } vr::VRChaperoneSetup()->SetWorkingStandingZeroPoseToRawTrackingPose( &offsetUniverseCenter ); + vr::VRChaperoneSetup()->ShowWorkingSetPreview(); m_chaperoneCommitted = false; + // loadChaperoneData( false ), false so that we don't load live data, and + // reference the working set instead. + parent->chaperoneUtils().loadChaperoneData( false ); + m_oldOffsetX = m_offsetX; m_oldOffsetY = m_offsetY; m_oldOffsetZ = m_offsetZ; @@ -1964,28 +2253,58 @@ void MoveCenterTabController::eventLoopTick( vr::TrackedDevicePose_t* devicePoses ) { - if ( settingsUpdateCounter >= k_moveCenterSettingsUpdateCounter ) + // detect if room setup is running + if ( universe == vr::TrackingUniverseRawAndUncalibrated ) { - if ( parent->isDashboardVisible() ) + if ( !m_roomSetupModeDetected ) { - setTrackingUniverse( int( universe ) ); + m_roomSetupModeDetected = true; + + // give up on any pending zero offsets so they aren't applied in the + // middle of room setup. + m_pendingZeroOffsets = false; + + LOG( INFO ) << "room setup ENTRY detected"; + vr::VRChaperoneSetup()->HideWorkingSetPreview(); + reset(); + vr::VRChaperoneSetup()->RevertWorkingCopy(); } - settingsUpdateCounter = 0; + setTrackingUniverse( int( universe ) ); + return; } - else + + // detect entering seated mode + if ( universe == vr::TrackingUniverseSeated && !m_seatedModeDetected ) { - settingsUpdateCounter++; + m_seatedModeDetected = true; + LOG( INFO ) << "seated mode ENTRY detected"; + } + + // detect exiting seated mode + if ( universe == vr::TrackingUniverseStanding && m_seatedModeDetected ) + { + m_seatedModeDetected = false; + reset(); + LOG( INFO ) << "seated mode EXIT detected"; } // If we're trying to redifine the origin point, but can't becaues of bad // chaperone calibration, we keep trying and hold off on motion features // until we get ChaperoneCalibrationState_OK - if ( m_pendingZeroOffsets ) + + // if we were in room setup, but got this far in the loop, universe is no + // longer raw mode and we detect room setup exit and zeroOffsets() to apply + // new setup. + if ( m_pendingZeroOffsets || m_roomSetupModeDetected ) { zeroOffsets(); + // m_roomSetupModeDetected is set to false in zeroOffsets() if it's + // successful. } else { + setTrackingUniverse( int( universe ) ); + // get current space rotation in radians double angle = m_rotation * k_centidegreesToRadians; diff --git a/src/tabcontrollers/MoveCenterTabController.h b/src/tabcontrollers/MoveCenterTabController.h index ac1018a..b715331 100644 --- a/src/tabcontrollers/MoveCenterTabController.h +++ b/src/tabcontrollers/MoveCenterTabController.h @@ -68,6 +68,11 @@ class MoveCenterTabController : public QObject requireLockYChanged ) Q_PROPERTY( bool lockZToggle READ lockZToggle WRITE setLockZ NOTIFY requireLockZChanged ) + Q_PROPERTY( + bool showLogMatricesButton READ showLogMatricesButton WRITE + setShowLogMatricesButton NOTIFY showLogMatricesButtonChanged ) + Q_PROPERTY( bool allowExternalEdits READ allowExternalEdits WRITE + setAllowExternalEdits NOTIFY allowExternalEditsChanged ) private: OverlayController* parent; @@ -100,6 +105,7 @@ private: float m_gravityFloor = 0.0f; float m_gravityStrength = 9.8f; float m_flingStrength = 1.0f; + float m_seatedHeight = 1.0f; bool m_momentumSave = false; bool m_lockXToggle = false; bool m_lockYToggle = false; @@ -138,6 +144,10 @@ private: bool m_chaperoneCommitted = true; bool m_pendingZeroOffsets = true; bool m_dashWasOpenPreviousFrame = false; + bool m_roomSetupModeDetected = false; + bool m_seatedModeDetected = false; + bool m_showLogMatricesButton = false; + bool m_allowExternalEdits = false; unsigned settingsUpdateCounter = 0; int m_hmdRotationStatsUpdateCounter = 0; unsigned m_dragComfortFrameSkipCounter = 0; @@ -148,6 +158,7 @@ private: vr::HmdQuad_t* m_collisionBoundsForReset; uint32_t m_collisionBoundsCountForReset = 0; vr::HmdMatrix34_t m_universeCenterForReset; + vr::HmdMatrix34_t m_seatedCenterForReset; vr::HmdQuad_t* m_collisionBoundsForOffset; void updateHmdRotationCounter( vr::TrackedDevicePose_t hmdPose, @@ -160,6 +171,7 @@ private: void updateChaperoneResetData(); void applyChaperoneResetData(); void saveUncommittedChaperone(); + void outputLogHmdMatrix( vr::HmdMatrix34_t hmdMatrix ); public: void initStage1(); @@ -190,8 +202,11 @@ public: bool lockXToggle() const; bool lockYToggle() const; bool lockZToggle() const; + bool showLogMatricesButton() const; + bool allowExternalEdits() const; double getHmdYawTotal(); void resetHmdYawTotal(); + void incomingSeatedReset(); // actions: void leftHandSpaceDrag( bool leftHandDragActive ); @@ -247,8 +262,13 @@ public slots: void setLockX( bool value, bool notify = true ); void setLockY( bool value, bool notify = true ); void setLockZ( bool value, bool notify = true ); + void setShowLogMatricesButton( bool value, bool notify = true ); + void setAllowExternalEdits( bool value, bool notify = true ); + void shutdown(); void reset(); + void updateSeatedResetData(); + void outputLogPoses(); void zeroOffsets(); signals: @@ -275,6 +295,8 @@ signals: void requireLockXChanged( bool value ); void requireLockYChanged( bool value ); void requireLockZChanged( bool value ); + void showLogMatricesButtonChanged( bool value ); + void allowExternalEditsChanged( bool value ); }; } // namespace advsettings diff --git a/src/utils/ChaperoneUtils.cpp b/src/utils/ChaperoneUtils.cpp index 3945694..63d25a6 100644 --- a/src/utils/ChaperoneUtils.cpp +++ b/src/utils/ChaperoneUtils.cpp @@ -74,10 +74,21 @@ float ChaperoneUtils::_getDistanceToChaperone( return distance; } -void ChaperoneUtils::loadChaperoneData() +void ChaperoneUtils::loadChaperoneData( bool fromLiveBounds ) { std::lock_guard lock( _mutex ); - vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo( nullptr, &_quadsCount ); + + if ( fromLiveBounds ) + { + vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo( nullptr, + &_quadsCount ); + } + else + { + vr::VRChaperoneSetup()->GetWorkingCollisionBoundsInfo( nullptr, + &_quadsCount ); + } + if ( _quadsCount > 0 ) { std::unique_ptr quadsBuffer( @@ -86,8 +97,17 @@ void ChaperoneUtils::loadChaperoneData() _corners.reset( reinterpret_cast( new vr::HmdQuad_t[_quadsCount] ) ); vr::HmdVector3_t* _cornersPtr = _corners.get(); - vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo( quadsBufferPtr, - &_quadsCount ); + if ( fromLiveBounds ) + { + vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo( quadsBufferPtr, + &_quadsCount ); + } + else + { + vr::VRChaperoneSetup()->GetWorkingCollisionBoundsInfo( + quadsBufferPtr, &_quadsCount ); + } + for ( uint32_t i = 0; i < _quadsCount; i++ ) { _cornersPtr[i] = quadsBufferPtr[i].vCorners[0]; diff --git a/src/utils/ChaperoneUtils.h b/src/utils/ChaperoneUtils.h index 9a1176e..636c344 100644 --- a/src/utils/ChaperoneUtils.h +++ b/src/utils/ChaperoneUtils.h @@ -32,7 +32,7 @@ public: return _mutex; } - void loadChaperoneData(); + void loadChaperoneData( bool fromLiveBounds = true ); float getDistanceToChaperone( const vr::HmdVector3_t& point, vr::HmdVector3_t* projectedPoint = nullptr,