Merge pull request #230 from GEEKiDoS/develop

Add RawMouse Compoment
This commit is contained in:
Edo 2022-05-03 09:27:25 +01:00 committed by GitHub
commit 6f057d3af7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 268 additions and 4 deletions

View File

@ -105,6 +105,7 @@ namespace Components
Loader::Register(new Elevators());
Loader::Register(new ClientCommand());
Loader::Register(new ScriptExtension());
Loader::Register(new RawMouse());
Loader::Pregame = false;
}

View File

@ -134,6 +134,6 @@ namespace Components
#include "Modules/Movement.hpp"
#include "Modules/Elevators.hpp"
#include "Modules/ClientCommand.hpp"
#include "Modules/Gamepad.hpp"
#include "Modules/ScriptExtension.hpp"
#include "Modules/RawMouse.hpp"

View File

@ -0,0 +1,162 @@
#include <STDInclude.hpp>
namespace Components
{
Dvar::Var RawMouse::M_RawInput;
int RawMouse::MouseRawX = 0;
int RawMouse::MouseRawY = 0;
void RawMouse::IN_ClampMouseMove()
{
tagRECT rc;
tagPOINT curPos;
GetCursorPos(&curPos);
GetWindowRect(Window::GetWindow(), &rc);
auto isClamped = false;
if (curPos.x >= rc.left)
{
if (curPos.x >= rc.right)
{
curPos.x = rc.right - 1;
isClamped = true;
}
}
else
{
curPos.x = rc.left;
isClamped = true;
}
if (curPos.y >= rc.top)
{
if (curPos.y >= rc.bottom)
{
curPos.y = rc.bottom - 1;
isClamped = true;
}
}
else
{
curPos.y = rc.top;
isClamped = true;
}
if (isClamped)
{
SetCursorPos(curPos.x, curPos.y);
}
}
BOOL RawMouse::OnRawInput(LPARAM lParam, WPARAM)
{
auto dwSize = sizeof(RAWINPUT);
static BYTE lpb[sizeof(RAWINPUT)];
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER));
auto* raw = reinterpret_cast<RAWINPUT*>(lpb);
if (raw->header.dwType == RIM_TYPEMOUSE)
{
// Is there's really absolute mouse on earth?
if (raw->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
{
MouseRawX = raw->data.mouse.lLastX;
MouseRawY = raw->data.mouse.lLastY;
}
else
{
MouseRawX += raw->data.mouse.lLastX;
MouseRawY += raw->data.mouse.lLastY;
}
}
return TRUE;
}
void RawMouse::IN_RawMouseMove()
{
static auto r_fullscreen = Dvar::Var("r_fullscreen");
if (GetForegroundWindow() == Window::GetWindow())
{
if (r_fullscreen.get<bool>())
IN_ClampMouseMove();
static auto oldX = 0, oldY = 0;
auto dx = MouseRawX - oldX;
auto dy = MouseRawY - oldY;
oldX = MouseRawX;
oldY = MouseRawY;
// Don't use raw input for menu?
// Because it needs to call the ScreenToClient
tagPOINT curPos;
GetCursorPos(&curPos);
Game::s_wmv->oldPos = curPos;
ScreenToClient(Window::GetWindow(), &curPos);
auto recenterMouse = Game::CL_MouseEvent(curPos.x, curPos.y, dx, dy);
if (recenterMouse)
{
Game::IN_RecenterMouse();
}
}
}
void RawMouse::IN_RawMouse_Init()
{
if (Window::GetWindow() && RawMouse::M_RawInput.get<bool>())
{
#ifdef DEBUG
Logger::Print("Raw Mouse Init.\n");
#endif
RAWINPUTDEVICE Rid[1];
Rid[0].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC
Rid[0].usUsage = 0x02; // HID_USAGE_GENERIC_MOUSE
Rid[0].dwFlags = RIDEV_INPUTSINK;
Rid[0].hwndTarget = Window::GetWindow();
RegisterRawInputDevices(Rid, ARRAYSIZE(Rid), sizeof(Rid[0]));
}
}
void RawMouse::IN_Init()
{
Game::IN_Init();
IN_RawMouse_Init();
}
void RawMouse::IN_MouseMove()
{
if (RawMouse::M_RawInput.get<bool>())
{
IN_RawMouseMove();
}
else
{
Game::IN_MouseMove();
}
}
RawMouse::RawMouse()
{
Utils::Hook(0x475E65, RawMouse::IN_MouseMove, HOOK_JUMP).install()->quick();
Utils::Hook(0x475E8D, RawMouse::IN_MouseMove, HOOK_JUMP).install()->quick();
Utils::Hook(0x475E9E, RawMouse::IN_MouseMove, HOOK_JUMP).install()->quick();
Utils::Hook(0x467C03, RawMouse::IN_Init, HOOK_CALL).install()->quick();
Utils::Hook(0x64D095, RawMouse::IN_Init, HOOK_JUMP).install()->quick();
Dvar::OnInit([]()
{
RawMouse::M_RawInput = Dvar::Register<bool>("m_rawinput", true, Game::dvar_flag::DVAR_ARCHIVE, "Use raw mouse input, Improves accuracy & has better support for higher polling rates. Use in_restart to take effect if not enabled.");
});
Window::OnWndMessage(WM_INPUT, RawMouse::OnRawInput);
Window::OnCreate(RawMouse::IN_RawMouse_Init);
}
}

