source-engine/inputsystem/inputsystem.h

488 lines
15 KiB
C++

//========= 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"
#define TOUCH_FINGER_MAX_COUNT 10
//-----------------------------------------------------------------------------
// 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 bool GetTouchAccumulators( int fingerId, float &dx, float &dy );
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 );
// Init touch
void InitializeTouch( void );
// Shut down touch
void ShutdownTouch( void );
#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 );
void FingerEvent( int eventType, int fingerId, float x, float y, float dx, float dy );
// 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;
}
virtual void StartTextInput();
#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_bTouchInitialized;
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;
float m_touchAccumX[TOUCH_FINGER_MAX_COUNT], m_touchAccumY[TOUCH_FINGER_MAX_COUNT];
// 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