2019-04-13 16:21:56 +00:00
/* Copyright (C) 2019 Mr Goldberg
This file is part of the Goldberg Emulator
The Goldberg Emulator is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
version 3 of the License , or ( at your option ) any later version .
The Goldberg Emulator is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public
License along with the Goldberg Emulator ; if not , see
< http : //www.gnu.org/licenses/>. */
# include "base.h"
2021-02-08 00:09:48 +00:00
# ifndef CONTROLLER_SUPPORT
inline void GamepadInit ( void ) { }
inline void GamepadShutdown ( void ) { }
inline void GamepadUpdate ( void ) { }
inline GAMEPAD_BOOL GamepadIsConnected ( GAMEPAD_DEVICE device ) { return GAMEPAD_FALSE ; }
inline GAMEPAD_BOOL GamepadButtonDown ( GAMEPAD_DEVICE device , GAMEPAD_BUTTON button ) { return GAMEPAD_FALSE ; }
inline float GamepadTriggerLength ( GAMEPAD_DEVICE device , GAMEPAD_TRIGGER trigger ) { return 0.0 ; }
inline GAMEPAD_STICKDIR GamepadStickDir ( GAMEPAD_DEVICE device , GAMEPAD_STICK stick ) { return STICKDIR_CENTER ; }
inline void GamepadStickNormXY ( GAMEPAD_DEVICE device , GAMEPAD_STICK stick , float * outX , float * outY ) { }
inline float GamepadStickLength ( GAMEPAD_DEVICE device , GAMEPAD_STICK stick ) { return 0.0 ; }
inline void GamepadSetRumble ( GAMEPAD_DEVICE device , float left , float right , unsigned int rumble_length_ms ) { }
# endif
2019-09-10 18:54:54 +00:00
struct Controller_Map {
std : : map < ControllerDigitalActionHandle_t , std : : set < int > > active_digital ;
std : : map < ControllerAnalogActionHandle_t , std : : pair < std : : set < int > , enum EInputSourceMode > > active_analog ;
} ;
struct Controller_Action {
ControllerHandle_t controller_handle ;
struct Controller_Map active_map ;
ControllerDigitalActionHandle_t active_set ;
Controller_Action ( ControllerHandle_t controller_handle ) {
this - > controller_handle = controller_handle ;
}
void activate_action_set ( ControllerDigitalActionHandle_t active_set , std : : map < ControllerActionSetHandle_t , struct Controller_Map > & controller_maps ) {
auto map = controller_maps . find ( active_set ) ;
if ( map = = controller_maps . end ( ) ) return ;
this - > active_set = active_set ;
this - > active_map = map - > second ;
}
std : : set < int > button_id ( ControllerDigitalActionHandle_t handle ) {
auto a = active_map . active_digital . find ( handle ) ;
if ( a = = active_map . active_digital . end ( ) ) return { } ;
return a - > second ;
}
std : : pair < std : : set < int > , enum EInputSourceMode > analog_id ( ControllerAnalogActionHandle_t handle ) {
auto a = active_map . active_analog . find ( handle ) ;
if ( a = = active_map . active_analog . end ( ) ) return std : : pair < std : : set < int > , enum EInputSourceMode > ( { } , k_EInputSourceMode_None ) ;
return a - > second ;
}
} ;
2021-09-14 20:11:17 +00:00
struct Rumble_Thread_Data {
std : : condition_variable rumble_thread_cv ;
2022-08-08 03:06:43 +00:00
bool kill_rumble_thread ;
2021-09-14 20:11:17 +00:00
std : : mutex rumble_mutex ;
struct Rumble_Data {
unsigned short left , right , last_left , last_right ;
unsigned int rumble_length_ms ;
bool new_data ;
} data [ GAMEPAD_COUNT ] ;
} ;
2019-09-10 18:54:54 +00:00
enum EXTRA_GAMEPAD_BUTTONS {
BUTTON_LTRIGGER = BUTTON_COUNT + 1 ,
BUTTON_RTRIGGER = BUTTON_COUNT + 2 ,
BUTTON_STICK_LEFT_UP = BUTTON_COUNT + 3 ,
BUTTON_STICK_LEFT_DOWN = BUTTON_COUNT + 4 ,
BUTTON_STICK_LEFT_LEFT = BUTTON_COUNT + 5 ,
BUTTON_STICK_LEFT_RIGHT = BUTTON_COUNT + 6 ,
BUTTON_STICK_RIGHT_UP = BUTTON_COUNT + 7 ,
BUTTON_STICK_RIGHT_DOWN = BUTTON_COUNT + 8 ,
BUTTON_STICK_RIGHT_LEFT = BUTTON_COUNT + 9 ,
BUTTON_STICK_RIGHT_RIGHT = BUTTON_COUNT + 10 ,
} ;
2019-04-13 16:21:56 +00:00
2019-09-14 21:24:05 +00:00
# define JOY_ID_START 10
2021-09-10 18:19:12 +00:00
# define STICK_DPAD 3
2022-04-02 08:33:34 +00:00
# define DEADZONE_BUTTON_STICK 0.3
2019-09-14 21:24:05 +00:00
2019-04-13 16:21:56 +00:00
class Steam_Controller :
public ISteamController001 ,
public ISteamController003 ,
public ISteamController004 ,
public ISteamController005 ,
public ISteamController006 ,
2021-01-18 03:46:00 +00:00
public ISteamController007 ,
2019-04-13 16:21:56 +00:00
public ISteamController ,
2021-01-18 03:46:00 +00:00
public ISteamInput001 ,
2021-12-06 21:51:17 +00:00
public ISteamInput002 ,
2022-01-25 20:49:26 +00:00
public ISteamInput005 ,
2019-04-13 16:21:56 +00:00
public ISteamInput
{
2019-09-10 18:54:54 +00:00
class Settings * settings ;
class SteamCallResults * callback_results ;
class SteamCallBacks * callbacks ;
class RunEveryRunCB * run_every_runcb ;
std : : map < std : : string , int > button_strings = {
{ " DUP " , BUTTON_DPAD_UP } ,
{ " DDOWN " , BUTTON_DPAD_DOWN } ,
{ " DLEFT " , BUTTON_DPAD_LEFT } ,
{ " DRIGHT " , BUTTON_DPAD_RIGHT } ,
{ " START " , BUTTON_START } ,
{ " BACK " , BUTTON_BACK } ,
{ " LSTICK " , BUTTON_LEFT_THUMB } ,
{ " RSTICK " , BUTTON_RIGHT_THUMB } ,
{ " LBUMPER " , BUTTON_LEFT_SHOULDER } ,
{ " RBUMPER " , BUTTON_RIGHT_SHOULDER } ,
{ " A " , BUTTON_A } ,
{ " B " , BUTTON_B } ,
{ " X " , BUTTON_X } ,
{ " Y " , BUTTON_Y } ,
{ " DLTRIGGER " , BUTTON_LTRIGGER } ,
{ " DRTRIGGER " , BUTTON_RTRIGGER } ,
{ " DLJOYUP " , BUTTON_STICK_LEFT_UP } ,
{ " DLJOYDOWN " , BUTTON_STICK_LEFT_DOWN } ,
{ " DLJOYLEFT " , BUTTON_STICK_LEFT_LEFT } ,
{ " DLJOYRIGHT " , BUTTON_STICK_LEFT_RIGHT } ,
{ " DRJOYUP " , BUTTON_STICK_RIGHT_UP } ,
{ " DRJOYDOWN " , BUTTON_STICK_RIGHT_DOWN } ,
{ " DRJOYLEFT " , BUTTON_STICK_RIGHT_LEFT } ,
{ " DRJOYRIGHT " , BUTTON_STICK_RIGHT_RIGHT } ,
} ;
std : : map < std : : string , int > analog_strings = {
{ " LTRIGGER " , TRIGGER_LEFT } ,
{ " RTRIGGER " , TRIGGER_RIGHT } ,
2019-09-14 21:24:05 +00:00
{ " LJOY " , STICK_LEFT + JOY_ID_START } ,
{ " RJOY " , STICK_RIGHT + JOY_ID_START } ,
2021-09-10 18:19:12 +00:00
{ " DPAD " , STICK_DPAD + JOY_ID_START } ,
2019-09-10 18:54:54 +00:00
} ;
std : : map < std : : string , enum EInputSourceMode > analog_input_modes = {
{ " joystick_move " , k_EInputSourceMode_JoystickMove } ,
{ " joystick_camera " , k_EInputSourceMode_JoystickCamera } ,
{ " trigger " , k_EInputSourceMode_Trigger } ,
} ;
std : : map < std : : string , ControllerActionSetHandle_t > action_handles ;
std : : map < std : : string , ControllerDigitalActionHandle_t > digital_action_handles ;
std : : map < std : : string , ControllerAnalogActionHandle_t > analog_action_handles ;
std : : map < ControllerActionSetHandle_t , struct Controller_Map > controller_maps ;
std : : map < ControllerHandle_t , struct Controller_Action > controllers ;
2019-12-11 17:06:19 +00:00
std : : map < EInputActionOrigin , std : : string > steaminput_glyphs ;
std : : map < EControllerActionOrigin , std : : string > steamcontroller_glyphs ;
2021-09-14 20:11:17 +00:00
std : : thread background_rumble_thread ;
Rumble_Thread_Data * rumble_thread_data ;
2019-09-10 18:54:54 +00:00
bool disabled ;
2020-01-19 06:34:52 +00:00
bool initialized ;
2021-12-06 21:51:17 +00:00
bool explicitly_call_run_frame ;
2019-09-10 18:54:54 +00:00
void set_handles ( std : : map < std : : string , std : : map < std : : string , std : : pair < std : : set < std : : string > , std : : string > > > action_sets ) {
uint64 handle_num = 1 ;
for ( auto & set : action_sets ) {
ControllerActionSetHandle_t action_handle_num = handle_num ;
+ + handle_num ;
action_handles [ set . first ] = action_handle_num ;
for ( auto & config_key : set . second ) {
uint64 current_handle_num = handle_num ;
+ + handle_num ;
for ( auto & button_string : config_key . second . first ) {
auto digital = button_strings . find ( button_string ) ;
if ( digital ! = button_strings . end ( ) ) {
ControllerDigitalActionHandle_t digital_handle_num = current_handle_num ;
2019-09-11 13:08:05 +00:00
if ( digital_action_handles . find ( config_key . first ) = = digital_action_handles . end ( ) ) {
digital_action_handles [ config_key . first ] = digital_handle_num ;
} else {
digital_handle_num = digital_action_handles [ config_key . first ] ;
}
2019-09-10 18:54:54 +00:00
controller_maps [ action_handle_num ] . active_digital [ digital_handle_num ] . insert ( digital - > second ) ;
} else {
auto analog = analog_strings . find ( button_string ) ;
if ( analog ! = analog_strings . end ( ) ) {
ControllerAnalogActionHandle_t analog_handle_num = current_handle_num ;
enum EInputSourceMode source_mode ;
if ( analog - > second = = TRIGGER_LEFT | | analog - > second = = TRIGGER_RIGHT ) {
source_mode = k_EInputSourceMode_Trigger ;
} else {
source_mode = k_EInputSourceMode_JoystickMove ;
}
auto input_mode = analog_input_modes . find ( config_key . second . second ) ;
if ( input_mode ! = analog_input_modes . end ( ) ) {
source_mode = input_mode - > second ;
}
2019-09-11 13:08:05 +00:00
if ( analog_action_handles . find ( config_key . first ) = = analog_action_handles . end ( ) ) {
analog_action_handles [ config_key . first ] = analog_handle_num ;
} else {
analog_handle_num = analog_action_handles [ config_key . first ] ;
}
2019-09-10 18:54:54 +00:00
controller_maps [ action_handle_num ] . active_analog [ analog_handle_num ] . first . insert ( analog - > second ) ;
controller_maps [ action_handle_num ] . active_analog [ analog_handle_num ] . second = source_mode ;
} else {
PRINT_DEBUG ( " Did not recognize controller button %s \n " , button_string . c_str ( ) ) ;
continue ;
}
}
}
}
}
}
2019-04-13 16:21:56 +00:00
public :
2019-09-10 18:54:54 +00:00
2021-09-14 20:11:17 +00:00
static void background_rumble ( Rumble_Thread_Data * data )
{
while ( true ) {
2022-08-08 03:06:43 +00:00
unsigned short left , right ;
unsigned int rumble_length_ms ;
int gamepad = - 1 ;
while ( gamepad = = - 1 ) {
std : : unique_lock < std : : mutex > lck ( data - > rumble_mutex ) ;
if ( data - > kill_rumble_thread ) {
return ;
2021-09-14 20:11:17 +00:00
}
2022-08-08 03:06:43 +00:00
data - > rumble_thread_cv . wait_for ( lck , std : : chrono : : milliseconds ( 1000 ) ) ;
2021-09-14 20:11:17 +00:00
if ( data - > kill_rumble_thread ) {
return ;
}
for ( int i = 0 ; i < GAMEPAD_COUNT ; + + i ) {
if ( data - > data [ i ] . new_data ) {
left = data - > data [ i ] . left ;
right = data - > data [ i ] . right ;
rumble_length_ms = data - > data [ i ] . rumble_length_ms ;
data - > data [ i ] . new_data = false ;
if ( data - > data [ i ] . last_left ! = left | | data - > data [ i ] . last_right ! = right ) {
gamepad = i ;
data - > data [ i ] . last_left = left ;
data - > data [ i ] . last_right = right ;
break ;
}
}
}
}
2022-08-08 03:06:43 +00:00
GamepadSetRumble ( ( GAMEPAD_DEVICE ) gamepad , ( ( double ) left ) / 65535.0 , ( ( double ) right ) / 65535.0 , rumble_length_ms ) ;
2021-09-14 20:11:17 +00:00
}
}
2019-09-10 18:54:54 +00:00
static void steam_run_every_runcb ( void * object )
{
PRINT_DEBUG ( " steam_controller_run_every_runcb \n " ) ;
Steam_Controller * steam_controller = ( Steam_Controller * ) object ;
steam_controller - > RunCallbacks ( ) ;
}
Steam_Controller ( class Settings * settings , class SteamCallResults * callback_results , class SteamCallBacks * callbacks , class RunEveryRunCB * run_every_runcb )
{
this - > settings = settings ;
this - > run_every_runcb = run_every_runcb ;
this - > run_every_runcb - > add ( & Steam_Controller : : steam_run_every_runcb , this ) ;
this - > callback_results = callback_results ;
this - > callbacks = callbacks ;
set_handles ( settings - > controller_settings . action_sets ) ;
disabled = ! action_handles . size ( ) ;
2020-01-19 06:34:52 +00:00
initialized = false ;
2019-09-10 18:54:54 +00:00
}
~ Steam_Controller ( )
{
//TODO rm network callbacks
2021-09-14 20:11:17 +00:00
//TODO rumble thread
2019-09-10 18:54:54 +00:00
this - > run_every_runcb - > remove ( & Steam_Controller : : steam_run_every_runcb , this ) ;
}
2019-04-13 16:21:56 +00:00
// Init and Shutdown must be called when starting/ending use of this interface
2021-12-06 21:51:17 +00:00
bool Init ( bool bExplicitlyCallRunFrame )
2019-04-13 16:21:56 +00:00
{
2021-12-06 21:51:17 +00:00
PRINT_DEBUG ( " Steam_Controller::Init() %u \n " , bExplicitlyCallRunFrame ) ;
2019-09-10 18:54:54 +00:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2021-09-14 20:11:17 +00:00
if ( disabled | | initialized ) {
2019-09-10 18:54:54 +00:00
return true ;
}
GamepadInit ( ) ;
GamepadUpdate ( ) ;
for ( int i = 1 ; i < 5 ; + + i ) {
2019-09-14 22:32:26 +00:00
struct Controller_Action cont_action ( i ) ;
2022-04-02 08:33:34 +00:00
//Activate the first action set.
//TODO: check exactly what decides which gets activated by default
if ( action_handles . size ( ) > = 1 ) {
2019-09-14 22:32:26 +00:00
cont_action . activate_action_set ( action_handles . begin ( ) - > second , controller_maps ) ;
}
controllers . insert ( std : : pair < ControllerHandle_t , struct Controller_Action > ( i , cont_action ) ) ;
2019-09-10 18:54:54 +00:00
}
2021-09-14 20:11:17 +00:00
rumble_thread_data = new Rumble_Thread_Data ( ) ;
background_rumble_thread = std : : thread ( background_rumble , rumble_thread_data ) ;
2020-01-19 06:34:52 +00:00
initialized = true ;
2021-12-06 21:51:17 +00:00
explicitly_call_run_frame = bExplicitlyCallRunFrame ;
2019-04-13 16:21:56 +00:00
return true ;
}
bool Init ( const char * pchAbsolutePathToControllerConfigVDF )
{
PRINT_DEBUG ( " Steam_Controller::Init() old \n " ) ;
return Init ( ) ;
}
2021-12-06 21:51:17 +00:00
bool Init ( )
{
return Init ( true ) ;
}
2019-04-13 16:21:56 +00:00
bool Shutdown ( )
{
PRINT_DEBUG ( " Steam_Controller::Shutdown() \n " ) ;
2019-09-10 18:54:54 +00:00
std : : lock_guard < std : : recursive_mutex > lock ( global_mutex ) ;
2021-09-14 20:11:17 +00:00
if ( disabled | | ! initialized ) {
2019-09-10 18:54:54 +00:00
return true ;
}
2021-09-14 20:11:17 +00:00
controllers = std : : map < ControllerHandle_t , struct Controller_Action > ( ) ;
2022-08-08 03:06:43 +00:00
rumble_thread_data - > rumble_mutex . lock ( ) ;
2021-09-14 20:11:17 +00:00
rumble_thread_data - > kill_rumble_thread = true ;
2022-08-08 03:06:43 +00:00
rumble_thread_data - > rumble_mutex . unlock ( ) ;
2021-09-14 20:11:17 +00:00
rumble_thread_data - > rumble_thread_cv . notify_one ( ) ;
background_rumble_thread . join ( ) ;
delete rumble_thread_data ;
2019-09-10 18:54:54 +00:00
GamepadShutdown ( ) ;
2021-09-14 20:11:17 +00:00
initialized = false ;
2019-04-13 16:21:56 +00:00
return true ;
}
void SetOverrideMode ( const char * pchMode )
{
PRINT_DEBUG ( " Steam_Controller::SetOverrideMode \n " ) ;
}
2021-12-06 21:51:17 +00:00
// Set the absolute path to the Input Action Manifest file containing the in-game actions
// and file paths to the official configurations. Used in games that bundle Steam Input
// configurations inside of the game depot instead of using the Steam Workshop
bool SetInputActionManifestFilePath ( const char * pchInputActionManifestAbsolutePath )
{
PRINT_DEBUG ( " TODO %s \n " , __FUNCTION__ ) ;
//TODO SteamInput005
return false ;
}
bool BWaitForData ( bool bWaitForever , uint32 unTimeout )
{
PRINT_DEBUG ( " TODO %s \n " , __FUNCTION__ ) ;
//TODO SteamInput005
return false ;
}
// Returns true if new data has been received since the last time action data was accessed
// via GetDigitalActionData or GetAnalogActionData. The game will still need to call
// SteamInput()->RunFrame() or SteamAPI_RunCallbacks() before this to update the data stream
bool BNewDataAvailable ( )
{
PRINT_DEBUG ( " TODO %s \n " , __FUNCTION__ ) ;
//TODO SteamInput005
return false ;
}
// Enable SteamInputDeviceConnected_t and SteamInputDeviceDisconnected_t callbacks.
// Each controller that is already connected will generate a device connected
// callback when you enable them
void EnableDeviceCallbacks ( )
{
PRINT_DEBUG ( " TODO %s \n " , __FUNCTION__ ) ;
//TODO SteamInput005
return ;
}
// Enable SteamInputActionEvent_t callbacks. Directly calls your callback function
// for lower latency than standard Steam callbacks. Supports one callback at a time.
// Note: this is called within either SteamInput()->RunFrame or by SteamAPI_RunCallbacks
void EnableActionEventCallbacks ( SteamInputActionEventCallbackPointer pCallback )
{
PRINT_DEBUG ( " TODO %s \n " , __FUNCTION__ ) ;
//TODO SteamInput005
return ;
}
2019-04-13 16:21:56 +00:00
// Synchronize API state with the latest Steam Controller inputs available. This
// is performed automatically by SteamAPI_RunCallbacks, but for the absolute lowest
// possible latency, you call this directly before reading controller state.
2021-12-06 21:51:17 +00:00
void RunFrame ( bool bReservedValue )
2019-04-13 16:21:56 +00:00
{
PRINT_DEBUG ( " Steam_Controller::RunFrame() \n " ) ;
2020-01-19 06:34:52 +00:00
if ( disabled | | ! initialized ) {
2019-09-10 18:54:54 +00:00
return ;
}
GamepadUpdate ( ) ;
2019-04-13 16:21:56 +00:00
}
2021-12-06 21:51:17 +00:00
void RunFrame ( )
{
RunFrame ( true ) ;
}
2019-04-13 16:21:56 +00:00
bool GetControllerState ( uint32 unControllerIndex , SteamControllerState001_t * pState )
{
PRINT_DEBUG ( " Steam_Controller::GetControllerState() \n " ) ;
return false ;
}
// Enumerate currently connected controllers
// handlesOut should point to a STEAM_CONTROLLER_MAX_COUNT sized array of ControllerHandle_t handles
// Returns the number of handles written to handlesOut
int GetConnectedControllers ( ControllerHandle_t * handlesOut )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetConnectedControllers \n " ) ;
if ( ! handlesOut ) return 0 ;
if ( disabled ) {
return 0 ;
}
int count = 0 ;
if ( GamepadIsConnected ( GAMEPAD_0 ) ) { * handlesOut = GAMEPAD_0 + 1 ; + + handlesOut ; + + count ; } ;
if ( GamepadIsConnected ( GAMEPAD_1 ) ) { * handlesOut = GAMEPAD_1 + 1 ; + + handlesOut ; + + count ; } ;
if ( GamepadIsConnected ( GAMEPAD_2 ) ) { * handlesOut = GAMEPAD_2 + 1 ; + + handlesOut ; + + count ; } ;
if ( GamepadIsConnected ( GAMEPAD_3 ) ) { * handlesOut = GAMEPAD_3 + 1 ; + + handlesOut ; + + count ; } ;
PRINT_DEBUG ( " returned %i connected controllers \n " , count ) ;
return count ;
2019-04-13 16:21:56 +00:00
}
// Invokes the Steam overlay and brings up the binding screen
// Returns false is overlay is disabled / unavailable, or the user is not in Big Picture mode
bool ShowBindingPanel ( ControllerHandle_t controllerHandle )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::ShowBindingPanel \n " ) ;
2019-04-13 16:21:56 +00:00
return false ;
}
// ACTION SETS
// Lookup the handle for an Action Set. Best to do this once on startup, and store the handles for all future API calls.
ControllerActionSetHandle_t GetActionSetHandle ( const char * pszActionSetName )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetActionSetHandle %s \n " , pszActionSetName ) ;
if ( ! pszActionSetName ) return 0 ;
std : : string upper_action_name ( pszActionSetName ) ;
std : : transform ( upper_action_name . begin ( ) , upper_action_name . end ( ) , upper_action_name . begin ( ) , [ ] ( unsigned char c ) { return std : : toupper ( c ) ; } ) ;
auto set_handle = action_handles . find ( upper_action_name ) ;
if ( set_handle = = action_handles . end ( ) ) return 0 ;
2021-09-14 20:11:17 +00:00
PRINT_DEBUG ( " Steam_Controller::GetActionSetHandle %s ret %llu \n " , pszActionSetName , set_handle - > second ) ;
2019-09-10 18:54:54 +00:00
return set_handle - > second ;
2019-04-13 16:21:56 +00:00
}
// Reconfigure the controller to use the specified action set (ie 'Menu', 'Walk' or 'Drive')
// This is cheap, and can be safely called repeatedly. It's often easier to repeatedly call it in
// your state loops, instead of trying to place it in all of your state transitions.
void ActivateActionSet ( ControllerHandle_t controllerHandle , ControllerActionSetHandle_t actionSetHandle )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::ActivateActionSet %llu %llu \n " , controllerHandle , actionSetHandle ) ;
2019-09-14 21:24:05 +00:00
if ( controllerHandle = = STEAM_CONTROLLER_HANDLE_ALL_CONTROLLERS ) {
for ( auto & c : controllers ) {
c . second . activate_action_set ( actionSetHandle , controller_maps ) ;
}
}
2019-09-10 18:54:54 +00:00
auto controller = controllers . find ( controllerHandle ) ;
if ( controller = = controllers . end ( ) ) return ;
controller - > second . activate_action_set ( actionSetHandle , controller_maps ) ;
2019-04-13 16:21:56 +00:00
}
ControllerActionSetHandle_t GetCurrentActionSet ( ControllerHandle_t controllerHandle )
{
2022-04-02 08:33:34 +00:00
//TODO: should return zero if no action set specifically activated with ActivateActionSet
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetCurrentActionSet %llu \n " , controllerHandle ) ;
auto controller = controllers . find ( controllerHandle ) ;
if ( controller = = controllers . end ( ) ) return 0 ;
return controller - > second . active_set ;
2019-04-13 16:21:56 +00:00
}
void ActivateActionSetLayer ( ControllerHandle_t controllerHandle , ControllerActionSetHandle_t actionSetLayerHandle )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::ActivateActionSetLayer \n " ) ;
2019-04-13 16:21:56 +00:00
}
void DeactivateActionSetLayer ( ControllerHandle_t controllerHandle , ControllerActionSetHandle_t actionSetLayerHandle )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::DeactivateActionSetLayer \n " ) ;
2019-04-13 16:21:56 +00:00
}
void DeactivateAllActionSetLayers ( ControllerHandle_t controllerHandle )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::DeactivateAllActionSetLayers \n " ) ;
2019-04-13 16:21:56 +00:00
}
int GetActiveActionSetLayers ( ControllerHandle_t controllerHandle , ControllerActionSetHandle_t * handlesOut )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetActiveActionSetLayers \n " ) ;
2019-04-13 16:21:56 +00:00
return 0 ;
}
// ACTIONS
// Lookup the handle for a digital action. Best to do this once on startup, and store the handles for all future API calls.
ControllerDigitalActionHandle_t GetDigitalActionHandle ( const char * pszActionName )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetDigitalActionHandle %s \n " , pszActionName ) ;
if ( ! pszActionName ) return 0 ;
std : : string upper_action_name ( pszActionName ) ;
std : : transform ( upper_action_name . begin ( ) , upper_action_name . end ( ) , upper_action_name . begin ( ) , [ ] ( unsigned char c ) { return std : : toupper ( c ) ; } ) ;
auto handle = digital_action_handles . find ( upper_action_name ) ;
2022-01-25 20:50:20 +00:00
if ( handle = = digital_action_handles . end ( ) ) {
//apparently GetDigitalActionHandle also works with analog handles
handle = analog_action_handles . find ( upper_action_name ) ;
if ( handle = = analog_action_handles . end ( ) ) return 0 ;
}
2019-09-10 18:54:54 +00:00
2021-09-14 20:11:17 +00:00
PRINT_DEBUG ( " Steam_Controller::GetDigitalActionHandle %s ret %llu \n " , pszActionName , handle - > second ) ;
2019-09-10 18:54:54 +00:00
return handle - > second ;
2019-04-13 16:21:56 +00:00
}
// Returns the current state of the supplied digital game action
ControllerDigitalActionData_t GetDigitalActionData ( ControllerHandle_t controllerHandle , ControllerDigitalActionHandle_t digitalActionHandle )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetDigitalActionData %llu %llu \n " , controllerHandle , digitalActionHandle ) ;
2019-04-13 16:21:56 +00:00
ControllerDigitalActionData_t digitalData ;
digitalData . bActive = false ;
2019-09-10 18:54:54 +00:00
digitalData . bState = false ;
auto controller = controllers . find ( controllerHandle ) ;
if ( controller = = controllers . end ( ) ) return digitalData ;
std : : set < int > buttons = controller - > second . button_id ( digitalActionHandle ) ;
if ( ! buttons . size ( ) ) return digitalData ;
digitalData . bActive = true ;
GAMEPAD_DEVICE device = ( GAMEPAD_DEVICE ) ( controllerHandle - 1 ) ;
for ( auto button : buttons ) {
bool pressed = false ;
if ( button < BUTTON_COUNT ) {
pressed = GamepadButtonDown ( device , ( GAMEPAD_BUTTON ) button ) ;
} else {
switch ( button ) {
case BUTTON_LTRIGGER :
pressed = GamepadTriggerLength ( device , TRIGGER_LEFT ) > 0.8 ;
break ;
case BUTTON_RTRIGGER :
pressed = GamepadTriggerLength ( device , TRIGGER_RIGHT ) > 0.8 ;
break ;
case BUTTON_STICK_LEFT_UP :
case BUTTON_STICK_LEFT_DOWN :
case BUTTON_STICK_LEFT_LEFT :
2022-04-02 08:33:34 +00:00
case BUTTON_STICK_LEFT_RIGHT : {
float x = 0 , y = 0 , len = GamepadStickLength ( device , STICK_LEFT ) ;
GamepadStickNormXY ( device , STICK_LEFT , & x , & y ) ;
x * = len ;
y * = len ;
if ( button = = BUTTON_STICK_LEFT_UP ) pressed = y > DEADZONE_BUTTON_STICK ;
if ( button = = BUTTON_STICK_LEFT_DOWN ) pressed = y < - DEADZONE_BUTTON_STICK ;
if ( button = = BUTTON_STICK_LEFT_RIGHT ) pressed = x > DEADZONE_BUTTON_STICK ;
if ( button = = BUTTON_STICK_LEFT_LEFT ) pressed = x < - DEADZONE_BUTTON_STICK ;
2019-09-10 18:54:54 +00:00
break ;
2022-04-02 08:33:34 +00:00
}
2019-09-10 18:54:54 +00:00
case BUTTON_STICK_RIGHT_UP :
case BUTTON_STICK_RIGHT_DOWN :
case BUTTON_STICK_RIGHT_LEFT :
2022-04-02 08:33:34 +00:00
case BUTTON_STICK_RIGHT_RIGHT : {
float x = 0 , y = 0 , len = GamepadStickLength ( device , STICK_RIGHT ) ;
GamepadStickNormXY ( device , STICK_RIGHT , & x , & y ) ;
x * = len ;
y * = len ;
if ( button = = BUTTON_STICK_RIGHT_UP ) pressed = y > DEADZONE_BUTTON_STICK ;
if ( button = = BUTTON_STICK_RIGHT_DOWN ) pressed = y < - DEADZONE_BUTTON_STICK ;
if ( button = = BUTTON_STICK_RIGHT_RIGHT ) pressed = x > DEADZONE_BUTTON_STICK ;
if ( button = = BUTTON_STICK_RIGHT_LEFT ) pressed = x < - DEADZONE_BUTTON_STICK ;
2019-09-10 18:54:54 +00:00
break ;
2022-04-02 08:33:34 +00:00
}
2019-09-10 18:54:54 +00:00
default :
break ;
}
}
if ( pressed ) {
digitalData . bState = true ;
break ;
}
}
2019-04-13 16:21:56 +00:00
return digitalData ;
}
// Get the origin(s) for a digital action within an action set. Returns the number of origins supplied in originsOut. Use this to display the appropriate on-screen prompt for the action.
// originsOut should point to a STEAM_CONTROLLER_MAX_ORIGINS sized array of EControllerActionOrigin handles
int GetDigitalActionOrigins ( ControllerHandle_t controllerHandle , ControllerActionSetHandle_t actionSetHandle , ControllerDigitalActionHandle_t digitalActionHandle , EControllerActionOrigin * originsOut )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetDigitalActionOrigins \n " ) ;
2019-09-14 21:24:05 +00:00
EInputActionOrigin origins [ STEAM_CONTROLLER_MAX_ORIGINS ] ;
int ret = GetDigitalActionOrigins ( controllerHandle , actionSetHandle , digitalActionHandle , origins ) ;
for ( int i = 0 ; i < ret ; + + i ) {
2019-09-20 10:14:08 +00:00
originsOut [ i ] = ( EControllerActionOrigin ) ( origins [ i ] - ( k_EInputActionOrigin_XBox360_A - k_EControllerActionOrigin_XBox360_A ) ) ;
2019-09-14 21:24:05 +00:00
}
return ret ;
2019-04-13 16:21:56 +00:00
}
int GetDigitalActionOrigins ( InputHandle_t inputHandle , InputActionSetHandle_t actionSetHandle , InputDigitalActionHandle_t digitalActionHandle , EInputActionOrigin * originsOut )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetDigitalActionOrigins steaminput \n " ) ;
2019-09-14 21:24:05 +00:00
auto controller = controllers . find ( inputHandle ) ;
if ( controller = = controllers . end ( ) ) return 0 ;
auto map = controller_maps . find ( actionSetHandle ) ;
if ( map = = controller_maps . end ( ) ) return 0 ;
auto a = map - > second . active_digital . find ( digitalActionHandle ) ;
if ( a = = map - > second . active_digital . end ( ) ) return 0 ;
int count = 0 ;
for ( auto button : a - > second ) {
switch ( button ) {
case BUTTON_A :
originsOut [ count ] = k_EInputActionOrigin_XBox360_A ;
break ;
case BUTTON_B :
originsOut [ count ] = k_EInputActionOrigin_XBox360_B ;
break ;
case BUTTON_X :
originsOut [ count ] = k_EInputActionOrigin_XBox360_X ;
break ;
case BUTTON_Y :
originsOut [ count ] = k_EInputActionOrigin_XBox360_Y ;
break ;
case BUTTON_LEFT_SHOULDER :
originsOut [ count ] = k_EInputActionOrigin_XBox360_LeftBumper ;
break ;
case BUTTON_RIGHT_SHOULDER :
originsOut [ count ] = k_EInputActionOrigin_XBox360_RightBumper ;
break ;
case BUTTON_START :
originsOut [ count ] = k_EInputActionOrigin_XBox360_Start ;
break ;
case BUTTON_BACK :
originsOut [ count ] = k_EInputActionOrigin_XBox360_Back ;
break ;
case BUTTON_LTRIGGER :
originsOut [ count ] = k_EInputActionOrigin_XBox360_LeftTrigger_Click ;
break ;
case BUTTON_RTRIGGER :
originsOut [ count ] = k_EInputActionOrigin_XBox360_RightTrigger_Click ;
break ;
case BUTTON_LEFT_THUMB :
originsOut [ count ] = k_EInputActionOrigin_XBox360_LeftStick_Click ;
break ;
case BUTTON_RIGHT_THUMB :
originsOut [ count ] = k_EInputActionOrigin_XBox360_RightStick_Click ;
break ;
case BUTTON_STICK_LEFT_UP :
originsOut [ count ] = k_EInputActionOrigin_XBox360_LeftStick_DPadNorth ;
break ;
case BUTTON_STICK_LEFT_DOWN :
originsOut [ count ] = k_EInputActionOrigin_XBox360_LeftStick_DPadSouth ;
break ;
case BUTTON_STICK_LEFT_LEFT :
originsOut [ count ] = k_EInputActionOrigin_XBox360_LeftStick_DPadWest ;
break ;
case BUTTON_STICK_LEFT_RIGHT :
originsOut [ count ] = k_EInputActionOrigin_XBox360_LeftStick_DPadEast ;
break ;
case BUTTON_STICK_RIGHT_UP :
originsOut [ count ] = k_EInputActionOrigin_XBox360_RightStick_DPadNorth ;
break ;
case BUTTON_STICK_RIGHT_DOWN :
originsOut [ count ] = k_EInputActionOrigin_XBox360_RightStick_DPadSouth ;
break ;
case BUTTON_STICK_RIGHT_LEFT :
originsOut [ count ] = k_EInputActionOrigin_XBox360_RightStick_DPadWest ;
break ;
case BUTTON_STICK_RIGHT_RIGHT :
originsOut [ count ] = k_EInputActionOrigin_XBox360_RightStick_DPadEast ;
break ;
case BUTTON_DPAD_UP :
originsOut [ count ] = k_EInputActionOrigin_XBox360_DPad_North ;
break ;
case BUTTON_DPAD_DOWN :
originsOut [ count ] = k_EInputActionOrigin_XBox360_DPad_South ;
break ;
case BUTTON_DPAD_LEFT :
originsOut [ count ] = k_EInputActionOrigin_XBox360_DPad_West ;
break ;
case BUTTON_DPAD_RIGHT :
originsOut [ count ] = k_EInputActionOrigin_XBox360_DPad_East ;
break ;
default :
originsOut [ count ] = k_EInputActionOrigin_None ;
break ;
}
+ + count ;
if ( count > = STEAM_INPUT_MAX_ORIGINS ) {
break ;
}
}
return count ;
2019-04-13 16:21:56 +00:00
}
2021-12-06 21:51:17 +00:00
// Returns a localized string (from Steam's language setting) for the user-facing action name corresponding to the specified handle
const char * GetStringForDigitalActionName ( InputDigitalActionHandle_t eActionHandle )
{
PRINT_DEBUG ( " TODO %s \n " , __FUNCTION__ ) ;
//TODO SteamInput005
return " Button String " ;
}
2019-04-13 16:21:56 +00:00
// Lookup the handle for an analog action. Best to do this once on startup, and store the handles for all future API calls.
ControllerAnalogActionHandle_t GetAnalogActionHandle ( const char * pszActionName )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetAnalogActionHandle %s \n " , pszActionName ) ;
if ( ! pszActionName ) return 0 ;
std : : string upper_action_name ( pszActionName ) ;
std : : transform ( upper_action_name . begin ( ) , upper_action_name . end ( ) , upper_action_name . begin ( ) , [ ] ( unsigned char c ) { return std : : toupper ( c ) ; } ) ;
auto handle = analog_action_handles . find ( upper_action_name ) ;
if ( handle = = analog_action_handles . end ( ) ) return 0 ;
return handle - > second ;
2019-04-13 16:21:56 +00:00
}
// Returns the current state of these supplied analog game action
ControllerAnalogActionData_t GetAnalogActionData ( ControllerHandle_t controllerHandle , ControllerAnalogActionHandle_t analogActionHandle )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetAnalogActionData %llu %llu \n " , controllerHandle , analogActionHandle ) ;
2021-09-10 18:19:12 +00:00
GAMEPAD_DEVICE device = ( GAMEPAD_DEVICE ) ( controllerHandle - 1 ) ;
2019-04-13 16:21:56 +00:00
ControllerAnalogActionData_t data ;
data . eMode = k_EInputSourceMode_None ;
data . x = data . y = 0 ;
data . bActive = false ;
2019-09-10 18:54:54 +00:00
auto controller = controllers . find ( controllerHandle ) ;
if ( controller = = controllers . end ( ) ) return data ;
auto analog = controller - > second . analog_id ( analogActionHandle ) ;
if ( ! analog . first . size ( ) ) return data ;
data . bActive = true ;
data . eMode = analog . second ;
for ( auto a : analog . first ) {
2019-09-14 21:24:05 +00:00
if ( a > = JOY_ID_START ) {
int joystick_id = a - JOY_ID_START ;
2021-09-10 18:19:12 +00:00
if ( joystick_id = = STICK_DPAD ) {
int mov_y = ( int ) GamepadButtonDown ( device , BUTTON_DPAD_UP ) - ( int ) GamepadButtonDown ( device , BUTTON_DPAD_DOWN ) ;
int mov_x = ( int ) GamepadButtonDown ( device , BUTTON_DPAD_RIGHT ) - ( int ) GamepadButtonDown ( device , BUTTON_DPAD_LEFT ) ;
if ( mov_y | | mov_x ) {
data . x = mov_x ;
data . y = mov_y ;
double length = 1.0 / std : : sqrt ( data . x * data . x + data . y * data . y ) ;
data . x = data . x * length ;
data . y = data . y * length ;
}
} else {
GamepadStickNormXY ( device , ( GAMEPAD_STICK ) joystick_id , & data . x , & data . y ) ;
float length = GamepadStickLength ( device , ( GAMEPAD_STICK ) joystick_id ) ;
data . x = data . x * length ;
data . y = data . y * length ;
}
2019-09-10 18:54:54 +00:00
} else {
2021-09-10 18:19:12 +00:00
data . x = GamepadTriggerLength ( device , ( GAMEPAD_TRIGGER ) a ) ;
2019-09-10 18:54:54 +00:00
}
2019-09-12 11:21:11 +00:00
if ( data . x | | data . y ) {
break ;
}
2019-09-10 18:54:54 +00:00
}
2019-04-13 16:21:56 +00:00
return data ;
}
// Get the origin(s) for an analog action within an action set. Returns the number of origins supplied in originsOut. Use this to display the appropriate on-screen prompt for the action.
// originsOut should point to a STEAM_CONTROLLER_MAX_ORIGINS sized array of EControllerActionOrigin handles
int GetAnalogActionOrigins ( ControllerHandle_t controllerHandle , ControllerActionSetHandle_t actionSetHandle , ControllerAnalogActionHandle_t analogActionHandle , EControllerActionOrigin * originsOut )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetAnalogActionOrigins \n " ) ;
2019-09-14 21:24:05 +00:00
EInputActionOrigin origins [ STEAM_CONTROLLER_MAX_ORIGINS ] ;
int ret = GetAnalogActionOrigins ( controllerHandle , actionSetHandle , analogActionHandle , origins ) ;
for ( int i = 0 ; i < ret ; + + i ) {
2019-09-20 10:14:08 +00:00
originsOut [ i ] = ( EControllerActionOrigin ) ( origins [ i ] - ( k_EInputActionOrigin_XBox360_A - k_EControllerActionOrigin_XBox360_A ) ) ;
2019-09-14 21:24:05 +00:00
}
return ret ;
2019-04-13 16:21:56 +00:00
}
int GetAnalogActionOrigins ( InputHandle_t inputHandle , InputActionSetHandle_t actionSetHandle , InputAnalogActionHandle_t analogActionHandle , EInputActionOrigin * originsOut )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetAnalogActionOrigins steaminput \n " ) ;
2019-09-14 21:24:05 +00:00
auto controller = controllers . find ( inputHandle ) ;
if ( controller = = controllers . end ( ) ) return 0 ;
auto map = controller_maps . find ( actionSetHandle ) ;
if ( map = = controller_maps . end ( ) ) return 0 ;
auto a = map - > second . active_analog . find ( analogActionHandle ) ;
if ( a = = map - > second . active_analog . end ( ) ) return 0 ;
int count = 0 ;
2020-01-12 19:43:25 +00:00
for ( auto b : a - > second . first ) {
switch ( b ) {
2019-09-14 21:24:05 +00:00
case TRIGGER_LEFT :
originsOut [ count ] = k_EInputActionOrigin_XBox360_LeftTrigger_Pull ;
break ;
case TRIGGER_RIGHT :
originsOut [ count ] = k_EInputActionOrigin_XBox360_RightTrigger_Pull ;
break ;
case STICK_LEFT + JOY_ID_START :
originsOut [ count ] = k_EInputActionOrigin_XBox360_LeftStick_Move ;
break ;
case STICK_RIGHT + JOY_ID_START :
originsOut [ count ] = k_EInputActionOrigin_XBox360_RightStick_Move ;
break ;
2021-09-10 18:19:12 +00:00
case STICK_DPAD + JOY_ID_START :
originsOut [ count ] = k_EInputActionOrigin_XBox360_DPad_Move ;
break ;
2019-09-14 21:24:05 +00:00
default :
originsOut [ count ] = k_EInputActionOrigin_None ;
break ;
}
+ + count ;
if ( count > = STEAM_INPUT_MAX_ORIGINS ) {
break ;
}
}
2019-09-20 15:04:04 +00:00
return count ;
2019-04-13 16:21:56 +00:00
}
void StopAnalogActionMomentum ( ControllerHandle_t controllerHandle , ControllerAnalogActionHandle_t eAction )
{
2020-01-12 19:28:57 +00:00
PRINT_DEBUG ( " Steam_Controller::StopAnalogActionMomentum %llu %llu \n " , controllerHandle , eAction ) ;
2019-04-13 16:21:56 +00:00
}
// Trigger a haptic pulse on a controller
void TriggerHapticPulse ( ControllerHandle_t controllerHandle , ESteamControllerPad eTargetPad , unsigned short usDurationMicroSec )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::TriggerHapticPulse \n " ) ;
2019-04-13 16:21:56 +00:00
}
2021-12-06 21:51:17 +00:00
// Trigger a haptic pulse on a controller
void Legacy_TriggerHapticPulse ( InputHandle_t inputHandle , ESteamControllerPad eTargetPad , unsigned short usDurationMicroSec )
{
PRINT_DEBUG ( " %s \n " , __FUNCTION__ ) ;
TriggerHapticPulse ( inputHandle , eTargetPad , usDurationMicroSec ) ;
}
2019-04-13 16:21:56 +00:00
void TriggerHapticPulse ( uint32 unControllerIndex , ESteamControllerPad eTargetPad , unsigned short usDurationMicroSec )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::TriggerHapticPulse old \n " ) ;
2019-04-13 16:21:56 +00:00
TriggerHapticPulse ( unControllerIndex , eTargetPad , usDurationMicroSec ) ;
}
// Trigger a pulse with a duty cycle of usDurationMicroSec / usOffMicroSec, unRepeat times.
// nFlags is currently unused and reserved for future use.
void TriggerRepeatedHapticPulse ( ControllerHandle_t controllerHandle , ESteamControllerPad eTargetPad , unsigned short usDurationMicroSec , unsigned short usOffMicroSec , unsigned short unRepeat , unsigned int nFlags )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::TriggerRepeatedHapticPulse \n " ) ;
2019-04-13 16:21:56 +00:00
}
2021-12-06 21:51:17 +00:00
void Legacy_TriggerRepeatedHapticPulse ( InputHandle_t inputHandle , ESteamControllerPad eTargetPad , unsigned short usDurationMicroSec , unsigned short usOffMicroSec , unsigned short unRepeat , unsigned int nFlags )
{
PRINT_DEBUG ( " %s \n " , __FUNCTION__ ) ;
TriggerRepeatedHapticPulse ( inputHandle , eTargetPad , usDurationMicroSec , usOffMicroSec , unRepeat , nFlags ) ;
}
// Send a haptic pulse, works on Steam Deck and Steam Controller devices
void TriggerSimpleHapticEvent ( InputHandle_t inputHandle , EControllerHapticLocation eHapticLocation , uint8 nIntensity , char nGainDB , uint8 nOtherIntensity , char nOtherGainDB )
{
PRINT_DEBUG ( " TODO %s \n " , __FUNCTION__ ) ;
}
2019-04-13 16:21:56 +00:00
// Tigger a vibration event on supported controllers.
void TriggerVibration ( ControllerHandle_t controllerHandle , unsigned short usLeftSpeed , unsigned short usRightSpeed )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::TriggerVibration %hu %hu \n " , usLeftSpeed , usRightSpeed ) ;
auto controller = controllers . find ( controllerHandle ) ;
if ( controller = = controllers . end ( ) ) return ;
2020-01-12 19:28:57 +00:00
unsigned int rumble_length_ms = 0 ;
# if defined(__linux__)
//FIXME: shadow of the tomb raider on linux doesn't seem to turn off the rumble so I made it expire after 100ms. Need to check if this is how linux steam actually behaves.
rumble_length_ms = 100 ;
# endif
2021-09-14 20:11:17 +00:00
unsigned gamepad_device = ( controllerHandle - 1 ) ;
if ( gamepad_device > GAMEPAD_COUNT ) return ;
rumble_thread_data - > rumble_mutex . lock ( ) ;
rumble_thread_data - > data [ gamepad_device ] . new_data = true ;
rumble_thread_data - > data [ gamepad_device ] . left = usLeftSpeed ;
rumble_thread_data - > data [ gamepad_device ] . right = usRightSpeed ;
rumble_thread_data - > data [ gamepad_device ] . rumble_length_ms = rumble_length_ms ;
rumble_thread_data - > rumble_mutex . unlock ( ) ;
rumble_thread_data - > rumble_thread_cv . notify_one ( ) ;
2019-04-13 16:21:56 +00:00
}
2021-12-06 21:51:17 +00:00
// Trigger a vibration event on supported controllers including Xbox trigger impulse rumble - Steam will translate these commands into haptic pulses for Steam Controllers
void TriggerVibrationExtended ( InputHandle_t inputHandle , unsigned short usLeftSpeed , unsigned short usRightSpeed , unsigned short usLeftTriggerSpeed , unsigned short usRightTriggerSpeed )
{
PRINT_DEBUG ( " TODO %s \n " , __FUNCTION__ ) ;
TriggerVibration ( inputHandle , usLeftSpeed , usRightSpeed ) ;
//TODO trigger impulse rumbles
}
2019-04-13 16:21:56 +00:00
// Set the controller LED color on supported controllers.
void SetLEDColor ( ControllerHandle_t controllerHandle , uint8 nColorR , uint8 nColorG , uint8 nColorB , unsigned int nFlags )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::SetLEDColor \n " ) ;
2019-04-13 16:21:56 +00:00
}
// Returns the associated gamepad index for the specified controller, if emulating a gamepad
int GetGamepadIndexForController ( ControllerHandle_t ulControllerHandle )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetGamepadIndexForController \n " ) ;
2020-07-11 15:48:01 +00:00
auto controller = controllers . find ( ulControllerHandle ) ;
if ( controller = = controllers . end ( ) ) return - 1 ;
return ulControllerHandle - 1 ;
2019-04-13 16:21:56 +00:00
}
// Returns the associated controller handle for the specified emulated gamepad
ControllerHandle_t GetControllerForGamepadIndex ( int nIndex )
{
2021-02-08 00:09:48 +00:00
PRINT_DEBUG ( " Steam_Controller::GetControllerForGamepadIndex %i \n " , nIndex ) ;
2020-07-11 15:48:01 +00:00
ControllerHandle_t out = nIndex + 1 ;
auto controller = controllers . find ( out ) ;
if ( controller = = controllers . end ( ) ) return 0 ;
return out ;
2019-04-13 16:21:56 +00:00
}
// Returns raw motion data from the specified controller
ControllerMotionData_t GetMotionData ( ControllerHandle_t controllerHandle )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetMotionData \n " ) ;
2019-04-13 16:21:56 +00:00
ControllerMotionData_t data = { } ;
return data ;
}
// Attempt to display origins of given action in the controller HUD, for the currently active action set
// Returns false is overlay is disabled / unavailable, or the user is not in Big Picture mode
bool ShowDigitalActionOrigins ( ControllerHandle_t controllerHandle , ControllerDigitalActionHandle_t digitalActionHandle , float flScale , float flXPosition , float flYPosition )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::ShowDigitalActionOrigins \n " ) ;
2019-04-13 16:21:56 +00:00
return true ;
}
bool ShowAnalogActionOrigins ( ControllerHandle_t controllerHandle , ControllerAnalogActionHandle_t analogActionHandle , float flScale , float flXPosition , float flYPosition )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::ShowAnalogActionOrigins \n " ) ;
2019-04-13 16:21:56 +00:00
return true ;
}
// Returns a localized string (from Steam's language setting) for the specified origin
const char * GetStringForActionOrigin ( EControllerActionOrigin eOrigin )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetStringForActionOrigin \n " ) ;
2019-04-13 16:21:56 +00:00
return " Button String " ;
}
const char * GetStringForActionOrigin ( EInputActionOrigin eOrigin )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetStringForActionOrigin steaminput \n " ) ;
2019-04-13 16:21:56 +00:00
return " Button String " ;
}
2021-12-06 21:51:17 +00:00
// Returns a localized string (from Steam's language setting) for the user-facing action name corresponding to the specified handle
const char * GetStringForAnalogActionName ( InputAnalogActionHandle_t eActionHandle )
{
PRINT_DEBUG ( " TODO %s \n " , __FUNCTION__ ) ;
//TODO SteamInput005
return " Button String " ;
}
2019-04-13 16:21:56 +00:00
// Get a local path to art for on-screen glyph for a particular origin
const char * GetGlyphForActionOrigin ( EControllerActionOrigin eOrigin )
{
2019-12-11 17:06:19 +00:00
PRINT_DEBUG ( " Steam_Controller::GetGlyphForActionOrigin %i \n " , eOrigin ) ;
if ( steamcontroller_glyphs . empty ( ) ) {
std : : string dir = settings - > glyphs_directory ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_A ] = dir + " button_a.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_B ] = dir + " button_b.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_X ] = dir + " button_x.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_Y ] = dir + " button_y.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_LeftBumper ] = dir + " shoulder_l.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_RightBumper ] = dir + " shoulder_r.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_Start ] = dir + " xbox_button_start.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_Back ] = dir + " xbox_button_select.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_LeftTrigger_Pull ] = dir + " trigger_l_pull.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_LeftTrigger_Click ] = dir + " trigger_l_click.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_RightTrigger_Pull ] = dir + " trigger_r_pull.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_RightTrigger_Click ] = dir + " trigger_r_click.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_LeftStick_Move ] = dir + " stick_l_move.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_LeftStick_Click ] = dir + " stick_l_click.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_LeftStick_DPadNorth ] = dir + " stick_dpad_n.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_LeftStick_DPadSouth ] = dir + " stick_dpad_s.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_LeftStick_DPadWest ] = dir + " stick_dpad_w.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_LeftStick_DPadEast ] = dir + " stick_dpad_e.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_RightStick_Move ] = dir + " stick_r_move.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_RightStick_Click ] = dir + " stick_r_click.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_RightStick_DPadNorth ] = dir + " stick_dpad_n.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_RightStick_DPadSouth ] = dir + " stick_dpad_s.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_RightStick_DPadWest ] = dir + " stick_dpad_w.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_RightStick_DPadEast ] = dir + " stick_dpad_e.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_DPad_North ] = dir + " xbox_button_dpad_n.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_DPad_South ] = dir + " xbox_button_dpad_s.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_DPad_West ] = dir + " xbox_button_dpad_w.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_DPad_East ] = dir + " xbox_button_dpad_e.png " ;
steamcontroller_glyphs [ k_EControllerActionOrigin_XBox360_DPad_Move ] = dir + " xbox_button_dpad_move.png " ;
}
auto glyph = steamcontroller_glyphs . find ( eOrigin ) ;
if ( glyph = = steamcontroller_glyphs . end ( ) ) return " " ;
return glyph - > second . c_str ( ) ;
2019-04-13 16:21:56 +00:00
}
const char * GetGlyphForActionOrigin ( EInputActionOrigin eOrigin )
{
2019-12-11 17:06:19 +00:00
PRINT_DEBUG ( " Steam_Controller::GetGlyphForActionOrigin steaminput %i \n " , eOrigin ) ;
if ( steaminput_glyphs . empty ( ) ) {
std : : string dir = settings - > glyphs_directory ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_A ] = dir + " button_a.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_B ] = dir + " button_b.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_X ] = dir + " button_x.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_Y ] = dir + " button_y.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_LeftBumper ] = dir + " shoulder_l.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_RightBumper ] = dir + " shoulder_r.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_Start ] = dir + " xbox_button_start.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_Back ] = dir + " xbox_button_select.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_LeftTrigger_Pull ] = dir + " trigger_l_pull.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_LeftTrigger_Click ] = dir + " trigger_l_click.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_RightTrigger_Pull ] = dir + " trigger_r_pull.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_RightTrigger_Click ] = dir + " trigger_r_click.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_LeftStick_Move ] = dir + " stick_l_move.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_LeftStick_Click ] = dir + " stick_l_click.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_LeftStick_DPadNorth ] = dir + " stick_dpad_n.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_LeftStick_DPadSouth ] = dir + " stick_dpad_s.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_LeftStick_DPadWest ] = dir + " stick_dpad_w.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_LeftStick_DPadEast ] = dir + " stick_dpad_e.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_RightStick_Move ] = dir + " stick_r_move.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_RightStick_Click ] = dir + " stick_r_click.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_RightStick_DPadNorth ] = dir + " stick_dpad_n.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_RightStick_DPadSouth ] = dir + " stick_dpad_s.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_RightStick_DPadWest ] = dir + " stick_dpad_w.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_RightStick_DPadEast ] = dir + " stick_dpad_e.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_DPad_North ] = dir + " xbox_button_dpad_n.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_DPad_South ] = dir + " xbox_button_dpad_s.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_DPad_West ] = dir + " xbox_button_dpad_w.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_DPad_East ] = dir + " xbox_button_dpad_e.png " ;
steaminput_glyphs [ k_EInputActionOrigin_XBox360_DPad_Move ] = dir + " xbox_button_dpad_move.png " ;
//steaminput_glyphs[] = dir + "";
}
auto glyph = steaminput_glyphs . find ( eOrigin ) ;
if ( glyph = = steaminput_glyphs . end ( ) ) return " " ;
return glyph - > second . c_str ( ) ;
2019-04-13 16:21:56 +00:00
}
2021-12-06 21:51:17 +00:00
// Get a local path to a PNG file for the provided origin's glyph.
const char * GetGlyphPNGForActionOrigin ( EInputActionOrigin eOrigin , ESteamInputGlyphSize eSize , uint32 unFlags )
{
PRINT_DEBUG ( " TODO %s \n " , __FUNCTION__ ) ;
//TODO SteamInput005
return " " ;
}
// Get a local path to a SVG file for the provided origin's glyph.
const char * GetGlyphSVGForActionOrigin ( EInputActionOrigin eOrigin , uint32 unFlags )
{
PRINT_DEBUG ( " TODO %s \n " , __FUNCTION__ ) ;
//TODO SteamInput005
return " " ;
}
// Get a local path to an older, Big Picture Mode-style PNG file for a particular origin
const char * GetGlyphForActionOrigin_Legacy ( EInputActionOrigin eOrigin )
{
PRINT_DEBUG ( " %s \n " , __FUNCTION__ ) ;
return GetGlyphForActionOrigin ( eOrigin ) ;
}
2019-04-13 16:21:56 +00:00
// Returns the input type for a particular handle
ESteamInputType GetInputTypeForHandle ( ControllerHandle_t controllerHandle )
{
2021-02-08 00:09:48 +00:00
PRINT_DEBUG ( " Steam_Controller::GetInputTypeForHandle %llu \n " , controllerHandle ) ;
2019-09-10 18:54:54 +00:00
auto controller = controllers . find ( controllerHandle ) ;
if ( controller = = controllers . end ( ) ) return k_ESteamInputType_Unknown ;
return k_ESteamInputType_XBox360Controller ;
2019-04-13 16:21:56 +00:00
}
const char * GetStringForXboxOrigin ( EXboxOrigin eOrigin )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetStringForXboxOrigin \n " ) ;
2019-04-13 16:21:56 +00:00
return " " ;
}
const char * GetGlyphForXboxOrigin ( EXboxOrigin eOrigin )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetGlyphForXboxOrigin \n " ) ;
2019-04-13 16:21:56 +00:00
return " " ;
}
EControllerActionOrigin GetActionOriginFromXboxOrigin_ ( ControllerHandle_t controllerHandle , EXboxOrigin eOrigin )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetActionOriginFromXboxOrigin \n " ) ;
2019-04-13 16:21:56 +00:00
return k_EControllerActionOrigin_None ;
}
EInputActionOrigin GetActionOriginFromXboxOrigin ( InputHandle_t inputHandle , EXboxOrigin eOrigin )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetActionOriginFromXboxOrigin steaminput \n " ) ;
2019-04-13 16:21:56 +00:00
return k_EInputActionOrigin_None ;
}
EControllerActionOrigin TranslateActionOrigin ( ESteamInputType eDestinationInputType , EControllerActionOrigin eSourceOrigin )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::TranslateActionOrigin \n " ) ;
2019-04-13 16:21:56 +00:00
return k_EControllerActionOrigin_None ;
}
EInputActionOrigin TranslateActionOrigin ( ESteamInputType eDestinationInputType , EInputActionOrigin eSourceOrigin )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::TranslateActionOrigin steaminput \n " ) ;
2019-04-13 16:21:56 +00:00
return k_EInputActionOrigin_None ;
}
2019-07-28 13:02:09 +00:00
bool GetControllerBindingRevision ( ControllerHandle_t controllerHandle , int * pMajor , int * pMinor )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetControllerBindingRevision \n " ) ;
2019-07-28 13:02:09 +00:00
return false ;
}
bool GetDeviceBindingRevision ( InputHandle_t inputHandle , int * pMajor , int * pMinor )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetDeviceBindingRevision \n " ) ;
2019-07-28 13:02:09 +00:00
return false ;
}
uint32 GetRemotePlaySessionID ( InputHandle_t inputHandle )
{
2019-09-10 18:54:54 +00:00
PRINT_DEBUG ( " Steam_Controller::GetRemotePlaySessionID \n " ) ;
2019-07-28 13:02:09 +00:00
return 0 ;
}
2019-04-13 16:21:56 +00:00
2021-12-06 21:51:17 +00:00
// Get a bitmask of the Steam Input Configuration types opted in for the current session. Returns ESteamInputConfigurationEnableType values.?
// Note: user can override the settings from the Steamworks Partner site so the returned values may not exactly match your default configuration
uint16 GetSessionInputConfigurationSettings ( )
{
PRINT_DEBUG ( " TODO %s \n " , __FUNCTION__ ) ;
return 0 ;
}
2022-08-05 05:32:20 +00:00
// Set the trigger effect for a DualSense controller
void SetDualSenseTriggerEffect ( InputHandle_t inputHandle , const ScePadTriggerEffectParam * pParam )
{
PRINT_DEBUG ( " TODO %s \n " , __FUNCTION__ ) ;
}
2019-09-10 18:54:54 +00:00
void RunCallbacks ( )
{
2021-12-06 21:51:17 +00:00
if ( explicitly_call_run_frame ) {
RunFrame ( ) ;
}
2019-09-10 18:54:54 +00:00
}
2019-04-13 16:21:56 +00:00
} ;