From 6c0c80b7bbb27c94a00fe8b9eaa4b5a8404000b0 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Mon, 16 Mar 2026 01:05:46 +0300 Subject: [PATCH] overlays/list-view: Use track to indicate scrolling instead of ugly highlight --- .../HomeMenu/overlay_home_menu_page.cpp | 2 - rpcs3/Emu/RSX/Overlays/overlay_list_view.cpp | 96 ++++++++++++------- rpcs3/Emu/RSX/Overlays/overlay_list_view.hpp | 10 +- rpcs3/Emu/RSX/Overlays/overlay_select.cpp | 2 +- 4 files changed, 69 insertions(+), 41 deletions(-) diff --git a/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_page.cpp b/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_page.cpp index 537fca0157..c71c1e6bd1 100644 --- a/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_page.cpp +++ b/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_page.cpp @@ -48,13 +48,11 @@ namespace rsx void home_menu_page::on_activate() { - hide_scroll_indicators(false); hide_row_highliter(false); } void home_menu_page::on_deactivate() { - hide_scroll_indicators(true); hide_row_highliter(true); } diff --git a/rpcs3/Emu/RSX/Overlays/overlay_list_view.cpp b/rpcs3/Emu/RSX/Overlays/overlay_list_view.cpp index b2cb2ea2c5..6c2c9aaeac 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_list_view.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_list_view.cpp @@ -12,20 +12,25 @@ namespace rsx w = width; h = height; - m_scroll_indicator_top = std::make_unique(width, 5); - m_scroll_indicator_bottom = std::make_unique(width, 5); - m_accept_btn = std::make_unique(120, 20); - m_cancel_btn = std::make_unique(120, 20); - m_highlight_box = std::make_unique(width, 0); + auto scroll_indicator_track = std::make_unique(5, height); + auto scroll_indicator_grip = std::make_unique(5, height); + + scroll_indicator_grip->set_pos(1, 0); + scroll_indicator_grip->set_size(5, 5); + scroll_indicator_grip->radius = 2; + scroll_indicator_track->set_size(7, height); + + m_scroll_indicator = std::make_unique(); + m_scroll_indicator_track = m_scroll_indicator->add_element(scroll_indicator_track); + m_scroll_indicator_grip = m_scroll_indicator->add_element(scroll_indicator_grip); + + m_accept_btn = std::make_unique(120, 20); + m_cancel_btn = std::make_unique(120, 20); + m_highlight_box = std::make_unique(width, 0); - m_scroll_indicator_top->set_size(width, 10); - m_scroll_indicator_bottom->set_size(width, 10); m_accept_btn->set_size(120, 30); m_cancel_btn->set_size(120, 30); - m_scroll_indicator_top->set_image_resource(resource_config::standard_image_resource::fade_top); - m_scroll_indicator_bottom->set_image_resource(resource_config::standard_image_resource::fade_bottom); - if (g_cfg.sys.enter_button_assignment == enter_button_assign::circle) { m_accept_btn->set_image_resource(resource_config::standard_image_resource::circle); @@ -37,7 +42,7 @@ namespace rsx m_cancel_btn->set_image_resource(resource_config::standard_image_resource::circle); } - m_scroll_indicator_bottom->set_pos(0, height - 10); + m_scroll_indicator->set_pos(width - 7, 0); m_accept_btn->set_pos(30, height + 20); if (can_deny) @@ -67,8 +72,6 @@ namespace rsx m_highlight_box->back_color = {.5f, .5f, .8f, 0.2f}; m_highlight_box->pulse_effect_enabled = true; - m_scroll_indicator_top->fore_color.a = 0.f; - m_scroll_indicator_bottom->fore_color.a = 0.f; } const overlay_element* list_view::get_selected_entry() const @@ -118,23 +121,16 @@ namespace rsx scroll_offset_value = max_y - h - 2; } - if ((scroll_offset_value + h + 2) >= m_elements_height) - m_scroll_indicator_bottom->fore_color.a = 0.f; - else - m_scroll_indicator_bottom->fore_color.a = 0.5f; - - if (scroll_offset_value == 0) - m_scroll_indicator_top->fore_color.a = 0.f; - else - m_scroll_indicator_top->fore_color.a = 0.5f; + if (m_elements_height > h) + { + update_scroll_indicator(); + } m_highlight_box->set_pos(current_element->x, current_element->y); m_highlight_box->h = current_element->h + pack_padding; m_highlight_box->y -= scroll_offset_value; m_highlight_box->refresh(); - m_scroll_indicator_top->refresh(); - m_scroll_indicator_bottom->refresh(); refresh(); } @@ -221,10 +217,10 @@ namespace rsx refresh(); } - void list_view::hide_scroll_indicators(bool hidden) + void list_view::hide_scroll_indicator(bool hidden) { - m_scroll_indicator_top->set_visible(!hidden); - m_scroll_indicator_bottom->set_visible(!hidden); + m_scroll_indicator_track->set_visible(!hidden); + m_scroll_indicator_grip->set_visible(!hidden); refresh(); } @@ -265,8 +261,7 @@ namespace rsx void list_view::translate(s16 _x, s16 _y) { layout_container::translate(_x, _y); - m_scroll_indicator_top->translate(_x, _y); - m_scroll_indicator_bottom->translate(_x, _y); + m_scroll_indicator->translate(_x, _y); m_accept_btn->translate(_x, _y); m_cancel_btn->translate(_x, _y); @@ -280,22 +275,49 @@ namespace rsx { vertical_layout::set_size(w, h); - m_scroll_indicator_top->w = w; - m_scroll_indicator_bottom->w = w; m_highlight_box->w = w; - m_scroll_indicator_top->refresh(); - m_scroll_indicator_bottom->refresh(); + update_scroll_indicator(); + + m_scroll_indicator->refresh(); m_highlight_box->refresh(); } void list_view::set_pos(s16 x, s16 y) { + const auto prev_x = this->x, prev_y = this->y; vertical_layout::set_pos(x, y); update_selection(); } + void list_view::update_scroll_indicator() + { + // Always reposition + m_scroll_indicator->set_pos(x + w - 7, y); + m_scroll_indicator->set_size(7, h); + + // Render grip and track + m_scroll_indicator_track->back_color = this->fore_color * 0.25f; + m_scroll_indicator_track->back_color.a = 1.f; + m_scroll_indicator_track->h = m_scroll_indicator->h; + + m_scroll_indicator_grip->back_color = this->fore_color; + m_scroll_indicator_grip->back_color.a = 1.f; + m_scroll_indicator_grip->h = 0; + + if (m_elements_height < h) + { + return; + } + + const f32 viewable_ratio = static_cast(m_scroll_indicator->h) / m_elements_height; + const f32 scroll_ratio = static_cast(scroll_offset_value) / m_elements_height; + + m_scroll_indicator_grip->h = static_cast(viewable_ratio * m_scroll_indicator->h); + m_scroll_indicator_grip->y = m_scroll_indicator->y + static_cast(scroll_ratio * m_scroll_indicator->h); + } + compiled_resource& list_view::get_compiled() { if (is_compiled()) @@ -313,10 +335,14 @@ namespace rsx auto& compiled = vertical_layout::get_compiled(); compiled.add(m_highlight_box->get_compiled()); - compiled.add(m_scroll_indicator_top->get_compiled()); - compiled.add(m_scroll_indicator_bottom->get_compiled()); compiled.add(m_cancel_btn->get_compiled()); + if (m_elements_height > h) + { + // Auto overflow + compiled.add(m_scroll_indicator->get_compiled()); + } + if (m_cancel_only) { m_is_compiled = true; diff --git a/rpcs3/Emu/RSX/Overlays/overlay_list_view.hpp b/rpcs3/Emu/RSX/Overlays/overlay_list_view.hpp index 72b5672fed..cc337d165c 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_list_view.hpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_list_view.hpp @@ -9,13 +9,15 @@ namespace rsx struct list_view : public vertical_layout { private: - std::unique_ptr m_scroll_indicator_top; - std::unique_ptr m_scroll_indicator_bottom; + std::unique_ptr m_scroll_indicator; std::unique_ptr m_cancel_btn; std::unique_ptr m_accept_btn; std::unique_ptr m_deny_btn; std::unique_ptr m_highlight_box; + overlay_element* m_scroll_indicator_track = nullptr; + rounded_rect* m_scroll_indicator_grip = nullptr; + u16 m_elements_height = 0; s32 m_selected_entry = -1; u16 m_elements_count = 0; @@ -23,6 +25,8 @@ namespace rsx bool m_use_separators = false; bool m_cancel_only = false; + void update_scroll_indicator(); + public: list_view(u16 width, u16 height, bool use_separators = true, bool can_deny = false); @@ -50,7 +54,7 @@ namespace rsx const overlay_element* get_selected_entry() const; void hide_prompt_buttons(bool hidden = true); - void hide_scroll_indicators(bool hidden = true); + void hide_scroll_indicator(bool hidden = true); void hide_row_highliter(bool hidden = false); void disable_selection_pulse(bool disabled = true); diff --git a/rpcs3/Emu/RSX/Overlays/overlay_select.cpp b/rpcs3/Emu/RSX/Overlays/overlay_select.cpp index d17a437002..5ef6eb254c 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_select.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_select.cpp @@ -11,7 +11,7 @@ namespace rsx::overlays : list_view(w, h, false) { hide_prompt_buttons(); - hide_scroll_indicators(); + hide_scroll_indicator(); pack_padding = dropdown_pack_padding; }