Add an optional pop-up notification when auto-turn is toggled (#496)
* Implement (most of) pop-up notification when autoturn is enabled * Add neato fading: doesn't appear to impact performance * formatting * added macro and UI for notification of auto-turn * changed notification default to true for auto-turn * added common issue for trackers * added warning for custom keys * minor documentation markdown format fixes * fix qml syntax error in atgb * gasd Co-authored-by: ykeara <ykeara1@gmail.com>
This commit is contained in:
@@ -125,7 +125,7 @@ Detailed instructions are available [here](docs/building_for_linux.md).
|
|||||||
|
|
||||||
### Overall Feature Overview Guides
|
### Overall Feature Overview Guides
|
||||||
|
|
||||||
- [Kung's 3.0 New Feature Guide (video/youtube)[https://youtu.be/2ZHdjOfnqOU)]
|
- [Kung's 3.0 New Feature Guide (video/youtube)[https://youtu.be/2ZHdjOfnqOU]
|
||||||
|
|
||||||
### SteamVR Input System (keybinds for app)
|
### SteamVR Input System (keybinds for app)
|
||||||
|
|
||||||
@@ -472,7 +472,7 @@ Allows users to temporarily move and rotate the center of the playspace. This al
|
|||||||
- **Brightness**: Same as regular.
|
- **Brightness**: Same as regular.
|
||||||
- **Opacity**: Adjusts opacity of color overlay.
|
- **Opacity**: Adjusts opacity of color overlay.
|
||||||
- **Toggle On/Off**: Turns on/off Color Adjustment Overlay.
|
- **Toggle On/Off**: Turns on/off Color Adjustment Overlay.
|
||||||
- **<Color>**: Adjusts the overlay to adjust the color.
|
- **Color (Red/Green/Blue)**: Adjusts the overlay to adjust the color.
|
||||||
|
|
||||||
## - Utilities Page
|
## - Utilities Page
|
||||||
|
|
||||||
@@ -546,6 +546,14 @@ Full build instructions can be found [here](docs/building_for_linux.md).
|
|||||||
- **Cause:** WMR boundary off, or set up for standing only.
|
- **Cause:** WMR boundary off, or set up for standing only.
|
||||||
- **Solution:** Please set-up WMR for all experiences, and then if you don't want WMR boundary you can toggle off the boundary **after** SteamVR/OpenVR has been started.
|
- **Solution:** Please set-up WMR for all experiences, and then if you don't want WMR boundary you can toggle off the boundary **after** SteamVR/OpenVR has been started.
|
||||||
|
|
||||||
|
- **Issue:** While using Trackers (additional devices besides controllers) Keybinds don't work.
|
||||||
|
- **Cause:** Trackers can Assume controller roles, and prevent your controllers from working properly.
|
||||||
|
- **Solution:** Assign Tracker Roles Via SteamVR Widget to anything besides `held-in-hand`
|
||||||
|
|
||||||
|
- **Issue:** Custom Key Presses Not Saving In file.
|
||||||
|
- **Cause:** Key Presses Modified while Advanced Settings is running.
|
||||||
|
- **Solution:** Only modify the settings file while VR/Advanced Settings is **not** running.
|
||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
This software is released under GPL 3.0, and other third-party Licenses
|
This software is released under GPL 3.0, and other third-party Licenses
|
||||||
|
|||||||
@@ -118,6 +118,10 @@
|
|||||||
### Case Sensative
|
### Case Sensative
|
||||||
- basic characters are all LOWER case, while keys such as ENTER are all UPPER case.
|
- basic characters are all LOWER case, while keys such as ENTER are all UPPER case.
|
||||||
|
|
||||||
|
### Custom Keys Not Saving.
|
||||||
|
- We only load keybinds from file on start-up, and save based on what is in memory (not in file)
|
||||||
|
- **ONLY** edit the settings file while Advanced Settings is **not** running.
|
||||||
|
|
||||||
### Focus Issues
|
### Focus Issues
|
||||||
- we deliver the keypress to the OS, depending on your set-up and program you may have to have the window "in-focus"
|
- we deliver the keypress to the OS, depending on your set-up and program you may have to have the window "in-focus"
|
||||||
|
|
||||||
@@ -126,4 +130,4 @@
|
|||||||
- alt + tab, alt + F4 = `*TAB *F4`
|
- alt + tab, alt + F4 = `*TAB *F4`
|
||||||
|
|
||||||
## Parser Spec
|
## Parser Spec
|
||||||
(Parser Spec)[https://github.com/OpenVR-Advanced-Settings/OpenVR-AdvancedSettings/blob/master/docs/specs/Keyboard_Manager-Parser_Spec.md]
|
[Parser Spec](https://github.com/OpenVR-Advanced-Settings/OpenVR-AdvancedSettings/blob/master/docs/specs/Keyboard_Manager-Parser_Spec.md)
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="100mm"
|
||||||
|
height="100mm"
|
||||||
|
viewBox="0 0 100 100"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<rect
|
||||||
|
x="43.277892"
|
||||||
|
y="36.927076"
|
||||||
|
width="23.295368"
|
||||||
|
height="30.546571"
|
||||||
|
id="rect1983" />
|
||||||
|
<marker
|
||||||
|
orient="auto"
|
||||||
|
refY="0.0"
|
||||||
|
refX="0.0"
|
||||||
|
id="Arrow1Lend"
|
||||||
|
style="overflow:visible;">
|
||||||
|
<path
|
||||||
|
id="path1440"
|
||||||
|
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||||
|
style="fill-rule:evenodd;stroke:#ffffff;stroke-width:1pt;stroke-opacity:1;fill:#ffffff;fill-opacity:1"
|
||||||
|
transform="scale(0.8) rotate(180) translate(12.5,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
orient="auto"
|
||||||
|
refY="0.0"
|
||||||
|
refX="0.0"
|
||||||
|
id="Arrow1Lstart"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path1437"
|
||||||
|
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
|
||||||
|
style="fill-rule:evenodd;stroke:#ffffff;stroke-width:1pt;stroke-opacity:1;fill:#ffffff;fill-opacity:1"
|
||||||
|
transform="scale(0.8) translate(12.5,0)" />
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<rect
|
||||||
|
y="17.717316"
|
||||||
|
x="17.717316"
|
||||||
|
height="64.565376"
|
||||||
|
width="64.565376"
|
||||||
|
id="rect1404"
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:5.0000958;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<rect
|
||||||
|
y="72.682518"
|
||||||
|
x="26.972013"
|
||||||
|
height="0.34497312"
|
||||||
|
width="46.055973"
|
||||||
|
id="rect1406"
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:4.65502977;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<rect
|
||||||
|
transform="rotate(-90)"
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:4.61399984;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="rect1406-3"
|
||||||
|
width="40.386425"
|
||||||
|
height="0.38642606"
|
||||||
|
x="-69.420227"
|
||||||
|
y="72.641556" />
|
||||||
|
<g
|
||||||
|
transform="matrix(2.1165483,0,0,2.1165483,-81.187201,-75.769488)"
|
||||||
|
id="g4567">
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.50000007, 2.50000007;stroke-dashoffset:17;stroke-opacity:1"
|
||||||
|
d="m 72.479209,53.094746 c 0,0 -6.460096,-1.327245 -12.308933,4.1861 -5.848839,5.513348 -5.595517,8.406487 -5.595517,8.406487"
|
||||||
|
id="path1435" />
|
||||||
|
<path
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:17;stroke-opacity:1"
|
||||||
|
id="path1977"
|
||||||
|
d="m 53.243307,65.791321 0.299848,-4.141501 3.436721,2.330426 z" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
d="m 72.968407,24.57116 3.522289,6.100784 h -7.044579 z"
|
||||||
|
id="path1979"
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:64.2519989;stroke-opacity:1" />
|
||||||
|
<text
|
||||||
|
y="-87.638542"
|
||||||
|
x="-96.653877"
|
||||||
|
transform="scale(0.9999973,1.0000027)"
|
||||||
|
style="font-style:normal;font-weight:normal;font-size:44.66781998px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;white-space:pre;shape-inside:url(#rect1983);fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.81372094"
|
||||||
|
id="text1981"
|
||||||
|
xml:space="preserve"><tspan
|
||||||
|
style="stroke-width:2.81372094"
|
||||||
|
x="25.116493"
|
||||||
|
y="55.786346"
|
||||||
|
id="tspan17"><tspan
|
||||||
|
style="font-size:44.66781998px;fill:#ffffff;fill-opacity:1;stroke-width:2.81372094"
|
||||||
|
id="tspan15">A</tspan></tspan></text>
|
||||||
|
<ellipse
|
||||||
|
ry="32.294323"
|
||||||
|
rx="32.294319"
|
||||||
|
cy="49.999966"
|
||||||
|
cx="50.000027"
|
||||||
|
id="path4571"
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#ff0000;stroke-width:4.9769268;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
id="path4573"
|
||||||
|
d="M 28.177966,24.682203 76.165254,69.385592"
|
||||||
|
style="fill:none;stroke:#ff0000;stroke-width:5.0000958;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.5 KiB |
@@ -35,10 +35,18 @@ GroupBox {
|
|||||||
MyToggleButton {
|
MyToggleButton {
|
||||||
id: autoTurn
|
id: autoTurn
|
||||||
text: "Toggle On/Off"
|
text: "Toggle On/Off"
|
||||||
Layout.preferredWidth: 300
|
Layout.preferredWidth: 250
|
||||||
onCheckedChanged: {
|
onCheckedChanged: {
|
||||||
RotationTabController.setAutoTurnEnabled(this.checked, true); }
|
RotationTabController.setAutoTurnEnabled(this.checked, true); }
|
||||||
}
|
}
|
||||||
|
MyToggleButton {
|
||||||
|
id: autoTurnNotificationToggle
|
||||||
|
text: "HMD Icon"
|
||||||
|
Layout.preferredWidth: 175
|
||||||
|
onCheckedChanged: {
|
||||||
|
RotationTabController.setAutoTurnShowNotification(this.checked, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MyText {
|
MyText {
|
||||||
text: "Activation Dist:"
|
text: "Activation Dist:"
|
||||||
@@ -160,7 +168,7 @@ GroupBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MyText {
|
MyText {
|
||||||
text: "Turn Speed (deg/sec):"
|
text: "Turn Speed(deg/sec):"
|
||||||
horizontalAlignment: Text.AlignRight
|
horizontalAlignment: Text.AlignRight
|
||||||
Layout.rightMargin: 10
|
Layout.rightMargin: 10
|
||||||
}
|
}
|
||||||
@@ -174,7 +182,7 @@ GroupBox {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
onPositionChanged: {
|
onPositionChanged: {
|
||||||
var val = this.value
|
var val = this.value
|
||||||
speedValueText.text = val.toFixed()
|
speedValueText.text = val.toFixed()+ "°"
|
||||||
}
|
}
|
||||||
onValueChanged: {
|
onValueChanged: {
|
||||||
|
|
||||||
@@ -184,7 +192,7 @@ GroupBox {
|
|||||||
|
|
||||||
MyTextField {
|
MyTextField {
|
||||||
id: speedValueText
|
id: speedValueText
|
||||||
text: "90"
|
text: "90°"
|
||||||
keyBoardUID: 1003
|
keyBoardUID: 1003
|
||||||
Layout.preferredWidth: 100
|
Layout.preferredWidth: 100
|
||||||
Layout.leftMargin: 10
|
Layout.leftMargin: 10
|
||||||
@@ -203,29 +211,30 @@ GroupBox {
|
|||||||
speedSlider.value = val;
|
speedSlider.value = val;
|
||||||
}
|
}
|
||||||
//converts the centidegrees to degrees
|
//converts the centidegrees to degrees
|
||||||
text = (((RotationTabController.autoTurnSpeed)/100).toFixed());
|
text = (((RotationTabController.autoTurnSpeed)/100).toFixed()) + "°";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
RowLayout{
|
RowLayout{
|
||||||
|
|
||||||
MyText{
|
MyText{
|
||||||
text: "Detangle Angle: "
|
text: "Detangle Angle: "
|
||||||
horizontalAlignment: Text.AlignLeft
|
horizontalAlignment: Text.AlignLeft
|
||||||
Layout.preferredWidth: 250
|
Layout.preferredWidth: 200
|
||||||
Layout.rightMargin: 5
|
Layout.rightMargin: 5
|
||||||
|
|
||||||
}
|
}
|
||||||
MyText{
|
MyText{
|
||||||
text:"Min Rotations(deg):"
|
text:"Min Rotations:"
|
||||||
Layout.rightMargin: 5
|
Layout.rightMargin: 5
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MyTextField {
|
MyTextField {
|
||||||
id: detangleAngleStartText
|
id: detangleAngleStartText
|
||||||
text: "360"
|
text: "360°"
|
||||||
keyBoardUID: 1005
|
keyBoardUID: 1005
|
||||||
Layout.preferredWidth: 100
|
Layout.preferredWidth: 100
|
||||||
Layout.leftMargin: 5
|
Layout.leftMargin: 5
|
||||||
@@ -239,6 +248,7 @@ GroupBox {
|
|||||||
val = 3600
|
val = 3600
|
||||||
}
|
}
|
||||||
RotationTabController.setMinCordTangle((val*(Math.PI/180)), true);
|
RotationTabController.setMinCordTangle((val*(Math.PI/180)), true);
|
||||||
|
text = (Math.round(val).toFixed())+ "°";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,7 +257,7 @@ GroupBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MyText{
|
MyText{
|
||||||
text: "Max Wall Angle(deg): "
|
text: "Max Wall Angle: "
|
||||||
horizontalAlignment: Text.AlignRight
|
horizontalAlignment: Text.AlignRight
|
||||||
Layout.rightMargin: 10
|
Layout.rightMargin: 10
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@@ -255,7 +265,7 @@ GroupBox {
|
|||||||
}
|
}
|
||||||
MyTextField {
|
MyTextField {
|
||||||
id: detangleAngleAssistText
|
id: detangleAngleAssistText
|
||||||
text: "10"
|
text: "10°"
|
||||||
keyBoardUID: 1006
|
keyBoardUID: 1006
|
||||||
Layout.preferredWidth: 100
|
Layout.preferredWidth: 100
|
||||||
Layout.leftMargin: 10
|
Layout.leftMargin: 10
|
||||||
@@ -269,6 +279,7 @@ GroupBox {
|
|||||||
val = 3600
|
val = 3600
|
||||||
}
|
}
|
||||||
RotationTabController.setCordDetangleAngle((val*(Math.PI/180)), true);
|
RotationTabController.setCordDetangleAngle((val*(Math.PI/180)), true);
|
||||||
|
text = (Math.round(val).toFixed())+ "°";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -285,6 +296,7 @@ GroupBox {
|
|||||||
deactivationSlider.value = RotationTabController.autoTurnDeactivationDistance.toFixed(2)
|
deactivationSlider.value = RotationTabController.autoTurnDeactivationDistance.toFixed(2)
|
||||||
cornerAngle.checked = RotationTabController.autoTurnUseCornerAngle
|
cornerAngle.checked = RotationTabController.autoTurnUseCornerAngle
|
||||||
speedSlider.value = (RotationTabController.autoTurnSpeed/100).toFixed()
|
speedSlider.value = (RotationTabController.autoTurnSpeed/100).toFixed()
|
||||||
|
autoTurnNotificationToggle.checked = RotationTabController.autoTurnShowNotification
|
||||||
if(RotationTabController.autoTurnMode === 1){
|
if(RotationTabController.autoTurnMode === 1){
|
||||||
|
|
||||||
autoTurnModeToggle.checked = true;
|
autoTurnModeToggle.checked = true;
|
||||||
@@ -293,8 +305,8 @@ GroupBox {
|
|||||||
|
|
||||||
autoTurnModeToggle.checked = false;
|
autoTurnModeToggle.checked = false;
|
||||||
}
|
}
|
||||||
detangleAngleStartText.text = parseInt(RotationTabController.minCordTangle*(180/Math.PI))
|
detangleAngleStartText.text = parseInt(RotationTabController.minCordTangle*(180/Math.PI))+ "°"
|
||||||
detangleAngleAssistText.text = parseInt(RotationTabController.cordDetangleAngle*(180/Math.PI))
|
detangleAngleAssistText.text = parseInt(RotationTabController.cordDetangleAngle*(180/Math.PI))+ "°"
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -327,10 +339,13 @@ GroupBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
onMinCordTangleChanged:{
|
onMinCordTangleChanged:{
|
||||||
detangleAngleStartText.text = parseInt(RotationTabController.minCordTangle*(180/Math.PI))
|
detangleAngleStartText.text = parseInt(RotationTabController.minCordTangle*(180/Math.PI))+ "°"
|
||||||
}
|
}
|
||||||
onCordDetangleAngleChanged:{
|
onCordDetangleAngleChanged:{
|
||||||
detangleAngleAssistText.text = parseInt(RotationTabController.cordDetangleAngle*(180/Math.PI))
|
detangleAngleAssistText.text = parseInt(RotationTabController.cordDetangleAngle*(180/Math.PI))+ "°"
|
||||||
|
}
|
||||||
|
onAutoTurnShowNotificationChanged:{
|
||||||
|
autoTurnNotificationToggle.checked = RotationTabController.autoTurnShowNotification
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -393,6 +393,10 @@ private:
|
|||||||
SettingCategory::Rotation,
|
SettingCategory::Rotation,
|
||||||
QtInfo{ "autoturnVestibularMotionEnabled" },
|
QtInfo{ "autoturnVestibularMotionEnabled" },
|
||||||
false },
|
false },
|
||||||
|
BoolSettingValue{ BoolSetting::ROTATION_autoturnShowNotification,
|
||||||
|
SettingCategory::Rotation,
|
||||||
|
QtInfo{ "autoturnShowNotification" },
|
||||||
|
true }
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr static auto doubleSettingSize
|
constexpr static auto doubleSettingSize
|
||||||
|
|||||||
@@ -55,8 +55,9 @@ enum class BoolSetting
|
|||||||
ROTATION_autoturnEnabled,
|
ROTATION_autoturnEnabled,
|
||||||
ROTATION_autoturnUseCornerAngle,
|
ROTATION_autoturnUseCornerAngle,
|
||||||
ROTATION_autoturnVestibularMotionEnabled,
|
ROTATION_autoturnVestibularMotionEnabled,
|
||||||
|
ROTATION_autoturnShowNotification,
|
||||||
// LAST_ENUMERATOR must always be set to the last value
|
// LAST_ENUMERATOR must always be set to the last value
|
||||||
LAST_ENUMERATOR = ROTATION_autoturnVestibularMotionEnabled,
|
LAST_ENUMERATOR = ROTATION_autoturnShowNotification,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class DoubleSetting
|
enum class DoubleSetting
|
||||||
|
|||||||
@@ -63,18 +63,6 @@ void AudioTabController::initStage1()
|
|||||||
eventLoopTick();
|
eventLoopTick();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> verifyIconFilePath( std::string filename )
|
|
||||||
{
|
|
||||||
const auto notifIconPath = paths::binaryDirectoryFindFile( filename );
|
|
||||||
if ( !notifIconPath.has_value() )
|
|
||||||
{
|
|
||||||
LOG( ERROR ) << "Could not find push to talk icon \"" << filename
|
|
||||||
<< "\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
return notifIconPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioTabController::initStage2()
|
void AudioTabController::initStage2()
|
||||||
{
|
{
|
||||||
const auto pushToTalkOverlayKey
|
const auto pushToTalkOverlayKey
|
||||||
@@ -102,9 +90,9 @@ void AudioTabController::initStage2()
|
|||||||
= "/res/img/audio/microphone/ptm_notification.png";
|
= "/res/img/audio/microphone/ptm_notification.png";
|
||||||
|
|
||||||
const auto pushToTalkIconFilePath
|
const auto pushToTalkIconFilePath
|
||||||
= verifyIconFilePath( pushToTalkIconFilepath );
|
= paths::verifyIconFilePath( pushToTalkIconFilepath );
|
||||||
const auto pushToMuteIconFilePath
|
const auto pushToMuteIconFilePath
|
||||||
= verifyIconFilePath( pushToMuteIconFilepath );
|
= paths::verifyIconFilePath( pushToMuteIconFilepath );
|
||||||
|
|
||||||
if ( !pushToTalkIconFilePath.has_value()
|
if ( !pushToTalkIconFilePath.has_value()
|
||||||
|| !pushToMuteIconFilePath.has_value() )
|
|| !pushToMuteIconFilePath.has_value() )
|
||||||
|
|||||||
@@ -17,6 +17,60 @@ void RotationTabController::initStage1()
|
|||||||
|
|
||||||
void RotationTabController::initStage2( OverlayController* var_parent )
|
void RotationTabController::initStage2( OverlayController* var_parent )
|
||||||
{
|
{
|
||||||
|
const auto autoturnOverlayKey
|
||||||
|
= std::string( application_strings::applicationKey )
|
||||||
|
+ ".autoturnnotification";
|
||||||
|
|
||||||
|
const auto overlayError
|
||||||
|
= vr::VROverlay()->CreateOverlay( autoturnOverlayKey.c_str(),
|
||||||
|
autoturnOverlayKey.c_str(),
|
||||||
|
&m_autoturnValues.overlayHandle );
|
||||||
|
if ( overlayError != vr::VROverlayError_None )
|
||||||
|
{
|
||||||
|
LOG( ERROR ) << "Could not create autoturn notification overlay: "
|
||||||
|
<< vr::VROverlay()->GetOverlayErrorNameFromEnum(
|
||||||
|
overlayError );
|
||||||
|
|
||||||
|
emit defaultProfileDisplay();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto autoturnIconFilepath = "/res/img/rotation/autoturn.png";
|
||||||
|
constexpr auto noautoturnIconFilepath = "/res/img/rotation/noautoturn.png";
|
||||||
|
|
||||||
|
const auto autoturnIconFilePath
|
||||||
|
= paths::verifyIconFilePath( autoturnIconFilepath );
|
||||||
|
const auto noautoturnIconFilePath
|
||||||
|
= paths::verifyIconFilePath( noautoturnIconFilepath );
|
||||||
|
|
||||||
|
if ( !autoturnIconFilePath.has_value()
|
||||||
|
|| !noautoturnIconFilePath.has_value() )
|
||||||
|
{
|
||||||
|
emit defaultProfileDisplay();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_autoturnValues.autoturnPath = *autoturnIconFilePath;
|
||||||
|
m_autoturnValues.noautoturnPath = *noautoturnIconFilePath;
|
||||||
|
|
||||||
|
auto pushToPath = m_autoturnValues.autoturnPath.c_str();
|
||||||
|
|
||||||
|
vr::VROverlay()->SetOverlayFromFile( m_autoturnValues.overlayHandle,
|
||||||
|
pushToPath );
|
||||||
|
vr::VROverlay()->SetOverlayWidthInMeters( m_autoturnValues.overlayHandle,
|
||||||
|
0.02f );
|
||||||
|
vr::HmdMatrix34_t notificationTransform
|
||||||
|
= { { { 1.0f, 0.0f, 0.0f, 0.12f },
|
||||||
|
{ 0.0f, 1.0f, 0.0f, 0.08f },
|
||||||
|
{ 0.0f, 0.0f, 1.0f, -0.3f } } };
|
||||||
|
vr::VROverlay()->SetOverlayTransformTrackedDeviceRelative(
|
||||||
|
m_autoturnValues.overlayHandle,
|
||||||
|
vr::k_unTrackedDeviceIndex_Hmd,
|
||||||
|
¬ificationTransform );
|
||||||
|
|
||||||
|
emit defaultProfileDisplay();
|
||||||
|
|
||||||
this->parent = var_parent;
|
this->parent = var_parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +119,29 @@ void RotationTabController::eventLoopTick(
|
|||||||
m_autoTurnChaperoneDistancesLast = std::move( chaperoneDistances );
|
m_autoTurnChaperoneDistancesLast = std::move( chaperoneDistances );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ( m_autoTurnNotificationTimestamp )
|
||||||
|
{
|
||||||
|
auto count = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
|
std::chrono::steady_clock::now()
|
||||||
|
- *m_autoTurnNotificationTimestamp )
|
||||||
|
.count();
|
||||||
|
if ( count > 1500 )
|
||||||
|
{
|
||||||
|
m_autoTurnNotificationTimestamp.reset();
|
||||||
|
if ( getNotificationOverlayHandle()
|
||||||
|
!= vr::k_ulOverlayHandleInvalid )
|
||||||
|
{
|
||||||
|
vr::VROverlay()->HideOverlay( getNotificationOverlayHandle() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float pct
|
||||||
|
= std::min( 1.0f, 3.0f - static_cast<float>( count ) / 500.0f );
|
||||||
|
vr::VROverlay()->SetOverlayAlpha( getNotificationOverlayHandle(),
|
||||||
|
pct );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RotationTabController::doVestibularMotion(
|
void RotationTabController::doVestibularMotion(
|
||||||
@@ -453,6 +530,12 @@ bool RotationTabController::autoTurnUseCornerAngle() const
|
|||||||
settings::BoolSetting::ROTATION_autoturnUseCornerAngle );
|
settings::BoolSetting::ROTATION_autoturnUseCornerAngle );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RotationTabController::autoTurnShowNotification() const
|
||||||
|
{
|
||||||
|
return settings::getSetting(
|
||||||
|
settings::BoolSetting::ROTATION_autoturnShowNotification );
|
||||||
|
}
|
||||||
|
|
||||||
double RotationTabController::cordDetangleAngle() const
|
double RotationTabController::cordDetangleAngle() const
|
||||||
{
|
{
|
||||||
return settings::getSetting(
|
return settings::getSetting(
|
||||||
@@ -505,6 +588,39 @@ void RotationTabController::setAutoTurnEnabled( bool value, bool notify )
|
|||||||
{
|
{
|
||||||
emit autoTurnEnabledChanged( value );
|
emit autoTurnEnabledChanged( value );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( !value )
|
||||||
|
{
|
||||||
|
vr::VROverlay()->SetOverlayFromFile(
|
||||||
|
m_autoturnValues.overlayHandle,
|
||||||
|
m_autoturnValues.noautoturnPath.c_str() );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vr::VROverlay()->SetOverlayFromFile(
|
||||||
|
m_autoturnValues.overlayHandle,
|
||||||
|
m_autoturnValues.autoturnPath.c_str() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( autoTurnShowNotification()
|
||||||
|
&& getNotificationOverlayHandle() != vr::k_ulOverlayHandleInvalid )
|
||||||
|
{
|
||||||
|
vr::VROverlay()->SetOverlayAlpha( getNotificationOverlayHandle(),
|
||||||
|
1.0f );
|
||||||
|
vr::VROverlay()->ShowOverlay( getNotificationOverlayHandle() );
|
||||||
|
m_autoTurnNotificationTimestamp.emplace(
|
||||||
|
std::chrono::steady_clock::now() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void RotationTabController::setAutoTurnShowNotification( bool value,
|
||||||
|
bool notify )
|
||||||
|
{
|
||||||
|
settings::setSetting(
|
||||||
|
settings::BoolSetting::ROTATION_autoturnShowNotification, value );
|
||||||
|
if ( notify )
|
||||||
|
{
|
||||||
|
emit autoTurnShowNotificationChanged( value );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void RotationTabController::setAutoTurnActivationDistance( float value,
|
void RotationTabController::setAutoTurnActivationDistance( float value,
|
||||||
bool notify )
|
bool notify )
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <openvr.h>
|
#include <openvr.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <optional>
|
||||||
#include "../utils/FrameRateUtils.h"
|
#include "../utils/FrameRateUtils.h"
|
||||||
#include "../utils/ChaperoneUtils.h"
|
#include "../utils/ChaperoneUtils.h"
|
||||||
#include "../settings/settings_object.h"
|
#include "../settings/settings_object.h"
|
||||||
@@ -82,10 +83,25 @@ class RotationTabController : public QObject
|
|||||||
Q_PROPERTY(
|
Q_PROPERTY(
|
||||||
double vestibularMotionRadius READ vestibularMotionRadius WRITE
|
double vestibularMotionRadius READ vestibularMotionRadius WRITE
|
||||||
setVestibularMotionRadius NOTIFY vestibularMotionRadiusChanged )
|
setVestibularMotionRadius NOTIFY vestibularMotionRadiusChanged )
|
||||||
|
Q_PROPERTY(
|
||||||
|
bool autoTurnShowNotification READ autoTurnShowNotification WRITE
|
||||||
|
setAutoTurnShowNotification NOTIFY autoTurnShowNotificationChanged )
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OverlayController* parent;
|
OverlayController* parent;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
vr::VROverlayHandle_t overlayHandle = vr::k_ulOverlayHandleInvalid;
|
||||||
|
std::string autoturnPath;
|
||||||
|
std::string noautoturnPath;
|
||||||
|
} m_autoturnValues;
|
||||||
|
|
||||||
|
virtual vr::VROverlayHandle_t getNotificationOverlayHandle()
|
||||||
|
{
|
||||||
|
return m_autoturnValues.overlayHandle;
|
||||||
|
}
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
int m_autoTurnLinearSmoothTurnRemaining = 0;
|
int m_autoTurnLinearSmoothTurnRemaining = 0;
|
||||||
std::chrono::steady_clock::time_point m_autoTurnLastUpdate;
|
std::chrono::steady_clock::time_point m_autoTurnLastUpdate;
|
||||||
@@ -95,6 +111,9 @@ private:
|
|||||||
double m_autoTurnRoundingError = 0.0;
|
double m_autoTurnRoundingError = 0.0;
|
||||||
std::chrono::steady_clock::time_point::duration m_estimatedFrameRate;
|
std::chrono::steady_clock::time_point::duration m_estimatedFrameRate;
|
||||||
|
|
||||||
|
std::optional<std::chrono::steady_clock::time_point>
|
||||||
|
m_autoTurnNotificationTimestamp;
|
||||||
|
|
||||||
bool m_isHMDActive = false;
|
bool m_isHMDActive = false;
|
||||||
|
|
||||||
void doAutoTurn(
|
void doAutoTurn(
|
||||||
@@ -116,6 +135,7 @@ public:
|
|||||||
float autoTurnActivationDistance() const;
|
float autoTurnActivationDistance() const;
|
||||||
float autoTurnDeactivationDistance() const;
|
float autoTurnDeactivationDistance() const;
|
||||||
bool autoTurnUseCornerAngle() const;
|
bool autoTurnUseCornerAngle() const;
|
||||||
|
bool autoTurnShowNotification() const;
|
||||||
double cordDetangleAngle() const;
|
double cordDetangleAngle() const;
|
||||||
double minCordTangle() const;
|
double minCordTangle() const;
|
||||||
int autoTurnSpeed() const;
|
int autoTurnSpeed() const;
|
||||||
@@ -126,6 +146,7 @@ public:
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setAutoTurnEnabled( bool value, bool notify = true );
|
void setAutoTurnEnabled( bool value, bool notify = true );
|
||||||
|
void setAutoTurnShowNotification( bool value, bool notify = true );
|
||||||
void setAutoTurnActivationDistance( float value, bool notify = true );
|
void setAutoTurnActivationDistance( float value, bool notify = true );
|
||||||
void setAutoTurnDeactivationDistance( float value, bool notify = true );
|
void setAutoTurnDeactivationDistance( float value, bool notify = true );
|
||||||
void setAutoTurnUseCornerAngle( bool value, bool notify = true );
|
void setAutoTurnUseCornerAngle( bool value, bool notify = true );
|
||||||
@@ -138,7 +159,9 @@ public slots:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
|
void defaultProfileDisplay();
|
||||||
void autoTurnEnabledChanged( bool value );
|
void autoTurnEnabledChanged( bool value );
|
||||||
|
void autoTurnShowNotificationChanged( bool value );
|
||||||
void autoTurnActivationDistanceChanged( float value );
|
void autoTurnActivationDistanceChanged( float value );
|
||||||
void autoTurnDeactivationDistanceChanged( float value );
|
void autoTurnDeactivationDistanceChanged( float value );
|
||||||
void autoTurnUseCornerAngleChanged( bool value );
|
void autoTurnUseCornerAngleChanged( bool value );
|
||||||
|
|||||||
@@ -57,4 +57,15 @@ optional<string> settingsDirectory()
|
|||||||
return path.toStdString();
|
return path.toStdString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> verifyIconFilePath( std::string filename )
|
||||||
|
{
|
||||||
|
const auto notifIconPath = paths::binaryDirectoryFindFile( filename );
|
||||||
|
if ( !notifIconPath.has_value() )
|
||||||
|
{
|
||||||
|
LOG( ERROR ) << "Could not find icon \"" << filename << "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
return notifIconPath;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace paths
|
} // namespace paths
|
||||||
|
|||||||
@@ -12,4 +12,6 @@ optional<string> binaryDirectoryFindFile( string fileName );
|
|||||||
|
|
||||||
optional<string> settingsDirectory();
|
optional<string> settingsDirectory();
|
||||||
|
|
||||||
|
std::optional<std::string> verifyIconFilePath( std::string filename );
|
||||||
|
|
||||||
} // namespace paths
|
} // namespace paths
|
||||||
|
|||||||
Reference in New Issue
Block a user