Merge branch 'imgui' into develop

This commit is contained in:
m 2022-06-04 18:53:49 -05:00 committed by GitHub
commit deb4c5294a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 494 additions and 42 deletions

3
.gitmodules vendored
View File

@ -45,3 +45,6 @@
path = deps/zlib
url = https://github.com/madler/zlib.git
branch = develop
[submodule "deps/imgui"]
path = deps/imgui
url = https://github.com/fedddddd/imgui.git

1
deps/imgui vendored Submodule

@ -0,0 +1 @@
Subproject commit 22e9093da37f0443f008b947caa6221724e760d6

31
deps/premake/imgui.lua vendored Normal file
View File

@ -0,0 +1,31 @@
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)

View File

@ -0,0 +1,359 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "game/dvars.hpp"
#include "scheduler.hpp"
#include "gui.hpp"
#include "renderer.hpp"
#include <utils/string.hpp>
#include <utils/hook.hpp>
#include <utils/concurrency.hpp>
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
namespace gui
{
std::unordered_map<std::string, bool> enabled_menus;
namespace
{
struct frame_callback
{
std::function<void()> callback;
bool always;
};
struct event
{
HWND hWnd;
UINT msg;
WPARAM wParam;
LPARAM lParam;
};
utils::concurrency::container<std::vector<frame_callback>> on_frame_callbacks;
utils::concurrency::container<std::deque<notification_t>> notifications;
utils::concurrency::container<std::vector<event>> event_queue;
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 run_event_queue()
{
event_queue.access([](std::vector<event>& queue)
{
for (const auto& event : queue)
{
ImGui_ImplWin32_WndProcHandler(event.hWnd, event.msg, event.wParam, event.lParam);
}
queue.clear();
});
}
void gui_style()
{
auto* style = &ImGui::GetStyle();
auto colors = style->Colors;
style->WindowRounding = 5.3f;
style->FrameRounding = 2.3f;
style->ScrollbarRounding = 0;
//const auto color = ImColor(0, 0, 0, 240);
auto alpha = 0.92f;
colors[ImGuiCol_Text] = ImVec4(1.000f, 1.000f, 1.000f, alpha);
colors[ImGuiCol_TextDisabled] = ImVec4(0.500f, 0.500f, 0.500f, alpha);
colors[ImGuiCol_WindowBg] = ImVec4(0.180f, 0.180f, 0.180f, alpha);
colors[ImGuiCol_ChildBg] = ImVec4(0.280f, 0.280f, 0.280f, 0.000f);
colors[ImGuiCol_PopupBg] = ImVec4(0.313f, 0.313f, 0.313f, alpha);
colors[ImGuiCol_Border] = ImVec4(0.266f, 0.266f, 0.266f, alpha);
colors[ImGuiCol_BorderShadow] = ImVec4(0.000f, 0.000f, 0.000f, 0.000f);
colors[ImGuiCol_FrameBg] = ImVec4(0.160f, 0.160f, 0.160f, alpha);
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.200f, 0.200f, 0.200f, alpha);
colors[ImGuiCol_FrameBgActive] = ImVec4(0.280f, 0.280f, 0.280f, alpha);
colors[ImGuiCol_TitleBg] = ImVec4(0.148f, 0.148f, 0.148f, alpha);
colors[ImGuiCol_TitleBgActive] = ImVec4(0.148f, 0.148f, 0.148f, alpha);
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.148f, 0.148f, 0.148f, alpha);
colors[ImGuiCol_MenuBarBg] = ImVec4(0.195f, 0.195f, 0.195f, alpha);
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.160f, 0.160f, 0.160f, alpha);
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.277f, 0.277f, 0.277f, alpha);
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.300f, 0.300f, 0.300f, alpha);
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(1.000f, 0.391f, 0.000f, alpha);
colors[ImGuiCol_CheckMark] = ImVec4(1.000f, 1.000f, 1.000f, alpha);
colors[ImGuiCol_SliderGrab] = ImVec4(0.391f, 0.391f, 0.391f, alpha);
colors[ImGuiCol_SliderGrabActive] = ImVec4(1.000f, 0.391f, 0.000f, alpha);
colors[ImGuiCol_Button] = ImVec4(1.000f, 1.000f, 1.000f, 0.000f);
colors[ImGuiCol_ButtonHovered] = ImVec4(1.000f, 1.000f, 1.000f, 0.156f);
colors[ImGuiCol_ButtonActive] = ImVec4(1.000f, 1.000f, 1.000f, 0.391f);
colors[ImGuiCol_Header] = ImVec4(0.313f, 0.313f, 0.313f, alpha);
colors[ImGuiCol_HeaderHovered] = ImVec4(0.469f, 0.469f, 0.469f, alpha);
colors[ImGuiCol_HeaderActive] = ImVec4(0.469f, 0.469f, 0.469f, alpha);
colors[ImGuiCol_Separator] = colors[ImGuiCol_Border];
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.391f, 0.391f, 0.391f, alpha);
colors[ImGuiCol_SeparatorActive] = ImVec4(1.000f, 0.391f, 0.000f, alpha);
colors[ImGuiCol_ResizeGrip] = ImVec4(1.000f, 1.000f, 1.000f, 0.250f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(1.000f, 1.000f, 1.000f, 0.670f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(1.000f, 0.391f, 0.000f, alpha);
colors[ImGuiCol_Tab] = ImVec4(0.098f, 0.098f, 0.098f, alpha);
colors[ImGuiCol_TabHovered] = ImVec4(0.352f, 0.352f, 0.352f, alpha);
colors[ImGuiCol_TabActive] = ImVec4(0.195f, 0.195f, 0.195f, alpha);
colors[ImGuiCol_TabUnfocused] = ImVec4(0.098f, 0.098f, 0.098f, alpha);
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.195f, 0.195f, 0.195f, alpha);
colors[ImGuiCol_PlotLines] = ImVec4(0.469f, 0.469f, 0.469f, alpha);
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.000f, 0.391f, 0.000f, alpha);
colors[ImGuiCol_PlotHistogram] = ImVec4(0.586f, 0.586f, 0.586f, alpha);
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.000f, 0.391f, 0.000f, alpha);
colors[ImGuiCol_TextSelectedBg] = ImVec4(1.000f, 1.000f, 1.000f, 0.156f);
colors[ImGuiCol_DragDropTarget] = ImVec4(1.000f, 0.391f, 0.000f, alpha);
colors[ImGuiCol_NavHighlight] = ImVec4(1.000f, 0.391f, 0.000f, alpha);
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.000f, 0.391f, 0.000f, alpha);
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.000f, 0.000f, 0.000f, 0.586f);
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.000f, 0.000f, 0.000f, 0.586f);
}
void new_gui_frame()
{
ImGui::GetIO().MouseDrawCursor = toggled;
if (toggled)
{
*game::keyCatchers |= 0x10;
}
else
{
*game::keyCatchers &= ~0x10;
}
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
run_event_queue();
ImGui::NewFrame();
gui_style();
}
void end_gui_frame()
{
ImGui::EndFrame();
ImGui::Render();
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
}
void toggle_menu(const std::string& name)
{
enabled_menus[name] = !enabled_menus[name];
}
void menu_checkbox(const std::string& name, const std::string& menu)
{
ImGui::Checkbox(name.data(), &enabled_menus[menu]);
}
void run_frame_callbacks()
{
on_frame_callbacks.access([](std::vector<frame_callback>& callbacks)
{
for (const auto& callback : callbacks)
{
if (callback.always || toggled)
{
callback.callback();
}
}
});
}
void draw_window()
{
ImGui::Begin("hello world!", nullptr);
static int value = 0;
ImGui::SliderInt("lighting technique", &value, 0, 25);
const auto should_apply = ImGui::Button("apply", ImVec2(125, 125));
if (should_apply)
{
printf("new technique! value is %d\n", value);
renderer::update_tech(value);
}
ImGui::End();
}
void gui_on_frame()
{
if (!initialized)
{
printf("initialzed gui context\n");
initialize_gui_context();
}
else
{
new_gui_frame();
run_frame_callbacks();
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;
}
void dxgi_swap_chain_present_stub(utils::hook::assembler& a)
{
a.pushad64();
a.call_aligned(gui_on_frame);
a.popad64();
a.mov(r8d, esi);
a.mov(edx, r15d);
a.mov(rcx, rdi);
a.call_aligned(rbx);
a.mov(dword_ptr(rsp, 0x20), eax);
a.jmp(0x6CB185_b);
}
utils::hook::detour wnd_proc_hook;
LRESULT wnd_proc_stub(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (wParam != VK_ESCAPE && toggled)
{
event_queue.access([hWnd, msg, wParam, lParam](std::vector<event>& queue)
{
queue.push_back({hWnd, msg, wParam, lParam});
});
}
return wnd_proc_hook.invoke<LRESULT>(hWnd, msg, wParam, lParam);
}
}
bool gui_key_event(const int local_client_num, const int key, const int down)
{
printf("gui key event\n");
if (key == game::K_INS && down)
{
toggled = !toggled;
return false;
}
if (key == game::K_ESCAPE && down && toggled)
{
toggled = false;
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;
}
void on_frame(const std::function<void()>& callback, bool always)
{
on_frame_callbacks.access([always, callback](std::vector<frame_callback>& callbacks)
{
callbacks.push_back({callback, always});
});
}
bool is_menu_open(const std::string& name)
{
return enabled_menus[name];
}
void notification(const std::string& title, const std::string& text, const std::chrono::milliseconds duration)
{
notification_t notification{};
notification.title = title;
notification.text = text;
notification.duration = duration;
notification.creation_time = std::chrono::high_resolution_clock::now();
notifications.access([notification](std::deque<notification_t>& notifications_)
{
notifications_.push_front(notification);
});
}
void copy_to_clipboard(const std::string& text)
{
utils::string::set_clipboard_data(text);
gui::notification("Text copied to clipboard", utils::string::va("\"%s\"", text.data()));
}
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
{
utils::hook::jump(0x6CB176_b, utils::hook::assemble(dxgi_swap_chain_present_stub), true);
wnd_proc_hook.create(0x5BFF60_b, wnd_proc_stub);
on_frame([]()
{
draw_window();
});
}
void pre_destroy() override
{
if (initialized)
{
ImGui_ImplWin32_Shutdown();
ImGui::DestroyContext();
}
}
};
}
REGISTER_COMPONENT(gui::component)

