rxs/overlays: Fix visual glitches in the tabbed settings dialogs

This commit is contained in:
kd-11 2026-03-09 03:22:14 +03:00 committed by kd-11
parent 7d92198ef0
commit 88278ec7c9
7 changed files with 155 additions and 82 deletions

View file

@ -28,12 +28,23 @@ namespace rsx
}
home_menu_checkbox::home_menu_checkbox(cfg::_bool* setting, const std::string& text) : home_menu_setting(setting, text)
{
m_background.set_size(menu_entry_margin, menu_entry_margin);
m_background.set_pos(overlay::virtual_width / 2 + menu_entry_margin, 0);
{}
m_checkbox.set_size(m_background.w - 2, m_background.h - 2);
m_checkbox.set_pos(m_background.x, m_background.y);
void home_menu_checkbox::set_size(u16 w, u16 h)
{
set_reserved_width(w / 2 + menu_entry_margin);
home_menu_setting::set_size(w, h);
auto box = std::make_unique<box_layout>();
m_background = box->add_element();
m_checkbox = box->add_element();
m_background->set_size(menu_checkbox_size, menu_checkbox_size);
m_checkbox->set_size(m_background->w - 2, m_background->h - 2);
m_checkbox->set_pos(1, 1);
box->set_pos(0, 16);
add_element(box);
}
compiled_resource& home_menu_checkbox::get_compiled()
@ -42,21 +53,14 @@ namespace rsx
if (!is_compiled())
{
const f32 col = m_last_value ? 1.0f : 0.3f;
const f32 bkg = m_last_value ? 0.3f : 1.0f;
m_background.back_color.r = bkg;
m_background.back_color.g = bkg;
m_background.back_color.b = bkg;
m_checkbox.back_color.r = col;
m_checkbox.back_color.g = col;
m_checkbox.back_color.b = col;
m_background.set_pos(m_background.x, y + (h - m_background.h) / 2);
m_checkbox.set_pos(m_background.x + 1, m_background.y + 1);
m_background->back_color = { 1.f };
m_checkbox->back_color = { 0.3f };
m_checkbox->back_color.a = 1.f;
m_checkbox->set_visible(!m_last_value);
compiled_resources = horizontal_layout::get_compiled();
compiled_resources.add(m_background.get_compiled());
compiled_resources.add(m_checkbox.get_compiled());
compiled_resources.add(m_background->get_compiled());
compiled_resources.add(m_checkbox->get_compiled());
}
return compiled_resources;

View file

@ -9,7 +9,8 @@ namespace rsx
namespace overlays
{
static constexpr u16 menu_entry_height = 40;
static constexpr u16 menu_entry_margin = 20;
static constexpr u16 menu_entry_margin = 30;
static constexpr u16 menu_checkbox_size = 20;
static constexpr u16 element_height = 25;
enum class page_navigation
@ -31,30 +32,50 @@ namespace rsx
struct home_menu_setting : horizontal_layout
{
public:
home_menu_setting(C* setting, const std::string& text) : m_setting(setting)
home_menu_setting(C* setting, const std::string& text)
: m_setting(setting)
, m_label_text(text)
{
std::unique_ptr<overlay_element> layout = std::make_unique<vertical_layout>();
update_value(true);
auto_resize = false;
}
void set_reserved_width(u16 size)
{
m_reserved_width = size;
}
void set_size(u16 w, u16 h = menu_entry_height) override
{
clear_items();
std::unique_ptr<overlay_element> layout = std::make_unique<vertical_layout>();
std::unique_ptr<overlay_element> padding = std::make_unique<spacer>();
std::unique_ptr<overlay_element> title = std::make_unique<label>(text);
std::unique_ptr<overlay_element> title = std::make_unique<label>(m_label_text);
const u16 available_width = std::max(w, m_reserved_width) - (menu_entry_margin * 2) - m_reserved_width;
layout->set_size(available_width, 0);
padding->set_size(1, 1);
title->set_size(available_side_width, menu_entry_height);
title->set_size(available_width, menu_entry_height);
title->set_font("Arial", 16);
title->set_wrap_text(true);
title->align_text(text_align::right);
title->align_text(text_align::left);
// Make back color transparent for text
title->back_color.a = 0.f;
static_cast<vertical_layout*>(layout.get())->auto_resize = true;
static_cast<vertical_layout*>(layout.get())->pack_padding = 5;
static_cast<vertical_layout*>(layout.get())->add_element(padding);
static_cast<vertical_layout*>(layout.get())->add_element(title);
horizontal_layout::set_size(w, std::max(h, layout->h));
horizontal_layout::advance_pos = menu_entry_margin / 2;
// Pack
this->pack_padding = 15;
add_element(layout);
update_value(true);
}
void update_value(bool initializing = false)
@ -72,29 +93,43 @@ namespace rsx
protected:
T m_last_value = {};
C* m_setting = nullptr;
u16 m_reserved_width;
std::string m_label_text;
};
struct home_menu_checkbox : public home_menu_setting<bool, cfg::_bool>
{
public:
home_menu_checkbox(cfg::_bool* setting, const std::string& text);
void set_size(u16 w, u16 h = element_height) override;
compiled_resource& get_compiled() override;
private:
overlay_element m_background;
overlay_element m_checkbox;
overlay_element* m_background = nullptr;
overlay_element* m_checkbox = nullptr;
};
template <typename T>
struct home_menu_dropdown : public home_menu_setting<T, cfg::_enum<T>>
{
public:
home_menu_dropdown(cfg::_enum<T>* setting, const std::string& text) : home_menu_setting<T, cfg::_enum<T>>(setting, text)
home_menu_dropdown(cfg::_enum<T>* setting, const std::string& text)
: home_menu_setting<T, cfg::_enum<T>>(setting, text)
{}
void set_size(u16 w, u16 h = element_height) override
{
m_dropdown.set_size(available_side_width / 2, element_height);
m_dropdown.set_pos(overlay::virtual_width / 2 + menu_entry_margin, 0);
m_dropdown.set_font("Arial", 14);
m_dropdown.align_text(home_menu_dropdown<T>::text_align::center);
m_dropdown.back_color = { 0.3f, 0.3f, 0.3f, 1.0f };
home_menu_setting<T, cfg::_enum<T>>::set_reserved_width(w / 2 + menu_entry_margin);
home_menu_setting<T, cfg::_enum<T>>::set_size(w, h);
auto dropdown = std::make_unique<overlays::label>();
m_dropdown = horizontal_layout::add_element(dropdown);
m_dropdown->set_size(w / 2, element_height);
m_dropdown->set_font("Arial", 14);
m_dropdown->align_text(home_menu_dropdown<T>::text_align::center);
m_dropdown->back_color = { 0.3f, 0.3f, 0.3f, 1.0f };
}
compiled_resource& get_compiled() override
@ -104,18 +139,18 @@ namespace rsx
if (!this->is_compiled())
{
const std::string value_text = Emu.GetCallbacks().get_localized_setting(home_menu_setting<T, cfg::_enum<T>>::m_setting, static_cast<u32>(this->m_last_value));
m_dropdown.set_text(value_text);
m_dropdown.set_pos(m_dropdown.x, this->y + (this->h - m_dropdown.h) / 2);
m_dropdown->set_text(value_text);
m_dropdown->set_pos(m_dropdown->x, this->y + (this->h - m_dropdown->h) / 2);
this->compiled_resources = horizontal_layout::get_compiled();
this->compiled_resources.add(m_dropdown.get_compiled());
this->compiled_resources.add(m_dropdown->get_compiled());
}
return this->compiled_resources;
}
private:
label m_dropdown;
label* m_dropdown;
};
template <typename T, typename C>
@ -128,17 +163,30 @@ namespace rsx
, m_special_labels(std::move(special_labels))
, m_minimum(minimum)
, m_maximum(maximum)
{}
void set_size(u16 w, u16 h = element_height) override
{
m_slider.set_size(available_side_width / 2, element_height);
m_slider.set_pos(overlay::virtual_width / 2 + menu_entry_margin, 0);
m_slider.back_color = { 0.3f, 0.3f, 0.3f, 1.0f };
home_menu_setting<T, C>::set_reserved_width(w / 2 + menu_entry_margin);
home_menu_setting<T, C>::set_size(w, h);
m_handle.set_size(element_height / 2, element_height);
m_handle.set_pos(m_slider.x, 0);
m_handle.back_color = { 1.0f, 1.0f, 1.0f, 1.0f };
auto box = std::make_unique<box_layout>();
m_slider = box->add_element();
m_handle = box->add_element();
m_value_label.back_color = m_slider.back_color;
m_value_label.set_font("Arial", 14);
m_slider->set_size(w / 2, element_height);
m_slider->back_color = { 0.3f, 0.3f, 0.3f, 1.0f };
m_handle->set_size(element_height / 2, element_height);
m_handle->set_pos(m_slider->x, 0);
m_handle->back_color = { 1.0f, 1.0f, 1.0f, 1.0f };
auto value_label = std::make_unique<label>();
value_label->back_color = m_slider->back_color;
value_label->set_font("Arial", 14);
m_value_label = box->add_element(value_label);
horizontal_layout::add_element(box);
}
compiled_resource& get_compiled() override
@ -148,54 +196,55 @@ namespace rsx
if (!this->is_compiled())
{
const f64 percentage = std::clamp((this->m_last_value - static_cast<T>(m_minimum)) / std::fabs(m_maximum - m_minimum), 0.0, 1.0);
m_slider.set_pos(m_slider.x, this->y + (this->h - m_slider.h) / 2);
m_handle.set_pos(m_slider.x + static_cast<s16>(percentage * (m_slider.w - m_handle.w)), this->y + (this->h - m_handle.h) / 2);
m_slider->set_pos(m_slider->x, this->y + (this->h - m_slider->h) / 2);
m_handle->set_pos(m_slider->x + static_cast<s16>(percentage * (m_slider->w - m_handle->w)), this->y + (this->h - m_handle->h) / 2);
const auto set_label_text = [this]() -> void
{
if (const auto it = m_special_labels.find(this->m_last_value); it != m_special_labels.cend())
{
m_value_label.set_text(it->second);
m_value_label->set_text(it->second);
return;
}
if constexpr (std::is_floating_point_v<T>)
{
m_value_label.set_text(fmt::format("%.2f%s", this->m_last_value, m_suffix));
m_value_label->set_text(fmt::format("%.2f%s", this->m_last_value, m_suffix));
}
else
{
m_value_label.set_text(fmt::format("%d%s", this->m_last_value, m_suffix));
m_value_label->set_text(fmt::format("%d%s", this->m_last_value, m_suffix));
}
};
set_label_text();
m_value_label.auto_resize();
m_value_label->auto_resize();
constexpr u16 handle_margin = 10;
if ((m_handle.x - m_slider.x) > (m_slider.w - (m_handle.w + 2 * handle_margin + m_value_label.w)))
if ((m_handle->x - m_slider->x) > (m_slider->w - (m_handle->w + 2 * handle_margin + m_value_label->w)))
{
m_value_label.set_pos(m_handle.x - (handle_margin + m_value_label.w), m_handle.y);
m_value_label->set_pos(m_handle->x - (handle_margin + m_value_label->w), m_handle->y);
}
else
{
m_value_label.set_pos(m_handle.x + m_handle.w + handle_margin, m_handle.y);
m_value_label->set_pos(m_handle->x + m_handle->w + handle_margin, m_handle->y);
}
this->compiled_resources = horizontal_layout::get_compiled();
this->compiled_resources.add(m_slider.get_compiled());
this->compiled_resources.add(m_handle.get_compiled());
this->compiled_resources.add(m_value_label.get_compiled());
this->compiled_resources.add(m_slider->get_compiled());
this->compiled_resources.add(m_handle->get_compiled());
this->compiled_resources.add(m_value_label->get_compiled());
}
return this->compiled_resources;
}
private:
overlay_element m_slider;
overlay_element m_handle;
label m_value_label;
overlay_element* m_slider;
overlay_element* m_handle;
label* m_value_label;
std::string m_suffix;
std::map<T, std::string> m_special_labels;
T m_minimum{};

