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
{
utils::concurrency::container<std::vector<std::function<void()>>> on_frame_callbacks;
utils::concurrency::container<std::vector<notification_t>> notifications;
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;
@ -38,13 +53,29 @@ namespace gui
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()
{
ImGui::GetIO().MouseDrawCursor = toggled;
*game::keyCatchers |= 0x10 * toggled;
ImGui_ImplDX11_NewFrame();
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
run_event_queue();
*game::keyCatchers |= 0x10;
ImGui::NewFrame();
}
void end_gui_frame()
@ -65,15 +96,15 @@ namespace gui
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav |
ImGuiWindowFlags_NoMove;
notifications.access([](std::vector<notification_t>& notifications_)
notifications.access([](std::deque<notification_t>& notifications_)
{
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();
if (now - i->creation_time >= i->duration)
{
notifications_.erase(i--);
i = notifications_.erase(i);
continue;
}
@ -91,7 +122,8 @@ namespace gui
ImGui::End();
index++;
++i;
++index;
}
});
}
@ -101,18 +133,22 @@ namespace gui
ImGui::Checkbox(name.data(), &enabled_menus[menu]);
}
void gui_draw()
void run_frame_callbacks()
{
show_notifications();
on_frame_callbacks.access([](std::vector<std::function<void()>>& callbacks)
on_frame_callbacks.access([](std::vector<frame_callback>& callbacks)
{
for (const auto& callback : callbacks)
{
callback();
if (callback.always || toggled)
{
callback.callback();
}
}
});
}
void draw_main_menu_bar()
{
if (ImGui::BeginMainMenuBar())
{
if (ImGui::BeginMenu("Windows"))
@ -121,6 +157,7 @@ namespace gui
menu_checkbox("Entity list", "entity_list");
menu_checkbox("Console", "console");
menu_checkbox("Script console", "script_console");
menu_checkbox("Debug", "debug");
ImGui::EndMenu();
}
@ -135,11 +172,10 @@ namespace gui
{
initialize_gui_context();
}
if (toggled)
else
{
new_gui_frame();
gui_draw();
run_frame_callbacks();
end_gui_frame();
}
}
@ -178,9 +214,12 @@ namespace gui
utils::hook::detour wnd_proc_hook;
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);
@ -214,11 +253,11 @@ namespace gui
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.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);
wnd_proc_hook.create(0x650F10_b, wnd_proc_stub);
on_frame([]()
{
show_notifications();
draw_main_menu_bar();
});
}
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_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);
void notification(const std::string& title, const std::string& text, const std::chrono::milliseconds duration = 3s);
void copy_to_clipboard(const std::string& text);