From 9cd608338e48ca6b8e7bb17bbed770cbbf11368a Mon Sep 17 00:00:00 2001 From: Johannes <52950755+Sumandora@users.noreply.github.com> Date: Tue, 12 Sep 2023 18:59:39 +0200 Subject: [PATCH] Rewrite cursor tracking, stop mouse warping --- Source/Features/General/Menu.cpp | 7 ++- Source/Features/General/Menu.hpp | 2 +- Source/GUI/GUI.cpp | 55 +++++++++---------- Source/GUI/GUI.hpp | 2 +- .../SDL/Functions/SetRelativeMouseMode.cpp | 11 ++++ .../Hooks/SDL/Functions/WarpMouseInWindow.cpp | 2 +- Source/Hooks/SDL/SDLFunctions.cpp | 2 + Source/Hooks/SDL/SDLFunctions.hpp | 19 +++++++ 8 files changed, 67 insertions(+), 33 deletions(-) create mode 100644 Source/Hooks/SDL/Functions/SetRelativeMouseMode.cpp diff --git a/Source/Features/General/Menu.cpp b/Source/Features/General/Menu.cpp index 4c0a45b..b2e13d1 100644 --- a/Source/Features/General/Menu.cpp +++ b/Source/Features/General/Menu.cpp @@ -24,9 +24,14 @@ void Menu::MenuKey::onChange() { Gui::visible = !Gui::visible; eventLog.createReport("%s the menu", Gui::visible ? "Opened" : "Closed"); + reinterpret_cast(Hooks::SDL::SetRelativeMouseMode::hook->proxy)(Gui::visible ? SDL_FALSE : Hooks::SDL::relativeMouseMode); + if (Gui::visible) { + ImGuiIO& io = ImGui::GetIO(); + reinterpret_cast(Hooks::SDL::WarpMouseInWindow::hook->proxy)(Hooks::SDL::windowPtr, (int)io.MousePos.x, (int)io.MousePos.y); + } } -void Menu::imGuiLoop() +void Menu::imGuiLoop() const { switch (style) { case 0: diff --git a/Source/Features/General/Menu.hpp b/Source/Features/General/Menu.hpp index 4ab5b50..9aa62e1 100644 --- a/Source/Features/General/Menu.hpp +++ b/Source/Features/General/Menu.hpp @@ -35,7 +35,7 @@ inline class Menu : public Feature { bool isShowingUserGuide = false; #endif - void imGuiLoop(); + void imGuiLoop() const; virtual void setupGUI() override; virtual SERIALIZER() override; diff --git a/Source/GUI/GUI.cpp b/Source/GUI/GUI.cpp index 680c49a..74004d3 100644 --- a/Source/GUI/GUI.cpp +++ b/Source/GUI/GUI.cpp @@ -2,10 +2,7 @@ #include #include -#include -#include #include -#include #include "Elements/Keybind.hpp" #include "imgui.h" @@ -14,8 +11,6 @@ #include "backends/imgui_impl_opengl3.h" #include "backends/imgui_impl_sdl2.h" -#include "../Hooks/SDL/SDLFunctions.hpp" - #include "../Features/General/EventLog.hpp" #include "../Features/General/Menu.hpp" #include "../Features/General/Watermark.hpp" @@ -26,8 +21,6 @@ #include "../Features/Visuals/ESP/ESP.hpp" #include "../Features/Visuals/SpectatorList.hpp" -#include "../Serialization/Serialization.hpp" - bool Gui::visible = true; void Gui::create() @@ -119,6 +112,8 @@ void Gui::swapWindow(SDL_Window* window) esp.imGuiRender(ImGui::GetBackgroundDrawList()); spectatorList.imGuiRender(ImGui::GetBackgroundDrawList()); + ImGui::GetForegroundDrawList()->AddRectFilled({ io.MousePos.x - 5, io.MousePos.y - 5 }, { io.MousePos.x + 5, io.MousePos.y + 5 }, ImGuiColors::red); + io.MouseDrawCursor = visible; io.WantCaptureMouse = visible; io.WantCaptureKeyboard = visible; @@ -127,37 +122,39 @@ void Gui::swapWindow(SDL_Window* window) ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); } -// I don't even want to know why I have to do this -static Uint32 lastTextInput; - bool Gui::pollEvent(SDL_Event* event) { - if (event->type == SDL_TEXTINPUT && lastTextInput >= event->text.timestamp) - return visible; - - ImGuiIO& io = ImGui::GetIO(); - // Emulate these 2 events, because ImGui is broken... :c - if (event->type == SDL_MOUSEMOTION) { - int x, y; - SDL_GetMouseState(&x, &y); + static Uint32 lastEvent; + if (event->type == SDL_TEXTINPUT) { + if (event->text.timestamp <= lastEvent) + return visible; // Not quite sure, why I have to do this + lastEvent = event->text.timestamp; + } - io.MousePos.x = (float)x; - io.MousePos.y = (float)y; - if (visible && SDL_GetMouseFocus() == Hooks::SDL::windowPtr) - reinterpret_cast(Hooks::SDL::WarpMouseInWindow::hook->proxy)(Hooks::SDL::windowPtr, (int)io.MousePos.x, (int)io.MousePos.y); - } else if (event->type == SDL_MOUSEWHEEL) { - io.MouseWheelH += (float)event->wheel.x; - io.MouseWheel += (float)event->wheel.y; +#if SDL_VERSION_ATLEAST(2, 0, 18) + // CS:GOs SDL is 2.0.15, however we can't realistically expect users to download this ancient version, so just do this + // preciseX/Y got introduced in 2.0.18 + if (event->type == SDL_MOUSEWHEEL) { + SDL_MouseWheelEvent sdlMouseWheelEvent{}; + sdlMouseWheelEvent.type = SDL_MOUSEWHEEL; + sdlMouseWheelEvent.preciseX = (float)event->wheel.x; + sdlMouseWheelEvent.preciseY = (float)event->wheel.y; + SDL_Event newEvent; + newEvent.wheel = sdlMouseWheelEvent; + ImGui_ImplSDL2_ProcessEvent(&newEvent); } else +#endif ImGui_ImplSDL2_ProcessEvent(event); - if (event->type == SDL_TEXTINPUT) - lastTextInput = event->text.timestamp; - return visible; } -bool Gui::warpMouseInWindow() +bool Gui::warpMouseInWindow(int x, int y) { + if (!visible) { + ImGuiIO& io = ImGui::GetIO(); + io.MousePos.x = (float)x; + io.MousePos.y = (float)y; + } return visible; } diff --git a/Source/GUI/GUI.hpp b/Source/GUI/GUI.hpp index 5f42d66..8e5e4d4 100644 --- a/Source/GUI/GUI.hpp +++ b/Source/GUI/GUI.hpp @@ -13,7 +13,7 @@ namespace Gui { void swapWindow(SDL_Window* window); bool pollEvent(SDL_Event* event); - bool warpMouseInWindow(); + bool warpMouseInWindow(int x, int y); } #endif diff --git a/Source/Hooks/SDL/Functions/SetRelativeMouseMode.cpp b/Source/Hooks/SDL/Functions/SetRelativeMouseMode.cpp new file mode 100644 index 0000000..5e2890f --- /dev/null +++ b/Source/Hooks/SDL/Functions/SetRelativeMouseMode.cpp @@ -0,0 +1,11 @@ +#include "../SDLFunctions.hpp" + +#include "../../../GUI/GUI.hpp" + +int Hooks::SDL::SetRelativeMouseMode::hookFunc(SDL_bool enabled) +{ + relativeMouseMode = enabled; + if(!Gui::visible) + return reinterpret_cast(hook->proxy)(enabled); + return 0; // :thumbsup: +} \ No newline at end of file diff --git a/Source/Hooks/SDL/Functions/WarpMouseInWindow.cpp b/Source/Hooks/SDL/Functions/WarpMouseInWindow.cpp index 005818d..1e58dbe 100644 --- a/Source/Hooks/SDL/Functions/WarpMouseInWindow.cpp +++ b/Source/Hooks/SDL/Functions/WarpMouseInWindow.cpp @@ -4,7 +4,7 @@ void Hooks::SDL::WarpMouseInWindow::hookFunc(SDL_Window* window, int x, int y) { - if (Gui::warpMouseInWindow()) + if (Gui::warpMouseInWindow(x, y)) return; return reinterpret_cast(hook->proxy)(window, x, y); diff --git a/Source/Hooks/SDL/SDLFunctions.cpp b/Source/Hooks/SDL/SDLFunctions.cpp index b9c5b60..d0f0726 100644 --- a/Source/Hooks/SDL/SDLFunctions.cpp +++ b/Source/Hooks/SDL/SDLFunctions.cpp @@ -8,10 +8,12 @@ void Hooks::SDL::hook() WarpMouseInWindow::hook = new SDLHook(reinterpret_cast(SDL_WarpMouseInWindow), reinterpret_cast(WarpMouseInWindow::hookFunc)); SwapWindow::hook = new SDLHook(reinterpret_cast(SDL_GL_SwapWindow), reinterpret_cast(SwapWindow::hookFunc)); PollEvent::hook = new SDLHook(reinterpret_cast(SDL_PollEvent), reinterpret_cast(PollEvent::hookFunc)); + SetRelativeMouseMode::hook = new SDLHook(reinterpret_cast(SDL_SetRelativeMouseMode), reinterpret_cast(SetRelativeMouseMode::hookFunc)); } void Hooks::SDL::unhook() { + delete SetRelativeMouseMode::hook; delete PollEvent::hook; delete SwapWindow::hook; delete WarpMouseInWindow::hook; diff --git a/Source/Hooks/SDL/SDLFunctions.hpp b/Source/Hooks/SDL/SDLFunctions.hpp index 4563f00..ffb1ea2 100644 --- a/Source/Hooks/SDL/SDLFunctions.hpp +++ b/Source/Hooks/SDL/SDLFunctions.hpp @@ -9,6 +9,19 @@ namespace Hooks::SDL { inline SDL_Window* windowPtr = nullptr; inline bool shuttingDown = false; + inline struct BackupVariable { + SDL_bool enabled = SDL_GetRelativeMouseMode(); + ~BackupVariable() { SDL_SetRelativeMouseMode(enabled); } + + inline SDL_bool& operator=(SDL_bool other) { + enabled = other; + return enabled; + } + inline operator SDL_bool() const { + return enabled; + } + } relativeMouseMode; + namespace SwapWindow { inline SDLHook* hook; @@ -33,6 +46,12 @@ namespace Hooks::SDL { void hookFunc(SDL_Window* window); } + namespace SetRelativeMouseMode { + inline SDLHook* hook; + + int hookFunc(SDL_bool enabled); + } + void hook(); void unhook(); }