csgo-2018-source/inputsystem/steamcontroller.cpp
2021-07-24 21:11:47 -07:00

276 lines
8.0 KiB
C++

//=========== 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"
#include "steam/steam_api.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
static CSteamAPIContext s_SteamAPIContext;
CSteamAPIContext *steamapicontext = &s_SteamAPIContext;
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." );
bool CInputSystem::InitializeSteamControllers()
{
static bool s_bSteamControllerInitAttempted = false; // we only initialize SteamAPI once, prevent multiple calls
static bool s_bSteamControllerInitSucceeded = false; // cached result from first SteamController()->Init() call
if ( !s_bSteamControllerInitAttempted )
{
s_bSteamControllerInitAttempted = true;
SteamAPI_InitSafe();
s_SteamAPIContext.Init();
if( s_SteamAPIContext.SteamController() )
{
m_flLastSteamControllerInput = -FLT_MAX;
s_bSteamControllerInitSucceeded = steamapicontext->SteamController()->Init();
if ( s_bSteamControllerInitSucceeded )
{
DevMsg( "Successfully Initialized Steam Controller Configuration." );
}
else
{
DevMsg( "Failed to Initialize Steam Controller Configuration." );
}
m_nJoystickBaseline = m_nJoystickCount;
s_SteamAPIContext.SteamController()->ActivateActionSet( STEAM_CONTROLLER_HANDLE_ALL_CONTROLLERS, s_SteamAPIContext.SteamController()->GetActionSetHandle( "MenuControls" ) );
}
}
return s_bSteamControllerInitSucceeded;
}
struct SDigitalMenuAction
{
const char *strName;
ButtonCode_t buttonCode;
ControllerDigitalActionHandle_t handle;
bool bState;
bool bActive;
};
static SDigitalMenuAction g_DigitalMenuActions[] = {
{ "menu_left", KEY_XSTICK1_LEFT, 0, false, false },
{ "menu_right", KEY_XSTICK1_RIGHT, 0, false, false },
{ "menu_up", KEY_XSTICK1_UP, 0, false, false },
{ "menu_down", KEY_XSTICK1_DOWN, 0, false, false },
{ "menu_cancel", KEY_XBUTTON_B, 0, false, false },
{ "menu_select", KEY_XBUTTON_A, 0, false, false },
{ "menu_x", KEY_XBUTTON_X, 0, false, false },
{ "menu_y", KEY_XBUTTON_Y, 0, false, false },
{ "pause_menu", KEY_ESCAPE, 0, false, false }, // Command is actually in the FPS Controls game action set.
{ "vote_yes", KEY_F1, 0, false, false }, // Command is actually in the FPS Controls game action set.
{ "vote_no", KEY_F2, 0, false, false }, // Command is actually in the FPS Controls game action set.
};
static void InitDigitalMenuActions()
{
for ( int i = 0; i != ARRAYSIZE( g_DigitalMenuActions ); ++i )
{
g_DigitalMenuActions[i].handle = steamapicontext->SteamController()->GetDigitalActionHandle( g_DigitalMenuActions[i].strName );
}
}
static const char *g_pSteamControllerMode = "MenuControls";
bool CInputSystem::PollSteamControllers( void )
{
unsigned int unNumConnected = 0;
if ( InitializeSteamControllers() )
{
ISteamController& ctrl = *s_SteamAPIContext.SteamController();
ctrl.RunFrame();
ControllerHandle_t handles[MAX_STEAM_CONTROLLERS];
int nControllers = ctrl.GetConnectedControllers( handles );
SetInputDeviceConnected( INPUT_DEVICE_STEAM_CONTROLLER, nControllers > 0 );
if ( nControllers > 0 )
{
static bool s_bInitialized = false;
if ( s_bInitialized == false )
{
ctrl.ActivateActionSet( STEAM_CONTROLLER_HANDLE_ALL_CONTROLLERS, ctrl.GetActionSetHandle( g_pSteamControllerMode ) );
InitDigitalMenuActions();
s_bInitialized = true;
}
for ( int i = 0; i != ARRAYSIZE( g_DigitalMenuActions ); ++i )
{
SDigitalMenuAction& action = g_DigitalMenuActions[ i ];
bool bNewState = false;
bool bNewActive = false;
for ( uint64 j = 0; j < nControllers; ++j )
{
ControllerDigitalActionData_t data = steamapicontext->SteamController()->GetDigitalActionData( handles[ j ], action.handle );
if ( data.bActive )
{
bNewActive = true;
}
if ( data.bState && data.bActive )
{
bNewState = true;
}
}
bNewActive = bNewActive && ( action.bActive || !bNewState );
if ( action.bActive && bNewState != action.bState )
{
if ( bNewState )
{
SetCurrentInputDevice( INPUT_DEVICE_STEAM_CONTROLLER );
PostButtonPressedEvent( IE_ButtonPressed, m_nLastSampleTick, action.buttonCode, action.buttonCode );
}
else
{
PostButtonReleasedEvent( IE_ButtonReleased, m_nLastSampleTick, action.buttonCode, action.buttonCode );
}
}
action.bState = bNewState;
action.bActive = bNewActive;
}
}
}
m_unNumSteamControllerConnected = unNumConnected;
return unNumConnected > 0;
}
bool CInputSystem::IsSteamControllerActive() const
{
if ( steamapicontext && steamapicontext->SteamController() )
{
uint64 nControllerHandles[STEAM_CONTROLLER_MAX_COUNT];
return steamapicontext->SteamController()->GetConnectedControllers( nControllerHandles ) > 0;
}
return false;
}
static const int g_nControllerModeMaxStackSize = 16;
static const void *g_pControllerModeObjectStack[g_nControllerModeMaxStackSize];
static const char *g_pControllerModeStack[g_nControllerModeMaxStackSize];
static int g_nControllerModeStackSize = 0;
static const char *g_pBaseControllerMode = "MenuControls";
static const char *GetCurrentSteamControllerMode()
{
if ( g_nControllerModeStackSize == 0 )
{
return g_pBaseControllerMode;
}
return g_pControllerModeStack[ g_nControllerModeStackSize-1 ];
}
void CInputSystem::SetSteamControllerMode( const char *pSteamControllerMode, const void *obj )
{
if ( !s_SteamAPIContext.SteamController() )
{
return;
}
if ( obj == NULL )
{
g_pBaseControllerMode = pSteamControllerMode;
}
else
{
int nIndex = 0;
while ( nIndex < g_nControllerModeStackSize && g_pControllerModeObjectStack[ nIndex ] != obj )
{
++nIndex;
}
Assert( nIndex < g_nControllerModeMaxStackSize );
if ( nIndex == g_nControllerModeMaxStackSize )
{
return;
}
if ( pSteamControllerMode != NULL )
{
g_pControllerModeObjectStack[ nIndex ] = obj;
g_pControllerModeStack[ nIndex ] = pSteamControllerMode;
if ( nIndex == g_nControllerModeStackSize )
{
++g_nControllerModeStackSize;
}
}
else if ( nIndex < g_nControllerModeStackSize )
{
for ( int i = nIndex+1; i < g_nControllerModeStackSize; ++i )
{
g_pControllerModeObjectStack[ i - 1 ] = g_pControllerModeObjectStack[ i ];
g_pControllerModeStack[ i - 1 ] = g_pControllerModeStack[ i ];
}
--g_nControllerModeStackSize;
}
}
const char *pNewMode = GetCurrentSteamControllerMode();
if ( V_strcmp( pNewMode, g_pSteamControllerMode ) == 0 )
{
return;
}
g_pSteamControllerMode = pNewMode;
s_SteamAPIContext.SteamController()->ActivateActionSet( STEAM_CONTROLLER_HANDLE_ALL_CONTROLLERS, s_SteamAPIContext.SteamController()->GetActionSetHandle( pNewMode ) );
}
CON_COMMAND( steam_controller_status, "Spew report of steam controller status" )
{
if ( !s_SteamAPIContext.SteamController() )
{
Msg( "Steam controller API is unavailable" );
return;
}
ControllerDigitalActionHandle_t handleAction = s_SteamAPIContext.SteamController()->GetActionSetHandle( GetCurrentSteamControllerMode() );
Msg( "Steam controller mode: %s (%d)\n", GetCurrentSteamControllerMode(), (int)handleAction );
ControllerHandle_t handles[MAX_STEAM_CONTROLLERS];
int nControllers = s_SteamAPIContext.SteamController()->GetConnectedControllers( handles );
Msg( "Controllers connected: %d\n", nControllers );
for ( int i = 0; i < nControllers; ++i )
{
Msg( " Controller %d, action set = %d\n", i, (int)s_SteamAPIContext.SteamController()->GetCurrentActionSet( handles[ i ] ) );
for ( int j = 0; j < STEAM_CONTROLLER_MAX_DIGITAL_ACTIONS; ++j )
{
ControllerDigitalActionData_t data = s_SteamAPIContext.SteamController()->GetDigitalActionData( handles[ i ], (int)j );
if ( data.bState && data.bActive )
{
Msg( " active action: %d\n", j );
}
}
}
}