View File

@ -0,0 +1,23 @@
#pragma once
namespace gui
{
struct notification_t
{
std::string title;
std::string text;
std::chrono::milliseconds duration{};
std::chrono::high_resolution_clock::time_point creation_time{};
};
extern std::unordered_map<std::string, bool> enabled_menus;
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);
void on_frame(const std::function<void()>& callback, bool always = false);
bool is_menu_open(const std::string& name);
void notification(const std::string& title, const std::string& text, const std::chrono::milliseconds duration = 3s);
void copy_to_clipboard(const std::string& text);
}

View File

@ -4,6 +4,7 @@
#include "game/game.hpp"
#include "game_console.hpp"
#include "gui.hpp"
#include "game/ui_scripting/execution.hpp"
#include <utils/hook.hpp>
@ -36,12 +37,15 @@ namespace input
void cl_key_event_stub(const int local_client_num, const int key, const int down)
{
const auto key_to_string = game::Key_KeynumToString(key, 0, 1);
printf("key to string: %s\n", key_to_string);
if (ui_scripting::lui_running())
{
ui_scripting::notify(down ? "keydown" : "keyup",
{
{"keynum", key},
{"key", game::Key_KeynumToString(key, 0, 1)},
{"key", key_to_string},
});
}
@ -50,6 +54,11 @@ namespace input
return;
}
if (!gui::gui_key_event(local_client_num, key, down))
{
return;
}
cl_key_event_hook.invoke<void>(local_client_num, key, down);
}
}

