Merge pull request #84 from OpenVR-Advanced-Settings/ivrinput-ptt

Move the Push To Talk system to the new IVRInputs
This commit is contained in:
username223
2019-02-20 20:04:09 +01:00
committed by GitHub
17 changed files with 88 additions and 455 deletions
+3 -6
View File
@@ -143,7 +143,7 @@ These version are not stable and this should be considered for advanced users on
- **Supersampling Profile**: Allows to apply supersampling profiles. Profiles can be created on the SteamVR page
- **Chaperone Profile**: Allows to apply chaperone profiles. Profiles can be created on the Chaperone page
- **Microphone**: Allows to set the microphone volume and to mute/unmute it.
- **Push-to-Talk**: Enable/disable push-to-talk and allows to apply push-to-talk profiles. Profiles can be created on the Audio page.
- **Push-to-Talk**: Enable/disable push-to-talk.
<a name="steamvr_page"></a>
## - SteamVR Page:
@@ -214,12 +214,9 @@ Allows to temporarily move and rotate the center of the playspace. This allows t
- **Mirror Device**: Allows to select the mirror device, set its volume and to mute/unmute it.
- **Microphone**: Allows to select the microphone device, set its volume and to mute/unmute it.
- **Proximity Sensor Mutes/Unmutes Microphone**: Allows the proximity sensor to mute the microphone when the user is not wearing the HMD, and to unmute it when the user is wearing the HMD.
- **Push-to-Talk**: Enable/disable push-to-talk. When push-to-talk is activated the microphone gets muted unless one of the configured buttons is pressed on one of the configured controllers.
- **Left Controller**: Configure the left controller for push-to-talk.
- **Right Controller**: Configure the right controller for push-to-talk.
- **Show Notification**: Shows a notification icon in the headset when push-to-talk is enabled a configured button is pressed.
- **Push-to-Talk**: Enable/disable push-to-talk. When push-to-talk is activated the microphone gets muted unless the Push To Talk action is activated.
- **Show Notification**: Shows a notification icon in the headset when the Push To Talk action is activated.
- **Push-to-Mute**: Inverse push-to-talk. The Microphone is unmuted by default and muted when any of the configured buttons is pressed.
- **PTT Profile**: Allows you to apply/define/delete push-to-talk profiles that save buttons, controller and notification settings.
- **Audio Profile**: Allows you to apply/define/delete audio profiles that save playback devices, mute state, and volume.
<a name="revive_page"></a>
-1
View File
@@ -126,7 +126,6 @@ DISTFILES += \
src/res/qml/ChaperoneWarningsPage.qml \
src/res/qml/FixFloorPage.qml \
src/res/qml/PlayspacePage.qml \
src/res/qml/PttControllerConfigDialog.qml \
src/res/qml/RevivePage.qml \
src/res/qml/RootPage.qml \
src/res/qml/SettingsPage.qml \
Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 58 KiB

