diff --git a/.gitmodules b/.gitmodules index 940663cc..e29de68d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -40,3 +40,6 @@ [submodule "deps/zlib"] path = deps/zlib url = https://github.com/madler/zlib.git +[submodule "deps/imgui"] + path = deps/imgui + url = https://github.com/ocornut/imgui.git diff --git a/deps/imgui b/deps/imgui new file mode 160000 index 00000000..0cdc4a95 --- /dev/null +++ b/deps/imgui @@ -0,0 +1 @@ +Subproject commit 0cdc4a956530cbe64a4e319446f8d9d2d7d149ee diff --git a/deps/premake/imgui.lua b/deps/premake/imgui.lua new file mode 100644 index 00000000..38b187b9 --- /dev/null +++ b/deps/premake/imgui.lua @@ -0,0 +1,39 @@ +imgui = { + source = path.join(dependencies.basePath, "imgui"), +} + +function imgui.import() + links { "imgui" } + imgui.includes() +end + +function imgui.includes() + includedirs { + imgui.source + } +end + +function imgui.project() + project "imgui" + language "C++" + + imgui.includes() + + files { + path.join(imgui.source, "*.cpp"), + path.join(imgui.source, "*.hpp"), + path.join(imgui.source, "*.c"), + path.join(imgui.source, "*.h"), + path.join(imgui.source, "backends/imgui_impl_dx11.cpp"), + path.join(imgui.source, "backends/imgui_impl_dx11.h"), + path.join(imgui.source, "backends/imgui_impl_win32.cpp"), + path.join(imgui.source, "backends/imgui_impl_win32.h"), + path.join(imgui.source, "misc/cpp/imgui_stdlib.cpp"), + path.join(imgui.source, "misc/cpp/imgui_stdlib.h"), + } + + warnings "Off" + kind "StaticLib" +end + +table.insert(dependencies, imgui) \ No newline at end of file diff --git a/src/client/component/gui.cpp b/src/client/component/gui.cpp new file mode 100644 index 00000000..3f19ce2a --- /dev/null +++ b/src/client/component/gui.cpp @@ -0,0 +1,154 @@ +#include +#include "loader/component_loader.hpp" + +#include "game/game.hpp" +#include "game/dvars.hpp" + +#include "scheduler.hpp" + +#include +#include + +extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + +namespace gui +{ + namespace + { + ID3D11Device* device; + ID3D11DeviceContext* device_context; + bool initialized = false; + bool toggled = false; + + void initialize_gui_context() + { + ImGui::CreateContext(); + ImGui::StyleColorsDark(); + + ImGui_ImplWin32_Init(*game::hWnd); + ImGui_ImplDX11_Init(device, device_context); + + initialized = true; + } + + void new_gui_frame() + { + ImGui_ImplDX11_NewFrame(); + ImGui_ImplWin32_NewFrame(); + ImGui::NewFrame(); + + *game::keyCatchers |= 0x10; + } + + void end_gui_frame() + { + ImGui::EndFrame(); + ImGui::Render(); + ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); + } + + void gui_draw() + { + + } + + void on_frame() + { + if (!initialized) + { + initialize_gui_context(); + } + + if (toggled) + { + new_gui_frame(); + gui_draw(); + end_gui_frame(); + } + } + + HRESULT d3d11_create_device_stub(IDXGIAdapter* pAdapter, D3D_DRIVER_TYPE DriverType, HMODULE Software, + UINT Flags, const D3D_FEATURE_LEVEL* pFeatureLevels, UINT FeatureLevels, UINT SDKVersion, + ID3D11Device** ppDevice, D3D_FEATURE_LEVEL* pFeatureLevel, ID3D11DeviceContext** ppImmediateContext) + { + const auto result = D3D11CreateDevice(pAdapter, DriverType, Software, Flags, pFeatureLevels, + FeatureLevels, SDKVersion, ppDevice, pFeatureLevel, ppImmediateContext); + + if (ppDevice != nullptr && ppImmediateContext != nullptr) + { + device = *ppDevice; + device_context = *ppImmediateContext; + } + + return result; + } + + utils::hook::detour dxgi_swap_chain_present_hook; + void* dxgi_swap_chain_present_stub() + { + on_frame(); + return dxgi_swap_chain_present_hook.invoke(); + } + + utils::hook::detour wnd_proc_hook; + LRESULT wnd_proc_stub(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + if (toggled && ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) + { + return TRUE; + } + + return wnd_proc_hook.invoke(hWnd, msg, wParam, lParam); + } + } + + bool gui_key_event(const int local_client_num, const int key, const int down) + { + if (key == game::K_F10 && down) + { + toggled = !toggled; + return false; + } + + return !toggled; + } + + bool gui_char_event(const int local_client_num, const int key) + { + return !toggled; + } + + bool gui_mouse_event(const int local_client_num, int x, int y) + { + return !toggled; + } + + class component final : public component_interface + { + public: + void* load_import(const std::string& library, const std::string& function) override + { + if (function == "D3D11CreateDevice") + { + return d3d11_create_device_stub; + } + + return nullptr; + } + + void post_unpack() override + { + dxgi_swap_chain_present_hook.create(0x7A13A0_b, dxgi_swap_chain_present_stub); + wnd_proc_hook.create(0x650F10_b, wnd_proc_stub); + } + + void pre_destroy() override + { + ImGui_ImplDX11_Shutdown(); + ImGui_ImplWin32_Shutdown(); + ImGui::DestroyContext(); + } + }; +} + +REGISTER_COMPONENT(gui::component) diff --git a/src/client/component/gui.hpp b/src/client/component/gui.hpp new file mode 100644 index 00000000..81edac10 --- /dev/null +++ b/src/client/component/gui.hpp @@ -0,0 +1,8 @@ +#pragma once + +namespace gui +{ + bool gui_key_event(const int local_client_num, const int key, const int down); + bool gui_char_event(const int local_client_num, const int key); + bool gui_mouse_event(const int local_client_num, int x, int y); +} \ No newline at end of file diff --git a/src/client/component/input.cpp b/src/client/component/input.cpp index dc777972..198ea92a 100644 --- a/src/client/component/input.cpp +++ b/src/client/component/input.cpp @@ -4,6 +4,7 @@ #include "game/game.hpp" #include "game_console.hpp" +#include "gui.hpp" #include "game/ui_scripting/lua/engine.hpp" #include @@ -31,6 +32,11 @@ namespace input return; } + if (!gui::gui_char_event(local_client_num, key)) + { + return; + } + cl_char_event_hook.invoke(local_client_num, key); } @@ -43,11 +49,21 @@ namespace input return; } + if (!gui::gui_key_event(local_client_num, key, down)) + { + return; + } + cl_key_event_hook.invoke(local_client_num, key, down); } void cl_mouse_move_stub(const int local_client_num, int x, int y) { + if (!gui::gui_mouse_event(local_client_num, x, y)) + { + return; + } + ui_scripting::lua::engine::ui_event("mousemove", {x, y}); cl_mouse_move_hook.invoke(local_client_num, x, y); } diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index 055dcc72..7fbaf1b8 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -123,6 +123,8 @@ namespace game WEAK symbol cmd_functions{0xAD17BB8}; WEAK symbol cmd_args{0xAD17A60}; + WEAK symbol hWnd{0xCCF81C0}; + WEAK symbol g_assetNames{0xBEF280}; WEAK symbol g_poolSize{0xBF2E40}; diff --git a/src/client/std_include.hpp b/src/client/std_include.hpp index 279d6e41..f0e7fe52 100644 --- a/src/client/std_include.hpp +++ b/src/client/std_include.hpp @@ -87,6 +87,12 @@ #include +#include +#include +#include +#include +#include + #pragma warning(pop) #pragma warning(disable: 4100) @@ -95,6 +101,7 @@ #pragma comment(lib, "urlmon.lib" ) #pragma comment(lib, "iphlpapi.lib") #pragma comment(lib, "Crypt32.lib") +#pragma comment(lib, "d3d11.lib") #include "resource.hpp"