From f2f3c28048963b37379fe05d75b0f6636401fc71 Mon Sep 17 00:00:00 2001 From: Yimura <24669514+Yimura@users.noreply.github.com> Date: Fri, 16 Dec 2022 18:55:55 +0100 Subject: [PATCH] refactor: Renderer (#694) * Simplified SwapCHain, Device and DeviceContext pointers * Added DX and WndProc callback registration * Cleaned up GUI code * Optimised Mouse Toggle --- src/backend/looped/weapons/rapid_fire.cpp | 2 +- src/backend/looped/weapons/vehicle_gun.cpp | 2 +- src/common.hpp | 4 - src/gui.cpp | 160 +++++++++++++----- src/gui.hpp | 24 ++- src/hooks/gui/wndproc.cpp | 2 - src/main.cpp | 1 + src/renderer.cpp | 94 +++++----- src/renderer.hpp | 35 +++- .../context_menu/context_menu_service.cpp | 2 +- src/services/hotkey/hotkey_service.cpp | 6 + .../model_preview/model_preview_service.cpp | 2 +- .../notifications/notification_service.cpp | 3 + src/views/view.hpp | 11 -- src/views/view_gta_data.cpp | 2 +- 15 files changed, 219 insertions(+), 131 deletions(-) diff --git a/src/backend/looped/weapons/rapid_fire.cpp b/src/backend/looped/weapons/rapid_fire.cpp index fea89e15..f00b9bb4 100644 --- a/src/backend/looped/weapons/rapid_fire.cpp +++ b/src/backend/looped/weapons/rapid_fire.cpp @@ -10,7 +10,7 @@ namespace big { if (g->weapons.rapid_fire) { - if(!HUD::IS_PAUSE_MENU_ACTIVE() && !g_gui.m_opened && !PED::IS_PED_DEAD_OR_DYING(self::ped, true)) + if(!HUD::IS_PAUSE_MENU_ACTIVE() && !g_gui->is_open() && !PED::IS_PED_DEAD_OR_DYING(self::ped, true)) { if (PAD::IS_DISABLED_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_ATTACK)) { diff --git a/src/backend/looped/weapons/vehicle_gun.cpp b/src/backend/looped/weapons/vehicle_gun.cpp index 3db92de0..9488711c 100644 --- a/src/backend/looped/weapons/vehicle_gun.cpp +++ b/src/backend/looped/weapons/vehicle_gun.cpp @@ -17,7 +17,7 @@ namespace big const auto elapsed_time_in_ms = std::chrono::duration_cast(time_now - last_time).count(); if (is_vehicle_gun_selected && - !g_gui.m_opened && + !g_gui->is_open() && elapsed_time_in_ms >= 100 && PAD::IS_DISABLED_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_ATTACK)) { diff --git a/src/common.hpp b/src/common.hpp index e0e9a14b..5e3bd985 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -5,7 +5,6 @@ #include #include #include -#include #include #include @@ -61,9 +60,6 @@ namespace big { using namespace std::chrono_literals; - - template - using comptr = Microsoft::WRL::ComPtr; inline HMODULE g_hmodule{}; inline HANDLE g_main_thread{}; diff --git a/src/gui.cpp b/src/gui.cpp index d34565ea..3cb3c5b2 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -3,20 +3,60 @@ #include "gui.hpp" #include "natives.hpp" #include "script.hpp" +#include "renderer.hpp" #include -#include "widgets/imgui_hotkey.hpp" #include "views/view.hpp" namespace big { + gui::gui() : + m_is_open(false) + { + g_renderer->add_dx_callback(view::gta_data, -1); // -1 highest priority of drawing + g_renderer->add_dx_callback(view::notifications, -2); // second highest priority + g_renderer->add_dx_callback([this] + { + dx_on_tick(); + }, -3); // 3rd highest priority + + g_renderer->add_wndproc_callback([this](HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) + { + wndproc(hwnd, msg, wparam, lparam); + }); + + g_renderer->add_dx_callback(esp::draw, 2); // TODO: move to ESP service + g_renderer->add_dx_callback(view::context_menu, 1); + + dx_init(); + + g_gui = this; + } + + gui::~gui() + { + g_gui = nullptr; + } + + bool gui::is_open() + { + return m_is_open; + } + + void gui::toggle(bool toggle) + { + m_is_open = toggle; + + toggle_mouse(); + } + void gui::dx_init() { - static ImVec4 bgColor = ImVec4(0.09f, 0.094f, 0.129f, .9f); - static ImVec4 primary = ImVec4(0.172f, 0.380f, 0.909f, 1.f); - static ImVec4 secondary = ImVec4(0.443f, 0.654f, 0.819f, 1.f); - static ImVec4 whiteBroken = ImVec4(0.792f, 0.784f, 0.827f, 1.f); + static auto bgColor = ImVec4(0.09f, 0.094f, 0.129f, .9f); + static auto primary = ImVec4(0.172f, 0.380f, 0.909f, 1.f); + static auto secondary = ImVec4(0.443f, 0.654f, 0.819f, 1.f); + static auto whiteBroken = ImVec4(0.792f, 0.784f, 0.827f, 1.f); auto& style = ImGui::GetStyle(); style.WindowPadding = ImVec2(15, 15); @@ -73,61 +113,89 @@ namespace big void gui::dx_on_tick() { - ImGui::PushStyleColor(ImGuiCol_WindowBg, ImGui::ColorConvertU32ToFloat4(g->window.color)); - view::root(); - ImGui::PopStyleColor(); - } - - void gui::always_draw() - { - view::always(); + if (m_is_open) + { + ImGui::PushStyleColor(ImGuiCol_WindowBg, ImGui::ColorConvertU32ToFloat4(g->window.color)); + view::root(); + ImGui::PopStyleColor(); + } } void gui::script_on_tick() { - TRY_CLAUSE + if (g_gui->m_is_open) { - if (g_gui.m_opened) - { - for (uint8_t i = 0; i <= 6; i++) - PAD::DISABLE_CONTROL_ACTION(2, i, true); - PAD::DISABLE_CONTROL_ACTION(2, 106, true); - PAD::DISABLE_CONTROL_ACTION(2, 329, true); - PAD::DISABLE_CONTROL_ACTION(2, 330, true); + for (uint8_t i = 0; i <= 6; i++) + PAD::DISABLE_CONTROL_ACTION(2, i, true); + PAD::DISABLE_CONTROL_ACTION(2, 106, true); + PAD::DISABLE_CONTROL_ACTION(2, 329, true); + PAD::DISABLE_CONTROL_ACTION(2, 330, true); - PAD::DISABLE_CONTROL_ACTION(2, 14, true); - PAD::DISABLE_CONTROL_ACTION(2, 15, true); - PAD::DISABLE_CONTROL_ACTION(2, 16, true); - PAD::DISABLE_CONTROL_ACTION(2, 17, true); - PAD::DISABLE_CONTROL_ACTION(2, 24, true); - PAD::DISABLE_CONTROL_ACTION(2, 69, true); - PAD::DISABLE_CONTROL_ACTION(2, 70, true); - PAD::DISABLE_CONTROL_ACTION(2, 84, true); - PAD::DISABLE_CONTROL_ACTION(2, 85, true); - PAD::DISABLE_CONTROL_ACTION(2, 99, true); - PAD::DISABLE_CONTROL_ACTION(2, 92, true); - PAD::DISABLE_CONTROL_ACTION(2, 100, true); - PAD::DISABLE_CONTROL_ACTION(2, 114, true); - PAD::DISABLE_CONTROL_ACTION(2, 115, true); - PAD::DISABLE_CONTROL_ACTION(2, 121, true); - PAD::DISABLE_CONTROL_ACTION(2, 142, true); - PAD::DISABLE_CONTROL_ACTION(2, 241, true); - PAD::DISABLE_CONTROL_ACTION(2, 261, true); - PAD::DISABLE_CONTROL_ACTION(2, 257, true); - PAD::DISABLE_CONTROL_ACTION(2, 262, true); - PAD::DISABLE_CONTROL_ACTION(2, 331, true); - } + PAD::DISABLE_CONTROL_ACTION(2, 14, true); + PAD::DISABLE_CONTROL_ACTION(2, 15, true); + PAD::DISABLE_CONTROL_ACTION(2, 16, true); + PAD::DISABLE_CONTROL_ACTION(2, 17, true); + PAD::DISABLE_CONTROL_ACTION(2, 24, true); + PAD::DISABLE_CONTROL_ACTION(2, 69, true); + PAD::DISABLE_CONTROL_ACTION(2, 70, true); + PAD::DISABLE_CONTROL_ACTION(2, 84, true); + PAD::DISABLE_CONTROL_ACTION(2, 85, true); + PAD::DISABLE_CONTROL_ACTION(2, 99, true); + PAD::DISABLE_CONTROL_ACTION(2, 92, true); + PAD::DISABLE_CONTROL_ACTION(2, 100, true); + PAD::DISABLE_CONTROL_ACTION(2, 114, true); + PAD::DISABLE_CONTROL_ACTION(2, 115, true); + PAD::DISABLE_CONTROL_ACTION(2, 121, true); + PAD::DISABLE_CONTROL_ACTION(2, 142, true); + PAD::DISABLE_CONTROL_ACTION(2, 241, true); + PAD::DISABLE_CONTROL_ACTION(2, 261, true); + PAD::DISABLE_CONTROL_ACTION(2, 257, true); + PAD::DISABLE_CONTROL_ACTION(2, 262, true); + PAD::DISABLE_CONTROL_ACTION(2, 331, true); } - EXCEPT_CLAUSE } void gui::script_func() { - g_notification_service->push("Welcome", std::format("Loaded YimMenu. Press {} to open", ImGui::key_names[g->settings.hotkeys.menu_toggle])); while (true) { - g_gui.script_on_tick(); + g_gui->script_on_tick(); script::get_current()->yield(); } } + + void gui::wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) + { + if (msg == WM_KEYUP && wparam == g->settings.hotkeys.menu_toggle) + { + //Persist and restore the cursor position between menu instances. + static POINT cursor_coords{}; + if (g_gui->m_is_open) + { + GetCursorPos(&cursor_coords); + } + else if (cursor_coords.x + cursor_coords.y != 0) + { + SetCursorPos(cursor_coords.x, cursor_coords.y); + } + + toggle(g->settings.hotkeys.editing_menu_toggle || !m_is_open); + if (g->settings.hotkeys.editing_menu_toggle) + g->settings.hotkeys.editing_menu_toggle = false; + } + } + + void gui::toggle_mouse() + { + if (m_is_open) + { + ImGui::GetIO().MouseDrawCursor = true; + ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouse; + } + else + { + ImGui::GetIO().MouseDrawCursor = false; + ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouse; + } + } } diff --git a/src/gui.hpp b/src/gui.hpp index 6a4983b3..4f3464b0 100644 --- a/src/gui.hpp +++ b/src/gui.hpp @@ -6,15 +6,31 @@ namespace big class gui { public: + gui(); + virtual ~gui(); + gui(const gui&) = delete; + gui(gui&&) noexcept = delete; + gui& operator=(const gui&) = delete; + gui& operator=(gui&&) noexcept = delete; + + bool is_open(); + void toggle(bool toggle); + void dx_init(); void dx_on_tick(); - void always_draw(); void script_on_tick(); static void script_func(); - public: - bool m_opened{}; + + void wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); + + private: + void toggle_mouse(); + + private: + bool m_is_open; + }; - inline gui g_gui; + inline gui* g_gui; } diff --git a/src/hooks/gui/wndproc.cpp b/src/hooks/gui/wndproc.cpp index 10eb09a7..5fe2ad0b 100644 --- a/src/hooks/gui/wndproc.cpp +++ b/src/hooks/gui/wndproc.cpp @@ -1,7 +1,6 @@ #include "hooking.hpp" #include "renderer.hpp" #include "script.hpp" -#include "services/hotkey/hotkey_service.hpp" namespace big { @@ -12,7 +11,6 @@ namespace big if (g_running) { g_renderer->wndproc(hwnd, msg, wparam, lparam); - g_hotkey_service->wndproc(static_cast(msg), wparam); } return CallWindowProcW(g_hooking->m_og_wndproc, hwnd, msg, wparam, lparam); diff --git a/src/main.cpp b/src/main.cpp index f3e6d536..528958d4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -69,6 +69,7 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID) auto renderer_instance = std::make_unique(); LOG(INFO) << "Renderer initialized."; + auto gui_instance = std::make_unique(); auto fiber_pool_instance = std::make_unique(11); LOG(INFO) << "Fiber pool initialized."; diff --git a/src/renderer.cpp b/src/renderer.cpp index 8cd3e319..84097921 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -16,17 +16,11 @@ namespace big renderer::renderer() : m_dxgi_swapchain(*g_pointers->m_swapchain) { - void* d3d_device{}; - if (SUCCEEDED(m_dxgi_swapchain->GetDevice(__uuidof(ID3D11Device), &d3d_device))) - { - m_d3d_device.Attach(static_cast(d3d_device)); - } - else + if (m_dxgi_swapchain->GetDevice(__uuidof(ID3D11Device), reinterpret_cast(&m_d3d_device)) < 0) { throw std::runtime_error("Failed to get D3D device."); } - - m_d3d_device->GetImmediateContext(m_d3d_device_context.GetAddressOf()); + m_d3d_device->GetImmediateContext(&m_d3d_device_context); auto file_path = g_file_manager->get_project_file("./imgui.ini").get_path(); @@ -35,7 +29,7 @@ namespace big static std::string path = file_path.make_preferred().string(); ctx->IO.IniFilename = path.c_str(); - ImGui_ImplDX11_Init(m_d3d_device.Get(), m_d3d_device_context.Get()); + ImGui_ImplDX11_Init(m_d3d_device, m_d3d_device_context); ImGui_ImplWin32_Init(g_pointers->m_hwnd); folder windows_fonts( @@ -112,46 +106,40 @@ namespace big rescale(g->window.gui_scale); - g_gui.dx_init(); g_renderer = this; } renderer::~renderer() { + g_renderer = nullptr; + ImGui_ImplWin32_Shutdown(); ImGui_ImplDX11_Shutdown(); ImGui::DestroyContext(); + } - g_renderer = nullptr; + bool renderer::add_dx_callback(dx_callback callback, std::uint32_t priority) + { + if (!m_dx_callbacks.insert({ priority, callback }).second) + { + LOG(WARNING) << "Duplicate priority given on DX Callback!"; + + return false; + } + return true; + } + + void renderer::add_wndproc_callback(wndproc_callback callback) + { + m_wndproc_callbacks.emplace_back(callback); } void renderer::on_present() { - if (g_gui.m_opened) - { - ImGui::GetIO().MouseDrawCursor = true; - ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouse; - } - else - { - ImGui::GetIO().MouseDrawCursor = false; - ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouse; - } - - ImGui_ImplDX11_NewFrame(); - ImGui_ImplWin32_NewFrame(); - ImGui::NewFrame(); - - g_gui.always_draw(); - - if (g_gui.m_opened) - { - g_gui.dx_on_tick(); - } - - - ImGui::Render(); - ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); + new_frame(); + for (const auto& cb : m_dx_callbacks | std::views::values) + cb(); + end_frame(); } void renderer::rescale(float rel_size) @@ -174,27 +162,25 @@ namespace big void renderer::wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - if (msg == WM_KEYUP && wparam == g->settings.hotkeys.menu_toggle) - { - //Persist and restore the cursor position between menu instances. - static POINT cursor_coords{}; - if (g_gui.m_opened) - { - GetCursorPos(&cursor_coords); - } - else if (cursor_coords.x + cursor_coords.y != 0) - { - SetCursorPos(cursor_coords.x, cursor_coords.y); - } + for (const auto& cb : m_wndproc_callbacks) + cb(hwnd, msg, wparam, lparam); - g_gui.m_opened = g->settings.hotkeys.editing_menu_toggle || !g_gui.m_opened; - if (g->settings.hotkeys.editing_menu_toggle) - g->settings.hotkeys.editing_menu_toggle = false; - } - - if (g_gui.m_opened) + if (g_gui->is_open()) { ImGui_ImplWin32_WndProcHandler(hwnd, msg, wparam, lparam); } } + + void renderer::new_frame() + { + ImGui_ImplDX11_NewFrame(); + ImGui_ImplWin32_NewFrame(); + ImGui::NewFrame(); + } + + void renderer::end_frame() + { + ImGui::Render(); + ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); + } } diff --git a/src/renderer.hpp b/src/renderer.hpp index 6f204f19..e83b6ea5 100644 --- a/src/renderer.hpp +++ b/src/renderer.hpp @@ -1,15 +1,33 @@ #pragma once #include "common.hpp" -#include namespace big { - class renderer + using dx_callback = std::function; + using wndproc_callback = std::function; + + class renderer final { public: explicit renderer(); ~renderer(); + /** + * @brief Add a callback function to draw your ImGui content in + * + * @param callback Function + * @param priority The higher the priority the value the later it gets drawn on top + * @return true + * @return false + */ + bool add_dx_callback(dx_callback callback, std::uint32_t priority); + /** + * @brief Add a callback function on wndproc + * + * @param callback Function + */ + void add_wndproc_callback(wndproc_callback callback); + void on_present(); void rescale(float rel_size); @@ -20,9 +38,16 @@ namespace big void wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); private: - comptr m_dxgi_swapchain; - comptr m_d3d_device; - comptr m_d3d_device_context; + static void new_frame(); + static void end_frame(); + + private: + IDXGISwapChain* m_dxgi_swapchain; + ID3D11Device* m_d3d_device; + ID3D11DeviceContext* m_d3d_device_context; + + std::map m_dx_callbacks; + std::vector m_wndproc_callbacks; }; inline renderer* g_renderer{}; diff --git a/src/services/context_menu/context_menu_service.cpp b/src/services/context_menu/context_menu_service.cpp index ed07fa0c..f6f74a6d 100644 --- a/src/services/context_menu/context_menu_service.cpp +++ b/src/services/context_menu/context_menu_service.cpp @@ -300,7 +300,7 @@ namespace big continue; } - if (g_gui.m_opened) + if (g_gui->is_open()) { script::get_current()->yield(); continue; diff --git a/src/services/hotkey/hotkey_service.cpp b/src/services/hotkey/hotkey_service.cpp index 89dff88b..cc18b4c7 100644 --- a/src/services/hotkey/hotkey_service.cpp +++ b/src/services/hotkey/hotkey_service.cpp @@ -2,6 +2,7 @@ #include "fiber_pool.hpp" #include "util/teleport.hpp" #include "hotkey_functions.hpp" +#include "renderer.hpp" #include "network/ChatData.hpp" #include "pointers.hpp" @@ -14,6 +15,11 @@ namespace big register_hotkey("objective", g->settings.hotkeys.teleport_objective, teleport::to_objective); register_hotkey("noclip", g->settings.hotkeys.noclip, hotkey_funcs::toggle_noclip); + g_renderer->add_wndproc_callback([this](HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) + { + wndproc(static_cast(msg), wparam); + }); + g_hotkey_service = this; } diff --git a/src/services/model_preview/model_preview_service.cpp b/src/services/model_preview/model_preview_service.cpp index cd2a7ee7..727c879b 100644 --- a/src/services/model_preview/model_preview_service.cpp +++ b/src/services/model_preview/model_preview_service.cpp @@ -115,7 +115,7 @@ namespace big m_loop_running = true; while ( - g_running && m_running && g_gui.m_opened && + g_running && m_running && g_gui->is_open() && (m_ped_model_hash|| m_veh_model_hash) ) { Vector3 location; diff --git a/src/services/notifications/notification_service.cpp b/src/services/notifications/notification_service.cpp index d0f8f022..af7197e9 100644 --- a/src/services/notifications/notification_service.cpp +++ b/src/services/notifications/notification_service.cpp @@ -1,9 +1,12 @@ #include "notification_service.hpp" +#include "widgets/imgui_hotkey.hpp" namespace big { notification_service::notification_service() { + push("Welcome", std::format("Loaded YimMenu. Press {} to open", ImGui::key_names[g->settings.hotkeys.menu_toggle])); + g_notification_service = this; } diff --git a/src/views/view.hpp b/src/views/view.hpp index 25a60263..6be48d74 100644 --- a/src/views/view.hpp +++ b/src/views/view.hpp @@ -52,16 +52,5 @@ namespace big static void player_kick(); static void player_toxic(); static void player_misc(); - - // later calls will be drawn over earlier calls - static void always() - { - esp::draw(); - context_menu(); - - gta_data(); - - notifications(); - } }; } diff --git a/src/views/view_gta_data.cpp b/src/views/view_gta_data.cpp index c33c6426..36ab4810 100644 --- a/src/views/view_gta_data.cpp +++ b/src/views/view_gta_data.cpp @@ -12,7 +12,7 @@ namespace big if (g_gta_data_service->cache_needs_update()) { - g_gui.m_opened = true; + g_gui->toggle(true); ImGui::OpenPopup("Game Cache"); }