+7 -1
View File
@@ -149,7 +149,8 @@ SteamIVRInput::SteamIVRInput()
ActionType::Digital ),
m_optionalOverrideRightHandRoomDrag(
input_strings::k_actionOptionalOverrideRightHandRoomDrag,
ActionType::Digital )
ActionType::Digital ),
m_pushToTalk( input_strings::k_actionPushToTalk, ActionType::Digital )
{
m_activeActionSet.ulActionSet = m_mainSet.handle();
m_activeActionSet.ulRestrictedToDevice = vr::k_ulInvalidInputValueHandle;
@@ -242,6 +243,11 @@ bool SteamIVRInput::optionalOverrideRightHandRoomDrag()
m_optionalOverrideRightHandRoomDrag );
}
bool SteamIVRInput::pushToTalk()
{
return isDigitalActionActivatedConstant( m_pushToTalk );
}
/*!
Updates the active action set(s).
Should be called every frame, or however often you want the input system to
+9
View File
@@ -36,10 +36,12 @@ public:
SteamIVRInput();
void UpdateStates();
bool nextSong();
bool previousSong();
bool pausePlaySong();
bool stopSong();
bool leftHandRoomTurn();
bool rightHandRoomTurn();
bool leftHandRoomDrag();
@@ -49,6 +51,8 @@ public:
bool optionalOverrideLeftHandRoomDrag();
bool optionalOverrideRightHandRoomDrag();
bool pushToTalk();
// Destructor. There are no terminating calls for the IVRInput API, so it
// is left blank.
~SteamIVRInput() {}
@@ -87,6 +91,9 @@ private:
Action m_optionalOverrideRightHandRoomTurn;
Action m_optionalOverrideLeftHandRoomDrag;
Action m_optionalOverrideRightHandRoomDrag;
// Push To Talk
Action m_pushToTalk;
};
/*!
@@ -118,6 +125,8 @@ namespace input_strings
constexpr auto k_actionOptionalOverrideRightHandRoomDrag
= "/actions/main/in/OptionalOverrideRightHandRoomDrag";
constexpr auto k_actionPushToTalk = "/actions/main/in/PushToTalk";
constexpr auto k_setMain = "/actions/main";
} // namespace input_strings
+38 -8
View File
@@ -464,14 +464,7 @@ QPoint OverlayController::getMousePositionForEvent( vr::VREvent_Mouse_t mouse )
return QPoint( mouse.x, y );
}
/*!
Checks if an action has been activated and dispatches the related action if it
has been.
This function should probably be split into several functions that are specific
to a binding type as the amount of actions grows.
*/
void OverlayController::processInputBindings()
void OverlayController::processMediaKeyBindings()
{
if ( m_actions.nextSong() )
{
@@ -489,6 +482,10 @@ void OverlayController::processInputBindings()
{
m_utilitiesTabController.sendMediaStopSong();
}
}
void OverlayController::processRoomBindings()
{
// Execution order for moveCenterTabController actions is important. Don't
// reorder these. Override actions must always come after normal because
// active priority is set based on which action is "newest"
@@ -511,6 +508,39 @@ void OverlayController::processInputBindings()
m_actions.optionalOverrideRightHandRoomTurn() );
}
void OverlayController::processPushToTalkBindings()
{
const auto pushToTalkCannotChange = !m_audioTabController.pttChangeValid();
if ( pushToTalkCannotChange )
{
return;
}
const auto pushToTalkButtonActivated = m_actions.pushToTalk();
const auto pushToTalkCurrentlyActive = m_audioTabController.pttActive();
if ( pushToTalkButtonActivated && !pushToTalkCurrentlyActive )
{
m_audioTabController.startPtt();
}
else if ( !pushToTalkButtonActivated && pushToTalkCurrentlyActive )
{
m_audioTabController.stopPtt();
}
}
/*!
Checks if an action has been activated and dispatches the related action if it
has been.
*/
void OverlayController::processInputBindings()
{
processMediaKeyBindings();
processRoomBindings();
processPushToTalkBindings();
}
// vsync implementation:
// (this function triggers every 1ms)
void OverlayController::OnTimeoutPumpEvents()
+3
View File
@@ -123,6 +123,9 @@ public: // I know it's an ugly hack to make them public to enable external
private:
QPoint getMousePositionForEvent( vr::VREvent_Mouse_t mouse );
void processInputBindings();
void processMediaKeyBindings();
void processRoomBindings();
void processPushToTalkBindings();
public:
OverlayController( bool desktopMode, bool noSound, QQmlEngine& qmlEngine );
+8 -1
View File
@@ -65,6 +65,11 @@
"name": "/actions/main/in/OptionalOverrideRightHandRoomDrag",
"requirement": "optional",
"type": "boolean"
},
{
"name": "/actions/main/in/PushToTalk",
"requirement": "optional",
"type": "boolean"
}
],
"action_sets": [
@@ -90,7 +95,9 @@
"/actions/main/in/OptionalOverrideLeftHandRoomTurn" : "Optional Override Left Hand Room Turn",
"/actions/main/in/OptionalOverrideRightHandRoomTurn" : "Optional Override Right Hand Room Turn",
"/actions/main/in/OptionalOverrideLeftHandRoomDrag" : "Optional Override Left Hand Room Drag",
"/actions/main/in/OptionalOverrideRightHandRoomDrag" : "Optional Override Right Hand Room Drag"
"/actions/main/in/OptionalOverrideRightHandRoomDrag" : "Optional Override Right Hand Room Drag",
"/actions/main/in/PushToTalk" : "Push To Talk"
}
]
}
-47
View File
@@ -351,39 +351,6 @@ MyStackViewPage {
AudioTabController.pttEnabled = checked
}
}
RowLayout {
spacing: 18
MyComboBox {
Layout.leftMargin: 78
id: summaryPttProfileComboBox
Layout.maximumWidth: 378
Layout.minimumWidth: 378
Layout.preferredWidth: 378
Layout.fillWidth: true
model: [""]
onCurrentIndexChanged: {
if (currentIndex > 0) {
summaryPttProfileApplyButton.enabled = true
} else {
summaryPttProfileApplyButton.enabled = false
}
}
}
MyPushButton {
id: summaryPttProfileApplyButton
enabled: false
Layout.preferredWidth: 150
text: "Apply"
onClicked: {
if (summaryPttProfileComboBox.currentIndex > 0) {
AudioTabController.applyPttProfile(summaryPttProfileComboBox.currentIndex - 1)
summaryPttProfileComboBox.currentIndex = 0
}
}
}
}
}
Item {
@@ -406,7 +373,6 @@ MyStackViewPage {
Component.onCompleted: {
reloadChaperoneProfiles()
reloadSteamVRProfiles()
reloadPttProfiles()
summaryVersionText.text = applicationVersion
@@ -443,9 +409,6 @@ MyStackViewPage {
Connections {
target: AudioTabController
onPttProfilesUpdated: {
reloadPttProfiles()
}
onMicVolumeChanged: {
summaryMicVolumeSlider.value = AudioTabController.micVolume
}
@@ -529,14 +492,4 @@ MyStackViewPage {
summarySteamVRProfileComboBox.currentIndex = 0
summarySteamVRProfileComboBox.model = profiles
}
function reloadPttProfiles() {
var profiles = [""]
var profileCount = AudioTabController.getPttProfileCount()
for (var i = 0; i < profileCount; i++) {
profiles.push(AudioTabController.getPttProfileName(i))
}
summaryPttProfileComboBox.currentIndex = 0
summaryPttProfileComboBox.model = profiles
}
}
@@ -45,7 +45,7 @@ RowLayout {
setShownAudioDevice(index)
}
onPlaybackDeviceListChanged: {
audioPlaybackNameCombo.devices = getAudioDeviceList()
audioMirrorNameCombo.devices = getAudioDeviceList()
setShownAudioDevice(AudioTabController.playbackDeviceIndex)
}
}
@@ -10,18 +10,10 @@ ColumnLayout {
id: audioMessageDialog
}
PttDeleteProfileDialog {
id: pttDeleteProfileDialog
}
AudioDeleteProfileDialog {
id: audioDeleteProfileDialog
}
PttNewProfileDialog {
id: pttNewProfileDialog
}
AudioNewProfileDialog {
id: audioNewProfileDialog
}
@@ -61,38 +53,9 @@ ColumnLayout {
}
}
}
MyText {
text: "PTT Profile:"
Layout.preferredWidth: 150
}
MyComboBox {
id: pttProfileComboBox
Layout.preferredWidth: 250
model: [""]
onCurrentIndexChanged: {
if (currentIndex > 0) {
pttApplyProfileButton.enabled = true
pttDeleteProfileButton.enabled = true
} else {
pttApplyProfileButton.enabled = false
pttDeleteProfileButton.enabled = false
}
}
}
MyPushButton {
id: pttApplyProfileButton
enabled: true
Layout.preferredWidth: 150
text: "Apply"
onClicked: {
if (pttProfileComboBox.currentIndex > 0) {
AudioTabController.applyPttProfile(
pttProfileComboBox.currentIndex - 1)
}
}
// Text continues in next RowLayout.
text: "Change the Push To Talk settings"
}
}
RowLayout {
@@ -117,62 +80,27 @@ ColumnLayout {
audioNewProfileDialog.openPopup()
}
}
Item {
Layout.fillWidth: true
}
MyPushButton {
id: pttDeleteProfileButton
enabled: true
Layout.preferredWidth: 200
text: "Delete Profile"
onClicked: {
if (pttProfileComboBox.currentIndex > 0) {
pttDeleteProfileDialog.profileIndex = pttProfileComboBox.currentIndex - 1
pttDeleteProfileDialog.open()
}
}
}
MyPushButton {
Layout.preferredWidth: 200
text: "New Profile"
onClicked: {
pttNewProfileDialog.openPopup()
}
MyText {
// Text continues from RowLayout above.
text: "\t\tin the SteamVR bindings menu."
}
}
Component.onCompleted: {
reloadPttProfiles()
reloadAudioProfiles()
}
Connections {
target: AudioTabController
onPttProfilesUpdated: {
reloadPttProfiles()
}
onAudioProfilesUpdated: {
reloadAudioProfiles()
}
onAudioProfileAdded: {
audioProfileComboBox.currentIndex = AudioTabController.getAudioProfileCount()
}
onPttProfileAdded: {
pttProfileComboBox.currentIndex = AudioTabController.getPttProfileCount()
}
onDefaultProfileDisplay: {
audioProfileComboBox.currentIndex = AudioTabController.getDefaultAudioProfileIndex(
) + 1
}
}
function reloadPttProfiles() {
var profiles = [""]
var profileCount = AudioTabController.getPttProfileCount()
for (var i = 0; i < profileCount; i++) {
profiles.push(AudioTabController.getPttProfileName(i))
}
pttProfileComboBox.currentIndex = 0
pttProfileComboBox.model = profiles
}
function reloadAudioProfiles() {
var profiles = [""]
var profileCount = AudioTabController.getAudioProfileCount()
@@ -6,54 +6,17 @@ import "../../common"
ColumnLayout {
RowLayout {
PttControllerConfigDialog {
id: pttControllerConfigDialog
pttControllerConfigClass: AudioTabController
}
MyToggleButton {
id: audioPttEnabledToggle
Layout.preferredWidth: 260
Layout.fillWidth: true
text: "Push-to-Talk:"
onClicked: {
AudioTabController.pttEnabled = checked
}
}
MyToggleButton {
id: audioPttLeftControllerToggle
text: "Left Controller"
onClicked: {
AudioTabController.setPttLeftControllerEnabled(checked, false)
}
}
MyPushButton {
text: "Configure"
onClicked: {
pttControllerConfigDialog.openPopup(0)
}
}
Item {
Layout.fillWidth: true
}
MyToggleButton {
id: audioPttRightControllerToggle
text: "Right Controller"
onClicked: {
AudioTabController.setPttRightControllerEnabled(checked, false)
}
}
MyPushButton {
text: "Configure"
onClicked: {
pttControllerConfigDialog.openPopup(1)
}
}
}
RowLayout {
MyToggleButton {
id: audioPttShowNotificationToggle
Layout.leftMargin: 350
Layout.fillWidth: true
text: "Show notification in HMD"
onCheckedChanged: {
AudioTabController.setPttShowNotification(checked, false)
@@ -61,7 +24,7 @@ ColumnLayout {
}
MyToggleButton {
id: audioPttReverseToggle
Layout.leftMargin: 118
Layout.fillWidth: true
text: "Push-to-Mute"
onClicked: {
AudioTabController.setMicReversePtt(checked, false)
@@ -71,8 +34,6 @@ ColumnLayout {
Component.onCompleted: {
audioPttEnabledToggle.checked = AudioTabController.pttEnabled
audioPttLeftControllerToggle.checked = AudioTabController.pttLeftControllerEnabled
audioPttRightControllerToggle.checked = AudioTabController.pttRightControllerEnabled
audioPttShowNotificationToggle.checked = AudioTabController.pttShowNotification
audioPttReverseToggle.checked = AudioTabController.micReversePtt
}
@@ -81,12 +42,6 @@ ColumnLayout {
onPttEnabledChanged: {
audioPttEnabledToggle.checked = AudioTabController.pttEnabled
}
onPttLeftControllerEnabledChanged: {
audioPttLeftControllerToggle.checked = AudioTabController.pttLeftControllerEnabled
}
onPttRightControllerEnabledChanged: {
audioPttRightControllerToggle.checked = AudioTabController.pttRightControllerEnabled
}
onMicReversePttChanged: {
audioPttReverseToggle.checked = AudioTabController.micReversePtt
}
@@ -1,148 +0,0 @@
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
import matzman666.advsettings 1.0
MyDialogOkCancelPopup {
id: pttControllerConfigDialog
property var pttControllerConfigClass
property int controllerIndex: -1
dialogTitle: "Controller Configuration"
dialogWidth: 600
dialogHeight: 620
dialogContentItem: ColumnLayout {
MyText {
text: "Buttons"
}
Rectangle {
color: "#cccccc"
height: 1
Layout.fillWidth: true
}
MyToggleButton {
id: pttControllerConfigGripButtonToggle
text: "Grip"
}
MyToggleButton {
id: pttControllerConfigMenuButtonToggle
text: "Menu"
}
MyToggleButton {
id: pttControllerConfigTriggerButtonToggle
text: "Trigger"
}
MyText {
Layout.topMargin: 32
text: "Touchpad"
}
Rectangle {
color: "#cccccc"
height: 1
Layout.fillWidth: true
}
RowLayout {
spacing: 64
MyToggleButton {
id: pttControllerConfigPadLeftToggle
text: "Left"
}
MyToggleButton {
id: pttControllerConfigPadRightToggle
text: "Right"
}
}
RowLayout {
spacing: 64
MyToggleButton {
id: pttControllerConfigPadTopToggle
text: "Top"
}
MyToggleButton {
id: pttControllerConfigPadBottomToggle
text: "Bottom"
}
}
RowLayout {
MyText {
text: "Mode:"
}
MyComboBox {
id: pttControllerConfigPadModeCombo
Layout.preferredWidth: 250
model: ["Disabled", "Touched", "Pressed"]
}
}
}
onClosed: {
if (okClicked) {
var buttons = []
if (pttControllerConfigGripButtonToggle.checked) {
buttons.push(2)
}
if (pttControllerConfigMenuButtonToggle.checked) {
buttons.push(1)
}
var triggerMode = 0
if (pttControllerConfigTriggerButtonToggle.checked) {
triggerMode = 1
}
var padAreas = 0
if (pttControllerConfigPadLeftToggle.checked) {
padAreas |= (1 << 0)
}
if (pttControllerConfigPadTopToggle.checked) {
padAreas |= (1 << 1)
}
if (pttControllerConfigPadRightToggle.checked) {
padAreas |= (1 << 2)
}
if (pttControllerConfigPadBottomToggle.checked) {
padAreas |= (1 << 3)
}
pttControllerConfigClass.setPttControllerConfig(controllerIndex, buttons, triggerMode, pttControllerConfigPadModeCombo.currentIndex, padAreas);
}
}
function openPopup(controller) {
if (controller === 0) {
dialogTitle = "Left Controller Configuration"
controllerIndex = 0
} else {
dialogTitle = "Right Controller Configuration"
controllerIndex = 1
}
pttControllerConfigGripButtonToggle.checked = false
pttControllerConfigMenuButtonToggle.checked = false
pttControllerConfigTriggerButtonToggle.checked = false
pttControllerConfigPadLeftToggle.checked = false
pttControllerConfigPadTopToggle.checked = false
pttControllerConfigPadRightToggle.checked = false
pttControllerConfigPadBottomToggle.checked = false
pttControllerConfigPadModeCombo.currentIndex = pttControllerConfigClass.pttTouchpadMode(controllerIndex)
var buttons = pttControllerConfigClass.pttDigitalButtons(controllerIndex)
for (var i = 0; i < buttons.length; i++) {
if (buttons[i] == 1) {
pttControllerConfigMenuButtonToggle.checked = true
} else if (buttons[i] == 2) {
pttControllerConfigGripButtonToggle.checked = true
}
}
if (pttControllerConfigClass.pttTriggerMode(controllerIndex) > 0) {
pttControllerConfigTriggerButtonToggle.checked = true
}
var padAreas = pttControllerConfigClass.pttTouchpadArea(controllerIndex)
if (padAreas & (1 << 0)) {
pttControllerConfigPadLeftToggle.checked = true
}
if (padAreas & (1 << 1)) {
pttControllerConfigPadTopToggle.checked = true
}
if (padAreas & (1 << 2)) {
pttControllerConfigPadRightToggle.checked = true
}
if (padAreas & (1 << 3)) {
pttControllerConfigPadBottomToggle.checked = true
}
open()
}
}
+3 -1
View File
@@ -87,7 +87,7 @@ private:
void onPttStop() override;
void onPttEnabled() override;
void onPttDisabled() override;
bool pttChangeValid() override;
virtual vr::VROverlayHandle_t getNotificationOverlayHandle() override
{
return m_ulNotificationOverlayHandle;
@@ -114,6 +114,8 @@ public:
void eventLoopTick();
bool pttChangeValid() override;
int playbackDeviceIndex() const;
int mirrorDeviceIndex() const;
+2 -112
View File
@@ -222,118 +222,8 @@ void PttController::savePttConfig()
void PttController::checkPttStatus()
{
static auto handleControllerState
= []( const vr::VRControllerState_t& state,
PttControllerConfig* config ) -> bool {
if ( state.ulButtonPressed & config->digitalButtonMask )
{
return true;
}
if ( config->triggerMode )
{
if ( state.ulButtonPressed
& vr::ButtonMaskFromId( vr::k_EButton_SteamVR_Trigger ) )
{
return true;
}
}
if ( config->touchpadMode )
{
if ( ( ( config->touchpadMode & 1 )
&& ( state.ulButtonTouched
& vr::ButtonMaskFromId(
vr::k_EButton_SteamVR_Touchpad ) ) )
|| ( ( config->touchpadMode & 2 )
&& ( state.ulButtonPressed
& vr::ButtonMaskFromId(
vr::k_EButton_SteamVR_Touchpad ) ) ) )
{
if ( config->touchpadAreas
== ( PAD_AREA_LEFT + PAD_AREA_TOP + PAD_AREA_RIGHT
+ PAD_AREA_BOTTOM ) )
{
return true;
}
else
{
float x = state.rAxis[0].x;
float y = state.rAxis[0].y;
if ( std::abs( x ) >= 0.2 || std::abs( y ) >= 0.2 )
{ // deadzone in the middle
if ( x < 0 && std::abs( y ) < -x
&& ( config->touchpadAreas & PAD_AREA_LEFT ) )
{
return true;
}
else if ( y > 0 && std::abs( x ) < y
&& ( config->touchpadAreas & PAD_AREA_TOP ) )
{
return true;
}
else if ( x > 0 && std::abs( y ) < x
&& ( config->touchpadAreas
& PAD_AREA_RIGHT ) )
{
return true;
}
else if ( y < 0 && std::abs( x ) < -y
&& ( config->touchpadAreas
& PAD_AREA_BOTTOM ) )
{
return true;
}
}
}
}
}
return false;
};
if ( m_pttEnabled )
{
bool newState = false;
if ( m_pttLeftControllerEnabled )
{
auto leftId
= vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(
vr::TrackedControllerRole_LeftHand );
if ( leftId != vr::k_unTrackedDeviceIndexInvalid )
{
vr::VRControllerState_t state;
if ( vr::VRSystem()->GetControllerState(
leftId, &state, sizeof( vr::VRControllerState_t ) ) )
{
// logControllerState(state, "Left ");
newState |= handleControllerState( state,
m_pttControllerConfigs );
}
}
}
if ( m_pttRightControllerEnabled )
{
auto rightId
= vr::VRSystem()->GetTrackedDeviceIndexForControllerRole(
vr::TrackedControllerRole_RightHand );
if ( rightId != vr::k_unTrackedDeviceIndexInvalid )
{
vr::VRControllerState_t state;
if ( vr::VRSystem()->GetControllerState(
rightId, &state, sizeof( vr::VRControllerState_t ) ) )
{
// logControllerState(state, "Right ");
newState |= handleControllerState(
state, m_pttControllerConfigs + 1 );
}
}
}
if ( newState && !m_pttActive && pttChangeValid() )
{
startPtt();
}
else if ( !newState && m_pttActive && pttChangeValid() )
{
stopPtt();
}
}
// PTT Controls are now handled in the overlaycontroller using public
// functions.
}
void PttController::startPtt()
+6 -4
View File
@@ -75,10 +75,7 @@ protected:
virtual void onPttStop(){};
virtual void onPttEnabled(){};
virtual void onPttDisabled(){};
virtual bool pttChangeValid()
{
return true;
}
virtual vr::VROverlayHandle_t getNotificationOverlayHandle()
{
return vr::k_ulOverlayHandleInvalid;
@@ -100,6 +97,11 @@ public:
void savePttProfiles();
void savePttConfig();
virtual bool pttChangeValid()
{
return true;
}
Q_INVOKABLE QVariantList pttDigitalButtons( unsigned controller );
Q_INVOKABLE unsigned long pttDigitalButtonMask( unsigned controller );
Q_INVOKABLE unsigned pttTouchpadMode( unsigned controller );