diff --git a/rpcs3/Emu/CMakeLists.txt b/rpcs3/Emu/CMakeLists.txt index 63951cfe92..c7eea83995 100644 --- a/rpcs3/Emu/CMakeLists.txt +++ b/rpcs3/Emu/CMakeLists.txt @@ -517,6 +517,7 @@ target_sources(rpcs3_emu PRIVATE RSX/Overlays/overlay_perf_metrics.cpp RSX/Overlays/overlay_progress_bar.cpp RSX/Overlays/overlay_save_dialog.cpp + RSX/Overlays/overlay_tabs.cpp RSX/Overlays/overlay_trophy_notification.cpp RSX/Overlays/overlay_user_list_dialog.cpp RSX/Overlays/overlay_utils.cpp diff --git a/rpcs3/Emu/RSX/Overlays/overlay_controls.cpp b/rpcs3/Emu/RSX/Overlays/overlay_controls.cpp index 65ef78be4d..96ffaac93d 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_controls.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_controls.cpp @@ -579,43 +579,49 @@ namespace rsx compiled_resource& overlay_element::get_compiled() { - if (!is_compiled()) + if (is_compiled()) { - compiled_resources.clear(); + return compiled_resources; + } - compiled_resource compiled_resources_temp = {}; - auto& cmd_bg = compiled_resources_temp.append({}); - auto& config = cmd_bg.config; + m_is_compiled = true; + compiled_resources.clear(); - config.color = back_color; - config.pulse_glow = pulse_effect_enabled; - config.pulse_sinus_offset = pulse_sinus_offset; - config.pulse_speed_modifier = pulse_speed_modifier; + if (!is_visible()) + { + return compiled_resources; + } - auto& verts = compiled_resources_temp.draw_commands.front().verts; - verts.resize(4); + compiled_resource compiled_resources_temp = {}; + auto& cmd_bg = compiled_resources_temp.append({}); + auto& config = cmd_bg.config; - verts[0].vec4(x, y, 0.f, 0.f); - verts[1].vec4(f32(x + w), y, 1.f, 0.f); - verts[2].vec4(x, f32(y + h), 0.f, 1.f); - verts[3].vec4(f32(x + w), f32(y + h), 1.f, 1.f); + config.color = back_color; + config.pulse_glow = pulse_effect_enabled; + config.pulse_sinus_offset = pulse_sinus_offset; + config.pulse_speed_modifier = pulse_speed_modifier; - compiled_resources.add(std::move(compiled_resources_temp), margin_left, margin_top); + auto& verts = compiled_resources_temp.draw_commands.front().verts; + verts.resize(4); - if (!text.empty()) - { - compiled_resources_temp.clear(); - auto& cmd_text = compiled_resources_temp.append({}); + verts[0].vec4(x, y, 0.f, 0.f); + verts[1].vec4(f32(x + w), y, 1.f, 0.f); + verts[2].vec4(x, f32(y + h), 0.f, 1.f); + verts[3].vec4(f32(x + w), f32(y + h), 1.f, 1.f); - cmd_text.config.set_font(get_font()); - cmd_text.config.color = fore_color; - cmd_text.verts = render_text(text.c_str(), static_cast(x), static_cast(y)); + compiled_resources.add(std::move(compiled_resources_temp), margin_left, margin_top); - if (!cmd_text.verts.empty()) - compiled_resources.add(std::move(compiled_resources_temp), margin_left - horizontal_scroll_offset, margin_top - vertical_scroll_offset); - } + if (!text.empty()) + { + compiled_resources_temp.clear(); + auto& cmd_text = compiled_resources_temp.append({}); - m_is_compiled = true; + cmd_text.config.set_font(get_font()); + cmd_text.config.color = fore_color; + cmd_text.verts = render_text(text.c_str(), static_cast(x), static_cast(y)); + + if (!cmd_text.verts.empty()) + compiled_resources.add(std::move(compiled_resources_temp), margin_left - horizontal_scroll_offset, margin_top - vertical_scroll_offset); } return compiled_resources; @@ -722,6 +728,13 @@ namespace rsx add_element(spacer_element); } + void layout_container::clear_items() + { + m_items.clear(); + advance_pos = 0; + scroll_offset_value = 0; + } + overlay_element* vertical_layout::add_element(std::unique_ptr& item, int offset) { if (auto_resize) @@ -888,27 +901,36 @@ namespace rsx compiled_resource& image_view::get_compiled() { - if (!is_compiled()) + if (is_compiled()) { - auto& result = overlay_element::get_compiled(); - auto& cmd_img = result.draw_commands.front(); - - cmd_img.config.set_image_resource(image_resource_ref); - cmd_img.config.color = fore_color; - cmd_img.config.external_data_ref = external_ref; - cmd_img.config.blur_strength = blur_strength; - - // Make padding work for images (treat them as the content instead of the 'background') - auto& verts = cmd_img.verts; - - verts[0] += vertex(padding_left, padding_bottom, 0, 0); - verts[1] += vertex(-padding_right, padding_bottom, 0, 0); - verts[2] += vertex(padding_left, -padding_top, 0, 0); - verts[3] += vertex(-padding_right, -padding_top, 0, 0); - - m_is_compiled = true; + return compiled_resources; } + compiled_resources.clear(); + + if (!is_visible()) + { + m_is_compiled = true; + return compiled_resources; + } + + auto& result = overlay_element::get_compiled(); + auto& cmd_img = result.draw_commands.front(); + + cmd_img.config.set_image_resource(image_resource_ref); + cmd_img.config.color = fore_color; + cmd_img.config.external_data_ref = external_ref; + cmd_img.config.blur_strength = blur_strength; + + // Make padding work for images (treat them as the content instead of the 'background') + auto& verts = cmd_img.verts; + + verts[0] += vertex(padding_left, padding_bottom, 0, 0); + verts[1] += vertex(-padding_right, padding_bottom, 0, 0); + verts[2] += vertex(padding_left, -padding_top, 0, 0); + verts[3] += vertex(-padding_right, -padding_top, 0, 0); + + m_is_compiled = true; return compiled_resources; } @@ -961,29 +983,40 @@ namespace rsx compiled_resource& image_button::get_compiled() { - if (!is_compiled()) + if (is_compiled()) { - auto& compiled = image_view::get_compiled(); - for (auto& cmd : compiled.draw_commands) + return compiled_resources; + } + + compiled_resources.clear(); + + if (!is_visible()) + { + m_is_compiled = true; + return compiled_resources; + } + + auto& compiled = image_view::get_compiled(); + for (auto& cmd : compiled.draw_commands) + { + if (cmd.config.texture_ref == image_resource_id::font_file) { - if (cmd.config.texture_ref == image_resource_id::font_file) + // Text, translate geometry to the right + for (auto &v : cmd.verts) { - // Text, translate geometry to the right - for (auto &v : cmd.verts) - { - v.values[0] += m_text_offset_x; - v.values[1] += m_text_offset_y; - } + v.values[0] += m_text_offset_x; + v.values[1] += m_text_offset_y; } } } + m_is_compiled = true; return compiled_resources; } - label::label(const std::string& text) + label::label(std::string_view text) { - set_text(text); + set_text(text.data()); } bool label::auto_resize(bool grow_only, u16 limit_w, u16 limit_h) @@ -1013,90 +1046,97 @@ namespace rsx compiled_resource& rounded_rect::get_compiled() { - if (!is_compiled()) + if (is_compiled()) { - compiled_resources.clear(); - -#ifdef __APPLE__ - if (true) -#else - if (radius == 0 || radius > (w / 2)) -#endif - { - // Invalid radius - compiled_resources = overlay_element::get_compiled(); - } - else - { - compiled_resource compiled_resources_temp = {}; - compiled_resources_temp.append({}); // Bg horizontal mid - compiled_resources_temp.append({}); // Bg horizontal top - compiled_resources_temp.append({}); // Bg horizontal bottom - compiled_resources_temp.append({}); // Bg upper-left - compiled_resources_temp.append({}); // Bg lower-left - compiled_resources_temp.append({}); // Bg upper-right - compiled_resources_temp.append({}); // Bg lower-right - - for (auto& draw_cmd : compiled_resources_temp.draw_commands) - { - auto& config = draw_cmd.config; - config.color = back_color; - config.disable_vertex_snap = true; - config.pulse_glow = pulse_effect_enabled; - config.pulse_sinus_offset = pulse_sinus_offset; - config.pulse_speed_modifier = pulse_speed_modifier; - } - - auto& bg0 = compiled_resources_temp.draw_commands[0]; - auto& bg1 = compiled_resources_temp.draw_commands[1]; - auto& bg2 = compiled_resources_temp.draw_commands[2]; - - bg0.verts.emplace_back(f32(x), f32(y + radius), 0.f, 0.f); - bg0.verts.emplace_back(f32(x + w), f32(y + radius), 0.f, 0.f); - bg0.verts.emplace_back(f32(x), f32(y + h) - radius, 0.f, 0.f); - bg0.verts.emplace_back(f32(x + w), f32(y + h) - radius, 0.f, 0.f); - - bg1.verts.emplace_back(f32(x + radius), f32(y), 0.f, 0.f); - bg1.verts.emplace_back(f32(x + w) - radius, f32(y), 0.f, 0.f); - bg1.verts.emplace_back(f32(x + radius), f32(y + radius), 0.f, 0.f); - bg1.verts.emplace_back(f32(x + w) - radius, f32(y + radius), 0.f, 0.f); - - bg2.verts.emplace_back(f32(x + radius), f32(y + h) - radius, 0.f, 0.f); - bg2.verts.emplace_back(f32(x + w) - radius, f32(y + h) - radius, 0.f, 0.f); - bg2.verts.emplace_back(f32(x + radius), f32(y + h), 0.f, 0.f); - bg2.verts.emplace_back(f32(x + w) - radius, f32(y + h), 0.f, 0.f); - - // Generate the quadrants - const f32 corners[4][2] = - { - { f32(x + radius), f32(y + radius) }, - { f32(x + radius), f32(y + h) - radius }, - { f32(x + w) - radius, f32(y + radius) }, - { f32(x + w) - radius, f32(y + h) - radius } - }; - - const f32 radius_f = static_cast(radius); - const f32 scale[4][2] = - { - { -radius_f, -radius_f }, - { -radius_f, +radius_f }, - { +radius_f, -radius_f }, - { +radius_f, +radius_f } - }; - - for (int i = 0; i < 4; ++i) - { - auto& command = compiled_resources_temp.draw_commands[i + 3]; - command.config.primitives = rsx::overlays::primitive_type::triangle_fan; - command.verts = generate_unit_quadrant(num_control_points, corners[i], scale[i]); - } - - compiled_resources.add(std::move(compiled_resources_temp), margin_left, margin_top); - } - - m_is_compiled = true; + return compiled_resources; } + compiled_resources.clear(); + + if (!is_visible()) + { + m_is_compiled = true; + return compiled_resources; + } + +#ifdef __APPLE__ + if (true) +#else + if (radius == 0 || radius > (w / 2)) +#endif + { + // Invalid radius + compiled_resources = overlay_element::get_compiled(); + m_is_compiled = true; + return compiled_resources; + } + + compiled_resource compiled_resources_temp = {}; + compiled_resources_temp.append({}); // Bg horizontal mid + compiled_resources_temp.append({}); // Bg horizontal top + compiled_resources_temp.append({}); // Bg horizontal bottom + compiled_resources_temp.append({}); // Bg upper-left + compiled_resources_temp.append({}); // Bg lower-left + compiled_resources_temp.append({}); // Bg upper-right + compiled_resources_temp.append({}); // Bg lower-right + + for (auto& draw_cmd : compiled_resources_temp.draw_commands) + { + auto& config = draw_cmd.config; + config.color = back_color; + config.disable_vertex_snap = true; + config.pulse_glow = pulse_effect_enabled; + config.pulse_sinus_offset = pulse_sinus_offset; + config.pulse_speed_modifier = pulse_speed_modifier; + } + + auto& bg0 = compiled_resources_temp.draw_commands[0]; + auto& bg1 = compiled_resources_temp.draw_commands[1]; + auto& bg2 = compiled_resources_temp.draw_commands[2]; + + bg0.verts.emplace_back(f32(x), f32(y + radius), 0.f, 0.f); + bg0.verts.emplace_back(f32(x + w), f32(y + radius), 0.f, 0.f); + bg0.verts.emplace_back(f32(x), f32(y + h) - radius, 0.f, 0.f); + bg0.verts.emplace_back(f32(x + w), f32(y + h) - radius, 0.f, 0.f); + + bg1.verts.emplace_back(f32(x + radius), f32(y), 0.f, 0.f); + bg1.verts.emplace_back(f32(x + w) - radius, f32(y), 0.f, 0.f); + bg1.verts.emplace_back(f32(x + radius), f32(y + radius), 0.f, 0.f); + bg1.verts.emplace_back(f32(x + w) - radius, f32(y + radius), 0.f, 0.f); + + bg2.verts.emplace_back(f32(x + radius), f32(y + h) - radius, 0.f, 0.f); + bg2.verts.emplace_back(f32(x + w) - radius, f32(y + h) - radius, 0.f, 0.f); + bg2.verts.emplace_back(f32(x + radius), f32(y + h), 0.f, 0.f); + bg2.verts.emplace_back(f32(x + w) - radius, f32(y + h), 0.f, 0.f); + + // Generate the quadrants + const f32 corners[4][2] = + { + { f32(x + radius), f32(y + radius) }, + { f32(x + radius), f32(y + h) - radius }, + { f32(x + w) - radius, f32(y + radius) }, + { f32(x + w) - radius, f32(y + h) - radius } + }; + + const f32 radius_f = static_cast(radius); + const f32 scale[4][2] = + { + { -radius_f, -radius_f }, + { -radius_f, +radius_f }, + { +radius_f, -radius_f }, + { +radius_f, +radius_f } + }; + + for (int i = 0; i < 4; ++i) + { + auto& command = compiled_resources_temp.draw_commands[i + 3]; + command.config.primitives = rsx::overlays::primitive_type::triangle_fan; + command.verts = generate_unit_quadrant(num_control_points, corners[i], scale[i]); + } + + compiled_resources.add(std::move(compiled_resources_temp), margin_left, margin_top); + + m_is_compiled = true; return compiled_resources; } } diff --git a/rpcs3/Emu/RSX/Overlays/overlay_controls.h b/rpcs3/Emu/RSX/Overlays/overlay_controls.h index 350a1c5901..7b95ce4950 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_controls.h +++ b/rpcs3/Emu/RSX/Overlays/overlay_controls.h @@ -219,6 +219,8 @@ namespace rsx virtual compiled_resource& get_compiled(); void measure_text(u16& width, u16& height, bool ignore_word_wrap = false) const; virtual void set_selected(bool selected) { static_cast(selected); } + virtual void set_visible(bool visible) { this->visible = visible; m_is_compiled = false; } + virtual bool is_visible() const { return visible; } protected: bool m_is_compiled = false; // Only use m_is_compiled as a getter in is_compiled() if possible @@ -233,6 +235,7 @@ namespace rsx bool auto_resize = true; virtual overlay_element* add_element(std::unique_ptr&, int = -1) = 0; + void clear_items(); layout_container(); @@ -320,7 +323,7 @@ namespace rsx struct label : public overlay_element { label() = default; - label(const std::string& text); + label(std::string_view text); bool auto_resize(bool grow_only = false, u16 limit_w = -1, u16 limit_h = -1); }; diff --git a/rpcs3/Emu/RSX/Overlays/overlay_list_view.cpp b/rpcs3/Emu/RSX/Overlays/overlay_list_view.cpp index 1b6f4e8fc6..2ff654254c 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_list_view.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_list_view.cpp @@ -18,8 +18,8 @@ namespace rsx m_cancel_btn = std::make_unique(120, 20); m_highlight_box = std::make_unique(width, 0); - m_scroll_indicator_top->set_size(width, 40); - m_scroll_indicator_bottom->set_size(width, 40); + 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); @@ -37,7 +37,7 @@ namespace rsx m_cancel_btn->set_image_resource(resource_config::standard_image_resource::circle); } - m_scroll_indicator_bottom->set_pos(0, height - 40); + m_scroll_indicator_bottom->set_pos(0, height - 10); m_accept_btn->set_pos(30, height + 20); if (can_deny) @@ -199,6 +199,37 @@ namespace rsx return m_selected_entry; } + void list_view::hide_prompt_buttons(bool hidden) + { + m_accept_btn->set_visible(!hidden); + m_cancel_btn->set_visible(!hidden); + + if (m_deny_btn) + { + m_deny_btn->set_visible(!hidden); + } + + refresh(); + } + + void list_view::hide_scroll_indicators(bool hidden) + { + m_scroll_indicator_top->set_visible(!hidden); + m_scroll_indicator_bottom->set_visible(!hidden); + m_highlight_box->set_visible(!hidden); + + refresh(); + } + + void list_view::disable_selection_pulse(bool disabled) + { + m_highlight_box->pulse_effect_enabled = !disabled; + m_highlight_box->set_sinus_offset(1.5f); + m_highlight_box->refresh(); + + refresh(); + } + void list_view::set_cancel_only(bool cancel_only) { if (cancel_only) @@ -209,7 +240,7 @@ namespace rsx m_cancel_btn->set_pos(x + 180, y + h + 20); m_cancel_only = cancel_only; - m_is_compiled = false; + refresh(); } bool list_view::get_cancel_only() const @@ -233,27 +264,39 @@ namespace rsx compiled_resource& list_view::get_compiled() { - if (!is_compiled()) + if (is_compiled()) { - 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_cancel_only) - { - compiled.add(m_accept_btn->get_compiled()); - - if (m_deny_btn) - { - compiled.add(m_deny_btn->get_compiled()); - } - } - - compiled_resources = compiled; + return compiled_resources; } + compiled_resources.clear(); + + if (!is_visible()) + { + m_is_compiled = true; + return compiled_resources; + } + + 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_cancel_only) + { + m_is_compiled = true; + return compiled_resources; + } + + compiled.add(m_accept_btn->get_compiled()); + + if (m_deny_btn) + { + compiled.add(m_deny_btn->get_compiled()); + } + + m_is_compiled = true; return compiled_resources; } } // namespace overlays diff --git a/rpcs3/Emu/RSX/Overlays/overlay_list_view.hpp b/rpcs3/Emu/RSX/Overlays/overlay_list_view.hpp index 8f191dd404..ffe2b2f9bf 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_list_view.hpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_list_view.hpp @@ -39,6 +39,10 @@ namespace rsx bool get_cancel_only() const; const overlay_element* get_selected_entry() const; + void hide_prompt_buttons(bool hidden = true); + void hide_scroll_indicators(bool hidden = true); + void disable_selection_pulse(bool disabled = true); + void set_cancel_only(bool cancel_only); void translate(s16 _x, s16 _y) override; diff --git a/rpcs3/Emu/RSX/Overlays/overlay_tabs.cpp b/rpcs3/Emu/RSX/Overlays/overlay_tabs.cpp new file mode 100644 index 0000000000..91ff87899e --- /dev/null +++ b/rpcs3/Emu/RSX/Overlays/overlay_tabs.cpp @@ -0,0 +1,142 @@ +#include "stdafx.h" +#include "overlay_tabs.h" + +namespace rsx::overlays +{ + tabbed_container::tabbed_container(u16 header_width) + : m_headers_width(header_width) + { + auto_resize = false; + } + + overlay_element* tabbed_container::add_element(std::unique_ptr& item, int offset) + { + return horizontal_layout::add_element(item, offset); + } + + void tabbed_container::add_tab(std::string_view title, std::shared_ptr& panel) + { + std::unique_ptr label_widget = std::make_unique