View file

@ -26,12 +26,10 @@ namespace rsx
m_message_box = std::make_shared<home_menu_message_box>(x, y, width, height);
m_message_box->visible = false;
m_config_changed = std::make_shared<bool>(g_backup_cfg.to_string() != g_cfg.to_string());
m_sidebar = std::make_unique<list_view>(350, height, false);
m_sidebar->set_pos(x, y);
m_sidebar->hide_prompt_buttons();
m_sidebar->back_color = color4f(0.15f, 0.15f, 0.15f, 0.85f);
m_sidebar->back_color = color4f(0.15f, 0.15f, 0.15f, 0.95f);
m_sliding_animation.duration_sec = 0.5f;
m_sliding_animation.type = animation_type::ease_in_out_cubic;

View file

@ -20,6 +20,12 @@ namespace rsx
m_message_box = parent->m_message_box;
m_config_changed = parent->m_config_changed;
}
else
{
m_config_changed = std::make_shared<bool>(g_backup_cfg.to_string() != g_cfg.to_string());
m_message_box = std::make_shared<home_menu_message_box>(x, y, width, height);
m_message_box->visible = false;
}
m_reset_btn.set_image_resource(resource_config::standard_image_resource::select);
m_save_btn.set_image_resource(resource_config::standard_image_resource::square);
@ -123,20 +129,24 @@ namespace rsx
clear_items();
// Center vertically if necessary
if (center_vertically)
usz total_height = 0;
for (auto& entry : m_entries)
{
usz total_height = 0;
total_height += entry->h;
}
for (auto& entry : m_entries)
{
total_height += entry->h;
}
if (total_height < h)
// Center vertically if necessary
if (total_height < h)
{
if (center_vertically)
{
advance_pos = (h - ::narrow<u16>(total_height)) / 2;
}
else
{
advance_pos = menu_entry_margin;
}
}
for (auto& entry : m_entries)
@ -144,6 +154,8 @@ namespace rsx
entry->set_pos(0, 0);
add_entry(entry);
}
refresh();
}
void home_menu_page::show_dialog(const std::string& text, std::function<void()> on_accept, std::function<void()> on_cancel)
@ -294,9 +306,10 @@ namespace rsx
void home_menu_page::translate(s16 _x, s16 _y)
{
list_view::translate(_x, _y);
m_save_btn.translate(_x, _y);
m_discard_btn.translate(_x, _y);
m_reset_btn.translate(_x, _y);
m_reset_btn.set_pos(x + w - 3 * (30 + 120), y + h + 20);
m_save_btn.set_pos(x + w - 2 * (30 + 120), y + h + 20);
m_discard_btn.set_pos(x + w - (30 + 120), y + h + 20);
}
void home_menu_page::set_size(u16 _w, u16 _h)
@ -309,6 +322,10 @@ namespace rsx
entry->set_size(_w, entry->h);
}
m_reset_btn.set_pos(x + w - 3 * (30 + 120), y + h + 20);
m_save_btn.set_pos(x + w - 2 * (30 + 120), y + h + 20);
m_discard_btn.set_pos(x + w - (30 + 120), y + h + 20);
apply_layout();
}

