├── LICENSE ├── Readme.md ├── advancedSettings.pro ├── bin ├── logging.conf.installer ├── logging.conf.standalone ├── win64 │ ├── LICENSE │ ├── logging.conf │ ├── manifest.vrmanifest │ ├── openvr_api.dll │ ├── qt.conf │ ├── res │ │ ├── qml │ │ │ ├── AccessibilityPage.qml │ │ │ ├── AudioPage.qml │ │ │ ├── ChaperonePage.qml │ │ │ ├── ChaperoneWarningsPage.qml │ │ │ ├── FixFloorPage.qml │ │ │ ├── MyComboBox.qml │ │ │ ├── MyDialogOkCancelPopup.qml │ │ │ ├── MyDialogOkPopup.qml │ │ │ ├── MyPushButton.qml │ │ │ ├── MyPushButton2.qml │ │ │ ├── MyResources.qml │ │ │ ├── MySlider.qml │ │ │ ├── MyStackViewPage.qml │ │ │ ├── MyText.qml │ │ │ ├── MyTextField.qml │ │ │ ├── MyToggleButton.qml │ │ │ ├── PlayspacePage.qml │ │ │ ├── PttControllerConfigDialog.qml │ │ │ ├── RevivePage.qml │ │ │ ├── RootPage.qml │ │ │ ├── SettingsPage.qml │ │ │ ├── StatisticsPage.qml │ │ │ ├── SteamVRPage.qml │ │ │ ├── UtilitiesPage.qml │ │ │ ├── backarrow.svg │ │ │ ├── mainwidget.qml │ │ │ ├── mic_off.svg │ │ │ ├── mic_on.svg │ │ │ ├── ptt_notification.png │ │ │ ├── ptt_notification.svg │ │ │ ├── qmldir │ │ │ ├── speaker_off.svg │ │ │ └── speaker_on.svg │ │ ├── sounds │ │ │ └── alarm01.wav │ │ └── thumbicon.png │ ├── restartvrserver.bat │ └── startdesktopmode.bat └── windeployqt.bat ├── docs └── screenshots │ ├── AccessibilityPage.png │ ├── AudioPage.png │ ├── ChaperonePage.png │ ├── ChaperoneWarningPage.png │ ├── FloorFixPage.png │ ├── InVRScreenshot.png │ ├── PlayspacePage.png │ ├── RevivePage.png │ ├── RootPage.png │ ├── SettingsPage.png │ ├── StatisticsPage.png │ ├── SteamVRPage.png │ └── UtilitiesPage.png ├── installer ├── installer.nsi ├── listUninstallFiles.sh └── uninstallFiles.list ├── src ├── logging.h ├── main.cpp ├── overlaycontroller.cpp ├── overlaycontroller.h ├── tabcontrollers │ ├── AccessibilityTabController.cpp │ ├── AccessibilityTabController.h │ ├── AudioManager.h │ ├── AudioTabController.cpp │ ├── AudioTabController.h │ ├── ChaperoneTabController.cpp │ ├── ChaperoneTabController.h │ ├── FixFloorTabController.cpp │ ├── FixFloorTabController.h │ ├── MoveCenterTabController.cpp │ ├── MoveCenterTabController.h │ ├── PttController.cpp │ ├── PttController.h │ ├── ReviveTabController.cpp │ ├── ReviveTabController.h │ ├── SettingsTabController.cpp │ ├── SettingsTabController.h │ ├── StatisticsTabController.cpp │ ├── StatisticsTabController.h │ ├── SteamVRTabController.cpp │ ├── SteamVRTabController.h │ ├── UtilitiesTabController.cpp │ ├── UtilitiesTabController.h │ └── audiomanager │ │ ├── AudioManagerWindows.cpp │ │ ├── AudioManagerWindows.h │ │ └── IPolicyConfig.h └── utils │ ├── ChaperoneUtils.cpp │ ├── ChaperoneUtils.h │ └── Matrix.h └── third-party ├── easylogging++ ├── LICENSE └── easylogging++.h └── openvr ├── LICENSE ├── README.md ├── bin ├── linux64 │ ├── libopenvr_api.so │ └── libopenvr_api.so.dbg ├── osx32 │ ├── libopenvr_api.dylib │ └── libopenvr_api.dylib.dSYM │ │ └── Contents │ │ ├── Info.plist │ │ └── Resources │ │ └── DWARF │ │ └── libopenvr_api.dylib ├── win32 │ ├── openvr_api.dll │ └── openvr_api.pdb └── win64 │ ├── openvr_api.dll │ └── openvr_api.pdb ├── include ├── openvr.h ├── openvr_api.cs ├── openvr_api.json ├── openvr_capi.h └── openvr_driver.h └── lib ├── linux64 └── libopenvr_api.so ├── osx32 └── libopenvr_api.dylib ├── win32 └── openvr_api.lib └── win64 └── openvr_api.lib /Readme.md: -------------------------------------------------------------------------------- 1 | 2 | ![language](https://img.shields.io/badge/Language-C%2B%2B11%2C%20QML-green.svg) ![dependencies](https://img.shields.io/badge/Dependencies-OpenVR%2C%20Qt5-green.svg) ![license_gpl3](https://img.shields.io/badge/License-GPL%203.0-green.svg) 3 | 4 | > # **This repository is deprecated!** 5 | > ### **The newest version can be found at [github.com/OpenVR-Advanced-Settings/OpenVR-AdvancedSettings](https://github.com/OpenVR-Advanced-Settings/OpenVR-AdvancedSettings).** 6 | 7 | # OpenVR Advanced Settings Overlay 8 | 9 | Adds an overlay to the OpenVR dashboard that allows access to advanced settings. 10 | 11 | ![Example Screenshot](docs/screenshots/InVRScreenshot.png) 12 | 13 | # Features 14 | 15 | - Set supersampling values. 16 | - Enable/disable asynchronous and interleaved reprojection. 17 | - Save supersampling and reprojection settings into profiles. 18 | - Change several chaperone settings not accessible via SteamVR settings (to e.g. make it completely invisible). 19 | - Chaperone Proximity Warning: Several warning methods can be configured. 20 | - Chaperone Profiles: Allows to quickly switch chaperone geometry and settings while in VR. 21 | - Temporarily move and rotate the playspace. 22 | - Floor height fix. 23 | - Displays several performance statistics and other statistics (e.g. headset rotations). 24 | - Select the playback/mirror/recording audio device 25 | - Mute/unmute and set volume of audio mirror device. 26 | - Mute/unmute and set volume of microphone device. 27 | - Implements push-to-talk and allows to configure push-to-talk profiles. 28 | - Desktop mode shows a window on the desktop instead of a vr overlay. 29 | - Revive settings support (Requires [Revive 1.0.4+](https://github.com/LibreVR/Revive) for full functionality). 30 | - VR Keyboard Input Utilities 31 | - Simple Alarm Clock 32 | - Player height adjust toggle (Credits to mklim) 33 | 34 | # Usage 35 | 36 | ## Installer 37 | 38 | Download the newest installer from the [release section](https://github.com/matzman666/OpenVR-AdvancedSettings/releases) and execute it. 39 | 40 | If you have an older standalone version installed, delete the old application folder first. 41 | 42 | ## Standalone 43 | 44 | Download the newest standalone archive from the [release section](https://github.com/matzman666/OpenVR-AdvancedSettings/releases) and unpack the archive. 45 | 46 | To install for the first time simply start AdvancedSettings.exe once while SteamVRis running. It will register with SteamVR and automatically starts whenever SteamVR starts (Can be disabled in the settings). 47 | 48 | To upgrade an existing installation first stop SteamVR and delete the old application folder (or override it). Then start SteamVR and run AdvancedSettings.exe once. 49 | 50 | ## Desktop mode 51 | 52 | Executing startdesktopmode.bat from the application folder shows a window on the desktop instead of a vr overlay. Desktop mode can be used alongside an already running vr overlay instance. 53 | 54 | # Documentation 55 | 56 | ## Top Page: 57 | 58 | ![Root Page](docs/screenshots/RootPage.png) 59 | 60 | - **Supersampling Profile**: Allows to apply supersampling profiles. Profiles can be created on the SteamVR page 61 | - **Chaperone Profile**: Allows to apply chaperone profiles. Profiles can be created on the Chaperone page 62 | - **Microphone**: Allows to set the microphone volume and to mute/unmute it. 63 | - **Push-to-Talk**: Enable/disable push-to-talk and allows to apply push-to-talk profiles. Profiles can be created on the Audio page. 64 | 65 | ## - SteamVR Page: 66 | 67 | ![SteamVR Page](docs/screenshots/SteamVRPage.png) 68 | 69 | - **Profile**: Allows to apply/define/delete supersampling profiles that save supersampling and reprojection settings. 70 | - **Application Supersampling**: Supersampling setting for OpenVR applications/games. Application supersampling [now behaves linearly](https://steamcommunity.com/games/250820/announcements/detail/1256913672017664045) where 2.0 means twice the number of pixel. 71 | - **Compositor Render Target Multiplier**: Supersampling setting for the OpenVR compositor (Requires restart). Compositor supersampling still behaves the old way where 2.0 means four-times the number of pixel. 72 | - **Enable Advanced Supersample Filtering**: Einable/disable image filtering on supersampled renderings. 73 | - **Allow Asynchronous Reprojection**: Enable/disable asynchronous reprojection. 74 | - **Allow Interleaved Reprojection**: Enable/disable interleaved reprojection. 75 | - **Enable Always-on Reprojection**: Enable/disable forced reprojection. 76 | - **Restart SteamVR**: Restart SteamVR (May crash the Steam overlay when SteamVR Home is running when you restart. Therefore I advice that you close SteamVR Home before restarting). 77 | 78 | ## - Chaperone Page: 79 | 80 | ![Chaperone Page](docs/screenshots/ChaperonePage.png) 81 | 82 | - **Profile**: Allows to apply/define/delete chaperone profiles that save geometry info, style info or other chaperone settings (What exactly is saved in a chaperone profile can be selected when a profile is created). 83 | - **Visibility**: Allows to configure the visibility of the chaperone bounds. Unlike the slider in the chaperone settings, this one is not capped at 30%. When set to 0 chaperone bounds are completely invisible. 84 | - **Fade Distance**: Allows to configure the distance at which the chaperone bounds are shown. When set to 0 chaperone bounds are completely invisible. 85 | - **Height**: Allows to configure the height of the chaperone bounds. 86 | - **Center Marker**: Displays a marker that represents the center of the playspace. 87 | - **Play Space Maker**: Displays the outlines of the rectangle representing the playspace. 88 | - **Force Bounds**: Force chaperone bounds always on. 89 | - **Proximity Warning Settings**: Opens a page that allows to configure several warning methods for when the user comes too close to the chaperone bounds. 90 | - **Flip Orientation**: Flips the orientation of the play space. 91 | - **Reload from Disk**: Reloads the chaperone bounds geometry from disk. 92 | 93 | 94 | ## - Chaperone Proximity Warning Settings Page: 95 | 96 | ![Chaperone Proximity Warning Settings Page](docs/screenshots/ChaperoneWarningPage.png) 97 | 98 | - **Switch to Beginner Mode**: Switches the chaperone bound's style to beginner mode when the user's distance to the chaperone falls below the configured activation distance. 99 | - **Trigger Haptic Feedback**: The left and right controller start vibrating when the user's distance to the chaperone falls below the configured activation distance. 100 | - **Audio Warning**: Plays an alarm sound when the user's distance to the chaperone falls below the configured activation distance. 101 | - **Loop Audio**: Whether the audio alarm should only be played once or in a loop. 102 | - **Loop Audio**: Modify audio volume as a function of the user's distance to the chaperone. 103 | - **Open dashboard**: Opens the dashboard when the user's distance to the chaperone falls below the configured activation distance. The idea is to pause the game (most single-player games auto-pause when the dashboard is shown) to give the user time for reorientation. 104 | - **Velocity Dependent Fade/Activation Distance**: Dynamically modifies the chaperone's fade distance and the proximity warning's activation distance as a function of the player's speed. The used formula is: *distance = old_distance * ( 1 + distance_modifier * max(left_controller_speed, right_controller_speed, hmd_speed) )* 105 | 106 | ## - Play Space Page: 107 | 108 | ![Play Space Page](docs/screenshots/PlayspacePage.png) 109 | 110 | Allows to temporarily move and rotate the center of the playspace. This allows to reach interaction elements that are just inside our real-world walls or otherwise inaccessible (e.g. when your playspace is smaller than the recommended one). Can also be used to discover the terrors that lie outside of the intended playspace (ever wondered what's behind the door in The Lab?). 111 | 112 | - **Adjust Chaperone**: When enabled then the chaperone bounds stay in place when the playspace is moved or rotated (so noone gets hurt). Unfortunately this does not work when moving up/down. 113 | 114 | ## - Floor Fix Page: 115 | 116 | ![Floor Fix Page](docs/screenshots/FloorFixPage.png) 117 | 118 | Allows you to fix the height of your floor. Just place one controller on your floor and press the button. 119 | 120 | ## - Audio Page: 121 | 122 | ![Audio Page](docs/screenshots/AudioPage.png) 123 | 124 | - **Playback Device**: Allows to select the playback device. 125 | - **Mirror Device**: Allows to select the mirror device, set its volume and to mute/unmute it. 126 | - **Microphone**: Allows to select the microphone device, set its volume and to mute/unmute it. 127 | - **Proximity Sensor Mutes/Unmutes Microphone**: Allows the proximity sensor to mute the microphone when the user is not wearing the HMD, and to unmute it when the user is wearing the HMD. 128 | - **Push-to-Talk**: Enable/disable push-to-talk. When push-to-talk is activated the microphone gets muted unless one of the configured buttons is pressed on one of the configured controllers. 129 | - **Left Controller**: Configure the left controller for push-to-talk. 130 | - **Right Controller**: Configure the right controller for push-to-talk. 131 | - **Show Notification**: Shows a notification icon in the headset when push-to-talk is enabled a configured button is pressed. 132 | - **Push-to-Mute**: Inverse push-to-talk. The Microphone is unmuted by default and muted when any of the configured buttons is pressed. 133 | - **Profile**: Allows to apply/define/delete push-to-talk profiles that save buttons, controller and notification settings. 134 | 135 | ## - Revive Page: 136 | 137 | ![Revive Page](docs/screenshots/RevivePage.png) 138 | 139 | The Revive page is only visible when the [Revive overlay](https://github.com/LibreVR/Revive) is installed. In case an installed Revive overlay is not correctly detected you can force the Revive page in the settings. 140 | 141 | Any changes to controller settings are immediately applied by Revive (Requires Revive 1.0.4+). 142 | 143 | - **Render Target Override**: Overrides the Oculus-side render target (aka supersampling). Enabling it prevents Oculus applications from dynamically modifying this value. Warning: Is applied on top of the SteamVR supersampling value. (pixelsPerDisplayPixel setting in the vrsettings file) 144 | - **Grip Button mode**: Allows to set the grip button mode. (ToggleGrip setting in the vrsettings file) 145 | - **Toggle Delay**: Allows to configure the toggle delay. (ToggleDelay setting in the vrsettings file) 146 | - **Trigger As Grip**: Swaps the trigger and grip. (TriggerAsGrip setting in the vrsettings file) 147 | - **Deadzone**: Allows to modify the simulated thumbsticks' deadzone. (ThumbDeadzone setting in the vrsettings file) 148 | - **Sensitivity**: Allows to modify the simulated thumbsticks' sensitivity. (ThumbSensitivity setting the vrsettings file) 149 | - **Yaw**: Allows to modify the touch controllers yaw orientation. (TouchYaw setting the vrsettings file) 150 | - **Pitch**: Allows to modify the touch controllers pitch orientation. (TouchPitch setting the vrsettings file) 151 | - **Roll**: Allows to modify the touch controllers roll orientation. (TouchRoll setting the vrsettings file) 152 | - **X**: Allows to modify the touch controllers x-offset. (TouchX setting the vrsettings file) 153 | - **Y**: Allows to modify the touch controllers y-offset. (TouchY setting the vrsettings file) 154 | - **Z**: Allows to modify the touch controllers z-offset. (TouchZ setting the vrsettings file) 155 | - **Controller Profile**: Allows to apply/define/delete controller profiles that save the controller settings (grip button mode, deadzone, sensitivity, pitch/yaw/roll and x/y/z-offsets). 156 | 157 | ## - Utilities Page: 158 | 159 | ![Utilities Page](docs/screenshots/UtilitiesPage.png) 160 | 161 | - **Keyboard Utilities:** Some applications (mostly 2D-monitor applications with tackled-on/modded-in VR support) do not support the VR keyboard but require an actual physical keyboard for text input. This utilities allow to send emulated key strokes from VR keyboard input to such application to overcome this limitation. Does not work in desktop mode. 162 | 163 | - **Alarm Clock:** Just a simple alarm clock so you don't miss important appointments. VR can sure mess up perception of time. Does not work in desktop mode. 164 | 165 | - **Steam Desktop Overlay Width:** Allows to increase the size of the Steam desktop overlay. Useful for multi-monitor setups. 166 | 167 | ## - Accessibility Page: 168 | 169 | ![Accessibility Page](docs/screenshots/AccessibilityPage.png) 170 | 171 | - **Adjust Player Height:** Offsets the player height to allows short or wheelchair-bound players to fully interact with height-limited applications by both boosting their height and being able to touch the in-game floor when necessary by pressing a configurable motion controller button. 172 | 173 | ## - Statistics Page: 174 | 175 | ![Statistics Page](docs/screenshots/StatisticsPage.png) 176 | 177 | - **HMD Distance Moved**: Shows the distance the headset has moved on the xz-plane. 178 | - **HMD Rotations**: Shows the number of rotations around the y-axis (Useful for untangling the cord). 179 | - **Left Controller Max Speed**: Shows the max speed of the left controller. 180 | - **Right Controller Max Speed**: Shows the max speed of the right controller. 181 | - **Presented Frames**: Number of frames presented to the hmd in the currently running application. 182 | - **Dropped Frames**: Number of frames dropped in the currently running application. 183 | - **Reprojected Frames**: Number of frames reprojected in the currently running application. 184 | - **Timed Out**: Number of times the currently running application timed out. 185 | - **Reprojection Ratio**: Ratio of presented frames to reprojected frames. 186 | 187 | ## - Settings Page: 188 | 189 | ![Settings Page](docs/screenshots/SettingsPage.png) 190 | 191 | - **Autostart:** Allows you to enable/disable auto start. 192 | - **Force Revive Page:** Force the Revive page button on the root page to be visible. 193 | 194 | # How to Compile 195 | 196 | - Use the Qt addon for Visual Studio to create a Visual Studio project from the .pro file. 197 | - Execute bin/windeployqt.bat which copies all Qt files necessary for execution into the output directory. 198 | 199 | # Notes: 200 | 201 | - The center marker and the play space marker are provided by the chaperone subsystem, and therefore they will have the same color and visibility settings as the chaperone bounds. 202 | 203 | - Application autostart can also be configured in the SteamVR menu (SteamVR->Settings->Applications->"Advanced Settings"). 204 | 205 | - You can modify the shutdown wait time when restarting SteamVR by opening restartvrserver.bat and changing the number behind "timeout /t" (unit is seconds). 206 | 207 | # Known Bugs 208 | 209 | - None yet. 210 | 211 | # License 212 | 213 | This software is released under GPL 3.0. 214 | -------------------------------------------------------------------------------- /advancedSettings.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2015-06-10T16:57:45 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui qml quick multimedia 8 | 9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 10 | 11 | TARGET = AdvancedSettings 12 | TEMPLATE = app 13 | 14 | 15 | SOURCES += src/main.cpp\ 16 | src/overlaycontroller.cpp \ 17 | src/tabcontrollers/AudioTabController.cpp \ 18 | src/tabcontrollers/ChaperoneTabController.cpp \ 19 | src/tabcontrollers/FixFloorTabController.cpp \ 20 | src/tabcontrollers/MoveCenterTabController.cpp \ 21 | src/tabcontrollers/SettingsTabController.cpp \ 22 | src/tabcontrollers/StatisticsTabController.cpp \ 23 | src/tabcontrollers/SteamVRTabController.cpp \ 24 | src/tabcontrollers/ReviveTabController.cpp \ 25 | src/tabcontrollers/UtilitiesTabController.cpp \ 26 | src/tabcontrollers/audiomanager/AudioManagerWindows.cpp \ 27 | src/tabcontrollers/PttController.cpp \ 28 | src/tabcontrollers/AccessibilityTabController.cpp \ 29 | src/utils/ChaperoneUtils.cpp 30 | 31 | HEADERS += src/overlaycontroller.h \ 32 | src/logging.h \ 33 | src/tabcontrollers/AudioTabController.h \ 34 | src/tabcontrollers/ChaperoneTabController.h \ 35 | src/tabcontrollers/FixFloorTabController.h \ 36 | src/tabcontrollers/MoveCenterTabController.h \ 37 | src/tabcontrollers/SettingsTabController.h \ 38 | src/tabcontrollers/StatisticsTabController.h \ 39 | src/tabcontrollers/SteamVRTabController.h \ 40 | src/tabcontrollers/ReviveTabController.h \ 41 | src/tabcontrollers/UtilitiesTabController.h \ 42 | src/tabcontrollers/AudioManager.h \ 43 | src/tabcontrollers/audiomanager/AudioManagerWindows.h \ 44 | src/tabcontrollers/PttController.h \ 45 | src/tabcontrollers/AccessibilityTabController.h \ 46 | src/utils/Matrix.h \ 47 | src/utils/ChaperoneUtils.h 48 | 49 | INCLUDEPATH += third-party/openvr/include \ 50 | third-party/easylogging++ 51 | 52 | LIBS += -Lthird-party/openvr/lib/win64 -lopenvr_api 53 | 54 | DESTDIR = bin/win64 55 | -------------------------------------------------------------------------------- /bin/logging.conf.installer: -------------------------------------------------------------------------------- 1 | * GLOBAL: 2 | FORMAT = "[%level] %datetime{%Y-%M-%d %H:%m:%s}: %msg" 3 | ENABLED = true 4 | TO_FILE = true 5 | TO_STANDARD_OUTPUT = true 6 | MAX_LOG_FILE_SIZE = 2097152 ## 2MB 7 | * DEBUG: 8 | ENABLED = false 9 | * TRACE: 10 | ENABLED = false 11 | -------------------------------------------------------------------------------- /bin/logging.conf.standalone: -------------------------------------------------------------------------------- 1 | * GLOBAL: 2 | FORMAT = "[%level] %datetime{%Y-%M-%d %H:%m:%s}: %msg" 3 | FILENAME = "AdvancedSettings.log" 4 | ENABLED = true 5 | TO_FILE = true 6 | TO_STANDARD_OUTPUT = true 7 | MAX_LOG_FILE_SIZE = 2097152 ## 2MB 8 | * DEBUG: 9 | ENABLED = false 10 | * TRACE: 11 | ENABLED = false 12 | -------------------------------------------------------------------------------- /bin/win64/logging.conf: -------------------------------------------------------------------------------- 1 | * GLOBAL: 2 | FORMAT = "[%level] %datetime{%Y-%M-%d %H:%m:%s}: %msg" 3 | FILENAME = "AdvancedSettings.log" 4 | ENABLED = true 5 | TO_FILE = true 6 | TO_STANDARD_OUTPUT = true 7 | MAX_LOG_FILE_SIZE = 2097152 ## 2MB 8 | * DEBUG: 9 | ENABLED = true 10 | * TRACE: 11 | ENABLED = false 12 | -------------------------------------------------------------------------------- /bin/win64/manifest.vrmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "source" : "builtin", 3 | "applications": [{ 4 | "app_key": "matzman666.AdvancedSettings", 5 | "launch_type": "binary", 6 | "binary_path_windows": "AdvancedSettings.exe", 7 | "is_dashboard_overlay": true, 8 | 9 | "strings": { 10 | "en_us": { 11 | "name": "Advanced Settings", 12 | "description": "OpenVR Advanced Settings Overlay" 13 | } 14 | } 15 | }] 16 | } -------------------------------------------------------------------------------- /bin/win64/openvr_api.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/bin/win64/openvr_api.dll -------------------------------------------------------------------------------- /bin/win64/qt.conf: -------------------------------------------------------------------------------- 1 | [Paths] 2 | Prefix = qtdata 3 | Qml2Imports = . 4 | Imports = . 5 | [Platforms] 6 | WindowsArguments = dpiawareness=0 7 | -------------------------------------------------------------------------------- /bin/win64/res/qml/AccessibilityPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.3 4 | import matzman666.advsettings 1.0 5 | 6 | 7 | 8 | MyStackViewPage { 9 | headerText: "Accessibility Tools" 10 | 11 | PttControllerConfigDialog { 12 | id: pttControllerConfigDialog 13 | pttControllerConfigClass: AccessibilityTabController 14 | } 15 | 16 | content: ColumnLayout { 17 | spacing: 92 18 | 19 | GroupBox { 20 | Layout.fillWidth: true 21 | 22 | label: MyText { 23 | leftPadding: 10 24 | text: "Adjust Player Height" 25 | bottomPadding: -10 26 | } 27 | background: Rectangle { 28 | color: "transparent" 29 | border.color: "#ffffff" 30 | radius: 8 31 | } 32 | 33 | ColumnLayout { 34 | anchors.fill: parent 35 | 36 | Rectangle { 37 | color: "#ffffff" 38 | height: 1 39 | Layout.fillWidth: true 40 | Layout.bottomMargin: 5 41 | } 42 | 43 | RowLayout { 44 | MyPushButton2 { 45 | Layout.preferredWidth: 40 46 | text: "-" 47 | onClicked: { 48 | accessibilityMoveYSlider.value -= 0.05 49 | } 50 | } 51 | 52 | MySlider { 53 | id: accessibilityMoveYSlider 54 | from: 0 55 | to: 1.5 56 | stepSize: 0.01 57 | value: 0.0 58 | Layout.fillWidth: true 59 | onPositionChanged: { 60 | var val = this.from + ( this.position * (this.to - this.from)) 61 | accessibilityMoveYText.text = val.toFixed(2) 62 | } 63 | onValueChanged: { 64 | AccessibilityTabController.heightOffset = this.value.toFixed(2) 65 | } 66 | } 67 | 68 | MyPushButton2 { 69 | Layout.preferredWidth: 40 70 | text: "+" 71 | onClicked: { 72 | accessibilityMoveYSlider.value += 0.05 73 | } 74 | } 75 | 76 | MyTextField { 77 | id: accessibilityMoveYText 78 | text: "0.00" 79 | keyBoardUID: 700 80 | Layout.preferredWidth: 140 81 | Layout.leftMargin: 10 82 | Layout.rightMargin: 10 83 | horizontalAlignment: Text.AlignHCenter 84 | function onInputEvent(input) { 85 | var val = parseFloat(input) 86 | if (!isNaN(val)) { 87 | if (val >= accessibilityMoveYSlider.from && val <= accessibilityMoveYSlider.to) { 88 | accessibilityMoveYSlider.value = val.toFixed(2); 89 | } else { 90 | AccessibilityTabController.setHeightOffset(val.toFixed(2), false); 91 | } 92 | } 93 | text = AccessibilityTabController.heightOffset.toFixed(2) 94 | } 95 | } 96 | } 97 | 98 | RowLayout { 99 | MyToggleButton { 100 | id: heightOffsetPttEnabledToggle 101 | Layout.preferredWidth: 260 102 | text: "Push-to-Toggle:" 103 | onClicked: { 104 | AccessibilityTabController.pttEnabled = checked 105 | } 106 | } 107 | MyToggleButton { 108 | id: heightOffsetPttLeftControllerToggle 109 | text: "Left Controller" 110 | onClicked: { 111 | AccessibilityTabController.setPttLeftControllerEnabled(checked, false) 112 | } 113 | } 114 | MyPushButton { 115 | text: "Configure" 116 | onClicked: { 117 | pttControllerConfigDialog.openPopup(0) 118 | } 119 | } 120 | Item { 121 | Layout.fillWidth: true 122 | } 123 | MyToggleButton { 124 | id: heightOffsetPttRightControllerToggle 125 | text: "Right Controller" 126 | onClicked: { 127 | AccessibilityTabController.setPttRightControllerEnabled(checked, false) 128 | } 129 | } 130 | MyPushButton { 131 | text: "Configure" 132 | onClicked: { 133 | pttControllerConfigDialog.openPopup(1) 134 | } 135 | } 136 | } 137 | } 138 | } 139 | 140 | Item { Layout.fillHeight: true; Layout.fillWidth: true} 141 | 142 | MyPushButton { 143 | id: accessibilityResetButton 144 | Layout.preferredWidth: 250 145 | text: "Reset" 146 | onClicked: { 147 | AccessibilityTabController.reset() 148 | } 149 | } 150 | 151 | Component.onCompleted: { 152 | var heightOffsetFormatted = AccessibilityTabController.heightOffset.toFixed(2) 153 | if (heightOffsetFormatted >= accessibilityMoveYSlider.from && heightOffsetFormatted <= accessibilityMoveYSlider.to) { 154 | accessibilityMoveYSlider.value = heightOffsetFormatted 155 | } 156 | accessibilityMoveYText.text = heightOffsetFormatted 157 | heightOffsetPttEnabledToggle.checked = AccessibilityTabController.pttEnabled 158 | heightOffsetPttLeftControllerToggle.checked = AccessibilityTabController.pttLeftControllerEnabled 159 | heightOffsetPttRightControllerToggle.checked = AccessibilityTabController.pttRightControllerEnabled 160 | } 161 | 162 | Connections { 163 | target: AccessibilityTabController 164 | onHeightOffsetChanged: { 165 | var heightOffsetFormatted = AccessibilityTabController.heightOffset.toFixed(2) 166 | if (heightOffsetFormatted >= accessibilityMoveYSlider.from && heightOffsetFormatted <= accessibilityMoveYSlider.to) { 167 | accessibilityMoveYSlider.value = heightOffsetFormatted 168 | } 169 | accessibilityMoveYText.text = heightOffsetFormatted 170 | } 171 | onPttEnabledChanged: { 172 | heightOffsetPttEnabledToggle.checked = AccessibilityTabController.pttEnabled 173 | } 174 | onPttActiveChanged: { 175 | 176 | } 177 | onPttLeftControllerEnabledChanged: { 178 | heightOffsetPttLeftControllerToggle.checked = AccessibilityTabController.pttLeftControllerEnabled 179 | } 180 | onPttRightControllerEnabledChanged: { 181 | heightOffsetPttRightControllerToggle.checked = AccessibilityTabController.pttRightControllerEnabled 182 | } 183 | } 184 | 185 | } 186 | 187 | } 188 | -------------------------------------------------------------------------------- /bin/win64/res/qml/FixFloorPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.3 4 | import matzman666.advsettings 1.0 5 | 6 | 7 | 8 | MyStackViewPage { 9 | headerText: "Floor Fix" 10 | 11 | content: ColumnLayout { 12 | spacing: 18 13 | 14 | Item { 15 | Layout.fillHeight: true 16 | Layout.fillWidth: true 17 | } 18 | 19 | MyText { 20 | text: "Place one controller on the ground and ensure good visibility to the base stations." 21 | wrapMode: Text.WordWrap 22 | font.pointSize: 28 23 | horizontalAlignment: Text.AlignHCenter 24 | verticalAlignment: Text.AlignVCenter 25 | Layout.fillWidth: true 26 | } 27 | 28 | Item { 29 | Layout.fillHeight: true 30 | Layout.fillWidth: true 31 | } 32 | 33 | MyText { 34 | id: statusMessageText 35 | enabled: false 36 | text: "Status Text" 37 | horizontalAlignment: Text.AlignHCenter 38 | verticalAlignment: Text.AlignVCenter 39 | Layout.fillWidth: true 40 | } 41 | 42 | Item { 43 | Layout.fillHeight: true 44 | Layout.fillWidth: true 45 | } 46 | 47 | MyPushButton { 48 | id: fixButton 49 | Layout.fillWidth: true 50 | text: "Fix Floor" 51 | Layout.preferredHeight: 100 52 | onClicked: { 53 | FixFloorTabController.fixFloorClicked() 54 | } 55 | } 56 | 57 | MyPushButton { 58 | id: undoFixButton 59 | enabled: false 60 | Layout.fillWidth: true 61 | text: "Undo Fix" 62 | onClicked: { 63 | FixFloorTabController.undoFixFloorClicked() 64 | } 65 | } 66 | 67 | Item { 68 | Layout.preferredHeight: 32 69 | } 70 | 71 | Component.onCompleted: { 72 | statusMessageText.text = "" 73 | undoFixButton.enabled = FixFloorTabController.canUndo 74 | fixButton.enabled = true 75 | } 76 | 77 | Timer { 78 | id: statusMessageTimer 79 | repeat: false 80 | onTriggered: { 81 | statusMessageText.text = "" 82 | } 83 | } 84 | 85 | Connections { 86 | target: FixFloorTabController 87 | onStatusMessageSignal: { 88 | if (statusMessageTimer.running) { 89 | statusMessageTimer.stop() 90 | } 91 | statusMessageText.text = FixFloorTabController.currentStatusMessage() 92 | statusMessageTimer.interval = FixFloorTabController.currentStatusMessageTimeout() * 1000 93 | statusMessageTimer.start() 94 | } 95 | onMeasureStartSignal: { 96 | fixButton.enabled = false 97 | undoFixButton.enabled = false 98 | } 99 | onMeasureEndSignal: { 100 | fixButton.enabled = true 101 | undoFixButton.enabled = FixFloorTabController.canUndo 102 | } 103 | onCanUndoChanged: { 104 | undoFixButton.enabled = FixFloorTabController.canUndo 105 | } 106 | } 107 | 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /bin/win64/res/qml/MyComboBox.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.0 3 | import "." // QTBUG-34418, singletons require explicit import to load qmldir file 4 | 5 | 6 | ComboBox { 7 | id: myComboBox 8 | hoverEnabled: true 9 | 10 | background: Rectangle { 11 | color: parent.pressed ? "#406288" : (parent.activeFocus ? "#365473" : "#2c435d") 12 | } 13 | 14 | contentItem: MyText { 15 | leftPadding: 0 16 | rightPadding: parent.indicator.width + parent.spacing 17 | text: parent.displayText 18 | horizontalAlignment: Text.AlignLeft 19 | verticalAlignment: Text.AlignVCenter 20 | elide: Text.ElideRight 21 | } 22 | 23 | delegate: ItemDelegate { 24 | width: myComboBox.width 25 | text: modelData 26 | hoverEnabled: true 27 | contentItem: MyText { 28 | horizontalAlignment: Text.AlignLeft 29 | verticalAlignment: Text.AlignVCenter 30 | text: parent.text 31 | color: parent.enabled ? "#ffffff" : "#909090" 32 | } 33 | background: Rectangle { 34 | color: parent.pressed ? "#406288" : (parent.hovered ? "#365473" : "#2c435d") 35 | } 36 | } 37 | 38 | indicator: Canvas { 39 | x: parent.width - width - parent.rightPadding 40 | y: parent.topPadding + (parent.availableHeight - height) / 2 41 | width: 13 42 | height: 7 43 | contextType: "2d" 44 | 45 | onPaint: { 46 | if (!context) { 47 | getContext("2d") 48 | } 49 | context.reset(); 50 | context.lineWidth = 2 51 | context.moveTo(1, 1); 52 | context.lineTo(Math.ceil(width / 2), height - 1); 53 | context.lineTo(width - 1, 1); 54 | context.strokeStyle = "#ffffff" 55 | context.stroke() 56 | } 57 | } 58 | 59 | onHoveredChanged: { 60 | if (hovered) { 61 | forceActiveFocus() 62 | } 63 | } 64 | 65 | onActivated: { 66 | if (activeFocus) { 67 | MyResources.playActivationSound() 68 | } 69 | } 70 | 71 | Component.onCompleted: { 72 | popup.background.color = "#2c435d" 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /bin/win64/res/qml/MyDialogOkCancelPopup.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.3 4 | 5 | Popup { 6 | id: myDialogPopup 7 | 8 | implicitHeight: parent.height 9 | implicitWidth: parent.width 10 | 11 | property string dialogTitle: "" 12 | property string dialogText: "" 13 | property int dialogWidth: 600 14 | property int dialogHeight: 300 15 | 16 | property Item dialogContentItem: MyText { 17 | text: dialogText 18 | horizontalAlignment: Text.AlignHCenter 19 | verticalAlignment: Text.AlignVCenter 20 | Layout.fillWidth: true 21 | } 22 | 23 | property bool okClicked: false 24 | 25 | closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent 26 | 27 | background: Rectangle { 28 | color: "black" 29 | opacity: 0.8 30 | } 31 | 32 | contentItem: Item { 33 | Rectangle { 34 | implicitWidth: dialogWidth 35 | implicitHeight: dialogHeight 36 | anchors.centerIn: parent 37 | radius: 24 38 | color: "#1b2939" 39 | border.color: "#cccccc" 40 | border.width: 2 41 | ColumnLayout { 42 | anchors.fill: parent 43 | anchors.margins: 12 44 | MyText { 45 | Layout.leftMargin: 16 46 | Layout.rightMargin: 16 47 | text: dialogTitle 48 | } 49 | Rectangle { 50 | color: "#cccccc" 51 | height: 1 52 | Layout.fillWidth: true 53 | } 54 | Item { 55 | Layout.fillHeight: true 56 | Layout.fillWidth: true 57 | } 58 | ColumnLayout { 59 | id: dialogContent 60 | } 61 | Item { 62 | Layout.fillHeight: true 63 | Layout.fillWidth: true 64 | } 65 | RowLayout { 66 | Layout.fillWidth: true 67 | Layout.leftMargin: 24 68 | Layout.rightMargin: 24 69 | Layout.bottomMargin: 12 70 | MyPushButton { 71 | implicitWidth: 200 72 | text: "Ok" 73 | onClicked: { 74 | okClicked = true 75 | myDialogPopup.close() 76 | } 77 | } 78 | Item { 79 | Layout.fillWidth: true 80 | } 81 | MyPushButton { 82 | implicitWidth: 200 83 | text: "Cancel" 84 | onClicked: { 85 | okClicked = false 86 | myDialogPopup.close() 87 | } 88 | } 89 | } 90 | } 91 | } 92 | } 93 | 94 | Component.onCompleted: { 95 | dialogContentItem.parent = dialogContent 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /bin/win64/res/qml/MyDialogOkPopup.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.3 4 | 5 | Popup { 6 | id: myDialogPopup 7 | 8 | implicitHeight: parent.height 9 | implicitWidth: parent.width 10 | 11 | property string dialogTitle: "" 12 | property string dialogText: "" 13 | property int dialogWidth: 600 14 | property int dialogHeight: 300 15 | 16 | property Item dialogContentItem: MyText { 17 | text: dialogText 18 | horizontalAlignment: Text.AlignHCenter 19 | verticalAlignment: Text.AlignVCenter 20 | Layout.fillWidth: true 21 | } 22 | 23 | property bool okClicked: false 24 | 25 | closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent 26 | 27 | background: Rectangle { 28 | color: "black" 29 | opacity: 0.8 30 | } 31 | 32 | contentItem: Item { 33 | Rectangle { 34 | implicitWidth: dialogWidth 35 | implicitHeight: dialogHeight 36 | anchors.centerIn: parent 37 | radius: 24 38 | color: "#1b2939" 39 | border.color: "#cccccc" 40 | border.width: 2 41 | ColumnLayout { 42 | anchors.fill: parent 43 | anchors.margins: 12 44 | MyText { 45 | Layout.leftMargin: 16 46 | Layout.rightMargin: 16 47 | text: dialogTitle 48 | } 49 | Rectangle { 50 | color: "#cccccc" 51 | height: 1 52 | Layout.fillWidth: true 53 | } 54 | Item { 55 | Layout.fillHeight: true 56 | Layout.fillWidth: true 57 | } 58 | ColumnLayout { 59 | id: dialogContent 60 | } 61 | Item { 62 | Layout.fillHeight: true 63 | Layout.fillWidth: true 64 | } 65 | RowLayout { 66 | Layout.fillWidth: true 67 | Layout.leftMargin: 24 68 | Layout.rightMargin: 24 69 | Layout.bottomMargin: 12 70 | Item { 71 | Layout.fillWidth: true 72 | } 73 | MyPushButton { 74 | implicitWidth: 200 75 | text: "Ok" 76 | onClicked: { 77 | okClicked = true 78 | myDialogPopup.close() 79 | } 80 | } 81 | Item { 82 | Layout.fillWidth: true 83 | } 84 | } 85 | } 86 | } 87 | } 88 | 89 | Component.onCompleted: { 90 | dialogContentItem.parent = dialogContent 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /bin/win64/res/qml/MyPushButton.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.0 3 | import "." // QTBUG-34418, singletons require explicit import to load qmldir file 4 | 5 | Button { 6 | property bool activationSoundEnabled: true 7 | hoverEnabled: true 8 | contentItem: MyText { 9 | horizontalAlignment: Text.AlignHCenter 10 | verticalAlignment: Text.AlignVCenter 11 | text: parent.text 12 | color: parent.enabled ? "#ffffff" : "#909090" 13 | } 14 | background: Rectangle { 15 | color: parent.down ? "#406288" : (parent.activeFocus ? "#365473" : "#2c435d") 16 | } 17 | 18 | onHoveredChanged: { 19 | if (hovered) { 20 | forceActiveFocus() 21 | } else { 22 | focus = false 23 | } 24 | } 25 | 26 | onClicked: { 27 | if (activationSoundEnabled) { 28 | MyResources.playActivationSound() 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /bin/win64/res/qml/MyPushButton2.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.0 3 | import "." // QTBUG-34418, singletons require explicit import to load qmldir file 4 | 5 | Button { 6 | hoverEnabled: true 7 | contentItem: MyText { 8 | horizontalAlignment: Text.AlignHCenter 9 | verticalAlignment: Text.AlignVCenter 10 | text: parent.text 11 | color: parent.enabled ? "#ffffff" : "#909090" 12 | } 13 | background: Rectangle { 14 | color: parent.down ? "#406288" : (parent.activeFocus ? "#365473" : "transparent") 15 | border.color: parent.enabled ? "#ffffff" : "#909090" 16 | radius: 8 17 | } 18 | onHoveredChanged: { 19 | if (hovered) { 20 | forceActiveFocus() 21 | } else { 22 | focus = false 23 | } 24 | } 25 | 26 | onClicked: { 27 | MyResources.playActivationSound() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /bin/win64/res/qml/MyResources.qml: -------------------------------------------------------------------------------- 1 | pragma Singleton 2 | import QtQuick 2.7 3 | import QtMultimedia 5.6 4 | import matzman666.advsettings 1.0 5 | 6 | QtObject { 7 | function playActivationSound() { 8 | OverlayController.playActivationSound() 9 | } 10 | function playFocusChangedSound() { 11 | OverlayController.playFocusChangedSound() 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /bin/win64/res/qml/MySlider.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.0 3 | import "." // QTBUG-34418, singletons require explicit import to load qmldir file 4 | 5 | 6 | 7 | Slider { 8 | snapMode: Slider.SnapAlways 9 | wheelEnabled: true 10 | hoverEnabled: true 11 | 12 | background: Rectangle { 13 | x: parent.leftPadding 14 | y: parent.topPadding + parent.availableHeight / 2 - height / 2 15 | width: parent.availableWidth 16 | height: parent.availableHeight 17 | radius: 2 18 | color: parent.activeFocus ? "#2c435d" : "#1b2939" 19 | Rectangle { 20 | y: parent.height / 2 - height / 2 21 | implicitHeight: 4 22 | width: parent.width 23 | height: implicitHeight 24 | radius: 2 25 | color: "#bdbebf" 26 | } 27 | } 28 | 29 | handle: Rectangle { 30 | x: parent.leftPadding + parent.visualPosition * (parent.availableWidth - width) 31 | y: parent.topPadding + parent.availableHeight / 2 - height / 2 32 | implicitWidth: 20 33 | implicitHeight: 40 34 | radius: 4 35 | color: parent.pressed ? "#ffffff" : "#eeeeee" 36 | border.color: "#bdbebf" 37 | } 38 | 39 | onHoveredChanged: { 40 | if (hovered) { 41 | forceActiveFocus() 42 | } else { 43 | focus = false 44 | } 45 | } 46 | 47 | onValueChanged: { 48 | if (activeFocus) { 49 | MyResources.playActivationSound() 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /bin/win64/res/qml/MyStackViewPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.2 4 | import "." // QTBUG-34418, singletons require explicit import to load qmldir file 5 | 6 | Rectangle { 7 | color: "#1b2939" 8 | width: 1200 9 | height: 800 10 | 11 | property StackView stackView 12 | 13 | property string headerText: "Header Title" 14 | 15 | property bool headerShowBackButton: true 16 | 17 | property Item header: ColumnLayout { 18 | RowLayout { 19 | Button { 20 | id: headerBackButton 21 | Layout.preferredHeight: 50 22 | Layout.preferredWidth: 50 23 | hoverEnabled: true 24 | enabled: headerShowBackButton 25 | opacity: headerShowBackButton ? 1.0 : 0.0 26 | contentItem: Image { 27 | source: "backarrow.svg" 28 | sourceSize.width: 50 29 | sourceSize.height: 50 30 | anchors.fill: parent 31 | } 32 | background: Rectangle { 33 | opacity: parent.down ? 1.0 : (parent.activeFocus ? 0.5 : 0.0) 34 | color: "#406288" 35 | radius: 4 36 | anchors.fill: parent 37 | } 38 | onHoveredChanged: { 39 | if (hovered) { 40 | forceActiveFocus() 41 | } else { 42 | focus = false 43 | } 44 | } 45 | onClicked: { 46 | MyResources.playFocusChangedSound() 47 | stackView.pop() 48 | } 49 | } 50 | MyText { 51 | id: headerTitle 52 | text: headerText 53 | font.pointSize: 30 54 | anchors.verticalCenter: headerBackButton.verticalCenter 55 | Layout.leftMargin: 32 56 | } 57 | } 58 | 59 | Rectangle { 60 | color: "#cccccc" 61 | height: 1 62 | Layout.topMargin: 10 63 | Layout.fillWidth: true 64 | } 65 | } 66 | 67 | property Item content: Frame { 68 | MyText { 69 | text: "Content" 70 | } 71 | } 72 | 73 | ColumnLayout { 74 | id: mainLayout 75 | spacing: 12 76 | anchors.fill: parent 77 | } 78 | 79 | Component.onCompleted: { 80 | header.parent = mainLayout 81 | header.Layout.leftMargin = 40 82 | header.Layout.topMargin = 30 83 | header.Layout.rightMargin = 40 84 | content.parent = mainLayout 85 | content.Layout.fillHeight = true 86 | content.Layout.fillWidth = true 87 | content.Layout.topMargin = 10 88 | content.Layout.leftMargin = 40 89 | content.Layout.rightMargin = 40 90 | content.Layout.bottomMargin = 40 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /bin/win64/res/qml/MyText.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.0 3 | 4 | 5 | Text { 6 | color: "#ffffff" 7 | font.pointSize: 20 8 | } 9 | -------------------------------------------------------------------------------- /bin/win64/res/qml/MyTextField.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.0 3 | import matzman666.advsettings 1.0 4 | 5 | TextField { 6 | property int keyBoardUID: 0 7 | property string savedText: "" 8 | id: myTextField 9 | color: "#cccccc" 10 | text: "" 11 | font.pointSize: 20 12 | background: Button { 13 | hoverEnabled: true 14 | background: Rectangle { 15 | color: parent.hovered ? "#2c435d" : "#1b2939" 16 | border.color: "#cccccc" 17 | border.width: 2 18 | } 19 | onClicked: { 20 | myTextField.forceActiveFocus() 21 | } 22 | } 23 | onActiveFocusChanged: { 24 | if (activeFocus) { 25 | if (!OverlayController.desktopMode) { 26 | OverlayController.showKeyboard(text, keyBoardUID) 27 | } else { 28 | savedText = text 29 | } 30 | } 31 | } 32 | onEditingFinished: { 33 | if (OverlayController.desktopMode && savedText !== text) { 34 | myTextField.onInputEvent(text) 35 | } 36 | } 37 | function onInputEvent(input) { 38 | text = input 39 | } 40 | Connections { 41 | target: OverlayController 42 | onKeyBoardInputSignal: { 43 | if (userValue == keyBoardUID) { 44 | if (myTextField.text !== input) { 45 | myTextField.onInputEvent(input) 46 | } 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /bin/win64/res/qml/MyToggleButton.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.0 3 | import "." // QTBUG-34418, singletons require explicit import to load qmldir file 4 | 5 | 6 | CheckBox { 7 | hoverEnabled: true 8 | spacing: 12 9 | 10 | indicator: Rectangle { 11 | implicitWidth: 28 12 | implicitHeight: 28 13 | x: parent.leftPadding 14 | y: parent.height / 2 - height / 2 15 | color: parent.enabled ? (parent.down ? "#e0e0e0" : "#ffffff") : "#a0a0a0" 16 | border.width: 0 17 | Image { 18 | width: 38 19 | height: 38 20 | x: (parent.width - width) / 2 21 | y: (parent.height - height) / 2 22 | source: "image://default/check/#2c435d" 23 | sourceSize.width: width 24 | sourceSize.height: height 25 | visible: parent.parent.checked 26 | } 27 | } 28 | 29 | contentItem: MyText { 30 | text: parent.text 31 | horizontalAlignment: Text.AlignLeft 32 | verticalAlignment: Text.AlignVCenter 33 | leftPadding: parent.indicator.width + parent.spacing 34 | color: parent.enabled ? "#ffffff" : "#909090" 35 | } 36 | 37 | background: Rectangle { 38 | color: "#2c435d" 39 | opacity: parent.activeFocus ? 1.0 : 0.0 40 | } 41 | 42 | onHoveredChanged: { 43 | if (hovered) { 44 | forceActiveFocus() 45 | } else { 46 | focus = false 47 | } 48 | } 49 | 50 | onClicked: { 51 | MyResources.playActivationSound() 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /bin/win64/res/qml/PlayspacePage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.3 4 | import matzman666.advsettings 1.0 5 | 6 | 7 | 8 | MyStackViewPage { 9 | headerText: "Play Space Settings" 10 | 11 | content: ColumnLayout { 12 | spacing: 18 13 | 14 | RowLayout { 15 | MyText { 16 | text: "Tracking Universe:" 17 | Layout.preferredWidth: 230 18 | } 19 | MyText { 20 | id: playspaceModeText 21 | font.bold: true 22 | text: "Standing" 23 | } 24 | } 25 | 26 | GroupBox { 27 | Layout.fillWidth: true 28 | 29 | label: MyText { 30 | leftPadding: 10 31 | text: "Move Play Space" 32 | bottomPadding: -10 33 | } 34 | background: Rectangle { 35 | color: "transparent" 36 | border.color: "#ffffff" 37 | radius: 8 38 | } 39 | ColumnLayout { 40 | anchors.fill: parent 41 | 42 | Rectangle { 43 | color: "#ffffff" 44 | height: 1 45 | Layout.fillWidth: true 46 | Layout.bottomMargin: 5 47 | } 48 | 49 | GridLayout { 50 | columns: 4 51 | 52 | MyText { 53 | text: "X-Axis (Left/Right):" 54 | Layout.preferredWidth: 500 55 | } 56 | 57 | MyPushButton2 { 58 | id: playSpaceMoveXMinusButton 59 | Layout.preferredWidth: 40 60 | text: "-" 61 | onClicked: { 62 | MoveCenterTabController.modOffsetX(-0.5) 63 | } 64 | } 65 | 66 | MyTextField { 67 | id: playSpaceMoveXText 68 | text: "0.00" 69 | keyBoardUID: 101 70 | Layout.preferredWidth: 140 71 | Layout.leftMargin: 10 72 | Layout.rightMargin: 10 73 | horizontalAlignment: Text.AlignHCenter 74 | function onInputEvent(input) { 75 | var val = parseFloat(input) 76 | if (!isNaN(val)) { 77 | MoveCenterTabController.offsetX = val.toFixed(2) 78 | text = MoveCenterTabController.offsetX.toFixed(2) 79 | } else { 80 | text = MoveCenterTabController.offsetX.toFixed(2) 81 | } 82 | } 83 | } 84 | 85 | MyPushButton2 { 86 | id: playSpaceMoveXPlusButton 87 | Layout.preferredWidth: 40 88 | text: "+" 89 | onClicked: { 90 | MoveCenterTabController.modOffsetX(0.5) 91 | } 92 | } 93 | 94 | MyText { 95 | text: "Y-Axis (Down/Up):" 96 | Layout.preferredWidth: 380 97 | } 98 | 99 | MyPushButton2 { 100 | Layout.preferredWidth: 40 101 | text: "-" 102 | onClicked: { 103 | MoveCenterTabController.modOffsetY(-0.5) 104 | } 105 | } 106 | 107 | MyTextField { 108 | id: playSpaceMoveYText 109 | text: "0.00" 110 | keyBoardUID: 102 111 | Layout.preferredWidth: 140 112 | Layout.leftMargin: 10 113 | Layout.rightMargin: 10 114 | horizontalAlignment: Text.AlignHCenter 115 | function onInputEvent(input) { 116 | var val = parseFloat(input) 117 | if (!isNaN(val)) { 118 | MoveCenterTabController.offsetY = val.toFixed(2) 119 | text = MoveCenterTabController.offsetY.toFixed(2) 120 | } else { 121 | text = MoveCenterTabController.offsetY.toFixed(2) 122 | } 123 | } 124 | } 125 | 126 | MyPushButton2 { 127 | Layout.preferredWidth: 40 128 | text: "+" 129 | onClicked: { 130 | MoveCenterTabController.modOffsetY(0.5) 131 | } 132 | } 133 | 134 | MyText { 135 | text: "Z-Axis (Forth/Back):" 136 | Layout.preferredWidth: 380 137 | } 138 | 139 | MyPushButton2 { 140 | Layout.preferredWidth: 40 141 | text: "-" 142 | onClicked: { 143 | MoveCenterTabController.modOffsetZ(-0.5) 144 | } 145 | } 146 | 147 | MyTextField { 148 | id: playSpaceMoveZText 149 | text: "0.00" 150 | keyBoardUID: 103 151 | Layout.preferredWidth: 140 152 | Layout.leftMargin: 10 153 | Layout.rightMargin: 10 154 | horizontalAlignment: Text.AlignHCenter 155 | function onInputEvent(input) { 156 | var val = parseFloat(input) 157 | if (!isNaN(val)) { 158 | MoveCenterTabController.offsetZ = val.toFixed(2) 159 | text = MoveCenterTabController.offsetZ.toFixed(2) 160 | } else { 161 | text = MoveCenterTabController.offsetZ.toFixed(2) 162 | } 163 | } 164 | } 165 | 166 | MyPushButton2 { 167 | Layout.preferredWidth: 40 168 | text: "+" 169 | onClicked: { 170 | MoveCenterTabController.modOffsetZ(0.5) 171 | } 172 | } 173 | } 174 | } 175 | } 176 | 177 | GroupBox { 178 | Layout.fillWidth: true 179 | 180 | label: MyText { 181 | leftPadding: 10 182 | text: "Rotate Play Space" 183 | bottomPadding: -10 184 | } 185 | background: Rectangle { 186 | color: "transparent" 187 | border.color: "#ffffff" 188 | radius: 8 189 | } 190 | ColumnLayout { 191 | anchors.fill: parent 192 | 193 | Rectangle { 194 | color: "#ffffff" 195 | height: 1 196 | Layout.fillWidth: true 197 | Layout.bottomMargin: 5 198 | } 199 | 200 | ColumnLayout { 201 | RowLayout { 202 | MyPushButton2 { 203 | id: playSpaceRotationMinusButton 204 | Layout.preferredWidth: 40 205 | text: "-" 206 | onClicked: { 207 | var val = MoveCenterTabController.rotation - 45 208 | if (val < -180) { 209 | val = val + 360; 210 | } 211 | MoveCenterTabController.rotation = val 212 | } 213 | } 214 | 215 | MySlider { 216 | id: playspaceRotationSlider 217 | from: -180 218 | to: 180 219 | stepSize: 1 220 | value: 0 221 | Layout.fillWidth: true 222 | onPositionChanged: { 223 | var val = this.from + ( this.position * (this.to - this.from)) 224 | playspaceRotationText.text = Math.round(val) + "°" 225 | } 226 | onValueChanged: { 227 | MoveCenterTabController.rotation = playspaceRotationSlider.value 228 | playspaceRotationText.text = Math.round(playspaceRotationSlider.value) + "°" 229 | } 230 | } 231 | 232 | MyPushButton2 { 233 | id: playSpaceRotationPlusButton 234 | Layout.preferredWidth: 40 235 | text: "+" 236 | onClicked: { 237 | var val = MoveCenterTabController.rotation + 45 238 | if (val > 180) { 239 | val = val -360; 240 | } 241 | MoveCenterTabController.rotation = val 242 | } 243 | } 244 | 245 | MyTextField { 246 | id: playspaceRotationText 247 | text: "0°" 248 | keyBoardUID: 104 249 | Layout.preferredWidth: 100 250 | Layout.leftMargin: 10 251 | horizontalAlignment: Text.AlignHCenter 252 | function onInputEvent(input) { 253 | var val = parseInt(input) 254 | if (!isNaN(val)) { 255 | val = val % 180 256 | MoveCenterTabController.rotation = val 257 | text = MoveCenterTabController.rotation + "°" 258 | } else { 259 | text = MoveCenterTabController.rotation + "°" 260 | } 261 | } 262 | } 263 | } 264 | } 265 | } 266 | } 267 | 268 | MyToggleButton { 269 | id: playspaceAdjustChaperoneToggle 270 | text: "Adjust Chaperone" 271 | onCheckedChanged: { 272 | MoveCenterTabController.adjustChaperone = this.checked 273 | } 274 | } 275 | 276 | Item { Layout.fillHeight: true; Layout.fillWidth: true} 277 | 278 | MyPushButton { 279 | id: playspaceResetButton 280 | Layout.preferredWidth: 250 281 | text: "Reset" 282 | onClicked: { 283 | MoveCenterTabController.reset() 284 | } 285 | } 286 | 287 | Component.onCompleted: { 288 | playspaceAdjustChaperoneToggle.checked = MoveCenterTabController.adjustChaperone 289 | playSpaceMoveXText.text = MoveCenterTabController.offsetX.toFixed(2) 290 | playSpaceMoveYText.text = MoveCenterTabController.offsetY.toFixed(2) 291 | playSpaceMoveZText.text = MoveCenterTabController.offsetZ.toFixed(2) 292 | playspaceRotationSlider.value = MoveCenterTabController.rotation 293 | if (MoveCenterTabController.trackingUniverse === 0) { 294 | playspaceModeText.text = "Sitting" 295 | playSpaceRotationPlusButton.enabled = false 296 | playSpaceRotationMinusButton.enabled = false 297 | playspaceRotationSlider.enabled = false 298 | playspaceRotationText.text = "-" 299 | } else if (MoveCenterTabController.trackingUniverse === 1) { 300 | playspaceModeText.text = "Standing" 301 | playSpaceRotationPlusButton.enabled = true 302 | playSpaceRotationMinusButton.enabled = true 303 | playspaceRotationSlider.enabled = true 304 | playspaceRotationText.text = "0°" 305 | } else { 306 | playspaceModeText.text = "Unknown(" + MoveCenterTabController.trackingUniverse + ")" 307 | } 308 | } 309 | 310 | Connections { 311 | target: MoveCenterTabController 312 | onOffsetXChanged: { 313 | playSpaceMoveXText.text = MoveCenterTabController.offsetX.toFixed(2) 314 | } 315 | onOffsetYChanged: { 316 | playSpaceMoveYText.text = MoveCenterTabController.offsetY.toFixed(2) 317 | } 318 | onOffsetZChanged: { 319 | playSpaceMoveZText.text = MoveCenterTabController.offsetZ.toFixed(2) 320 | } 321 | onRotationChanged: { 322 | playspaceRotationSlider.value = MoveCenterTabController.rotation 323 | } 324 | onAdjustChaperoneChanged: { 325 | playspaceAdjustChaperoneToggle = value 326 | } 327 | onTrackingUniverseChanged: { 328 | if (MoveCenterTabController.trackingUniverse === 0) { 329 | playspaceModeText.text = "Sitting" 330 | playSpaceRotationPlusButton.enabled = false 331 | playSpaceRotationMinusButton.enabled = false 332 | playspaceRotationSlider.enabled = false 333 | playspaceRotationText.text = "-" 334 | } else if (MoveCenterTabController.trackingUniverse === 1) { 335 | playspaceModeText.text = "Standing" 336 | playSpaceRotationPlusButton.enabled = true 337 | playSpaceRotationMinusButton.enabled = true 338 | playspaceRotationSlider.enabled = true 339 | playspaceRotationText.text = "0°" 340 | } else { 341 | playspaceModeText.text = "Unknown(" + MoveCenterTabController.trackingUniverse + ")" 342 | } 343 | } 344 | } 345 | 346 | } 347 | 348 | } 349 | -------------------------------------------------------------------------------- /bin/win64/res/qml/PttControllerConfigDialog.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.3 4 | import matzman666.advsettings 1.0 5 | 6 | MyDialogOkCancelPopup { 7 | id: pttControllerConfigDialog 8 | property var pttControllerConfigClass 9 | property int controllerIndex: -1 10 | dialogTitle: "Controller Configuration" 11 | dialogWidth: 600 12 | dialogHeight: 620 13 | dialogContentItem: ColumnLayout { 14 | MyText { 15 | text: "Buttons" 16 | } 17 | Rectangle { 18 | color: "#cccccc" 19 | height: 1 20 | Layout.fillWidth: true 21 | } 22 | MyToggleButton { 23 | id: pttControllerConfigGripButtonToggle 24 | text: "Grip" 25 | } 26 | MyToggleButton { 27 | id: pttControllerConfigMenuButtonToggle 28 | text: "Menu" 29 | } 30 | MyToggleButton { 31 | id: pttControllerConfigTriggerButtonToggle 32 | text: "Trigger" 33 | } 34 | 35 | MyText { 36 | Layout.topMargin: 32 37 | text: "Touchpad" 38 | } 39 | Rectangle { 40 | color: "#cccccc" 41 | height: 1 42 | Layout.fillWidth: true 43 | } 44 | RowLayout { 45 | spacing: 64 46 | MyToggleButton { 47 | id: pttControllerConfigPadLeftToggle 48 | text: "Left" 49 | } 50 | MyToggleButton { 51 | id: pttControllerConfigPadRightToggle 52 | text: "Right" 53 | } 54 | } 55 | RowLayout { 56 | spacing: 64 57 | MyToggleButton { 58 | id: pttControllerConfigPadTopToggle 59 | text: "Top" 60 | } 61 | MyToggleButton { 62 | id: pttControllerConfigPadBottomToggle 63 | text: "Bottom" 64 | } 65 | } 66 | RowLayout { 67 | MyText { 68 | text: "Mode:" 69 | } 70 | MyComboBox { 71 | id: pttControllerConfigPadModeCombo 72 | Layout.preferredWidth: 250 73 | model: ["Disabled", "Touched", "Pressed"] 74 | } 75 | } 76 | } 77 | onClosed: { 78 | if (okClicked) { 79 | var buttons = [] 80 | if (pttControllerConfigGripButtonToggle.checked) { 81 | buttons.push(2) 82 | } 83 | if (pttControllerConfigMenuButtonToggle.checked) { 84 | buttons.push(1) 85 | } 86 | var triggerMode = 0 87 | if (pttControllerConfigTriggerButtonToggle.checked) { 88 | triggerMode = 1 89 | } 90 | var padAreas = 0 91 | if (pttControllerConfigPadLeftToggle.checked) { 92 | padAreas |= (1 << 0) 93 | } 94 | if (pttControllerConfigPadTopToggle.checked) { 95 | padAreas |= (1 << 1) 96 | } 97 | if (pttControllerConfigPadRightToggle.checked) { 98 | padAreas |= (1 << 2) 99 | } 100 | if (pttControllerConfigPadBottomToggle.checked) { 101 | padAreas |= (1 << 3) 102 | } 103 | pttControllerConfigClass.setPttControllerConfig(controllerIndex, buttons, triggerMode, pttControllerConfigPadModeCombo.currentIndex, padAreas); 104 | } 105 | } 106 | function openPopup(controller) { 107 | if (controller === 0) { 108 | dialogTitle = "Left Controller Configuration" 109 | controllerIndex = 0 110 | } else { 111 | dialogTitle = "Right Controller Configuration" 112 | controllerIndex = 1 113 | } 114 | pttControllerConfigGripButtonToggle.checked = false 115 | pttControllerConfigMenuButtonToggle.checked = false 116 | pttControllerConfigTriggerButtonToggle.checked = false 117 | pttControllerConfigPadLeftToggle.checked = false 118 | pttControllerConfigPadTopToggle.checked = false 119 | pttControllerConfigPadRightToggle.checked = false 120 | pttControllerConfigPadBottomToggle.checked = false 121 | pttControllerConfigPadModeCombo.currentIndex = pttControllerConfigClass.pttTouchpadMode(controllerIndex) 122 | var buttons = pttControllerConfigClass.pttDigitalButtons(controllerIndex) 123 | for (var i = 0; i < buttons.length; i++) { 124 | if (buttons[i] == 1) { 125 | pttControllerConfigMenuButtonToggle.checked = true 126 | } else if (buttons[i] == 2) { 127 | pttControllerConfigGripButtonToggle.checked = true 128 | } 129 | } 130 | if (pttControllerConfigClass.pttTriggerMode(controllerIndex) > 0) { 131 | pttControllerConfigTriggerButtonToggle.checked = true 132 | } 133 | var padAreas = pttControllerConfigClass.pttTouchpadArea(controllerIndex) 134 | if (padAreas & (1 << 0)) { 135 | pttControllerConfigPadLeftToggle.checked = true 136 | } 137 | if (padAreas & (1 << 1)) { 138 | pttControllerConfigPadTopToggle.checked = true 139 | } 140 | if (padAreas & (1 << 2)) { 141 | pttControllerConfigPadRightToggle.checked = true 142 | } 143 | if (padAreas & (1 << 3)) { 144 | pttControllerConfigPadBottomToggle.checked = true 145 | } 146 | open() 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /bin/win64/res/qml/SettingsPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.3 4 | import matzman666.advsettings 1.0 5 | 6 | 7 | MyStackViewPage { 8 | headerText: "Application Settings" 9 | 10 | content: ColumnLayout { 11 | spacing: 18 12 | 13 | MyToggleButton { 14 | id: settingsAutoStartToggle 15 | text: "Autostart" 16 | onCheckedChanged: { 17 | SettingsTabController.setAutoStartEnabled(checked, false) 18 | } 19 | } 20 | 21 | MyToggleButton { 22 | id: forceReviveToggle 23 | text: "Force Revive Page" 24 | onCheckedChanged: { 25 | SettingsTabController.setForceRevivePage(checked, true) 26 | } 27 | } 28 | 29 | Item { 30 | Layout.fillHeight: true 31 | } 32 | 33 | Component.onCompleted: { 34 | settingsAutoStartToggle.checked = SettingsTabController.autoStartEnabled 35 | forceReviveToggle.checked = SettingsTabController.forceRevivePage 36 | } 37 | 38 | Connections { 39 | target: SettingsTabController 40 | onAutoStartEnabledChanged: { 41 | settingsAutoStartToggle.checked = SettingsTabController.autoStartEnabled 42 | } 43 | onForceRevivePageChanged: { 44 | forceReviveToggle.checked = SettingsTabController.forceRevivePage 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /bin/win64/res/qml/StatisticsPage.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.3 4 | import matzman666.advsettings 1.0 5 | 6 | 7 | 8 | MyStackViewPage { 9 | headerText: "Statistics" 10 | 11 | content: ColumnLayout { 12 | spacing: 18 13 | 14 | GridLayout { 15 | columns: 3 16 | 17 | MyText { 18 | text: "HMD Distance Moved:" 19 | } 20 | 21 | MyText { 22 | id: statsHmdMovedText 23 | text: "-00.0" 24 | Layout.fillWidth: true 25 | horizontalAlignment: Text.AlignRight 26 | Layout.rightMargin: 10 27 | } 28 | 29 | MyPushButton { 30 | text: "Reset" 31 | onClicked: { 32 | StatisticsTabController.statsDistanceResetClicked() 33 | } 34 | } 35 | 36 | MyText { 37 | text: "HMD Rotations:" 38 | } 39 | 40 | MyText { 41 | id: statsHmdRotationText 42 | text: "0.0 CCW" 43 | Layout.fillWidth: true 44 | horizontalAlignment: Text.AlignRight 45 | Layout.rightMargin: 10 46 | } 47 | 48 | MyPushButton { 49 | text: "Reset" 50 | onClicked: { 51 | StatisticsTabController.statsRotationResetClicked() 52 | } 53 | } 54 | 55 | MyText { 56 | text: "Left Controller Max Speed:" 57 | } 58 | 59 | MyText { 60 | id: statsLeftControllerSpeedText 61 | text: "99.9 m/s" 62 | Layout.fillWidth: true 63 | horizontalAlignment: Text.AlignRight 64 | Layout.rightMargin: 10 65 | } 66 | 67 | MyPushButton { 68 | text: "Reset" 69 | onClicked: { 70 | StatisticsTabController.statsLeftControllerSpeedResetClicked() 71 | } 72 | } 73 | 74 | MyText { 75 | text: "Right Controller Max Speed:" 76 | } 77 | 78 | MyText { 79 | id: statsRightControllerSpeedText 80 | text: "99.9 m/s" 81 | Layout.fillWidth: true 82 | horizontalAlignment: Text.AlignRight 83 | Layout.rightMargin: 10 84 | } 85 | 86 | MyPushButton { 87 | text: "Reset" 88 | onClicked: { 89 | StatisticsTabController.statsRightControllerSpeedResetClicked() 90 | } 91 | } 92 | } 93 | 94 | GridLayout { 95 | columns: 3 96 | Layout.topMargin: 32 97 | 98 | MyText { 99 | text: "Presented Frames:" 100 | } 101 | 102 | MyText { 103 | id: statsPresentedFramesText 104 | text: "000" 105 | Layout.fillWidth: true 106 | horizontalAlignment: Text.AlignRight 107 | Layout.rightMargin: 10 108 | } 109 | 110 | MyPushButton { 111 | text: "Reset" 112 | onClicked: { 113 | StatisticsTabController.presentedFramesResetClicked() 114 | } 115 | } 116 | 117 | MyText { 118 | text: "Dropped Frames:" 119 | } 120 | 121 | MyText { 122 | id: statsDroppedFramesText 123 | text: "000" 124 | Layout.fillWidth: true 125 | horizontalAlignment: Text.AlignRight 126 | Layout.rightMargin: 10 127 | } 128 | 129 | MyPushButton { 130 | text: "Reset" 131 | onClicked: { 132 | StatisticsTabController.droppedFramesResetClicked() 133 | } 134 | } 135 | 136 | MyText { 137 | text: "Reprojected Frames:" 138 | } 139 | 140 | MyText { 141 | id: statsReprojectionFramesText 142 | text: "000" 143 | Layout.fillWidth: true 144 | horizontalAlignment: Text.AlignRight 145 | Layout.rightMargin: 10 146 | } 147 | 148 | MyPushButton { 149 | text: "Reset" 150 | onClicked: { 151 | StatisticsTabController.reprojectedFramesResetClicked() 152 | } 153 | } 154 | 155 | MyText { 156 | text: "Timed Out:" 157 | } 158 | 159 | MyText { 160 | id: statsTimedOutText 161 | text: "000" 162 | Layout.fillWidth: true 163 | horizontalAlignment: Text.AlignRight 164 | Layout.rightMargin: 10 165 | } 166 | 167 | MyPushButton { 168 | text: "Reset" 169 | onClicked: { 170 | StatisticsTabController.timedOutResetClicked() 171 | } 172 | } 173 | 174 | MyText { 175 | text: "Reprojection Ratio:" 176 | } 177 | 178 | MyText { 179 | id: statstotalRatioText 180 | text: "0.0" 181 | Layout.fillWidth: true 182 | horizontalAlignment: Text.AlignRight 183 | Layout.rightMargin: 10 184 | } 185 | 186 | MyPushButton { 187 | text: "Reset" 188 | onClicked: { 189 | StatisticsTabController.totalRatioResetClicked() 190 | } 191 | } 192 | } 193 | Item { 194 | Layout.fillHeight: true 195 | } 196 | 197 | function updateStatistics() { 198 | statsHmdMovedText.text = StatisticsTabController.hmdDistanceMoved.toFixed(1) + " m" 199 | var rotations = StatisticsTabController.hmdRotations 200 | if (rotations > 0) { 201 | statsHmdRotationText.text = rotations.toFixed(1) + " CCW" 202 | } else { 203 | statsHmdRotationText.text = -rotations.toFixed(1) + " CW" 204 | } 205 | statsLeftControllerSpeedText.text = " " + StatisticsTabController.leftControllerMaxSpeed.toFixed(1) + " m/s" 206 | statsRightControllerSpeedText.text = " " + StatisticsTabController.rightControllerMaxSpeed.toFixed(1) + " m/s" 207 | statsPresentedFramesText.text = StatisticsTabController.presentedFrames 208 | statsDroppedFramesText.text = StatisticsTabController.droppedFrames 209 | statsReprojectionFramesText.text = StatisticsTabController.reprojectedFrames 210 | statsTimedOutText.text = StatisticsTabController.timedOut 211 | statstotalRatioText.text = (StatisticsTabController.totalReprojectedRatio*100.0).toFixed(1) + "%" 212 | } 213 | 214 | Timer { 215 | id: statisticsUpdateTimer 216 | repeat: true 217 | interval: 100 218 | onTriggered: { 219 | parent.updateStatistics() 220 | } 221 | } 222 | 223 | onVisibleChanged: { 224 | if (visible) { 225 | updateStatistics() 226 | statisticsUpdateTimer.start() 227 | } else { 228 | statisticsUpdateTimer.stop() 229 | } 230 | } 231 | 232 | } 233 | 234 | } 235 | -------------------------------------------------------------------------------- /bin/win64/res/qml/backarrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 16 | 18 | 19 | 21 | image/svg+xml 22 | 24 | 25 | 26 | 27 | 28 | 30 | 32 | 36 | 40 | 41 | 42 | 62 | 65 | 66 | 70 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /bin/win64/res/qml/mainwidget.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.0 4 | 5 | 6 | Rectangle { 7 | id: root 8 | color: "#1b2939" 9 | width: 1200 10 | height: 800 11 | 12 | property RootPage rootPage: RootPage { 13 | stackView: mainView 14 | } 15 | 16 | property SteamVRPage steamVRPage: SteamVRPage { 17 | stackView: mainView 18 | visible: false 19 | } 20 | 21 | property ChaperonePage chaperonePage: ChaperonePage { 22 | stackView: mainView 23 | visible: false 24 | } 25 | 26 | property ChaperoneWarningsPage chaperoneWarningsPage: ChaperoneWarningsPage { 27 | stackView: mainView 28 | visible: false 29 | } 30 | 31 | property PlayspacePage playspacePage: PlayspacePage { 32 | stackView: mainView 33 | visible: false 34 | } 35 | 36 | property FixFloorPage fixFloorPage: FixFloorPage { 37 | stackView: mainView 38 | visible: false 39 | } 40 | 41 | property StatisticsPage statisticsPage: StatisticsPage { 42 | stackView: mainView 43 | visible: false 44 | } 45 | 46 | property SettingsPage settingsPage: SettingsPage { 47 | stackView: mainView 48 | visible: false 49 | } 50 | 51 | property AudioPage audioPage: AudioPage { 52 | stackView: mainView 53 | visible: false 54 | } 55 | 56 | property RevivePage revivePage: RevivePage { 57 | stackView: mainView 58 | visible: false 59 | } 60 | 61 | property UtilitiesPage utilitiesPage: UtilitiesPage { 62 | stackView: mainView 63 | visible: false 64 | } 65 | 66 | property AccessibilityPage accessibilityPage: AccessibilityPage { 67 | stackView: mainView 68 | visible: false 69 | } 70 | 71 | StackView { 72 | id: mainView 73 | anchors.fill: parent 74 | 75 | pushEnter: Transition { 76 | PropertyAnimation { 77 | property: "x" 78 | from: mainView.width 79 | to: 0 80 | duration: 200 81 | } 82 | } 83 | pushExit: Transition { 84 | PropertyAnimation { 85 | property: "x" 86 | from: 0 87 | to: -mainView.width 88 | duration: 200 89 | } 90 | } 91 | popEnter: Transition { 92 | PropertyAnimation { 93 | property: "x" 94 | from: -mainView.width 95 | to: 0 96 | duration: 200 97 | } 98 | } 99 | popExit: Transition { 100 | PropertyAnimation { 101 | property: "x" 102 | from: 0 103 | to: mainView.width 104 | duration: 200 105 | } 106 | } 107 | 108 | initialItem: rootPage 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /bin/win64/res/qml/mic_off.svg: -------------------------------------------------------------------------------- 1 | 2 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 46 | 48 | 50 | 53 | 54 | 55 | 59 | 64 | 69 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /bin/win64/res/qml/mic_on.svg: -------------------------------------------------------------------------------- 1 | 2 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 46 | 48 | 50 | 53 | 54 | 55 | 59 | 64 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /bin/win64/res/qml/ptt_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/bin/win64/res/qml/ptt_notification.png -------------------------------------------------------------------------------- /bin/win64/res/qml/ptt_notification.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 20 | 22 | image/svg+xml 23 | 25 | 26 | 27 | 28 | 29 | 49 | 51 | 53 | 57 | 58 | 59 | 63 | 66 | 71 | 76 | 77 | 78 | 85 | 86 | -------------------------------------------------------------------------------- /bin/win64/res/qml/qmldir: -------------------------------------------------------------------------------- 1 | singleton MyResources 1.0 MyResources.qml -------------------------------------------------------------------------------- /bin/win64/res/qml/speaker_off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bin/win64/res/qml/speaker_on.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bin/win64/res/sounds/alarm01.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/bin/win64/res/sounds/alarm01.wav -------------------------------------------------------------------------------- /bin/win64/res/thumbicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/bin/win64/res/thumbicon.png -------------------------------------------------------------------------------- /bin/win64/restartvrserver.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | REM First (optional) parameter is the vr runtime path 4 | REM When no parameter given use default steam install location 5 | IF [%1] == [] ( 6 | SET "steamVRPath=C:\Program Files (x86)\Steam\steamapps\common\SteamVR\" 7 | ) ELSE ( 8 | SET "steamVRPath=%~1" 9 | ) 10 | echo VR Runtime Path: %steamVRPath% 11 | echo. 12 | 13 | REM Kill vrmonitor.exe and give SteamVR some time for a graceful shutdown 14 | REM When no process was killed then exit (helps to prevent the taskkill clone bug) 15 | (taskkill /im vrmonitor.exe /f >nul 2>nul && echo Give SteamVR some time for a graceful shutdown ... && timeout /t 20) || exit 16 | 17 | REM Forcefully kill all remaining processes 18 | taskkill /im vrcompositor.exe /f >nul 2>nul 19 | taskkill /im vrdashboard.exe /f >nul 2>nul 20 | taskkill /im vrserver.exe /f >nul 2>nul 21 | 22 | REM Start vrmonitor.exe 23 | REM start "" "%steamVRPath%\bin\win32\vrmonitor.exe" 24 | start "" "%steamVRPath%\bin\win32\vrstartup.exe" 25 | -------------------------------------------------------------------------------- /bin/win64/startdesktopmode.bat: -------------------------------------------------------------------------------- 1 | start AdvancedSettings.exe -desktop -nosound -------------------------------------------------------------------------------- /bin/windeployqt.bat: -------------------------------------------------------------------------------- 1 | 2 | cd win64 3 | 4 | windeployqt.exe --dir qtdata --libdir . --plugindir qtdata/plugins --no-system-d3d-compiler --no-opengl-sw --release --qmldir res/qml AdvancedSettings.exe 5 | 6 | @REM Debug: 7 | @REM windeployqt.exe --dir qtdata --libdir . --plugindir qtdata/plugins --no-system-d3d-compiler --compiler-runtime --no-opengl-sw --debug --qmldir res/qml AdvancedSettings.exe 8 | -------------------------------------------------------------------------------- /docs/screenshots/AccessibilityPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/docs/screenshots/AccessibilityPage.png -------------------------------------------------------------------------------- /docs/screenshots/AudioPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/docs/screenshots/AudioPage.png -------------------------------------------------------------------------------- /docs/screenshots/ChaperonePage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/docs/screenshots/ChaperonePage.png -------------------------------------------------------------------------------- /docs/screenshots/ChaperoneWarningPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/docs/screenshots/ChaperoneWarningPage.png -------------------------------------------------------------------------------- /docs/screenshots/FloorFixPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/docs/screenshots/FloorFixPage.png -------------------------------------------------------------------------------- /docs/screenshots/InVRScreenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/docs/screenshots/InVRScreenshot.png -------------------------------------------------------------------------------- /docs/screenshots/PlayspacePage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/docs/screenshots/PlayspacePage.png -------------------------------------------------------------------------------- /docs/screenshots/RevivePage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/docs/screenshots/RevivePage.png -------------------------------------------------------------------------------- /docs/screenshots/RootPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/docs/screenshots/RootPage.png -------------------------------------------------------------------------------- /docs/screenshots/SettingsPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/docs/screenshots/SettingsPage.png -------------------------------------------------------------------------------- /docs/screenshots/StatisticsPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/docs/screenshots/StatisticsPage.png -------------------------------------------------------------------------------- /docs/screenshots/SteamVRPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/docs/screenshots/SteamVRPage.png -------------------------------------------------------------------------------- /docs/screenshots/UtilitiesPage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/docs/screenshots/UtilitiesPage.png -------------------------------------------------------------------------------- /installer/installer.nsi: -------------------------------------------------------------------------------- 1 | ;-------------------------------- 2 | ;Include Modern UI 3 | 4 | !include "MUI2.nsh" 5 | 6 | ;-------------------------------- 7 | ;General 8 | 9 | !define BASEDIR "..\bin\win64" 10 | 11 | ;Name and file 12 | Name "OpenVR Advanced Settings" 13 | OutFile "OpenVR-AdvancedSettings-Installer.exe" 14 | 15 | ;Default installation folder 16 | InstallDir "$PROGRAMFILES64\OpenVR-AdvancedSettings" 17 | 18 | ;Get installation folder from registry if available 19 | InstallDirRegKey HKLM "Software\OpenVR-AdvancedSettings" "" 20 | 21 | ;Request application privileges for Windows Vista 22 | RequestExecutionLevel admin 23 | 24 | ;-------------------------------- 25 | ;Variables 26 | 27 | VAR upgradeInstallation 28 | 29 | ;-------------------------------- 30 | ;Interface Settings 31 | 32 | !define MUI_ABORTWARNING 33 | 34 | ;-------------------------------- 35 | ;Pages 36 | 37 | !insertmacro MUI_PAGE_LICENSE "..\LICENSE" 38 | !define MUI_PAGE_CUSTOMFUNCTION_PRE dirPre 39 | !insertmacro MUI_PAGE_DIRECTORY 40 | !insertmacro MUI_PAGE_INSTFILES 41 | 42 | !insertmacro MUI_UNPAGE_CONFIRM 43 | !insertmacro MUI_UNPAGE_INSTFILES 44 | 45 | ;-------------------------------- 46 | ;Languages 47 | 48 | !insertmacro MUI_LANGUAGE "English" 49 | 50 | ;-------------------------------- 51 | ;Macros 52 | 53 | !macro TerminateOverlay 54 | DetailPrint "Terminating OpenVR Advanced Settings overlay..." 55 | ExecWait '"taskkill" /F /IM AdvancedSettings.exe' 56 | Sleep 2000 ; give 2 seconds for the application to finish exiting 57 | !macroend 58 | 59 | ;-------------------------------- 60 | ;Functions 61 | 62 | Function dirPre 63 | StrCmp $upgradeInstallation "true" 0 +2 64 | Abort 65 | FunctionEnd 66 | 67 | Function .onInit 68 | StrCpy $upgradeInstallation "false" 69 | 70 | ReadRegStr $R0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenVRAdvancedSettings" "UninstallString" 71 | StrCmp $R0 "" done 72 | 73 | MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \ 74 | "OpenVR Advanced Settings is already installed. $\n$\nClick `OK` to upgrade the \ 75 | existing installation or `Cancel` to cancel this upgrade." \ 76 | IDOK upgrade 77 | Abort 78 | 79 | upgrade: 80 | StrCpy $upgradeInstallation "true" 81 | done: 82 | FunctionEnd 83 | 84 | ;-------------------------------- 85 | ;Installer Sections 86 | 87 | Section "Install" SecInstall 88 | 89 | !insertmacro TerminateOverlay 90 | 91 | StrCmp $upgradeInstallation "true" 0 noupgrade 92 | DetailPrint "Uninstall previous version..." 93 | ExecWait '"$INSTDIR\Uninstall.exe" /S _?=$INSTDIR' 94 | Delete $INSTDIR\Uninstall.exe 95 | Goto afterupgrade 96 | 97 | noupgrade: 98 | 99 | afterupgrade: 100 | 101 | SetOutPath "$INSTDIR" 102 | 103 | ;ADD YOUR OWN FILES HERE... 104 | File "${BASEDIR}\LICENSE" 105 | File "${BASEDIR}\*.exe" 106 | File "${BASEDIR}\*.dll" 107 | File "${BASEDIR}\*.bat" 108 | File "${BASEDIR}\*.vrmanifest" 109 | File "${BASEDIR}\*.conf" 110 | File /r "${BASEDIR}\res" 111 | File /r "${BASEDIR}\qtdata" 112 | 113 | ; Install redistributable 114 | ExecWait '"$INSTDIR\vcredist_x64.exe" /install /quiet' 115 | 116 | ; Install the vrmanifest 117 | nsExec::ExecToLog '"$INSTDIR\AdvancedSettings.exe" -installmanifest' 118 | 119 | ;Store installation folder 120 | WriteRegStr HKLM "Software\OpenVR-AdvancedSettings" "" $INSTDIR 121 | 122 | ;Create uninstaller 123 | WriteUninstaller "$INSTDIR\Uninstall.exe" 124 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenVRAdvancedSettings" "DisplayName" "OpenVR Advanced Settings" 125 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenVRAdvancedSettings" "UninstallString" "$\"$INSTDIR\Uninstall.exe$\"" 126 | 127 | ; If SteamVR is already running, execute the dashboard as the user 128 | FindWindow $0 "Qt5QWindowIcon" "SteamVR Status" 129 | StrCmp $0 0 +2 130 | Exec '"$INSTDIR\AdvancedSettings.exe"' 131 | 132 | SectionEnd 133 | 134 | ;-------------------------------- 135 | ;Uninstaller Section 136 | 137 | Section "Uninstall" 138 | 139 | !insertmacro TerminateOverlay 140 | 141 | ; Remove the vrmanifest 142 | nsExec::ExecToLog '"$INSTDIR\AdvancedSettings.exe" -removemanifest' 143 | 144 | ; Delete installed files 145 | !include uninstallFiles.list 146 | 147 | DeleteRegKey HKLM "Software\OpenVR-AdvancedSettings" 148 | DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\OpenVRAdvancedSettings" 149 | 150 | 151 | 152 | SectionEnd 153 | 154 | -------------------------------------------------------------------------------- /installer/listUninstallFiles.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Execute this script in the root folder of the install dir 4 | # Dont't forget to set OUTPUTFILE to a path that is writeable 5 | 6 | OUTPUTFILE=../../installed_files.txt 7 | INSTALLDIR=. 8 | 9 | # Get command line arguments 10 | if [ $# -eq 1 ]; then 11 | OUTPUTFILE=$1 12 | elif [ $# -gt 1 ]; then 13 | OUTPUTFILE=$1 14 | INSTALLDIR=$2 15 | fi 16 | 17 | # Find all files 18 | find "$INSTALLDIR" -iname '*' -type f -exec echo "Delete \$INSTDIR/{}" \; > $OUTPUTFILE 19 | 20 | # Find all directories and print them out in reverse order 21 | find "$INSTALLDIR" -iname '*' -type d -exec echo "RMdir \$INSTDIR/{}" \; | tac.exe >> $OUTPUTFILE 22 | 23 | # Remove "/./" from the file paths 24 | sed -i 's/\/\.//g' $OUTPUTFILE 25 | 26 | # Replace "/" with "\" 27 | sed -i 's/\//\\/g' $OUTPUTFILE 28 | -------------------------------------------------------------------------------- /src/logging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // easylogging includes 4 | #ifndef _DEBUG 5 | #define _DEBUG 6 | #define ELPP_THREAD_SAFE 7 | #define ELPP_QT_LOGGING 8 | #define ELPP_NO_DEFAULT_LOG_FILE 9 | #include 10 | #undef _DEBUG 11 | #else 12 | #define ELPP_THREAD_SAFE 13 | #define ELPP_QT_LOGGING 14 | #define ELPP_NO_DEFAULT_LOG_FILE 15 | #include 16 | #endif 17 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "overlaycontroller.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "logging.h" 12 | 13 | const char* logConfigFileName = "logging.conf"; 14 | 15 | const char* logConfigDefault = 16 | "* GLOBAL:\n" 17 | " FORMAT = \"[%level] %datetime{%Y-%M-%d %H:%m:%s}: %msg\"\n" 18 | " FILENAME = \"AdvancedSettings.log\"\n" 19 | " ENABLED = true\n" 20 | " TO_FILE = true\n" 21 | " TO_STANDARD_OUTPUT = true\n" 22 | " MAX_LOG_FILE_SIZE = 2097152 ## 2MB\n" 23 | "* TRACE:\n" 24 | " ENABLED = false\n" 25 | "* DEBUG:\n" 26 | " ENABLED = false\n"; 27 | 28 | INITIALIZE_EASYLOGGINGPP 29 | 30 | void myQtMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { 31 | QByteArray localMsg = msg.toLocal8Bit(); 32 | switch (type) { 33 | case QtDebugMsg: 34 | LOG(DEBUG) << localMsg.constData() << " (" << context.file << ":" << context.line << ")"; 35 | break; 36 | case QtInfoMsg: 37 | LOG(INFO) << localMsg.constData() << " (" << context.file << ":" << context.line << ")"; 38 | break; 39 | case QtWarningMsg: 40 | LOG(WARNING) << localMsg.constData() << " (" << context.file << ":" << context.line << ")"; 41 | break; 42 | case QtCriticalMsg: 43 | LOG(ERROR) << localMsg.constData() << " (" << context.file << ":" << context.line << ")"; 44 | break; 45 | case QtFatalMsg: 46 | LOG(FATAL) << localMsg.constData() << " (" << context.file << ":" << context.line << ")"; 47 | break; 48 | } 49 | } 50 | 51 | void installManifest(bool cleaninstall = false) { 52 | auto manifestQPath = QDir::cleanPath(QDir(QCoreApplication::applicationDirPath()).absoluteFilePath("manifest.vrmanifest")); 53 | if (QFile::exists(manifestQPath)) { 54 | bool alreadyInstalled = false; 55 | if (vr::VRApplications()->IsApplicationInstalled(advsettings::OverlayController::applicationKey)) { 56 | if (cleaninstall) { 57 | char buffer[1024]; 58 | auto appError = vr::VRApplicationError_None; 59 | vr::VRApplications()->GetApplicationPropertyString(advsettings::OverlayController::applicationKey, vr::VRApplicationProperty_WorkingDirectory_String, buffer, 1024, &appError); 60 | if (appError == vr::VRApplicationError_None) { 61 | auto oldManifestQPath = QDir::cleanPath(QDir(buffer).absoluteFilePath("manifest.vrmanifest")); 62 | if (oldManifestQPath.compare(manifestQPath, Qt::CaseInsensitive) != 0) { 63 | vr::VRApplications()->RemoveApplicationManifest(QDir::toNativeSeparators(oldManifestQPath).toStdString().c_str()); 64 | } else { 65 | alreadyInstalled = true; 66 | } 67 | } 68 | } else { 69 | alreadyInstalled = true; 70 | } 71 | } 72 | auto apperror = vr::VRApplications()->AddApplicationManifest(QDir::toNativeSeparators(manifestQPath).toStdString().c_str()); 73 | if (apperror != vr::VRApplicationError_None) { 74 | throw std::runtime_error(std::string("Could not add application manifest: ") + std::string(vr::VRApplications()->GetApplicationsErrorNameFromEnum(apperror))); 75 | } else if (!alreadyInstalled || cleaninstall) { 76 | auto apperror = vr::VRApplications()->SetApplicationAutoLaunch(advsettings::OverlayController::applicationKey, true); 77 | if (apperror != vr::VRApplicationError_None) { 78 | throw std::runtime_error(std::string("Could not set auto start: ") + std::string(vr::VRApplications()->GetApplicationsErrorNameFromEnum(apperror))); 79 | } 80 | } 81 | } else { 82 | throw std::runtime_error(std::string("Could not find application manifest: ") + manifestQPath.toStdString()); 83 | } 84 | } 85 | 86 | void removeManifest() { 87 | auto manifestQPath = QDir::cleanPath(QDir(QCoreApplication::applicationDirPath()).absoluteFilePath("manifest.vrmanifest")); 88 | if (QFile::exists(manifestQPath)) { 89 | if (vr::VRApplications()->IsApplicationInstalled(advsettings::OverlayController::applicationKey)) { 90 | vr::VRApplications()->RemoveApplicationManifest(QDir::toNativeSeparators(manifestQPath).toStdString().c_str()); 91 | } 92 | } else { 93 | throw std::runtime_error(std::string("Could not find application manifest: ") + manifestQPath.toStdString()); 94 | } 95 | } 96 | 97 | 98 | class MyQApplication : public QApplication { 99 | public: 100 | using QApplication::QApplication; 101 | 102 | virtual bool notify(QObject * receiver, QEvent * event) override { 103 | try { 104 | return QApplication::notify(receiver, event); 105 | } catch (std::exception& e) { 106 | LOG(ERROR) << "Exception thrown from an event handler: " << e.what(); 107 | } 108 | return false; 109 | } 110 | }; 111 | 112 | 113 | int main(int argc, char *argv[]) { 114 | 115 | bool desktopMode = false; 116 | bool noSound = false; 117 | bool noManifest = false; 118 | 119 | // Parse command line arguments 120 | for (int i = 1; i < argc; i++) { 121 | if (std::string(argv[i]).compare("-desktop") == 0) { 122 | desktopMode = true; 123 | } else if (std::string(argv[i]).compare("-nosound") == 0) { 124 | noSound = true; 125 | } else if (std::string(argv[i]).compare("-nomanifest") == 0) { 126 | noManifest = true; 127 | } else if (std::string(argv[i]).compare("-installmanifest") == 0) { 128 | int exitcode = 0; 129 | QCoreApplication coreApp(argc, argv); 130 | auto initError = vr::VRInitError_None; 131 | vr::VR_Init(&initError, vr::VRApplication_Utility); 132 | if (initError == vr::VRInitError_None) { 133 | try { 134 | installManifest(true); 135 | } catch (std::exception& e) { 136 | exitcode = -1; 137 | std::cerr << e.what() << std::endl; 138 | } 139 | } else { 140 | exitcode = -2; 141 | std::cerr << std::string("Failed to initialize OpenVR: " + std::string(vr::VR_GetVRInitErrorAsEnglishDescription(initError))) << std::endl; 142 | } 143 | vr::VR_Shutdown(); 144 | exit(exitcode); 145 | } else if (std::string(argv[i]).compare("-removemanifest") == 0) { 146 | int exitcode = 0; 147 | QCoreApplication coreApp(argc, argv); 148 | auto initError = vr::VRInitError_None; 149 | vr::VR_Init(&initError, vr::VRApplication_Utility); 150 | if (initError == vr::VRInitError_None) { 151 | try { 152 | removeManifest(); 153 | } catch (std::exception& e) { 154 | exitcode = -1; 155 | std::cerr << e.what() << std::endl; 156 | } 157 | } else { 158 | exitcode = -2; 159 | std::cerr << std::string("Failed to initialize OpenVR: " + std::string(vr::VR_GetVRInitErrorAsEnglishDescription(initError))) << std::endl; 160 | } 161 | vr::VR_Shutdown(); 162 | exit(exitcode); 163 | } 164 | } 165 | 166 | try { 167 | MyQApplication a(argc, argv); 168 | a.setOrganizationName("matzman666"); 169 | a.setApplicationName("OpenVRAdvancedSettings"); 170 | a.setApplicationDisplayName(advsettings::OverlayController::applicationName); 171 | a.setApplicationVersion(advsettings::OverlayController::applicationVersionString); 172 | 173 | qInstallMessageHandler(myQtMessageHandler); 174 | 175 | // Configure logger 176 | QString logFilePath; 177 | START_EASYLOGGINGPP(argc, argv); 178 | el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog); 179 | auto logconfigfile = QFileInfo(logConfigFileName).absoluteFilePath(); 180 | el::Configurations conf; 181 | if (QFile::exists(logconfigfile)) { 182 | conf.parseFromFile(logconfigfile.toStdString()); 183 | } else { 184 | conf.parseFromText(logConfigDefault); 185 | } 186 | if (!conf.get(el::Level::Global, el::ConfigurationType::Filename)) { 187 | logFilePath = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).absoluteFilePath("AdvancedSettings.log"); 188 | conf.set(el::Level::Global, el::ConfigurationType::Filename, QDir::toNativeSeparators(logFilePath).toStdString()); 189 | } 190 | conf.setRemainingToDefault(); 191 | el::Loggers::reconfigureAllLoggers(conf); 192 | LOG(INFO) << "Application started (Version " << advsettings::OverlayController::applicationVersionString << ")"; 193 | LOG(INFO) << "Log Config: " << QDir::toNativeSeparators(logconfigfile).toStdString(); 194 | if (!logFilePath.isEmpty()) { 195 | LOG(INFO) << "Log File: " << logFilePath; 196 | } 197 | 198 | if (desktopMode) { 199 | LOG(INFO) << "Desktop mode enabled."; 200 | } 201 | if (noSound) { 202 | LOG(INFO) << "Sound effects disabled."; 203 | } 204 | if (noManifest) { 205 | LOG(INFO) << "vrmanifest disabled."; 206 | } 207 | 208 | QSettings appSettings(QSettings::IniFormat, QSettings::UserScope, a.organizationName(), a.applicationName()); 209 | advsettings::OverlayController::setAppSettings(&appSettings); 210 | LOG(INFO) << "Settings File: " << appSettings.fileName().toStdString(); 211 | 212 | QQmlEngine qmlEngine; 213 | 214 | advsettings::OverlayController* controller = advsettings::OverlayController::createInstance(desktopMode, noSound); 215 | controller->Init(&qmlEngine); 216 | 217 | QQmlComponent component(&qmlEngine, QUrl::fromLocalFile("res/qml/mainwidget.qml")); 218 | auto errors = component.errors(); 219 | for (auto& e : errors) { 220 | LOG(ERROR) << "QML Error: " << e.toString().toStdString() << std::endl; 221 | } 222 | auto quickObj = component.create(); 223 | controller->SetWidget(qobject_cast(quickObj), advsettings::OverlayController::applicationName, advsettings::OverlayController::applicationKey); 224 | 225 | if (!desktopMode && !noManifest) { 226 | try { 227 | installManifest(); 228 | } catch (std::exception& e) { 229 | LOG(ERROR) << e.what(); 230 | } 231 | } 232 | 233 | if (desktopMode) { 234 | auto m_pWindow = new QQuickWindow(); 235 | qobject_cast(quickObj)->setParentItem(m_pWindow->contentItem()); 236 | m_pWindow->setGeometry(0, 0, qobject_cast(quickObj)->width(), qobject_cast(quickObj)->height()); 237 | m_pWindow->show(); 238 | } 239 | 240 | return a.exec(); 241 | 242 | } catch (const std::exception& e) { 243 | LOG(FATAL) << e.what(); 244 | return -1; 245 | } 246 | return 0; 247 | } 248 | -------------------------------------------------------------------------------- /src/overlaycontroller.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | // because of incompatibilities with QtOpenGL and GLEW we need to cherry pick includes 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include "logging.h" 25 | #include "utils/ChaperoneUtils.h" 26 | 27 | #include "tabcontrollers/SteamVRTabController.h" 28 | #include "tabcontrollers/ChaperoneTabController.h" 29 | #include "tabcontrollers/MoveCenterTabController.h" 30 | #include "tabcontrollers/FixFloorTabController.h" 31 | #include "tabcontrollers/AudioTabController.h" 32 | #include "tabcontrollers/StatisticsTabController.h" 33 | #include "tabcontrollers/SettingsTabController.h" 34 | #include "tabcontrollers/ReviveTabController.h" 35 | #include "tabcontrollers/UtilitiesTabController.h" 36 | #include "tabcontrollers/AccessibilityTabController.h" 37 | 38 | 39 | 40 | // application namespace 41 | namespace advsettings { 42 | 43 | class OverlayController : public QObject { 44 | Q_OBJECT 45 | Q_PROPERTY(bool desktopMode READ isDesktopMode) 46 | 47 | public: 48 | static constexpr const char* applicationKey = "matzman666.AdvancedSettings"; 49 | static constexpr const char* applicationName = "Advanced Settings"; 50 | static constexpr const char* applicationVersionString = "v2.5"; 51 | 52 | private: 53 | vr::VROverlayHandle_t m_ulOverlayHandle = vr::k_ulOverlayHandleInvalid; 54 | vr::VROverlayHandle_t m_ulOverlayThumbnailHandle = vr::k_ulOverlayHandleInvalid; 55 | 56 | std::unique_ptr m_pRenderControl; 57 | std::unique_ptr m_pWindow; 58 | std::unique_ptr m_pFbo; 59 | std::unique_ptr m_pOpenGLContext; 60 | std::unique_ptr m_pOffscreenSurface; 61 | 62 | std::unique_ptr m_pPumpEventsTimer; 63 | std::unique_ptr m_pRenderTimer; 64 | bool dashboardVisible = false; 65 | 66 | QPoint m_ptLastMouse; 67 | Qt::MouseButtons m_lastMouseButtons = 0; 68 | 69 | bool desktopMode; 70 | bool noSound; 71 | 72 | QUrl m_runtimePathUrl; 73 | 74 | utils::ChaperoneUtils m_chaperoneUtils; 75 | 76 | QSoundEffect activationSoundEffect; 77 | QSoundEffect focusChangedSoundEffect; 78 | QSoundEffect alarm01SoundEffect; 79 | 80 | public: // I know it's an ugly hack to make them public to enable external access, but I am too lazy to implement getters. 81 | SteamVRTabController steamVRTabController; 82 | ChaperoneTabController chaperoneTabController; 83 | MoveCenterTabController moveCenterTabController; 84 | FixFloorTabController fixFloorTabController; 85 | AudioTabController audioTabController; 86 | StatisticsTabController statisticsTabController; 87 | SettingsTabController settingsTabController; 88 | ReviveTabController reviveTabController; 89 | UtilitiesTabController utilitiesTabController; 90 | AccessibilityTabController accessibilityTabController; 91 | 92 | private: 93 | OverlayController(bool desktopMode, bool noSound) : QObject(), desktopMode(desktopMode), noSound(noSound) {} 94 | 95 | public: 96 | virtual ~OverlayController(); 97 | 98 | void Init(QQmlEngine* qmlEngine); 99 | void Shutdown(); 100 | 101 | bool isDashboardVisible() { 102 | return dashboardVisible; 103 | } 104 | 105 | void SetWidget(QQuickItem* quickItem, const std::string& name, const std::string& key = ""); 106 | 107 | void AddOffsetToUniverseCenter(vr::ETrackingUniverseOrigin universe, unsigned axisId, float offset, bool adjustBounds = true, bool commit = true); 108 | void RotateUniverseCenter(vr::ETrackingUniverseOrigin universe, float yAngle, bool adjustBounds = true, bool commit = true); // around y axis 109 | void AddOffsetToCollisionBounds(unsigned axisId, float offset, bool commit = true); 110 | void RotateCollisionBounds(float angle, bool commit = true); // around y axis 111 | 112 | bool isDesktopMode() { return desktopMode; }; 113 | 114 | utils::ChaperoneUtils& chaperoneUtils() noexcept { return m_chaperoneUtils; } 115 | 116 | Q_INVOKABLE QString getVersionString(); 117 | Q_INVOKABLE QUrl getVRRuntimePathUrl(); 118 | 119 | Q_INVOKABLE bool soundDisabled(); 120 | 121 | const vr::VROverlayHandle_t& overlayHandle(); 122 | const vr::VROverlayHandle_t& overlayThumbnailHandle(); 123 | 124 | bool pollNextEvent(vr::VROverlayHandle_t ulOverlayHandle, vr::VREvent_t* pEvent); 125 | 126 | public slots: 127 | void renderOverlay(); 128 | void OnRenderRequest(); 129 | void OnTimeoutPumpEvents(); 130 | 131 | void showKeyboard(QString existingText, unsigned long userValue = 0); 132 | 133 | void playActivationSound(); 134 | void playFocusChangedSound(); 135 | void playAlarm01Sound(bool loop = false); 136 | void setAlarm01SoundVolume(float vol); 137 | void cancelAlarm01Sound(); 138 | 139 | signals: 140 | void keyBoardInputSignal(QString input, unsigned long userValue = 0); 141 | 142 | private: 143 | static QSettings* _appSettings; 144 | static std::unique_ptr singleton; 145 | 146 | public: 147 | static OverlayController* getInstance() { 148 | return singleton.get(); 149 | } 150 | 151 | static OverlayController* createInstance(bool desktopMode, bool noSound) { 152 | singleton.reset(new advsettings::OverlayController(desktopMode, noSound)); 153 | return singleton.get(); 154 | } 155 | 156 | static QSettings* appSettings() { return _appSettings; } 157 | 158 | static void setAppSettings(QSettings* settings) { _appSettings = settings; } 159 | }; 160 | 161 | } // namespace advsettings 162 | -------------------------------------------------------------------------------- /src/tabcontrollers/AccessibilityTabController.cpp: -------------------------------------------------------------------------------- 1 | #include "AccessibilityTabController.h" 2 | #include 3 | #include "../overlaycontroller.h" 4 | 5 | // application namespace 6 | namespace advsettings { 7 | 8 | void AccessibilityTabController::initStage1() { 9 | setTrackingUniverse(vr::VRCompositor()->GetTrackingSpace()); 10 | auto settings = OverlayController::appSettings(); 11 | settings->beginGroup(getSettingsName()); 12 | auto value = settings->value("heightOffset", m_heightOffset); 13 | settings->endGroup(); 14 | if (value.isValid() && !value.isNull()) { 15 | m_heightOffset = value.toFloat(); 16 | emit heightOffsetChanged(m_heightOffset); 17 | } 18 | 19 | reloadPttConfig(); 20 | } 21 | 22 | void AccessibilityTabController::initStage2(OverlayController * parent, QQuickWindow * widget) { 23 | this->parent = parent; 24 | this->widget = widget; 25 | } 26 | 27 | void AccessibilityTabController::setTrackingUniverse(int value) { 28 | if (m_trackingUniverse != value) { 29 | reset(); 30 | m_trackingUniverse = value; 31 | } 32 | } 33 | 34 | float AccessibilityTabController::heightOffset() const { 35 | return m_heightOffset; 36 | } 37 | 38 | void AccessibilityTabController::setHeightOffset(float value, bool notify) { 39 | if (std::abs(m_heightOffset - value) > 0.001) { 40 | modHeightOffset(value - m_heightOffset, notify); 41 | } 42 | } 43 | 44 | void AccessibilityTabController::modHeightOffset(float value, bool notify) { 45 | parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 1, -value, false); 46 | m_heightOffset += value; 47 | auto settings = OverlayController::appSettings(); 48 | settings->beginGroup(getSettingsName()); 49 | settings->setValue("heightOffset", m_heightOffset); 50 | settings->endGroup(); 51 | settings->sync(); 52 | if (notify) { 53 | emit heightOffsetChanged(m_heightOffset); 54 | } 55 | } 56 | 57 | 58 | void AccessibilityTabController::onPttStart() { 59 | m_toggleHeightOffset = m_heightOffset; 60 | parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 1, m_toggleHeightOffset, false); 61 | } 62 | 63 | void AccessibilityTabController::onPttStop() { 64 | parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 1, -m_toggleHeightOffset, false); 65 | } 66 | 67 | void AccessibilityTabController::onPttDisabled() { 68 | if (pttActive()) { 69 | stopPtt(); 70 | } 71 | m_toggleHeightOffset = 0; 72 | } 73 | 74 | void AccessibilityTabController::reset() { 75 | std::lock_guard lock(eventLoopMutex); 76 | vr::VRChaperoneSetup()->RevertWorkingCopy(); 77 | parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 1, m_heightOffset, false, false); 78 | vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live); 79 | m_heightOffset = 0.0f; 80 | emit heightOffsetChanged(m_heightOffset); 81 | } 82 | 83 | void AccessibilityTabController::eventLoopTick(vr::ETrackingUniverseOrigin universe) { 84 | if (!eventLoopMutex.try_lock()) { 85 | return; 86 | } 87 | if (settingsUpdateCounter >= 50) { 88 | setTrackingUniverse((int)universe); 89 | settingsUpdateCounter = 0; 90 | } else { 91 | settingsUpdateCounter++; 92 | } 93 | checkPttStatus(); 94 | eventLoopMutex.unlock(); 95 | } 96 | 97 | } // namespace advconfig 98 | -------------------------------------------------------------------------------- /src/tabcontrollers/AccessibilityTabController.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include "PttController.h" 5 | 6 | class QQuickWindow; 7 | // application namespace 8 | namespace advsettings { 9 | 10 | // forward declaration 11 | class OverlayController; 12 | 13 | 14 | class AccessibilityTabController : public PttController { 15 | Q_OBJECT 16 | Q_PROPERTY(float heightOffset READ heightOffset WRITE setHeightOffset NOTIFY heightOffsetChanged) 17 | 18 | private: 19 | OverlayController* parent; 20 | QQuickWindow* widget; 21 | 22 | int m_trackingUniverse = (int)vr::TrackingUniverseStanding; 23 | float m_heightOffset = 0.0f; 24 | float m_toggleHeightOffset = 0.0f; 25 | 26 | unsigned settingsUpdateCounter = 0; 27 | 28 | QString getSettingsName() override { return "accessibilitySettings"; } 29 | void onPttStart() override; 30 | void onPttStop() override; 31 | void onPttDisabled() override; 32 | 33 | public: 34 | void initStage1(); 35 | void initStage2(OverlayController* parent, QQuickWindow* widget); 36 | void eventLoopTick(vr::ETrackingUniverseOrigin universe); 37 | 38 | float heightOffset() const; 39 | 40 | public slots: 41 | void setTrackingUniverse(int value); 42 | void setHeightOffset(float value, bool notify = true); 43 | void modHeightOffset(float value, bool notify = true); 44 | void reset(); 45 | 46 | signals: 47 | void heightOffsetChanged(float value); 48 | }; 49 | 50 | } // namespace advsettings 51 | -------------------------------------------------------------------------------- /src/tabcontrollers/AudioManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | // application namespace 7 | namespace advsettings { 8 | 9 | class AudioTabController; 10 | 11 | class AudioManager 12 | { 13 | public: 14 | virtual ~AudioManager() {}; 15 | 16 | virtual void init(AudioTabController* controller) = 0; 17 | 18 | virtual void setPlaybackDevice(const std::string& id, bool notify = true) = 0; 19 | virtual std::string getPlaybackDevName() = 0; 20 | virtual std::string getPlaybackDevId() = 0; 21 | 22 | virtual void setMirrorDevice(const std::string& id, bool notify = true) = 0; 23 | virtual bool isMirrorValid() = 0; 24 | virtual std::string getMirrorDevName() = 0; 25 | virtual std::string getMirrorDevId() = 0; 26 | virtual float getMirrorVolume() = 0; 27 | virtual bool setMirrorVolume(float value) = 0; 28 | virtual bool getMirrorMuted() = 0; 29 | virtual bool setMirrorMuted(bool value) = 0; 30 | 31 | virtual void setMicDevice(const std::string& id, bool notify = true) = 0; 32 | virtual bool isMicValid() = 0; 33 | virtual std::string getMicDevName() = 0; 34 | virtual std::string getMicDevId() = 0; 35 | virtual float getMicVolume() = 0; 36 | virtual bool setMicVolume(float value) = 0; 37 | virtual bool getMicMuted() = 0; 38 | virtual bool setMicMuted(bool value) = 0; 39 | 40 | virtual std::vector> getRecordingDevices() = 0; 41 | virtual std::vector> getPlaybackDevices() = 0; 42 | }; 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /src/tabcontrollers/AudioTabController.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include "AudioManager.h" 5 | #include "PttController.h" 6 | #include 7 | 8 | class QQuickWindow; 9 | // application namespace 10 | namespace advsettings { 11 | 12 | // forward declaration 13 | class OverlayController; 14 | 15 | 16 | class AudioTabController : public PttController { 17 | Q_OBJECT 18 | Q_PROPERTY(int playbackDeviceIndex READ playbackDeviceIndex WRITE setPlaybackDeviceIndex NOTIFY playbackDeviceIndexChanged) 19 | Q_PROPERTY(int mirrorDeviceIndex READ mirrorDeviceIndex WRITE setMirrorDeviceIndex NOTIFY mirrorDeviceIndexChanged) 20 | //Q_PROPERTY(bool mirrorPresent READ mirrorPresent NOTIFY mirrorPresentChanged) 21 | //Q_PROPERTY(QString mirrorDevName READ mirrorDevName NOTIFY mirrorDevNameChanged) 22 | Q_PROPERTY(float mirrorVolume READ mirrorVolume WRITE setMirrorVolume NOTIFY mirrorVolumeChanged) 23 | Q_PROPERTY(bool mirrorMuted READ mirrorMuted WRITE setMirrorMuted NOTIFY mirrorMutedChanged) 24 | Q_PROPERTY(int micDeviceIndex READ micDeviceIndex WRITE setMicDeviceIndex NOTIFY micDeviceIndexChanged) 25 | //Q_PROPERTY(bool micPresent READ micPresent NOTIFY micPresentChanged) 26 | //Q_PROPERTY(QString micDevName READ micDevName NOTIFY micDevNameChanged) 27 | Q_PROPERTY(float micVolume READ micVolume WRITE setMicVolume NOTIFY micVolumeChanged) 28 | Q_PROPERTY(bool micMuted READ micMuted WRITE setMicMuted NOTIFY micMutedChanged) 29 | Q_PROPERTY(bool micProximitySensorCanMute READ micProximitySensorCanMute WRITE setMicProximitySensorCanMute NOTIFY micProximitySensorCanMuteChanged) 30 | Q_PROPERTY(bool micReversePtt READ micReversePtt WRITE setMicReversePtt NOTIFY micReversePttChanged) 31 | 32 | private: 33 | OverlayController* parent; 34 | QQuickWindow* widget; 35 | 36 | vr::VROverlayHandle_t m_ulNotificationOverlayHandle = vr::k_ulOverlayHandleInvalid; 37 | 38 | int m_playbackDeviceIndex = -1; 39 | 40 | int m_mirrorDeviceIndex = -1; 41 | float m_mirrorVolume = 1.0; 42 | bool m_mirrorMuted = false; 43 | 44 | int m_recordingDeviceIndex = -1; 45 | float m_micVolume = 1.0; 46 | bool m_micMuted = false; 47 | bool m_micProximitySensorCanMute = false; 48 | bool m_micReversePtt = false; 49 | 50 | unsigned settingsUpdateCounter = 0; 51 | 52 | std::unique_ptr audioManager; 53 | std::vector> m_recordingDevices; 54 | std::vector> m_playbackDevices; 55 | std::string lastMirrorDevId; 56 | 57 | QString getSettingsName() override { return "audioSettings"; } 58 | void onPttStart() override; 59 | void onPttStop() override; 60 | void onPttEnabled() override; 61 | void onPttDisabled() override; 62 | bool pttChangeValid() override; 63 | virtual vr::VROverlayHandle_t getNotificationOverlayHandle() override { return m_ulNotificationOverlayHandle; } 64 | 65 | void findPlaybackDeviceIndex(std::string id, bool notify = true); 66 | void findMirrorDeviceIndex(std::string id, bool notify = true); 67 | void findMicDeviceIndex(std::string id, bool notify = true); 68 | 69 | public: 70 | void initStage1(); 71 | void initStage2(OverlayController* parent, QQuickWindow* widget); 72 | 73 | void reloadAudioSettings(); 74 | void saveAudioSettings(); 75 | 76 | void eventLoopTick(); 77 | 78 | int playbackDeviceIndex() const; 79 | 80 | int mirrorDeviceIndex() const; 81 | float mirrorVolume() const; 82 | bool mirrorMuted() const; 83 | 84 | int micDeviceIndex() const; 85 | float micVolume() const; 86 | bool micMuted() const; 87 | bool micProximitySensorCanMute() const; 88 | bool micReversePtt() const; 89 | 90 | Q_INVOKABLE int getPlaybackDeviceCount(); 91 | Q_INVOKABLE QString getPlaybackDeviceName(int index); 92 | 93 | Q_INVOKABLE int getRecordingDeviceCount(); 94 | Q_INVOKABLE QString getRecordingDeviceName(int index); 95 | 96 | void onNewRecordingDevice(); 97 | void onNewPlaybackDevice(); 98 | void onNewMirrorDevice(); 99 | void onDeviceStateChanged(); 100 | 101 | public slots: 102 | void setMirrorVolume(float value, bool notify = true); 103 | void setMirrorMuted(bool value, bool notify = true); 104 | 105 | void setMicVolume(float value, bool notify = true); 106 | void setMicMuted(bool value, bool notify = true); 107 | void setMicProximitySensorCanMute(bool value, bool notify = true); 108 | void setMicReversePtt(bool value, bool notify = true); 109 | 110 | void setPlaybackDeviceIndex(int value, bool notify = true); 111 | void setMirrorDeviceIndex(int value, bool notify = true); 112 | void setMicDeviceIndex(int value, bool notify = true); 113 | 114 | signals: 115 | void playbackDeviceIndexChanged(int index); 116 | 117 | void mirrorDeviceIndexChanged(int index); 118 | void mirrorVolumeChanged(float value); 119 | void mirrorMutedChanged(bool value); 120 | 121 | void micDeviceIndexChanged(int index); 122 | void micVolumeChanged(float value); 123 | void micMutedChanged(bool value); 124 | void micProximitySensorCanMuteChanged(bool value); 125 | void micReversePttChanged(bool value); 126 | 127 | void playbackDeviceListChanged(); 128 | void recordingDeviceListChanged(); 129 | }; 130 | 131 | } // namespace advsettings 132 | -------------------------------------------------------------------------------- /src/tabcontrollers/ChaperoneTabController.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class QQuickWindow; 11 | // application namespace 12 | namespace advsettings { 13 | 14 | // forward declaration 15 | class OverlayController; 16 | 17 | 18 | struct ChaperoneProfile { 19 | std::string profileName; 20 | 21 | bool includesChaperoneGeometry = false; 22 | unsigned chaperoneGeometryQuadCount = 0; 23 | std::unique_ptr chaperoneGeometryQuads = nullptr; 24 | vr::HmdMatrix34_t standingCenter; 25 | float playSpaceAreaX = 0.0f; 26 | float playSpaceAreaZ = 0.0f; 27 | 28 | bool includesVisibility = false; 29 | float visibility = 0.6f; 30 | 31 | bool includesFadeDistance = false; 32 | float fadeDistance = 0.7f; 33 | 34 | bool includesCenterMarker = false; 35 | bool centerMarker = false; 36 | 37 | bool includesPlaySpaceMarker = false; 38 | bool playSpaceMarker = false; 39 | 40 | bool includesFloorBoundsMarker = false; 41 | bool floorBoundsMarker = false; 42 | 43 | bool includesBoundsColor = false; 44 | int boundsColor[3] = {0, 0, 0}; 45 | 46 | bool includesChaperoneStyle = false; 47 | int chaperoneStyle = 0; 48 | 49 | bool includesForceBounds = false; 50 | bool forceBounds = false; 51 | 52 | bool includesProximityWarningSettings = false; 53 | bool enableChaperoneSwitchToBeginner = false; 54 | float chaperoneSwitchToBeginnerDistance = 0.0f; 55 | bool enableChaperoneHapticFeedback = false; 56 | float chaperoneHapticFeedbackDistance = 0.0f; 57 | bool enableChaperoneAlarmSound = false; 58 | bool chaperoneAlarmSoundLooping = true; 59 | bool chaperoneAlarmSoundAdjustVolume = false; 60 | float chaperoneAlarmSoundDistance = 0.0f; 61 | bool enableChaperoneShowDashboard = false; 62 | float chaperoneShowDashboardDistance = 0.0f; 63 | bool enableChaperoneVelocityModifier = false; 64 | float chaperoneVelocityModifier = 0.0f; 65 | }; 66 | 67 | 68 | class ChaperoneTabController : public QObject { 69 | Q_OBJECT 70 | Q_PROPERTY(float boundsVisibility READ boundsVisibility WRITE setBoundsVisibility NOTIFY boundsVisibilityChanged) 71 | Q_PROPERTY(float fadeDistance READ fadeDistance WRITE setFadeDistance NOTIFY fadeDistanceChanged) 72 | Q_PROPERTY(float height READ height WRITE setHeight NOTIFY heightChanged) 73 | Q_PROPERTY(bool centerMarker READ centerMarker WRITE setCenterMarker NOTIFY centerMarkerChanged) 74 | Q_PROPERTY(bool playSpaceMarker READ playSpaceMarker WRITE setPlaySpaceMarker NOTIFY playSpaceMarkerChanged) 75 | Q_PROPERTY(bool forceBounds READ forceBounds WRITE setForceBounds NOTIFY forceBoundsChanged) 76 | 77 | Q_PROPERTY(bool chaperoneSwitchToBeginnerEnabled READ isChaperoneSwitchToBeginnerEnabled WRITE setChaperoneSwitchToBeginnerEnabled NOTIFY chaperoneSwitchToBeginnerEnabledChanged) 78 | Q_PROPERTY(float chaperoneSwitchToBeginnerDistance READ chaperoneSwitchToBeginnerDistance WRITE setChaperoneSwitchToBeginnerDistance NOTIFY chaperoneSwitchToBeginnerDistanceChanged) 79 | 80 | Q_PROPERTY(bool chaperoneHapticFeedbackEnabled READ isChaperoneHapticFeedbackEnabled WRITE setChaperoneHapticFeedbackEnabled NOTIFY chaperoneHapticFeedbackEnabledChanged) 81 | Q_PROPERTY(float chaperoneHapticFeedbackDistance READ chaperoneHapticFeedbackDistance WRITE setChaperoneHapticFeedbackDistance NOTIFY chaperoneHapticFeedbackDistanceChanged) 82 | 83 | Q_PROPERTY(bool chaperoneAlarmSoundEnabled READ isChaperoneAlarmSoundEnabled WRITE setChaperoneAlarmSoundEnabled NOTIFY chaperoneAlarmSoundEnabledChanged) 84 | Q_PROPERTY(bool chaperoneAlarmSoundLooping READ isChaperoneAlarmSoundLooping WRITE setChaperoneAlarmSoundLooping NOTIFY chaperoneAlarmSoundLoopingChanged) 85 | Q_PROPERTY(bool chaperoneAlarmSoundAdjustVolume READ isChaperoneAlarmSoundAdjustVolume WRITE setChaperoneAlarmSoundAdjustVolume NOTIFY chaperoneAlarmSoundAdjustVolumeChanged) 86 | Q_PROPERTY(float chaperoneAlarmSoundDistance READ chaperoneAlarmSoundDistance WRITE setChaperoneAlarmSoundDistance NOTIFY chaperoneAlarmSoundDistanceChanged) 87 | 88 | Q_PROPERTY(bool chaperoneShowDashboardEnabled READ isChaperoneShowDashboardEnabled WRITE setChaperoneShowDashboardEnabled NOTIFY chaperoneShowDashboardEnabledChanged) 89 | Q_PROPERTY(float chaperoneShowDashboardDistance READ chaperoneShowDashboardDistance WRITE setChaperoneShowDashboardDistance NOTIFY chaperoneShowDashboardDistanceChanged) 90 | 91 | Q_PROPERTY(bool chaperoneVelocityModifierEnabled READ isChaperoneVelocityModifierEnabled WRITE setChaperoneVelocityModifierEnabled NOTIFY chaperoneVelocityModifierEnabledChanged) 92 | Q_PROPERTY(float chaperoneVelocityModifier READ chaperoneVelocityModifier WRITE setChaperoneVelocityModifier NOTIFY chaperoneVelocityModifierChanged) 93 | 94 | private: 95 | OverlayController* parent; 96 | QQuickWindow* widget; 97 | 98 | float m_visibility = 0.6f; 99 | float m_fadeDistance = 0.7f; 100 | float m_fadeDistanceModified = 0.7f; 101 | float m_height = 2.0f; 102 | bool m_centerMarker = false; 103 | bool m_playSpaceMarker = false; 104 | bool m_forceBounds = false; 105 | 106 | bool m_enableChaperoneSwitchToBeginner = false; 107 | float m_chaperoneSwitchToBeginnerDistance = 0.5f; 108 | bool m_chaperoneSwitchToBeginnerActive = false; 109 | int32_t m_chaperoneSwitchToBeginnerLastStyle = 0; 110 | 111 | bool m_enableChaperoneHapticFeedback = true; 112 | float m_chaperoneHapticFeedbackDistance = 0.5f; 113 | bool m_chaperoneHapticFeedbackActive = false; 114 | std::thread m_chaperoneHapticFeedbackThread; 115 | 116 | bool m_enableChaperoneAlarmSound = false; 117 | bool m_chaperoneAlarmSoundLooping = true; 118 | bool m_chaperoneAlarmSoundAdjustVolume = false; 119 | float m_chaperoneAlarmSoundDistance = 0.5f; 120 | bool m_chaperoneAlarmSoundActive = false; 121 | 122 | bool m_enableChaperoneShowDashboard = false; 123 | float m_chaperoneShowDashboardDistance = 0.5f; 124 | bool m_chaperoneShowDashboardActive = false; 125 | 126 | bool m_enableChaperoneVelocityModifier = false; 127 | float m_chaperoneVelocityModifier = 0.0f; 128 | float m_chaperoneVelocityModifierCurrent = 1.0f; 129 | 130 | unsigned settingsUpdateCounter = 0; 131 | 132 | std::vector chaperoneProfiles; 133 | 134 | public: 135 | ~ChaperoneTabController(); 136 | 137 | void initStage1(); 138 | void initStage2(OverlayController* parent, QQuickWindow* widget); 139 | 140 | void eventLoopTick(vr::TrackedDevicePose_t* devicePoses, float leftSpeed, float rightSpeed, float hmdSpeed); 141 | void handleChaperoneWarnings(float distance); 142 | 143 | float boundsVisibility() const; 144 | float fadeDistance() const; 145 | float height() const; 146 | bool centerMarker() const; 147 | bool playSpaceMarker() const; 148 | bool forceBounds() const; 149 | 150 | bool isChaperoneSwitchToBeginnerEnabled() const; 151 | float chaperoneSwitchToBeginnerDistance() const; 152 | 153 | bool isChaperoneHapticFeedbackEnabled() const; 154 | float chaperoneHapticFeedbackDistance() const; 155 | 156 | bool isChaperoneAlarmSoundEnabled() const; 157 | bool isChaperoneAlarmSoundLooping() const; 158 | bool isChaperoneAlarmSoundAdjustVolume() const; 159 | float chaperoneAlarmSoundDistance() const; 160 | 161 | bool isChaperoneShowDashboardEnabled() const; 162 | float chaperoneShowDashboardDistance() const; 163 | 164 | bool isChaperoneVelocityModifierEnabled() const; 165 | float chaperoneVelocityModifier() const; 166 | 167 | void reloadChaperoneProfiles(); 168 | void saveChaperoneProfiles(); 169 | 170 | Q_INVOKABLE unsigned getChaperoneProfileCount(); 171 | Q_INVOKABLE QString getChaperoneProfileName(unsigned index); 172 | 173 | float getBoundsMaxY(); 174 | 175 | public slots: 176 | void setBoundsVisibility(float value, bool notify = true); 177 | void setFadeDistance(float value, bool notify = true); 178 | void setHeight(float value, bool notify = true); 179 | void updateHeight(float value, bool notify = true); 180 | void setCenterMarker(bool value, bool notify = true); 181 | void setPlaySpaceMarker(bool value, bool notify = true); 182 | void setForceBounds(bool value, bool notify = true); 183 | 184 | void setChaperoneSwitchToBeginnerEnabled(bool value, bool notify = true); 185 | void setChaperoneSwitchToBeginnerDistance(float value, bool notify = true); 186 | 187 | void setChaperoneHapticFeedbackEnabled(bool value, bool notify = true); 188 | void setChaperoneHapticFeedbackDistance(float value, bool notify = true); 189 | 190 | void setChaperoneAlarmSoundEnabled(bool value, bool notify = true); 191 | void setChaperoneAlarmSoundLooping(bool value, bool notify = true); 192 | void setChaperoneAlarmSoundAdjustVolume(bool value, bool notify = true); 193 | void setChaperoneAlarmSoundDistance(float value, bool notify = true); 194 | 195 | void setChaperoneShowDashboardEnabled(bool value, bool notify = true); 196 | void setChaperoneShowDashboardDistance(float value, bool notify = true); 197 | 198 | void setChaperoneVelocityModifierEnabled(bool value, bool notify = true); 199 | void setChaperoneVelocityModifier(float value, bool notify = true); 200 | 201 | void flipOrientation(); 202 | void reloadFromDisk(); 203 | 204 | void addChaperoneProfile(QString name, bool includeGeometry, bool includeVisbility, bool includeFadeDistance, bool includeCenterMarker, 205 | bool includePlaySpaceMarker, bool includeFloorBounds, bool includeBoundsColor, bool includeChaperoneStyle, bool includeForceBounds, 206 | bool includesProximityWarningSettings); 207 | void applyChaperoneProfile(unsigned index); 208 | void deleteChaperoneProfile(unsigned index); 209 | 210 | void reset(); 211 | 212 | void shutdown(); 213 | 214 | signals: 215 | void boundsVisibilityChanged(float value); 216 | void fadeDistanceChanged(float value); 217 | void heightChanged(float value); 218 | void centerMarkerChanged(bool value); 219 | void playSpaceMarkerChanged(bool value); 220 | void forceBoundsChanged(bool value); 221 | 222 | void chaperoneSwitchToBeginnerEnabledChanged(bool value); 223 | void chaperoneSwitchToBeginnerDistanceChanged(float value); 224 | 225 | void chaperoneHapticFeedbackEnabledChanged(bool value); 226 | void chaperoneHapticFeedbackDistanceChanged(float value); 227 | 228 | void chaperoneAlarmSoundEnabledChanged(bool value); 229 | void chaperoneAlarmSoundLoopingChanged(bool value); 230 | void chaperoneAlarmSoundAdjustVolumeChanged(bool value); 231 | void chaperoneAlarmSoundDistanceChanged(float value); 232 | 233 | void chaperoneShowDashboardEnabledChanged(bool value); 234 | void chaperoneShowDashboardDistanceChanged(float value); 235 | 236 | void chaperoneVelocityModifierEnabledChanged(bool value); 237 | void chaperoneVelocityModifierChanged(float value); 238 | 239 | void chaperoneProfilesUpdated(); 240 | }; 241 | 242 | } // namespace advsettings 243 | -------------------------------------------------------------------------------- /src/tabcontrollers/FixFloorTabController.cpp: -------------------------------------------------------------------------------- 1 | #include "FixFloorTabController.h" 2 | #include 3 | #include "../overlaycontroller.h" 4 | 5 | // application namespace 6 | namespace advsettings { 7 | 8 | 9 | void FixFloorTabController::initStage1() { 10 | } 11 | 12 | void FixFloorTabController::initStage2(OverlayController * parent, QQuickWindow * widget) { 13 | this->parent = parent; 14 | this->widget = widget; 15 | } 16 | 17 | void FixFloorTabController::eventLoopTick(vr::TrackedDevicePose_t* devicePoses) { 18 | if (state == 1) { 19 | if (measurementCount == 0) { 20 | // Get Controller ids for left/right hand 21 | auto leftId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_LeftHand); 22 | if (leftId == vr::k_unTrackedDeviceIndexInvalid) { 23 | statusMessage = "No left controller found."; 24 | statusMessageTimeout = 2.0; 25 | emit statusMessageSignal(); 26 | emit measureEndSignal(); 27 | state = 0; 28 | return; 29 | } 30 | auto rightId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_RightHand); 31 | if (rightId == vr::k_unTrackedDeviceIndexInvalid) { 32 | statusMessage = "No right controller found."; 33 | statusMessageTimeout = 2.0; 34 | emit statusMessageSignal(); 35 | emit measureEndSignal(); 36 | state = 0; 37 | return; 38 | } 39 | // Get poses 40 | vr::TrackedDevicePose_t* leftPose = devicePoses + leftId; 41 | vr::TrackedDevicePose_t* rightPose = devicePoses + rightId; 42 | if (!leftPose->bPoseIsValid || !leftPose->bDeviceIsConnected || leftPose->eTrackingResult != vr::TrackingResult_Running_OK) { 43 | statusMessage = "Left controller tracking problems."; 44 | statusMessageTimeout = 2.0; 45 | emit statusMessageSignal(); 46 | emit measureEndSignal(); 47 | state = 0; 48 | return; 49 | } else if (!rightPose->bPoseIsValid || !rightPose->bDeviceIsConnected || rightPose->eTrackingResult != vr::TrackingResult_Running_OK) { 50 | statusMessage = "Right controller tracking problems."; 51 | statusMessageTimeout = 2.0; 52 | emit statusMessageSignal(); 53 | emit measureEndSignal(); 54 | state = 0; 55 | return; 56 | } else { 57 | // The controller with the lowest y-pos is the floor fix reference 58 | if (leftPose->mDeviceToAbsoluteTracking.m[1][3] < rightPose->mDeviceToAbsoluteTracking.m[1][3]) { 59 | referenceController = leftId; 60 | } else { 61 | referenceController = rightId; 62 | } 63 | 64 | auto& m = devicePoses[referenceController].mDeviceToAbsoluteTracking.m; 65 | tempOffsetY = (double)m[1][3]; 66 | /* 67 | | Intrinsic y-x'-z" rotation matrix: 68 | | cr*cy+sp*sr*sy | cr*sp*sy-cy*sr | cp*sy | 69 | | cp*sr | cp*cr |-sp | 70 | | cy*sp*sr-cr*sy | cr*cy*sp+sr*sy | cp*cy | 71 | 72 | yaw = atan2(cp*sy, cp*cy) [pi, -pi], CCW 73 | pitch = -asin(-sp) [pi/2, -pi/2] 74 | roll = atan2(cp*sr, cp*cr) [pi, -pi], CW 75 | */ 76 | tempRoll = std::atan2((double)m[1][0], (double)m[1][1]); 77 | measurementCount = 1; 78 | } 79 | 80 | } else { 81 | measurementCount++; 82 | auto& m = devicePoses[referenceController].mDeviceToAbsoluteTracking.m; 83 | 84 | double rollDiff = std::atan2((double)m[1][0], (double)m[1][1]) - tempRoll; 85 | if (rollDiff > M_PI) { 86 | rollDiff -= 2.0 * M_PI; 87 | } else if (rollDiff < -M_PI) { 88 | rollDiff += 2.0 * M_PI; 89 | } 90 | tempRoll += rollDiff / (double)measurementCount; 91 | if (tempRoll > M_PI) { 92 | tempRoll -= 2.0 * M_PI; 93 | } else if (tempRoll < -M_PI) { 94 | tempRoll += 2.0 * M_PI; 95 | } 96 | 97 | if (measurementCount >= 25) { 98 | if (std::abs(tempRoll) <= M_PI_2) { 99 | floorOffset = tempOffsetY - controllerUpOffsetCorrection; 100 | } else { 101 | floorOffset = tempOffsetY - controllerDownOffsetCorrection; 102 | } 103 | LOG(INFO) << "Fix Floor: Floor Offset = " << floorOffset; 104 | parent->AddOffsetToUniverseCenter(vr::TrackingUniverseStanding, 1, floorOffset, false); 105 | statusMessage = "Fixing ... OK"; 106 | statusMessageTimeout = 1.0; 107 | emit statusMessageSignal(); 108 | emit measureEndSignal(); 109 | setCanUndo(true); 110 | state = 0; 111 | } 112 | } 113 | } 114 | } 115 | 116 | QString FixFloorTabController::currentStatusMessage() { 117 | return statusMessage; 118 | } 119 | 120 | float FixFloorTabController::currentStatusMessageTimeout() { 121 | return statusMessageTimeout; 122 | } 123 | 124 | bool FixFloorTabController::canUndo() const { 125 | return m_canUndo; 126 | } 127 | 128 | void FixFloorTabController::setCanUndo(bool value, bool notify) { 129 | if (m_canUndo != value) { 130 | m_canUndo = value; 131 | if (notify) { 132 | emit canUndoChanged(m_canUndo); 133 | } 134 | } 135 | } 136 | 137 | void FixFloorTabController::fixFloorClicked() { 138 | statusMessage = "Fixing ..."; 139 | statusMessageTimeout = 1.0; 140 | emit statusMessageSignal(); 141 | emit measureStartSignal(); 142 | measurementCount = 0; 143 | state = 1; 144 | } 145 | 146 | void FixFloorTabController::undoFixFloorClicked() { 147 | parent->AddOffsetToUniverseCenter(vr::TrackingUniverseStanding, 1, -floorOffset, false); 148 | LOG(INFO) << "Fix Floor: Undo Floor Offset = " << -floorOffset; 149 | floorOffset = 0.0f; 150 | statusMessage = "Undo ... OK"; 151 | statusMessageTimeout = 1.0; 152 | emit statusMessageSignal(); 153 | setCanUndo(false); 154 | } 155 | 156 | } // namespace advconfig 157 | -------------------------------------------------------------------------------- /src/tabcontrollers/FixFloorTabController.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | class QQuickWindow; 8 | // application namespace 9 | namespace advsettings { 10 | 11 | // forward declaration 12 | class OverlayController; 13 | 14 | class FixFloorTabController : public QObject { 15 | Q_OBJECT 16 | Q_PROPERTY(bool canUndo READ canUndo WRITE setCanUndo NOTIFY canUndoChanged) 17 | 18 | private: 19 | OverlayController* parent; 20 | QQuickWindow* widget; 21 | 22 | float controllerUpOffsetCorrection = 0.062f; // Controller touchpad facing upwards 23 | float controllerDownOffsetCorrection = 0.006f; // Controller touchpad facing downwards 24 | 25 | int state = 0; // 0 .. idle, 1 .. measurement in progress 26 | vr::TrackedDeviceIndex_t referenceController = vr::k_unTrackedDeviceIndexInvalid; 27 | unsigned measurementCount = 0; 28 | double tempOffsetY = 0.0; 29 | double tempRoll = 0.0; 30 | float floorOffset = 0.0f; 31 | QString statusMessage = ""; 32 | float statusMessageTimeout = 0.0f; 33 | bool m_canUndo = false; 34 | 35 | 36 | public: 37 | void initStage1(); 38 | void initStage2(OverlayController* parent, QQuickWindow* widget); 39 | 40 | void eventLoopTick(vr::TrackedDevicePose_t* devicePoses); 41 | 42 | Q_INVOKABLE QString currentStatusMessage(); 43 | Q_INVOKABLE float currentStatusMessageTimeout(); 44 | 45 | bool canUndo() const; 46 | 47 | public slots: 48 | void fixFloorClicked(); 49 | void undoFixFloorClicked(); 50 | 51 | void setCanUndo(bool value, bool notify = true); 52 | 53 | signals: 54 | void statusMessageSignal(); 55 | void measureStartSignal(); 56 | void measureEndSignal(); 57 | void canUndoChanged(bool value); 58 | }; 59 | 60 | } // namespace advsettings 61 | -------------------------------------------------------------------------------- /src/tabcontrollers/MoveCenterTabController.cpp: -------------------------------------------------------------------------------- 1 | #include "MoveCenterTabController.h" 2 | #include 3 | #include "../overlaycontroller.h" 4 | 5 | // application namespace 6 | namespace advsettings { 7 | 8 | void MoveCenterTabController::initStage1() { 9 | setTrackingUniverse(vr::VRCompositor()->GetTrackingSpace()); 10 | auto settings = OverlayController::appSettings(); 11 | settings->beginGroup("playspaceSettings"); 12 | auto value = settings->value("adjustChaperone", m_adjustChaperone); 13 | settings->endGroup(); 14 | if (value.isValid() && !value.isNull()) { 15 | m_adjustChaperone = value.toBool(); 16 | } 17 | } 18 | 19 | void MoveCenterTabController::initStage2(OverlayController * parent, QQuickWindow * widget) { 20 | this->parent = parent; 21 | this->widget = widget; 22 | } 23 | 24 | 25 | int MoveCenterTabController::trackingUniverse() const { 26 | return (int)m_trackingUniverse; 27 | } 28 | 29 | void MoveCenterTabController::setTrackingUniverse(int value, bool notify) { 30 | if (m_trackingUniverse != value) { 31 | reset(); 32 | m_trackingUniverse = value; 33 | if (notify) { 34 | emit trackingUniverseChanged(m_trackingUniverse); 35 | } 36 | } 37 | } 38 | 39 | float MoveCenterTabController::offsetX() const { 40 | return m_offsetX; 41 | } 42 | 43 | void MoveCenterTabController::setOffsetX(float value, bool notify) { 44 | if (m_offsetX != value) { 45 | modOffsetX(value - m_offsetX, notify); 46 | } 47 | } 48 | 49 | float MoveCenterTabController::offsetY() const { 50 | return m_offsetY; 51 | } 52 | 53 | void MoveCenterTabController::setOffsetY(float value, bool notify) { 54 | if (m_offsetY != value) { 55 | modOffsetY(value - m_offsetY, notify); 56 | } 57 | } 58 | 59 | float MoveCenterTabController::offsetZ() const { 60 | return m_offsetZ; 61 | } 62 | 63 | void MoveCenterTabController::setOffsetZ(float value, bool notify) { 64 | if (m_offsetZ != value) { 65 | modOffsetZ(value - m_offsetZ, notify); 66 | } 67 | } 68 | 69 | int MoveCenterTabController::rotation() const { 70 | return m_rotation; 71 | } 72 | 73 | void MoveCenterTabController::setRotation(int value, bool notify) { 74 | if (m_rotation != value) { 75 | float angle = (value - m_rotation) * 2 * M_PI / 360.0; 76 | parent->RotateUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, angle, m_adjustChaperone); 77 | m_rotation = value; 78 | if (notify) { 79 | emit rotationChanged(m_rotation); 80 | } 81 | } 82 | } 83 | 84 | bool MoveCenterTabController::adjustChaperone() const { 85 | return m_adjustChaperone; 86 | } 87 | 88 | void MoveCenterTabController::setAdjustChaperone(bool value, bool notify) { 89 | if (m_adjustChaperone != value) { 90 | m_adjustChaperone = value; 91 | if (m_trackingUniverse == vr::TrackingUniverseStanding) { 92 | vr::VRChaperoneSetup()->RevertWorkingCopy(); 93 | float offsetdir; 94 | if (m_adjustChaperone) { 95 | offsetdir = -1.0; 96 | } else { 97 | offsetdir = 1.0; 98 | } 99 | 100 | if (m_offsetX != 0.0f) { 101 | if (m_adjustChaperone || m_rotation == 0) { 102 | parent->AddOffsetToCollisionBounds(0, offsetdir * m_offsetX, false); 103 | } else { 104 | auto angle = m_rotation * 2 * M_PI / 360.0; 105 | parent->AddOffsetToCollisionBounds(0, offsetdir * m_offsetX * std::cos(angle), false); 106 | parent->AddOffsetToCollisionBounds(2, offsetdir * m_offsetX * std::sin(angle), false); 107 | } 108 | } 109 | if (m_offsetY != 0.0f) { 110 | parent->AddOffsetToCollisionBounds(1, offsetdir * m_offsetY, false); 111 | } 112 | if (m_offsetZ != 0.0f) { 113 | if (m_adjustChaperone || m_rotation == 0) { 114 | parent->AddOffsetToCollisionBounds(2, offsetdir * m_offsetZ, false); 115 | } else { 116 | auto angle = m_rotation * 2 * M_PI / 360.0; 117 | parent->AddOffsetToCollisionBounds(2, offsetdir * m_offsetZ * std::cos(angle), false); 118 | parent->AddOffsetToCollisionBounds(0, -offsetdir * m_offsetZ * std::sin(angle), false); 119 | } 120 | } 121 | if (m_rotation != 0) { 122 | float angle = m_rotation * 2 * M_PI / 360.0; 123 | parent->RotateCollisionBounds(offsetdir * angle, false); 124 | } 125 | vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live); 126 | } 127 | auto settings = OverlayController::appSettings(); 128 | settings->beginGroup("playspaceSettings"); 129 | settings->setValue("adjustChaperone", m_adjustChaperone); 130 | settings->endGroup(); 131 | settings->sync(); 132 | if (notify) { 133 | emit adjustChaperoneChanged(m_adjustChaperone); 134 | } 135 | } 136 | } 137 | 138 | void MoveCenterTabController::modOffsetX(float value, bool notify) { 139 | if (m_rotation == 0) { 140 | parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 0, value, m_adjustChaperone); 141 | } else { 142 | auto angle = m_rotation * 2 * M_PI / 360.0; 143 | vr::VRChaperoneSetup()->RevertWorkingCopy(); 144 | parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 0, value * std::cos(angle), m_adjustChaperone, false); 145 | parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 2, value * std::sin(angle), m_adjustChaperone, false); 146 | vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live); 147 | } 148 | m_offsetX += value; 149 | if (notify) { 150 | emit offsetXChanged(m_offsetX); 151 | } 152 | } 153 | 154 | void MoveCenterTabController::modOffsetY(float value, bool notify) { 155 | parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 1, value, m_adjustChaperone); 156 | m_offsetY += value; 157 | if (notify) { 158 | emit offsetYChanged(m_offsetY); 159 | } 160 | } 161 | 162 | void MoveCenterTabController::modOffsetZ(float value, bool notify) { 163 | if (m_rotation == 0) { 164 | parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 2, value, m_adjustChaperone); 165 | } else { 166 | auto angle = m_rotation * 2 * M_PI / 360.0; 167 | vr::VRChaperoneSetup()->RevertWorkingCopy(); 168 | parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 2, value * std::cos(angle), m_adjustChaperone, false); 169 | parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 0, -value * std::sin(angle), m_adjustChaperone, false); 170 | vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live); 171 | } 172 | m_offsetZ += value; 173 | if (notify) { 174 | emit offsetZChanged(m_offsetZ); 175 | } 176 | } 177 | 178 | void MoveCenterTabController::reset() { 179 | vr::VRChaperoneSetup()->RevertWorkingCopy(); 180 | parent->RotateUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, -m_rotation * 2 * M_PI / 360.0, m_adjustChaperone, false); 181 | parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 0, -m_offsetX, m_adjustChaperone, false); 182 | parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 1, -m_offsetY, m_adjustChaperone, false); 183 | parent->AddOffsetToUniverseCenter((vr::TrackingUniverseOrigin)m_trackingUniverse, 2, -m_offsetZ, m_adjustChaperone, false); 184 | vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live); 185 | m_offsetX = 0.0f; 186 | m_offsetY = 0.0f; 187 | m_offsetZ = 0.0f; 188 | m_rotation = 0; 189 | emit offsetXChanged(m_offsetX); 190 | emit offsetYChanged(m_offsetY); 191 | emit offsetZChanged(m_offsetZ); 192 | emit rotationChanged(m_rotation); 193 | } 194 | 195 | void MoveCenterTabController::eventLoopTick(vr::ETrackingUniverseOrigin universe) { 196 | if (settingsUpdateCounter >= 50) { 197 | setTrackingUniverse((int)universe); 198 | settingsUpdateCounter = 0; 199 | } else { 200 | settingsUpdateCounter++; 201 | } 202 | } 203 | 204 | } // namespace advconfig 205 | -------------------------------------------------------------------------------- /src/tabcontrollers/MoveCenterTabController.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | class QQuickWindow; 8 | // application namespace 9 | namespace advsettings { 10 | 11 | // forward declaration 12 | class OverlayController; 13 | 14 | 15 | class MoveCenterTabController : public QObject { 16 | Q_OBJECT 17 | Q_PROPERTY(int trackingUniverse READ trackingUniverse WRITE setTrackingUniverse NOTIFY trackingUniverseChanged) 18 | Q_PROPERTY(float offsetX READ offsetX WRITE setOffsetX NOTIFY offsetXChanged) 19 | Q_PROPERTY(float offsetY READ offsetY WRITE setOffsetY NOTIFY offsetYChanged) 20 | Q_PROPERTY(float offsetZ READ offsetZ WRITE setOffsetZ NOTIFY offsetZChanged) 21 | Q_PROPERTY(int rotation READ rotation WRITE setRotation NOTIFY rotationChanged) 22 | Q_PROPERTY(bool adjustChaperone READ adjustChaperone WRITE setAdjustChaperone NOTIFY adjustChaperoneChanged) 23 | 24 | private: 25 | OverlayController* parent; 26 | QQuickWindow* widget; 27 | 28 | int m_trackingUniverse = (int)vr::TrackingUniverseStanding; 29 | float m_offsetX = 0.0f; 30 | float m_offsetY = 0.0f; 31 | float m_offsetZ = 0.0f; 32 | int m_rotation = 0; 33 | bool m_adjustChaperone = true; 34 | 35 | unsigned settingsUpdateCounter = 0; 36 | 37 | public: 38 | void initStage1(); 39 | void initStage2(OverlayController* parent, QQuickWindow* widget); 40 | 41 | void eventLoopTick(vr::ETrackingUniverseOrigin universe); 42 | 43 | float offsetX() const; 44 | float offsetY() const; 45 | float offsetZ() const; 46 | int rotation() const; 47 | bool adjustChaperone() const; 48 | 49 | public slots: 50 | int trackingUniverse() const; 51 | void setTrackingUniverse(int value, bool notify = true); 52 | 53 | void setOffsetX(float value, bool notify = true); 54 | void setOffsetY(float value, bool notify = true); 55 | void setOffsetZ(float value, bool notify = true); 56 | 57 | void setRotation(int value, bool notify = true); 58 | 59 | void setAdjustChaperone(bool value, bool notify = true); 60 | 61 | void modOffsetX(float value, bool notify = true); 62 | void modOffsetY(float value, bool notify = true); 63 | void modOffsetZ(float value, bool notify = true); 64 | void reset(); 65 | 66 | signals: 67 | void trackingUniverseChanged(int value); 68 | void offsetXChanged(float value); 69 | void offsetYChanged(float value); 70 | void offsetZChanged(float value); 71 | void rotationChanged(int value); 72 | void adjustChaperoneChanged(bool value); 73 | }; 74 | 75 | } // namespace advsettings 76 | -------------------------------------------------------------------------------- /src/tabcontrollers/PttController.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class QQuickWindow; 12 | // application namespace 13 | namespace advsettings { 14 | 15 | // forward declaration 16 | class OverlayController; 17 | 18 | enum TouchPadArea { 19 | PAD_AREA_LEFT = (1 << 0), 20 | PAD_AREA_TOP = (1 << 1), 21 | PAD_AREA_RIGHT = (1 << 2), 22 | PAD_AREA_BOTTOM = (1 << 3), 23 | }; 24 | 25 | struct PttControllerConfig { 26 | QVariantList digitalButtons; 27 | uint64_t digitalButtonMask = 0; 28 | unsigned triggerMode = 0; // 0 .. disabled, 1 .. enabled 29 | unsigned touchpadMode = 0; // 0 .. disabled, 1 .. only touch, 2 .. only press, 3 .. both 30 | unsigned touchpadAreas = 0; 31 | }; 32 | 33 | struct PttProfile { 34 | std::string profileName; 35 | 36 | bool showNotification = false; 37 | bool leftControllerEnabled = false; 38 | bool rightControllerEnabled = false; 39 | PttControllerConfig controllerConfigs[2]; 40 | }; 41 | 42 | 43 | class PttController : public QObject { 44 | Q_OBJECT 45 | Q_PROPERTY(bool pttEnabled READ pttEnabled WRITE setPttEnabled NOTIFY pttEnabledChanged) 46 | Q_PROPERTY(bool pttActive READ pttActive NOTIFY pttActiveChanged) 47 | Q_PROPERTY(bool pttShowNotification READ pttShowNotification WRITE setPttShowNotification NOTIFY pttShowNotificationChanged) 48 | Q_PROPERTY(bool pttLeftControllerEnabled READ pttLeftControllerEnabled WRITE setPttLeftControllerEnabled NOTIFY pttLeftControllerEnabledChanged) 49 | Q_PROPERTY(bool pttRightControllerEnabled READ pttRightControllerEnabled WRITE setPttRightControllerEnabled NOTIFY pttRightControllerEnabledChanged) 50 | 51 | protected: 52 | bool m_pttEnabled = false; 53 | bool m_pttActive = false; 54 | bool m_pttShowNotification = false; 55 | bool m_pttLeftControllerEnabled = false; 56 | bool m_pttRightControllerEnabled = false; 57 | PttControllerConfig m_pttControllerConfigs[2]; 58 | 59 | std::vector pttProfiles; 60 | 61 | protected: 62 | void checkPttStatus(); 63 | virtual QString getSettingsName() = 0; 64 | virtual void onPttStart() {}; 65 | virtual void onPttStop() {}; 66 | virtual void onPttEnabled() {}; 67 | virtual void onPttDisabled() {}; 68 | virtual bool pttChangeValid() { return true; } 69 | virtual vr::VROverlayHandle_t getNotificationOverlayHandle() { return vr::k_ulOverlayHandleInvalid; } 70 | std::recursive_mutex eventLoopMutex; 71 | 72 | public: 73 | bool pttEnabled() const; 74 | bool pttActive() const; 75 | bool pttShowNotification() const; 76 | bool pttLeftControllerEnabled() const; 77 | bool pttRightControllerEnabled() const; 78 | 79 | void startPtt(); 80 | void stopPtt(); 81 | 82 | void reloadPttProfiles(); 83 | void reloadPttConfig(); 84 | void savePttProfiles(); 85 | void savePttConfig(); 86 | 87 | 88 | Q_INVOKABLE QVariantList pttDigitalButtons(unsigned controller); 89 | Q_INVOKABLE unsigned long pttDigitalButtonMask(unsigned controller); 90 | Q_INVOKABLE unsigned pttTouchpadMode(unsigned controller); 91 | Q_INVOKABLE unsigned pttTriggerMode(unsigned controller); 92 | Q_INVOKABLE unsigned pttTouchpadArea(unsigned controller); 93 | 94 | Q_INVOKABLE unsigned getPttProfileCount(); 95 | Q_INVOKABLE QString getPttProfileName(unsigned index); 96 | 97 | public slots: 98 | void setPttEnabled(bool value, bool notify = true, bool save = true); 99 | void setPttShowNotification(bool value, bool notify = true, bool save = true); 100 | void setPttLeftControllerEnabled(bool value, bool notify = true, bool save = true); 101 | void setPttRightControllerEnabled(bool value, bool notify = true, bool save = true); 102 | 103 | void setPttControllerConfig(unsigned controller, QVariantList buttons, unsigned triggerMode, unsigned padMode, unsigned padAreas); 104 | 105 | void addPttProfile(QString name); 106 | void applyPttProfile(unsigned index); 107 | void deletePttProfile(unsigned index); 108 | 109 | signals: 110 | void pttEnabledChanged(bool value); 111 | void pttActiveChanged(bool value); 112 | void pttShowNotificationChanged(bool value); 113 | void pttLeftControllerEnabledChanged(bool value); 114 | void pttRightControllerEnabledChanged(bool value); 115 | 116 | void pttProfilesUpdated(); 117 | }; 118 | 119 | } // namespace advsettings 120 | -------------------------------------------------------------------------------- /src/tabcontrollers/ReviveTabController.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | 6 | class QQuickWindow; 7 | // application namespace 8 | namespace advsettings { 9 | 10 | 11 | // forward declaration 12 | class OverlayController; 13 | 14 | 15 | struct ReviveControllerProfile { 16 | std::string profileName; 17 | int gripButtonMode; 18 | bool triggerAsGrip; 19 | float thumbDeadzone; 20 | float thumbRange; 21 | float touchPitch; 22 | float touchYaw; 23 | float touchRoll; 24 | float touchX; 25 | float touchY; 26 | float touchZ; 27 | }; 28 | 29 | 30 | class ReviveTabController : public QObject { 31 | Q_OBJECT 32 | Q_PROPERTY(int isOverlayInstalled READ isOverlayInstalled NOTIFY isOverlayInstalledChanged) 33 | Q_PROPERTY(int gripButtonMode READ gripButtonMode WRITE setGripButtonMode NOTIFY gripButtonModeChanged) 34 | Q_PROPERTY(int triggerAsGrip READ triggerAsGrip WRITE setTriggerAsGrip NOTIFY triggerAsGripChanged) 35 | Q_PROPERTY(bool pixelsPerDisplayPixelOverrideEnabled READ isPixelsPerDisplayPixelOverrideEnabled WRITE setPixelsPerDisplayPixelOverrideEnabled NOTIFY pixelsPerDisplayPixelOverrideEnabledChanged) 36 | Q_PROPERTY(float toggleDelay READ toggleDelay WRITE setToggleDelay NOTIFY toggleDelayChanged) 37 | Q_PROPERTY(float pixelsPerDisplayPixelOverride READ pixelsPerDisplayPixelOverride WRITE setPixelsPerDisplayPixelOverride NOTIFY pixelsPerDisplayPixelOverrideChanged) 38 | Q_PROPERTY(float thumbDeadzone READ thumbDeadzone WRITE setThumbDeadzone NOTIFY thumbDeadzoneChanged) 39 | Q_PROPERTY(float thumbRange READ thumbRange WRITE setThumbRange NOTIFY thumbRangeChanged) 40 | Q_PROPERTY(float touchPitch READ touchPitch WRITE setTouchPitch NOTIFY touchPitchChanged) 41 | Q_PROPERTY(float touchYaw READ touchYaw WRITE setTouchYaw NOTIFY touchYawChanged) 42 | Q_PROPERTY(float touchRoll READ touchRoll WRITE setTouchRoll NOTIFY touchRollChanged) 43 | Q_PROPERTY(float touchX READ touchX WRITE setTouchX NOTIFY touchXChanged) 44 | Q_PROPERTY(float touchY READ touchY WRITE setTouchY NOTIFY touchYChanged) 45 | Q_PROPERTY(float touchZ READ touchZ WRITE setTouchZ NOTIFY touchZChanged) 46 | Q_PROPERTY(float piPlayerHeight READ piPlayerHeight WRITE setPiPlayerHeight NOTIFY piPlayerHeightChanged) 47 | Q_PROPERTY(float piEyeHeight READ piEyeHeight WRITE setPiEyeHeight NOTIFY piEyeHeightChanged) 48 | Q_PROPERTY(QString piUsername READ piUsername WRITE setPiUsername NOTIFY piUsernameChanged) 49 | Q_PROPERTY(QString piName READ piName WRITE setPiName NOTIFY piNameChanged) 50 | Q_PROPERTY(int piGender READ piGender WRITE setPiGender NOTIFY piGenderChanged) 51 | 52 | private: 53 | OverlayController* parent; 54 | QQuickWindow* widget; 55 | 56 | bool m_isOverlayInstalled = false; 57 | int m_gripButtonMode = 0; 58 | float m_toggleDelay = 0.5f; 59 | bool m_triggerAsGrip = false; 60 | bool m_pixelsPerDisplayPixelOverrideEnabled = false; 61 | float m_pixelsPerDisplayPixelOverride = 1.0f; 62 | float m_thumbDeadzone = 0.3f; 63 | float m_thumbRange = 2.0f; 64 | float m_touchPitch = -28.0f; 65 | float m_touchYaw = 0.0f; 66 | float m_touchRoll = -14.0f; 67 | float m_touchX = 0.016f; 68 | float m_touchY = -0.036f; 69 | float m_touchZ = 0.016f; 70 | float m_piPlayerHeight = 1.778f; 71 | float m_piEyeHeight = 1.675f; 72 | QString m_piUsername = ""; 73 | QString m_piName = ""; 74 | int m_piGender = 0; // 0 .. Unknown, 1 .. Male, 2 .. Female 75 | 76 | unsigned settingsUpdateCounter = 0; 77 | 78 | std::vector controllerProfiles; 79 | 80 | public: 81 | void initStage1(bool forceRevivePage); 82 | void initStage2(OverlayController* parent, QQuickWindow* widget); 83 | 84 | void eventLoopTick(); 85 | 86 | bool isOverlayInstalled() const; 87 | 88 | int gripButtonMode() const; 89 | bool triggerAsGrip() const; 90 | float toggleDelay() const; 91 | 92 | bool isPixelsPerDisplayPixelOverrideEnabled() const; 93 | float pixelsPerDisplayPixelOverride() const; 94 | 95 | float thumbDeadzone() const; 96 | float thumbRange() const; 97 | 98 | float touchPitch() const; 99 | float touchYaw() const; 100 | float touchRoll() const; 101 | float touchX() const; 102 | float touchY() const; 103 | float touchZ() const; 104 | 105 | float piPlayerHeight() const; 106 | float piEyeHeight() const; 107 | const QString& piUsername() const; 108 | const QString& piName() const; 109 | int piGender() const; // 0 .. Unknown, 1 .. Male, 2 .. Female 110 | 111 | Q_INVOKABLE float getCurrentHMDHeight(); 112 | 113 | void reloadControllerProfiles(); 114 | void saveControllerProfiles(); 115 | 116 | Q_INVOKABLE unsigned getControllerProfileCount(); 117 | Q_INVOKABLE QString getControllerProfileName(unsigned index); 118 | 119 | public slots: 120 | void setGripButtonMode(int value, bool notify = true); 121 | void setTriggerAsGrip(bool value, bool notify = true); 122 | void setToggleDelay(float value, bool notify = true); 123 | 124 | void setPixelsPerDisplayPixelOverrideEnabled(bool value, bool notify = true); 125 | void setPixelsPerDisplayPixelOverride(float value, bool notify = true); 126 | 127 | void setThumbDeadzone(float value, bool notify = true); 128 | void setThumbRange(float value, bool notify = true); 129 | 130 | void setTouchPitch(float value, bool notify = true); 131 | void setTouchYaw(float value, bool notify = true); 132 | void setTouchRoll(float value, bool notify = true); 133 | void setTouchX(float value, bool notify = true); 134 | void setTouchY(float value, bool notify = true); 135 | void setTouchZ(float value, bool notify = true); 136 | 137 | void setPiPlayerHeight(float value, bool notify = true); 138 | void setPiEyeHeight(float value, bool notify = true); 139 | void setPiUsername(const QString& value, bool notify = true); 140 | void setPiName(const QString& value, bool notify = true); 141 | void setPiGender(int value, bool notify = true); // 0 .. Unknown, 1 .. Male, 2 .. Female 142 | 143 | void addControllerProfile(QString name); 144 | void applyControllerProfile(unsigned index); 145 | void deleteControllerProfile(unsigned index); 146 | 147 | void reset(); 148 | 149 | signals: 150 | void isOverlayInstalledChanged(bool value); 151 | 152 | void gripButtonModeChanged(int value); 153 | void triggerAsGripChanged(bool value); 154 | void toggleDelayChanged(float value); 155 | 156 | void pixelsPerDisplayPixelOverrideEnabledChanged(bool value); 157 | void pixelsPerDisplayPixelOverrideChanged(float value); 158 | 159 | void thumbDeadzoneChanged(float value); 160 | void thumbRangeChanged(float value); 161 | 162 | void touchPitchChanged(float value); 163 | void touchYawChanged(float value); 164 | void touchRollChanged(float value); 165 | void touchXChanged(float value); 166 | void touchYChanged(float value); 167 | void touchZChanged(float value); 168 | 169 | void piPlayerHeightChanged(float value); 170 | void piEyeHeightChanged(float value); 171 | void piUsernameChanged(const QString& value); 172 | void piNameChanged(const QString& value); 173 | void piGenderChanged(int value); 174 | 175 | void controllerProfilesUpdated(); 176 | }; 177 | 178 | } // namespace advsettings 179 | -------------------------------------------------------------------------------- /src/tabcontrollers/SettingsTabController.cpp: -------------------------------------------------------------------------------- 1 | #include "SettingsTabController.h" 2 | #include 3 | #include "../overlaycontroller.h" 4 | 5 | // application namespace 6 | namespace advsettings { 7 | 8 | 9 | void SettingsTabController::initStage1() { 10 | m_autoStartEnabled = vr::VRApplications()->GetApplicationAutoLaunch(OverlayController::applicationKey); 11 | auto settings = OverlayController::appSettings(); 12 | settings->beginGroup("applicationSettings"); 13 | auto value = settings->value("forceRevivePage", m_forceRevivePage); 14 | settings->endGroup(); 15 | if (value.isValid() && !value.isNull()) { 16 | m_forceRevivePage = value.toBool(); 17 | } 18 | } 19 | 20 | void SettingsTabController::initStage2(OverlayController * parent, QQuickWindow * widget) { 21 | this->parent = parent; 22 | this->widget = widget; 23 | } 24 | 25 | void SettingsTabController::eventLoopTick() { 26 | if (settingsUpdateCounter >= 50) { 27 | setAutoStartEnabled(vr::VRApplications()->GetApplicationAutoLaunch(OverlayController::applicationKey)); 28 | settingsUpdateCounter = 0; 29 | } else { 30 | settingsUpdateCounter++; 31 | } 32 | } 33 | 34 | bool SettingsTabController::autoStartEnabled() const { 35 | return m_autoStartEnabled; 36 | } 37 | 38 | void SettingsTabController::setAutoStartEnabled(bool value, bool notify) { 39 | if (m_autoStartEnabled != value) { 40 | m_autoStartEnabled = value; 41 | auto apperror = vr::VRApplications()->SetApplicationAutoLaunch(OverlayController::applicationKey, m_autoStartEnabled); 42 | if (apperror != vr::VRApplicationError_None) { 43 | LOG(ERROR) << "Could not set auto start: " << vr::VRApplications()->GetApplicationsErrorNameFromEnum(apperror); 44 | } 45 | if (notify) { 46 | emit autoStartEnabledChanged(m_autoStartEnabled); 47 | } 48 | } 49 | } 50 | 51 | 52 | bool SettingsTabController::forceRevivePage() const { 53 | return m_forceRevivePage; 54 | } 55 | 56 | 57 | void SettingsTabController::setForceRevivePage(bool value, bool notify) { 58 | if (m_forceRevivePage != value) { 59 | m_forceRevivePage = value; 60 | auto settings = OverlayController::appSettings(); 61 | settings->beginGroup("applicationSettings"); 62 | settings->setValue("forceRevivePage", m_forceRevivePage); 63 | settings->endGroup(); 64 | settings->sync(); 65 | if (notify) { 66 | emit forceRevivePageChanged(m_forceRevivePage); 67 | } 68 | } 69 | } 70 | 71 | } // namespace advconfig 72 | -------------------------------------------------------------------------------- /src/tabcontrollers/SettingsTabController.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | 6 | class QQuickWindow; 7 | // application namespace 8 | namespace advsettings { 9 | 10 | // forward declaration 11 | class OverlayController; 12 | 13 | 14 | class SettingsTabController : public QObject { 15 | Q_OBJECT 16 | Q_PROPERTY(bool autoStartEnabled READ autoStartEnabled WRITE setAutoStartEnabled NOTIFY autoStartEnabledChanged) 17 | Q_PROPERTY(bool forceRevivePage READ forceRevivePage WRITE setForceRevivePage NOTIFY forceRevivePageChanged) 18 | 19 | private: 20 | OverlayController* parent; 21 | QQuickWindow* widget; 22 | 23 | unsigned settingsUpdateCounter = 0; 24 | 25 | bool m_autoStartEnabled = false; 26 | bool m_forceRevivePage = false; 27 | 28 | public: 29 | void initStage1(); 30 | void initStage2(OverlayController* parent, QQuickWindow* widget); 31 | 32 | void eventLoopTick(); 33 | 34 | bool autoStartEnabled() const; 35 | bool forceRevivePage() const; 36 | 37 | public slots: 38 | void setAutoStartEnabled(bool value, bool notify = true); 39 | void setForceRevivePage(bool value, bool notify = true); 40 | 41 | signals: 42 | void autoStartEnabledChanged(bool value); 43 | void forceRevivePageChanged(bool value); 44 | }; 45 | 46 | } // namespace advsettings 47 | -------------------------------------------------------------------------------- /src/tabcontrollers/StatisticsTabController.cpp: -------------------------------------------------------------------------------- 1 | #include "StatisticsTabController.h" 2 | #include 3 | #include "../overlaycontroller.h" 4 | 5 | // application namespace 6 | namespace advsettings { 7 | 8 | void StatisticsTabController::initStage1() { 9 | } 10 | 11 | void StatisticsTabController::initStage2(OverlayController * parent, QQuickWindow * widget) { 12 | this->parent = parent; 13 | this->widget = widget; 14 | } 15 | 16 | void StatisticsTabController::eventLoopTick(vr::TrackedDevicePose_t* devicePoses, float leftSpeed, float rightSpeed) { 17 | vr::Compositor_CumulativeStats pStats; 18 | vr::VRCompositor()->GetCumulativeStats(&pStats, sizeof(vr::Compositor_CumulativeStats)); 19 | if (pStats.m_nPid != m_cumStats.m_nPid) { 20 | m_cumStats = pStats; 21 | m_droppedFramesOffset = 0; 22 | m_reprojectedFramesOffset = 0; 23 | m_timedOutOffset = 0; 24 | m_totalRatioPresentedOffset = 0; 25 | m_totalRatioReprojectedOffset = 0; 26 | } 27 | m_cumStats = pStats; 28 | 29 | auto& m = devicePoses->mDeviceToAbsoluteTracking.m; 30 | 31 | // Hmd Distance // 32 | if (lastPosTimer == 0) { 33 | if (devicePoses[0].bPoseIsValid && devicePoses[0].eTrackingResult == vr::TrackingResult_Running_OK) { 34 | if (!lastHmdPosValid) { 35 | lastHmdPosValid = true; 36 | } else { 37 | auto delta = std::sqrt(std::pow(m[0][3] - lastHmdPos[0], 2) /*+ std::pow(m[1][3] - lastHmdPos[1], 2)*/ + std::pow(m[2][3] - lastHmdPos[2], 2)); 38 | if (delta >= 0.01f) { 39 | m_hmdDistanceMoved += delta; 40 | } 41 | } 42 | lastHmdPos[0] = m[0][3]; 43 | lastHmdPos[1] = m[1][3]; 44 | lastHmdPos[2] = m[2][3]; 45 | } else { 46 | lastHmdPosValid = false; 47 | } 48 | } 49 | 50 | // Controller speeds // 51 | if (leftSpeed > m_leftControllerMaxSpeed) { 52 | m_leftControllerMaxSpeed = leftSpeed; 53 | } 54 | if (rightSpeed > m_rightControllerMaxSpeed) { 55 | m_rightControllerMaxSpeed = rightSpeed; 56 | } 57 | 58 | // Hmd Rotation // 59 | /* 60 | | Intrinsic y-x'-z" rotation matrix: 61 | | cr*cy+sp*sr*sy | cr*sp*sy-cy*sr | cp*sy | 62 | | cp*sr | cp*cr |-sp | 63 | | cy*sp*sr-cr*sy | cr*cy*sp+sr*sy | cp*cy | 64 | 65 | yaw = atan2(cp*sy, cp*cy) [pi, -pi], CCW 66 | pitch = -asin(-sp) [pi/2, -pi/2] 67 | roll = atan2(cp*sr, cp*cr) [pi, -pi], CW 68 | */ 69 | 70 | double yawRaw = 0.0; 71 | double yaw = 0.0; 72 | bool rotationChanged = false; 73 | if (devicePoses[0].bPoseIsValid && devicePoses[0].eTrackingResult == vr::TrackingResult_Running_OK) { 74 | yawRaw = std::atan2(m[0][2], m[2][2]); 75 | if (yawRaw < 0.0f) { 76 | yawRaw += 2 * M_PI; // map to [0, 2*pi], CCW 77 | } 78 | yaw = yawRaw - rotationOffset; 79 | if (yaw < 0.0) { 80 | yaw = 2 * M_PI + yaw; 81 | } 82 | if (rotationResetFlag) { 83 | rotationDir = 0; 84 | rotationCounter = 0; 85 | rotationOffset = yawRaw; 86 | rotationResetFlag = false; 87 | lastYaw = -1.0f; 88 | rotationChanged = true; 89 | } else if (lastYaw < 0.0f && yaw > 0.0) { 90 | lastYaw = yaw; 91 | rotationChanged = true; 92 | if (yaw <= M_PI) { 93 | rotationDir = 1; 94 | } else { 95 | rotationDir = -1; 96 | } 97 | } else if (std::abs(lastYaw - yaw) >= 0.01 && yaw > 0.0) { 98 | auto diff = yaw - lastYaw; 99 | int mode = 0; 100 | if (std::abs(diff) > M_PI) { 101 | if (diff < -M_PI) { // CCW overflow 102 | mode = 1; 103 | } else if (diff > M_PI) { // CW overflow 104 | mode = -1; 105 | } 106 | } else { 107 | if (lastYaw < 0.0 && yaw > 0.0) { 108 | mode = 1; 109 | } else if (lastYaw > 0.0 && yaw < 0.0) { 110 | mode = -1; 111 | } 112 | } 113 | if (mode > 0) { 114 | if (rotationCounter == 0 && rotationDir <= 0) { 115 | rotationDir = 1; 116 | } else { 117 | rotationCounter++; 118 | } 119 | } else if (mode < 0) { 120 | if (rotationCounter == 0 && rotationDir >= 0) { 121 | rotationDir = -1; 122 | } else { 123 | rotationCounter--; 124 | } 125 | } 126 | lastYaw = yaw; 127 | rotationChanged = true; 128 | } 129 | } else { 130 | lastYaw = -1; 131 | } 132 | 133 | if (rotationChanged) { 134 | m_hmdRotation = (float)rotationCounter; 135 | if (rotationDir > 0) { 136 | m_hmdRotation += yaw / (2 * M_PI); 137 | } else if (rotationDir < 0) { 138 | m_hmdRotation += -1.0f + yaw / (2 * M_PI); 139 | } 140 | } 141 | if (lastPosTimer == 0) { 142 | lastPosTimer = 10; 143 | } else { 144 | lastPosTimer--; 145 | } 146 | } 147 | 148 | float StatisticsTabController::hmdDistanceMoved() const { 149 | return m_hmdDistanceMoved; 150 | } 151 | 152 | float StatisticsTabController::hmdRotations() const { 153 | return m_hmdRotation; 154 | } 155 | 156 | float StatisticsTabController::rightControllerMaxSpeed() const { 157 | return m_rightControllerMaxSpeed; 158 | } 159 | 160 | float StatisticsTabController::leftControllerMaxSpeed() const { 161 | return m_leftControllerMaxSpeed; 162 | } 163 | 164 | unsigned StatisticsTabController::presentedFrames() const { 165 | return m_cumStats.m_nNumFramePresents - m_presentedFramesOffset; 166 | } 167 | 168 | unsigned StatisticsTabController::droppedFrames() const { 169 | return m_cumStats.m_nNumDroppedFrames - m_droppedFramesOffset; 170 | } 171 | 172 | unsigned StatisticsTabController::reprojectedFrames() const { 173 | return m_cumStats.m_nNumReprojectedFrames - m_reprojectedFramesOffset; 174 | } 175 | 176 | unsigned StatisticsTabController::timedOut() const { 177 | return m_cumStats.m_nNumTimedOut - m_timedOutOffset; 178 | } 179 | 180 | float StatisticsTabController::totalReprojectedRatio() const { 181 | float totalFrames = (float)(m_cumStats.m_nNumFramePresents - m_totalRatioPresentedOffset); 182 | float reprojectedFrames = (float)(m_cumStats.m_nNumReprojectedFrames - m_totalRatioReprojectedOffset); 183 | if (totalFrames != 0.0f) { 184 | return reprojectedFrames / totalFrames; 185 | } else { 186 | return 0.0; 187 | } 188 | } 189 | 190 | void StatisticsTabController::statsDistanceResetClicked() { 191 | lastHmdPosValid = false; 192 | if (m_hmdDistanceMoved != 0.0) { 193 | m_hmdDistanceMoved = 0.0; 194 | } 195 | } 196 | 197 | void StatisticsTabController::statsRotationResetClicked() { 198 | rotationResetFlag = true; 199 | } 200 | 201 | void StatisticsTabController::statsLeftControllerSpeedResetClicked() { 202 | if (m_leftControllerMaxSpeed != 0.0) { 203 | m_leftControllerMaxSpeed = 0.0; 204 | } 205 | } 206 | 207 | void StatisticsTabController::statsRightControllerSpeedResetClicked() { 208 | if (m_rightControllerMaxSpeed != 0.0) { 209 | m_rightControllerMaxSpeed = 0.0; 210 | } 211 | } 212 | 213 | void StatisticsTabController::presentedFramesResetClicked() { 214 | m_presentedFramesOffset = m_cumStats.m_nNumFramePresents; 215 | } 216 | 217 | void StatisticsTabController::droppedFramesResetClicked() { 218 | m_droppedFramesOffset = m_cumStats.m_nNumDroppedFrames; 219 | } 220 | 221 | void StatisticsTabController::reprojectedFramesResetClicked() { 222 | m_reprojectedFramesOffset = m_cumStats.m_nNumReprojectedFrames; 223 | } 224 | 225 | void StatisticsTabController::timedOutResetClicked() { 226 | m_timedOutOffset = m_cumStats.m_nNumTimedOut; 227 | } 228 | 229 | void StatisticsTabController::totalRatioResetClicked() { 230 | m_totalRatioPresentedOffset = m_cumStats.m_nNumFramePresents; 231 | m_totalRatioReprojectedOffset = m_cumStats.m_nNumReprojectedFrames; 232 | } 233 | 234 | } // namespace advconfig 235 | -------------------------------------------------------------------------------- /src/tabcontrollers/StatisticsTabController.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | class QQuickWindow; 8 | // application namespace 9 | namespace advsettings { 10 | 11 | // forward declaration 12 | class OverlayController; 13 | 14 | 15 | class StatisticsTabController : public QObject { 16 | Q_OBJECT 17 | Q_PROPERTY(float hmdDistanceMoved READ hmdDistanceMoved) 18 | Q_PROPERTY(float hmdRotations READ hmdRotations) 19 | Q_PROPERTY(float leftControllerMaxSpeed READ leftControllerMaxSpeed) 20 | Q_PROPERTY(float rightControllerMaxSpeed READ rightControllerMaxSpeed) 21 | Q_PROPERTY(int presentedFrames READ presentedFrames) 22 | Q_PROPERTY(int droppedFrames READ droppedFrames) 23 | Q_PROPERTY(int reprojectedFrames READ reprojectedFrames) 24 | Q_PROPERTY(int timedOut READ timedOut) 25 | Q_PROPERTY(float totalReprojectedRatio READ totalReprojectedRatio) 26 | 27 | private: 28 | OverlayController* parent; 29 | QQuickWindow* widget; 30 | 31 | bool rotationResetFlag = false; 32 | float rotationOffset = 0.0f; 33 | int rotationDir = 0; 34 | int64_t rotationCounter = 0; 35 | float lastYaw = -1.0f; 36 | unsigned lastPosTimer = 0; 37 | float lastHmdPos[3]; 38 | bool lastHmdPosValid = false; 39 | 40 | float m_hmdRotation = 0.0f; 41 | double m_hmdDistanceMoved = 0.0; 42 | 43 | float m_leftControllerMaxSpeed = 0.0f; 44 | float m_rightControllerMaxSpeed = 0.0f; 45 | 46 | vr::Compositor_CumulativeStats m_cumStats; 47 | unsigned m_presentedFramesOffset = 0; 48 | unsigned m_droppedFramesOffset = 0; 49 | unsigned m_reprojectedFramesOffset = 0; 50 | unsigned m_timedOutOffset = 0; 51 | unsigned m_totalRatioPresentedOffset = 0; 52 | unsigned m_totalRatioReprojectedOffset = 0; 53 | 54 | public: 55 | void initStage1(); 56 | void initStage2(OverlayController* parent, QQuickWindow* widget); 57 | 58 | void eventLoopTick(vr::TrackedDevicePose_t* devicePoses, float leftSpeed, float rightSpeed); 59 | 60 | float hmdDistanceMoved() const; 61 | float hmdRotations() const; 62 | float rightControllerMaxSpeed() const; 63 | float leftControllerMaxSpeed() const; 64 | 65 | unsigned presentedFrames() const; 66 | unsigned droppedFrames() const; 67 | unsigned reprojectedFrames() const; 68 | unsigned timedOut() const; 69 | float totalReprojectedRatio() const; 70 | 71 | public slots: 72 | void statsDistanceResetClicked(); 73 | void statsRotationResetClicked(); 74 | void statsLeftControllerSpeedResetClicked(); 75 | void statsRightControllerSpeedResetClicked(); 76 | void presentedFramesResetClicked(); 77 | void droppedFramesResetClicked(); 78 | void reprojectedFramesResetClicked(); 79 | void timedOutResetClicked(); 80 | void totalRatioResetClicked(); 81 | }; 82 | 83 | 84 | } // namespace advsettings 85 | -------------------------------------------------------------------------------- /src/tabcontrollers/SteamVRTabController.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | 6 | // openvr's github repo hasn't been updated yet to reflect changes in beta 1477423729. 7 | //static const char* vrsettings_steamvr_allowAsyncReprojection = "allowAsyncReprojection"; 8 | //static const char* vrsettings_steamvr_allowInterleavedReprojection = "allowInterleavedReprojection"; 9 | static const char* vrsettings_compositor_category = "compositor"; 10 | static const char* vrsettings_steamvr_supersampleScale = "supersampleScale"; 11 | static const char* vrsettings_steamvr_allowSupersampleFiltering = "allowSupersampleFiltering"; 12 | 13 | 14 | class QQuickWindow; 15 | // application namespace 16 | namespace advsettings { 17 | 18 | // forward declaration 19 | class OverlayController; 20 | 21 | 22 | struct SteamVRProfile { 23 | std::string profileName; 24 | 25 | bool includesSupersampling = false; 26 | float supersampling = 1.0f; 27 | 28 | bool includesSupersampleFiltering = false; 29 | bool supersampleFiltering = false; 30 | 31 | bool includesReprojectionSettings = false; 32 | bool asynchronousReprojection = true; 33 | bool interleavedReprojection = true; 34 | bool alwaysOnReprojection = true; 35 | }; 36 | 37 | 38 | class SteamVRTabController : public QObject { 39 | Q_OBJECT 40 | Q_PROPERTY(float superSampling READ superSampling WRITE setSuperSampling NOTIFY superSamplingChanged) 41 | Q_PROPERTY(float compositorSuperSampling READ compositorSuperSampling WRITE setCompositorSuperSampling NOTIFY compositorSuperSamplingChanged) 42 | Q_PROPERTY(bool allowInterleavedReprojection READ allowInterleavedReprojection WRITE setAllowInterleavedReprojection NOTIFY allowInterleavedReprojectionChanged) 43 | Q_PROPERTY(bool allowAsyncReprojection READ allowAsyncReprojection WRITE setAllowAsyncReprojection NOTIFY allowAsyncReprojectionChanged) 44 | Q_PROPERTY(bool forceReprojection READ forceReprojection WRITE setForceReprojection NOTIFY forceReprojectionChanged) 45 | Q_PROPERTY(bool allowSupersampleFiltering READ allowSupersampleFiltering WRITE setAllowSupersampleFiltering NOTIFY allowSupersampleFilteringChanged) 46 | 47 | private: 48 | OverlayController* parent; 49 | QQuickWindow* widget; 50 | 51 | float m_superSampling = 1.0; 52 | float m_compositorSuperSampling = 1.0; 53 | bool m_allowInterleavedReprojection = true; 54 | bool m_allowAsyncReprojection = true; 55 | bool m_forceReprojection = false; 56 | bool m_allowSupersampleFiltering = true; 57 | 58 | std::vector steamvrProfiles; 59 | 60 | unsigned settingsUpdateCounter = 0; 61 | 62 | public: 63 | void initStage1(); 64 | void initStage2(OverlayController* parent, QQuickWindow* widget); 65 | 66 | void eventLoopTick(); 67 | 68 | float superSampling() const; 69 | float compositorSuperSampling() const; 70 | bool allowInterleavedReprojection() const; 71 | bool allowAsyncReprojection() const; 72 | bool forceReprojection() const; 73 | bool allowSupersampleFiltering() const; 74 | 75 | void reloadSteamVRProfiles(); 76 | void saveSteamVRProfiles(); 77 | 78 | Q_INVOKABLE unsigned getSteamVRProfileCount(); 79 | Q_INVOKABLE QString getSteamVRProfileName(unsigned index); 80 | 81 | public slots: 82 | void setSuperSampling(float value, bool notify = true); 83 | void setCompositorSuperSampling(float value, bool notify = true); 84 | void setAllowInterleavedReprojection(bool value, bool notify = true); 85 | void setAllowAsyncReprojection(bool value, bool notify = true); 86 | void setForceReprojection(bool value, bool notify = true); 87 | void setAllowSupersampleFiltering(bool value, bool notify = true); 88 | 89 | void addSteamVRProfile(QString name, bool includeSupersampling, bool includeSupersampleFiltering, bool includeReprojectionSettings); 90 | void applySteamVRProfile(unsigned index); 91 | void deleteSteamVRProfile(unsigned index); 92 | 93 | void reset(); 94 | void restartSteamVR(); 95 | 96 | signals: 97 | void superSamplingChanged(float value); 98 | void compositorSuperSamplingChanged(float value); 99 | void allowInterleavedReprojectionChanged(bool value); 100 | void allowAsyncReprojectionChanged(bool value); 101 | void forceReprojectionChanged(bool value); 102 | void allowSupersampleFilteringChanged(bool value); 103 | 104 | void steamVRProfilesUpdated(); 105 | }; 106 | 107 | } // namespace advsettings 108 | -------------------------------------------------------------------------------- /src/tabcontrollers/UtilitiesTabController.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | class QQuickWindow; 8 | // application namespace 9 | namespace advsettings { 10 | 11 | // forward declaration 12 | class OverlayController; 13 | 14 | 15 | class UtilitiesTabController : public QObject { 16 | Q_OBJECT 17 | Q_PROPERTY(bool alarmEnabled READ alarmEnabled WRITE setAlarmEnabled NOTIFY alarmEnabledChanged) 18 | Q_PROPERTY(bool alarmIsModal READ alarmIsModal WRITE setAlarmIsModal NOTIFY alarmIsModalChanged) 19 | Q_PROPERTY(int alarmTimeHour READ alarmTimeHour WRITE setAlarmTimeHour NOTIFY alarmTimeHourChanged) 20 | Q_PROPERTY(int alarmTimeMinute READ alarmTimeMinute WRITE setAlarmTimeMinute NOTIFY alarmTimeMinuteChanged) 21 | Q_PROPERTY(bool steamDesktopOverlayAvailable READ steamDesktopOverlayAvailable NOTIFY steamDesktopOverlayAvailableChanged) 22 | Q_PROPERTY(float steamDesktopOverlayWidth READ steamDesktopOverlayWidth WRITE setSteamDesktopOverlayWidth NOTIFY steamDesktopOverlayWidthChanged) 23 | 24 | private: 25 | OverlayController* parent; 26 | QQuickWindow* widget; 27 | 28 | unsigned settingsUpdateCounter = 0; 29 | 30 | bool m_alarmEnabled = false; 31 | bool m_alarmIsModal = true; 32 | QTime m_alarmTime; 33 | QTime m_alarmLastCheckTime; 34 | bool m_steamDesktopOverlayAvailable = false; 35 | float m_steamDesktopOverlayWidth = 4.0f; 36 | 37 | public: 38 | void initStage1(); 39 | void initStage2(OverlayController* parent, QQuickWindow* widget); 40 | 41 | void eventLoopTick(); 42 | 43 | bool alarmEnabled() const; 44 | bool alarmIsModal() const; 45 | int alarmTimeHour() const; 46 | int alarmTimeMinute() const; 47 | 48 | bool steamDesktopOverlayAvailable() const; 49 | float steamDesktopOverlayWidth() const; 50 | 51 | public slots: 52 | void sendKeyboardInput(QString input); 53 | void sendKeyboardEnter(); 54 | void sendKeyboardBackspace(int count); 55 | 56 | void setAlarmEnabled(bool enabled, bool notify = true); 57 | void setAlarmIsModal(bool modal, bool notify = true); 58 | void setAlarmTimeHour(int hour, bool notify = true); 59 | void setAlarmTimeMinute(int min, bool notify = true); 60 | void setAlarmTimeToCurrentTime(); 61 | void modAlarmTimeHour(int value, bool notify = true); 62 | void modAlarmTimeMinute(int value, bool notify = true); 63 | 64 | void setSteamDesktopOverlayWidth(float width, bool notify = true, bool notifyOpenVr = true); 65 | 66 | signals: 67 | void alarmEnabledChanged(bool enabled); 68 | void alarmIsModalChanged(bool modal); 69 | void alarmTimeHourChanged(int hour); 70 | void alarmTimeMinuteChanged(int min); 71 | 72 | void steamDesktopOverlayAvailableChanged(bool available); 73 | void steamDesktopOverlayWidthChanged(float width); 74 | }; 75 | 76 | } // namespace advsettings 77 | -------------------------------------------------------------------------------- /src/tabcontrollers/audiomanager/AudioManagerWindows.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../audiomanager.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include "IPolicyConfig.h" 9 | #include 10 | 11 | 12 | // application namespace 13 | namespace advsettings { 14 | 15 | class AudioManagerWindows : public AudioManager, IMMNotificationClient { 16 | friend class AudioNotificationClient; 17 | private: 18 | std::recursive_mutex _mutex; 19 | AudioTabController* controller = nullptr; 20 | IMMDeviceEnumerator* audioDeviceEnumerator = nullptr; 21 | IMMDevice* playbackAudioDevice = nullptr; 22 | IMMDevice* mirrorAudioDevice = nullptr; 23 | IAudioEndpointVolume* mirrorAudioEndpointVolume = nullptr; 24 | IMMDevice* micAudioDevice = nullptr; 25 | IAudioEndpointVolume* micAudioEndpointVolume = nullptr; 26 | IPolicyConfig* policyConfig = nullptr; 27 | 28 | public: 29 | ~AudioManagerWindows(); 30 | 31 | virtual void init(AudioTabController* controller) override; 32 | 33 | virtual void setPlaybackDevice(const std::string& id, bool notify = true) override; 34 | virtual std::string getPlaybackDevName() override; 35 | virtual std::string getPlaybackDevId() override; 36 | 37 | virtual void setMirrorDevice(const std::string& id, bool notify = true) override; 38 | virtual bool isMirrorValid() override; 39 | virtual std::string getMirrorDevName() override; 40 | virtual std::string getMirrorDevId() override; 41 | virtual float getMirrorVolume() override; 42 | virtual bool setMirrorVolume(float value) override; 43 | virtual bool getMirrorMuted() override; 44 | virtual bool setMirrorMuted(bool value) override; 45 | 46 | virtual bool isMicValid() override; 47 | virtual void setMicDevice(const std::string& id, bool notify = true) override; 48 | virtual std::string getMicDevName() override; 49 | virtual std::string getMicDevId() override; 50 | virtual float getMicVolume() override; 51 | virtual bool setMicVolume(float value) override; 52 | virtual bool getMicMuted() override; 53 | virtual bool setMicMuted(bool value) override; 54 | 55 | virtual std::vector> getRecordingDevices() override; 56 | virtual std::vector> getPlaybackDevices() override; 57 | 58 | void deleteMirrorDevice(); 59 | 60 | // from IMMNotificationClient 61 | virtual HRESULT QueryInterface(REFIID riid, void ** ppvObject) override; 62 | virtual ULONG AddRef(void) override; 63 | virtual ULONG Release(void) override; 64 | virtual HRESULT OnDeviceStateChanged(LPCWSTR pwstrDeviceId, DWORD dwNewState) override; 65 | virtual HRESULT OnDeviceAdded(LPCWSTR pwstrDeviceId) override; 66 | virtual HRESULT OnDeviceRemoved(LPCWSTR pwstrDeviceId) override; 67 | virtual HRESULT OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId) override; 68 | virtual HRESULT OnPropertyValueChanged(LPCWSTR pwstrDeviceId, const PROPERTYKEY key) override; 69 | 70 | private: 71 | IMMDeviceEnumerator* getAudioDeviceEnumerator(); 72 | IPolicyConfig* getPolicyConfig(); 73 | IMMDevice* getDefaultRecordingDevice(IMMDeviceEnumerator* deviceEnumerator); 74 | IMMDevice* getDefaultPlaybackDevice(IMMDeviceEnumerator* deviceEnumerator); 75 | IMMDevice* getDevice(IMMDeviceEnumerator* deviceEnumerator, const std::string& id); 76 | IMMDevice* getDevice(IMMDeviceEnumerator* deviceEnumerator, LPCWSTR id); 77 | IAudioEndpointVolume* getAudioEndpointVolume(IMMDevice* device); 78 | std::string getDeviceName(IMMDevice* device); 79 | std::string getDeviceId(IMMDevice* device); 80 | std::vector> getDevices(IMMDeviceEnumerator* deviceEnumerator, EDataFlow dataFlow); 81 | }; 82 | 83 | } 84 | 85 | -------------------------------------------------------------------------------- /src/tabcontrollers/audiomanager/IPolicyConfig.h: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // PolicyConfig.h 3 | // Undocumented COM-interface IPolicyConfig. 4 | // Use for set default audio render endpoint 5 | // @author EreTIk 6 | // ---------------------------------------------------------------------------- 7 | 8 | 9 | #pragma once 10 | 11 | // ca286fc3-91fd-42c3-8e9b-caafa66242e3 12 | static const GUID IID_IPolicyConfig2 = { 0xCA286FC3, 0x91FD, 0x42C3, { 0x8E, 0x9B, 0xCA, 0xAF, 0xA6, 0x62, 0x42, 0xE3 } }; 13 | 14 | // 6be54be8-a068-4875-a49d-0c2966473b11 15 | static const GUID IID_IPolicyConfig1 = { 0x6BE54BE8, 0xA068, 0x4875, { 0xA4, 0x9D, 0x0C, 0x29, 0x66, 0x47, 0x3B, 0x11 } }; 16 | 17 | // f8679f50-850a-41cf-9c72-430f290290c8 18 | static const GUID IID_IPolicyConfig0 = { 0xF8679F50, 0x850A, 0x41CF, { 0x9C, 0x72, 0x43, 0x0F, 0x29, 0x02, 0x90, 0xC8 } }; 19 | 20 | class DECLSPEC_UUID("870af99c-171d-4f9e-af0d-e63df40c2bc9") CPolicyConfigClient; 21 | 22 | interface IPolicyConfig : public IUnknown 23 | { 24 | public: 25 | 26 | virtual HRESULT GetMixFormat( 27 | PCWSTR, 28 | WAVEFORMATEX ** 29 | ); 30 | 31 | virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat( 32 | PCWSTR, 33 | INT, 34 | WAVEFORMATEX ** 35 | ); 36 | 37 | virtual HRESULT STDMETHODCALLTYPE ResetDeviceFormat( 38 | PCWSTR 39 | ); 40 | 41 | virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat( 42 | PCWSTR, 43 | WAVEFORMATEX *, 44 | WAVEFORMATEX * 45 | ); 46 | 47 | virtual HRESULT STDMETHODCALLTYPE GetProcessingPeriod( 48 | PCWSTR, 49 | INT, 50 | PINT64, 51 | PINT64 52 | ); 53 | 54 | virtual HRESULT STDMETHODCALLTYPE SetProcessingPeriod( 55 | PCWSTR, 56 | PINT64 57 | ); 58 | 59 | virtual HRESULT STDMETHODCALLTYPE GetShareMode( 60 | PCWSTR, 61 | struct DeviceShareMode * 62 | ); 63 | 64 | virtual HRESULT STDMETHODCALLTYPE SetShareMode( 65 | PCWSTR, 66 | struct DeviceShareMode * 67 | ); 68 | 69 | virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( 70 | PCWSTR, 71 | int, 72 | const PROPERTYKEY &, 73 | const PROPVARIANT * 74 | ); 75 | 76 | virtual HRESULT STDMETHODCALLTYPE SetPropertyValue( 77 | PCWSTR, 78 | int, 79 | const PROPERTYKEY &, 80 | const PROPVARIANT * 81 | ); 82 | 83 | virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint( 84 | __in PCWSTR wszDeviceId, 85 | __in ERole eRole 86 | ); 87 | 88 | virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility( 89 | PCWSTR, 90 | INT 91 | ); 92 | }; 93 | 94 | interface DECLSPEC_UUID("568b9108-44bf-40b4-9006-86afe5b5a620") 95 | IPolicyConfigVista; 96 | class DECLSPEC_UUID("294935CE-F637-4E7C-A41B-AB255460B862") 97 | CPolicyConfigVistaClient; 98 | // ---------------------------------------------------------------------------- 99 | // class CPolicyConfigVistaClient 100 | // {294935CE-F637-4E7C-A41B-AB255460B862} 101 | // 102 | // interface IPolicyConfigVista 103 | // {568b9108-44bf-40b4-9006-86afe5b5a620} 104 | // 105 | // Query interface: 106 | // CComPtr PolicyConfig; 107 | // PolicyConfig.CoCreateInstance(__uuidof(CPolicyConfigVistaClient)); 108 | // 109 | // @compatible: Windows Vista and Later 110 | // ---------------------------------------------------------------------------- 111 | interface IPolicyConfigVista : public IUnknown 112 | { 113 | public: 114 | 115 | virtual HRESULT GetMixFormat( 116 | PCWSTR, 117 | WAVEFORMATEX ** 118 | ); // not available on Windows 7, use method from IPolicyConfig 119 | 120 | virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat( 121 | PCWSTR, 122 | INT, 123 | WAVEFORMATEX ** 124 | ); 125 | 126 | virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat( 127 | PCWSTR, 128 | WAVEFORMATEX *, 129 | WAVEFORMATEX * 130 | ); 131 | 132 | virtual HRESULT STDMETHODCALLTYPE GetProcessingPeriod( 133 | PCWSTR, 134 | INT, 135 | PINT64, 136 | PINT64 137 | ); // not available on Windows 7, use method from IPolicyConfig 138 | 139 | virtual HRESULT STDMETHODCALLTYPE SetProcessingPeriod( 140 | PCWSTR, 141 | PINT64 142 | ); // not available on Windows 7, use method from IPolicyConfig 143 | 144 | virtual HRESULT STDMETHODCALLTYPE GetShareMode( 145 | PCWSTR, 146 | struct DeviceShareMode * 147 | ); // not available on Windows 7, use method from IPolicyConfig 148 | 149 | virtual HRESULT STDMETHODCALLTYPE SetShareMode( 150 | PCWSTR, 151 | struct DeviceShareMode * 152 | ); // not available on Windows 7, use method from IPolicyConfig 153 | 154 | virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( 155 | PCWSTR, 156 | int, 157 | const PROPERTYKEY &, 158 | const PROPVARIANT * 159 | ); 160 | 161 | virtual HRESULT STDMETHODCALLTYPE SetPropertyValue( 162 | PCWSTR, 163 | int, 164 | const PROPERTYKEY &, 165 | const PROPVARIANT * 166 | ); 167 | 168 | virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint( 169 | __in PCWSTR wszDeviceId, 170 | __in ERole eRole 171 | ); 172 | 173 | virtual HRESULT STDMETHODCALLTYPE SetEndpointVisibility( 174 | PCWSTR, 175 | INT 176 | ); // not available on Windows 7, use method from IPolicyConfig 177 | }; 178 | -------------------------------------------------------------------------------- /src/utils/ChaperoneUtils.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "ChaperoneUtils.h" 3 | #include 4 | 5 | namespace utils { 6 | 7 | 8 | float ChaperoneUtils::_getDistanceToChaperone(const vr::HmdVector3_t & x, vr::HmdVector3_t * projectedPoint) { 9 | float distance = NAN; 10 | vr::HmdVector3_t* _cornersPtr = _corners.get(); 11 | for (uint32_t i = 0; i < _quadsCount; i++) { 12 | uint32_t i2 = (i + 1) % _quadsCount; 13 | vr::HmdVector3_t& r0 = _cornersPtr[i]; 14 | vr::HmdVector3_t& r1 = _cornersPtr[i2]; 15 | float u_x = r1.v[0] - r0.v[0]; 16 | float u_z = r1.v[2] - r0.v[2]; 17 | float r = ((x.v[0] - r0.v[0]) * u_x + (x.v[2] - r0.v[2]) * u_z) / (u_x*u_x + u_z*u_z); 18 | //int mode = 0; // 0 .. projected point on segment, 1 .. projected point outside of segment (r0 closer than r1), 2 .. projected point outside of segment (r1 closer than r0) 19 | float d; 20 | float x1_x; 21 | float x1_z; 22 | if (r < 0.0f || r > 1.0f) { // projected point outside of segment 23 | float d_x = r0.v[0] - x.v[0]; 24 | float d_z = r0.v[2] - x.v[2]; 25 | float d1 = sqrt(d_x*d_x + d_z*d_z); 26 | d_x = r1.v[0] - x.v[0]; 27 | d_z = r1.v[2] - x.v[2]; 28 | float d2 = sqrt(d_x*d_x + d_z*d_z); 29 | if (d1 < d2) { 30 | d = d1; 31 | x1_x = r0.v[0]; 32 | x1_z = r0.v[2]; 33 | } else { 34 | d = d2; 35 | x1_x = r1.v[0]; 36 | x1_z = r1.v[2]; 37 | } 38 | } else { // projected point on segment 39 | x1_x = r0.v[0] + r * u_x; 40 | x1_z = r0.v[2] + r * u_z; 41 | float d_x = x1_x - x.v[0]; 42 | float d_z = x1_z - x.v[2]; 43 | d = sqrt(d_x*d_x + d_z*d_z); 44 | } 45 | if (isnan(distance) || d < distance) { 46 | distance = d; 47 | if (projectedPoint) { 48 | projectedPoint->v[0] = x1_x; 49 | projectedPoint->v[1] = x.v[1]; 50 | projectedPoint->v[2] = x1_z; 51 | } 52 | } 53 | } 54 | return distance; 55 | } 56 | 57 | 58 | void ChaperoneUtils::loadChaperoneData() { 59 | std::lock_guard lock(_mutex); 60 | vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo(nullptr, &_quadsCount); 61 | if (_quadsCount > 0) { 62 | std::unique_ptr quadsBuffer(new vr::HmdQuad_t[_quadsCount]); 63 | vr::HmdQuad_t* quadsBufferPtr = quadsBuffer.get(); 64 | _corners.reset((vr::HmdVector3_t*)new vr::HmdQuad_t[_quadsCount]); 65 | vr::HmdVector3_t* _cornersPtr = _corners.get(); 66 | vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo(quadsBufferPtr, &_quadsCount); 67 | for (uint32_t i = 0; i < _quadsCount; i++) { 68 | _cornersPtr[i] = quadsBufferPtr[i].vCorners[0]; 69 | uint32_t i2 = (i + 1) % _quadsCount; 70 | if (quadsBufferPtr[i].vCorners[3].v[0] != quadsBufferPtr[i2].vCorners[0].v[0] 71 | || quadsBufferPtr[i].vCorners[3].v[1] != quadsBufferPtr[i2].vCorners[0].v[1] 72 | || quadsBufferPtr[i].vCorners[3].v[2] != quadsBufferPtr[i2].vCorners[0].v[2] 73 | || quadsBufferPtr[i].vCorners[0].v[1] != 0.0f) { 74 | _chaperoneWellFormed = false; 75 | } 76 | } 77 | } 78 | } 79 | 80 | 81 | } // end namespace utils 82 | -------------------------------------------------------------------------------- /src/utils/ChaperoneUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace utils { 8 | 9 | class ChaperoneUtils { 10 | private: 11 | std::recursive_mutex _mutex; 12 | uint32_t _quadsCount = 0; 13 | std::unique_ptr _corners; 14 | bool _chaperoneWellFormed = true; 15 | 16 | float _getDistanceToChaperone(const vr::HmdVector3_t& point, vr::HmdVector3_t* projectedPoint); 17 | 18 | public: 19 | uint32_t quadsCount() const noexcept { return _quadsCount; } 20 | bool isChaperoneWellFormed() const noexcept { return _chaperoneWellFormed; } 21 | 22 | std::recursive_mutex& mutex() noexcept { return _mutex; } 23 | 24 | void loadChaperoneData(); 25 | 26 | float getDistanceToChaperone(const vr::HmdVector3_t& point, vr::HmdVector3_t* projectedPoint = nullptr, bool doLock = false) { 27 | if (doLock) { 28 | std::lock_guard lock(_mutex); 29 | return _getDistanceToChaperone(point, projectedPoint); 30 | } else { 31 | return _getDistanceToChaperone(point, projectedPoint); 32 | } 33 | } 34 | }; 35 | 36 | 37 | } // end namespace utils 38 | 39 | -------------------------------------------------------------------------------- /src/utils/Matrix.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | namespace utils { 8 | 9 | inline vr::HmdMatrix34_t& initRotationMatrix(vr::HmdMatrix34_t& matrix, unsigned axisId, float angle) { 10 | switch (axisId) { 11 | case 0: // x-axis 12 | matrix.m[0][0] = 1.0f; 13 | matrix.m[0][1] = 0.0f; 14 | matrix.m[0][2] = 0.0f; 15 | matrix.m[0][3] = 0.0f; 16 | matrix.m[1][0] = 0.0f; 17 | matrix.m[1][1] = std::cos(angle); 18 | matrix.m[1][2] = -std::sin(angle); 19 | matrix.m[1][3] = 0.0f; 20 | matrix.m[2][0] = 0.0f; 21 | matrix.m[2][1] = std::sin(angle); 22 | matrix.m[2][2] = std::cos(angle); 23 | matrix.m[2][3] = 0.0f; 24 | break; 25 | case 1: // y-axis 26 | matrix.m[0][0] = std::cos(angle); 27 | matrix.m[0][1] = 0.0f; 28 | matrix.m[0][2] = std::sin(angle); 29 | matrix.m[0][3] = 0.0f; 30 | matrix.m[1][0] = 0.0f; 31 | matrix.m[1][1] = 1.0f; 32 | matrix.m[1][2] = 0.0f; 33 | matrix.m[1][3] = 0.0f; 34 | matrix.m[2][0] = -std::sin(angle); 35 | matrix.m[2][1] = 0.0f; 36 | matrix.m[2][2] = std::cos(angle); 37 | matrix.m[2][3] = 0.0f; 38 | break; 39 | case 2: // z-axis 40 | matrix.m[0][0] = std::cos(angle); 41 | matrix.m[0][1] = -std::sin(angle); 42 | matrix.m[0][2] = 0.0f; 43 | matrix.m[0][3] = 0.0f; 44 | matrix.m[1][0] = std::sin(angle); 45 | matrix.m[1][1] = std::cos(angle); 46 | matrix.m[1][2] = 0.0f; 47 | matrix.m[1][3] = 0.0f; 48 | matrix.m[2][0] = 0.0f; 49 | matrix.m[2][1] = 0.0f; 50 | matrix.m[2][2] = 1.0f; 51 | matrix.m[2][3] = 0.0f; 52 | break; 53 | default: 54 | break; 55 | } 56 | return matrix; 57 | } 58 | 59 | 60 | inline vr::HmdMatrix34_t& matMul33(vr::HmdMatrix34_t& result, const vr::HmdMatrix34_t& a, const vr::HmdMatrix34_t& b) { 61 | for (unsigned i = 0; i < 3; i++) { 62 | for (unsigned j = 0; j < 3; j++) { 63 | result.m[i][j] = 0.0f; 64 | for (unsigned k = 0; k < 3; k++) { 65 | result.m[i][j] += a.m[i][k] * b.m[k][j]; 66 | } 67 | } 68 | } 69 | return result; 70 | } 71 | 72 | 73 | inline vr::HmdVector3_t& matMul33(vr::HmdVector3_t& result, const vr::HmdMatrix34_t& a, const vr::HmdVector3_t& b) { 74 | for (unsigned i = 0; i < 3; i++) { 75 | result.v[i] = 0.0f; 76 | for (unsigned k = 0; k < 3; k++) { 77 | result.v[i] += a.m[i][k] * b.v[k]; 78 | }; 79 | } 80 | return result; 81 | } 82 | 83 | 84 | inline vr::HmdVector3_t& matMul33(vr::HmdVector3_t& result, const vr::HmdVector3_t& a, const vr::HmdMatrix34_t& b) { 85 | for (unsigned i = 0; i < 3; i++) { 86 | result.v[i] = 0.0f; 87 | for (unsigned k = 0; k < 3; k++) { 88 | result.v[i] += a.v[k] * b.m[k][i]; 89 | }; 90 | } 91 | return result; 92 | } 93 | 94 | 95 | 96 | } // end namespace utils 97 | 98 | -------------------------------------------------------------------------------- /third-party/easylogging++/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 muflihun.com 4 | 5 | http://github.com/easylogging/ 6 | http://easylogging.muflihun.com 7 | http://muflihun.com 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy of 10 | this software and associated documentation files (the "Software"), to deal in 11 | the Software without restriction, including without limitation the rights to 12 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 13 | the Software, and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 21 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 22 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 23 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /third-party/openvr/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Valve Corporation 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /third-party/openvr/README.md: -------------------------------------------------------------------------------- 1 | OpenVR SDK 2 | --- 3 | 4 | OpenVR is an API and runtime that allows access to VR hardware from multiple 5 | vendors without requiring that applications have specific knowledge of the 6 | hardware they are targeting. This repository is an SDK that contains the API 7 | and samples. The runtime is under SteamVR in Tools on Steam. 8 | 9 | ### Documentation 10 | 11 | Documentation for the API is available on the [Github Wiki](https://github.com/ValveSoftware/openvr/wiki/API-Documentation) 12 | 13 | More information on OpenVR and SteamVR can be found on http://steamvr.com 14 | -------------------------------------------------------------------------------- /third-party/openvr/bin/linux64/libopenvr_api.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/third-party/openvr/bin/linux64/libopenvr_api.so -------------------------------------------------------------------------------- /third-party/openvr/bin/linux64/libopenvr_api.so.dbg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/third-party/openvr/bin/linux64/libopenvr_api.so.dbg -------------------------------------------------------------------------------- /third-party/openvr/bin/osx32/libopenvr_api.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/third-party/openvr/bin/osx32/libopenvr_api.dylib -------------------------------------------------------------------------------- /third-party/openvr/bin/osx32/libopenvr_api.dylib.dSYM/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleIdentifier 8 | com.apple.xcode.dsym.libopenvr_api.dylib 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundlePackageType 12 | dSYM 13 | CFBundleSignature 14 | ???? 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleVersion 18 | 1 19 | 20 | 21 | -------------------------------------------------------------------------------- /third-party/openvr/bin/osx32/libopenvr_api.dylib.dSYM/Contents/Resources/DWARF/libopenvr_api.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/third-party/openvr/bin/osx32/libopenvr_api.dylib.dSYM/Contents/Resources/DWARF/libopenvr_api.dylib -------------------------------------------------------------------------------- /third-party/openvr/bin/win32/openvr_api.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/third-party/openvr/bin/win32/openvr_api.dll -------------------------------------------------------------------------------- /third-party/openvr/bin/win32/openvr_api.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/third-party/openvr/bin/win32/openvr_api.pdb -------------------------------------------------------------------------------- /third-party/openvr/bin/win64/openvr_api.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/third-party/openvr/bin/win64/openvr_api.dll -------------------------------------------------------------------------------- /third-party/openvr/bin/win64/openvr_api.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/third-party/openvr/bin/win64/openvr_api.pdb -------------------------------------------------------------------------------- /third-party/openvr/lib/linux64/libopenvr_api.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/third-party/openvr/lib/linux64/libopenvr_api.so -------------------------------------------------------------------------------- /third-party/openvr/lib/osx32/libopenvr_api.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/third-party/openvr/lib/osx32/libopenvr_api.dylib -------------------------------------------------------------------------------- /third-party/openvr/lib/win32/openvr_api.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/third-party/openvr/lib/win32/openvr_api.lib -------------------------------------------------------------------------------- /third-party/openvr/lib/win64/openvr_api.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/matzman666/OpenVR-AdvancedSettings/e57a4880dfdd7b7d5643e842e0ccca82ba076acd/third-party/openvr/lib/win64/openvr_api.lib --------------------------------------------------------------------------------