mirror of
https://github.com/Mr-Wiseguy/Zelda64Recomp.git
synced 2025-04-07 05:56:53 +02:00
Reimplement prompts as a separate UI context and make it so the quit game prompt doesn't bring up the config menu
This commit is contained in:
parent
470644e700
commit
27db2aeaa0
@ -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
|
||||
|
@ -1,30 +0,0 @@
|
||||
<template name="prompt">
|
||||
<head>
|
||||
</head>
|
||||
<body class="prompt">
|
||||
<div class="prompt__overlay" />
|
||||
<div class="prompt__content-wrapper" data-if="promptOpen">
|
||||
<div class="prompt__content">
|
||||
<h3>{{ promptHeader }}</h3>
|
||||
<p>{{ promptContent }}</p>
|
||||
<div class="prompt__controls">
|
||||
<button
|
||||
autofocus="true"
|
||||
id="prompt__confirm-button"
|
||||
class="button button--success"
|
||||
style="nav-left: none; nav-right: #prompt__cancel-button"
|
||||
>
|
||||
<div class="button__label" id="prompt__confirm-button-label">{{ promptConfirmLabel }}</div>
|
||||
</button>
|
||||
<button
|
||||
id="prompt__cancel-button"
|
||||
class="button button--error"
|
||||
style="nav-right: none; nav-left: #prompt__confirm-button"
|
||||
>
|
||||
<div class="button__label" id="prompt__cancel-button-label">{{ promptCancelLabel }}</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</template>
|
@ -29,7 +29,6 @@
|
||||
<link type="text/template" href="config_menu/sound.rml" />
|
||||
<link type="text/template" href="config_menu/mods.rml" />
|
||||
<link type="text/template" href="config_menu/debug.rml" />
|
||||
<link type="text/template" href="components/prompt.rml" />
|
||||
</head>
|
||||
<body class="window">
|
||||
<!-- <handle move_target="#document"> -->
|
||||
@ -117,19 +116,6 @@
|
||||
<label><span style="font-family:promptfont;">↧</span> Accept</label> -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div
|
||||
id="prompt-root"
|
||||
data-model="prompt_model"
|
||||
data-if="prompt__open"
|
||||
data-alias-promptOpen="prompt__open"
|
||||
data-alias-promptHeader="prompt__header"
|
||||
data-alias-promptContent="prompt__content"
|
||||
data-alias-promptConfirmLabel="prompt__confirmLabel"
|
||||
data-alias-promptCancelLabel="prompt__cancelLabel"
|
||||
data-event-click="prompt__on_click"
|
||||
>
|
||||
<template src="prompt"/>
|
||||
</div> -->
|
||||
</div>
|
||||
<!-- </handle> -->
|
||||
<!-- <handle size_target="#document" style="position: absolute; width: 16dp; height: 16dp; bottom: 0px; right: 0px; cursor: resize;"></handle> -->
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,9 @@ namespace recompui {
|
||||
public:
|
||||
Button(Element *parent, const std::string &text, ButtonStyle style);
|
||||
void add_pressed_callback(std::function<void()> 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
|
@ -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<void()> confirmCb,
|
||||
std::function<void()> 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();
|
||||
|
||||
|
@ -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",
|
||||
|
243
src/ui/ui_prompt.cpp
Normal file
243
src/ui/ui_prompt.cpp
Normal file
@ -0,0 +1,243 @@
|
||||
#include <mutex>
|
||||
|
||||
#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<void()> confirm_action;
|
||||
std::function<void()> cancel_action;
|
||||
std::string return_element_id;
|
||||
std::mutex mutex;
|
||||
} prompt_state;
|
||||
|
||||
void run_confirm_callback() {
|
||||
std::function<void()> 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<void()> 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<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<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<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<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<Label>(prompt_content, "Graphics options have changed", LabelStyle::Large);
|
||||
prompt_state.prompt_header->set_margin(24, Unit::Dp);
|
||||
|
||||
prompt_state.prompt_label = context.create_element<Label>(prompt_content, "Would you like to apply or discard these changes?", LabelStyle::Small);
|
||||
prompt_state.prompt_label->set_margin(24, Unit::Dp);
|
||||
prompt_state.prompt_label->set_margin_top(0);
|
||||
|
||||
Element* prompt_controls = context.create_element<Element>(prompt_content);
|
||||
|
||||
prompt_controls->set_display(Display::Flex);
|
||||
prompt_controls->set_flex_direction(FlexDirection::Row);
|
||||
prompt_controls->set_justify_content(JustifyContent::Center);
|
||||
prompt_controls->set_padding_top(24, Unit::Dp);
|
||||
prompt_controls->set_padding_bottom(24, Unit::Dp);
|
||||
prompt_controls->set_padding_left(12, Unit::Dp);
|
||||
prompt_controls->set_padding_right(12, Unit::Dp);
|
||||
prompt_controls->set_border_top_width(1.1, Unit::Dp);
|
||||
prompt_controls->set_border_top_color({ 255, 255, 255, 25 });
|
||||
|
||||
prompt_state.confirm_button = context.create_element<Button>(prompt_controls, "", ButtonStyle::Primary);
|
||||
prompt_state.confirm_button->set_min_width(185.0f, Unit::Dp);
|
||||
prompt_state.confirm_button->set_margin_top(0);
|
||||
prompt_state.confirm_button->set_margin_bottom(0);
|
||||
prompt_state.confirm_button->set_margin_left(12, Unit::Dp);
|
||||
prompt_state.confirm_button->set_margin_right(12, Unit::Dp);
|
||||
prompt_state.confirm_button->set_text_align(TextAlign::Center);
|
||||
prompt_state.confirm_button->set_color(Color{ 204, 204, 204, 255 });
|
||||
prompt_state.confirm_button->add_pressed_callback(run_confirm_callback);
|
||||
// TODO nav: autofocus
|
||||
// TODO nav: nav-left: none; nav-right: cancel_button
|
||||
|
||||
Style* confirm_hover_style = prompt_state.confirm_button->get_hover_style();
|
||||
confirm_hover_style->set_border_color(Color{ 69, 208, 67, 255 });
|
||||
confirm_hover_style->set_background_color(Color{ 69, 208, 67, 76 });
|
||||
confirm_hover_style->set_color(Color{ 242, 242, 242, 255 });
|
||||
|
||||
prompt_state.cancel_button = context.create_element<Button>(prompt_controls, "", ButtonStyle::Primary);
|
||||
prompt_state.cancel_button->set_min_width(185.0f, Unit::Dp);
|
||||
prompt_state.cancel_button->set_margin_top(0);
|
||||
prompt_state.cancel_button->set_margin_bottom(0);
|
||||
prompt_state.cancel_button->set_margin_left(12, Unit::Dp);
|
||||
prompt_state.cancel_button->set_margin_right(12, Unit::Dp);
|
||||
prompt_state.cancel_button->set_text_align(TextAlign::Center);
|
||||
prompt_state.cancel_button->set_color(Color{ 204, 204, 204, 255 });
|
||||
prompt_state.cancel_button->add_pressed_callback(run_cancel_callback);
|
||||
// TODO nav: nav-left: confirm_button; nav-right: none
|
||||
|
||||
Style* cancel_hover_style = prompt_state.cancel_button->get_hover_style();
|
||||
cancel_hover_style->set_border_color(Color{ 248, 96, 57, 255 });
|
||||
cancel_hover_style->set_background_color(Color{ 248, 96, 57, 76 });
|
||||
cancel_hover_style->set_color(Color{ 242, 242, 242, 255 });
|
||||
|
||||
context.close();
|
||||
}
|
||||
|
||||
void style_button(recompui::Button* button, recompui::ButtonVariant variant) {
|
||||
recompui::Color button_color{};
|
||||
|
||||
switch (variant) {
|
||||
case recompui::ButtonVariant::Primary:
|
||||
button_color = { 185, 125, 242, 255 };
|
||||
break;
|
||||
case recompui::ButtonVariant::Secondary:
|
||||
button_color = { 23, 214, 232, 255 };
|
||||
break;
|
||||
case recompui::ButtonVariant::Tertiary:
|
||||
button_color = { 242, 242, 242, 255 };
|
||||
break;
|
||||
case recompui::ButtonVariant::Success:
|
||||
button_color = { 69, 208, 67, 255 };
|
||||
break;
|
||||
case recompui::ButtonVariant::Error:
|
||||
button_color = { 248, 96, 57, 255 };
|
||||
break;
|
||||
case recompui::ButtonVariant::Warning:
|
||||
button_color = { 233, 205, 53, 255 };
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
recompui::Color border_color = button_color;
|
||||
recompui::Color background_color = button_color;
|
||||
border_color.a = 0.8f * 255;
|
||||
background_color.a = 0.05f * 255;
|
||||
button->set_border_color(border_color);
|
||||
button->set_background_color(background_color);
|
||||
|
||||
recompui::Color hover_border_color = button_color;
|
||||
recompui::Color hover_background_color = button_color;
|
||||
hover_border_color.a = 255;
|
||||
hover_background_color.a = 0.3f * 255;
|
||||
recompui::Style* hover_style = button->get_hover_style();
|
||||
hover_style->set_border_color(hover_border_color);
|
||||
hover_style->set_background_color(hover_background_color);
|
||||
|
||||
recompui::Color disabled_color { 255, 255, 255, 0.6f * 255 };
|
||||
recompui::Style* disabled_style = button->get_disabled_style();
|
||||
disabled_style->set_color(disabled_color);
|
||||
}
|
||||
|
||||
void recompui::open_prompt(
|
||||
const std::string& headerText,
|
||||
const std::string& contentText,
|
||||
const std::string& confirmLabelText,
|
||||
const std::string& cancelLabelText,
|
||||
std::function<void()> confirmCb,
|
||||
std::function<void()> cancelCb,
|
||||
ButtonVariant _confirmVariant,
|
||||
ButtonVariant _cancelVariant,
|
||||
bool _focusOnCancel,
|
||||
const std::string& _returnElementId
|
||||
) {
|
||||
std::lock_guard lock{ prompt_state.mutex };
|
||||
|
||||
prompt_state.ui_context.open();
|
||||
|
||||
prompt_state.prompt_header->set_text(headerText);
|
||||
prompt_state.prompt_label->set_text(contentText);
|
||||
prompt_state.confirm_button->set_text(confirmLabelText);
|
||||
prompt_state.cancel_button->set_text(cancelLabelText);
|
||||
prompt_state.confirm_action = confirmCb;
|
||||
prompt_state.cancel_action = cancelCb;
|
||||
prompt_state.return_element_id = _returnElementId;
|
||||
|
||||
style_button(prompt_state.confirm_button, _confirmVariant);
|
||||
style_button(prompt_state.cancel_button, _cancelVariant);
|
||||
|
||||
if (_focusOnCancel) {
|
||||
// TODO nav: focus cancel button
|
||||
}
|
||||
else {
|
||||
// TODO nav: focus confirm button
|
||||
}
|
||||
|
||||
prompt_state.ui_context.close();
|
||||
|
||||
if (!recompui::is_context_shown(prompt_state.ui_context)) {
|
||||
recompui::show_context(prompt_state.ui_context, "");
|
||||
}
|
||||
}
|
||||
|
||||
bool recompui::is_prompt_open() {
|
||||
return false;
|
||||
}
|
@ -231,9 +231,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void load_documents() {
|
||||
launcher_menu_controller->load_document(context);
|
||||
config_menu_controller->load_document(context);
|
||||
void create_menus() {
|
||||
launcher_menu_controller->load_document();
|
||||
config_menu_controller->load_document();
|
||||
recompui::init_prompt_context();
|
||||
}
|
||||
|
||||
void unload() {
|
||||
@ -443,7 +444,7 @@ void init_hook(RT64::RenderInterface* interface, RT64::RenderDevice* device) {
|
||||
std::locale::global(std::locale::classic());
|
||||
#endif
|
||||
ui_state = std::make_unique<UIState>(window, interface, device);
|
||||
ui_state->load_documents();
|
||||
ui_state->create_menus();
|
||||
}
|
||||
|
||||
moodycamel::ConcurrentQueue<SDL_Event> ui_event_queue{};
|
||||
|
Loading…
x
Reference in New Issue
Block a user