View file

@ -24,7 +24,7 @@ namespace rsx
void on_activate();
void on_deactivate();
virtual void update(u64 timestamp_us) {}
virtual void update(u64 /*timestamp_us*/) {}
virtual bool show_reset_button() const { return false; }
bool is_current_page = false;
@ -38,7 +38,7 @@ namespace rsx
virtual void add_page(std::shared_ptr<home_menu_page> page);
virtual void add_item(std::unique_ptr<overlay_element>& element, std::function<page_navigation(pad_button)> callback);
virtual void add_item(std::string_view, std::function<page_navigation(pad_button)> callback);
void apply_layout(bool center_vertically = true);
void apply_layout(bool center_vertically = false);
void show_dialog(const std::string& text, std::function<void()> on_accept = nullptr, std::function<void()> on_cancel = nullptr);
std::vector<std::shared_ptr<home_menu_page>> m_pages;

View file

@ -9,8 +9,9 @@ namespace rsx
home_menu_settings::home_menu_settings(s16 x, s16 y, u16 width, u16 height, bool use_separators, home_menu_page* parent)
: home_menu_page(x, y, width, height, use_separators, parent, get_localized_string(localized_string_id::HOME_MENU_SETTINGS))
{
m_tabs = std::make_unique<tabbed_container>(width, height, 350);
m_tabs = std::make_unique<tabbed_container>(width, height, 300);
m_tabs->set_pos(x, y);
m_tabs->set_headers_background_color({ 0.25f, 0.25f, 0.25f, 0.95f });
add_page(std::make_shared<home_menu_settings_audio>(x, y, width, height, use_separators, nullptr));
add_page(std::make_shared<home_menu_settings_video>(x, y, width, height, use_separators, nullptr));
@ -20,8 +21,6 @@ namespace rsx
add_page(std::make_shared<home_menu_settings_performance_overlay>(x, y, width, height, use_separators, nullptr));
add_page(std::make_shared<home_menu_settings_debug>(x, y, width, height, use_separators, nullptr));
//apply_layout();
// Select the first item
m_tabs->set_selected_tab(0);
}
@ -30,6 +29,7 @@ namespace rsx
{
auto panel = std::static_pointer_cast<overlay_element>(page);
page->on_deactivate();
page->hide_prompt_buttons();
m_tabs->add_tab(page->title, panel);
}
@ -102,7 +102,7 @@ namespace rsx
add_checkbox(&g_cfg.audio.enable_time_stretching, localized_string_id::HOME_MENU_SETTINGS_AUDIO_TIME_STRETCHING);
add_signed_slider(&g_cfg.audio.time_stretching_threshold, localized_string_id::HOME_MENU_SETTINGS_AUDIO_TIME_STRETCHING_THRESHOLD, " %", 1);
apply_layout(false);
apply_layout();
}
home_menu_settings_video::home_menu_settings_video(s16 x, s16 y, u16 width, u16 height, bool use_separators, home_menu_page* parent)

