From 8bcab9b2c09e13480fa663b8363c02269b8a9395 Mon Sep 17 00:00:00 2001 From: Vasily Date: Sat, 19 Jan 2019 16:14:05 +0100 Subject: [PATCH] Refactor ivrinput functions to be more generic --- advancedSettings.pro | 3 +- src/ivrinput/ivrinput_action.h | 42 ++++++++++++ src/overlaycontroller.cpp | 2 +- src/steamivrinput.cpp | 118 ++++++++++++++++++++------------- src/steamivrinput.h | 29 ++++++-- 5 files changed, 141 insertions(+), 53 deletions(-) create mode 100644 src/ivrinput/ivrinput_action.h diff --git a/advancedSettings.pro b/advancedSettings.pro index 9ed0a57..20b477a 100644 --- a/advancedSettings.pro +++ b/advancedSettings.pro @@ -80,7 +80,8 @@ HEADERS += src/overlaycontroller.h \ src/tabcontrollers/audiomanager/AudioManagerDummy.h \ src/tabcontrollers/keyboardinput/KeyboardInputDummy.h \ src/overlaycontroller/openvr_init.h \ - src/steamivrinput.h + src/steamivrinput.h \ + src/ivrinput/ivrinput_action.h win32 { SOURCES += src/tabcontrollers/audiomanager/AudioManagerWindows.cpp \ diff --git a/src/ivrinput/ivrinput_action.h b/src/ivrinput/ivrinput_action.h new file mode 100644 index 0000000..85d2463 --- /dev/null +++ b/src/ivrinput/ivrinput_action.h @@ -0,0 +1,42 @@ +#pragma once +#include +#include + +enum class ActionType +{ + Undefined, + Digital, +}; + +class Action +{ +public: + Action( const char* const actionName, const ActionType type ) + : m_name( actionName ), m_type( type ) + { + auto error = vr::VRInput()->GetActionHandle( actionName, &m_handle ); + + if ( error != vr::EVRInputError::VRInputError_None ) + { + LOG( ERROR ) << "Error getting handle for '" << actionName + << "'. OpenVR Error: " << error; + } + } + vr::VRActionHandle_t handle() + { + return m_handle; + } + const char* name() + { + return m_name; + } + ActionType type() + { + return m_type; + } + +private: + vr::VRActionHandle_t m_handle = 0; + const char* m_name; + ActionType m_type = ActionType::Undefined; +}; diff --git a/src/overlaycontroller.cpp b/src/overlaycontroller.cpp index 170cdba..288fba7 100644 --- a/src/overlaycontroller.cpp +++ b/src/overlaycontroller.cpp @@ -118,7 +118,7 @@ OverlayController::OverlayController( bool desktopMode, nullptr, "OpenVR Advanced Settings Overlay", "Is OpenVR running?" ); throw std::runtime_error( std::string( "No Overlay interface" ) ); } - m_actions.Init( false ); + m_actions.Init(); // Init controllers m_steamVRTabController.initStage1(); m_chaperoneTabController.initStage1(); diff --git a/src/steamivrinput.cpp b/src/steamivrinput.cpp index 57ba219..69edfda 100644 --- a/src/steamivrinput.cpp +++ b/src/steamivrinput.cpp @@ -2,43 +2,84 @@ #include #include #include +#include -void SteamIVRInput::Init( const bool init ) +void setActionManifestPath( const QString actionManifestPath ) { - if ( init ) + auto error = vr::VRInput()->SetActionManifestPath( + actionManifestPath.toStdString().c_str() ); + if ( error != vr::EVRInputError::VRInputError_None ) { - auto initError = vr::VRInitError_None; - vr::VR_Init( &initError, vr::VRApplication_Overlay ); - if ( initError != vr::VRInitError_None ) - { - std::cout << "SteamVR init error."; - } + LOG( ERROR ) << "Error setting action manifest path: " + << actionManifestPath << ". OpenVR Error: " << error; + } +} + +vr::VRActionHandle_t getActionHandle( const char* const action ) +{ + vr::VRActionHandle_t actionHandle = 0; + + auto error = vr::VRInput()->GetActionHandle( action, &actionHandle ); + + if ( error != vr::EVRInputError::VRInputError_None ) + { + LOG( ERROR ) << "Error getting handle for '" << action + << "'. OpenVR Error: " << error; } - QString manifestPath + return actionHandle; +} + +vr::VRActionSetHandle_t getActionSetHandle( const char* const set ) +{ + vr::VRActionSetHandle_t setHandle = 0; + + auto error = vr::VRInput()->GetActionSetHandle( set, &setHandle ); + if ( error != vr::EVRInputError::VRInputError_None ) + { + LOG( ERROR ) << "Error getting handle for '" << set + << "'. OpenVR Error: " << error; + } + + return setHandle; +} + +vr::InputDigitalActionData_t getDigitalActionData( vr::VRActionHandle_t handle ) +{ + vr::InputDigitalActionData_t handleData = {}; + + auto error = vr::VRInput()->GetDigitalActionData( + handle, + &handleData, + sizeof( handleData ), + vr::k_ulInvalidInputValueHandle ); + + if ( error != vr::EVRInputError::VRInputError_None ) + { + LOG( ERROR ) << "Error getting Digital Action Data for handle " + << handle << ". SteamVR Error: " << error; + } + + return handleData; +} + +bool isActionActivatedOnce( vr::VRActionHandle_t handle ) +{ + auto handleData = getDigitalActionData( handle ); + + return handleData.bState && handleData.bChanged; +} + +void SteamIVRInput::Init() +{ + QString actionManifestPath = QStandardPaths::locate( QStandardPaths::AppDataLocation, QStringLiteral( "action_manifest.json" ) ); - auto error = vr::VRInput()->SetActionManifestPath( - manifestPath.toStdString().c_str() ); - if ( error != vr::EVRInputError::VRInputError_None ) - { - std::cout << "Action manifest error\n"; - } + setActionManifestPath( actionManifestPath ); - // Get action handle - error = vr::VRInput()->GetActionHandle( "/actions/main/in/PlayNextTrack", - &m_nextSongHandler ); - if ( error != vr::EVRInputError::VRInputError_None ) - { - std::cout << "Handle error.\n"; - } + m_nextSongHandler = getActionHandle( input_strings::k_actionNextTrack ); - error = vr::VRInput()->GetActionSetHandle( "/actions/main", - &m_mainSetHandler ); - if ( error != vr::EVRInputError::VRInputError_None ) - { - std::cout << "Handle error.\n"; - } + m_mainSetHandler = getActionSetHandle( input_strings::k_setMain ); m_activeActionSet.ulActionSet = m_mainSetHandler; m_activeActionSet.ulRestrictedToDevice = vr::k_ulInvalidInputValueHandle; @@ -47,24 +88,7 @@ void SteamIVRInput::Init( const bool init ) bool SteamIVRInput::nextSongSet() { - auto e = vr::VRInput()->GetDigitalActionData( - m_nextSongHandler, - &m_nextSongData, - sizeof( m_nextSongData ), - vr::k_ulInvalidInputValueHandle ); - - if ( e != vr::EVRInputError::VRInputError_None ) - { - std::cout << e; - std::cout << "GetDigitalAction error.\n"; - } - - if ( m_nextSongData.bActive ) - { - std::cout << "Action Set Active!\n"; - } - - return m_nextSongData.bState; + return isActionActivatedOnce( m_nextSongHandler ); } void SteamIVRInput::Loop() @@ -74,6 +98,6 @@ void SteamIVRInput::Loop() if ( error != vr::EVRInputError::VRInputError_None ) { - std::cout << "Loop error.\n"; + LOG( ERROR ) << "Loop error."; } } diff --git a/src/steamivrinput.h b/src/steamivrinput.h index 91e50f8..06f0adc 100644 --- a/src/steamivrinput.h +++ b/src/steamivrinput.h @@ -1,15 +1,31 @@ -#ifndef STEAMIVRINPUT_H -#define STEAMIVRINPUT_H +#pragma once #include +#include "ivrinput/ivrinput_action.h" class SteamIVRInput { public: - void Init( const bool init ); + // SteamIVRInput(); + void Init(); void Loop(); bool nextSongSet(); + // These have been explicitly deleted to make sure there are no attempts at + // copying the class in weird ways. It is not worth defining what should + // happen on copy because it simply shouldn't be done. + // Destructor. There are not terminating calls for the IVRInput API, so it + // is unneeded. + //~SteamIVRInput() = delete; + //// Copy constructor + // SteamIVRInput( const SteamIVRInput& ) = delete; + //// Copy assignment + // SteamIVRInput& operator=( const SteamIVRInput& ) = delete; + //// Move constructor + // SteamIVRInput( SteamIVRInput&& ) = delete; + //// Move assignment + // SteamIVRInput& operator=( const SteamIVRInput&& ) = delete; + private: vr::VRActionHandle_t m_nextSongHandler = {}; vr::VRActionSetHandle_t m_mainSetHandler = {}; @@ -17,4 +33,9 @@ private: vr::InputDigitalActionData_t m_nextSongData = {}; }; -#endif // STEAMIVRINPUT_H +namespace input_strings +{ +constexpr auto k_actionNextTrack = "/actions/main/in/PlayNextTrack"; +constexpr auto k_setMain = "/actions/main"; + +} // namespace input_strings