From 27db2aeaa06fc069c257da15ab6e037cd6dda1a8 Mon Sep 17 00:00:00 2001 From: Mr-Wiseguy Date: Fri, 4 Apr 2025 04:35:06 -0400 Subject: [PATCH] Reimplement prompts as a separate UI context and make it so the quit game prompt doesn't bring up the config menu --- CMakeLists.txt | 1 + assets/components/prompt.rml | 30 ----- assets/config_menu.rml | 14 -- include/recomp_ui.h | 4 +- src/game/input.cpp | 5 - src/ui/core/ui_context.cpp | 3 + src/ui/elements/ui_button.h | 3 + src/ui/ui_config.cpp | 26 +--- src/ui/ui_launcher.cpp | 5 +- src/ui/ui_prompt.cpp | 243 +++++++++++++++++++++++++++++++++++ src/ui/ui_state.cpp | 9 +- 11 files changed, 259 insertions(+), 84 deletions(-) delete mode 100644 assets/components/prompt.rml create mode 100644 src/ui/ui_prompt.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index bd719b2..af69dbe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -172,6 +172,7 @@ set (SOURCES ${CMAKE_SOURCE_DIR}/src/ui/ui_state.cpp ${CMAKE_SOURCE_DIR}/src/ui/ui_launcher.cpp ${CMAKE_SOURCE_DIR}/src/ui/ui_config.cpp + ${CMAKE_SOURCE_DIR}/src/ui/ui_prompt.cpp ${CMAKE_SOURCE_DIR}/src/ui/ui_config_sub_menu.cpp ${CMAKE_SOURCE_DIR}/src/ui/ui_color_hack.cpp ${CMAKE_SOURCE_DIR}/src/ui/ui_rml_hacks.cpp diff --git a/assets/components/prompt.rml b/assets/components/prompt.rml deleted file mode 100644 index 3de53ea..0000000 --- a/assets/components/prompt.rml +++ /dev/null @@ -1,30 +0,0 @@ - diff --git a/assets/config_menu.rml b/assets/config_menu.rml index 0666d77..3865510 100644 --- a/assets/config_menu.rml +++ b/assets/config_menu.rml @@ -29,7 +29,6 @@ - @@ -117,19 +116,6 @@ --> - diff --git a/include/recomp_ui.h b/include/recomp_ui.h index acae932..3982a86 100644 --- a/include/recomp_ui.h +++ b/include/recomp_ui.h @@ -29,7 +29,7 @@ namespace recompui { class MenuController { public: virtual ~MenuController() {} - virtual Rml::ElementDocument* load_document(Rml::Context* context) = 0; + virtual void load_document() = 0; virtual void register_events(UiEventListenerInstancer& listener) = 0; virtual void make_bindings(Rml::Context* context) = 0; }; @@ -56,7 +56,6 @@ namespace recompui { ContextId get_launcher_context_id(); ContextId get_config_context_id(); ContextId get_config_sub_menu_context_id(); - ContextId get_close_prompt_context_id(); enum class ConfigTab { General, @@ -79,6 +78,7 @@ namespace recompui { NumVariants, }; + void init_prompt_context(); void open_prompt( const std::string& headerText, const std::string& contentText, diff --git a/src/game/input.cpp b/src/game/input.cpp index 7384e37..45a6f9f 100644 --- a/src/game/input.cpp +++ b/src/game/input.cpp @@ -156,11 +156,6 @@ bool sdl_event_filter(void* userdata, SDL_Event* event) { return true; } - recompui::ContextId config_context_id = recompui::get_config_context_id(); - if (!recompui::is_context_shown(config_context_id)) { - recompui::show_context(config_context_id, ""); - } - zelda64::open_quit_game_prompt(); recompui::activate_mouse(); break; diff --git a/src/ui/core/ui_context.cpp b/src/ui/core/ui_context.cpp index 69214e8..397d6d8 100644 --- a/src/ui/core/ui_context.cpp +++ b/src/ui/core/ui_context.cpp @@ -206,6 +206,7 @@ recompui::ContextId recompui::create_context() { root->set_height(100.0f, Unit::Percent); root->set_display(Display::Flex); root->set_opacity(1.0f); + root->set_color(Color{ 242, 242, 242, 255 }); root->set_font_family("chiaro"); root->set_font_style(FontStyle::Normal); root->set_font_weight(400); @@ -218,6 +219,8 @@ recompui::ContextId recompui::create_context() { root->set_line_height(sz_add, Unit::Dp); ret.close(); + doc->Hide(); + return ret; } diff --git a/src/ui/elements/ui_button.h b/src/ui/elements/ui_button.h index a133b24..b5ff114 100644 --- a/src/ui/elements/ui_button.h +++ b/src/ui/elements/ui_button.h @@ -22,6 +22,9 @@ namespace recompui { public: Button(Element *parent, const std::string &text, ButtonStyle style); void add_pressed_callback(std::function callback); + Style* get_hover_style() { return &hover_style; } + Style* get_disabled_style() { return &disabled_style; } + Style* get_hover_disabled_style() { return &hover_disabled_style; } }; } // namespace recompui \ No newline at end of file diff --git a/src/ui/ui_config.cpp b/src/ui/ui_config.cpp index 8258739..5d20c7e 100644 --- a/src/ui/ui_config.cpp +++ b/src/ui/ui_config.cpp @@ -442,11 +442,8 @@ public: ~ConfigMenu() override { } - Rml::ElementDocument* load_document(Rml::Context* context) override { - (void)context; + void load_document() override { config_context = recompui::create_context(zelda64::get_asset_path("config_menu.rml")); - Rml::ElementDocument* ret = config_context.get_document(); - return ret; } void register_events(recompui::UiEventListenerInstancer& listener) override { recompui::register_event(listener, "apply_options", @@ -959,27 +956,6 @@ void recompui::toggle_fullscreen() { graphics_model_handle.DirtyVariable("wm_option"); } -void recompui::open_prompt( - const std::string& headerText, - const std::string& contentText, - const std::string& confirmLabelText, - const std::string& cancelLabelText, - std::function confirmCb, - std::function cancelCb, - ButtonVariant _confirmVariant, - ButtonVariant _cancelVariant, - bool _focusOnCancel, - const std::string& _returnElementId -) { - printf("Prompt opened\n %s (%s): %s %s\n", contentText.c_str(), headerText.c_str(), confirmLabelText.c_str(), cancelLabelText.c_str()); - printf(" Autoselected %s\n", confirmLabelText.c_str()); - confirmCb(); -} - -bool recompui::is_prompt_open() { - return false; -} - void recompui::set_config_tab(ConfigTab tab) { ContextId config_context = recompui::get_config_context_id(); diff --git a/src/ui/ui_launcher.cpp b/src/ui/ui_launcher.cpp index fd0ee8e..67149c1 100644 --- a/src/ui/ui_launcher.cpp +++ b/src/ui/ui_launcher.cpp @@ -62,11 +62,8 @@ public: ~LauncherMenu() override { } - Rml::ElementDocument* load_document(Rml::Context* context) override { - (void)context; + void load_document() override { launcher_context = recompui::create_context(zelda64::get_asset_path("launcher.rml")); - Rml::ElementDocument* ret = launcher_context.get_document(); - return ret; } void register_events(recompui::UiEventListenerInstancer& listener) override { recompui::register_event(listener, "select_rom", diff --git a/src/ui/ui_prompt.cpp b/src/ui/ui_prompt.cpp new file mode 100644 index 0000000..7e79f42 --- /dev/null +++ b/src/ui/ui_prompt.cpp @@ -0,0 +1,243 @@ +#include + +#include "recomp_ui.h" + +#include "elements/ui_element.h" +#include "elements/ui_label.h" +#include "elements/ui_button.h" + +struct { + recompui::ContextId ui_context; + recompui::Label* prompt_header; + recompui::Label* prompt_label; + recompui::Button* confirm_button; + recompui::Button* cancel_button; + std::function confirm_action; + std::function cancel_action; + std::string return_element_id; + std::mutex mutex; +} prompt_state; + +void run_confirm_callback() { + std::function confirm_action; + { + std::lock_guard lock{ prompt_state.mutex }; + confirm_action = std::move(prompt_state.confirm_action); + } + if (confirm_action) { + confirm_action(); + } + recompui::hide_context(prompt_state.ui_context); + + // TODO nav: focus on return_element_id + // or just remove it as the usage of the prompt can change now +} + +void run_cancel_callback() { + std::function cancel_action; + { + std::lock_guard lock{ prompt_state.mutex }; + cancel_action = std::move(prompt_state.cancel_action); + } + if (cancel_action) { + cancel_action(); + } + recompui::hide_context(prompt_state.ui_context); + + // TODO nav: focus on return_element_id + // or just remove it as the usage of the prompt can change now +} + +void recompui::init_prompt_context() { + ContextId context = create_context(); + + std::lock_guard lock{ prompt_state.mutex }; + + context.open(); + + prompt_state.ui_context = context; + + Element* window = context.create_element(context.get_root_element()); + window->set_display(Display::Flex); + window->set_flex_direction(FlexDirection::Column); + window->set_background_color({0, 0, 0, 0}); + + Element* prompt_overlay = context.create_element(window); + prompt_overlay->set_background_color(Color{ 190, 184, 219, 25 }); + prompt_overlay->set_position(Position::Absolute); + prompt_overlay->set_top(0); + prompt_overlay->set_right(0); + prompt_overlay->set_bottom(0); + prompt_overlay->set_left(0); + + Element* prompt_content_wrapper = context.create_element(window); + prompt_content_wrapper->set_display(Display::Flex); + prompt_content_wrapper->set_position(Position::Absolute); + prompt_content_wrapper->set_top(0); + prompt_content_wrapper->set_right(0); + prompt_content_wrapper->set_bottom(0); + prompt_content_wrapper->set_left(0); + prompt_content_wrapper->set_align_items(AlignItems::Center); + prompt_content_wrapper->set_justify_content(JustifyContent::Center); + + Element* prompt_content = context.create_element(prompt_content_wrapper); + prompt_content->set_display(Display::Flex); + prompt_content->set_position(Position::Relative); + prompt_content->set_flex(1.0f, 1.0f); + prompt_content->set_flex_basis(100, Unit::Percent); + prompt_content->set_flex_direction(FlexDirection::Column); + prompt_content->set_width(100, Unit::Percent); + prompt_content->set_max_width(700, Unit::Dp); + prompt_content->set_height_auto(); + prompt_content->set_margin_auto(); + prompt_content->set_border_width(1.1, Unit::Dp); + prompt_content->set_border_radius(16, Unit::Dp); + prompt_content->set_border_color(Color{ 255, 255, 255, 51 }); + prompt_content->set_background_color(Color{ 8, 7, 13, 229 }); + + prompt_state.prompt_header = context.create_element