mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-07 17:29:36 +00:00
1
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
LIBRARY inputsystem_360.dll
|
||||
EXPORTS
|
||||
CreateInterface @1
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,469 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//===========================================================================//
|
||||
#ifndef INPUTSYSTEM_H
|
||||
#define INPUTSYSTEM_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#if !defined( _X360 )
|
||||
#define _WIN32_WINNT 0x502
|
||||
#include <windows.h>
|
||||
#include <zmouse.h>
|
||||
#include "xbox/xboxstubs.h"
|
||||
#include "../../dx9sdk/include/XInput.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef POSIX
|
||||
#include "posix_stubs.h"
|
||||
#endif // POSIX
|
||||
|
||||
#include "appframework/ilaunchermgr.h"
|
||||
|
||||
#include "inputsystem/iinputsystem.h"
|
||||
#include "tier2/tier2.h"
|
||||
|
||||
#include "inputsystem/ButtonCode.h"
|
||||
#include "inputsystem/AnalogCode.h"
|
||||
#include "bitvec.h"
|
||||
#include "tier1/utlvector.h"
|
||||
#include "tier1/utlflags.h"
|
||||
|
||||
#if defined( _X360 )
|
||||
#include "xbox/xbox_win32stubs.h"
|
||||
#include "xbox/xbox_console.h"
|
||||
#endif
|
||||
|
||||
#include "steam/steam_api.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Implementation of the input system
|
||||
//-----------------------------------------------------------------------------
|
||||
class CInputSystem : public CTier2AppSystem< IInputSystem >
|
||||
{
|
||||
typedef CTier2AppSystem< IInputSystem > BaseClass;
|
||||
|
||||
public:
|
||||
// Constructor, destructor
|
||||
CInputSystem();
|
||||
virtual ~CInputSystem();
|
||||
|
||||
// Inherited from IAppSystem
|
||||
virtual InitReturnVal_t Init();
|
||||
virtual bool Connect( CreateInterfaceFn factory );
|
||||
|
||||
virtual void Shutdown();
|
||||
|
||||
// Inherited from IInputSystem
|
||||
virtual void AttachToWindow( void* hWnd );
|
||||
virtual void DetachFromWindow();
|
||||
virtual void EnableInput( bool bEnable );
|
||||
virtual void EnableMessagePump( bool bEnable );
|
||||
virtual int GetPollTick() const;
|
||||
virtual void PollInputState();
|
||||
virtual bool IsButtonDown( ButtonCode_t code ) const;
|
||||
virtual int GetButtonPressedTick( ButtonCode_t code ) const;
|
||||
virtual int GetButtonReleasedTick( ButtonCode_t code ) const;
|
||||
virtual int GetAnalogValue( AnalogCode_t code ) const;
|
||||
virtual int GetAnalogDelta( AnalogCode_t code ) const;
|
||||
virtual int GetEventCount() const;
|
||||
virtual const InputEvent_t* GetEventData() const;
|
||||
virtual void PostUserEvent( const InputEvent_t &event );
|
||||
virtual int GetJoystickCount() const;
|
||||
virtual void EnableJoystickInput( int nJoystick, bool bEnable );
|
||||
virtual void EnableJoystickDiagonalPOV( int nJoystick, bool bEnable );
|
||||
virtual void SampleDevices( void );
|
||||
virtual void SetRumble( float fLeftMotor, float fRightMotor, int userId );
|
||||
virtual void StopRumble( void );
|
||||
virtual void ResetInputState( void );
|
||||
virtual void SetPrimaryUserId( int userId );
|
||||
virtual const char *ButtonCodeToString( ButtonCode_t code ) const;
|
||||
virtual const char *AnalogCodeToString( AnalogCode_t code ) const;
|
||||
virtual ButtonCode_t StringToButtonCode( const char *pString ) const;
|
||||
virtual AnalogCode_t StringToAnalogCode( const char *pString ) const;
|
||||
virtual ButtonCode_t VirtualKeyToButtonCode( int nVirtualKey ) const;
|
||||
virtual int ButtonCodeToVirtualKey( ButtonCode_t code ) const;
|
||||
virtual ButtonCode_t ScanCodeToButtonCode( int lParam ) const;
|
||||
virtual void SleepUntilInput( int nMaxSleepTimeMS );
|
||||
virtual int GetPollCount() const;
|
||||
virtual void SetCursorPosition( int x, int y );
|
||||
#if defined( WIN32 ) && !defined ( _X360 )
|
||||
virtual void *GetHapticsInterfaceAddress() const;
|
||||
#else
|
||||
virtual void *GetHapticsInterfaceAddress() const { return NULL;}
|
||||
#endif
|
||||
bool GetRawMouseAccumulators( int& accumX, int& accumY );
|
||||
virtual void SetConsoleTextMode( bool bConsoleTextMode );
|
||||
|
||||
// Windows proc
|
||||
LRESULT WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
STICK1_AXIS_LEFT,
|
||||
STICK1_AXIS_RIGHT,
|
||||
STICK1_AXIS_DOWN,
|
||||
STICK1_AXIS_UP,
|
||||
STICK2_AXIS_LEFT,
|
||||
STICK2_AXIS_RIGHT,
|
||||
STICK2_AXIS_DOWN,
|
||||
STICK2_AXIS_UP,
|
||||
MAX_STICKAXIS
|
||||
};
|
||||
|
||||
// track Xbox stick keys from previous frame
|
||||
enum
|
||||
{
|
||||
LASTKEY_STICK1_X,
|
||||
LASTKEY_STICK1_Y,
|
||||
LASTKEY_STICK2_X,
|
||||
LASTKEY_STICK2_Y,
|
||||
MAX_LASTKEY,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
INPUT_STATE_QUEUED = 0,
|
||||
INPUT_STATE_CURRENT,
|
||||
|
||||
INPUT_STATE_COUNT,
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
struct JoystickInfo_t
|
||||
{
|
||||
void *m_pDevice; // Really an SDL_GameController*, NULL if not present.
|
||||
void *m_pHaptic; // Really an SDL_Haptic*
|
||||
float m_fCurrentRumble;
|
||||
bool m_bRumbleEnabled;
|
||||
int m_nButtonCount;
|
||||
int m_nAxisFlags;
|
||||
int m_nDeviceId;
|
||||
bool m_bHasPOVControl;
|
||||
bool m_bDiagonalPOVControlEnabled;
|
||||
unsigned int m_nFlags;
|
||||
unsigned int m_nLastPolledButtons;
|
||||
unsigned int m_nLastPolledAxisButtons;
|
||||
unsigned int m_nLastPolledPOVState;
|
||||
unsigned long m_pLastPolledAxes[MAX_JOYSTICK_AXES];
|
||||
};
|
||||
|
||||
struct xdevice_t
|
||||
{
|
||||
int userId;
|
||||
byte type;
|
||||
byte subtype;
|
||||
word flags;
|
||||
bool active;
|
||||
XINPUT_STATE states[2];
|
||||
int newState;
|
||||
xKey_t lastStickKeys[MAX_LASTKEY];
|
||||
int stickThreshold[MAX_STICKAXIS];
|
||||
float stickScale[MAX_STICKAXIS];
|
||||
int quitTimeout;
|
||||
int dpadLock;
|
||||
// rumble
|
||||
XINPUT_VIBRATION vibration;
|
||||
bool pendingRumbleUpdate;
|
||||
};
|
||||
|
||||
struct appKey_t
|
||||
{
|
||||
int repeats;
|
||||
int sample;
|
||||
};
|
||||
|
||||
struct InputState_t
|
||||
{
|
||||
// Analog states
|
||||
CBitVec<BUTTON_CODE_LAST> m_ButtonState;
|
||||
int m_ButtonPressedTick[BUTTON_CODE_LAST];
|
||||
int m_ButtonReleasedTick[BUTTON_CODE_LAST];
|
||||
int m_pAnalogDelta[ANALOG_CODE_LAST];
|
||||
int m_pAnalogValue[ANALOG_CODE_LAST];
|
||||
CUtlVector< InputEvent_t > m_Events;
|
||||
bool m_bDirty;
|
||||
};
|
||||
|
||||
// Initializes all Xbox controllers
|
||||
void InitializeXDevices( void );
|
||||
|
||||
// Opens an Xbox controller
|
||||
void OpenXDevice( xdevice_t* pXDevice, int userId );
|
||||
|
||||
// Closes an Xbox controller
|
||||
void CloseXDevice( xdevice_t* pXDevice );
|
||||
|
||||
// Samples the Xbox controllers
|
||||
void PollXDevices( void );
|
||||
|
||||
// Samples an Xbox controller and queues input events
|
||||
void ReadXDevice( xdevice_t* pXDevice );
|
||||
|
||||
// Submits force feedback data to an Xbox controller
|
||||
void WriteToXDevice( xdevice_t* pXDevice );
|
||||
|
||||
// Sets rumble values for an Xbox controller
|
||||
void SetXDeviceRumble( float fLeftMotor, float fRightMotor, int userId );
|
||||
|
||||
// Posts an Xbox key event, ignoring key repeats
|
||||
void PostXKeyEvent( int nUserId, xKey_t xKey, int nSample );
|
||||
|
||||
// Dispatches all joystick button events through the game's window procs
|
||||
void ProcessEvent( UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
// Initializes joysticks
|
||||
void InitializeJoysticks( void );
|
||||
|
||||
// Shut down joysticks
|
||||
void ShutdownJoysticks( void );
|
||||
|
||||
// Samples the joystick
|
||||
void PollJoystick( void );
|
||||
|
||||
// Update the joystick button state
|
||||
void UpdateJoystickButtonState( int nJoystick );
|
||||
|
||||
// Update the joystick POV control
|
||||
void UpdateJoystickPOVControl( int nJoystick );
|
||||
|
||||
// Record button state and post the event
|
||||
void JoystickButtonEvent( ButtonCode_t button, int sample );
|
||||
|
||||
#if defined( WIN32 ) && !defined ( _X360 )
|
||||
// NVNT attaches window to novint devices
|
||||
void AttachWindowToNovintDevices( void * hWnd );
|
||||
|
||||
// NVNT detaches window from novint input
|
||||
void DetachWindowFromNovintDevices( void );
|
||||
|
||||
// NVNT Initializes novint devices
|
||||
void InitializeNovintDevices( void );
|
||||
|
||||
// NVNT Samples a novint device
|
||||
void PollNovintDevices( void );
|
||||
|
||||
// NVNT Update the novint device button state
|
||||
void UpdateNovintDeviceButtonState( int nDevice );
|
||||
|
||||
// NVNT Record button state and post the event
|
||||
void NovintDeviceButtonEvent( ButtonCode_t button, int sample );
|
||||
|
||||
//Added called and set to true when binding input and set to false once bound
|
||||
void SetNovintPure( bool bPure );
|
||||
#else
|
||||
void SetNovintPure( bool bPure ) {} // to satify the IInput virtual interface
|
||||
#endif
|
||||
// Chains the window message to the previous wndproc
|
||||
LRESULT ChainWindowMessage( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
// Post an event to the queue
|
||||
void PostEvent( int nType, int nTick, int nData = 0, int nData2 = 0, int nData3 = 0 );
|
||||
|
||||
// Deals with app deactivation (sends a bunch of button released messages)
|
||||
void ActivateInputSystem( bool bActivated );
|
||||
|
||||
// Determines all mouse button presses
|
||||
int ButtonMaskFromMouseWParam( WPARAM wParam, ButtonCode_t code = BUTTON_CODE_INVALID, bool bDown = false ) const;
|
||||
|
||||
// Updates the state of all mouse buttons
|
||||
void UpdateMouseButtonState( int nButtonMask, ButtonCode_t dblClickCode = BUTTON_CODE_INVALID );
|
||||
|
||||
// Copies the input state record over
|
||||
void CopyInputState( InputState_t *pDest, const InputState_t &src, bool bCopyEvents );
|
||||
|
||||
// Post an button press/release event to the queue
|
||||
void PostButtonPressedEvent( InputEventType_t nType, int nTick, ButtonCode_t scanCode, ButtonCode_t virtualCode );
|
||||
void PostButtonReleasedEvent( InputEventType_t nType, int nTick, ButtonCode_t scanCode, ButtonCode_t virtualCode );
|
||||
|
||||
// Release all buttons
|
||||
void ReleaseAllButtons( int nFirstButton = 0, int nLastButton = BUTTON_CODE_LAST - 1 );
|
||||
|
||||
// Zero analog state
|
||||
void ZeroAnalogState( int nFirstState, int nLastState );
|
||||
|
||||
// Converts xbox keys to button codes
|
||||
ButtonCode_t XKeyToButtonCode( int nUserId, int nXKey ) const;
|
||||
|
||||
// Computes the sample tick
|
||||
int ComputeSampleTick();
|
||||
|
||||
// Clears the input state, doesn't generate key-up messages
|
||||
void ClearInputState();
|
||||
|
||||
// Called for mouse move events. Sets the current x and y and posts events for the mouse moving.
|
||||
void UpdateMousePositionState( InputState_t &state, short x, short y );
|
||||
|
||||
// Initializes SteamControllers - Returns true if steam is running and finds controllers, otherwise false
|
||||
bool InitializeSteamControllers( void );
|
||||
|
||||
// Returns number of connected Steam Controllers
|
||||
uint32 GetNumSteamControllersConnected();
|
||||
|
||||
// Update and sample steam controllers
|
||||
void PollSteamControllers( void );
|
||||
|
||||
#if defined( PLATFORM_WINDOWS_PC )
|
||||
void PollInputState_Windows();
|
||||
#endif
|
||||
|
||||
void JoystickHotplugAdded( int joystickIndex );
|
||||
void JoystickHotplugRemoved( int joystickId );
|
||||
void JoystickButtonPress( int joystickId, int button ); // button is a SDL_CONTROLLER_BUTTON;
|
||||
void JoystickButtonRelease( int joystickId, int button ); // same as above.
|
||||
void JoystickAxisMotion( int joystickId, int axis, int value );
|
||||
|
||||
// Steam Controller
|
||||
void ReadSteamController( int iIndex );
|
||||
void PostKeyEvent( int iIndex, sKey_t sKey, int nSample );
|
||||
const int GetSteamPadDeadZone( ESteamPadAxis axis );
|
||||
bool IsSteamControllerConnected( void ) { return m_bSteamController; }
|
||||
bool IsSteamControllerActive( void );
|
||||
void ActivateSteamControllerActionSetForSlot( uint64 nSlot, GameActionSet_t eActionSet );
|
||||
ControllerActionSetHandle_t GetActionSetHandle( GameActionSet_t eActionSet );
|
||||
ControllerActionSetHandle_t GetActionSetHandle( const char* szActionSet );
|
||||
bool GetControllerStateForSlot( int nSlot );
|
||||
int GetSteamControllerIndexForSlot( int nSlot );
|
||||
bool GetRadialMenuStickValues( int nSlot, float &fX, float &fY );
|
||||
virtual ISteamController* SteamControllerInterface();
|
||||
bool InitializeSteamControllerActionSets();
|
||||
|
||||
// Gets the action origin (i.e. which physical input) maps to the given action name
|
||||
virtual EControllerActionOrigin GetSteamControllerActionOrigin( const char* action, GameActionSet_t action_set );
|
||||
virtual EControllerActionOrigin GetSteamControllerActionOrigin( const char* action, ControllerActionSetHandle_t action_set_handle );
|
||||
|
||||
// Maps a Steam Controller action origin to a string (consisting of a single character) in our SC icon font
|
||||
virtual const wchar_t* GetSteamControllerFontCharacterForActionOrigin( EControllerActionOrigin origin );
|
||||
|
||||
// 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.
|
||||
virtual const wchar_t* GetSteamControllerDescriptionForActionOrigin( EControllerActionOrigin origin );
|
||||
|
||||
// Converts SteamController keys to button codes
|
||||
ButtonCode_t SKeyToButtonCode( int nUserId, int nXKey ) const;
|
||||
|
||||
// This is called with "true" by dedicated server initialization (before calling Init) in order to
|
||||
// force us to skip initialization of Steam (which messes up dedicated servers).
|
||||
virtual void SetSkipControllerInitialization( bool bSkip )
|
||||
{
|
||||
m_bSkipControllerInitialization = bSkip;
|
||||
}
|
||||
|
||||
#if defined( USE_SDL )
|
||||
void PollInputState_Platform();
|
||||
|
||||
ILauncherMgr *m_pLauncherMgr;
|
||||
#endif
|
||||
|
||||
WNDPROC m_ChainedWndProc;
|
||||
HWND m_hAttachedHWnd;
|
||||
bool m_bEnabled;
|
||||
bool m_bPumpEnabled;
|
||||
bool m_bIsPolling;
|
||||
|
||||
// Current button state
|
||||
InputState_t m_InputState[INPUT_STATE_COUNT];
|
||||
|
||||
// Current action set
|
||||
GameActionSet_t m_currentActionSet[STEAM_CONTROLLER_MAX_COUNT];
|
||||
|
||||
DWORD m_StartupTimeTick;
|
||||
int m_nLastPollTick;
|
||||
int m_nLastSampleTick;
|
||||
int m_nPollCount;
|
||||
|
||||
// Mouse wheel hack
|
||||
UINT m_uiMouseWheel;
|
||||
|
||||
// Joystick info
|
||||
CUtlFlags<unsigned short> m_JoysticksEnabled;
|
||||
int m_nJoystickCount;
|
||||
bool m_bJoystickInitialized;
|
||||
bool m_bXController;
|
||||
JoystickInfo_t m_pJoystickInfo[ MAX_JOYSTICKS ];
|
||||
|
||||
// Steam Controller
|
||||
struct steampad_t
|
||||
{
|
||||
steampad_t()
|
||||
{
|
||||
m_nHardwareIndex = 0;
|
||||
m_nJoystickIndex = INVALID_USER_ID;
|
||||
m_nLastPacketIndex = 0;
|
||||
active = false;
|
||||
memset( lastAnalogKeys, 0, sizeof( lastAnalogKeys ) );
|
||||
}
|
||||
bool active;
|
||||
|
||||
sKey_t lastAnalogKeys[MAX_STEAMPADAXIS];
|
||||
appKey_t m_appSKeys[SK_MAX_KEYS];
|
||||
// Hardware index and joystick index don't necessarily match
|
||||
// Joystick index will depend on the order of multiple initialized devices
|
||||
// Which could include other controller types
|
||||
// Hardware index should line up 1:1 with the order they're polled
|
||||
// and could change based on removing devices, unlike Joystick Index
|
||||
uint32 m_nHardwareIndex;
|
||||
int m_nJoystickIndex;
|
||||
uint32 m_nLastPacketIndex;
|
||||
};
|
||||
|
||||
float m_pRadialMenuStickVal[STEAM_CONTROLLER_MAX_COUNT][2];
|
||||
steampad_t m_Device[STEAM_CONTROLLER_MAX_COUNT];
|
||||
uint32 m_unNumConnected;
|
||||
float m_flLastSteamControllerInput;
|
||||
int m_nJoystickBaseline;
|
||||
int m_nControllerType[MAX_JOYSTICKS+STEAM_CONTROLLER_MAX_COUNT];
|
||||
|
||||
bool m_bSteamController; // true if the Steam Controller system has been initialized successfully (this doesn't mean one is actually connected necessarily)
|
||||
bool m_bSteamControllerActionsInitialized; // true if our action sets and handles were successfully initialized (this doesn't mean a controller is necessarily connected, or that in-game client actions were initialized)
|
||||
bool m_bSteamControllerActive; // true if our action sets and handles were successfully initialized *and* that at least one controller is actually connected and switched on.
|
||||
|
||||
#if defined( WIN32 ) && !defined ( _X360 )
|
||||
// NVNT Novint device info
|
||||
int m_nNovintDeviceCount;
|
||||
bool m_bNovintDevices;
|
||||
#endif
|
||||
|
||||
// Xbox controller info
|
||||
appKey_t m_appXKeys[ XUSER_MAX_COUNT ][ XK_MAX_KEYS ];
|
||||
xdevice_t m_XDevices[ XUSER_MAX_COUNT ];
|
||||
int m_PrimaryUserId;
|
||||
|
||||
// raw mouse input
|
||||
bool m_bRawInputSupported;
|
||||
int m_mouseRawAccumX, m_mouseRawAccumY;
|
||||
|
||||
// For the 'SleepUntilInput' feature
|
||||
HANDLE m_hEvent;
|
||||
|
||||
CSysModule *m_pXInputDLL;
|
||||
CSysModule *m_pRawInputDLL;
|
||||
|
||||
#if defined( WIN32 ) && !defined ( _X360 )
|
||||
// NVNT falcon module
|
||||
CSysModule *m_pNovintDLL;
|
||||
#endif
|
||||
|
||||
bool m_bConsoleTextMode;
|
||||
|
||||
public:
|
||||
// Steam API context for use by input system for access to steam controllers.
|
||||
CSteamAPIContext& SteamAPIContext() { return m_SteamAPIContext; }
|
||||
|
||||
private:
|
||||
CSteamAPIContext m_SteamAPIContext;
|
||||
bool m_bSkipControllerInitialization;
|
||||
};
|
||||
|
||||
#endif // INPUTSYSTEM_H
|
||||
@@ -0,0 +1,55 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// INPUTSYSTEM.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$macro SRCDIR ".."
|
||||
$Macro OUTBINDIR "$SRCDIR\..\game\bin"
|
||||
|
||||
$include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$AdditionalIncludeDirectories "$BASE;$SRCDIR\thirdparty\SDL2" [!$SDL] // If $SDL, then we already have this from source_video_base.vpc.
|
||||
$PreprocessorDefinitions "$BASE;VERSION_SAFE_STEAM_API_INTERFACES"
|
||||
}
|
||||
$Linker
|
||||
{
|
||||
$SystemLibraries "iconv" [$OSXALL]
|
||||
$SystemFrameworks "IOKit;Carbon;ForceFeedback"
|
||||
}
|
||||
}
|
||||
|
||||
$Project "inputsystem"
|
||||
{
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$File "inputsystem.cpp"
|
||||
$File "inputsystem.h"
|
||||
$File "joystick_sdl.cpp"
|
||||
$File "novint.cpp" [$WIN32]
|
||||
$File "key_translation.cpp"
|
||||
$File "key_translation.h"
|
||||
$File "steamcontroller.cpp"
|
||||
}
|
||||
|
||||
$Folder "Public Headers"
|
||||
{
|
||||
$File "$SRCDIR\public\inputsystem\AnalogCode.h"
|
||||
$File "$SRCDIR\public\inputsystem\ButtonCode.h"
|
||||
$File "$SRCDIR\public\inputsystem\iinputsystem.h"
|
||||
$File "$SRCDIR\public\inputsystem\InputEnums.h"
|
||||
$File "$SRCDIR\dx9sdk\include\xinput.h" [$WIN32]
|
||||
}
|
||||
|
||||
$Folder "Link Libraries"
|
||||
{
|
||||
$Lib tier1
|
||||
$Lib tier2
|
||||
$ImpLib SDL2
|
||||
$Implib "steam_api" [($WIN32||$WIN64||$POSIX||$PS3)&&!$NO_STEAM]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,615 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Linux Joystick implementation for inputsystem.dll
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
/* For force feedback testing. */
|
||||
#include "inputsystem.h"
|
||||
#include "tier1/convar.h"
|
||||
#include "tier0/icommandline.h"
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_gamecontroller.h"
|
||||
#include "SDL_haptic.h"
|
||||
|
||||
// NOTE: This has to be the last file included!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
static ButtonCode_t ControllerButtonToButtonCode( SDL_GameControllerButton button );
|
||||
static AnalogCode_t ControllerAxisToAnalogCode( SDL_GameControllerAxis axis );
|
||||
static int JoystickSDLWatcher( void *userInfo, SDL_Event *event );
|
||||
|
||||
ConVar joy_axisbutton_threshold( "joy_axisbutton_threshold", "0.3", FCVAR_ARCHIVE, "Analog axis range before a button press is registered." );
|
||||
ConVar joy_axis_deadzone( "joy_axis_deadzone", "0.2", FCVAR_ARCHIVE, "Dead zone near the zero point to not report movement." );
|
||||
|
||||
static void joy_active_changed_f( IConVar *var, const char *pOldValue, float flOldValue );
|
||||
ConVar joy_active( "joy_active", "-1", FCVAR_NONE, "Which of the connected joysticks / gamepads to use (-1 means first found)", &joy_active_changed_f);
|
||||
|
||||
static void joy_gamecontroller_config_changed_f( IConVar *var, const char *pOldValue, float flOldValue );
|
||||
ConVar joy_gamecontroller_config( "joy_gamecontroller_config", "", FCVAR_ARCHIVE, "Game controller mapping (passed to SDL with SDL_HINT_GAMECONTROLLERCONFIG), can also be configured in Steam Big Picture mode.", &joy_gamecontroller_config_changed_f );
|
||||
|
||||
void SearchForDevice()
|
||||
{
|
||||
int newJoystickId = joy_active.GetInt();
|
||||
CInputSystem *pInputSystem = (CInputSystem *)g_pInputSystem;
|
||||
|
||||
if ( !pInputSystem )
|
||||
{
|
||||
return;
|
||||
}
|
||||
// -1 means "first available."
|
||||
if ( newJoystickId < 0 )
|
||||
{
|
||||
pInputSystem->JoystickHotplugAdded(0);
|
||||
return;
|
||||
}
|
||||
|
||||
for ( int device_index = 0; device_index < SDL_NumJoysticks(); ++device_index )
|
||||
{
|
||||
SDL_Joystick *joystick = SDL_JoystickOpen(device_index);
|
||||
if ( joystick == NULL )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int joystickId = SDL_JoystickInstanceID(joystick);
|
||||
SDL_JoystickClose(joystick);
|
||||
|
||||
if ( joystickId == newJoystickId )
|
||||
{
|
||||
pInputSystem->JoystickHotplugAdded(device_index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Switch our active joystick to another device
|
||||
//---------------------------------------------------------------------------------------
|
||||
void joy_active_changed_f( IConVar *var, const char *pOldValue, float flOldValue )
|
||||
{
|
||||
SearchForDevice();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------
|
||||
// Reinitialize the game controller layer when the joy_gamecontroller_config is updated.
|
||||
//---------------------------------------------------------------------------------------
|
||||
void joy_gamecontroller_config_changed_f( IConVar *var, const char *pOldValue, float flOldValue )
|
||||
{
|
||||
CInputSystem *pInputSystem = (CInputSystem *)g_pInputSystem;
|
||||
if ( pInputSystem && SDL_WasInit(SDL_INIT_GAMECONTROLLER) )
|
||||
{
|
||||
bool oldValuePresent = pOldValue && ( strlen( pOldValue ) > 0 );
|
||||
bool newValuePresent = ( strlen( joy_gamecontroller_config.GetString() ) > 0 );
|
||||
if ( !oldValuePresent && !newValuePresent )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to reinitialize the whole thing (i.e. undo CInputSystem::InitializeJoysticks and then call it again)
|
||||
// due to SDL_GameController only reading the SDL_HINT_GAMECONTROLLERCONFIG on init.
|
||||
pInputSystem->ShutdownJoysticks();
|
||||
pInputSystem->InitializeJoysticks();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Handle the events coming from the GameController SDL subsystem.
|
||||
//-----------------------------------------------------------------------------
|
||||
int JoystickSDLWatcher( void *userInfo, SDL_Event *event )
|
||||
{
|
||||
CInputSystem *pInputSystem = (CInputSystem *)userInfo;
|
||||
Assert(pInputSystem != NULL);
|
||||
Assert(event != NULL);
|
||||
|
||||
if ( event == NULL || pInputSystem == NULL )
|
||||
{
|
||||
Warning("No input system\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch ( event->type )
|
||||
{
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
case SDL_CONTROLLERDEVICEREMOVED:
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
// This is executed on the same thread as SDL_PollEvent, as PollEvent
|
||||
// updates the joystick subsystem, which then calls SDL_PushEvent for
|
||||
// the various events below. PushEvent invokes this callback.
|
||||
// SDL_PollEvent is called in PumpWindowsMessageLoop which is coming
|
||||
// from PollInputState_Linux, so there's no worry about calling
|
||||
// PostEvent (which doesn't seem to be thread safe) from other threads.
|
||||
Assert(ThreadInMainThread());
|
||||
|
||||
switch ( event->type )
|
||||
{
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
{
|
||||
pInputSystem->JoystickAxisMotion(event->caxis.which, event->caxis.axis, event->caxis.value);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
pInputSystem->JoystickButtonPress(event->cbutton.which, event->cbutton.button);
|
||||
break;
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
pInputSystem->JoystickButtonRelease(event->cbutton.which, event->cbutton.button);
|
||||
break;
|
||||
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
pInputSystem->JoystickHotplugAdded(event->cdevice.which);
|
||||
break;
|
||||
case SDL_CONTROLLERDEVICEREMOVED:
|
||||
pInputSystem->JoystickHotplugRemoved(event->cdevice.which);
|
||||
SearchForDevice();
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Initialize all joysticks
|
||||
//-----------------------------------------------------------------------------
|
||||
void CInputSystem::InitializeJoysticks( void )
|
||||
{
|
||||
if ( m_bJoystickInitialized )
|
||||
{
|
||||
ShutdownJoysticks();
|
||||
}
|
||||
|
||||
// assume no joystick
|
||||
m_nJoystickCount = 0;
|
||||
memset( m_pJoystickInfo, 0, sizeof( m_pJoystickInfo ) );
|
||||
for ( int i = 0; i < MAX_JOYSTICKS; ++i )
|
||||
{
|
||||
m_pJoystickInfo[ i ].m_nDeviceId = -1;
|
||||
}
|
||||
|
||||
// abort startup if user requests no joystick
|
||||
if ( CommandLine()->FindParm("-nojoy") ) return;
|
||||
|
||||
const char *controllerConfig = joy_gamecontroller_config.GetString();
|
||||
if ( strlen(controllerConfig) > 0 )
|
||||
{
|
||||
DevMsg("Passing joy_gamecontroller_config to SDL ('%s').\n", controllerConfig);
|
||||
// We need to pass this hint to SDL *before* we init the gamecontroller subsystem, otherwise it gets ignored.
|
||||
SDL_SetHint(SDL_HINT_GAMECONTROLLERCONFIG, controllerConfig);
|
||||
}
|
||||
|
||||
if ( SDL_InitSubSystem( SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC ) == -1 )
|
||||
{
|
||||
Warning("Joystick init failed -- SDL_Init(SDL_INIT_GAMECONTROLLER|SDL_INIT_HAPTIC) failed: %s.\n", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
m_bJoystickInitialized = true;
|
||||
|
||||
SDL_AddEventWatch(JoystickSDLWatcher, this);
|
||||
|
||||
const int totalSticks = SDL_NumJoysticks();
|
||||
for ( int i = 0; i < totalSticks; i++ )
|
||||
{
|
||||
if ( SDL_IsGameController(i) )
|
||||
{
|
||||
JoystickHotplugAdded(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_JoystickGUID joyGUID = SDL_JoystickGetDeviceGUID(i);
|
||||
char szGUID[sizeof(joyGUID.data)*2 + 1];
|
||||
SDL_JoystickGetGUIDString(joyGUID, szGUID, sizeof(szGUID));
|
||||
|
||||
Msg("Found joystick '%s' (%s), but no recognized controller configuration for it.\n", SDL_JoystickNameForIndex(i), szGUID);
|
||||
}
|
||||
}
|
||||
|
||||
if ( totalSticks < 1 )
|
||||
{
|
||||
Msg("Did not detect any valid joysticks.\n");
|
||||
}
|
||||
}
|
||||
|
||||
void CInputSystem::ShutdownJoysticks()
|
||||
{
|
||||
if ( !m_bJoystickInitialized )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_DelEventWatch( JoystickSDLWatcher, this );
|
||||
if ( m_pJoystickInfo[ 0 ].m_pDevice != NULL )
|
||||
{
|
||||
JoystickHotplugRemoved( m_pJoystickInfo[ 0 ].m_nDeviceId );
|
||||
}
|
||||
SDL_QuitSubSystem( SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC );
|
||||
|
||||
m_bJoystickInitialized = false;
|
||||
}
|
||||
|
||||
// Update the joy_xcontroller_found convar to force CInput::JoyStickMove to re-exec 360controller-linux.cfg
|
||||
static void SetJoyXControllerFound( bool found )
|
||||
{
|
||||
static ConVarRef xcontrollerVar( "joy_xcontroller_found" );
|
||||
static ConVarRef joystickVar( "joystick" );
|
||||
if ( xcontrollerVar.IsValid() )
|
||||
{
|
||||
xcontrollerVar.SetValue(found);
|
||||
}
|
||||
|
||||
if ( found && joystickVar.IsValid() )
|
||||
{
|
||||
joystickVar.SetValue(true);
|
||||
}
|
||||
}
|
||||
|
||||
void CInputSystem::JoystickHotplugAdded( int joystickIndex )
|
||||
{
|
||||
// SDL_IsGameController doesn't bounds check its inputs.
|
||||
if ( joystickIndex < 0 || joystickIndex >= SDL_NumJoysticks() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !SDL_IsGameController(joystickIndex) )
|
||||
{
|
||||
Warning("Joystick is not recognized by the game controller system. You can configure the controller in Steam Big Picture mode.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Joystick *joystick = SDL_JoystickOpen(joystickIndex);
|
||||
if ( joystick == NULL )
|
||||
{
|
||||
Warning("Could not open joystick %i: %s", joystickIndex, SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
int joystickId = SDL_JoystickInstanceID(joystick);
|
||||
SDL_JoystickClose(joystick);
|
||||
|
||||
int activeJoystick = joy_active.GetInt();
|
||||
JoystickInfo_t& info = m_pJoystickInfo[ 0 ];
|
||||
if ( activeJoystick < 0 )
|
||||
{
|
||||
// Only opportunistically open devices if we don't have one open already.
|
||||
if ( info.m_nDeviceId != -1 )
|
||||
{
|
||||
Msg("Detected supported joystick #%i '%s'. Currently active joystick is #%i.\n", joystickId, SDL_JoystickNameForIndex(joystickIndex), info.m_nDeviceId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if ( activeJoystick != joystickId )
|
||||
{
|
||||
Msg("Detected supported joystick #%i '%s'. Currently active joystick is #%i.\n", joystickId, SDL_JoystickNameForIndex(joystickIndex), activeJoystick);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( info.m_nDeviceId != -1 )
|
||||
{
|
||||
// Don't try to open the device we already have open.
|
||||
if ( info.m_nDeviceId == joystickId )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DevMsg("Joystick #%i already initialized, removing it first.\n", info.m_nDeviceId);
|
||||
JoystickHotplugRemoved(info.m_nDeviceId);
|
||||
}
|
||||
|
||||
Msg("Initializing joystick #%i and making it active.\n", joystickId);
|
||||
|
||||
SDL_GameController *controller = SDL_GameControllerOpen(joystickIndex);
|
||||
if ( controller == NULL )
|
||||
{
|
||||
Warning("Failed to open joystick %i: %s\n", joystickId, SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX: This will fail if this is a *real* hotplug event (and not coming from the initial InitializeJoysticks call).
|
||||
// That's because the SDL haptic subsystem currently doesn't do hotplugging. Everything but haptics will work fine.
|
||||
SDL_Haptic *haptic = SDL_HapticOpenFromJoystick(SDL_GameControllerGetJoystick(controller));
|
||||
if ( haptic == NULL || SDL_HapticRumbleInit(haptic) != 0 )
|
||||
{
|
||||
Warning("Unable to initialize rumble for joystick #%i: %s\n", joystickId, SDL_GetError());
|
||||
haptic = NULL;
|
||||
}
|
||||
|
||||
info.m_pDevice = controller;
|
||||
info.m_pHaptic = haptic;
|
||||
info.m_nDeviceId = SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(controller));
|
||||
info.m_nButtonCount = SDL_CONTROLLER_BUTTON_MAX;
|
||||
info.m_bRumbleEnabled = false;
|
||||
|
||||
SetJoyXControllerFound(true);
|
||||
EnableJoystickInput(0, true);
|
||||
m_nJoystickCount = 1;
|
||||
m_bXController = true;
|
||||
|
||||
// We reset joy_active to -1 because joystick ids are never reused - until you restart.
|
||||
// Setting it to -1 means that you get expected hotplugging behavior if you disconnect the current joystick.
|
||||
joy_active.SetValue(-1);
|
||||
}
|
||||
|
||||
void CInputSystem::JoystickHotplugRemoved( int joystickId )
|
||||
{
|
||||
JoystickInfo_t& info = m_pJoystickInfo[ 0 ];
|
||||
if ( info.m_nDeviceId != joystickId )
|
||||
{
|
||||
DevMsg("Ignoring hotplug remove for #%i, active joystick is #%i.\n", joystickId, info.m_nDeviceId);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( info.m_pDevice == NULL )
|
||||
{
|
||||
info.m_nDeviceId = -1;
|
||||
DevMsg("Got hotplug remove event for removed joystick #%i, ignoring.\n", joystickId);
|
||||
return;
|
||||
}
|
||||
|
||||
m_nJoystickCount = 0;
|
||||
m_bXController = false;
|
||||
EnableJoystickInput(0, false);
|
||||
SetJoyXControllerFound(false);
|
||||
|
||||
SDL_HapticClose((SDL_Haptic *)info.m_pHaptic);
|
||||
SDL_GameControllerClose((SDL_GameController *)info.m_pDevice);
|
||||
|
||||
info.m_pHaptic = NULL;
|
||||
info.m_pDevice = NULL;
|
||||
info.m_nButtonCount = 0;
|
||||
info.m_nDeviceId = -1;
|
||||
info.m_bRumbleEnabled = false;
|
||||
|
||||
Msg("Joystick %i removed.\n", joystickId);
|
||||
}
|
||||
|
||||
void CInputSystem::JoystickButtonPress( int joystickId, int button )
|
||||
{
|
||||
JoystickInfo_t& info = m_pJoystickInfo[ 0 ];
|
||||
if ( info.m_nDeviceId != joystickId )
|
||||
{
|
||||
Warning("Not active device input system (%i x %i)\n", info.m_nDeviceId, joystickId);
|
||||
return;
|
||||
}
|
||||
|
||||
ButtonCode_t buttonCode = ControllerButtonToButtonCode((SDL_GameControllerButton)button);
|
||||
PostButtonPressedEvent(IE_ButtonPressed, m_nLastSampleTick, buttonCode, buttonCode);
|
||||
}
|
||||
|
||||
void CInputSystem::JoystickButtonRelease( int joystickId, int button )
|
||||
{
|
||||
JoystickInfo_t& info = m_pJoystickInfo[ 0 ];
|
||||
if ( info.m_nDeviceId != joystickId )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ButtonCode_t buttonCode = ControllerButtonToButtonCode((SDL_GameControllerButton)button);
|
||||
PostButtonReleasedEvent(IE_ButtonReleased, m_nLastSampleTick, buttonCode, buttonCode);
|
||||
}
|
||||
|
||||
|
||||
void CInputSystem::JoystickAxisMotion( int joystickId, int axis, int value )
|
||||
{
|
||||
JoystickInfo_t& info = m_pJoystickInfo[ 0 ];
|
||||
if ( info.m_nDeviceId != joystickId )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AnalogCode_t code = ControllerAxisToAnalogCode((SDL_GameControllerAxis)axis);
|
||||
if ( code == ANALOG_CODE_INVALID )
|
||||
{
|
||||
Warning("Invalid code for axis %i\n", axis);
|
||||
return;
|
||||
}
|
||||
|
||||
ButtonCode_t buttonCode = BUTTON_CODE_NONE;
|
||||
switch ( axis )
|
||||
{
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
|
||||
buttonCode = KEY_XBUTTON_RTRIGGER;
|
||||
break;
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
|
||||
buttonCode = KEY_XBUTTON_LTRIGGER;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( buttonCode != BUTTON_CODE_NONE )
|
||||
{
|
||||
int pressThreshold = joy_axisbutton_threshold.GetFloat() * 32767;
|
||||
int keyIndex = buttonCode - KEY_XBUTTON_LTRIGGER;
|
||||
Assert( keyIndex < ARRAYSIZE( m_appXKeys[0] ) && keyIndex >= 0 );
|
||||
|
||||
appKey_t &key = m_appXKeys[0][keyIndex];
|
||||
if ( value > pressThreshold )
|
||||
{
|
||||
if ( key.repeats < 1 )
|
||||
{
|
||||
PostButtonPressedEvent( IE_ButtonPressed, m_nLastSampleTick, buttonCode, buttonCode );
|
||||
}
|
||||
key.repeats++;
|
||||
}
|
||||
else
|
||||
{
|
||||
PostButtonReleasedEvent( IE_ButtonReleased, m_nLastSampleTick, buttonCode, buttonCode );
|
||||
key.repeats = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int minValue = joy_axis_deadzone.GetFloat() * 32767;
|
||||
if ( abs(value) < minValue )
|
||||
{
|
||||
value = 0;
|
||||
}
|
||||
|
||||
InputState_t& state = m_InputState[ m_bIsPolling ];
|
||||
state.m_pAnalogDelta[ code ] = value - state.m_pAnalogValue[ code ];
|
||||
state.m_pAnalogValue[ code ] = value;
|
||||
if ( state.m_pAnalogDelta[ code ] != 0 )
|
||||
{
|
||||
PostEvent(IE_AnalogValueChanged, m_nLastSampleTick, code, value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Process the event
|
||||
//-----------------------------------------------------------------------------
|
||||
void CInputSystem::JoystickButtonEvent( ButtonCode_t button, int sample )
|
||||
{
|
||||
// Not used - we post button events from JoystickButtonPress/Release.
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Update the joystick button state
|
||||
//-----------------------------------------------------------------------------
|
||||
void CInputSystem::UpdateJoystickButtonState( int nJoystick )
|
||||
{
|
||||
// We don't sample - we get events posted by SDL_GameController in JoystickSDLWatcher
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Update the joystick POV control
|
||||
//-----------------------------------------------------------------------------
|
||||
void CInputSystem::UpdateJoystickPOVControl( int nJoystick )
|
||||
{
|
||||
// SDL GameController does not support joystick POV. Should we poll?
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sample the joystick
|
||||
//-----------------------------------------------------------------------------
|
||||
void CInputSystem::PollJoystick( void )
|
||||
{
|
||||
// We only pump the SDL event loop if we're not an SDL app, since otherwise PollInputState_Platform calls into CSDLMgr to pump it.
|
||||
// Our state updates happen in events posted by SDL_GameController in JoystickSDLWatcher, so the loop is empty.
|
||||
#if !defined( USE_SDL )
|
||||
SDL_Event event;
|
||||
int nEventsProcessed = 0;
|
||||
|
||||
SDL_PumpEvents();
|
||||
while ( SDL_PollEvent( &event ) && nEventsProcessed < 100 )
|
||||
{
|
||||
nEventsProcessed++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CInputSystem::SetXDeviceRumble( float fLeftMotor, float fRightMotor, int userId )
|
||||
{
|
||||
JoystickInfo_t& info = m_pJoystickInfo[ 0 ];
|
||||
if ( info.m_nDeviceId < 0 || info.m_pHaptic == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float strength = (fLeftMotor + fRightMotor) / 2.f;
|
||||
static ConVarRef joystickVar( "joystick" );
|
||||
|
||||
// 0f means "stop".
|
||||
bool shouldStop = ( strength < 0.01f );
|
||||
// If they've disabled the gamecontroller in settings, never rumble.
|
||||
if ( !joystickVar.IsValid() || !joystickVar.GetBool() )
|
||||
{
|
||||
shouldStop = true;
|
||||
}
|
||||
|
||||
if ( shouldStop )
|
||||
{
|
||||
if ( info.m_bRumbleEnabled )
|
||||
{
|
||||
SDL_HapticRumbleStop( (SDL_Haptic *)info.m_pHaptic );
|
||||
info.m_bRumbleEnabled = false;
|
||||
info.m_fCurrentRumble = 0.0f;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// If there's little change, then don't change the rumble strength.
|
||||
if ( info.m_bRumbleEnabled && abs(info.m_fCurrentRumble - strength) < 0.01f )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
info.m_bRumbleEnabled = true;
|
||||
info.m_fCurrentRumble = strength;
|
||||
|
||||
if ( SDL_HapticRumblePlay((SDL_Haptic *)info.m_pHaptic, strength, SDL_HAPTIC_INFINITY) != 0 )
|
||||
{
|
||||
Warning("Couldn't play rumble (strength %.1f): %s\n", strength, SDL_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
ButtonCode_t ControllerButtonToButtonCode( SDL_GameControllerButton button )
|
||||
{
|
||||
switch ( button )
|
||||
{
|
||||
case SDL_CONTROLLER_BUTTON_A: // KEY_XBUTTON_A
|
||||
case SDL_CONTROLLER_BUTTON_B: // KEY_XBUTTON_B
|
||||
case SDL_CONTROLLER_BUTTON_X: // KEY_XBUTTON_X
|
||||
case SDL_CONTROLLER_BUTTON_Y: // KEY_XBUTTON_Y
|
||||
return JOYSTICK_BUTTON(0, button);
|
||||
|
||||
case SDL_CONTROLLER_BUTTON_BACK:
|
||||
return KEY_XBUTTON_BACK;
|
||||
case SDL_CONTROLLER_BUTTON_START:
|
||||
return KEY_XBUTTON_START;
|
||||
|
||||
case SDL_CONTROLLER_BUTTON_GUIDE:
|
||||
return KEY_XBUTTON_BACK; // XXX: How are we supposed to handle this? Steam overlay etc.
|
||||
|
||||
case SDL_CONTROLLER_BUTTON_LEFTSTICK:
|
||||
return KEY_XBUTTON_STICK1;
|
||||
case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
|
||||
return KEY_XBUTTON_STICK2;
|
||||
case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
|
||||
return KEY_XBUTTON_LEFT_SHOULDER;
|
||||
case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
|
||||
return KEY_XBUTTON_RIGHT_SHOULDER;
|
||||
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_UP:
|
||||
return KEY_XBUTTON_UP;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
|
||||
return KEY_XBUTTON_DOWN;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
|
||||
return KEY_XBUTTON_LEFT;
|
||||
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
|
||||
return KEY_XBUTTON_RIGHT;
|
||||
}
|
||||
|
||||
return BUTTON_CODE_NONE;
|
||||
}
|
||||
|
||||
AnalogCode_t ControllerAxisToAnalogCode( SDL_GameControllerAxis axis )
|
||||
{
|
||||
switch ( axis )
|
||||
{
|
||||
case SDL_CONTROLLER_AXIS_LEFTX:
|
||||
return JOYSTICK_AXIS(0, JOY_AXIS_X);
|
||||
case SDL_CONTROLLER_AXIS_LEFTY:
|
||||
return JOYSTICK_AXIS(0, JOY_AXIS_Y);
|
||||
|
||||
case SDL_CONTROLLER_AXIS_RIGHTX:
|
||||
return JOYSTICK_AXIS(0, JOY_AXIS_U);
|
||||
case SDL_CONTROLLER_AXIS_RIGHTY:
|
||||
return JOYSTICK_AXIS(0, JOY_AXIS_R);
|
||||
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
|
||||
return JOYSTICK_AXIS(0, JOY_AXIS_Z);
|
||||
}
|
||||
|
||||
return ANALOG_CODE_INVALID;
|
||||
}
|
||||
@@ -0,0 +1,911 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
|
||||
#if defined( WIN32 )
|
||||
#if !defined( _X360 )
|
||||
#include <wtypes.h>
|
||||
#include <winuser.h>
|
||||
#include "xbox/xboxstubs.h"
|
||||
#else
|
||||
#include "xbox/xbox_win32stubs.h"
|
||||
#endif
|
||||
#endif // WIN32
|
||||
|
||||
#include "key_translation.h"
|
||||
#include "tier1/convar.h"
|
||||
#include "tier1/strtools.h"
|
||||
#include "tier0/dbg.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma GCC diagnostic ignored "-Wchar-subscripts"
|
||||
#endif
|
||||
|
||||
static ButtonCode_t s_pVirtualKeyToButtonCode[256];
|
||||
|
||||
static ButtonCode_t s_pSKeytoButtonCode[SK_MAX_KEYS];
|
||||
|
||||
#if !defined( POSIX )
|
||||
static ButtonCode_t s_pXKeyTrans[XK_MAX_KEYS];
|
||||
#endif
|
||||
|
||||
#define SCONTROLLERBUTTONS_BUTTONS( x ) \
|
||||
"SC_A",\
|
||||
"SC_B",\
|
||||
"SC_X",\
|
||||
"SC_Y",\
|
||||
"SC_DPAD_UP",\
|
||||
"SC_DPAD_RIGHT",\
|
||||
"SC_DPAD_DOWN",\
|
||||
"SC_DPAD_LEFT",\
|
||||
"SC_LEFT_BUMPER",\
|
||||
"SC_RIGHT_BUMPER",\
|
||||
"SC_LEFT_TRIGGER",\
|
||||
"SC_RIGHT_TRIGGER",\
|
||||
"SC_LEFT_GRIP",\
|
||||
"SC_RIGHT_GRIP",\
|
||||
"SC_LEFT_PAD_TOUCH",\
|
||||
"SC_RIGHT_PAD_TOUCH",\
|
||||
"SC_LEFT_PAD_CLICK",\
|
||||
"SC_RIGHT_PAD_CLICK",\
|
||||
"SC_LPAD_UP",\
|
||||
"SC_LPAD_RIGHT",\
|
||||
"SC_LPAD_DOWN",\
|
||||
"SC_LPAD_LEFT",\
|
||||
"SC_RPAD_UP",\
|
||||
"SC_RPAD_RIGHT",\
|
||||
"SC_RPAD_DOWN",\
|
||||
"SC_RPAD_LEFT",\
|
||||
"SC_SELECT",\
|
||||
"SC_START",\
|
||||
"SC_STEAM",\
|
||||
"SC_NULL"
|
||||
|
||||
#define SCONTROLLERBUTTONS_AXIS( x ) \
|
||||
"SC_LPAD_AXIS_RIGHT",\
|
||||
"SC_LPAD_AXIS_LEFT",\
|
||||
"SC_LPAD_AXIS_DOWN",\
|
||||
"SC_LPAD_AXIS_UP",\
|
||||
"SC_AXIS_L_TRIGGER",\
|
||||
"SC_AXIS_R_TRIGGER",\
|
||||
"SC_RPAD_AXIS_RIGHT",\
|
||||
"SC_RPAD_AXIS_LEFT",\
|
||||
"SC_RPAD_AXIS_DOWN",\
|
||||
"SC_RPAD_AXIS_UP",\
|
||||
"SC_GYRO_AXIS_PITCH_POSITIVE",\
|
||||
"SC_GYRO_AXIS_PITCH_NEGATIVE",\
|
||||
"SC_GYRO_AXIS_ROLL_POSITIVE",\
|
||||
"SC_GYRO_AXIS_ROLL_NEGATIVE",\
|
||||
"SC_GYRO_AXIS_YAW_POSITIVE",\
|
||||
"SC_GYRO_AXIS_YAW_NEGATIVE"
|
||||
|
||||
#define SCONTROLLERBUTTONS_VBUTTONS( x ) \
|
||||
"SC_F1",\
|
||||
"SC_F2",\
|
||||
"SC_F3",\
|
||||
"SC_F4",\
|
||||
"SC_F5",\
|
||||
"SC_F6",\
|
||||
"SC_F7",\
|
||||
"SC_F8",\
|
||||
"SC_F9",\
|
||||
"SC_F10",\
|
||||
"SC_F11",\
|
||||
"SC_F12"
|
||||
|
||||
static int s_pButtonCodeToVirtual[BUTTON_CODE_LAST];
|
||||
|
||||
static const char *s_pButtonCodeName[ ] =
|
||||
{
|
||||
"", // KEY_NONE
|
||||
"0", // KEY_0,
|
||||
"1", // KEY_1,
|
||||
"2", // KEY_2,
|
||||
"3", // KEY_3,
|
||||
"4", // KEY_4,
|
||||
"5", // KEY_5,
|
||||
"6", // KEY_6,
|
||||
"7", // KEY_7,
|
||||
"8", // KEY_8,
|
||||
"9", // KEY_9,
|
||||
"a", // KEY_A,
|
||||
"b", // KEY_B,
|
||||
"c", // KEY_C,
|
||||
"d", // KEY_D,
|
||||
"e", // KEY_E,
|
||||
"f", // KEY_F,
|
||||
"g", // KEY_G,
|
||||
"h", // KEY_H,
|
||||
"i", // KEY_I,
|
||||
"j", // KEY_J,
|
||||
"k", // KEY_K,
|
||||
"l", // KEY_L,
|
||||
"m", // KEY_M,
|
||||
"n", // KEY_N,
|
||||
"o", // KEY_O,
|
||||
"p", // KEY_P,
|
||||
"q", // KEY_Q,
|
||||
"r", // KEY_R,
|
||||
"s", // KEY_S,
|
||||
"t", // KEY_T,
|
||||
"u", // KEY_U,
|
||||
"v", // KEY_V,
|
||||
"w", // KEY_W,
|
||||
"x", // KEY_X,
|
||||
"y", // KEY_Y,
|
||||
"z", // KEY_Z,
|
||||
"KP_INS", // KEY_PAD_0,
|
||||
"KP_END", // KEY_PAD_1,
|
||||
"KP_DOWNARROW", // KEY_PAD_2,
|
||||
"KP_PGDN", // KEY_PAD_3,
|
||||
"KP_LEFTARROW", // KEY_PAD_4,
|
||||
"KP_5", // KEY_PAD_5,
|
||||
"KP_RIGHTARROW",// KEY_PAD_6,
|
||||
"KP_HOME", // KEY_PAD_7,
|
||||
"KP_UPARROW", // KEY_PAD_8,
|
||||
"KP_PGUP", // KEY_PAD_9,
|
||||
"KP_SLASH", // KEY_PAD_DIVIDE,
|
||||
"KP_MULTIPLY", // KEY_PAD_MULTIPLY,
|
||||
"KP_MINUS", // KEY_PAD_MINUS,
|
||||
"KP_PLUS", // KEY_PAD_PLUS,
|
||||
"KP_ENTER", // KEY_PAD_ENTER,
|
||||
"KP_DEL", // KEY_PAD_DECIMAL,
|
||||
"[", // KEY_LBRACKET,
|
||||
"]", // KEY_RBRACKET,
|
||||
"SEMICOLON", // KEY_SEMICOLON,
|
||||
"'", // KEY_APOSTROPHE,
|
||||
"`", // KEY_BACKQUOTE,
|
||||
",", // KEY_COMMA,
|
||||
".", // KEY_PERIOD,
|
||||
"/", // KEY_SLASH,
|
||||
"\\", // KEY_BACKSLASH,
|
||||
"-", // KEY_MINUS,
|
||||
"=", // KEY_EQUAL,
|
||||
"ENTER", // KEY_ENTER,
|
||||
"SPACE", // KEY_SPACE,
|
||||
"BACKSPACE", // KEY_BACKSPACE,
|
||||
"TAB", // KEY_TAB,
|
||||
"CAPSLOCK", // KEY_CAPSLOCK,
|
||||
"NUMLOCK", // KEY_NUMLOCK,
|
||||
"ESCAPE", // KEY_ESCAPE,
|
||||
"SCROLLLOCK", // KEY_SCROLLLOCK,
|
||||
"INS", // KEY_INSERT,
|
||||
"DEL", // KEY_DELETE,
|
||||
"HOME", // KEY_HOME,
|
||||
"END", // KEY_END,
|
||||
"PGUP", // KEY_PAGEUP,
|
||||
"PGDN", // KEY_PAGEDOWN,
|
||||
"PAUSE", // KEY_BREAK,
|
||||
"SHIFT", // KEY_LSHIFT,
|
||||
"RSHIFT", // KEY_RSHIFT,
|
||||
"ALT", // KEY_LALT,
|
||||
"RALT", // KEY_RALT,
|
||||
"CTRL", // KEY_LCONTROL,
|
||||
"RCTRL", // KEY_RCONTROL,
|
||||
"LWIN", // KEY_LWIN,
|
||||
"RWIN", // KEY_RWIN,
|
||||
"APP", // KEY_APP,
|
||||
"UPARROW", // KEY_UP,
|
||||
"LEFTARROW", // KEY_LEFT,
|
||||
"DOWNARROW", // KEY_DOWN,
|
||||
"RIGHTARROW", // KEY_RIGHT,
|
||||
"F1", // KEY_F1,
|
||||
"F2", // KEY_F2,
|
||||
"F3", // KEY_F3,
|
||||
"F4", // KEY_F4,
|
||||
"F5", // KEY_F5,
|
||||
"F6", // KEY_F6,
|
||||
"F7", // KEY_F7,
|
||||
"F8", // KEY_F8,
|
||||
"F9", // KEY_F9,
|
||||
"F10", // KEY_F10,
|
||||
"F11", // KEY_F11,
|
||||
"F12", // KEY_F12,
|
||||
|
||||
// FIXME: CAPSLOCK/NUMLOCK/SCROLLLOCK all appear above. What are these for?!
|
||||
// They only appear in CInputWin32::UpdateToggleButtonState in vgui2
|
||||
"CAPSLOCKTOGGLE", // KEY_CAPSLOCKTOGGLE,
|
||||
"NUMLOCKTOGGLE", // KEY_NUMLOCKTOGGLE,
|
||||
"SCROLLLOCKTOGGLE", // KEY_SCROLLLOCKTOGGLE,
|
||||
|
||||
// Mouse
|
||||
"MOUSE1", // MOUSE_LEFT,
|
||||
"MOUSE2", // MOUSE_RIGHT,
|
||||
"MOUSE3", // MOUSE_MIDDLE,
|
||||
"MOUSE4", // MOUSE_4,
|
||||
"MOUSE5", // MOUSE_5,
|
||||
|
||||
"MWHEELUP", // MOUSE_WHEEL_UP
|
||||
"MWHEELDOWN", // MOUSE_WHEEL_DOWN
|
||||
|
||||
#if defined ( _X360 ) || defined ( _LINUX )
|
||||
"A_BUTTON", // JOYSTICK_FIRST_BUTTON
|
||||
"B_BUTTON",
|
||||
"X_BUTTON",
|
||||
"Y_BUTTON",
|
||||
"L_SHOULDER",
|
||||
"R_SHOULDER",
|
||||
"BACK",
|
||||
"START",
|
||||
"STICK1",
|
||||
"STICK2",
|
||||
#else
|
||||
"JOY1", // JOYSTICK_FIRST_BUTTON
|
||||
"JOY2",
|
||||
"JOY3",
|
||||
"JOY4",
|
||||
"JOY5",
|
||||
"JOY6",
|
||||
"JOY7",
|
||||
"JOY8",
|
||||
"JOY9",
|
||||
"JOY10",
|
||||
#endif
|
||||
|
||||
"JOY11",
|
||||
"JOY12",
|
||||
"JOY13",
|
||||
"JOY14",
|
||||
"JOY15",
|
||||
"JOY16",
|
||||
"JOY17",
|
||||
"JOY18",
|
||||
"JOY19",
|
||||
"JOY20",
|
||||
"JOY21",
|
||||
"JOY22",
|
||||
"JOY23",
|
||||
"JOY24",
|
||||
"JOY25",
|
||||
"JOY26",
|
||||
"JOY27",
|
||||
"JOY28",
|
||||
"JOY29",
|
||||
"JOY30",
|
||||
"JOY31",
|
||||
"JOY32", // JOYSTICK_LAST_BUTTON
|
||||
|
||||
#if defined ( _X360 )
|
||||
"UP", // JOYSTICK_FIRST_POV_BUTTON
|
||||
"RIGHT",
|
||||
"DOWN",
|
||||
"LEFT", // JOYSTICK_LAST_POV_BUTTON
|
||||
|
||||
"S1_RIGHT", // JOYSTICK_FIRST_AXIS_BUTTON
|
||||
"S1_LEFT",
|
||||
"S1_DOWN",
|
||||
"S1_UP",
|
||||
"L_TRIGGER",
|
||||
"R_TRIGGER",
|
||||
"S2_RIGHT",
|
||||
"S2_LEFT",
|
||||
"S2_DOWN",
|
||||
"S2_UP", // JOYSTICK_LAST_AXIS_BUTTON
|
||||
"V AXIS POS",
|
||||
"V AXIS NEG",
|
||||
#else
|
||||
"POV_UP", // JOYSTICK_FIRST_POV_BUTTON
|
||||
"POV_RIGHT",
|
||||
"POV_DOWN",
|
||||
"POV_LEFT", // JOYSTICK_LAST_POV_BUTTON
|
||||
|
||||
"X AXIS POS", // JOYSTICK_FIRST_AXIS_BUTTON
|
||||
"X AXIS NEG",
|
||||
"Y AXIS POS",
|
||||
"Y AXIS NEG",
|
||||
"Z AXIS POS",
|
||||
"Z AXIS NEG",
|
||||
"R AXIS POS",
|
||||
"R AXIS NEG",
|
||||
"U AXIS POS",
|
||||
"U AXIS NEG",
|
||||
"V AXIS POS",
|
||||
"V AXIS NEG", // JOYSTICK_LAST_AXIS_BUTTON
|
||||
"FALCON_NULL", // NVNT temp Fix for unaligned joystick enumeration
|
||||
"FALCON_1", // NOVINT_FIRST
|
||||
"FALCON_2",
|
||||
"FALCON_3",
|
||||
"FALCON_4",
|
||||
"FALCON2_1",
|
||||
"FALCON2_2",
|
||||
"FALCON2_3",
|
||||
"FALCON2_4", // NOVINT_LAST
|
||||
#endif
|
||||
|
||||
SCONTROLLERBUTTONS_BUTTONS( 0 ),
|
||||
SCONTROLLERBUTTONS_BUTTONS( 1 ),
|
||||
SCONTROLLERBUTTONS_BUTTONS( 2 ),
|
||||
SCONTROLLERBUTTONS_BUTTONS( 3 ),
|
||||
SCONTROLLERBUTTONS_BUTTONS( 4 ),
|
||||
SCONTROLLERBUTTONS_BUTTONS( 5 ),
|
||||
SCONTROLLERBUTTONS_BUTTONS( 6 ),
|
||||
SCONTROLLERBUTTONS_BUTTONS( 7 ),
|
||||
|
||||
SCONTROLLERBUTTONS_AXIS( 0 ),
|
||||
SCONTROLLERBUTTONS_AXIS( 1 ),
|
||||
SCONTROLLERBUTTONS_AXIS( 2 ),
|
||||
SCONTROLLERBUTTONS_AXIS( 3 ),
|
||||
SCONTROLLERBUTTONS_AXIS( 4 ),
|
||||
SCONTROLLERBUTTONS_AXIS( 5 ),
|
||||
SCONTROLLERBUTTONS_AXIS( 6 ),
|
||||
SCONTROLLERBUTTONS_AXIS( 7 ),
|
||||
|
||||
SCONTROLLERBUTTONS_VBUTTONS( 0 ),
|
||||
SCONTROLLERBUTTONS_VBUTTONS( 1 ),
|
||||
SCONTROLLERBUTTONS_VBUTTONS( 2 ),
|
||||
SCONTROLLERBUTTONS_VBUTTONS( 3 ),
|
||||
SCONTROLLERBUTTONS_VBUTTONS( 4 ),
|
||||
SCONTROLLERBUTTONS_VBUTTONS( 5 ),
|
||||
SCONTROLLERBUTTONS_VBUTTONS( 6 ),
|
||||
SCONTROLLERBUTTONS_VBUTTONS( 7 ),
|
||||
};
|
||||
|
||||
static const char *s_pAnalogCodeName[ ] =
|
||||
{
|
||||
"MOUSE_X", // MOUSE_X = 0,
|
||||
"MOUSE_Y", // MOUSE_Y,
|
||||
"MOUSE_XY", // MOUSE_XY, // Invoked when either x or y changes
|
||||
"MOUSE_WHEEL", // MOUSE_WHEEL,
|
||||
|
||||
"X AXIS", // JOY_AXIS_X
|
||||
"Y AXIS", // JOY_AXIS_Y
|
||||
"Z AXIS", // JOY_AXIS_Z
|
||||
"R AXIS", // JOY_AXIS_R
|
||||
"U AXIS", // JOY_AXIS_U
|
||||
"V AXIS", // JOY_AXIS_V
|
||||
};
|
||||
|
||||
#if !defined ( _X360 )
|
||||
static const char *s_pXControllerButtonCodeNames[ ] =
|
||||
{
|
||||
"A_BUTTON", // JOYSTICK_FIRST_BUTTON
|
||||
"B_BUTTON",
|
||||
"X_BUTTON",
|
||||
"Y_BUTTON",
|
||||
"L_SHOULDER",
|
||||
"R_SHOULDER",
|
||||
"BACK",
|
||||
"START",
|
||||
"STICK1",
|
||||
"STICK2",
|
||||
"JOY11",
|
||||
"JOY12",
|
||||
"JOY13",
|
||||
"JOY14",
|
||||
"JOY15",
|
||||
"JOY16",
|
||||
"JOY17",
|
||||
"JOY18",
|
||||
"JOY19",
|
||||
"JOY20",
|
||||
"JOY21",
|
||||
"JOY22",
|
||||
"JOY23",
|
||||
"JOY24",
|
||||
"JOY25",
|
||||
"JOY26",
|
||||
"JOY27",
|
||||
"JOY28",
|
||||
"JOY29",
|
||||
"JOY30",
|
||||
"JOY31",
|
||||
"JOY32", // JOYSTICK_LAST_BUTTON
|
||||
|
||||
"UP", // JOYSTICK_FIRST_POV_BUTTON
|
||||
"RIGHT",
|
||||
"DOWN",
|
||||
"LEFT", // JOYSTICK_LAST_POV_BUTTON
|
||||
|
||||
"S1_RIGHT", // JOYSTICK_FIRST_AXIS_BUTTON
|
||||
"S1_LEFT",
|
||||
"S1_DOWN",
|
||||
"S1_UP",
|
||||
"L_TRIGGER",
|
||||
"R_TRIGGER",
|
||||
"S2_RIGHT",
|
||||
"S2_LEFT",
|
||||
"S2_DOWN",
|
||||
"S2_UP", // JOYSTICK_LAST_AXIS_BUTTON
|
||||
"V AXIS POS",
|
||||
"V AXIS NEG",
|
||||
};
|
||||
#endif
|
||||
|
||||
// this maps non-translated keyboard scan codes to engine key codes
|
||||
// Google for 'Keyboard Scan Code Specification'
|
||||
static ButtonCode_t s_pScanToButtonCode_QWERTY[128] =
|
||||
{
|
||||
// 0 1 2 3 4 5 6 7
|
||||
// 8 9 A B C D E F
|
||||
KEY_NONE, KEY_ESCAPE, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, // 0
|
||||
KEY_7, KEY_8, KEY_9, KEY_0, KEY_MINUS, KEY_EQUAL, KEY_BACKSPACE, KEY_TAB, // 0
|
||||
|
||||
KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, KEY_Y, KEY_U, KEY_I, // 1
|
||||
KEY_O, KEY_P, KEY_LBRACKET, KEY_RBRACKET, KEY_ENTER, KEY_LCONTROL, KEY_A, KEY_S, // 1
|
||||
|
||||
KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON, // 2
|
||||
KEY_APOSTROPHE, KEY_BACKQUOTE, KEY_LSHIFT, KEY_BACKSLASH, KEY_Z, KEY_X, KEY_C, KEY_V, // 2
|
||||
|
||||
KEY_B, KEY_N, KEY_M, KEY_COMMA, KEY_PERIOD, KEY_SLASH, KEY_RSHIFT, KEY_PAD_MULTIPLY,// 3
|
||||
KEY_LALT, KEY_SPACE, KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, // 3
|
||||
|
||||
KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_NUMLOCK, KEY_SCROLLLOCK, KEY_HOME, // 4
|
||||
KEY_UP, KEY_PAGEUP, KEY_PAD_MINUS, KEY_LEFT, KEY_PAD_5, KEY_RIGHT, KEY_PAD_PLUS, KEY_END, // 4
|
||||
|
||||
KEY_DOWN, KEY_PAGEDOWN, KEY_INSERT, KEY_DELETE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_F11, // 5
|
||||
KEY_F12, KEY_BREAK, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, // 5
|
||||
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, // 6
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, // 6
|
||||
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, // 7
|
||||
KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE // 7
|
||||
};
|
||||
|
||||
static ButtonCode_t s_pScanToButtonCode[128];
|
||||
|
||||
|
||||
void ButtonCode_InitKeyTranslationTable()
|
||||
{
|
||||
COMPILE_TIME_ASSERT( sizeof(s_pButtonCodeName) / sizeof( const char * ) == BUTTON_CODE_LAST );
|
||||
COMPILE_TIME_ASSERT( sizeof(s_pAnalogCodeName) / sizeof( const char * ) == ANALOG_CODE_LAST );
|
||||
|
||||
// set virtual key translation table
|
||||
memset( s_pVirtualKeyToButtonCode, KEY_NONE, sizeof(s_pVirtualKeyToButtonCode) );
|
||||
|
||||
s_pVirtualKeyToButtonCode['0'] =KEY_0;
|
||||
s_pVirtualKeyToButtonCode['1'] =KEY_1;
|
||||
s_pVirtualKeyToButtonCode['2'] =KEY_2;
|
||||
s_pVirtualKeyToButtonCode['3'] =KEY_3;
|
||||
s_pVirtualKeyToButtonCode['4'] =KEY_4;
|
||||
s_pVirtualKeyToButtonCode['5'] =KEY_5;
|
||||
s_pVirtualKeyToButtonCode['6'] =KEY_6;
|
||||
s_pVirtualKeyToButtonCode['7'] =KEY_7;
|
||||
s_pVirtualKeyToButtonCode['8'] =KEY_8;
|
||||
s_pVirtualKeyToButtonCode['9'] =KEY_9;
|
||||
s_pVirtualKeyToButtonCode['A'] =KEY_A;
|
||||
s_pVirtualKeyToButtonCode['B'] =KEY_B;
|
||||
s_pVirtualKeyToButtonCode['C'] =KEY_C;
|
||||
s_pVirtualKeyToButtonCode['D'] =KEY_D;
|
||||
s_pVirtualKeyToButtonCode['E'] =KEY_E;
|
||||
s_pVirtualKeyToButtonCode['F'] =KEY_F;
|
||||
s_pVirtualKeyToButtonCode['G'] =KEY_G;
|
||||
s_pVirtualKeyToButtonCode['H'] =KEY_H;
|
||||
s_pVirtualKeyToButtonCode['I'] =KEY_I;
|
||||
s_pVirtualKeyToButtonCode['J'] =KEY_J;
|
||||
s_pVirtualKeyToButtonCode['K'] =KEY_K;
|
||||
s_pVirtualKeyToButtonCode['L'] =KEY_L;
|
||||
s_pVirtualKeyToButtonCode['M'] =KEY_M;
|
||||
s_pVirtualKeyToButtonCode['N'] =KEY_N;
|
||||
s_pVirtualKeyToButtonCode['O'] =KEY_O;
|
||||
s_pVirtualKeyToButtonCode['P'] =KEY_P;
|
||||
s_pVirtualKeyToButtonCode['Q'] =KEY_Q;
|
||||
s_pVirtualKeyToButtonCode['R'] =KEY_R;
|
||||
s_pVirtualKeyToButtonCode['S'] =KEY_S;
|
||||
s_pVirtualKeyToButtonCode['T'] =KEY_T;
|
||||
s_pVirtualKeyToButtonCode['U'] =KEY_U;
|
||||
s_pVirtualKeyToButtonCode['V'] =KEY_V;
|
||||
s_pVirtualKeyToButtonCode['W'] =KEY_W;
|
||||
s_pVirtualKeyToButtonCode['X'] =KEY_X;
|
||||
s_pVirtualKeyToButtonCode['Y'] =KEY_Y;
|
||||
s_pVirtualKeyToButtonCode['Z'] =KEY_Z;
|
||||
#if !defined( POSIX )
|
||||
s_pVirtualKeyToButtonCode[VK_NUMPAD0] =KEY_PAD_0;
|
||||
s_pVirtualKeyToButtonCode[VK_NUMPAD1] =KEY_PAD_1;
|
||||
s_pVirtualKeyToButtonCode[VK_NUMPAD2] =KEY_PAD_2;
|
||||
s_pVirtualKeyToButtonCode[VK_NUMPAD3] =KEY_PAD_3;
|
||||
s_pVirtualKeyToButtonCode[VK_NUMPAD4] =KEY_PAD_4;
|
||||
s_pVirtualKeyToButtonCode[VK_NUMPAD5] =KEY_PAD_5;
|
||||
s_pVirtualKeyToButtonCode[VK_NUMPAD6] =KEY_PAD_6;
|
||||
s_pVirtualKeyToButtonCode[VK_NUMPAD7] =KEY_PAD_7;
|
||||
s_pVirtualKeyToButtonCode[VK_NUMPAD8] =KEY_PAD_8;
|
||||
s_pVirtualKeyToButtonCode[VK_NUMPAD9] =KEY_PAD_9;
|
||||
s_pVirtualKeyToButtonCode[VK_DIVIDE] =KEY_PAD_DIVIDE;
|
||||
s_pVirtualKeyToButtonCode[VK_MULTIPLY] =KEY_PAD_MULTIPLY;
|
||||
s_pVirtualKeyToButtonCode[VK_SUBTRACT] =KEY_PAD_MINUS;
|
||||
s_pVirtualKeyToButtonCode[VK_ADD] =KEY_PAD_PLUS;
|
||||
s_pVirtualKeyToButtonCode[VK_RETURN] =KEY_PAD_ENTER;
|
||||
s_pVirtualKeyToButtonCode[VK_DECIMAL] =KEY_PAD_DECIMAL;
|
||||
#endif
|
||||
s_pVirtualKeyToButtonCode[0xdb] =KEY_LBRACKET;
|
||||
s_pVirtualKeyToButtonCode[0xdd] =KEY_RBRACKET;
|
||||
s_pVirtualKeyToButtonCode[0xba] =KEY_SEMICOLON;
|
||||
s_pVirtualKeyToButtonCode[0xde] =KEY_APOSTROPHE;
|
||||
s_pVirtualKeyToButtonCode[0xc0] =KEY_BACKQUOTE;
|
||||
s_pVirtualKeyToButtonCode[0xbc] =KEY_COMMA;
|
||||
s_pVirtualKeyToButtonCode[0xbe] =KEY_PERIOD;
|
||||
s_pVirtualKeyToButtonCode[0xbf] =KEY_SLASH;
|
||||
s_pVirtualKeyToButtonCode[0xdc] =KEY_BACKSLASH;
|
||||
s_pVirtualKeyToButtonCode[0xbd] =KEY_MINUS;
|
||||
s_pVirtualKeyToButtonCode[0xbb] =KEY_EQUAL;
|
||||
#if !defined( POSIX )
|
||||
s_pVirtualKeyToButtonCode[VK_RETURN] =KEY_ENTER;
|
||||
s_pVirtualKeyToButtonCode[VK_SPACE] =KEY_SPACE;
|
||||
s_pVirtualKeyToButtonCode[VK_BACK] =KEY_BACKSPACE;
|
||||
s_pVirtualKeyToButtonCode[VK_TAB] =KEY_TAB;
|
||||
s_pVirtualKeyToButtonCode[VK_CAPITAL] =KEY_CAPSLOCK;
|
||||
s_pVirtualKeyToButtonCode[VK_NUMLOCK] =KEY_NUMLOCK;
|
||||
s_pVirtualKeyToButtonCode[VK_ESCAPE] =KEY_ESCAPE;
|
||||
s_pVirtualKeyToButtonCode[VK_SCROLL] =KEY_SCROLLLOCK;
|
||||
s_pVirtualKeyToButtonCode[VK_INSERT] =KEY_INSERT;
|
||||
s_pVirtualKeyToButtonCode[VK_DELETE] =KEY_DELETE;
|
||||
s_pVirtualKeyToButtonCode[VK_HOME] =KEY_HOME;
|
||||
s_pVirtualKeyToButtonCode[VK_END] =KEY_END;
|
||||
s_pVirtualKeyToButtonCode[VK_PRIOR] =KEY_PAGEUP;
|
||||
s_pVirtualKeyToButtonCode[VK_NEXT] =KEY_PAGEDOWN;
|
||||
s_pVirtualKeyToButtonCode[VK_PAUSE] =KEY_BREAK;
|
||||
s_pVirtualKeyToButtonCode[VK_SHIFT] =KEY_RSHIFT;
|
||||
s_pVirtualKeyToButtonCode[VK_SHIFT] =KEY_LSHIFT; // SHIFT -> left SHIFT
|
||||
s_pVirtualKeyToButtonCode[VK_MENU] =KEY_RALT;
|
||||
s_pVirtualKeyToButtonCode[VK_MENU] =KEY_LALT; // ALT -> left ALT
|
||||
s_pVirtualKeyToButtonCode[VK_CONTROL] =KEY_RCONTROL;
|
||||
s_pVirtualKeyToButtonCode[VK_CONTROL] =KEY_LCONTROL; // CTRL -> left CTRL
|
||||
s_pVirtualKeyToButtonCode[VK_LWIN] =KEY_LWIN;
|
||||
s_pVirtualKeyToButtonCode[VK_RWIN] =KEY_RWIN;
|
||||
s_pVirtualKeyToButtonCode[VK_APPS] =KEY_APP;
|
||||
s_pVirtualKeyToButtonCode[VK_UP] =KEY_UP;
|
||||
s_pVirtualKeyToButtonCode[VK_LEFT] =KEY_LEFT;
|
||||
s_pVirtualKeyToButtonCode[VK_DOWN] =KEY_DOWN;
|
||||
s_pVirtualKeyToButtonCode[VK_RIGHT] =KEY_RIGHT;
|
||||
s_pVirtualKeyToButtonCode[VK_F1] =KEY_F1;
|
||||
s_pVirtualKeyToButtonCode[VK_F2] =KEY_F2;
|
||||
s_pVirtualKeyToButtonCode[VK_F3] =KEY_F3;
|
||||
s_pVirtualKeyToButtonCode[VK_F4] =KEY_F4;
|
||||
s_pVirtualKeyToButtonCode[VK_F5] =KEY_F5;
|
||||
s_pVirtualKeyToButtonCode[VK_F6] =KEY_F6;
|
||||
s_pVirtualKeyToButtonCode[VK_F7] =KEY_F7;
|
||||
s_pVirtualKeyToButtonCode[VK_F8] =KEY_F8;
|
||||
s_pVirtualKeyToButtonCode[VK_F9] =KEY_F9;
|
||||
s_pVirtualKeyToButtonCode[VK_F10] =KEY_F10;
|
||||
s_pVirtualKeyToButtonCode[VK_F11] =KEY_F11;
|
||||
s_pVirtualKeyToButtonCode[VK_F12] =KEY_F12;
|
||||
#endif
|
||||
|
||||
// init the xkey translation table
|
||||
#if !defined( POSIX )
|
||||
s_pXKeyTrans[XK_NULL] = KEY_NONE;
|
||||
s_pXKeyTrans[XK_BUTTON_UP] = KEY_XBUTTON_UP;
|
||||
s_pXKeyTrans[XK_BUTTON_DOWN] = KEY_XBUTTON_DOWN;
|
||||
s_pXKeyTrans[XK_BUTTON_LEFT] = KEY_XBUTTON_LEFT;
|
||||
s_pXKeyTrans[XK_BUTTON_RIGHT] = KEY_XBUTTON_RIGHT;
|
||||
s_pXKeyTrans[XK_BUTTON_START] = KEY_XBUTTON_START;
|
||||
s_pXKeyTrans[XK_BUTTON_BACK] = KEY_XBUTTON_BACK;
|
||||
s_pXKeyTrans[XK_BUTTON_STICK1] = KEY_XBUTTON_STICK1;
|
||||
s_pXKeyTrans[XK_BUTTON_STICK2] = KEY_XBUTTON_STICK2;
|
||||
s_pXKeyTrans[XK_BUTTON_A] = KEY_XBUTTON_A;
|
||||
s_pXKeyTrans[XK_BUTTON_B] = KEY_XBUTTON_B;
|
||||
s_pXKeyTrans[XK_BUTTON_X] = KEY_XBUTTON_X;
|
||||
s_pXKeyTrans[XK_BUTTON_Y] = KEY_XBUTTON_Y;
|
||||
s_pXKeyTrans[XK_BUTTON_LEFT_SHOULDER] = KEY_XBUTTON_LEFT_SHOULDER;
|
||||
s_pXKeyTrans[XK_BUTTON_RIGHT_SHOULDER] = KEY_XBUTTON_RIGHT_SHOULDER;
|
||||
s_pXKeyTrans[XK_BUTTON_LTRIGGER] = KEY_XBUTTON_LTRIGGER;
|
||||
s_pXKeyTrans[XK_BUTTON_RTRIGGER] = KEY_XBUTTON_RTRIGGER;
|
||||
s_pXKeyTrans[XK_STICK1_UP] = KEY_XSTICK1_UP;
|
||||
s_pXKeyTrans[XK_STICK1_DOWN] = KEY_XSTICK1_DOWN;
|
||||
s_pXKeyTrans[XK_STICK1_LEFT] = KEY_XSTICK1_LEFT;
|
||||
s_pXKeyTrans[XK_STICK1_RIGHT] = KEY_XSTICK1_RIGHT;
|
||||
s_pXKeyTrans[XK_STICK2_UP] = KEY_XSTICK2_UP;
|
||||
s_pXKeyTrans[XK_STICK2_DOWN] = KEY_XSTICK2_DOWN;
|
||||
s_pXKeyTrans[XK_STICK2_LEFT] = KEY_XSTICK2_LEFT;
|
||||
s_pXKeyTrans[XK_STICK2_RIGHT] = KEY_XSTICK2_RIGHT;
|
||||
#endif // PLATFORM_POSIX
|
||||
|
||||
// create reverse table engine to virtual
|
||||
for ( int i = 0; i < ARRAYSIZE( s_pVirtualKeyToButtonCode ); i++ )
|
||||
{
|
||||
s_pButtonCodeToVirtual[ s_pVirtualKeyToButtonCode[i] ] = i;
|
||||
}
|
||||
|
||||
s_pButtonCodeToVirtual[0] = 0;
|
||||
|
||||
s_pSKeytoButtonCode[SK_NULL] = KEY_NONE;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_A] = STEAMCONTROLLER_A;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_B] = STEAMCONTROLLER_B;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_X] = STEAMCONTROLLER_X;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_Y] = STEAMCONTROLLER_Y;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_UP] = STEAMCONTROLLER_DPAD_UP;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_RIGHT] = STEAMCONTROLLER_DPAD_RIGHT;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_DOWN] = STEAMCONTROLLER_DPAD_DOWN;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_LEFT] = STEAMCONTROLLER_DPAD_LEFT;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_LEFT_BUMPER] = STEAMCONTROLLER_LEFT_BUMPER;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_RIGHT_BUMPER] = STEAMCONTROLLER_RIGHT_BUMPER;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_LEFT_TRIGGER] = STEAMCONTROLLER_LEFT_TRIGGER;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_RIGHT_TRIGGER] = STEAMCONTROLLER_RIGHT_TRIGGER;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_LEFT_GRIP] = STEAMCONTROLLER_LEFT_GRIP;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_RIGHT_GRIP] = STEAMCONTROLLER_RIGHT_GRIP;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_LPAD_TOUCH] = STEAMCONTROLLER_LEFT_PAD_FINGERDOWN;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_RPAD_TOUCH] = STEAMCONTROLLER_RIGHT_PAD_FINGERDOWN;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_LPAD_CLICK] = STEAMCONTROLLER_LEFT_PAD_CLICK;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_RPAD_CLICK] = STEAMCONTROLLER_RIGHT_PAD_CLICK;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_LPAD_UP] = STEAMCONTROLLER_LEFT_PAD_UP;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_LPAD_RIGHT] = STEAMCONTROLLER_LEFT_PAD_RIGHT;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_LPAD_DOWN] = STEAMCONTROLLER_LEFT_PAD_DOWN;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_LPAD_LEFT] = STEAMCONTROLLER_LEFT_PAD_LEFT;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_RPAD_UP] = STEAMCONTROLLER_RIGHT_PAD_UP;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_RPAD_RIGHT] = STEAMCONTROLLER_RIGHT_PAD_RIGHT;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_RPAD_DOWN] = STEAMCONTROLLER_RIGHT_PAD_DOWN;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_RPAD_LEFT] = STEAMCONTROLLER_RIGHT_PAD_LEFT;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_SELECT] = STEAMCONTROLLER_SELECT;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_START] = STEAMCONTROLLER_START;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_STEAM] = STEAMCONTROLLER_STEAM;
|
||||
s_pSKeytoButtonCode[SK_BUTTON_INACTIVE_START] = STEAMCONTROLLER_INACTIVE_START;
|
||||
|
||||
// These are fake ("virtual") steam controller buttons that don't physically exist, but we can manufacture to make internal routing
|
||||
// to old school UI (which is expecting button code rather than actions) without clashing with other butt
|
||||
s_pSKeytoButtonCode[SK_VBUTTON_F1] = STEAMCONTROLLER_F1;
|
||||
s_pSKeytoButtonCode[SK_VBUTTON_F2] = STEAMCONTROLLER_F2;
|
||||
s_pSKeytoButtonCode[SK_VBUTTON_F3] = STEAMCONTROLLER_F3;
|
||||
s_pSKeytoButtonCode[SK_VBUTTON_F4] = STEAMCONTROLLER_F4;
|
||||
s_pSKeytoButtonCode[SK_VBUTTON_F5] = STEAMCONTROLLER_F5;
|
||||
s_pSKeytoButtonCode[SK_VBUTTON_F6] = STEAMCONTROLLER_F6;
|
||||
s_pSKeytoButtonCode[SK_VBUTTON_F7] = STEAMCONTROLLER_F7;
|
||||
s_pSKeytoButtonCode[SK_VBUTTON_F8] = STEAMCONTROLLER_F8;
|
||||
s_pSKeytoButtonCode[SK_VBUTTON_F9] = STEAMCONTROLLER_F9;
|
||||
s_pSKeytoButtonCode[SK_VBUTTON_F10] = STEAMCONTROLLER_F10;
|
||||
s_pSKeytoButtonCode[SK_VBUTTON_F11] = STEAMCONTROLLER_F11;
|
||||
s_pSKeytoButtonCode[SK_VBUTTON_F12] = STEAMCONTROLLER_F12;
|
||||
}
|
||||
|
||||
ButtonCode_t ButtonCode_VirtualKeyToButtonCode( int keyCode )
|
||||
{
|
||||
if ( keyCode < 0 || keyCode >= sizeof( s_pVirtualKeyToButtonCode ) / sizeof( s_pVirtualKeyToButtonCode[0] ) )
|
||||
{
|
||||
Assert( false );
|
||||
return KEY_NONE;
|
||||
}
|
||||
return s_pVirtualKeyToButtonCode[keyCode];
|
||||
}
|
||||
|
||||
int ButtonCode_ButtonCodeToVirtualKey( ButtonCode_t code )
|
||||
{
|
||||
return s_pButtonCodeToVirtual[code];
|
||||
}
|
||||
|
||||
ButtonCode_t ButtonCode_XKeyToButtonCode( int nPort, int keyCode )
|
||||
{
|
||||
#if !defined( POSIX )
|
||||
if ( keyCode < 0 || keyCode >= sizeof( s_pXKeyTrans ) / sizeof( s_pXKeyTrans[0] ) )
|
||||
{
|
||||
Assert( false );
|
||||
return KEY_NONE;
|
||||
}
|
||||
|
||||
ButtonCode_t code = s_pXKeyTrans[keyCode];
|
||||
if ( IsJoystickButtonCode( code ) )
|
||||
{
|
||||
int nOffset = code - JOYSTICK_FIRST_BUTTON;
|
||||
return JOYSTICK_BUTTON( nPort, nOffset );
|
||||
}
|
||||
|
||||
if ( IsJoystickPOVCode( code ) )
|
||||
{
|
||||
int nOffset = code - JOYSTICK_FIRST_POV_BUTTON;
|
||||
return JOYSTICK_POV_BUTTON( nPort, nOffset );
|
||||
}
|
||||
|
||||
if ( IsJoystickAxisCode( code ) )
|
||||
{
|
||||
int nOffset = code - JOYSTICK_FIRST_AXIS_BUTTON;
|
||||
return JOYSTICK_AXIS_BUTTON( nPort, nOffset );
|
||||
}
|
||||
|
||||
return code;
|
||||
#else // POSIX
|
||||
return KEY_NONE;
|
||||
#endif // POSIX
|
||||
}
|
||||
|
||||
// Convert back + forth between ButtonCode/AnalogCode + strings
|
||||
const char *ButtonCode_ButtonCodeToString( ButtonCode_t code, bool bXController )
|
||||
{
|
||||
#if !defined ( _X360 )
|
||||
if ( bXController && code >= JOYSTICK_FIRST_BUTTON && code <= JOYSTICK_LAST_AXIS_BUTTON )
|
||||
return s_pXControllerButtonCodeNames[ code - JOYSTICK_FIRST_BUTTON ];
|
||||
#endif
|
||||
|
||||
return s_pButtonCodeName[ code ];
|
||||
}
|
||||
|
||||
const char *AnalogCode_AnalogCodeToString( AnalogCode_t code )
|
||||
{
|
||||
return s_pAnalogCodeName[ code ];
|
||||
}
|
||||
|
||||
ButtonCode_t ButtonCode_StringToButtonCode( const char *pString, bool bXController )
|
||||
{
|
||||
if ( !pString || !pString[0] )
|
||||
return BUTTON_CODE_INVALID;
|
||||
|
||||
// Backward compat for screwed up previous joystick button names
|
||||
if ( !Q_strnicmp( pString, "aux", 3 ) )
|
||||
{
|
||||
int nIndex = atoi( &pString[3] );
|
||||
if ( nIndex < 29 )
|
||||
return JOYSTICK_BUTTON( 0, nIndex );
|
||||
if ( ( nIndex >= 29 ) && ( nIndex <= 32 ) )
|
||||
return JOYSTICK_POV_BUTTON( 0, nIndex - 29 );
|
||||
return BUTTON_CODE_INVALID;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < BUTTON_CODE_LAST; ++i )
|
||||
{
|
||||
if ( !Q_stricmp( s_pButtonCodeName[i], pString ) )
|
||||
return (ButtonCode_t)i;
|
||||
}
|
||||
|
||||
#if !defined ( _X360 )
|
||||
if ( bXController )
|
||||
{
|
||||
for ( int i = 0; i < ARRAYSIZE(s_pXControllerButtonCodeNames); ++i )
|
||||
{
|
||||
if ( !Q_stricmp( s_pXControllerButtonCodeNames[i], pString ) )
|
||||
return (ButtonCode_t)(JOYSTICK_FIRST_BUTTON + i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return BUTTON_CODE_INVALID;
|
||||
}
|
||||
|
||||
ButtonCode_t ButtonCode_SKeyToButtonCode( int nPort, int keyCode )
|
||||
{
|
||||
#if !defined( _GAMECONSOLE )
|
||||
if ( keyCode < 0 || keyCode >= sizeof( s_pSKeytoButtonCode ) / sizeof( s_pSKeytoButtonCode[0] ) )
|
||||
{
|
||||
Assert( false );
|
||||
return KEY_NONE;
|
||||
}
|
||||
|
||||
ButtonCode_t code = s_pSKeytoButtonCode[keyCode];
|
||||
// if ( IsSteamControllerCode( code ) )
|
||||
// {
|
||||
// // Need Per Controller Offset here.
|
||||
// return code;
|
||||
// }
|
||||
|
||||
if ( IsSteamControllerButtonCode( code ) )
|
||||
{
|
||||
int nOffset = code - STEAMCONTROLLER_FIRST_BUTTON;
|
||||
return STEAMCONTROLLER_BUTTON( nPort, nOffset );
|
||||
}
|
||||
|
||||
if ( IsSteamControllerAxisCode( code ) )
|
||||
{
|
||||
int nOffset = code - STEAMCONTROLLER_FIRST_AXIS_BUTTON;
|
||||
return STEAMCONTROLLER_AXIS_BUTTON( nPort, nOffset );
|
||||
}
|
||||
|
||||
return code;
|
||||
#else // _GAMECONSOLE
|
||||
return KEY_NONE;
|
||||
#endif // _GAMECONSOLE
|
||||
}
|
||||
|
||||
AnalogCode_t AnalogCode_StringToAnalogCode( const char *pString )
|
||||
{
|
||||
if ( !pString || !pString[0] )
|
||||
return ANALOG_CODE_INVALID;
|
||||
|
||||
for ( int i = 0; i < ANALOG_CODE_LAST; ++i )
|
||||
{
|
||||
if ( !Q_stricmp( s_pAnalogCodeName[i], pString ) )
|
||||
return (AnalogCode_t)i;
|
||||
}
|
||||
|
||||
return ANALOG_CODE_INVALID;
|
||||
}
|
||||
|
||||
ButtonCode_t ButtonCode_ScanCodeToButtonCode( int lParam )
|
||||
{
|
||||
int nScanCode = ( lParam >> 16 ) & 0xFF;
|
||||
if ( nScanCode > 127 )
|
||||
return KEY_NONE;
|
||||
|
||||
ButtonCode_t result = s_pScanToButtonCode[nScanCode];
|
||||
|
||||
bool bIsExtended = ( lParam & ( 1 << 24 ) ) != 0;
|
||||
if ( !bIsExtended )
|
||||
{
|
||||
switch ( result )
|
||||
{
|
||||
case KEY_HOME:
|
||||
return KEY_PAD_7;
|
||||
case KEY_UP:
|
||||
return KEY_PAD_8;
|
||||
case KEY_PAGEUP:
|
||||
return KEY_PAD_9;
|
||||
case KEY_LEFT:
|
||||
return KEY_PAD_4;
|
||||
case KEY_RIGHT:
|
||||
return KEY_PAD_6;
|
||||
case KEY_END:
|
||||
return KEY_PAD_1;
|
||||
case KEY_DOWN:
|
||||
return KEY_PAD_2;
|
||||
case KEY_PAGEDOWN:
|
||||
return KEY_PAD_3;
|
||||
case KEY_INSERT:
|
||||
return KEY_PAD_0;
|
||||
case KEY_DELETE:
|
||||
return KEY_PAD_DECIMAL;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ( result )
|
||||
{
|
||||
case KEY_ENTER:
|
||||
return KEY_PAD_ENTER;
|
||||
case KEY_LALT:
|
||||
return KEY_RALT;
|
||||
case KEY_LCONTROL:
|
||||
return KEY_RCONTROL;
|
||||
case KEY_SLASH:
|
||||
return KEY_PAD_DIVIDE;
|
||||
case KEY_CAPSLOCK:
|
||||
return KEY_PAD_PLUS;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Update scan codes for foreign keyboards
|
||||
//-----------------------------------------------------------------------------
|
||||
void ButtonCode_UpdateScanCodeLayout( )
|
||||
{
|
||||
// reset the keyboard
|
||||
memcpy( s_pScanToButtonCode, s_pScanToButtonCode_QWERTY, sizeof(s_pScanToButtonCode) );
|
||||
|
||||
#if !defined( _X360 ) && !defined( POSIX )
|
||||
// fix up keyboard layout for other languages
|
||||
HKL currentKb = ::GetKeyboardLayout( 0 );
|
||||
HKL englishKb = ::LoadKeyboardLayout("00000409", 0);
|
||||
|
||||
if (englishKb && englishKb != currentKb)
|
||||
{
|
||||
for ( int i = 0; i < ARRAYSIZE(s_pScanToButtonCode); i++ )
|
||||
{
|
||||
// take the english/QWERTY
|
||||
ButtonCode_t code = s_pScanToButtonCode_QWERTY[ i ];
|
||||
|
||||
// only remap printable keys
|
||||
if ( code != KEY_NONE && code != KEY_BACKQUOTE && ( IsAlphaNumeric( code ) || IsPunctuation( code ) ) )
|
||||
{
|
||||
// get it's virtual key based on the old layout
|
||||
int vk = ::MapVirtualKeyEx( i, 1, englishKb );
|
||||
|
||||
// turn in into a scancode on the new layout
|
||||
int newScanCode = ::MapVirtualKeyEx( vk, 0, currentKb );
|
||||
|
||||
// strip off any high bits
|
||||
newScanCode &= 0x0000007F;
|
||||
|
||||
// set in the new layout
|
||||
s_pScanToButtonCode[newScanCode] = code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_pScanToButtonCode[0] = KEY_NONE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Updates the current keyboard layout
|
||||
//-----------------------------------------------------------------------------
|
||||
CON_COMMAND( key_updatelayout, "Updates game keyboard layout to current windows keyboard setting." )
|
||||
{
|
||||
ButtonCode_UpdateScanCodeLayout();
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
#ifndef KEY_TRANSLATION_H
|
||||
#define KEY_TRANSLATION_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "inputsystem/ButtonCode.h"
|
||||
#include "inputsystem/AnalogCode.h"
|
||||
|
||||
// Call this to initialize the system
|
||||
void ButtonCode_InitKeyTranslationTable();
|
||||
|
||||
// Convert from Windows scan codes to Button codes.
|
||||
ButtonCode_t ButtonCode_ScanCodeToButtonCode( int lParam );
|
||||
|
||||
// Update scan codes for foreign keyboards
|
||||
void ButtonCode_UpdateScanCodeLayout( );
|
||||
|
||||
// Convert from Windows virtual key codes to Button codes.
|
||||
ButtonCode_t ButtonCode_VirtualKeyToButtonCode( int keyCode );
|
||||
int ButtonCode_ButtonCodeToVirtualKey( ButtonCode_t code );
|
||||
|
||||
ButtonCode_t ButtonCode_XKeyToButtonCode( int nPort, int keyCode );
|
||||
|
||||
// Convert back + forth between ButtonCode/AnalogCode + strings
|
||||
const char *ButtonCode_ButtonCodeToString( ButtonCode_t code, bool bXController );
|
||||
const char *AnalogCode_AnalogCodeToString( AnalogCode_t code );
|
||||
ButtonCode_t ButtonCode_StringToButtonCode( const char *pString, bool bXController );
|
||||
AnalogCode_t AnalogCode_StringToAnalogCode( const char *pString );
|
||||
ButtonCode_t ButtonCode_SKeyToButtonCode( int nPort, int keyCode );
|
||||
|
||||
#endif // KEY_TRANSLATION_H
|
||||
@@ -0,0 +1,138 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//===========================================================================//
|
||||
|
||||
#include "inputsystem.h"
|
||||
#include "key_translation.h"
|
||||
#include "inputsystem/ButtonCode.h"
|
||||
#include "inputsystem/AnalogCode.h"
|
||||
#include "tier1/convar.h"
|
||||
|
||||
typedef void*(*NovintGetIHaptics_t)(void);
|
||||
typedef bool (*NovintAttemptHWND_t)(void *hWnd);
|
||||
typedef void (*NovintDisableHWND_t)(void);
|
||||
typedef void (*NovintPollDevices_t)(void);
|
||||
typedef bool (*NovintButtonState_t)(int nDevice,
|
||||
int &down,
|
||||
int &pressed,
|
||||
int &released);
|
||||
typedef int (*NovintDeviceCount_t)();
|
||||
typedef int (*NovintButtonCount_t)(int nDevice);
|
||||
typedef bool (__cdecl *NovintMouseModeCallback_t) (void);
|
||||
typedef void (*NovintInputActive_t)(bool bGameInput);
|
||||
typedef __int64 (*NovintGetDeviceID_t)(int nDevice);
|
||||
|
||||
NovintGetIHaptics_t NovintGetIHaptics = NULL;
|
||||
NovintAttemptHWND_t NovintAttemptHWND = NULL;
|
||||
NovintDisableHWND_t NovintDisableHWND = NULL;
|
||||
NovintPollDevices_t NovintPollDevices = NULL;
|
||||
NovintButtonState_t NovintButtonState = NULL;
|
||||
NovintDeviceCount_t NovintDeviceCount = NULL;
|
||||
NovintButtonCount_t NovintButtonCount = NULL;
|
||||
NovintInputActive_t NovintInputActive = NULL;
|
||||
NovintGetDeviceID_t NovintGetDeviceID = NULL;
|
||||
|
||||
static CInputSystem *pNovintInputSystem = 0;
|
||||
|
||||
static bool bNovintPure = false;
|
||||
|
||||
bool __cdecl NovintDevicesInputMode(void)
|
||||
{
|
||||
if(pNovintInputSystem)
|
||||
{
|
||||
return !bNovintPure;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void *CInputSystem::GetHapticsInterfaceAddress(void)const
|
||||
{
|
||||
if( NovintGetIHaptics )
|
||||
return NovintGetIHaptics();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CInputSystem::AttachWindowToNovintDevices( void * hWnd )
|
||||
{
|
||||
if( NovintAttemptHWND )
|
||||
NovintAttemptHWND( hWnd );
|
||||
}
|
||||
|
||||
void CInputSystem::DetachWindowFromNovintDevices(void)
|
||||
{
|
||||
if( NovintDisableHWND )
|
||||
NovintDisableHWND();
|
||||
}
|
||||
|
||||
void CInputSystem::InitializeNovintDevices()
|
||||
{
|
||||
pNovintInputSystem = this;
|
||||
// assume no novint devices
|
||||
m_bNovintDevices = false;
|
||||
m_nNovintDeviceCount = 0;
|
||||
|
||||
if(!m_pNovintDLL)
|
||||
return;
|
||||
|
||||
NovintGetIHaptics = (NovintGetIHaptics_t)GetProcAddress( (HMODULE)m_pNovintDLL, "NovintGetIHaptics" );
|
||||
NovintAttemptHWND = (NovintAttemptHWND_t)GetProcAddress( (HMODULE)m_pNovintDLL, "NovintAttemptHWND" );
|
||||
NovintDisableHWND = (NovintDisableHWND_t)GetProcAddress( (HMODULE)m_pNovintDLL, "NovintDisableHWND" );
|
||||
NovintPollDevices = (NovintPollDevices_t)GetProcAddress( (HMODULE)m_pNovintDLL, "NovintPollDevices" );
|
||||
NovintButtonState = (NovintButtonState_t)GetProcAddress( (HMODULE)m_pNovintDLL, "NovintButtonState" );
|
||||
NovintDeviceCount = (NovintDeviceCount_t)GetProcAddress( (HMODULE)m_pNovintDLL, "NovintDeviceCount" );
|
||||
NovintButtonCount = (NovintButtonCount_t)GetProcAddress( (HMODULE)m_pNovintDLL, "NovintButtonCount" );
|
||||
NovintGetDeviceID = (NovintGetDeviceID_t)GetProcAddress( (HMODULE)m_pNovintDLL, "NovintGetDeviceID" );
|
||||
NovintInputActive = (NovintInputActive_t)GetProcAddress( (HMODULE)m_pNovintDLL, "NovintInputActive" );
|
||||
|
||||
|
||||
m_nNovintDeviceCount = NovintDeviceCount();
|
||||
|
||||
if( m_nNovintDeviceCount > 0 )
|
||||
m_bNovintDevices = true;
|
||||
}
|
||||
|
||||
void CInputSystem::PollNovintDevices()
|
||||
{
|
||||
if( NovintPollDevices )
|
||||
NovintPollDevices();
|
||||
|
||||
for ( int i = 0; i < m_nNovintDeviceCount; i++ )
|
||||
{
|
||||
UpdateNovintDeviceButtonState(i);
|
||||
}
|
||||
}
|
||||
|
||||
void CInputSystem::UpdateNovintDeviceButtonState(int nDevice)
|
||||
{
|
||||
int nDown;
|
||||
int nPressed;
|
||||
int nReleased;
|
||||
if(NovintButtonState(nDevice, nDown, nPressed, nReleased))
|
||||
{
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
ButtonCode_t code = (ButtonCode_t)( NOVINT_FIRST + ( nDevice * 4 ) + i );
|
||||
|
||||
if( nPressed & (1 << i) )
|
||||
{
|
||||
PostButtonPressedEvent(IE_ButtonPressed, m_nLastSampleTick, code, KEY_NONE);
|
||||
}
|
||||
|
||||
if( nReleased & (1 << i) )
|
||||
{
|
||||
PostButtonReleasedEvent(IE_ButtonReleased, m_nLastSampleTick, code, KEY_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CInputSystem::SetNovintPure( bool bPure )
|
||||
{
|
||||
bNovintPure = bPure;
|
||||
if(NovintInputActive)
|
||||
NovintInputActive(bNovintPure);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
//
|
||||
//
|
||||
//==================================================================================================
|
||||
|
||||
#ifndef POSIX_WIN32STUBS_H
|
||||
#define POSIX_WIN32STUBS_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "tier0/basetypes.h"
|
||||
#include "tier0/platform.h"
|
||||
|
||||
typedef int32 LRESULT;
|
||||
typedef void* HWND;
|
||||
typedef uint32 UINT;
|
||||
typedef uintp WPARAM;
|
||||
typedef uintp LPARAM;
|
||||
|
||||
typedef uint8 BYTE;
|
||||
typedef int16 SHORT;
|
||||
|
||||
typedef void* WNDPROC;
|
||||
typedef void* HANDLE;
|
||||
|
||||
typedef char xKey_t;
|
||||
|
||||
#define XUSER_MAX_COUNT 2
|
||||
#define XK_MAX_KEYS 5
|
||||
|
||||
typedef struct joyinfoex_tag
|
||||
{
|
||||
DWORD dwSize;
|
||||
DWORD dwFlags;
|
||||
DWORD dwXpos;
|
||||
DWORD dwYpos;
|
||||
DWORD dwZpos;
|
||||
DWORD dwRpos;
|
||||
DWORD dwUpos;
|
||||
DWORD dwVpos;
|
||||
DWORD dwButtons;
|
||||
DWORD dwButtonNumber;
|
||||
DWORD dwPOV;
|
||||
DWORD dwReserved1;
|
||||
DWORD dwReserved2;
|
||||
} JOYINFOEX, *LPJOYINFOEX;
|
||||
|
||||
|
||||
typedef struct _XINPUT_GAMEPAD
|
||||
{
|
||||
WORD wButtons;
|
||||
BYTE bLeftTrigger;
|
||||
BYTE bRightTrigger;
|
||||
SHORT sThumbLX;
|
||||
SHORT sThumbLY;
|
||||
SHORT sThumbRX;
|
||||
SHORT sThumbRY;
|
||||
} XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;
|
||||
|
||||
typedef struct _XINPUT_STATE
|
||||
{
|
||||
DWORD dwPacketNumber;
|
||||
XINPUT_GAMEPAD Gamepad;
|
||||
} XINPUT_STATE, *PXINPUT_STATE;
|
||||
|
||||
typedef struct _XINPUT_VIBRATION
|
||||
{
|
||||
WORD wLeftMotorSpeed;
|
||||
WORD wRightMotorSpeed;
|
||||
} XINPUT_VIBRATION, *PXINPUT_VIBRATION;
|
||||
|
||||
|
||||
#endif // POSIX_WIN32STUBS_H
|
||||
@@ -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"";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user