From bbebbdac13f864c0b4313b02862d0b31416924e8 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Fri, 5 Apr 2024 17:09:47 +0200 Subject: [PATCH] InputSystem: largely reversed struct and fully reversed iface Struct has been largely mapped out (still requires a bit of work, mostly the Xbox/Hid data structures). The vftable has been fully mapped out. --- r5dev/common/xbox/xboxstubs.h | 49 ++++++++ r5dev/inputsystem/CMakeLists.txt | 3 + r5dev/inputsystem/inputsystem.cpp | 80 ++++++------- r5dev/inputsystem/inputsystem.h | 144 +++++++++++++++++++++-- r5dev/public/inputsystem/AnalogCode.h | 38 ++++++ r5dev/public/inputsystem/ButtonCode.h | 3 +- r5dev/public/inputsystem/InputEnums.h | 8 +- r5dev/public/inputsystem/iinputsystem.h | 149 ++++++++++++++++++++++++ 8 files changed, 418 insertions(+), 56 deletions(-) create mode 100644 r5dev/common/xbox/xboxstubs.h create mode 100644 r5dev/public/inputsystem/AnalogCode.h create mode 100644 r5dev/public/inputsystem/iinputsystem.h diff --git a/r5dev/common/xbox/xboxstubs.h b/r5dev/common/xbox/xboxstubs.h new file mode 100644 index 00000000..cfef77cf --- /dev/null +++ b/r5dev/common/xbox/xboxstubs.h @@ -0,0 +1,49 @@ +//========= Copyright 1996-2004, Valve LLC, All rights reserved. ============ +// +// Purpose: Win32 replacements for XBox. +// +//============================================================================= +#if !defined( XBOXSTUBS_H ) && !defined( _X360 ) +#define XBOXSTUBS_H + +typedef enum +{ + XK_BUTTON_UP, + XK_BUTTON_DOWN, + XK_BUTTON_LEFT, + XK_BUTTON_RIGHT, + + XK_BUTTON_START, + XK_BUTTON_BACK, + + XK_BUTTON_STICK1, + XK_BUTTON_STICK2, + + XK_BUTTON_A, + XK_BUTTON_B, + XK_BUTTON_X, + XK_BUTTON_Y, + + XK_BUTTON_LEFT_SHOULDER, + XK_BUTTON_RIGHT_SHOULDER, + + XK_XBUTTON_LTRIGGER_PARTIAL, + XK_XBUTTON_LTRIGGER_FULL, + + XK_XBUTTON_RTRIGGER_PARTIAL, + XK_XBUTTON_RTRIGGER_FULL, + + XK_STICK1_UP, + XK_STICK1_DOWN, + XK_STICK1_LEFT, + XK_STICK1_RIGHT, + + XK_STICK2_UP, + XK_STICK2_DOWN, + XK_STICK2_LEFT, + XK_STICK2_RIGHT, + + XK_MAX_KEYS, +} xKey_t; + +#endif // XBOXSTUBS_H \ No newline at end of file diff --git a/r5dev/inputsystem/CMakeLists.txt b/r5dev/inputsystem/CMakeLists.txt index c22fca6f..5d6ea714 100644 --- a/r5dev/inputsystem/CMakeLists.txt +++ b/r5dev/inputsystem/CMakeLists.txt @@ -9,7 +9,10 @@ add_sources( SOURCE_GROUP "Private" ) add_sources( SOURCE_GROUP "Public" + "${ENGINE_SOURCE_DIR}/public/inputsystem/iinputsystem.h" + "${ENGINE_SOURCE_DIR}/public/inputsystem/AnalogCode.h" "${ENGINE_SOURCE_DIR}/public/inputsystem/ButtonCode.h" + "${ENGINE_SOURCE_DIR}/public/inputsystem/InputEnums.h" ) end_sources() diff --git a/r5dev/inputsystem/inputsystem.cpp b/r5dev/inputsystem/inputsystem.cpp index d78ed76c..256fc8b0 100644 --- a/r5dev/inputsystem/inputsystem.cpp +++ b/r5dev/inputsystem/inputsystem.cpp @@ -8,46 +8,46 @@ #include "vpc/IAppSystem.h" #include "inputsystem/inputsystem.h" -//----------------------------------------------------------------------------- -// Enables/disables input -//----------------------------------------------------------------------------- -void CInputSystem::EnableInput(bool bEnabled) -{ - const static int index = 10; - CallVFunc(index, this, bEnabled); -} - -//----------------------------------------------------------------------------- -// Enables/disables the inputsystem windows message pump -//----------------------------------------------------------------------------- -void CInputSystem::EnableMessagePump(bool bEnabled) -{ - const static int index = 11; - CallVFunc(index, this, bEnabled); -} - -//----------------------------------------------------------------------------- -// Poll current state -//----------------------------------------------------------------------------- -bool CInputSystem::IsButtonDown(ButtonCode_t Button) -{ - const static int index = 13; - return CallVFunc(index, this, Button); -} - -//----------------------------------------------------------------------------- -// Convert back + forth between ButtonCode/AnalogCode + strings -//----------------------------------------------------------------------------- -bool CInputSystem::ButtonCodeToString(ButtonCode_t Button) -{ - const static int index = 25; - return CallVFunc(index, this, Button); -} -ButtonCode_t CInputSystem::StringToButtonCode(const char* pString) -{ - const static int index = 26; - return CallVFunc(index, this, pString); -} +////----------------------------------------------------------------------------- +//// Enables/disables input +////----------------------------------------------------------------------------- +//void CInputSystem::EnableInput(bool bEnabled) +//{ +// const static int index = 10; +// CallVFunc(index, this, bEnabled); +//} +// +////----------------------------------------------------------------------------- +//// Enables/disables the inputsystem windows message pump +////----------------------------------------------------------------------------- +//void CInputSystem::EnableMessagePump(bool bEnabled) +//{ +// const static int index = 11; +// CallVFunc(index, this, bEnabled); +//} +// +////----------------------------------------------------------------------------- +//// Poll current state +////----------------------------------------------------------------------------- +//bool CInputSystem::IsButtonDown(ButtonCode_t Button) +//{ +// const static int index = 13; +// return CallVFunc(index, this, Button); +//} +// +////----------------------------------------------------------------------------- +//// Convert back + forth between ButtonCode/AnalogCode + strings +////----------------------------------------------------------------------------- +//bool CInputSystem::ButtonCodeToString(ButtonCode_t Button) +//{ +// const static int index = 25; +// return CallVFunc(index, this, Button); +//} +//ButtonCode_t CInputSystem::StringToButtonCode(const char* pString) +//{ +// const static int index = 26; +// return CallVFunc(index, this, pString); +//} /////////////////////////////////////////////////////////////////////////////// CInputSystem* g_pInputSystem = nullptr; \ No newline at end of file diff --git a/r5dev/inputsystem/inputsystem.h b/r5dev/inputsystem/inputsystem.h index 1961b641..a24a4c70 100644 --- a/r5dev/inputsystem/inputsystem.h +++ b/r5dev/inputsystem/inputsystem.h @@ -1,21 +1,141 @@ #pragma once -#include "core/stdafx.h" -#include "inputsystem/ButtonCode.h" +#include "inputsystem/iinputsystem.h" +#include "mathlib/bitvec.h" +#include "tier1/utlstringmap.h" +#include -class CInputSystem +//----------------------------------------------------------------------------- +// Implementation of the input system +//----------------------------------------------------------------------------- +class CInputSystem : public CTier1AppSystem< IInputSystem > { public: - void EnableInput(bool bEnabled); // @0x14039F100 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM - void EnableMessagePump(bool bEnabled); // @0x14039F110 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM - bool IsButtonDown(ButtonCode_t Button); // @0x1403A0140 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM - bool ButtonCodeToString(ButtonCode_t Button); - ButtonCode_t StringToButtonCode(const char* pString); + // !!!interface implemented in engine!!! private: - char pad_0000[16]; //0x0000 -public: - bool m_bEnabled; //0x0010 IsInputEnabled variable. - bool m_bPumpEnabled; //0x0011 EnabledMessagePump variable. + enum + { + INPUT_STATE_QUEUED = 0, + INPUT_STATE_CURRENT, + + INPUT_STATE_COUNT, + }; + + struct xdevice_t + { + struct xvibration_t + { + float leftMainMotor; + float rightMainMotor; + float leftTriggerMotor; + float rightTriggerMotor; + }; + + int userId; + char active; + XINPUT_STATE states[INPUT_STATE_COUNT]; + int newState; + _BYTE gap6[20]; + bool pendingRumbleUpdate; + _BYTE gap41[3]; + xvibration_t vibration; + bool bUnk0; + char field_55; + _BYTE gap56[42]; + int field_80; + _BYTE gap84[316]; + }; + + struct appKey_t + { + int repeats; + int sample; + }; + + struct InputState_t + { + // Analog states + CBitVec m_ButtonState; + int m_pAnalogValue[JOYSTICK_MAX_BUTTON_COUNT]; + }; + + + HWND m_ChainedWndProc; + HWND m_hAttachedHWnd; + bool m_bEnabled; + bool m_bPumpEnabled; + bool m_bIsPolling; + bool m_bIMEComposing; + bool m_bMouseCursorVisible; + bool m_bJoystickCursorVisible; + bool m_bIsInGame; // Delay joystick polling if in-game. + + // Current button state + InputState_t m_InputState[INPUT_STATE_COUNT]; + + // Current button state mutex + CRITICAL_SECTION m_InputStateMutex; + int unknown0; + short unknown1; + bool unknown2; + + // Analog event mutex + CRITICAL_SECTION m_AnalogEventMutex; + int unknown3; + short unknown4; + bool unknown5; + + // Analog events + InputEvent_t m_AnalogEvents[JOYSTICK_AXIS_BUTTON_COUNT]; + int m_AnalogEventTypes[JOYSTICK_AXIS_BUTTON_COUNT]; + + // Button events + InputEvent_t m_Events[128]; + InputEvent_t m_CurrentEvent; + + DWORD m_StartupTimeTick; + int m_nLastPollTick; + int m_nLastSampleTick; + int m_nLastAnalogPollTick; + int m_nLastAnalogSampleTick; + + // Mouse wheel hack + UINT m_uiMouseWheel; + + // Xbox controller info + int m_nJoystickCount; + appKey_t m_appXKeys[XUSER_MAX_COUNT][XK_MAX_KEYS+2]; + char pad_unk[16]; + xdevice_t m_XDevices[XUSER_MAX_COUNT]; + + // Used to determine whether to generate UI events + int m_nUIEventClientCount; + + // Raw mouse input + bool m_bRawInputSupported; + CRITICAL_SECTION m_MouseAccumMutex; + int m_mouseRawAccumX; + int m_mouseRawAccumY; + + _BYTE gap1785[8]; + + // Current mouse capture window + PlatWindow_t m_hCurrentCaptureWnd; + + // For the 'SleepUntilInput' feature + HANDLE m_hEvent; + + InputCursorHandle_t m_pDefaultCursors[INPUT_CURSOR_COUNT]; + CUtlStringMap m_UserCursors; + + CSysModule* m_pXInputDLL; + CSysModule* m_pRawInputDLL; + + // NVNT falcon module + CSysModule* m_pNovintDLL; // Unused in R5? + + bool m_bIgnoreLocalJoystick; + InputCursorHandle_t m_hCursor; }; /////////////////////////////////////////////////////////////////////////////// diff --git a/r5dev/public/inputsystem/AnalogCode.h b/r5dev/public/inputsystem/AnalogCode.h new file mode 100644 index 00000000..cb439583 --- /dev/null +++ b/r5dev/public/inputsystem/AnalogCode.h @@ -0,0 +1,38 @@ +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#ifndef ANALOGCODE_H +#define ANALOGCODE_H +#include "inputsystem/InputEnums.h" + + +//----------------------------------------------------------------------------- +// Macro to get at joystick codes +//----------------------------------------------------------------------------- +#define JOYSTICK_AXIS_INTERNAL( _joystick, _axis ) ( JOYSTICK_FIRST_AXIS + ((_joystick) * MAX_JOYSTICK_AXES) + (_axis) ) +#define JOYSTICK_AXIS( _joystick, _axis ) ( (AnalogCode_t)JOYSTICK_AXIS_INTERNAL( _joystick, _axis ) ) + + +//----------------------------------------------------------------------------- +// Enumeration for analog input devices. Includes joysticks, mousewheel, mouse +//----------------------------------------------------------------------------- +enum AnalogCode_t +{ + ANALOG_CODE_INVALID = -1, + MOUSE_X = 0, + MOUSE_Y, + MOUSE_XY, // Invoked when either x or y changes + MOUSE_WHEEL, + + JOYSTICK_FIRST_AXIS, + JOYSTICK_LAST_AXIS = JOYSTICK_AXIS_INTERNAL(MAX_JOYSTICKS - 1, MAX_JOYSTICK_AXES - 1), + + ANALOG_CODE_LAST, +}; + + +#endif // ANALOGCODE_H diff --git a/r5dev/public/inputsystem/ButtonCode.h b/r5dev/public/inputsystem/ButtonCode.h index 8ac9b09c..0f9c2df1 100644 --- a/r5dev/public/inputsystem/ButtonCode.h +++ b/r5dev/public/inputsystem/ButtonCode.h @@ -1,5 +1,6 @@ #pragma once #include "InputEnums.h" +#include "common/xbox/xboxstubs.h" #define JOYSTICK_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_BUTTON + ((_joystick) * JOYSTICK_MAX_BUTTON_COUNT) + (_button) ) #define JOYSTICK_POV_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_POV_BUTTON + ((_joystick) * JOYSTICK_POV_BUTTON_COUNT) + (_button) ) @@ -11,7 +12,7 @@ enum { - JOYSTICK_MAX_BUTTON_COUNT = 26, + JOYSTICK_MAX_BUTTON_COUNT = XK_MAX_KEYS, JOYSTICK_POV_BUTTON_COUNT = 4, JOYSTICK_AXIS_BUTTON_COUNT = MAX_JOYSTICK_AXES * 2, }; diff --git a/r5dev/public/inputsystem/InputEnums.h b/r5dev/public/inputsystem/InputEnums.h index 638c7c10..7f7c5f99 100644 --- a/r5dev/public/inputsystem/InputEnums.h +++ b/r5dev/public/inputsystem/InputEnums.h @@ -84,9 +84,11 @@ enum InputEventType_t struct InputEvent_t { - const char* m_pCommand; - int m_nTick; - bool m_bDown; + int m_nType; // Type of the event (see InputEventType_t) + int m_nTick; // Tick on which the event occurred + int m_nData; // Generic 32-bit data, what it contains depends on the event + int m_nData2; // Generic 32-bit data, what it contains depends on the event + int m_nData3; // Generic 32-bit data, what it contains depends on the event }; #endif // INPUTENUMS_H diff --git a/r5dev/public/inputsystem/iinputsystem.h b/r5dev/public/inputsystem/iinputsystem.h new file mode 100644 index 00000000..578ef757 --- /dev/null +++ b/r5dev/public/inputsystem/iinputsystem.h @@ -0,0 +1,149 @@ +//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======// +// +// Purpose: +// +//===========================================================================// +#ifndef IINPUTSYSTEM_H +#define IINPUTSYSTEM_H + +#include "inputsystem/ButtonCode.h" +#include "inputsystem/AnalogCode.h" +#include "inputsystem/InputEnums.h" + +///----------------------------------------------------------------------------- +/// A handle to a cursor icon +///----------------------------------------------------------------------------- +DECLARE_POINTER_HANDLE( InputCursorHandle_t ); +#define INPUT_CURSOR_HANDLE_INVALID ( (InputCursorHandle_t)0 ) + + +///----------------------------------------------------------------------------- +/// An enumeration describing well-known cursor icons +///----------------------------------------------------------------------------- +enum InputStandardCursor_t +{ + INPUT_CURSOR_NONE = 0, + INPUT_CURSOR_ARROW, + INPUT_CURSOR_IBEAM, + INPUT_CURSOR_HOURGLASS, + INPUT_CURSOR_CROSSHAIR, + INPUT_CURSOR_WAITARROW, + INPUT_CURSOR_UP, + INPUT_CURSOR_SIZE_NW_SE, + INPUT_CURSOR_SIZE_NE_SW, + INPUT_CURSOR_SIZE_W_E, + INPUT_CURSOR_SIZE_N_S, + INPUT_CURSOR_SIZE_ALL, + INPUT_CURSOR_NO, + INPUT_CURSOR_HAND, + + INPUT_CURSOR_COUNT +}; + +//----------------------------------------------------------------------------- +// Main interface for input. This is a low-level interface +//----------------------------------------------------------------------------- +#define INPUTSYSTEM_INTERFACE_VERSION "InputSystemVersion001" +abstract_class IInputSystem : public IAppSystem +{ +public: + /// Attach, detach input system from a particular window + /// This window should be the root window for the application + /// Only 1 window should be attached at any given time. + virtual void AttachToWindow( const void* const hWnd ) = 0; + virtual void DetachFromWindow( ) = 0; + + /// Enables/disables input. PollInputState will not update current + /// button/analog states when it is called if the system is disabled. + virtual void EnableInput( const bool bEnable ) = 0; + + /// Enables/disables the windows message pump. PollInputState will not. + /// Peek/Dispatch messages if this is disabled. + virtual void EnableMessagePump( const bool bEnable ) = 0; + + /// Gets the time of the last polling in ms. + virtual int GetPollTick() const = 0; + + /// Is a button down? "Buttons" are binary-state input devices (mouse buttons, keyboard keys). + virtual bool IsButtonDown( const ButtonCode_t code ) const = 0; + + /// Returns the tick at which the button was pressed and released + virtual int GetButtonPressedTick( const ButtonCode_t code ) const = 0; + + /// TODO[ AMOS ]: reverse this further ( returns an enum ? )... + virtual int GetJoystickDeadzoneIndex( ) const = 0; + + /// DoNothing; VFTable padding. + virtual bool ReturnFalse( ) const = 0; + + /// Polls the current input state. + virtual void PollInputState( const void* const eventCallback ) = 0; + + /// Posts a user-defined event into the event queue; this is expected + /// to be called in overridden wndprocs connected to the root panel. + virtual void PostUserEvent( const InputEvent_t &event ) = 0; + virtual void PostUserEvent( const InputEventType_t type ) = 0; + + /// Returns the number of joysticks + virtual int GetJoystickCount( ) const = 0; + + /// Sample the joystick and append events to the input queue. + virtual void SampleDevices( void ) = 0; + + virtual void SetRumble( const float fLeftMainMotor, const float fRightMainMotor, const float fLeftTriggerMotor, const float fRightTriggerMotor, const int userId = INVALID_USER_ID ) = 0; + virtual void StopRumble( const int userId = INVALID_USER_ID ) = 0; + + /// Resets the input state. + virtual void ResetInputState() = 0; + + /// Convert back + forth between ButtonCode/AnalogCode + strings. + virtual const char* ButtonCodeToString( const ButtonCode_t code ) const = 0; + virtual ButtonCode_t StringToButtonCode( const char* const pString ) const = 0; + + /// Sleeps until input happens. Pass a negative number to sleep infinitely. + virtual void SleepUntilInput( const int nMaxSleepTimeMS = -1 ) = 0; + + /// Convert back + forth between virtual codes + button codes + virtual ButtonCode_t VirtualKeyToButtonCode( const int nVirtualKey ) const = 0; + virtual int ButtonCodeToVirtualKey( const ButtonCode_t code ) const = 0; + + /// Sets the cursor position. + virtual void SetCursorPosition( const int x, const int y ) = 0; + + /// Tells the input system to generate UI-related events, defined + /// in inputsystem/inputenums.h (see IE_FirstUIEvent) + /// We could have multiple clients that care about UI-related events + /// so we refcount the clients with an Add/Remove strategy. If there + /// are no interested clients, the UI events are not generated. + virtual void AddUIEventListener() = 0; + virtual void RemoveUIEventListener() = 0; + + /// Creates a cursor using one of the well-known cursor icons. + virtual InputCursorHandle_t GetStandardCursor( const InputStandardCursor_t id ) = 0; + + /// Loads a cursor defined in a file. + virtual InputCursorHandle_t LoadCursorFromFile( const char* const pFileName, const char* const pPathID = NULL ) = 0; + + /// Sets the cursor icon. + virtual void SetCursorIcon( const InputCursorHandle_t hCursor ) = 0; + + /// Gets the cursor position. + virtual void GetCursorPosition( const int* const pX, const int* const pY ) = 0; + + /// Mouse capture. + virtual void EnableMouseCapture( const PlatWindow_t hWnd ) = 0; + virtual void DisableMouseCapture( ) = 0; + + // Mouse/Joystick cursor visibility, tell inputsystem when we hide stuff rather than querying the OS which is expensive on OSX. + virtual void SetMouseCursorVisible( const bool bVisible ) = 0; + virtual void SetJoystickCursorVisible( const bool bVisible ) = 0; + + /// Reset the current cursor icon. Used to reset the icon in the case of alt+tabs where the cursor has been forced to a different + /// icon because it was outside of the client rect during the reload. + virtual void ResetCursorIcon() = 0; + + // read and clear accumulated raw input values. + virtual void GetRawMouseAccumulators( int& accumX, int& accumY ) = 0; +}; + +#endif // IINPUTSYSTEM_H