View File

@ -0,0 +1,20 @@
#pragma once
namespace Components
{
class RawMouse : public Component
{
public:
RawMouse();
private:
static Dvar::Var M_RawInput;
static int MouseRawX, MouseRawY;
static void IN_ClampMouseMove();
static BOOL OnRawInput(LPARAM lParam, WPARAM);
static void IN_RawMouseMove();
static void IN_RawMouse_Init();
static void IN_Init();
static void IN_MouseMove();
};
}

View File

@ -7,6 +7,8 @@ namespace Components
HWND Window::MainWindow = nullptr;
BOOL Window::CursorVisible = TRUE;
std::unordered_map<UINT, Utils::Slot<Window::WndProcCallback>> Window::WndMessageCallbacks;
Utils::Signal<Window::CreateCallback> Window::CreateSignals;
int Window::Width()
{
@ -66,6 +68,16 @@ namespace Components
return Window::MainWindow;
}
void Window::OnWndMessage(UINT Msg, Utils::Slot<Window::WndProcCallback> callback)
{
WndMessageCallbacks.emplace(Msg, callback);
}
void Window::OnCreate(Utils::Slot<CreateCallback> callback)
{
CreateSignals.connect(callback);
}
int Window::IsNoBorder()
{
return Window::NoBorder.get<bool>();
@ -121,6 +133,9 @@ namespace Components
HWND WINAPI Window::CreateMainWindow(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
{
Window::MainWindow = CreateWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
CreateSignals();
return Window::MainWindow;
}
@ -132,15 +147,21 @@ namespace Components
BOOL WINAPI Window::MessageHandler(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if (Msg == WM_SETCURSOR)
if (const auto cb = WndMessageCallbacks.find(Msg); cb != WndMessageCallbacks.end())
{
Window::ApplyCursor();
return TRUE;
return cb->second(lParam, wParam);
}
return Utils::Hook::Call<BOOL(__stdcall)(HWND, UINT, WPARAM, LPARAM)>(0x4731F0)(hWnd, Msg, wParam, lParam);
}
void Window::EnableDpiAwareness()
{
const Utils::Library user32{"user32.dll"};
user32.invokePascal<void>("SetProcessDpiAwarenessContext", DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
}
Window::Window()
{
// Borderless window
@ -184,5 +205,13 @@ namespace Components
// Use custom message handler
Utils::Hook::Set(0x64D298, Window::MessageHandler);
Window::OnWndMessage(WM_SETCURSOR, [](WPARAM, LPARAM)
{
Window::ApplyCursor();
return TRUE;
});
Window::EnableDpiAwareness();
}
}

View File

@ -5,6 +5,9 @@ namespace Components
class Window : public Component
{
public:
typedef BOOL(WndProcCallback)(WPARAM wParam, LPARAM lParam);
typedef void(CreateCallback)();
Window();
static int Width();
@ -18,10 +21,15 @@ namespace Components
static HWND GetWindow();
static void OnWndMessage(UINT Msg, Utils::Slot<WndProcCallback> callback);
static void OnCreate(Utils::Slot<CreateCallback> callback);
private:
static BOOL CursorVisible;
static Dvar::Var NoBorder;
static Dvar::Var NativeCursor;
static std::unordered_map<UINT, Utils::Slot<WndProcCallback>> WndMessageCallbacks;
static Utils::Signal<CreateCallback> CreateSignals;
static HWND MainWindow;
@ -36,5 +44,7 @@ namespace Components
static void StyleHookStub();
static HWND WINAPI CreateMainWindow(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam);
static void EnableDpiAwareness();
};
}

View File

@ -421,6 +421,13 @@ namespace Game
PM_Trace_t PM_Trace = PM_Trace_t(0x441F60);
PM_GetEffectiveStance_t PM_GetEffectiveStance = PM_GetEffectiveStance_t(0x412540);
CL_MouseEvent_t CL_MouseEvent = CL_MouseEvent_t(0x4D7C50);
IN_RecenterMouse_t IN_RecenterMouse = IN_RecenterMouse_t(0x463D80);
IN_MouseMove_t IN_MouseMove = IN_MouseMove_t(0x64C490);
IN_Init_t IN_Init = IN_Init_t(0x45D620);
IN_Shutdown_t IN_Shutdown = IN_Shutdown_t(0x426360);
XAssetHeader* DB_XAssetPool = reinterpret_cast<XAssetHeader*>(0x7998A8);
unsigned int* g_poolSize = reinterpret_cast<unsigned int*>(0x7995E8);
@ -543,6 +550,11 @@ namespace Game
level_locals_t* level = reinterpret_cast<level_locals_t*>(0x1A831A8);
WinMouseVars_t* s_wmv = reinterpret_cast<WinMouseVars_t*>(0x649D640);
int* window_center_x = reinterpret_cast<int*>(0x649D638);
int* window_center_y = reinterpret_cast<int*>(0x649D630);
void Sys_LockRead(FastCriticalSection* critSect)
{
InterlockedIncrement(&critSect->readCount);

View File

@ -1005,6 +1005,21 @@ namespace Game
typedef EffectiveStance(__cdecl * PM_GetEffectiveStance_t)(const playerState_s* ps);
extern PM_GetEffectiveStance_t PM_GetEffectiveStance;
typedef int(__cdecl * CL_MouseEvent_t)(int x, int y, int dx, int dy);
extern CL_MouseEvent_t CL_MouseEvent;
typedef void(__cdecl * IN_RecenterMouse_t)();
extern IN_RecenterMouse_t IN_RecenterMouse;
typedef void(__cdecl * IN_MouseMove_t)();
extern IN_MouseMove_t IN_MouseMove;
typedef void(__cdecl * IN_Init_t)();
extern IN_Init_t IN_Init;
typedef void(__cdecl * IN_Shutdown_t)();
extern IN_Shutdown_t IN_Shutdown;
extern XAssetHeader* DB_XAssetPool;
extern unsigned int* g_poolSize;
@ -1133,6 +1148,11 @@ namespace Game
extern level_locals_t* level;
extern WinMouseVars_t* s_wmv;
extern int* window_center_x;
extern int* window_center_y;
void Sys_LockRead(FastCriticalSection* critSect);
void Sys_UnlockRead(FastCriticalSection* critSect);

View File

@ -7473,6 +7473,16 @@ namespace Game
static_assert(sizeof(level_locals_t) == 0x2F78);
struct WinMouseVars_t
{
int oldButtonState;
tagPOINT oldPos;
bool mouseActive;
bool mouseInitialized;
};
static_assert(sizeof(WinMouseVars_t) == 0x10);
#pragma endregion
#ifndef IDA