Fixed UI events happening while the menu is closed, fixed crash on exit caused by destruction order of UI

This commit is contained in:
Mr-Wiseguy 2024-02-25 17:08:19 -05:00
parent 0337a7fbc2
commit 8faa532e53
1 changed files with 54 additions and 39 deletions

View File

@ -731,7 +731,7 @@ void recomp::register_event(UiEventListenerInstancer& listener, const std::strin
listener.register_event(name, handler); listener.register_event(name, handler);
} }
struct { struct UIContext {
struct UIRenderContext render; struct UIRenderContext render;
class { class {
std::unordered_map<recomp::Menu, std::unique_ptr<recomp::MenuController>> menus; std::unordered_map<recomp::Menu, std::unique_ptr<recomp::MenuController>> menus;
@ -745,7 +745,6 @@ struct {
std::unique_ptr<Rml::ElementInstancer> svg_instancer; std::unique_ptr<Rml::ElementInstancer> svg_instancer;
Rml::Context* context; Rml::Context* context;
recomp::UiEventListenerInstancer event_listener_instancer; recomp::UiEventListenerInstancer event_listener_instancer;
std::mutex draw_mutex;
void unload() { void unload() {
render_interface.reset(); render_interface.reset();
@ -872,7 +871,10 @@ struct {
menus.emplace(menu, std::move(controller)); menus.emplace(menu, std::move(controller));
} }
} rml; } rml;
} UIContext; };
std::unique_ptr<UIContext> ui_context;
std::mutex ui_context_mutex{};
// TODO make this not be global // TODO make this not be global
extern SDL_Window* window; extern SDL_Window* window;
@ -884,30 +886,32 @@ void recomp::get_window_size(int& width, int& height) {
void init_hook(RT64::RenderInterface* interface, RT64::RenderDevice* device) { void init_hook(RT64::RenderInterface* interface, RT64::RenderDevice* device) {
printf("RT64 hook init\n"); printf("RT64 hook init\n");
UIContext.rml.add_menu(recomp::Menu::Config, recomp::create_config_menu()); ui_context = std::make_unique<UIContext>();
UIContext.rml.add_menu(recomp::Menu::Launcher, recomp::create_launcher_menu());
UIContext.render.interface = interface; ui_context->rml.add_menu(recomp::Menu::Config, recomp::create_config_menu());
UIContext.render.device = device; ui_context->rml.add_menu(recomp::Menu::Launcher, recomp::create_launcher_menu());
ui_context->render.interface = interface;
ui_context->render.device = device;
// Setup RML // Setup RML
UIContext.rml.system_interface = std::make_unique<SystemInterface_SDL>(); ui_context->rml.system_interface = std::make_unique<SystemInterface_SDL>();
UIContext.rml.system_interface->SetWindow(window); ui_context->rml.system_interface->SetWindow(window);
UIContext.rml.render_interface = std::make_unique<RmlRenderInterface_RT64>(&UIContext.render); ui_context->rml.render_interface = std::make_unique<RmlRenderInterface_RT64>(&ui_context->render);
UIContext.rml.make_event_listeners(); ui_context->rml.make_event_listeners();
Rml::SetSystemInterface(UIContext.rml.system_interface.get()); Rml::SetSystemInterface(ui_context->rml.system_interface.get());
Rml::SetRenderInterface(UIContext.rml.render_interface.get()); Rml::SetRenderInterface(ui_context->rml.render_interface.get());
Rml::Factory::RegisterEventListenerInstancer(&UIContext.rml.event_listener_instancer); Rml::Factory::RegisterEventListenerInstancer(&ui_context->rml.event_listener_instancer);
UIContext.rml.font_interface = std::make_unique<RecompRml::FontEngineInterfaceScaled>(); ui_context->rml.font_interface = std::make_unique<RecompRml::FontEngineInterfaceScaled>();
Rml::SetFontEngineInterface(UIContext.rml.font_interface.get()); Rml::SetFontEngineInterface(ui_context->rml.font_interface.get());
Rml::Initialise(); Rml::Initialise();
UIContext.rml.svg_instancer = std::make_unique<Rml::ElementInstancerGeneric<RecompRml::ElementScaledSVG>>(); ui_context->rml.svg_instancer = std::make_unique<Rml::ElementInstancerGeneric<RecompRml::ElementScaledSVG>>();
Rml::Factory::RegisterElementInstancer("svg", UIContext.rml.svg_instancer.get()); Rml::Factory::RegisterElementInstancer("svg", ui_context->rml.svg_instancer.get());
// Apply the hack to replace RmlUi's default color parser with one that conforms to HTML5 alpha parsing for SASS compatibility // Apply the hack to replace RmlUi's default color parser with one that conforms to HTML5 alpha parsing for SASS compatibility
recomp::apply_color_hack(); recomp::apply_color_hack();
@ -915,10 +919,10 @@ void init_hook(RT64::RenderInterface* interface, RT64::RenderDevice* device) {
int width, height; int width, height;
SDL_GetWindowSizeInPixels(window, &width, &height); SDL_GetWindowSizeInPixels(window, &width, &height);
UIContext.rml.context = Rml::CreateContext("main", Rml::Vector2i(width * RecompRml::global_font_scale, height * RecompRml::global_font_scale)); ui_context->rml.context = Rml::CreateContext("main", Rml::Vector2i(width * RecompRml::global_font_scale, height * RecompRml::global_font_scale));
UIContext.rml.make_bindings(); ui_context->rml.make_bindings();
Rml::Debugger::Initialise(UIContext.rml.context); Rml::Debugger::Initialise(ui_context->rml.context);
{ {
const Rml::String directory = "assets/"; const Rml::String directory = "assets/";
@ -943,7 +947,7 @@ void init_hook(RT64::RenderInterface* interface, RT64::RenderDevice* device) {
} }
} }
UIContext.rml.load_documents(); ui_context->rml.load_documents();
} }
moodycamel::ConcurrentQueue<SDL_Event> ui_event_queue{}; moodycamel::ConcurrentQueue<SDL_Event> ui_event_queue{};
@ -960,7 +964,13 @@ std::atomic<recomp::Menu> open_menu = recomp::Menu::Launcher;
std::atomic<recomp::ConfigSubmenu> open_config_submenu = recomp::ConfigSubmenu::Count; std::atomic<recomp::ConfigSubmenu> open_config_submenu = recomp::ConfigSubmenu::Count;
void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* swap_chain_framebuffer) { void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* swap_chain_framebuffer) {
std::lock_guard lock {UIContext.rml.draw_mutex}; std::lock_guard lock {ui_context_mutex};
// Return early if the ui context has been destroyed already.
if (!ui_context) {
return;
}
int num_keys; int num_keys;
const Uint8* key_state = SDL_GetKeyboardState(&num_keys); const Uint8* key_state = SDL_GetKeyboardState(&num_keys);
@ -973,17 +983,17 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
recomp::Menu cur_menu = open_menu.load(); recomp::Menu cur_menu = open_menu.load();
if (reload_sheets) { if (reload_sheets) {
UIContext.rml.load_documents(); ui_context->rml.load_documents();
prev_menu = recomp::Menu::None; prev_menu = recomp::Menu::None;
} }
if (cur_menu != prev_menu) { if (cur_menu != prev_menu) {
UIContext.rml.swap_document(cur_menu); ui_context->rml.swap_document(cur_menu);
} }
recomp::ConfigSubmenu config_submenu = open_config_submenu.load(); recomp::ConfigSubmenu config_submenu = open_config_submenu.load();
if (config_submenu != recomp::ConfigSubmenu::Count) { if (config_submenu != recomp::ConfigSubmenu::Count) {
UIContext.rml.swap_config_menu(config_submenu); ui_context->rml.swap_config_menu(config_submenu);
open_config_submenu.store(recomp::ConfigSubmenu::Count); open_config_submenu.store(recomp::ConfigSubmenu::Count);
} }
@ -1018,10 +1028,11 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
} }
break; break;
} }
RmlSDL::InputEventHandler(UIContext.rml.context, cur_event);
// If a menu is open then implement some additional behavior for specific events on top of what RmlUi normally does with them. // Send events to RmlUi if a menu is open.
if (cur_menu != recomp::Menu::None) { if (cur_menu != recomp::Menu::None) {
RmlSDL::InputEventHandler(ui_context->rml.context, cur_event);
// Implement some additional behavior for specific events on top of what RmlUi normally does with them.
switch (cur_event.type) { switch (cur_event.type) {
case SDL_EventType::SDL_MOUSEMOTION: case SDL_EventType::SDL_MOUSEMOTION:
mouse_moved = true; mouse_moved = true;
@ -1048,7 +1059,7 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
if (open_config) { if (open_config) {
cur_menu = recomp::Menu::Config; cur_menu = recomp::Menu::Config;
open_menu.store(recomp::Menu::Config); open_menu.store(recomp::Menu::Config);
UIContext.rml.swap_document(cur_menu); ui_context->rml.swap_document(cur_menu);
} }
} }
} }
@ -1058,29 +1069,29 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
recomp::finish_scanning_input(scanned_field); recomp::finish_scanning_input(scanned_field);
} }
UIContext.rml.update_focus(mouse_moved); ui_context->rml.update_focus(mouse_moved);
if (cur_menu != recomp::Menu::None) { if (cur_menu != recomp::Menu::None) {
int width = swap_chain_framebuffer->getWidth(); int width = swap_chain_framebuffer->getWidth();
int height = swap_chain_framebuffer->getHeight(); int height = swap_chain_framebuffer->getHeight();
// Scale the UI based on the window size with 1080 vertical resolution as the reference point. // Scale the UI based on the window size with 1080 vertical resolution as the reference point.
UIContext.rml.context->SetDensityIndependentPixelRatio((height * RecompRml::global_font_scale) / 1080.0f); ui_context->rml.context->SetDensityIndependentPixelRatio((height * RecompRml::global_font_scale) / 1080.0f);
UIContext.rml.render_interface->start(command_list, width, height); ui_context->rml.render_interface->start(command_list, width, height);
static int prev_width = 0; static int prev_width = 0;
static int prev_height = 0; static int prev_height = 0;
if (prev_width != width || prev_height != height) { if (prev_width != width || prev_height != height) {
UIContext.rml.context->SetDimensions({ (int)(width * RecompRml::global_font_scale), (int)(height * RecompRml::global_font_scale) }); ui_context->rml.context->SetDimensions({ (int)(width * RecompRml::global_font_scale), (int)(height * RecompRml::global_font_scale) });
} }
prev_width = width; prev_width = width;
prev_height = height; prev_height = height;
UIContext.rml.context->Update(); ui_context->rml.context->Update();
UIContext.rml.context->Render(); ui_context->rml.context->Render();
UIContext.rml.render_interface->end(command_list, swap_chain_framebuffer); ui_context->rml.render_interface->end(command_list, swap_chain_framebuffer);
} }
} }
@ -1094,6 +1105,9 @@ void set_rt64_hooks() {
void recomp::set_current_menu(Menu menu) { void recomp::set_current_menu(Menu menu) {
open_menu.store(menu); open_menu.store(menu);
if (menu == recomp::Menu::None) {
ui_context->rml.system_interface->SetMouseCursor("arrow");
}
} }
void recomp::set_config_submenu(recomp::ConfigSubmenu submenu) { void recomp::set_config_submenu(recomp::ConfigSubmenu submenu) {
@ -1101,10 +1115,11 @@ void recomp::set_config_submenu(recomp::ConfigSubmenu submenu) {
} }
void recomp::destroy_ui() { void recomp::destroy_ui() {
std::lock_guard lock {UIContext.rml.draw_mutex}; std::lock_guard lock {ui_context_mutex};
UIContext.rml.font_interface.reset(); ui_context->rml.font_interface.reset();
Rml::Shutdown(); Rml::Shutdown();
UIContext.rml.unload(); ui_context->rml.unload();
ui_context.reset();
} }
recomp::Menu recomp::get_current_menu() { recomp::Menu recomp::get_current_menu() {