View file

@ -36,6 +36,7 @@ namespace rsx
const std::string localized_text = get_localized_string(loc_id);
std::unique_ptr<overlay_element> elem = std::make_unique<home_menu_checkbox>(setting, localized_text);
elem->set_size(this->w, menu_entry_height);
add_item(elem, [this, setting](pad_button btn) -> page_navigation
{
@ -76,6 +77,7 @@ namespace rsx
const std::string localized_text = get_localized_string(loc_id);
std::unique_ptr<overlay_element> elem = std::make_unique<home_menu_dropdown<T>>(setting, localized_text);
elem->set_size(this->w, menu_entry_height);
add_item(elem, [this, setting](pad_button btn) -> page_navigation
{
@ -149,6 +151,7 @@ namespace rsx
const std::string localized_text = get_localized_string(loc_id);
std::unique_ptr<overlay_element> elem = std::make_unique<home_menu_signed_slider<Min, Max>>(setting, localized_text, suffix, special_labels, minimum, maximum);
elem->set_size(this->w, menu_entry_height);
add_item(elem, [this, setting, step_size, minimum, maximum](pad_button btn) -> page_navigation
{
@ -194,6 +197,7 @@ namespace rsx
const std::string localized_text = get_localized_string(loc_id);
std::unique_ptr<overlay_element> elem = std::make_unique<home_menu_unsigned_slider<Min, Max>>(setting, localized_text, suffix, special_labels, minimum, maximum);
elem->set_size(this->w, menu_entry_height);
add_item(elem, [this, setting, step_size, minimum, maximum, exceptions](pad_button btn) -> page_navigation
{
@ -246,6 +250,7 @@ namespace rsx
const std::string localized_text = get_localized_string(loc_id);
std::unique_ptr<overlay_element> elem = std::make_unique<home_menu_float_slider<Min, Max>>(setting, localized_text, suffix, special_labels, minimum, maximum);
elem->set_size(this->w, menu_entry_height);
add_item(elem, [this, setting, step_size, minimum, maximum](pad_button btn) -> page_navigation
{