Reimplemented sound effects.

Added chaperone proximity warnings.
Other bugfixes and improvements.
This commit is contained in:
2017-08-15 21:44:29 +02:00
parent 0bc693c76b
commit f48b583aca
17 changed files with 1523 additions and 54 deletions
+5 -2
View File
@@ -25,7 +25,8 @@ SOURCES += src/main.cpp\
src/tabcontrollers/UtilitiesTabController.cpp \ src/tabcontrollers/UtilitiesTabController.cpp \
src/tabcontrollers/audiomanager/AudioManagerWindows.cpp \ src/tabcontrollers/audiomanager/AudioManagerWindows.cpp \
src/tabcontrollers/PttController.cpp \ src/tabcontrollers/PttController.cpp \
src/tabcontrollers/AccessibilityTabController.cpp src/tabcontrollers/AccessibilityTabController.cpp \
src/utils/ChaperoneUtils.cpp
HEADERS += src/overlaycontroller.h \ HEADERS += src/overlaycontroller.h \
src/logging.h \ src/logging.h \
@@ -41,7 +42,9 @@ HEADERS += src/overlaycontroller.h \
src/tabcontrollers/AudioManager.h \ src/tabcontrollers/AudioManager.h \
src/tabcontrollers/audiomanager/AudioManagerWindows.h \ src/tabcontrollers/audiomanager/AudioManagerWindows.h \
src/tabcontrollers/PttController.h \ src/tabcontrollers/PttController.h \
src/tabcontrollers/AccessibilityTabController.h src/tabcontrollers/AccessibilityTabController.h \
src/utils/Matrix.h \
src/utils/ChaperoneUtils.h
INCLUDEPATH += third-party/openvr/include \ INCLUDEPATH += third-party/openvr/include \
third-party/easylogging++ third-party/easylogging++
+23 -2
View File
@@ -3,6 +3,7 @@ import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.2 import QtQuick.Dialogs 1.2
import matzman666.advsettings 1.0 import matzman666.advsettings 1.0
import "." // QTBUG-34418, singletons require explicit import to load qmldir file
MyStackViewPage { MyStackViewPage {
headerText: "Chaperone Settings" headerText: "Chaperone Settings"
@@ -102,6 +103,11 @@ MyStackViewPage {
Layout.leftMargin: 32 Layout.leftMargin: 32
text: "Force Bounds Setting" text: "Force Bounds Setting"
} }
MyToggleButton {
id: chaperoneNewProfileIncludeProximityWarnings
Layout.leftMargin: 32
text: "Proximity Warning Settings"
}
} }
onClosed: { onClosed: {
if (okClicked) { if (okClicked) {
@@ -115,7 +121,8 @@ MyStackViewPage {
&& !chaperoneNewProfileIncludeFloorBoundsMarker.checked && !chaperoneNewProfileIncludeFloorBoundsMarker.checked
&& !chaperoneNewProfileIncludeBoundsColor.checked && !chaperoneNewProfileIncludeBoundsColor.checked
&& !chaperoneNewProfileIncludeStyle.checked && !chaperoneNewProfileIncludeStyle.checked
&& !chaperoneNewProfileIncludeForceBounds.checked) { && !chaperoneNewProfileIncludeForceBounds.checked
&& !chaperoneNewProfileIncludeProximityWarnings.checked) {
chaperoneMessageDialog.showMessage("Create New Profile", "ERROR: Nothing included.") chaperoneMessageDialog.showMessage("Create New Profile", "ERROR: Nothing included.")
} else { } else {
ChaperoneTabController.addChaperoneProfile(chaperoneNewProfileName.text, ChaperoneTabController.addChaperoneProfile(chaperoneNewProfileName.text,
@@ -127,7 +134,8 @@ MyStackViewPage {
chaperoneNewProfileIncludeFloorBoundsMarker.checked, chaperoneNewProfileIncludeFloorBoundsMarker.checked,
chaperoneNewProfileIncludeBoundsColor.checked, chaperoneNewProfileIncludeBoundsColor.checked,
chaperoneNewProfileIncludeStyle.checked, chaperoneNewProfileIncludeStyle.checked,
chaperoneNewProfileIncludeForceBounds.checked) chaperoneNewProfileIncludeForceBounds.checked,
chaperoneNewProfileIncludeProximityWarnings.checked)
} }
} }
@@ -143,6 +151,7 @@ MyStackViewPage {
chaperoneNewProfileIncludeBoundsColor.checked = false chaperoneNewProfileIncludeBoundsColor.checked = false
chaperoneNewProfileIncludeStyle.checked = false chaperoneNewProfileIncludeStyle.checked = false
chaperoneNewProfileIncludeForceBounds.checked = false chaperoneNewProfileIncludeForceBounds.checked = false
chaperoneNewProfileIncludeProximityWarnings.checked = false
open() open()
} }
} }
@@ -440,6 +449,18 @@ MyStackViewPage {
ChaperoneTabController.setForceBounds(this.checked, false) ChaperoneTabController.setForceBounds(this.checked, false)
} }
} }
Item { Layout.fillWidth: true }
MyPushButton {
id: chaperoneWarningsConfigButton
text: "Proximity Warning Settings"
Layout.preferredWidth: 350
onClicked: {
MyResources.playFocusChangedSound()
mainView.push(chaperoneWarningsPage)
}
}
} }
MyPushButton { MyPushButton {
+567
View File
@@ -0,0 +1,567 @@
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.2
import matzman666.advsettings 1.0
import "." // QTBUG-34418, singletons require explicit import to load qmldir file
MyStackViewPage {
headerText: "Chaperone Proximity Warning Settings"
ColorDialog {
id: colorDialog
title: "Please choose a color"
onAccepted: {
console.log("You chose: " + colorDialog.color)
Qt.quit()
}
onRejected: {
console.log("Canceled")
Qt.quit()
}
}
content: ColumnLayout {
spacing: 36
ColumnLayout {
spacing: 0
MyToggleButton {
id: switchBeginnerToggle
text: "Switch to Beginner Mode"
onCheckedChanged: {
ChaperoneTabController.chaperoneSwitchToBeginnerEnabled = checked
}
}
RowLayout {
MyText {
text: "Activation Distance: "
Layout.preferredWidth: 250
}
MyPushButton2 {
id: switchBeginnerDistanceMinusButton
Layout.preferredWidth: 40
text: "-"
onClicked: {
var val = ChaperoneTabController.chaperoneSwitchToBeginnerDistance - 0.1
if (val <= 0) {
val = 0.1;
}
ChaperoneTabController.chaperoneSwitchToBeginnerDistance = val.toFixed(2)
}
}
MySlider {
id: switchBeginnerDistanceSlider
from: 0
to: 2.0
stepSize: 0.01
value: 0.5
Layout.fillWidth: true
onPositionChanged: {
var val = this.from + ( this.position * (this.to - this.from))
switchBeginnerDistanceText.text = val.toFixed(2)
}
onValueChanged: {
var val = switchBeginnerDistanceSlider.value.toFixed(2)
if (val < 0.01) {
val = 0.01
}
ChaperoneTabController.chaperoneSwitchToBeginnerDistance = val
switchBeginnerDistanceText.text = val
}
}
MyPushButton2 {
id: switchBeginnerDistancePlusButton
Layout.preferredWidth: 40
text: "+"
onClicked: {
var val = ChaperoneTabController.chaperoneSwitchToBeginnerDistance + 0.1
if (val > 2.0) {
val = 2.0;
}
ChaperoneTabController.chaperoneSwitchToBeginnerDistance = val.toFixed(2)
}
}
MyTextField {
id: switchBeginnerDistanceText
text: "0.00"
keyBoardUID: 801
Layout.preferredWidth: 100
Layout.leftMargin: 10
horizontalAlignment: Text.AlignHCenter
function onInputEvent(input) {
var val = parseFloat(input)
if (!isNaN(val)) {
if (val <= 0.0) {
val = 0.01
}
val = val.toFixed(2)
ChaperoneTabController.chaperoneSwitchToBeginnerDistance = val
text = val
} else {
text = ChaperoneTabController.chaperoneSwitchToBeginnerDistance.toFixed(2)
}
}
}
}
}
ColumnLayout {
spacing: 0
MyToggleButton {
id: hapticFeedbackToggle
text: "Trigger Haptic Feedback"
onCheckedChanged: {
ChaperoneTabController.chaperoneHapticFeedbackEnabled = checked
}
}
RowLayout {
MyText {
text: "Activation Distance: "
Layout.preferredWidth: 250
}
MyPushButton2 {
id: hapticFeedbackDistanceMinusButton
Layout.preferredWidth: 40
text: "-"
onClicked: {
var val = ChaperoneTabController.chaperoneHapticFeedbackDistance - 0.1
if (val <= 0) {
val = 0.1;
}
ChaperoneTabController.chaperoneHapticFeedbackDistance = val.toFixed(2)
}
}
MySlider {
id: hapticFeedbackDistanceSlider
from: 0
to: 2.0
stepSize: 0.01
value: 0.5
Layout.fillWidth: true
onPositionChanged: {
var val = this.from + ( this.position * (this.to - this.from))
hapticFeedbackDistanceText.text = val.toFixed(2)
}
onValueChanged: {
var val = hapticFeedbackDistanceSlider.value.toFixed(2)
if (val < 0.01) {
val = 0.01
}
ChaperoneTabController.chaperoneHapticFeedbackDistance = val
hapticFeedbackDistanceText.text = val
}
}
MyPushButton2 {
id: hapticFeedbackDistancePlusButton
Layout.preferredWidth: 40
text: "+"
onClicked: {
var val = ChaperoneTabController.chaperoneHapticFeedbackDistance + 0.1
if (val > 2.0) {
val = 2.0;
}
ChaperoneTabController.chaperoneHapticFeedbackDistance = val.toFixed(2)
}
}
MyTextField {
id: hapticFeedbackDistanceText
text: "0.00"
keyBoardUID: 805
Layout.preferredWidth: 100
Layout.leftMargin: 10
horizontalAlignment: Text.AlignHCenter
function onInputEvent(input) {
var val = parseFloat(input)
if (!isNaN(val)) {
if (val <= 0.0) {
val = 0.01
}
val = val.toFixed(2)
ChaperoneTabController.chaperoneHapticFeedbackDistance = val
text = val
} else {
text = ChaperoneTabController.chaperoneHapticFeedbackDistance.toFixed(2)
}
}
}
}
}
ColumnLayout {
spacing: 0
RowLayout {
spacing: 32
MyToggleButton {
id: audioWarningToggle
text: "Audio Warning"
onCheckedChanged: {
ChaperoneTabController.chaperoneAlarmSoundEnabled = checked
}
}
MyToggleButton {
id: audioWarningLoopingToggle
text: "Loop Audio"
onCheckedChanged: {
ChaperoneTabController.chaperoneAlarmSoundLooping = checked
audioWarningAdjustVolumeToggle.enabled = checked
}
}
MyToggleButton {
id: audioWarningAdjustVolumeToggle
text: "Adjust Volume"
enabled: false
onCheckedChanged: {
ChaperoneTabController.chaperoneAlarmSoundAdjustVolume = checked
}
}
}
RowLayout {
MyText {
text: "Activation Distance: "
Layout.preferredWidth: 250
}
MyPushButton2 {
id: audioWarningDistanceMinusButton
Layout.preferredWidth: 40
text: "-"
onClicked: {
var val = ChaperoneTabController.chaperoneAlarmSoundDistance - 0.1
if (val <= 0.0) {
val = 0.01;
}
ChaperoneTabController.chaperoneAlarmSoundDistance = val.toFixed(2)
}
}
MySlider {
id: audioWarningDistanceSlider
from: 0
to: 2.0
stepSize: 0.01
value: 0.5
Layout.fillWidth: true
onPositionChanged: {
var val = this.from + ( this.position * (this.to - this.from))
audioWarningDistanceText.text = val.toFixed(2)
}
onValueChanged: {
var val = audioWarningDistanceSlider.value.toFixed(2)
if (val < 0.01) {
val = 0.01
}
ChaperoneTabController.chaperoneAlarmSoundDistance = val
audioWarningDistanceText.text = val
}
}
MyPushButton2 {
id: audioWarningDistancePlusButton
Layout.preferredWidth: 40
text: "+"
onClicked: {
var val = ChaperoneTabController.chaperoneAlarmSoundDistance + 0.1
if (val > 2.0) {
val = 2.0;
}
ChaperoneTabController.chaperoneAlarmSoundDistance = val.toFixed(2)
}
}
MyTextField {
id: audioWarningDistanceText
text: "0.00"
keyBoardUID: 802
Layout.preferredWidth: 100
Layout.leftMargin: 10
horizontalAlignment: Text.AlignHCenter
function onInputEvent(input) {
var val = parseFloat(input)
if (!isNaN(val)) {
if (val <= 0.0) {
val = 0.01
}
val = val.toFixed(2)
ChaperoneTabController.chaperoneAlarmSoundDistance = val
text = val
} else {
text = ChaperoneTabController.chaperoneAlarmSoundDistance.toFixed(2)
}
}
}
}
}
ColumnLayout {
spacing: 0
MyToggleButton {
id: openDashboardToggle
text: "Open Dashboard"
onCheckedChanged: {
ChaperoneTabController.chaperoneShowDashboardEnabled = checked
}
}
RowLayout {
MyText {
text: "Activation Distance: "
Layout.preferredWidth: 250
}
MyPushButton2 {
id: openDashboardDistanceMinusButton
Layout.preferredWidth: 40
text: "-"
onClicked: {
var val = ChaperoneTabController.chaperoneShowDashboardDistance - 0.1
if (val <= 0.0) {
val = 0.01;
}
ChaperoneTabController.chaperoneShowDashboardDistance = val.toFixed(2)
}
}
MySlider {
id: openDashboardDistanceSlider
from: 0
to: 2.0
stepSize: 0.01
value: 0.5
Layout.fillWidth: true
onPositionChanged: {
var val = this.from + ( this.position * (this.to - this.from))
openDashboardDistanceText.text = val.toFixed(2)
}
onValueChanged: {
var val = openDashboardDistanceSlider.value.toFixed(2)
if (val < 0.01) {
val = 0.01
}
ChaperoneTabController.chaperoneShowDashboardDistance = val
openDashboardDistanceText.text = val
}
}
MyPushButton2 {
id: openDashboardDistancePlusButton
Layout.preferredWidth: 40
text: "+"
onClicked: {
var val = ChaperoneTabController.chaperoneShowDashboardDistance + 0.1
if (val > 2.0) {
val = 2.0;
}
ChaperoneTabController.chaperoneShowDashboardDistance = val.toFixed(2)
}
}
MyTextField {
id: openDashboardDistanceText
text: "0.00"
keyBoardUID: 803
Layout.preferredWidth: 100
Layout.leftMargin: 10
horizontalAlignment: Text.AlignHCenter
function onInputEvent(input) {
var val = parseFloat(input)
if (!isNaN(val)) {
if (val <= 0.0) {
val = 0.01
}
val = val.toFixed(2)
ChaperoneTabController.chaperoneShowDashboardDistance = val
text = val
} else {
text = ChaperoneTabController.chaperoneShowDashboardDistance.toFixed(2)
}
}
}
}
}
ColumnLayout {
spacing: 0
MyToggleButton {
id: velModifierToggle
text: "Velocity Dependent Fade/Activation Distance"
onCheckedChanged: {
ChaperoneTabController.chaperoneVelocityModifierEnabled = checked
}
}
RowLayout {
MyText {
text: "Distance Modifier: "
Layout.preferredWidth: 250
}
MyPushButton2 {
id: velModifierMinusButton
Layout.preferredWidth: 40
text: "-"
onClicked: {
var val = ChaperoneTabController.chaperoneVelocityModifier - 0.01
if (val < 0.0) {
val = 0.0;
}
ChaperoneTabController.chaperoneVelocityModifier = val.toFixed(2)
}
}
MySlider {
id: velModifierSlider
from: 0
to: 1.0
stepSize: 0.01
value: 0.3
Layout.fillWidth: true
onPositionChanged: {
var val = this.from + ( this.position * (this.to - this.from))
velModifierText.text = val.toFixed(2)
}
onValueChanged: {
var val = velModifierSlider.value.toFixed(2)
if (val < 0.0) {
val = 0.0
}
ChaperoneTabController.chaperoneVelocityModifier = val
velModifierText.text = val
}
}
MyPushButton2 {
id: velModifierPlusButton
Layout.preferredWidth: 40
text: "+"
onClicked: {
var val = ChaperoneTabController.chaperoneVelocityModifier + 0.01
if (val > 1.0) {
val = 1.0;
}
ChaperoneTabController.chaperoneVelocityModifier = val.toFixed(2)
}
}
MyTextField {
id: velModifierText
text: "0.00"
keyBoardUID: 803
Layout.preferredWidth: 100
Layout.leftMargin: 10
horizontalAlignment: Text.AlignHCenter
function onInputEvent(input) {
var val = parseFloat(input)
if (!isNaN(val)) {
if (val < 0.0) {
val = 0.0
}
val = val.toFixed(2)
ChaperoneTabController.chaperoneVelocityModifier = val
text = val
} else {
text = ChaperoneTabController.chaperoneVelocityModifier.toFixed(2)
}
}
}
}
}
Item { Layout.fillHeight: true; Layout.fillWidth: true }
Component.onCompleted: {
switchBeginnerToggle.checked = ChaperoneTabController.chaperoneSwitchToBeginnerEnabled
var d = ChaperoneTabController.chaperoneSwitchToBeginnerDistance.toFixed(2)
if (d <= switchBeginnerDistanceSlider.to) {
switchBeginnerDistanceSlider.value = d
}
switchBeginnerDistanceText.text = d
hapticFeedbackToggle.checked = ChaperoneTabController.chaperoneHapticFeedbackEnabled
var d = ChaperoneTabController.chaperoneHapticFeedbackDistance.toFixed(2)
if (d <= hapticFeedbackDistanceSlider.to) {
hapticFeedbackDistanceSlider.value = d
}
hapticFeedbackDistanceText.text = d
audioWarningToggle.checked = ChaperoneTabController.chaperoneAlarmSoundEnabled
audioWarningLoopingToggle.checked = ChaperoneTabController.chaperoneAlarmSoundLooping
audioWarningAdjustVolumeToggle.checked = ChaperoneTabController.chaperoneAlarmSoundAdjustVolume
d = ChaperoneTabController.chaperoneAlarmSoundDistance.toFixed(2)
if (d <= audioWarningDistanceSlider.to) {
audioWarningDistanceSlider.value = d
}
audioWarningDistanceText.text = d
openDashboardToggle.checked = ChaperoneTabController.chaperoneShowDashboardEnabled
d = ChaperoneTabController.chaperoneShowDashboardDistance.toFixed(2)
if (d <= openDashboardDistanceSlider.to) {
openDashboardDistanceSlider.value = d
}
openDashboardDistanceText.text = d
velModifierToggle.checked = ChaperoneTabController.chaperoneVelocityModifierEnabled
d = ChaperoneTabController.chaperoneVelocityModifier.toFixed(2)
if (d <= velModifierSlider.to) {
velModifierSlider.value = d
}
velModifierText.text = d
}
Connections {
target: ChaperoneTabController
onChaperoneSwitchToBeginnerEnabledChanged: {
switchBeginnerToggle.checked = ChaperoneTabController.chaperoneSwitchToBeginnerEnabled
}
onChaperoneSwitchToBeginnerDistanceChanged: {
var d = ChaperoneTabController.chaperoneSwitchToBeginnerDistance.toFixed(2)
if (d <= switchBeginnerDistanceSlider.to && Math.abs(switchBeginnerDistanceSlider.value - d) > 0.0008) {
switchBeginnerDistanceSlider.value = d
}
switchBeginnerDistanceText.text = d
}
onChaperoneHapticFeedbackEnabledChanged: {
hapticFeedbackToggle.checked = ChaperoneTabController.chaperoneHapticFeedbackEnabled
}
onChaperoneHapticFeedbackDistanceChanged: {
var d = ChaperoneTabController.chaperoneHapticFeedbackDistance.toFixed(2)
if (d <= hapticFeedbackDistanceSlider.to && Math.abs(hapticFeedbackDistanceSlider.value - d) > 0.0008) {
hapticFeedbackDistanceSlider.value = d
}
hapticFeedbackDistanceText.text = d
}
onChaperoneAlarmSoundEnabledChanged: {
audioWarningToggle.checked = ChaperoneTabController.chaperoneAlarmSoundEnabled
}
onChaperoneAlarmSoundLoopingChanged: {
audioWarningLoopingToggle.checked = ChaperoneTabController.chaperoneAlarmSoundLooping
}
onChaperoneAlarmSoundDistanceChanged: {
var d = ChaperoneTabController.chaperoneAlarmSoundDistance.toFixed(2)
if (d <= audioWarningDistanceSlider.to && Math.abs(audioWarningDistanceSlider.value - d) > 0.0008) {
audioWarningDistanceSlider.value = d
}
audioWarningDistanceText.text = d
}
onChaperoneShowDashboardEnabledChanged: {
openDashboardToggle.checked = ChaperoneTabController.chaperoneShowDashboardEnabled
}
onChaperoneShowDashboardDistanceChanged: {
var d = ChaperoneTabController.chaperoneShowDashboardDistance.toFixed(2)
if (d <= openDashboardDistanceSlider.to && Math.abs(openDashboardDistanceSlider.value - d) > 0.0008) {
openDashboardDistanceSlider.value = d
}
openDashboardDistanceText.text = d
}
onChaperoneVelocityModifierEnabledChanged: {
velModifierToggle.checked = ChaperoneTabController.chaperoneVelocityModifierEnabled
}
onChaperoneVelocityModifierChanged: {
var d = ChaperoneTabController.chaperoneVelocityModifier.toFixed(2)
if (d <= velModifierSlider.to && Math.abs(velModifierSlider.value - d) > 0.0008) {
velModifierSlider.value = d
}
velModifierText.text = d
}
}
}
}
+3 -13
View File
@@ -5,19 +5,9 @@ import matzman666.advsettings 1.0
QtObject { QtObject {
function playActivationSound() { function playActivationSound() {
/*if (!OverlayController.soundDisabled()) { OverlayController.playActivationSound()
activationSound.play()
}*/
} }
function playFocusChangedSound() { function playFocusChangedSound() {
/*if (!OverlayController.soundDisabled()) { OverlayController.playFocusChangedSound()
focusChangedSound.play() }
}*/
}
/*property SoundEffect activationSound: SoundEffect {
source: vrRuntimePath + "content/panorama/sounds/activation.wav"
}
property SoundEffect focusChangedSound: SoundEffect {
source: vrRuntimePath + "content/panorama/sounds/focus_change.wav"
}*/
} }
+1 -1
View File
@@ -144,7 +144,7 @@ MyStackViewPage {
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
Layout.leftMargin: 80 Layout.leftMargin: 80
spacing: 18 spacing: 9
RowLayout { RowLayout {
spacing: 18 spacing: 18
+5
View File
@@ -23,6 +23,11 @@ Rectangle {
visible: false visible: false
} }
property ChaperoneWarningsPage chaperoneWarningsPage: ChaperoneWarningsPage {
stackView: mainView
visible: false
}
property PlayspacePage playspacePage: PlayspacePage { property PlayspacePage playspacePage: PlayspacePage {
stackView: mainView stackView: mainView
visible: false visible: false
Binary file not shown.
+3
View File
@@ -389,6 +389,7 @@ Delete $INSTDIR\qtdata\Universal\Tumbler.qml
Delete $INSTDIR\res\qml\AudioPage.qml Delete $INSTDIR\res\qml\AudioPage.qml
Delete $INSTDIR\res\qml\backarrow.svg Delete $INSTDIR\res\qml\backarrow.svg
Delete $INSTDIR\res\qml\ChaperonePage.qml Delete $INSTDIR\res\qml\ChaperonePage.qml
Delete $INSTDIR\res\qml\ChaperoneWarningsPage.qml
Delete $INSTDIR\res\qml\FixFloorPage.qml Delete $INSTDIR\res\qml\FixFloorPage.qml
Delete $INSTDIR\res\qml\mainwidget.qml Delete $INSTDIR\res\qml\mainwidget.qml
Delete $INSTDIR\res\qml\mic_off.svg Delete $INSTDIR\res\qml\mic_off.svg
@@ -419,11 +420,13 @@ Delete $INSTDIR\res\qml\SteamVRPage.qml
Delete $INSTDIR\res\qml\UtilitiesPage.qml Delete $INSTDIR\res\qml\UtilitiesPage.qml
Delete $INSTDIR\res\qml\AccessibilityPage.qml Delete $INSTDIR\res\qml\AccessibilityPage.qml
Delete $INSTDIR\res\thumbicon.png Delete $INSTDIR\res\thumbicon.png
Delete $INSTDIR\res\sounds\alarm01.wav
Delete $INSTDIR\restartvrserver.bat Delete $INSTDIR\restartvrserver.bat
Delete $INSTDIR\startdesktopmode.bat Delete $INSTDIR\startdesktopmode.bat
Delete $INSTDIR\Uninstall.exe Delete $INSTDIR\Uninstall.exe
Delete $INSTDIR\vcredist_x64.exe Delete $INSTDIR\vcredist_x64.exe
RMdir $INSTDIR\res\qml RMdir $INSTDIR\res\qml
RMdir $INSTDIR\res\sounds
RMdir $INSTDIR\res RMdir $INSTDIR\res
RMdir $INSTDIR\qtdata\Universal RMdir $INSTDIR\qtdata\Universal
RMdir $INSTDIR\qtdata\translations RMdir $INSTDIR\qtdata\translations
+17 -2
View File
@@ -95,6 +95,21 @@ void removeManifest() {
} }
class MyQApplication : public QApplication {
public:
using QApplication::QApplication;
virtual bool notify(QObject * receiver, QEvent * event) override {
try {
return QApplication::notify(receiver, event);
} catch (std::exception& e) {
LOG(ERROR) << "Exception thrown from an event handler: " << e.what();
}
return false;
}
};
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
bool desktopMode = false; bool desktopMode = false;
@@ -149,7 +164,7 @@ int main(int argc, char *argv[]) {
} }
try { try {
QApplication a(argc, argv); MyQApplication a(argc, argv);
a.setOrganizationName("matzman666"); a.setOrganizationName("matzman666");
a.setApplicationName("OpenVRAdvancedSettings"); a.setApplicationName("OpenVRAdvancedSettings");
a.setApplicationDisplayName(advsettings::OverlayController::applicationName); a.setApplicationDisplayName(advsettings::OverlayController::applicationName);
@@ -174,7 +189,7 @@ int main(int argc, char *argv[]) {
} }
conf.setRemainingToDefault(); conf.setRemainingToDefault();
el::Loggers::reconfigureAllLoggers(conf); el::Loggers::reconfigureAllLoggers(conf);
LOG(INFO) << "Application started"; LOG(INFO) << "Application started (Version " << advsettings::OverlayController::applicationVersionString << ")";
LOG(INFO) << "Log Config: " << QDir::toNativeSeparators(logconfigfile).toStdString(); LOG(INFO) << "Log Config: " << QDir::toNativeSeparators(logconfigfile).toStdString();
if (!logFilePath.isEmpty()) { if (!logFilePath.isEmpty()) {
LOG(INFO) << "Log File: " << logFilePath; LOG(INFO) << "Log File: " << logFilePath;
+110 -4
View File
@@ -15,7 +15,6 @@
#include <QCursor> #include <QCursor>
#include <QProcess> #include <QProcess>
#include <QMessageBox> #include <QMessageBox>
#include <exception>
#include <iostream> #include <iostream>
#include <cmath> #include <cmath>
#include <openvr.h> #include <openvr.h>
@@ -49,6 +48,33 @@ void OverlayController::Init(QQmlEngine* qmlEngine) {
m_runtimePathUrl = QUrl::fromLocalFile(vr::VR_RuntimePath()); m_runtimePathUrl = QUrl::fromLocalFile(vr::VR_RuntimePath());
LOG(INFO) << "VR Runtime Path: " << m_runtimePathUrl.toLocalFile(); LOG(INFO) << "VR Runtime Path: " << m_runtimePathUrl.toLocalFile();
QString activationSoundFile = m_runtimePathUrl.toLocalFile().append("/content/panorama/sounds/activation.wav");
QFileInfo activationSoundFileInfo(activationSoundFile);
if (activationSoundFileInfo.exists() && activationSoundFileInfo.isFile()) {
activationSoundEffect.setSource(QUrl::fromLocalFile(activationSoundFile));
activationSoundEffect.setVolume(1.0);
} else {
LOG(ERROR) << "Could not find activation sound file " << activationSoundFile;
}
QString focusChangedSoundFile = m_runtimePathUrl.toLocalFile().append("/content/panorama/sounds/focus_change.wav");
QFileInfo focusChangedSoundFileInfo(focusChangedSoundFile);
if (focusChangedSoundFileInfo.exists() && focusChangedSoundFileInfo.isFile()) {
focusChangedSoundEffect.setSource(QUrl::fromLocalFile(focusChangedSoundFile));
focusChangedSoundEffect.setVolume(1.0);
} else {
LOG(ERROR) << "Could not find focus changed sound file " << focusChangedSoundFile;
}
QString alarm01SoundFile = QApplication::applicationDirPath().append("/res/sounds/alarm01.wav");
QFileInfo alarm01SoundFileInfo(alarm01SoundFile);
if (alarm01SoundFileInfo.exists() && alarm01SoundFileInfo.isFile()) {
alarm01SoundEffect.setSource(QUrl::fromLocalFile(alarm01SoundFile));
alarm01SoundEffect.setVolume(1.0);
} else {
LOG(ERROR) << "Could not find alarm01 sound file " << alarm01SoundFile;
}
// Check whether OpenVR is too outdated // Check whether OpenVR is too outdated
if (!vr::VR_IsInterfaceVersionValid(vr::IVRSystem_Version)) { if (!vr::VR_IsInterfaceVersionValid(vr::IVRSystem_Version)) {
QMessageBox::critical(nullptr, "OpenVR Advanced Settings Overlay", "OpenVR version is too outdated. Please update OpenVR."); QMessageBox::critical(nullptr, "OpenVR Advanced Settings Overlay", "OpenVR version is too outdated. Please update OpenVR.");
@@ -294,13 +320,21 @@ void OverlayController::renderOverlay() {
} }
} }
bool OverlayController::pollNextEvent(vr::VROverlayHandle_t ulOverlayHandle, vr::VREvent_t* pEvent) {
if (isDesktopMode()) {
return vr::VRSystem()->PollNextEvent(pEvent, sizeof(vr::VREvent_t));
} else {
return vr::VROverlay()->PollNextOverlayEvent(ulOverlayHandle, pEvent, sizeof(vr::VREvent_t));
}
}
void OverlayController::OnTimeoutPumpEvents() { void OverlayController::OnTimeoutPumpEvents() {
if (!vr::VRSystem()) if (!vr::VRSystem())
return; return;
vr::VREvent_t vrEvent; vr::VREvent_t vrEvent;
while (vr::VROverlay()->PollNextOverlayEvent(m_ulOverlayHandle, &vrEvent, sizeof(vrEvent))) { bool chaperoneDataAlreadyUpdated = false;
while (pollNextEvent(m_ulOverlayHandle, &vrEvent)) {
switch (vrEvent.eventType) { switch (vrEvent.eventType) {
case vr::VREvent_MouseMove: { case vr::VREvent_MouseMove: {
QPoint ptNewMouse(vrEvent.data.mouse.x, vrEvent.data.mouse.y); QPoint ptNewMouse(vrEvent.data.mouse.x, vrEvent.data.mouse.y);
@@ -349,6 +383,7 @@ void OverlayController::OnTimeoutPumpEvents() {
LOG(INFO) << "Received quit request."; LOG(INFO) << "Received quit request.";
vr::VRSystem()->AcknowledgeQuit_Exiting(); // Let us buy some time just in case vr::VRSystem()->AcknowledgeQuit_Exiting(); // Let us buy some time just in case
moveCenterTabController.reset(); moveCenterTabController.reset();
chaperoneTabController.shutdown();
Shutdown(); Shutdown();
QApplication::exit(); QApplication::exit();
return; return;
@@ -373,16 +408,54 @@ void OverlayController::OnTimeoutPumpEvents() {
emit keyBoardInputSignal(QString(keyboardBuffer), vrEvent.data.keyboard.uUserValue); emit keyBoardInputSignal(QString(keyboardBuffer), vrEvent.data.keyboard.uUserValue);
} }
break; break;
// Multiple ChaperoneUniverseHasChanged are often emitted at the same time (some with a little bit of delay)
// There is no sure way to recognize redundant events, we can only exclude redundant events during the same call of OnTimeoutPumpEvents()
case vr::VREvent_ChaperoneUniverseHasChanged:
case vr::VREvent_ChaperoneDataHasChanged: {
if (!chaperoneDataAlreadyUpdated) {
LOG(INFO) << "Re-loading chaperone data ...";
m_chaperoneUtils.loadChaperoneData();
LOG(INFO) << "Found " << m_chaperoneUtils.quadsCount() << " chaperone quads.";
if (m_chaperoneUtils.isChaperoneWellFormed()) {
LOG(INFO) << "Chaperone data seems to be well-formed.";
} else {
LOG(INFO) << "Chaperone data is NOT well-formed.";
}
chaperoneDataAlreadyUpdated = true;
}
}
break;
} }
} }
vr::TrackedDevicePose_t devicePoses[vr::k_unMaxTrackedDeviceCount]; vr::TrackedDevicePose_t devicePoses[vr::k_unMaxTrackedDeviceCount];
vr::VRSystem()->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, 0.0f, devicePoses, vr::k_unMaxTrackedDeviceCount); vr::VRSystem()->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, 0.0f, devicePoses, vr::k_unMaxTrackedDeviceCount);
// HMD/Controller Velocities
auto leftId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_LeftHand);
float leftSpeed = 0.0f;
if (leftId != vr::k_unTrackedDeviceIndexInvalid && devicePoses[leftId].bPoseIsValid && devicePoses[leftId].eTrackingResult == vr::TrackingResult_Running_OK) {
auto& vel = devicePoses[leftId].vVelocity.v;
leftSpeed = std::sqrt(vel[0] * vel[0] + vel[1] * vel[1] + vel[2] * vel[2]);
}
auto rightId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_RightHand);
auto rightSpeed = 0.0f;
if (rightId != vr::k_unTrackedDeviceIndexInvalid && devicePoses[rightId].bPoseIsValid && devicePoses[rightId].eTrackingResult == vr::TrackingResult_Running_OK) {
auto& vel = devicePoses[rightId].vVelocity.v;
rightSpeed = std::sqrt(vel[0] * vel[0] + vel[1] * vel[1] + vel[2] * vel[2]);
}
auto hmdSpeed = 0.0f;
if (devicePoses[vr::k_unTrackedDeviceIndex_Hmd].bPoseIsValid && devicePoses[vr::k_unTrackedDeviceIndex_Hmd].eTrackingResult == vr::TrackingResult_Running_OK) {
auto& vel = devicePoses[vr::k_unTrackedDeviceIndex_Hmd].vVelocity.v;
hmdSpeed = std::sqrt(vel[0] * vel[0] + vel[1] * vel[1] + vel[2] * vel[2]);
}
fixFloorTabController.eventLoopTick(devicePoses); fixFloorTabController.eventLoopTick(devicePoses);
statisticsTabController.eventLoopTick(devicePoses); statisticsTabController.eventLoopTick(devicePoses, leftSpeed, rightSpeed);
moveCenterTabController.eventLoopTick(vr::VRCompositor()->GetTrackingSpace()); moveCenterTabController.eventLoopTick(vr::VRCompositor()->GetTrackingSpace());
steamVRTabController.eventLoopTick(); steamVRTabController.eventLoopTick();
chaperoneTabController.eventLoopTick(); chaperoneTabController.eventLoopTick(devicePoses, leftSpeed, rightSpeed, hmdSpeed);
settingsTabController.eventLoopTick(); settingsTabController.eventLoopTick();
reviveTabController.eventLoopTick(); reviveTabController.eventLoopTick();
audioTabController.eventLoopTick(); audioTabController.eventLoopTick();
@@ -547,4 +620,37 @@ void OverlayController::showKeyboard(QString existingText, unsigned long userVal
} }
void OverlayController::playActivationSound() {
if (!noSound) {
activationSoundEffect.play();
}
}
void OverlayController::playFocusChangedSound() {
if (!noSound) {
focusChangedSoundEffect.play();
}
}
void OverlayController::playAlarm01Sound(bool loop) {
if (!noSound && !alarm01SoundEffect.isPlaying()) {
if (loop) {
alarm01SoundEffect.setLoopCount(QSoundEffect::Infinite);
} else {
alarm01SoundEffect.setLoopCount(1);
}
alarm01SoundEffect.play();
}
}
void OverlayController::setAlarm01SoundVolume(float vol) {
alarm01SoundEffect.setVolume(vol);
}
void OverlayController::cancelAlarm01Sound() {
alarm01SoundEffect.stop();
}
} // namespace advconfig } // namespace advconfig
+19 -1
View File
@@ -19,8 +19,10 @@
#include <QQuickWindow> #include <QQuickWindow>
#include <QQuickItem> #include <QQuickItem>
#include <QQuickRenderControl> #include <QQuickRenderControl>
#include <QSoundEffect>
#include <memory> #include <memory>
#include "logging.h" #include "logging.h"
#include "utils/ChaperoneUtils.h"
#include "tabcontrollers/SteamVRTabController.h" #include "tabcontrollers/SteamVRTabController.h"
#include "tabcontrollers/ChaperoneTabController.h" #include "tabcontrollers/ChaperoneTabController.h"
@@ -45,7 +47,7 @@ class OverlayController : public QObject {
public: public:
static constexpr const char* applicationKey = "matzman666.AdvancedSettings"; static constexpr const char* applicationKey = "matzman666.AdvancedSettings";
static constexpr const char* applicationName = "Advanced Settings"; static constexpr const char* applicationName = "Advanced Settings";
static constexpr const char* applicationVersionString = "v2.4.1"; static constexpr const char* applicationVersionString = "v2.5";
private: private:
vr::VROverlayHandle_t m_ulOverlayHandle = vr::k_ulOverlayHandleInvalid; vr::VROverlayHandle_t m_ulOverlayHandle = vr::k_ulOverlayHandleInvalid;
@@ -69,6 +71,12 @@ private:
QUrl m_runtimePathUrl; QUrl m_runtimePathUrl;
utils::ChaperoneUtils m_chaperoneUtils;
QSoundEffect activationSoundEffect;
QSoundEffect focusChangedSoundEffect;
QSoundEffect alarm01SoundEffect;
public: // I know it's an ugly hack to make them public to enable external access, but I am too lazy to implement getters. public: // I know it's an ugly hack to make them public to enable external access, but I am too lazy to implement getters.
SteamVRTabController steamVRTabController; SteamVRTabController steamVRTabController;
ChaperoneTabController chaperoneTabController; ChaperoneTabController chaperoneTabController;
@@ -103,6 +111,8 @@ public:
bool isDesktopMode() { return desktopMode; }; bool isDesktopMode() { return desktopMode; };
utils::ChaperoneUtils& chaperoneUtils() noexcept { return m_chaperoneUtils; }
Q_INVOKABLE QString getVersionString(); Q_INVOKABLE QString getVersionString();
Q_INVOKABLE QUrl getVRRuntimePathUrl(); Q_INVOKABLE QUrl getVRRuntimePathUrl();
@@ -111,6 +121,8 @@ public:
const vr::VROverlayHandle_t& overlayHandle(); const vr::VROverlayHandle_t& overlayHandle();
const vr::VROverlayHandle_t& overlayThumbnailHandle(); const vr::VROverlayHandle_t& overlayThumbnailHandle();
bool pollNextEvent(vr::VROverlayHandle_t ulOverlayHandle, vr::VREvent_t* pEvent);
public slots: public slots:
void renderOverlay(); void renderOverlay();
void OnRenderRequest(); void OnRenderRequest();
@@ -118,6 +130,12 @@ public slots:
void showKeyboard(QString existingText, unsigned long userValue = 0); void showKeyboard(QString existingText, unsigned long userValue = 0);
void playActivationSound();
void playFocusChangedSound();
void playAlarm01Sound(bool loop = false);
void setAlarm01SoundVolume(float vol);
void cancelAlarm01Sound();
signals: signals:
void keyBoardInputSignal(QString input, unsigned long userValue = 0); void keyBoardInputSignal(QString input, unsigned long userValue = 0);
+528 -9
View File
@@ -8,8 +8,26 @@ namespace advsettings {
void ChaperoneTabController::initStage1() { void ChaperoneTabController::initStage1() {
m_height = getBoundsMaxY(); m_height = getBoundsMaxY();
auto settings = OverlayController::appSettings();
settings->beginGroup("chaperoneSettings");
m_enableChaperoneSwitchToBeginner = settings->value("chaperoneSwitchToBeginnerEnabled", false).toBool();
m_chaperoneSwitchToBeginnerDistance = settings->value("chaperoneSwitchToBeginnerDistance", 0.5f).toFloat();
m_enableChaperoneHapticFeedback = settings->value("chaperoneHapticFeedbackEnabled", false).toBool();
m_chaperoneHapticFeedbackDistance = settings->value("chaperoneHapticFeedbackDistance", 0.5f).toFloat();
m_enableChaperoneAlarmSound = settings->value("chaperoneAlarmSoundEnabled", false).toBool();
m_chaperoneAlarmSoundLooping = settings->value("chaperoneAlarmSoundLooping", true).toBool();
m_chaperoneAlarmSoundAdjustVolume = settings->value("chaperoneAlarmSoundAdjustVolume", false).toBool();
m_chaperoneAlarmSoundDistance = settings->value("chaperoneAlarmSoundDistance", 0.5f).toFloat();
m_enableChaperoneShowDashboard = settings->value("chaperoneShowDashboardEnabled", false).toBool();
m_chaperoneShowDashboardDistance = settings->value("chaperoneShowDashboardDistance", 0.5f).toFloat();
m_enableChaperoneVelocityModifier = settings->value("chaperoneVelocityModifierEnabled", false).toBool();
m_chaperoneVelocityModifier = settings->value("chaperoneVelocityModifier", 0.3f).toFloat();
m_chaperoneVelocityModifierCurrent = 1.0f;
settings->endGroup();
reloadChaperoneProfiles(); reloadChaperoneProfiles();
eventLoopTick(); eventLoopTick(nullptr, 0.0f, 0.0f, 0.0f);
} }
@@ -20,6 +38,14 @@ void ChaperoneTabController::initStage2(OverlayController * parent, QQuickWindow
ChaperoneTabController::~ChaperoneTabController() {
m_chaperoneHapticFeedbackActive = false;
if (m_chaperoneHapticFeedbackThread.joinable()) {
m_chaperoneHapticFeedbackThread.join();
}
}
void ChaperoneTabController::reloadChaperoneProfiles() { void ChaperoneTabController::reloadChaperoneProfiles() {
chaperoneProfiles.clear(); chaperoneProfiles.clear();
auto settings = OverlayController::appSettings(); auto settings = OverlayController::appSettings();
@@ -94,6 +120,21 @@ void ChaperoneTabController::reloadChaperoneProfiles() {
if (entry.includesForceBounds) { if (entry.includesForceBounds) {
entry.forceBounds = settings->value("forceBounds", false).toBool(); entry.forceBounds = settings->value("forceBounds", false).toBool();
} }
entry.includesProximityWarningSettings = settings->value("includesProximityWarningSettings", false).toBool();
if (entry.includesProximityWarningSettings){
entry.enableChaperoneSwitchToBeginner = settings->value("chaperoneSwitchToBeginnerEnabled", false).toBool();
entry.chaperoneSwitchToBeginnerDistance = settings->value("chaperoneSwitchToBeginnerDistance", 0.5f).toFloat();
entry.enableChaperoneHapticFeedback = settings->value("chaperoneHapticFeedbackEnabled", false).toBool();
entry.chaperoneHapticFeedbackDistance = settings->value("chaperoneHapticFeedbackDistance", 0.5f).toFloat();
entry.enableChaperoneAlarmSound = settings->value("chaperoneAlarmSoundEnabled", false).toBool();
entry.chaperoneAlarmSoundLooping = settings->value("chaperoneAlarmSoundLooping", true).toBool();
entry.chaperoneAlarmSoundAdjustVolume = settings->value("chaperoneAlarmSoundAdjustVolume", false).toBool();
entry.chaperoneAlarmSoundDistance = settings->value("chaperoneAlarmSoundDistance", 0.5f).toFloat();
entry.enableChaperoneShowDashboard = settings->value("chaperoneShowDashboardEnabled", false).toBool();
entry.chaperoneShowDashboardDistance = settings->value("chaperoneShowDashboardDistance", 0.5f).toFloat();
entry.enableChaperoneVelocityModifier = settings->value("chaperoneVelocityModifierEnabled", false).toBool();
entry.chaperoneVelocityModifier = settings->value("chaperoneVelocityModifier", 0.3f).toFloat();
}
} }
settings->endArray(); settings->endArray();
settings->endGroup(); settings->endGroup();
@@ -171,15 +212,191 @@ void ChaperoneTabController::saveChaperoneProfiles() {
if (p.includesForceBounds) { if (p.includesForceBounds) {
settings->setValue("forceBounds", p.forceBounds); settings->setValue("forceBounds", p.forceBounds);
} }
settings->setValue("includesProximityWarningSettings", p.includesProximityWarningSettings);
if (p.includesProximityWarningSettings) {
settings->setValue("chaperoneSwitchToBeginnerEnabled", p.enableChaperoneSwitchToBeginner);
settings->setValue("chaperoneSwitchToBeginnerDistance", p.chaperoneSwitchToBeginnerDistance);
settings->setValue("chaperoneHapticFeedbackEnabled", p.enableChaperoneHapticFeedback);
settings->setValue("chaperoneHapticFeedbackDistance", p.chaperoneHapticFeedbackDistance);
settings->setValue("chaperoneAlarmSoundEnabled", p.enableChaperoneAlarmSound);
settings->setValue("chaperoneAlarmSoundLooping", p.chaperoneAlarmSoundLooping);
settings->setValue("chaperoneAlarmSoundAdjustVolume", p.chaperoneAlarmSoundAdjustVolume);
settings->setValue("chaperoneAlarmSoundDistance", p.chaperoneAlarmSoundDistance);
settings->setValue("chaperoneShowDashboardEnabled", p.enableChaperoneShowDashboard);
settings->setValue("chaperoneShowDashboardDistance", p.chaperoneShowDashboardDistance);
settings->setValue("chaperoneVelocityModifierEnabled", p.enableChaperoneVelocityModifier);
settings->setValue("chaperoneVelocityModifier", p.chaperoneVelocityModifier);
}
i++; i++;
} }
settings->endArray(); settings->endArray();
settings->endGroup(); settings->endGroup();
} }
void ChaperoneTabController::eventLoopTick() { void ChaperoneTabController::handleChaperoneWarnings(float distance) {
vr::VRControllerState_t hmdState;
vr::VRSystem()->GetControllerState(vr::k_unTrackedDeviceIndex_Hmd, &hmdState, sizeof(vr::VRControllerState_t));
// Switch to Beginner Mode
if (m_enableChaperoneSwitchToBeginner) {
float activationDistance = m_chaperoneSwitchToBeginnerDistance * m_chaperoneVelocityModifierCurrent;
if (distance <= activationDistance && (hmdState.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_ProximitySensor)) && !m_chaperoneSwitchToBeginnerActive) {
vr::EVRSettingsError vrSettingsError;
m_chaperoneSwitchToBeginnerLastStyle = vr::VRSettings()->GetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_Style_Int32, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not read \"" << vr::k_pch_CollisionBounds_Style_Int32 << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
} else {
vr::VRSettings()->SetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_Style_Int32, vr::COLLISION_BOUNDS_STYLE_BEGINNER, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not set \"" << vr::k_pch_CollisionBounds_Style_Int32 << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
} else {
vr::VRSettings()->Sync(true);
m_chaperoneSwitchToBeginnerActive = true;
}
}
} else if ((distance > activationDistance || !(hmdState.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_ProximitySensor))) && m_chaperoneSwitchToBeginnerActive) {
vr::EVRSettingsError vrSettingsError;
vr::VRSettings()->SetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_Style_Int32, m_chaperoneSwitchToBeginnerLastStyle, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not set \"" << vr::k_pch_CollisionBounds_Style_Int32 << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
} else {
vr::VRSettings()->Sync(true);
m_chaperoneSwitchToBeginnerActive = false;
}
}
}
// Haptic Feedback
if (m_enableChaperoneHapticFeedback) {
float activationDistance = m_chaperoneHapticFeedbackDistance * m_chaperoneVelocityModifierCurrent;
if (distance <= activationDistance && (hmdState.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_ProximitySensor))) {
if (!m_chaperoneHapticFeedbackActive) {
if (m_chaperoneHapticFeedbackThread.joinable()) {
m_chaperoneHapticFeedbackActive = false;
m_chaperoneHapticFeedbackThread.join();
}
m_chaperoneHapticFeedbackActive = true;
m_chaperoneHapticFeedbackThread = std::thread([](ChaperoneTabController* _this) {
auto leftIndex = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_LeftHand);
auto rightIndex = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_RightHand);
while (_this->m_chaperoneHapticFeedbackActive) {
if (leftIndex != vr::k_unTrackedDeviceIndexInvalid) {
vr::VRSystem()->TriggerHapticPulse(leftIndex, 0, 2000);
}
if (rightIndex != vr::k_unTrackedDeviceIndexInvalid) {
vr::VRSystem()->TriggerHapticPulse(rightIndex, 0, 2000);
}
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
}, this);
}
} else if ((distance > activationDistance || !(hmdState.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_ProximitySensor))) && m_chaperoneHapticFeedbackActive) {
m_chaperoneHapticFeedbackActive = false;
}
}
// Alarm Sound
if (m_enableChaperoneAlarmSound) {
float activationDistance = m_chaperoneAlarmSoundDistance * m_chaperoneVelocityModifierCurrent;
if (distance <= activationDistance && (hmdState.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_ProximitySensor))) {
if (!m_chaperoneAlarmSoundActive) {
parent->playAlarm01Sound(m_chaperoneAlarmSoundLooping);
m_chaperoneAlarmSoundActive = true;
}
if (m_chaperoneAlarmSoundLooping && m_chaperoneAlarmSoundAdjustVolume) {
float vol = 1.1f - distance / activationDistance;
if (vol > 1.0f) {
vol = 1.0f;
}
parent->setAlarm01SoundVolume(vol);
} else {
parent->setAlarm01SoundVolume(1.0f);
}
} else if ((distance > activationDistance || !(hmdState.ulButtonPressed & vr::ButtonMaskFromId(vr::k_EButton_ProximitySensor))) && m_chaperoneAlarmSoundActive) {
parent->cancelAlarm01Sound();
m_chaperoneAlarmSoundActive = false;
}
}
// Show Dashboard
if (m_enableChaperoneShowDashboard) {
float activationDistance = m_chaperoneShowDashboardDistance * m_chaperoneVelocityModifierCurrent;
if (distance <= activationDistance && !m_chaperoneShowDashboardActive) {
if (!vr::VROverlay()->IsDashboardVisible()) {
vr::VROverlay()->ShowDashboard(OverlayController::applicationKey);
}
m_chaperoneShowDashboardActive = true;
} else if (distance > activationDistance && m_chaperoneShowDashboardActive) {
m_chaperoneShowDashboardActive = false;
}
}
}
void ChaperoneTabController::eventLoopTick(vr::TrackedDevicePose_t* devicePoses, float leftSpeed, float rightSpeed, float hmdSpeed) {
m_chaperoneVelocityModifierCurrent = 1.0f;
if (m_enableChaperoneVelocityModifier) {
float mod = m_chaperoneVelocityModifier * std::max({ leftSpeed, rightSpeed, hmdSpeed });
if (mod > 0.02) {
m_chaperoneVelocityModifierCurrent += mod;
}
}
//LOG(INFO) << "m_chaperoneVelocityModifierCurrent: " << m_chaperoneVelocityModifierCurrent;
float newFadeDistance = m_fadeDistance * m_chaperoneVelocityModifierCurrent;
if (m_fadeDistanceModified != newFadeDistance) {
m_fadeDistanceModified = newFadeDistance;
vr::VRSettings()->SetFloat(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_FadeDistance_Float, m_fadeDistanceModified);
vr::VRSettings()->Sync();
}
if (devicePoses) {
std::lock_guard<std::recursive_mutex> lock(parent->chaperoneUtils().mutex());
auto minDistance = NAN;
auto& poseHmd = devicePoses[vr::k_unTrackedDeviceIndex_Hmd];
if (poseHmd.bPoseIsValid && poseHmd.bDeviceIsConnected && poseHmd.eTrackingResult == vr::TrackingResult_Running_OK) {
auto distanceHmd = parent->chaperoneUtils().getDistanceToChaperone({
poseHmd.mDeviceToAbsoluteTracking.m[0][3],
poseHmd.mDeviceToAbsoluteTracking.m[1][3],
poseHmd.mDeviceToAbsoluteTracking.m[2][3]
});
if (!isnan(distanceHmd)) {
minDistance = distanceHmd;
}
}
auto leftIndex = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_LeftHand);
if (leftIndex != vr::k_unTrackedDeviceIndexInvalid) {
auto& poseLeft = devicePoses[leftIndex];
if (poseLeft.bPoseIsValid && poseLeft.bDeviceIsConnected && poseLeft.eTrackingResult == vr::TrackingResult_Running_OK) {
auto distanceLeft = parent->chaperoneUtils().getDistanceToChaperone({
poseLeft.mDeviceToAbsoluteTracking.m[0][3],
poseLeft.mDeviceToAbsoluteTracking.m[1][3],
poseLeft.mDeviceToAbsoluteTracking.m[2][3]
});
if (!isnan(distanceLeft) && (isnan(minDistance) || distanceLeft < minDistance)) {
minDistance = distanceLeft;
}
}
}
auto rightIndex = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_RightHand);
if (rightIndex != vr::k_unTrackedDeviceIndexInvalid) {
auto& poseRight = devicePoses[rightIndex];
if (poseRight.bPoseIsValid && poseRight.bDeviceIsConnected && poseRight.eTrackingResult == vr::TrackingResult_Running_OK) {
auto distanceRight = parent->chaperoneUtils().getDistanceToChaperone({
poseRight.mDeviceToAbsoluteTracking.m[0][3],
poseRight.mDeviceToAbsoluteTracking.m[1][3],
poseRight.mDeviceToAbsoluteTracking.m[2][3]
});
if (!isnan(distanceRight) && (isnan(minDistance) || distanceRight < minDistance)) {
minDistance = distanceRight;
}
}
}
if (!isnan(minDistance)) {
handleChaperoneWarnings(minDistance);
}
}
if (settingsUpdateCounter >= 50) { if (settingsUpdateCounter >= 50) {
vr::EVRSettingsError vrSettingsError; vr::EVRSettingsError vrSettingsError;
float vis = vr::VRSettings()->GetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_ColorGammaA_Int32, &vrSettingsError); float vis = vr::VRSettings()->GetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_ColorGammaA_Int32, &vrSettingsError);
@@ -187,11 +404,13 @@ void ChaperoneTabController::eventLoopTick() {
LOG(WARNING) << "Could not read \"" << vr::k_pch_CollisionBounds_ColorGammaA_Int32 << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError); LOG(WARNING) << "Could not read \"" << vr::k_pch_CollisionBounds_ColorGammaA_Int32 << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
} }
setBoundsVisibility(vis/255.0f); setBoundsVisibility(vis/255.0f);
auto fd = vr::VRSettings()->GetFloat(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_FadeDistance_Float, &vrSettingsError); if (m_chaperoneVelocityModifierCurrent == 1.0f) {
if (vrSettingsError != vr::VRSettingsError_None) { auto fd = vr::VRSettings()->GetFloat(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_FadeDistance_Float, &vrSettingsError);
LOG(WARNING) << "Could not read \"" << vr::k_pch_CollisionBounds_FadeDistance_Float << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError); if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not read \"" << vr::k_pch_CollisionBounds_FadeDistance_Float << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
}
setFadeDistance(fd);
} }
setFadeDistance(fd);
auto cm = vr::VRSettings()->GetBool(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_CenterMarkerOn_Bool, &vrSettingsError); auto cm = vr::VRSettings()->GetBool(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_CenterMarkerOn_Bool, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) { if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not read \"" << vr::k_pch_CollisionBounds_CenterMarkerOn_Bool << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError); LOG(WARNING) << "Could not read \"" << vr::k_pch_CollisionBounds_CenterMarkerOn_Bool << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
@@ -319,6 +538,62 @@ bool ChaperoneTabController::forceBounds() const {
return m_forceBounds; return m_forceBounds;
} }
bool ChaperoneTabController::isChaperoneSwitchToBeginnerEnabled() const {
return m_enableChaperoneSwitchToBeginner;
}
float ChaperoneTabController::chaperoneSwitchToBeginnerDistance() const {
return m_chaperoneSwitchToBeginnerDistance;
}
bool ChaperoneTabController::isChaperoneHapticFeedbackEnabled() const {
return m_enableChaperoneHapticFeedback;
}
float ChaperoneTabController::chaperoneHapticFeedbackDistance() const {
return m_chaperoneHapticFeedbackDistance;
}
bool ChaperoneTabController::isChaperoneAlarmSoundEnabled() const {
return m_enableChaperoneAlarmSound;
}
bool ChaperoneTabController::isChaperoneAlarmSoundLooping() const {
return m_chaperoneAlarmSoundLooping;
}
bool ChaperoneTabController::isChaperoneAlarmSoundAdjustVolume() const {
return m_chaperoneAlarmSoundAdjustVolume;
}
float ChaperoneTabController::chaperoneAlarmSoundDistance() const {
return m_chaperoneAlarmSoundDistance;
}
bool ChaperoneTabController::isChaperoneShowDashboardEnabled() const {
return m_enableChaperoneShowDashboard;
}
float ChaperoneTabController::chaperoneShowDashboardDistance() const {
return m_chaperoneShowDashboardDistance;
}
bool ChaperoneTabController::isChaperoneVelocityModifierEnabled() const {
return m_enableChaperoneVelocityModifier;
}
float ChaperoneTabController::chaperoneVelocityModifier() const {
return m_chaperoneVelocityModifier;
}
Q_INVOKABLE unsigned ChaperoneTabController::getChaperoneProfileCount() { Q_INVOKABLE unsigned ChaperoneTabController::getChaperoneProfileCount() {
return (unsigned)chaperoneProfiles.size(); return (unsigned)chaperoneProfiles.size();
} }
@@ -341,6 +616,207 @@ void ChaperoneTabController::setForceBounds(bool value, bool notify) {
} }
} }
void ChaperoneTabController::setChaperoneSwitchToBeginnerEnabled(bool value, bool notify) {
if (m_enableChaperoneSwitchToBeginner != value) {
if (!value && m_chaperoneSwitchToBeginnerActive) {
vr::EVRSettingsError vrSettingsError;
vr::VRSettings()->SetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_Style_Int32, m_chaperoneSwitchToBeginnerLastStyle, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not set \"" << vr::k_pch_CollisionBounds_Style_Int32 << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
} else {
vr::VRSettings()->Sync(true);
}
}
m_enableChaperoneSwitchToBeginner = value;
m_chaperoneSwitchToBeginnerActive = false;
auto settings = OverlayController::appSettings();
settings->beginGroup("chaperoneSettings");
settings->setValue("chaperoneSwitchToBeginnerEnabled", m_enableChaperoneSwitchToBeginner);
settings->endGroup();
settings->sync();
if (notify) {
emit chaperoneSwitchToBeginnerEnabledChanged(m_enableChaperoneSwitchToBeginner);
}
}
}
void ChaperoneTabController::setChaperoneSwitchToBeginnerDistance(float value, bool notify) {
if (m_chaperoneSwitchToBeginnerDistance != value) {
m_chaperoneSwitchToBeginnerDistance = value;
auto settings = OverlayController::appSettings();
settings->beginGroup("chaperoneSettings");
settings->setValue("chaperoneSwitchToBeginnerDistance", m_chaperoneSwitchToBeginnerDistance);
settings->endGroup();
settings->sync();
if (notify) {
emit chaperoneSwitchToBeginnerDistanceChanged(m_chaperoneSwitchToBeginnerDistance);
}
}
}
void ChaperoneTabController::setChaperoneHapticFeedbackEnabled(bool value, bool notify) {
if (m_enableChaperoneHapticFeedback != value) {
m_chaperoneHapticFeedbackActive = false;
if (m_chaperoneHapticFeedbackThread.joinable()) {
m_chaperoneHapticFeedbackThread.join();
}
m_enableChaperoneHapticFeedback = value;
auto settings = OverlayController::appSettings();
settings->beginGroup("chaperoneSettings");
settings->setValue("chaperoneHapticFeedbackEnabled", m_enableChaperoneHapticFeedback);
settings->endGroup();
settings->sync();
if (notify) {
emit chaperoneHapticFeedbackEnabledChanged(m_enableChaperoneHapticFeedback);
}
}
}
void ChaperoneTabController::setChaperoneHapticFeedbackDistance(float value, bool notify) {
if (m_chaperoneHapticFeedbackDistance != value) {
m_chaperoneHapticFeedbackDistance = value;
auto settings = OverlayController::appSettings();
settings->beginGroup("chaperoneSettings");
settings->setValue("chaperoneHapticFeedbackDistance", m_chaperoneHapticFeedbackDistance);
settings->endGroup();
settings->sync();
if (notify) {
emit chaperoneHapticFeedbackDistanceChanged(m_chaperoneHapticFeedbackDistance);
}
}
}
void ChaperoneTabController::setChaperoneAlarmSoundEnabled(bool value, bool notify) {
if (m_enableChaperoneAlarmSound != value) {
if (!value && m_chaperoneAlarmSoundActive) {
parent->cancelAlarm01Sound();
}
m_enableChaperoneAlarmSound = value;
m_chaperoneAlarmSoundActive = false;
auto settings = OverlayController::appSettings();
settings->beginGroup("chaperoneSettings");
settings->setValue("chaperoneAlarmSoundEnabled", m_enableChaperoneAlarmSound);
settings->endGroup();
settings->sync();
if (notify) {
emit chaperoneAlarmSoundEnabledChanged(m_enableChaperoneAlarmSound);
}
}
}
void ChaperoneTabController::setChaperoneAlarmSoundLooping(bool value, bool notify) {
if (m_chaperoneAlarmSoundLooping != value) {
m_chaperoneAlarmSoundLooping = value;
if (m_enableChaperoneAlarmSound && m_chaperoneAlarmSoundActive) {
if (m_chaperoneAlarmSoundLooping) {
parent->playAlarm01Sound(m_chaperoneAlarmSoundLooping);
} else {
parent->cancelAlarm01Sound();
}
}
auto settings = OverlayController::appSettings();
settings->beginGroup("chaperoneSettings");
settings->setValue("chaperoneAlarmSoundLooping", m_chaperoneAlarmSoundLooping);
settings->endGroup();
settings->sync();
if (notify) {
emit chaperoneAlarmSoundLoopingChanged(m_chaperoneAlarmSoundLooping);
}
}
}
void ChaperoneTabController::setChaperoneAlarmSoundAdjustVolume(bool value, bool notify) {
if (m_chaperoneAlarmSoundAdjustVolume != value) {
m_chaperoneAlarmSoundAdjustVolume = value;
auto settings = OverlayController::appSettings();
settings->beginGroup("chaperoneSettings");
settings->setValue("chaperoneAlarmSoundAdjustVolume", m_chaperoneAlarmSoundAdjustVolume);
settings->endGroup();
settings->sync();
if (notify) {
emit chaperoneAlarmSoundAdjustVolumeChanged(m_chaperoneAlarmSoundAdjustVolume);
}
}
}
void ChaperoneTabController::setChaperoneAlarmSoundDistance(float value, bool notify) {
if (m_chaperoneAlarmSoundDistance != value) {
m_chaperoneAlarmSoundDistance = value;
auto settings = OverlayController::appSettings();
settings->beginGroup("chaperoneSettings");
settings->setValue("chaperoneAlarmSoundDistance", m_chaperoneAlarmSoundDistance);
settings->endGroup();
settings->sync();
if (notify) {
emit chaperoneAlarmSoundDistanceChanged(m_chaperoneAlarmSoundDistance);
}
}
}
void ChaperoneTabController::setChaperoneShowDashboardEnabled(bool value, bool notify) {
if (m_enableChaperoneShowDashboard != value) {
m_enableChaperoneShowDashboard = value;
m_chaperoneShowDashboardActive = false;
auto settings = OverlayController::appSettings();
settings->beginGroup("chaperoneSettings");
settings->setValue("chaperoneShowDashboardEnabled", m_enableChaperoneShowDashboard);
settings->endGroup();
settings->sync();
if (notify) {
emit chaperoneShowDashboardEnabledChanged(m_enableChaperoneShowDashboard);
}
}
}
void ChaperoneTabController::setChaperoneShowDashboardDistance(float value, bool notify) {
if (m_chaperoneShowDashboardDistance != value) {
m_chaperoneShowDashboardDistance = value;
auto settings = OverlayController::appSettings();
settings->beginGroup("chaperoneSettings");
settings->setValue("chaperoneShowDashboardDistance", m_chaperoneShowDashboardDistance);
settings->endGroup();
settings->sync();
if (notify) {
emit chaperoneShowDashboardDistanceChanged(m_chaperoneShowDashboardDistance);
}
}
}
void ChaperoneTabController::setChaperoneVelocityModifierEnabled(bool value, bool notify) {
if (m_enableChaperoneVelocityModifier != value) {
m_enableChaperoneVelocityModifier = value;
auto settings = OverlayController::appSettings();
settings->beginGroup("chaperoneSettings");
settings->setValue("chaperoneVelocityModifierEnabled", m_enableChaperoneVelocityModifier);
settings->endGroup();
settings->sync();
if (notify) {
emit chaperoneVelocityModifierEnabledChanged(m_enableChaperoneVelocityModifier);
}
}
}
void ChaperoneTabController::setChaperoneVelocityModifier(float value, bool notify) {
if (m_chaperoneVelocityModifier != value) {
m_chaperoneVelocityModifier = value;
auto settings = OverlayController::appSettings();
settings->beginGroup("chaperoneSettings");
settings->setValue("chaperoneVelocityModifier", m_chaperoneVelocityModifier);
settings->endGroup();
settings->sync();
if (notify) {
emit chaperoneVelocityModifierChanged(m_chaperoneVelocityModifier);
}
}
}
void ChaperoneTabController::flipOrientation() { void ChaperoneTabController::flipOrientation() {
parent->RotateUniverseCenter(vr::TrackingUniverseStanding, (float)M_PI); parent->RotateUniverseCenter(vr::TrackingUniverseStanding, (float)M_PI);
} }
@@ -351,7 +827,7 @@ void ChaperoneTabController::reloadFromDisk() {
} }
void ChaperoneTabController::addChaperoneProfile(QString name, bool includeGeometry, bool includeVisbility, bool includeFadeDistance, bool includeCenterMarker, void ChaperoneTabController::addChaperoneProfile(QString name, bool includeGeometry, bool includeVisbility, bool includeFadeDistance, bool includeCenterMarker,
bool includePlaySpaceMarker, bool includeFloorBounds, bool includeBoundsColor, bool includeChaperoneStyle, bool includeForceBounds) { bool includePlaySpaceMarker, bool includeFloorBounds, bool includeBoundsColor, bool includeChaperoneStyle, bool includeForceBounds, bool includesProximityWarningSettings) {
vr::EVRSettingsError vrSettingsError; vr::EVRSettingsError vrSettingsError;
ChaperoneProfile* profile = nullptr; ChaperoneProfile* profile = nullptr;
for (auto& p : chaperoneProfiles) { for (auto& p : chaperoneProfiles) {
@@ -426,6 +902,21 @@ void ChaperoneTabController::addChaperoneProfile(QString name, bool includeGeome
if (includeForceBounds) { if (includeForceBounds) {
profile->forceBounds = m_forceBounds; profile->forceBounds = m_forceBounds;
} }
profile->includesProximityWarningSettings = includesProximityWarningSettings;
if (includesProximityWarningSettings) {
profile->enableChaperoneSwitchToBeginner = m_enableChaperoneSwitchToBeginner;
profile->chaperoneSwitchToBeginnerDistance = m_chaperoneSwitchToBeginnerDistance;
profile->enableChaperoneHapticFeedback = m_enableChaperoneHapticFeedback;
profile->chaperoneHapticFeedbackDistance = m_chaperoneHapticFeedbackDistance;
profile->enableChaperoneAlarmSound = m_enableChaperoneAlarmSound;
profile->chaperoneAlarmSoundLooping = m_chaperoneAlarmSoundLooping;
profile->chaperoneAlarmSoundAdjustVolume = m_chaperoneAlarmSoundAdjustVolume;
profile->chaperoneAlarmSoundDistance = m_chaperoneAlarmSoundDistance;
profile->enableChaperoneShowDashboard = m_enableChaperoneShowDashboard;
profile->chaperoneShowDashboardDistance = m_chaperoneShowDashboardDistance;
profile->enableChaperoneVelocityModifier = m_enableChaperoneVelocityModifier;
profile->chaperoneVelocityModifier = m_chaperoneVelocityModifier;
}
saveChaperoneProfiles(); saveChaperoneProfiles();
OverlayController::appSettings()->sync(); OverlayController::appSettings()->sync();
emit chaperoneProfilesUpdated(); emit chaperoneProfilesUpdated();
@@ -467,7 +958,21 @@ void ChaperoneTabController::applyChaperoneProfile(unsigned index) {
if (profile.includesForceBounds) { if (profile.includesForceBounds) {
setForceBounds(profile.forceBounds); setForceBounds(profile.forceBounds);
} }
vr::VRSettings()->Sync(); if (profile.includesProximityWarningSettings) {
setChaperoneSwitchToBeginnerDistance(profile.chaperoneSwitchToBeginnerDistance);
setChaperoneSwitchToBeginnerEnabled(profile.enableChaperoneSwitchToBeginner);
setChaperoneHapticFeedbackDistance(profile.chaperoneHapticFeedbackDistance);
setChaperoneHapticFeedbackEnabled(profile.enableChaperoneHapticFeedback);
setChaperoneAlarmSoundLooping(profile.chaperoneAlarmSoundLooping);
setChaperoneAlarmSoundAdjustVolume(profile.chaperoneAlarmSoundAdjustVolume);
setChaperoneAlarmSoundDistance(profile.chaperoneAlarmSoundDistance);
setChaperoneAlarmSoundEnabled(profile.enableChaperoneAlarmSound);
setChaperoneShowDashboardDistance(profile.chaperoneShowDashboardDistance);
setChaperoneShowDashboardEnabled(profile.enableChaperoneShowDashboard);
setChaperoneVelocityModifier(profile.chaperoneVelocityModifier);
setChaperoneVelocityModifierEnabled(profile.enableChaperoneVelocityModifier);
}
vr::VRSettings()->Sync(true);
updateHeight(getBoundsMaxY()); updateHeight(getBoundsMaxY());
} }
} }
@@ -534,4 +1039,18 @@ void ChaperoneTabController::reset() {
settingsUpdateCounter = 999; // Easiest way to get default values settingsUpdateCounter = 999; // Easiest way to get default values
} }
void ChaperoneTabController::shutdown() {
if (m_enableChaperoneSwitchToBeginner && m_chaperoneSwitchToBeginnerActive) {
vr::EVRSettingsError vrSettingsError;
vr::VRSettings()->SetInt32(vr::k_pch_CollisionBounds_Section, vr::k_pch_CollisionBounds_Style_Int32, m_chaperoneSwitchToBeginnerLastStyle, &vrSettingsError);
if (vrSettingsError != vr::VRSettingsError_None) {
LOG(WARNING) << "Could not set \"" << vr::k_pch_CollisionBounds_Style_Int32 << "\" setting: " << vr::VRSettings()->GetSettingsErrorNameFromEnum(vrSettingsError);
} else {
vr::VRSettings()->Sync(true);
}
}
}
} // namespace advconfig } // namespace advconfig
+117 -2
View File
@@ -3,6 +3,8 @@
#include <QObject> #include <QObject>
#include <memory> #include <memory>
#include <chrono>
#include <thread>
#include <openvr.h> #include <openvr.h>
class QQuickWindow; class QQuickWindow;
@@ -46,6 +48,20 @@ struct ChaperoneProfile {
bool includesForceBounds = false; bool includesForceBounds = false;
bool forceBounds = false; bool forceBounds = false;
bool includesProximityWarningSettings = false;
bool enableChaperoneSwitchToBeginner = false;
float chaperoneSwitchToBeginnerDistance = 0.0f;
bool enableChaperoneHapticFeedback = false;
float chaperoneHapticFeedbackDistance = 0.0f;
bool enableChaperoneAlarmSound = false;
bool chaperoneAlarmSoundLooping = true;
bool chaperoneAlarmSoundAdjustVolume = false;
float chaperoneAlarmSoundDistance = 0.0f;
bool enableChaperoneShowDashboard = false;
float chaperoneShowDashboardDistance = 0.0f;
bool enableChaperoneVelocityModifier = false;
float chaperoneVelocityModifier = 0.0f;
}; };
@@ -58,26 +74,71 @@ class ChaperoneTabController : public QObject {
Q_PROPERTY(bool playSpaceMarker READ playSpaceMarker WRITE setPlaySpaceMarker NOTIFY playSpaceMarkerChanged) Q_PROPERTY(bool playSpaceMarker READ playSpaceMarker WRITE setPlaySpaceMarker NOTIFY playSpaceMarkerChanged)
Q_PROPERTY(bool forceBounds READ forceBounds WRITE setForceBounds NOTIFY forceBoundsChanged) Q_PROPERTY(bool forceBounds READ forceBounds WRITE setForceBounds NOTIFY forceBoundsChanged)
Q_PROPERTY(bool chaperoneSwitchToBeginnerEnabled READ isChaperoneSwitchToBeginnerEnabled WRITE setChaperoneSwitchToBeginnerEnabled NOTIFY chaperoneSwitchToBeginnerEnabledChanged)
Q_PROPERTY(float chaperoneSwitchToBeginnerDistance READ chaperoneSwitchToBeginnerDistance WRITE setChaperoneSwitchToBeginnerDistance NOTIFY chaperoneSwitchToBeginnerDistanceChanged)
Q_PROPERTY(bool chaperoneHapticFeedbackEnabled READ isChaperoneHapticFeedbackEnabled WRITE setChaperoneHapticFeedbackEnabled NOTIFY chaperoneHapticFeedbackEnabledChanged)
Q_PROPERTY(float chaperoneHapticFeedbackDistance READ chaperoneHapticFeedbackDistance WRITE setChaperoneHapticFeedbackDistance NOTIFY chaperoneHapticFeedbackDistanceChanged)
Q_PROPERTY(bool chaperoneAlarmSoundEnabled READ isChaperoneAlarmSoundEnabled WRITE setChaperoneAlarmSoundEnabled NOTIFY chaperoneAlarmSoundEnabledChanged)
Q_PROPERTY(bool chaperoneAlarmSoundLooping READ isChaperoneAlarmSoundLooping WRITE setChaperoneAlarmSoundLooping NOTIFY chaperoneAlarmSoundLoopingChanged)
Q_PROPERTY(bool chaperoneAlarmSoundAdjustVolume READ isChaperoneAlarmSoundAdjustVolume WRITE setChaperoneAlarmSoundAdjustVolume NOTIFY chaperoneAlarmSoundAdjustVolumeChanged)
Q_PROPERTY(float chaperoneAlarmSoundDistance READ chaperoneAlarmSoundDistance WRITE setChaperoneAlarmSoundDistance NOTIFY chaperoneAlarmSoundDistanceChanged)
Q_PROPERTY(bool chaperoneShowDashboardEnabled READ isChaperoneShowDashboardEnabled WRITE setChaperoneShowDashboardEnabled NOTIFY chaperoneShowDashboardEnabledChanged)
Q_PROPERTY(float chaperoneShowDashboardDistance READ chaperoneShowDashboardDistance WRITE setChaperoneShowDashboardDistance NOTIFY chaperoneShowDashboardDistanceChanged)
Q_PROPERTY(bool chaperoneVelocityModifierEnabled READ isChaperoneVelocityModifierEnabled WRITE setChaperoneVelocityModifierEnabled NOTIFY chaperoneVelocityModifierEnabledChanged)
Q_PROPERTY(float chaperoneVelocityModifier READ chaperoneVelocityModifier WRITE setChaperoneVelocityModifier NOTIFY chaperoneVelocityModifierChanged)
private: private:
OverlayController* parent; OverlayController* parent;
QQuickWindow* widget; QQuickWindow* widget;
float m_visibility = 0.6f; float m_visibility = 0.6f;
float m_fadeDistance = 0.7f; float m_fadeDistance = 0.7f;
float m_fadeDistanceModified = 0.7f;
float m_height = 2.0f; float m_height = 2.0f;
bool m_centerMarker = false; bool m_centerMarker = false;
bool m_playSpaceMarker = false; bool m_playSpaceMarker = false;
bool m_forceBounds = false; bool m_forceBounds = false;
bool m_enableChaperoneSwitchToBeginner = false;
float m_chaperoneSwitchToBeginnerDistance = 0.5f;
bool m_chaperoneSwitchToBeginnerActive = false;
int32_t m_chaperoneSwitchToBeginnerLastStyle = 0;
bool m_enableChaperoneHapticFeedback = true;
float m_chaperoneHapticFeedbackDistance = 0.5f;
bool m_chaperoneHapticFeedbackActive = false;
std::thread m_chaperoneHapticFeedbackThread;
bool m_enableChaperoneAlarmSound = false;
bool m_chaperoneAlarmSoundLooping = true;
bool m_chaperoneAlarmSoundAdjustVolume = false;
float m_chaperoneAlarmSoundDistance = 0.5f;
bool m_chaperoneAlarmSoundActive = false;
bool m_enableChaperoneShowDashboard = false;
float m_chaperoneShowDashboardDistance = 0.5f;
bool m_chaperoneShowDashboardActive = false;
bool m_enableChaperoneVelocityModifier = false;
float m_chaperoneVelocityModifier = 0.0f;
float m_chaperoneVelocityModifierCurrent = 1.0f;
unsigned settingsUpdateCounter = 0; unsigned settingsUpdateCounter = 0;
std::vector<ChaperoneProfile> chaperoneProfiles; std::vector<ChaperoneProfile> chaperoneProfiles;
public: public:
~ChaperoneTabController();
void initStage1(); void initStage1();
void initStage2(OverlayController* parent, QQuickWindow* widget); void initStage2(OverlayController* parent, QQuickWindow* widget);
void eventLoopTick(); void eventLoopTick(vr::TrackedDevicePose_t* devicePoses, float leftSpeed, float rightSpeed, float hmdSpeed);
void handleChaperoneWarnings(float distance);
float boundsVisibility() const; float boundsVisibility() const;
float fadeDistance() const; float fadeDistance() const;
@@ -86,6 +147,23 @@ public:
bool playSpaceMarker() const; bool playSpaceMarker() const;
bool forceBounds() const; bool forceBounds() const;
bool isChaperoneSwitchToBeginnerEnabled() const;
float chaperoneSwitchToBeginnerDistance() const;
bool isChaperoneHapticFeedbackEnabled() const;
float chaperoneHapticFeedbackDistance() const;
bool isChaperoneAlarmSoundEnabled() const;
bool isChaperoneAlarmSoundLooping() const;
bool isChaperoneAlarmSoundAdjustVolume() const;
float chaperoneAlarmSoundDistance() const;
bool isChaperoneShowDashboardEnabled() const;
float chaperoneShowDashboardDistance() const;
bool isChaperoneVelocityModifierEnabled() const;
float chaperoneVelocityModifier() const;
void reloadChaperoneProfiles(); void reloadChaperoneProfiles();
void saveChaperoneProfiles(); void saveChaperoneProfiles();
@@ -103,15 +181,35 @@ public slots:
void setPlaySpaceMarker(bool value, bool notify = true); void setPlaySpaceMarker(bool value, bool notify = true);
void setForceBounds(bool value, bool notify = true); void setForceBounds(bool value, bool notify = true);
void setChaperoneSwitchToBeginnerEnabled(bool value, bool notify = true);
void setChaperoneSwitchToBeginnerDistance(float value, bool notify = true);
void setChaperoneHapticFeedbackEnabled(bool value, bool notify = true);
void setChaperoneHapticFeedbackDistance(float value, bool notify = true);
void setChaperoneAlarmSoundEnabled(bool value, bool notify = true);
void setChaperoneAlarmSoundLooping(bool value, bool notify = true);
void setChaperoneAlarmSoundAdjustVolume(bool value, bool notify = true);
void setChaperoneAlarmSoundDistance(float value, bool notify = true);
void setChaperoneShowDashboardEnabled(bool value, bool notify = true);
void setChaperoneShowDashboardDistance(float value, bool notify = true);
void setChaperoneVelocityModifierEnabled(bool value, bool notify = true);
void setChaperoneVelocityModifier(float value, bool notify = true);
void flipOrientation(); void flipOrientation();
void reloadFromDisk(); void reloadFromDisk();
void addChaperoneProfile(QString name, bool includeGeometry, bool includeVisbility, bool includeFadeDistance, bool includeCenterMarker, void addChaperoneProfile(QString name, bool includeGeometry, bool includeVisbility, bool includeFadeDistance, bool includeCenterMarker,
bool includePlaySpaceMarker, bool includeFloorBounds, bool includeBoundsColor, bool includeChaperoneStyle, bool includeForceBounds); bool includePlaySpaceMarker, bool includeFloorBounds, bool includeBoundsColor, bool includeChaperoneStyle, bool includeForceBounds,
bool includesProximityWarningSettings);
void applyChaperoneProfile(unsigned index); void applyChaperoneProfile(unsigned index);
void deleteChaperoneProfile(unsigned index); void deleteChaperoneProfile(unsigned index);
void reset(); void reset();
void shutdown();
signals: signals:
void boundsVisibilityChanged(float value); void boundsVisibilityChanged(float value);
@@ -121,6 +219,23 @@ signals:
void playSpaceMarkerChanged(bool value); void playSpaceMarkerChanged(bool value);
void forceBoundsChanged(bool value); void forceBoundsChanged(bool value);
void chaperoneSwitchToBeginnerEnabledChanged(bool value);
void chaperoneSwitchToBeginnerDistanceChanged(float value);
void chaperoneHapticFeedbackEnabledChanged(bool value);
void chaperoneHapticFeedbackDistanceChanged(float value);
void chaperoneAlarmSoundEnabledChanged(bool value);
void chaperoneAlarmSoundLoopingChanged(bool value);
void chaperoneAlarmSoundAdjustVolumeChanged(bool value);
void chaperoneAlarmSoundDistanceChanged(float value);
void chaperoneShowDashboardEnabledChanged(bool value);
void chaperoneShowDashboardDistanceChanged(float value);
void chaperoneVelocityModifierEnabledChanged(bool value);
void chaperoneVelocityModifierChanged(float value);
void chaperoneProfilesUpdated(); void chaperoneProfilesUpdated();
}; };
+5 -17
View File
@@ -13,7 +13,7 @@ void StatisticsTabController::initStage2(OverlayController * parent, QQuickWindo
this->widget = widget; this->widget = widget;
} }
void StatisticsTabController::eventLoopTick(vr::TrackedDevicePose_t* devicePoses) { void StatisticsTabController::eventLoopTick(vr::TrackedDevicePose_t* devicePoses, float leftSpeed, float rightSpeed) {
vr::Compositor_CumulativeStats pStats; vr::Compositor_CumulativeStats pStats;
vr::VRCompositor()->GetCumulativeStats(&pStats, sizeof(vr::Compositor_CumulativeStats)); vr::VRCompositor()->GetCumulativeStats(&pStats, sizeof(vr::Compositor_CumulativeStats));
if (pStats.m_nPid != m_cumStats.m_nPid) { if (pStats.m_nPid != m_cumStats.m_nPid) {
@@ -48,26 +48,14 @@ void StatisticsTabController::eventLoopTick(vr::TrackedDevicePose_t* devicePoses
} }
// Controller speeds // // Controller speeds //
auto leftId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_LeftHand); if (leftSpeed > m_leftControllerMaxSpeed) {
if (leftId != vr::k_unTrackedDeviceIndexInvalid && devicePoses[leftId].bPoseIsValid && devicePoses[leftId].eTrackingResult == vr::TrackingResult_Running_OK) { m_leftControllerMaxSpeed = leftSpeed;
auto& vel = devicePoses[leftId].vVelocity.v;
auto lspeed = std::sqrt(std::pow(vel[0], 2) + std::pow(vel[1], 2) + std::pow(vel[2], 2));
if (lspeed > m_leftControllerMaxSpeed) {
m_leftControllerMaxSpeed = lspeed;
}
} }
if (rightSpeed > m_rightControllerMaxSpeed) {
auto rightId = vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_RightHand); m_rightControllerMaxSpeed = rightSpeed;
if (rightId != vr::k_unTrackedDeviceIndexInvalid && devicePoses[rightId].bPoseIsValid && devicePoses[rightId].eTrackingResult == vr::TrackingResult_Running_OK) {
auto& vel = devicePoses[rightId].vVelocity.v;
auto rspeed = std::sqrt(std::pow(vel[0], 2) + std::pow(vel[1], 2) + std::pow(vel[2], 2));
if (rspeed > m_rightControllerMaxSpeed) {
m_rightControllerMaxSpeed = rspeed;
}
} }
// Hmd Rotation // // Hmd Rotation //
/* /*
| Intrinsic y-x'-z" rotation matrix: | Intrinsic y-x'-z" rotation matrix:
| cr*cy+sp*sr*sy | cr*sp*sy-cy*sr | cp*sy | | cr*cy+sp*sr*sy | cr*sp*sy-cy*sr | cp*sy |
+1 -1
View File
@@ -55,7 +55,7 @@ public:
void initStage1(); void initStage1();
void initStage2(OverlayController* parent, QQuickWindow* widget); void initStage2(OverlayController* parent, QQuickWindow* widget);
void eventLoopTick(vr::TrackedDevicePose_t* devicePoses); void eventLoopTick(vr::TrackedDevicePose_t* devicePoses, float leftSpeed, float rightSpeed);
float hmdDistanceMoved() const; float hmdDistanceMoved() const;
float hmdRotations() const; float hmdRotations() const;
+81
View File
@@ -0,0 +1,81 @@
#include "ChaperoneUtils.h"
#include <iostream>
namespace utils {
float ChaperoneUtils::_getDistanceToChaperone(const vr::HmdVector3_t & x, vr::HmdVector3_t * projectedPoint) {
float distance = NAN;
vr::HmdVector3_t* _cornersPtr = _corners.get();
for (uint32_t i = 0; i < _quadsCount; i++) {
uint32_t i2 = (i + 1) % _quadsCount;
vr::HmdVector3_t& r0 = _cornersPtr[i];
vr::HmdVector3_t& r1 = _cornersPtr[i2];
float u_x = r1.v[0] - r0.v[0];
float u_z = r1.v[2] - r0.v[2];
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);
//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)
float d;
float x1_x;
float x1_z;
if (r < 0.0f || r > 1.0f) { // projected point outside of segment
float d_x = r0.v[0] - x.v[0];
float d_z = r0.v[2] - x.v[2];
float d1 = sqrt(d_x*d_x + d_z*d_z);
d_x = r1.v[0] - x.v[0];
d_z = r1.v[2] - x.v[2];
float d2 = sqrt(d_x*d_x + d_z*d_z);
if (d1 < d2) {
d = d1;
x1_x = r0.v[0];
x1_z = r0.v[2];
} else {
d = d2;
x1_x = r1.v[0];
x1_z = r1.v[2];
}
} else { // projected point on segment
x1_x = r0.v[0] + r * u_x;
x1_z = r0.v[2] + r * u_z;
float d_x = x1_x - x.v[0];
float d_z = x1_z - x.v[2];
d = sqrt(d_x*d_x + d_z*d_z);
}
if (isnan(distance) || d < distance) {
distance = d;
if (projectedPoint) {
projectedPoint->v[0] = x1_x;
projectedPoint->v[1] = x.v[1];
projectedPoint->v[2] = x1_z;
}
}
}
return distance;
}
void ChaperoneUtils::loadChaperoneData() {
std::lock_guard<std::recursive_mutex> lock(_mutex);
vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo(nullptr, &_quadsCount);
if (_quadsCount > 0) {
std::unique_ptr<vr::HmdQuad_t> quadsBuffer(new vr::HmdQuad_t[_quadsCount]);
vr::HmdQuad_t* quadsBufferPtr = quadsBuffer.get();
_corners.reset((vr::HmdVector3_t*)new vr::HmdQuad_t[_quadsCount]);
vr::HmdVector3_t* _cornersPtr = _corners.get();
vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo(quadsBufferPtr, &_quadsCount);
for (uint32_t i = 0; i < _quadsCount; i++) {
_cornersPtr[i] = quadsBufferPtr[i].vCorners[0];
uint32_t i2 = (i + 1) % _quadsCount;
if (quadsBufferPtr[i].vCorners[3].v[0] != quadsBufferPtr[i2].vCorners[0].v[0]
|| quadsBufferPtr[i].vCorners[3].v[1] != quadsBufferPtr[i2].vCorners[0].v[1]
|| quadsBufferPtr[i].vCorners[3].v[2] != quadsBufferPtr[i2].vCorners[0].v[2]
|| quadsBufferPtr[i].vCorners[0].v[1] != 0.0f) {
_chaperoneWellFormed = false;
}
}
}
}
} // end namespace utils
+38
View File
@@ -0,0 +1,38 @@
#pragma once
#include <memory>
#include <mutex>
#include <openvr.h>
namespace utils {
class ChaperoneUtils {
private:
std::recursive_mutex _mutex;
uint32_t _quadsCount = 0;
std::unique_ptr<vr::HmdVector3_t> _corners;
bool _chaperoneWellFormed = true;
float _getDistanceToChaperone(const vr::HmdVector3_t& point, vr::HmdVector3_t* projectedPoint);
public:
uint32_t quadsCount() const noexcept { return _quadsCount; }
bool isChaperoneWellFormed() const noexcept { return _chaperoneWellFormed; }
std::recursive_mutex& mutex() noexcept { return _mutex; }
void loadChaperoneData();
float getDistanceToChaperone(const vr::HmdVector3_t& point, vr::HmdVector3_t* projectedPoint = nullptr, bool doLock = false) {
if (doLock) {
std::lock_guard<std::recursive_mutex> lock(_mutex);
return _getDistanceToChaperone(point, projectedPoint);
} else {
return _getDistanceToChaperone(point, projectedPoint);
}
}
};
} // end namespace utils