Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

275 lines
8.0 KiB

  1. //=========== Copyright Valve Corporation, All rights reserved. ===============//
  2. //
  3. // Purpose: Native Steam Controller Interface
  4. //=============================================================================//
  5. #include "inputsystem.h"
  6. #include "key_translation.h"
  7. #include "filesystem.h"
  8. #include "steam/isteamcontroller.h"
  9. #include "math.h"
  10. #include "steam/steam_api.h"
  11. // memdbgon must be the last include file in a .cpp file!!!
  12. #include <tier0/memdbgon.h>
  13. static CSteamAPIContext s_SteamAPIContext;
  14. CSteamAPIContext *steamapicontext = &s_SteamAPIContext;
  15. 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." );
  16. bool CInputSystem::InitializeSteamControllers()
  17. {
  18. static bool s_bSteamControllerInitAttempted = false; // we only initialize SteamAPI once, prevent multiple calls
  19. static bool s_bSteamControllerInitSucceeded = false; // cached result from first SteamController()->Init() call
  20. if ( !s_bSteamControllerInitAttempted )
  21. {
  22. s_bSteamControllerInitAttempted = true;
  23. SteamAPI_InitSafe();
  24. s_SteamAPIContext.Init();
  25. if( s_SteamAPIContext.SteamController() )
  26. {
  27. m_flLastSteamControllerInput = -FLT_MAX;
  28. s_bSteamControllerInitSucceeded = steamapicontext->SteamController()->Init();
  29. if ( s_bSteamControllerInitSucceeded )
  30. {
  31. DevMsg( "Successfully Initialized Steam Controller Configuration." );
  32. }
  33. else
  34. {
  35. DevMsg( "Failed to Initialize Steam Controller Configuration." );
  36. }
  37. m_nJoystickBaseline = m_nJoystickCount;
  38. s_SteamAPIContext.SteamController()->ActivateActionSet( STEAM_CONTROLLER_HANDLE_ALL_CONTROLLERS, s_SteamAPIContext.SteamController()->GetActionSetHandle( "MenuControls" ) );
  39. }
  40. }
  41. return s_bSteamControllerInitSucceeded;
  42. }
  43. struct SDigitalMenuAction
  44. {
  45. const char *strName;
  46. ButtonCode_t buttonCode;
  47. ControllerDigitalActionHandle_t handle;
  48. bool bState;
  49. bool bActive;
  50. };
  51. static SDigitalMenuAction g_DigitalMenuActions[] = {
  52. { "menu_left", KEY_XSTICK1_LEFT, 0, false, false },
  53. { "menu_right", KEY_XSTICK1_RIGHT, 0, false, false },
  54. { "menu_up", KEY_XSTICK1_UP, 0, false, false },
  55. { "menu_down", KEY_XSTICK1_DOWN, 0, false, false },
  56. { "menu_cancel", KEY_XBUTTON_B, 0, false, false },
  57. { "menu_select", KEY_XBUTTON_A, 0, false, false },
  58. { "menu_x", KEY_XBUTTON_X, 0, false, false },
  59. { "menu_y", KEY_XBUTTON_Y, 0, false, false },
  60. { "pause_menu", KEY_ESCAPE, 0, false, false }, // Command is actually in the FPS Controls game action set.
  61. { "vote_yes", KEY_F1, 0, false, false }, // Command is actually in the FPS Controls game action set.
  62. { "vote_no", KEY_F2, 0, false, false }, // Command is actually in the FPS Controls game action set.
  63. };
  64. static void InitDigitalMenuActions()
  65. {
  66. for ( int i = 0; i != ARRAYSIZE( g_DigitalMenuActions ); ++i )
  67. {
  68. g_DigitalMenuActions[i].handle = steamapicontext->SteamController()->GetDigitalActionHandle( g_DigitalMenuActions[i].strName );
  69. }
  70. }
  71. static const char *g_pSteamControllerMode = "MenuControls";
  72. bool CInputSystem::PollSteamControllers( void )
  73. {
  74. unsigned int unNumConnected = 0;
  75. if ( InitializeSteamControllers() )
  76. {
  77. ISteamController& ctrl = *s_SteamAPIContext.SteamController();
  78. ctrl.RunFrame();
  79. ControllerHandle_t handles[MAX_STEAM_CONTROLLERS];
  80. int nControllers = ctrl.GetConnectedControllers( handles );
  81. SetInputDeviceConnected( INPUT_DEVICE_STEAM_CONTROLLER, nControllers > 0 );
  82. if ( nControllers > 0 )
  83. {
  84. static bool s_bInitialized = false;
  85. if ( s_bInitialized == false )
  86. {
  87. ctrl.ActivateActionSet( STEAM_CONTROLLER_HANDLE_ALL_CONTROLLERS, ctrl.GetActionSetHandle( g_pSteamControllerMode ) );
  88. InitDigitalMenuActions();
  89. s_bInitialized = true;
  90. }
  91. for ( int i = 0; i != ARRAYSIZE( g_DigitalMenuActions ); ++i )
  92. {
  93. SDigitalMenuAction& action = g_DigitalMenuActions[ i ];
  94. bool bNewState = false;
  95. bool bNewActive = false;
  96. for ( uint64 j = 0; j < nControllers; ++j )
  97. {
  98. ControllerDigitalActionData_t data = steamapicontext->SteamController()->GetDigitalActionData( handles[ j ], action.handle );
  99. if ( data.bActive )
  100. {
  101. bNewActive = true;
  102. }
  103. if ( data.bState && data.bActive )
  104. {
  105. bNewState = true;
  106. }
  107. }
  108. bNewActive = bNewActive && ( action.bActive || !bNewState );
  109. if ( action.bActive && bNewState != action.bState )
  110. {
  111. if ( bNewState )
  112. {
  113. SetCurrentInputDevice( INPUT_DEVICE_STEAM_CONTROLLER );
  114. PostButtonPressedEvent( IE_ButtonPressed, m_nLastSampleTick, action.buttonCode, action.buttonCode );
  115. }
  116. else
  117. {
  118. PostButtonReleasedEvent( IE_ButtonReleased, m_nLastSampleTick, action.buttonCode, action.buttonCode );
  119. }
  120. }
  121. action.bState = bNewState;
  122. action.bActive = bNewActive;
  123. }
  124. }
  125. }
  126. m_unNumSteamControllerConnected = unNumConnected;
  127. return unNumConnected > 0;
  128. }
  129. bool CInputSystem::IsSteamControllerActive() const
  130. {
  131. if ( steamapicontext && steamapicontext->SteamController() )
  132. {
  133. uint64 nControllerHandles[STEAM_CONTROLLER_MAX_COUNT];
  134. return steamapicontext->SteamController()->GetConnectedControllers( nControllerHandles ) > 0;
  135. }
  136. return false;
  137. }
  138. static const int g_nControllerModeMaxStackSize = 16;
  139. static const void *g_pControllerModeObjectStack[g_nControllerModeMaxStackSize];
  140. static const char *g_pControllerModeStack[g_nControllerModeMaxStackSize];
  141. static int g_nControllerModeStackSize = 0;
  142. static const char *g_pBaseControllerMode = "MenuControls";
  143. static const char *GetCurrentSteamControllerMode()
  144. {
  145. if ( g_nControllerModeStackSize == 0 )
  146. {
  147. return g_pBaseControllerMode;
  148. }
  149. return g_pControllerModeStack[ g_nControllerModeStackSize-1 ];
  150. }
  151. void CInputSystem::SetSteamControllerMode( const char *pSteamControllerMode, const void *obj )
  152. {
  153. if ( !s_SteamAPIContext.SteamController() )
  154. {
  155. return;
  156. }
  157. if ( obj == NULL )
  158. {
  159. g_pBaseControllerMode = pSteamControllerMode;
  160. }
  161. else
  162. {
  163. int nIndex = 0;
  164. while ( nIndex < g_nControllerModeStackSize && g_pControllerModeObjectStack[ nIndex ] != obj )
  165. {
  166. ++nIndex;
  167. }
  168. Assert( nIndex < g_nControllerModeMaxStackSize );
  169. if ( nIndex == g_nControllerModeMaxStackSize )
  170. {
  171. return;
  172. }
  173. if ( pSteamControllerMode != NULL )
  174. {
  175. g_pControllerModeObjectStack[ nIndex ] = obj;
  176. g_pControllerModeStack[ nIndex ] = pSteamControllerMode;
  177. if ( nIndex == g_nControllerModeStackSize )
  178. {
  179. ++g_nControllerModeStackSize;
  180. }
  181. }
  182. else if ( nIndex < g_nControllerModeStackSize )
  183. {
  184. for ( int i = nIndex+1; i < g_nControllerModeStackSize; ++i )
  185. {
  186. g_pControllerModeObjectStack[ i - 1 ] = g_pControllerModeObjectStack[ i ];
  187. g_pControllerModeStack[ i - 1 ] = g_pControllerModeStack[ i ];
  188. }
  189. --g_nControllerModeStackSize;
  190. }
  191. }
  192. const char *pNewMode = GetCurrentSteamControllerMode();
  193. if ( V_strcmp( pNewMode, g_pSteamControllerMode ) == 0 )
  194. {
  195. return;
  196. }
  197. g_pSteamControllerMode = pNewMode;
  198. s_SteamAPIContext.SteamController()->ActivateActionSet( STEAM_CONTROLLER_HANDLE_ALL_CONTROLLERS, s_SteamAPIContext.SteamController()->GetActionSetHandle( pNewMode ) );
  199. }
  200. CON_COMMAND( steam_controller_status, "Spew report of steam controller status" )
  201. {
  202. if ( !s_SteamAPIContext.SteamController() )
  203. {
  204. Msg( "Steam controller API is unavailable" );
  205. return;
  206. }
  207. ControllerDigitalActionHandle_t handleAction = s_SteamAPIContext.SteamController()->GetActionSetHandle( GetCurrentSteamControllerMode() );
  208. Msg( "Steam controller mode: %s (%d)\n", GetCurrentSteamControllerMode(), (int)handleAction );
  209. ControllerHandle_t handles[MAX_STEAM_CONTROLLERS];
  210. int nControllers = s_SteamAPIContext.SteamController()->GetConnectedControllers( handles );
  211. Msg( "Controllers connected: %d\n", nControllers );
  212. for ( int i = 0; i < nControllers; ++i )
  213. {
  214. Msg( " Controller %d, action set = %d\n", i, (int)s_SteamAPIContext.SteamController()->GetCurrentActionSet( handles[ i ] ) );
  215. for ( int j = 0; j < STEAM_CONTROLLER_MAX_DIGITAL_ACTIONS; ++j )
  216. {
  217. ControllerDigitalActionData_t data = s_SteamAPIContext.SteamController()->GetDigitalActionData( handles[ i ], (int)j );
  218. if ( data.bState && data.bActive )
  219. {
  220. Msg( " active action: %d\n", j );
  221. }
  222. }
  223. }
  224. }