View File

@ -10,11 +10,34 @@
namespace renderer
{
static int tech = 0;
void custom_gfx_draw_method()
{
game::gfxDrawMethod->drawScene = game::GFX_DRAW_SCENE_STANDARD;
game::gfxDrawMethod->baseTechType = tech;
game::gfxDrawMethod->emissiveTechType = tech;
game::gfxDrawMethod->forceTechType = tech;
}
void default_gfx_draw_method()
{
game::gfxDrawMethod->drawScene = game::GFX_DRAW_SCENE_STANDARD;
game::gfxDrawMethod->baseTechType = game::TECHNIQUE_LIT;
game::gfxDrawMethod->emissiveTechType = game::TECHNIQUE_EMISSIVE;
game::gfxDrawMethod->forceTechType = 242;
}
void update_tech(int new_tech)
{
tech = new_tech;
custom_gfx_draw_method();
}
namespace
{
utils::hook::detour r_init_draw_method_hook;
utils::hook::detour r_update_front_end_dvar_options_hook;
utils::hook::detour db_load_xassets_hook;
game::dvar_t* r_red_dot_brightness_scale;
@ -45,45 +68,9 @@ namespace renderer
{"mp_bog_summer", 24.f},
};
int get_fullbright_technique()
{
switch (dvars::r_fullbright->current.integer)
{
case 4:
return 3;
case 3:
return 13;
case 2:
return 25;
default:
return game::TECHNIQUE_UNLIT;
}
}
void gfxdrawmethod()
{
game::gfxDrawMethod->drawScene = game::GFX_DRAW_SCENE_STANDARD;
game::gfxDrawMethod->baseTechType = dvars::r_fullbright->current.enabled ? get_fullbright_technique() : game::TECHNIQUE_LIT;
game::gfxDrawMethod->emissiveTechType = dvars::r_fullbright->current.enabled ? get_fullbright_technique() : game::TECHNIQUE_EMISSIVE;
game::gfxDrawMethod->forceTechType = dvars::r_fullbright->current.enabled ? get_fullbright_technique() : 242;
}
void r_init_draw_method_stub()
{
gfxdrawmethod();
}
bool r_update_front_end_dvar_options_stub()
{
if (dvars::r_fullbright->modified)
{
game::Dvar_ClearModified(dvars::r_fullbright);
game::R_SyncRenderThread();
gfxdrawmethod();
}
return r_update_front_end_dvar_options_hook.invoke<bool>();
default_gfx_draw_method();
}
void set_tonemap_highlight_range()
@ -148,10 +135,7 @@ namespace renderer
return;
}
dvars::r_fullbright = dvars::register_int("r_fullbright", 0, 0, 4, game::DVAR_FLAG_SAVED, "Toggles rendering without lighting");
r_init_draw_method_hook.create(SELECT_VALUE(0x5467E0_b, 0x669580_b), &r_init_draw_method_stub);
r_update_front_end_dvar_options_hook.create(SELECT_VALUE(0x583560_b, 0x6A78C0_b), &r_update_front_end_dvar_options_stub);
// use "saved" flags
dvars::override::register_enum("r_normalMap", game::DVAR_FLAG_SAVED);

