summaryrefslogtreecommitdiff
path: root/inputsystem/steamcontroller.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /inputsystem/steamcontroller.cpp
downloadarchived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz
archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip
Diffstat (limited to 'inputsystem/steamcontroller.cpp')
-rw-r--r--inputsystem/steamcontroller.cpp695
1 files changed, 695 insertions, 0 deletions
diff --git a/inputsystem/steamcontroller.cpp b/inputsystem/steamcontroller.cpp
new file mode 100644
index 0000000..007ccec
--- /dev/null
+++ b/inputsystem/steamcontroller.cpp
@@ -0,0 +1,695 @@
+//=========== Copyright Valve Corporation, All rights reserved. ===============//
+//
+// Purpose: Native Steam Controller Interface
+//=============================================================================//
+#include "inputsystem.h"
+#include "key_translation.h"
+#include "filesystem.h"
+#include "steam/isteamcontroller.h"
+#include "math.h"
+
+#ifndef UINT64_MAX
+const uint64 UINT64_MAX = 0xffffffffffffffff;
+#endif
+
+#if !defined( NO_STEAM )
+#include "steam/steam_api.h"
+#endif //NO_STEAM
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include <tier0/memdbgon.h>
+
+ConVar sc_joystick_map( "sc_joystick_map", "1", FCVAR_ARCHIVE, "How to map the analog joystick deadzone and extents 0 = Scaled Cross, 1 = Concentric Mapping to Square." );
+
+#define STEAMPAD_MAX_ANALOGSAMPLE_GYRO 32768
+#define STEAMPAD_MAX_ANALOGSAMPLE_TRIGGER 32768
+#define STEAMPAD_MAX_ANALOGSAMPLE_LEFT 32768
+#define STEAMPAD_MAX_ANALOGSAMPLE_RIGHT 32767
+#define STEAMPAD_MAX_ANALOGSAMPLE_DOWN 32768
+#define STEAMPAD_MAX_ANALOGSAMPLE_UP 32767
+#define STEAMPAD_MAX_ANALOGSAMPLE_MAX 32768
+#define STEAMPAD_ANALOG_SCALE_LEFT(x) ( ( float )STEAMPAD_MAX_ANALOGSAMPLE_LEFT/( float )( STEAMPAD_MAX_ANALOGSAMPLE_LEFT-(x) ) )
+#define STEAMPAD_ANALOG_SCALE_RIGHT(x) ( ( float )STEAMPAD_MAX_ANALOGSAMPLE_RIGHT/( float )( STEAMPAD_MAX_ANALOGSAMPLE_RIGHT-(x) ) )
+#define STEAMPAD_ANALOG_SCALE_DOWN(x) ( ( float )STEAMPAD_MAX_ANALOGSAMPLE_DOWN/( float )( STEAMPAD_MAX_ANALOGSAMPLE_DOWN-(x) ) )
+#define STEAMPAD_ANALOG_SCALE_UP(x) ( ( float )STEAMPAD_MAX_ANALOGSAMPLE_UP/( float )( STEAMPAD_MAX_ANALOGSAMPLE_UP-(x) ) )
+
+
+#define STEAMPAD_ANALOG_TRIGGER_THRESHOLD ( ( int )( STEAMPAD_MAX_ANALOGSAMPLE_TRIGGER * 0.5f ) )
+#define STEAMPAD_ANALOG_PAD_THRESHOLD ( ( int )( STEAMPAD_MAX_ANALOGSAMPLE_MAX * 0.25f ) )
+#define STEAMPAD_ANALOG_GYRO_THRESHOLD ( ( int ) ( STEAMPAD_MAX_ANALOGSAMPLE_GYRO * 0.3f ) )
+#define STEAMPAD_DIGITAL_PAD_THRESHOLD ( ( int )( STEAMPAD_MAX_ANALOGSAMPLE_MAX * 0.52f ) )
+
+#define STEAMPAD_AXIS_REPEAT_INTERVAL_START 0.6f
+#define STEAMPAD_AXIS_REPEAT_INTERVAL_END 0.05f
+#define STEAMPAD_AXIS_REPEAT_CURVE_TIME 1.75f
+
+#define PAD_ANALOG_BUTTON_THRESHOLD ( ( int )( STEAMPAD_MAX_ANALOGSAMPLE_MAX * 0.285f ) )
+#define PAD_ANALOG_BUTTON_THRESHOLD_STRONG ( ( int )( STEAMPAD_MAX_ANALOGSAMPLE_MAX * 0.68f ) )
+
+#define SQRT2 1.414213562
+
+// key translation
+typedef struct
+{
+ uint64 steampadinput;
+ ButtonCode_t steampadkey;
+} steampadInputTosteampadKey_t;
+
+static const int s_nSteamPadDeadZoneTable[] =
+{
+ STEAMPAD_ANALOG_PAD_THRESHOLD, // LEFTPAD_AXIS_X
+ STEAMPAD_ANALOG_PAD_THRESHOLD, // LEFTPAD_AXIS_Y
+ STEAMPAD_ANALOG_PAD_THRESHOLD, // RIGHTPAD_AXIS_X
+ STEAMPAD_ANALOG_PAD_THRESHOLD, // RIGHTPAD_AXIS_Y
+ STEAMPAD_ANALOG_TRIGGER_THRESHOLD, //LEFT_TRIGGER_AXIS
+ STEAMPAD_ANALOG_TRIGGER_THRESHOLD, //RIGHT_TRIGGER_AXIS
+ STEAMPAD_ANALOG_GYRO_THRESHOLD, //GYRO_AXIS_PITCH
+ STEAMPAD_ANALOG_GYRO_THRESHOLD, //GYRO_AXIS_ROLL
+ STEAMPAD_ANALOG_GYRO_THRESHOLD, //GYRO_AXIS_YAW
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: Counts the number of active gamepads connected
+//-----------------------------------------------------------------------------
+uint32 CInputSystem::GetNumSteamControllersConnected()
+{
+ return m_unNumConnected;
+}
+
+struct SDigitalMenuAction
+{
+ const char *strName;
+ ButtonCode_t buttonCode;
+ ControllerDigitalActionHandle_t handle;
+ bool bState[STEAM_CONTROLLER_MAX_COUNT];
+ bool bAwaitingDebounce[STEAM_CONTROLLER_MAX_COUNT];
+};
+
+static SDigitalMenuAction g_DigitalMenuActions[] = {
+ { "menu_left", STEAMCONTROLLER_DPAD_LEFT, 0, { false }, { false } },
+ { "menu_right", STEAMCONTROLLER_DPAD_RIGHT, 0, { false }, { false } },
+ { "menu_up", STEAMCONTROLLER_DPAD_UP, 0, { false }, { false } },
+ { "menu_down", STEAMCONTROLLER_DPAD_DOWN, 0, { false }, { false } },
+ { "menu_cancel", STEAMCONTROLLER_B, 0, { false }, { false } },
+ { "menu_select", STEAMCONTROLLER_A, 0, { false }, { false } },
+ { "resume_esc", STEAMCONTROLLER_START, 0, { false }, { false } },
+ { "cl_trigger_first_notification", STEAMCONTROLLER_F1, 0, { false }, { false } }, // Command is in the in-game action set (use for hitting accept/ok on dialogs)
+ { "cl_decline_first_notification", STEAMCONTROLLER_F2, 0, { false }, { false } }, // Command is in the in-game action set (use for hitting cancel/decline on dialogs)
+ { "menu_toggle_function", STEAMCONTROLLER_Y, 0, { false }, { false }, }, // Command is in the in-game HUD action set
+ { "menu_alt_function", STEAMCONTROLLER_X, 0, { false }, { false } }, // Command is in the in-game HUD action set
+ { "cancelselect", STEAMCONTROLLER_START, 0, { false }, { false } }, // Command is in the in-game action set
+ { "toggleready", STEAMCONTROLLER_F4, 0, { false }, { false } }, // Command is in the in-game action set
+};
+
+struct SAnalogAction
+{
+ const char *strName;
+ JoystickAxis_t joystickAxisX, joystickAxisY;
+ ControllerAnalogActionHandle_t handle;
+};
+
+struct SGameActionSet
+{
+ const char *strName;
+ GameActionSet_t eGameActionSet;
+ ControllerActionSetHandle_t handle;
+};
+static SGameActionSet g_GameActionSets[] = {
+ { "MenuControls", GAME_ACTION_SET_MENUCONTROLS, 0 },
+ { "FPSControls", GAME_ACTION_SET_FPSCONTROLS, 0 },
+ { "InGameHUDControls", GAME_ACTION_SET_IN_GAME_HUD, 0 },
+ { "SpectatorControls", GAME_ACTION_SET_SPECTATOR, 0 },
+};
+
+
+// Table that maps a physical steam controller origin to the corresponding character in our icon font.
+// If the EControllerActionOrigin enum or the font changes, this table must be changed to match.
+static const wchar_t* g_MapSteamControllerOriginToIconFont[] = {
+ L"", // k_EControllerActionOrigin_None
+ L"A", // k_EControllerActionOrigin_A
+ L"B", // k_EControllerActionOrigin_B
+ L"X", // k_EControllerActionOrigin_X
+ L"Y", // k_EControllerActionOrigin_Y
+ L"2", // k_EControllerActionOrigin_LeftBumper
+ L"3", // k_EControllerActionOrigin_RightBumper
+ L"(", // k_EControllerActionOrigin_LeftGrip
+ L")", // k_EControllerActionOrigin_RightGrip
+ L"5", // k_EControllerActionOrigin_Start
+ L"4", // k_EControllerActionOrigin_Back
+ L"q", // k_EControllerActionOrigin_LeftPad_Touch
+ L"w", // k_EControllerActionOrigin_LeftPad_Swipe
+ L"e", // k_EControllerActionOrigin_LeftPad_Click
+ L"a", // k_EControllerActionOrigin_LeftPad_DPadNorth
+ L"s", // k_EControllerActionOrigin_LeftPad_DPadSouth
+ L"d", // k_EControllerActionOrigin_LeftPad_DPadWest
+ L"f", // k_EControllerActionOrigin_LeftPad_DPadEast
+ L"y", // k_EControllerActionOrigin_RightPad_Touch
+ L"u", // k_EControllerActionOrigin_RightPad_Swipe
+ L"i", // k_EControllerActionOrigin_RightPad_Click
+ L"h", // k_EControllerActionOrigin_RightPad_DPadNorth
+ L"j", // k_EControllerActionOrigin_RightPad_DPadSouth
+ L"k", // k_EControllerActionOrigin_RightPad_DPadWest
+ L"l", // k_EControllerActionOrigin_RightPad_DEast
+ L"z", // k_EControllerActionOrigin_LeftTrigger_Pull
+ L"x", // k_EControllerActionOrigin_LeftTrigger_Click
+ L"n", // k_EControllerActionOrigin_RightTrigger_Pull
+ L"m", // k_EControllerActionOrigin_RightTrigger_Click
+ L"C", // k_EControllerActionOrigin_LeftStick_Move
+ L"V", // k_EControllerActionOrigin_LeftStick_Click
+ L"7", // k_EControllerActionOrigin_LeftStick_DPadNorth
+ L"8", // k_EControllerActionOrigin_LeftStick_DPadSouth
+ L"9", // k_EControllerActionOrigin_LeftStick_DPadWest
+ L"0", // k_EControllerActionOrigin_LeftStick_DPadEast
+ L"6", // k_EControllerActionOrigin_Gyro_Move
+ L"6", // k_EControllerActionOrigin_Gyro_Pitch
+ L"6", // k_EControllerActionOrigin_Gyro_Yaw
+ L"6", // k_EControllerActionOrigin_Gyro_Roll
+};
+
+// Table that maps a physical steam controller origin to a short description string for user display (only use this
+// if it's impractical to use the icon font).
+// If the EControllerActionOrigin enum changes, this table must be changed to match.
+static const wchar_t* g_MapSteamControllerOriginToDescription[] = {
+ L"", // k_EControllerActionOrigin_None
+ L"A", // k_EControllerActionOrigin_A
+ L"B", // k_EControllerActionOrigin_B
+ L"X", // k_EControllerActionOrigin_X
+ L"Y", // k_EControllerActionOrigin_Y
+ L"LB", // k_EControllerActionOrigin_LeftBumper
+ L"RB", // k_EControllerActionOrigin_RightBumper
+ L"LG", // k_EControllerActionOrigin_LeftGrip
+ L"RG", // k_EControllerActionOrigin_RightGrip
+ L"START", // k_EControllerActionOrigin_Start
+ L"BACK", // k_EControllerActionOrigin_Back
+ L"LPTOUCH", // k_EControllerActionOrigin_LeftPad_Touch
+ L"LPSWIPE", // k_EControllerActionOrigin_LeftPad_Swipe
+ L"LPCLICK", // k_EControllerActionOrigin_LeftPad_Click
+ L"LPUP", // k_EControllerActionOrigin_LeftPad_DPadNorth
+ L"LPDOWN", // k_EControllerActionOrigin_LeftPad_DPadSouth
+ L"LPLEFT", // k_EControllerActionOrigin_LeftPad_DPadWest
+ L"LPRIGHT", // k_EControllerActionOrigin_LeftPad_DPadEast
+ L"RPTOUCH", // k_EControllerActionOrigin_RightPad_Touch
+ L"RPSWIPE", // k_EControllerActionOrigin_RightPad_Swipe
+ L"RPCLICK", // k_EControllerActionOrigin_RightPad_Click
+ L"RPUP", // k_EControllerActionOrigin_RightPad_DPadNorth
+ L"RPDOWN", // k_EControllerActionOrigin_RightPad_DPadSouth
+ L"RPLEFT", // k_EControllerActionOrigin_RightPad_DPadWest
+ L"RPRIGHT", // k_EControllerActionOrigin_RightPad_DEast
+ L"LT", // k_EControllerActionOrigin_LeftTrigger_Pull
+ L"LT", // k_EControllerActionOrigin_LeftTrigger_Click
+ L"LT", // k_EControllerActionOrigin_RightTrigger_Pull
+ L"LT", // k_EControllerActionOrigin_RightTrigger_Click
+ L"LS", // k_EControllerActionOrigin_LeftStick_Move
+ L"LSCLICK", // k_EControllerActionOrigin_LeftStick_Click
+ L"LSUP", // k_EControllerActionOrigin_LeftStick_DPadNorth
+ L"LSDOWN", // k_EControllerActionOrigin_LeftStick_DPadSouth
+ L"LSLEFT", // k_EControllerActionOrigin_LeftStick_DPadWest
+ L"LSRIGHT", // k_EControllerActionOrigin_LeftStick_DPadEast
+ L"GYRO", // k_EControllerActionOrigin_Gyro_Move
+ L"GYRO", // k_EControllerActionOrigin_Gyro_Pitch
+ L"GYRO", // k_EControllerActionOrigin_Gyro_Yaw
+ L"GYRO", // k_EControllerActionOrigin_Gyro_Roll
+};
+
+
+bool CInputSystem::InitializeSteamControllerActionSets()
+{
+ auto psteamcontroller = g_pInputSystem->SteamControllerInterface();
+ if ( !psteamcontroller )
+ {
+ return false;
+ }
+
+ bool bGotHandles = true;
+
+ for ( int i = 0; i != ARRAYSIZE( g_DigitalMenuActions ); ++i )
+ {
+ g_DigitalMenuActions[i].handle = psteamcontroller->GetDigitalActionHandle( g_DigitalMenuActions[i].strName );
+ bGotHandles = bGotHandles && ( g_DigitalMenuActions[i].handle != 0 );
+
+ // Init the button state array
+ for( int j = 0; j < STEAM_CONTROLLER_MAX_COUNT; j++ )
+ {
+ g_DigitalMenuActions[i].bState[j] = false;
+ }
+ }
+
+ for ( int i = 0; i != ARRAYSIZE( g_GameActionSets ); ++i )
+ {
+ g_GameActionSets[i].handle = psteamcontroller->GetActionSetHandle( g_GameActionSets[i].strName );
+ bGotHandles = bGotHandles && g_GameActionSets[i].handle;
+ }
+
+ return bGotHandles;
+}
+
+ConVar sc_debug_sets( "sc_debug_sets", "0", FCVAR_ARCHIVE, "Debugging" );
+
+void CInputSystem::PollSteamControllers( void )
+{
+ // Make sure we've got the appropriate connections to Steam
+ auto steamcontroller = SteamControllerInterface();
+ if ( !steamcontroller )
+ {
+ return;
+ }
+
+ steamcontroller->RunFrame();
+
+ uint64 nControllerHandles[STEAM_CONTROLLER_MAX_COUNT];
+ m_unNumConnected = steamcontroller->GetConnectedControllers( nControllerHandles );
+
+ if ( m_unNumConnected > 0 )
+ {
+ if ( !m_bSteamControllerActionsInitialized )
+ {
+ // Retry initialization of controller actions if we didn't acquire them all before for some reason.
+ m_bSteamControllerActionsInitialized = m_bSteamController && InitializeSteamControllerActionSets();
+ g_pInputSystem->ActivateSteamControllerActionSet( GAME_ACTION_SET_MENUCONTROLS );
+ }
+
+ if ( m_bSteamControllerActionsInitialized )
+ {
+ // If we successfully initialized all the actions, and we have a connected controller, then we're considered "active".
+ m_bSteamControllerActive = true;
+
+ // For each digital action
+ for ( int i = 0; i != ARRAYSIZE( g_DigitalMenuActions ); ++i )
+ {
+ SDigitalMenuAction& action = g_DigitalMenuActions[i];
+
+ // and for each controller
+ for ( uint64 j = 0; j < m_unNumConnected; ++j )
+ {
+
+ // Get the action's current state
+ ControllerDigitalActionData_t data = steamcontroller->GetDigitalActionData( nControllerHandles[j], action.handle );
+
+ // We only care if the action is active
+ if ( data.bActive )
+ {
+ action.bAwaitingDebounce[j] = action.bAwaitingDebounce[j] && data.bState;
+
+ // If the action's state has changed
+ if ( data.bState != action.bState[j] )
+ {
+ action.bState[j] = data.bState;
+
+ // Press the key for the correct controller
+ ButtonCode_t buttonCode = ButtonCodeToJoystickButtonCode( action.buttonCode, j );
+
+ if ( action.bState[j] )
+ {
+ if ( !action.bAwaitingDebounce[j] )
+ {
+ PostButtonPressedEvent( IE_ButtonPressed, m_nLastSampleTick, buttonCode, buttonCode );
+ }
+ }
+ else
+ {
+ PostButtonReleasedEvent( IE_ButtonReleased, m_nLastSampleTick, buttonCode, buttonCode );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // If no controllers are connected, unflag the active state.
+ m_bSteamControllerActive = false;
+ }
+}
+
+bool CInputSystem::GetRadialMenuStickValues( int nSlot, float &fX, float &fY )
+{
+ fX = m_pRadialMenuStickVal[nSlot][0];
+ fY = m_pRadialMenuStickVal[nSlot][1];
+
+ return true;
+}
+
+bool CInputSystem::IsSteamControllerActive( void )
+{
+ return m_bSteamControllerActive;
+}
+
+bool CInputSystem::InitializeSteamControllers()
+{
+ m_flLastSteamControllerInput = -FLT_MAX;
+ auto steamcontroller = SteamControllerInterface();
+ if ( steamcontroller )
+ {
+ if ( !steamcontroller->Init() )
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+
+ for( int i=0; i<STEAM_CONTROLLER_MAX_COUNT; i++ )
+ {
+ m_pRadialMenuStickVal[i][0] = 0.0f;
+ m_pRadialMenuStickVal[i][1] = 0.0f;
+ }
+
+ // We have to account for other joysticks prior to adding steam controllers
+ // So we get the baseline number here when first initializing
+ m_nJoystickBaseline = m_nJoystickCount;
+ if ( steamcontroller )
+ {
+ uint64 nControllerHandles[STEAM_CONTROLLER_MAX_COUNT];
+ m_unNumConnected = steamcontroller->GetConnectedControllers( nControllerHandles );
+ steamcontroller->RunFrame();
+
+ if ( m_unNumConnected > 0 )
+ {
+ for ( uint32 i = 0; i < m_unNumConnected; i++ )
+ {
+ if ( m_Device[i].m_nJoystickIndex == INVALID_USER_ID )
+ {
+ int nJoystickIndex = i;
+ m_Device[i].m_nJoystickIndex = nJoystickIndex;
+ m_Device[i].m_nHardwareIndex = i;
+ }
+ m_nControllerType[m_Device[i].m_nJoystickIndex] = INPUT_TYPE_STEAMCONTROLLER;
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+ControllerActionSetHandle_t CInputSystem::GetActionSetHandle( GameActionSet_t eActionSet )
+{
+ return g_GameActionSets[eActionSet].handle;
+}
+
+ControllerActionSetHandle_t CInputSystem::GetActionSetHandle( const char* szActionSet )
+{
+ for ( int i = 0; i != ARRAYSIZE( g_GameActionSets ); ++i )
+ {
+ if ( !Q_strcmp( szActionSet, g_GameActionSets[i].strName ) )
+ {
+ return g_GameActionSets[i].handle;
+ }
+ }
+
+ return 0;
+}
+
+
+void CInputSystem::ActivateSteamControllerActionSetForSlot( uint64 nSlot, GameActionSet_t eActionSet )
+{
+ auto steamcontroller = SteamControllerInterface();
+ bool bChangedActionSet = false;
+
+ if ( steamcontroller )
+ {
+ if ( nSlot == STEAM_CONTROLLER_HANDLE_ALL_CONTROLLERS )
+ {
+ for ( int i = 0; i < STEAM_CONTROLLER_MAX_COUNT; i++ )
+ {
+ if ( m_currentActionSet[i] != eActionSet )
+ {
+ bChangedActionSet = true;
+ m_currentActionSet[i] = eActionSet;
+ }
+ }
+
+ steamcontroller->ActivateActionSet( STEAM_CONTROLLER_HANDLE_ALL_CONTROLLERS, g_GameActionSets[eActionSet].handle );
+ }
+ else
+ {
+ uint64 nControllerHandles[STEAM_CONTROLLER_MAX_COUNT];
+ int unNumConnected = steamcontroller->GetConnectedControllers( nControllerHandles );
+
+ if( nSlot < unNumConnected )
+ {
+ if ( m_currentActionSet[nSlot] != eActionSet )
+ {
+ bChangedActionSet = true;
+ m_currentActionSet[nSlot] = eActionSet;
+ }
+
+ steamcontroller->ActivateActionSet( nControllerHandles[nSlot], g_GameActionSets[eActionSet].handle );
+ }
+ }
+ }
+
+ if ( bChangedActionSet )
+ {
+ // If we changed action set, then flag everything for a debounce (meaning we demand to see an unpressed state before we'll register a pressed one)
+ for ( int i = 0; i < STEAM_CONTROLLER_MAX_COUNT; i++ )
+ {
+ for ( int j = 0; j != ARRAYSIZE( g_DigitalMenuActions ); ++j )
+ {
+ g_DigitalMenuActions[j].bAwaitingDebounce[i] = true;
+ }
+ }
+ }
+}
+
+const int CInputSystem::GetSteamPadDeadZone( ESteamPadAxis axis )
+{
+ int nDeadzone = s_nSteamPadDeadZoneTable[ axis ];
+
+ // Do modifications if required here?
+
+ return nDeadzone;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Processes data for controller
+//-----------------------------------------------------------------------------
+void CInputSystem::ReadSteamController( int iIndex )
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Pulse haptic feedback
+//-----------------------------------------------------------------------------
+/* void CInputSystem::PulseHapticOnSteamController( uint32 nControllerIndex, ESteamControllerPad ePad, unsigned short durationMicroSec )
+{
+ auto steamcontroller = SteamControllerInterface();
+ if ( steamcontroller )
+ {
+ steamcontroller->TriggerHapticPulse( nControllerIndex, ePad, durationMicroSec );
+ }
+}*/
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns the controller State for a particular joystick slot
+//-----------------------------------------------------------------------------
+bool CInputSystem::GetControllerStateForSlot( int nSlot )
+{
+ return false;
+}
+
+int CInputSystem::GetSteamControllerIndexForSlot( int nSlot )
+{
+ for ( int i = 0; i < Q_ARRAYSIZE( m_Device ); i++ )
+ {
+ if ( m_Device[i].active && (int)m_Device[i].m_nJoystickIndex == nSlot )
+ {
+ return m_Device[i].m_nHardwareIndex;
+ }
+ }
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Post events, ignoring key repeats
+//-----------------------------------------------------------------------------
+void CInputSystem::PostKeyEvent( int iIndex, sKey_t sKey, int nSample )
+{
+ // Rework of xbox code here :
+
+ AnalogCode_t code = ANALOG_CODE_LAST;
+ float value = 0.f;
+ //int nMsgSlot = iIndex;
+ int nMsgSlot = m_Device[iIndex].m_nJoystickIndex;
+ int nSampleThreshold = 1;
+
+ // Look for changes on the analog axes
+ switch( sKey )
+ {
+ case SK_BUTTON_LPAD_LEFT:
+ case SK_BUTTON_LPAD_RIGHT:
+ {
+ code = (AnalogCode_t)JOYSTICK_AXIS( nMsgSlot, JOY_AXIS_X );
+ value = ( sKey == SK_BUTTON_LPAD_LEFT ) ? -nSample : nSample;
+ // Kind of a hack to horizontal values for menu selection items in Portal 2
+ // The additional 5k helps accidental horizontals in menus.
+ nSampleThreshold = ( int )( STEAMPAD_DIGITAL_PAD_THRESHOLD ) + 5000;
+ }
+ break;
+
+ case SK_BUTTON_LPAD_UP:
+ case SK_BUTTON_LPAD_DOWN:
+ {
+ code = (AnalogCode_t)JOYSTICK_AXIS( nMsgSlot, JOY_AXIS_Y );
+ value = ( sKey == SK_BUTTON_LPAD_UP ) ? -nSample : nSample;
+ nSampleThreshold = ( int )( STEAMPAD_DIGITAL_PAD_THRESHOLD );
+ }
+ break;
+
+ case SK_BUTTON_RPAD_LEFT:
+ case SK_BUTTON_RPAD_RIGHT:
+ {
+ code = (AnalogCode_t)JOYSTICK_AXIS( nMsgSlot, JOY_AXIS_U );
+ value = ( sKey == SK_BUTTON_RPAD_LEFT ) ? -nSample : nSample;
+ // Kind of a hack to horizontal values for menu selection items in Portal 2
+ // The additional 5k helps accidental horizontals in menus.
+ nSampleThreshold = ( int )( STEAMPAD_DIGITAL_PAD_THRESHOLD ) + 5000;;
+ }
+ break;
+
+ case SK_BUTTON_RPAD_UP:
+ case SK_BUTTON_RPAD_DOWN:
+ {
+ code = (AnalogCode_t)JOYSTICK_AXIS( nMsgSlot, JOY_AXIS_R );
+ value = ( sKey == SK_BUTTON_RPAD_UP ) ? -nSample : nSample;
+ nSampleThreshold = ( int )( STEAMPAD_DIGITAL_PAD_THRESHOLD );
+ }
+ break;
+ }
+
+ // Store the analog event
+ if ( ANALOG_CODE_LAST != code )
+ {
+ InputState_t &state = m_InputState[ m_bIsPolling ];
+ state.m_pAnalogDelta[ code ] = ( int )( value - state.m_pAnalogValue[ code ] );
+ state.m_pAnalogValue[ code ] = ( int )value;
+ if ( state.m_pAnalogDelta[ code ] != 0 )
+ {
+ PostEvent( IE_AnalogValueChanged, m_nLastSampleTick, code, ( int )value, state.m_pAnalogDelta[ code ] );
+ }
+ }
+
+ // store the key
+ m_Device[iIndex].m_appSKeys[sKey].sample = nSample;
+ if ( nSample > nSampleThreshold )
+ {
+ m_Device[iIndex].m_appSKeys[sKey].repeats++;
+ }
+ else
+ {
+ m_Device[iIndex].m_appSKeys[sKey].repeats = 0;
+ nSample = 0;
+ }
+
+ if ( m_Device[iIndex].m_appSKeys[sKey].repeats > 1 )
+ {
+ // application cannot handle streaming keys
+ // first keypress is the only edge trigger
+ return;
+ }
+
+ // package the key
+ ButtonCode_t buttonCode = SKeyToButtonCode( nMsgSlot, sKey );
+ if ( nSample )
+ {
+ PostButtonPressedEvent( IE_ButtonPressed, m_nLastSampleTick, buttonCode, buttonCode );
+ }
+ else
+ {
+ PostButtonReleasedEvent( IE_ButtonReleased, m_nLastSampleTick, buttonCode, buttonCode );
+ }
+}
+
+// Gets the action origin (i.e. which physical input) maps to the given virtual button for the given action set
+EControllerActionOrigin CInputSystem::GetSteamControllerActionOrigin( const char* action, GameActionSet_t action_set )
+{
+ auto pSC = SteamControllerInterface();
+ if ( pSC )
+ {
+ ControllerHandle_t hConnected[STEAM_CONTROLLER_MAX_COUNT];
+ auto nConnected = pSC->GetConnectedControllers( hConnected );
+ if ( nConnected == 0 )
+ {
+ return k_EControllerActionOrigin_None;
+ }
+
+ SGameActionSet* pActionSet = nullptr;
+ for ( int i = 0; i < ARRAYSIZE( g_GameActionSets ); i++ )
+ {
+ if ( g_GameActionSets[i].eGameActionSet == action_set )
+ {
+ pActionSet = &g_GameActionSets[i];
+ break;
+ }
+ }
+
+ if ( pActionSet )
+ {
+ auto actionHandle = pSC->GetDigitalActionHandle( action );
+ EControllerActionOrigin origins[STEAM_CONTROLLER_MAX_ORIGINS];
+ int nOrigins = pSC->GetDigitalActionOrigins( hConnected[0], pActionSet->handle, actionHandle, origins );
+ if ( nOrigins > 0 )
+ {
+ return origins[0];
+ }
+ }
+ }
+
+ return k_EControllerActionOrigin_None;
+}
+
+// Gets the action origin (i.e. which physical input) maps to the given virtual button for the given action set
+EControllerActionOrigin CInputSystem::GetSteamControllerActionOrigin( const char* action, ControllerActionSetHandle_t action_set_handle )
+{
+ auto pSC = SteamControllerInterface();
+ if ( pSC && action_set_handle )
+ {
+ ControllerHandle_t hConnected[STEAM_CONTROLLER_MAX_COUNT];
+ auto nConnected = pSC->GetConnectedControllers( hConnected );
+ if ( nConnected == 0 )
+ {
+ return k_EControllerActionOrigin_None;
+ }
+
+ auto actionHandle = pSC->GetDigitalActionHandle( action );
+ EControllerActionOrigin origins[STEAM_CONTROLLER_MAX_ORIGINS];
+ int nOrigins = pSC->GetDigitalActionOrigins( hConnected[0], action_set_handle, actionHandle, origins );
+ if ( nOrigins > 0 )
+ {
+ return origins[0];
+ }
+ }
+
+ return k_EControllerActionOrigin_None;
+}
+
+// Maps a Steam Controller action origin to a string (consisting of a single character) in our SC icon font
+const wchar_t* CInputSystem::GetSteamControllerFontCharacterForActionOrigin( EControllerActionOrigin origin )
+{
+ if ( origin >= 0 && origin < ARRAYSIZE( g_MapSteamControllerOriginToIconFont ) )
+ {
+ return g_MapSteamControllerOriginToIconFont[origin];
+ }
+ else
+ {
+ return L"";
+ }
+}
+
+// Maps a Steam Controller action origin to a short text string (e.g. "X", "LB", "LDOWN") describing the control.
+// Prefer to actually use the icon font wherever possible.
+const wchar_t* CInputSystem::GetSteamControllerDescriptionForActionOrigin( EControllerActionOrigin origin )
+{
+ if ( origin >= 0 && origin < ARRAYSIZE( g_MapSteamControllerOriginToDescription ) )
+ {
+ return g_MapSteamControllerOriginToDescription[origin];
+ }
+ else
+ {
+ return L"";
+ }
+}