GUI fixes

This commit is contained in:
Federico Cecchetto 2022-01-06 19:09:09 +01:00
parent 9ee243c078
commit 21b28e705b
2 changed files with 69 additions and 24 deletions

View File

@ -19,8 +19,23 @@ namespace gui
namespace namespace
{ {
utils::concurrency::container<std::vector<std::function<void()>>> on_frame_callbacks; struct frame_callback
utils::concurrency::container<std::vector<notification_t>> notifications; {
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; ID3D11Device* device;
ID3D11DeviceContext* device_context; ID3D11DeviceContext* device_context;
@ -38,13 +53,29 @@ namespace gui
initialized = true; 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 new_gui_frame() void new_gui_frame()
{ {
ImGui::GetIO().MouseDrawCursor = toggled;
*game::keyCatchers |= 0x10 * toggled;
ImGui_ImplDX11_NewFrame(); ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame(); ImGui_ImplWin32_NewFrame();
ImGui::NewFrame(); run_event_queue();
*game::keyCatchers |= 0x10; ImGui::NewFrame();
} }
void end_gui_frame() void end_gui_frame()
@ -65,15 +96,15 @@ namespace gui
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav |
ImGuiWindowFlags_NoMove; ImGuiWindowFlags_NoMove;
notifications.access([](std::vector<notification_t>& notifications_) notifications.access([](std::deque<notification_t>& notifications_)
{ {
auto index = 0; auto index = 0;
for (auto i = notifications_.begin(); i != notifications_.end(); ++i) for (auto i = notifications_.begin(); i != notifications_.end();)
{ {
const auto now = std::chrono::high_resolution_clock::now(); const auto now = std::chrono::high_resolution_clock::now();
if (now - i->creation_time >= i->duration) if (now - i->creation_time >= i->duration)
{ {
notifications_.erase(i--); i = notifications_.erase(i);
continue; continue;
} }
@ -91,7 +122,8 @@ namespace gui
ImGui::End(); ImGui::End();
index++; ++i;
++index;
} }
}); });
} }
@ -101,18 +133,22 @@ namespace gui
ImGui::Checkbox(name.data(), &enabled_menus[menu]); ImGui::Checkbox(name.data(), &enabled_menus[menu]);
} }
void gui_draw() void run_frame_callbacks()
{ {
show_notifications(); on_frame_callbacks.access([](std::vector<frame_callback>& callbacks)
on_frame_callbacks.access([](std::vector<std::function<void()>>& callbacks)
{ {
for (const auto& callback : callbacks) for (const auto& callback : callbacks)
{ {
callback(); if (callback.always || toggled)
{
callback.callback();
}
} }
}); });
}
void draw_main_menu_bar()
{
if (ImGui::BeginMainMenuBar()) if (ImGui::BeginMainMenuBar())
{ {
if (ImGui::BeginMenu("Windows")) if (ImGui::BeginMenu("Windows"))
@ -121,6 +157,7 @@ namespace gui
menu_checkbox("Entity list", "entity_list"); menu_checkbox("Entity list", "entity_list");
menu_checkbox("Console", "console"); menu_checkbox("Console", "console");
menu_checkbox("Script console", "script_console"); menu_checkbox("Script console", "script_console");
menu_checkbox("Debug", "debug");
ImGui::EndMenu(); ImGui::EndMenu();
} }
@ -135,11 +172,10 @@ namespace gui
{ {
initialize_gui_context(); initialize_gui_context();
} }
else
if (toggled)
{ {
new_gui_frame(); new_gui_frame();
gui_draw(); run_frame_callbacks();
end_gui_frame(); end_gui_frame();
} }
} }
@ -178,9 +214,12 @@ namespace gui
utils::hook::detour wnd_proc_hook; utils::hook::detour wnd_proc_hook;
LRESULT wnd_proc_stub(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) LRESULT wnd_proc_stub(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{ {
if (wParam != VK_ESCAPE && toggled && ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) if (wParam != VK_ESCAPE && toggled)
{ {
return TRUE; 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); return wnd_proc_hook.invoke<LRESULT>(hWnd, msg, wParam, lParam);
@ -214,11 +253,11 @@ namespace gui
return !toggled; return !toggled;
} }
void on_frame(const std::function<void()>& callback) void on_frame(const std::function<void()>& callback, bool always)
{ {
on_frame_callbacks.access([callback](std::vector<std::function<void()>>& callbacks) on_frame_callbacks.access([always, callback](std::vector<frame_callback>& callbacks)
{ {
callbacks.push_back(callback); callbacks.push_back({callback, always});
}); });
} }
@ -235,9 +274,9 @@ namespace gui
notification.duration = duration; notification.duration = duration;
notification.creation_time = std::chrono::high_resolution_clock::now(); notification.creation_time = std::chrono::high_resolution_clock::now();
notifications.access([notification](std::vector<notification_t>& notifications_) notifications.access([notification](std::deque<notification_t>& notifications_)
{ {
notifications_.insert(notifications_.begin(), notification); notifications_.push_front(notification);
}); });
} }
@ -264,6 +303,12 @@ namespace gui
{ {
utils::hook::jump(0x7A14C4_b, utils::hook::assemble(dxgi_swap_chain_present_stub), true); utils::hook::jump(0x7A14C4_b, utils::hook::assemble(dxgi_swap_chain_present_stub), true);
wnd_proc_hook.create(0x650F10_b, wnd_proc_stub); wnd_proc_hook.create(0x650F10_b, wnd_proc_stub);
on_frame([]()
{
show_notifications();
draw_main_menu_bar();
});
} }
void pre_destroy() override void pre_destroy() override

View File

@ -16,7 +16,7 @@ namespace gui
bool gui_char_event(const int local_client_num, const int key); 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); bool gui_mouse_event(const int local_client_num, int x, int y);
void on_frame(const std::function<void()>& callback); void on_frame(const std::function<void()>& callback, bool always = false);
bool is_menu_open(const std::string& name); 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 notification(const std::string& title, const std::string& text, const std::chrono::milliseconds duration = 3s);
void copy_to_clipboard(const std::string& text); void copy_to_clipboard(const std::string& text);