View File

@ -0,0 +1,6 @@
#pragma once
namespace renderer
{
void update_tech(int tech);
}

View File

@ -229,6 +229,8 @@ namespace game
* Variables
**************************************************************/
WEAK symbol<HWND> hWnd{0x0, 0xC9DD2E0};
WEAK symbol<CmdArgs> sv_cmd_args{0xB48FF90, 0x2ED1EB0};
WEAK symbol<int> g_script_error_level{0xC3FD358, 0xB7AC1A4};

View File

@ -89,6 +89,13 @@
#include <asmjit/core/jitruntime.h>
#include <asmjit/x86/x86assembler.h>
#include <d3d11.h>
#include <imgui.h>
#include <imgui_internal.h>
#include <backends/imgui_impl_dx11.h>
#include <backends/imgui_impl_win32.h>
#include <misc/cpp/imgui_stdlib.h>
#include <google/protobuf/stubs/logging.h>
#include <proto/auth.pb.h>
@ -100,6 +107,7 @@
#pragma comment(lib, "urlmon.lib" )
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "Crypt32.lib")
#pragma comment(lib, "d3d11.lib")
#include "resource.hpp"

View File

@ -105,6 +105,22 @@ namespace utils::string
return {};
}
void set_clipboard_data(const std::string& text)
{
const auto len = text.size() + 1;
const auto mem = GlobalAlloc(GMEM_MOVEABLE, len);
memcpy(GlobalLock(mem), text.data(), len);
GlobalUnlock(mem);
if (OpenClipboard(nullptr))
{
EmptyClipboard();
SetClipboardData(CF_TEXT, mem);
CloseClipboard();
}
}
void strip(const char* in, char* out, int max)
{
if (!in || !out) return;
@ -177,6 +193,13 @@ namespace utils::string
return str;
}
std::string truncate(const std::string& text, const size_t length, const std::string& end)
{
return text.size() <= length
? text
: text.substr(0, length - end.size()) + end;
}
bool match_compare(const std::string& input, const std::string& text, const bool exact)
{
if (exact && text == input) return true;

View File

@ -90,6 +90,7 @@ namespace utils::string
std::string dump_hex(const std::string& data, const std::string& separator = " ");
std::string get_clipboard_data();
void set_clipboard_data(const std::string& text);
void strip(const char* in, char* out, int max);
@ -98,5 +99,7 @@ namespace utils::string
std::string replace(std::string str, const std::string& from, const std::string& to);
std::string truncate(const std::string& text, const size_t length, const std::string& end);
bool match_compare(const std::string& input, const std::string& text, const bool exact);
}