diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 011db3da9f..e3d3026771 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -750,19 +750,7 @@ bool GLGSRender::load_program() // Notify the user with HUD notification if (g_cfg.misc.show_shader_compilation_hint) { - if (m_overlay_manager) - { - if (auto dlg = m_overlay_manager->get()) - { - // Extend duration - dlg->touch(); - } - else - { - // Create dialog but do not show immediately - m_overlay_manager->create(); - } - } + rsx::overlays::show_shader_compile_notification(); } } else diff --git a/rpcs3/Emu/RSX/Overlays/overlay_animated_icon.cpp b/rpcs3/Emu/RSX/Overlays/overlay_animated_icon.cpp new file mode 100644 index 0000000000..bc735d7a1a --- /dev/null +++ b/rpcs3/Emu/RSX/Overlays/overlay_animated_icon.cpp @@ -0,0 +1,63 @@ +#include "stdafx.h" +#include "overlay_animated_icon.h" + +#include "Utilities/File.h" +#include "../Common/time.hpp" + +namespace rsx +{ + namespace overlays + { + animated_icon::animated_icon(const char* icon_name) + { + const std::string image_path = fmt::format("%s/Icons/ui/%s", fs::get_config_dir(), icon_name); + m_icon = std::make_unique(image_path.c_str()); + set_raw_image(m_icon.get()); + } + + void animated_icon::update_animation_frame(compiled_resource& result) + { + if (m_last_update_timestamp == 0) + { + m_last_update_timestamp = rsx::uclock(); + } + else + { + const auto now = rsx::uclock(); + m_current_frame_duration += (rsx::uclock() - m_last_update_timestamp); + m_last_update_timestamp = now; + } + + if (m_current_frame_duration > m_frame_duration) + { + m_current_frame = (m_current_frame + 1) % m_total_frames; + m_current_frame_duration = 0; + } + + // We only care about the uvs (zw) components + float x = f32(m_frame_width + m_spacing_x) * (m_current_frame % m_row_length) + m_start_x; + float y = f32(m_frame_height + m_spacing_y) * (m_current_frame / m_row_length) + m_start_y; + + auto& cmd = result.draw_commands[0]; + cmd.verts[0].z() = x / m_icon->w; + cmd.verts[0].w() = (y / m_icon->h); + cmd.verts[1].z() = (x + m_frame_width) / m_icon->w; + cmd.verts[1].w() = (y / m_icon->h); + cmd.verts[2].z() = x / m_icon->w; + cmd.verts[2].w() = ((y + m_frame_height) / m_icon->h); + cmd.verts[3].z() = (x + m_frame_width) / m_icon->w; + cmd.verts[3].w() = ((y + m_frame_height) / m_icon->h); + } + + compiled_resource& animated_icon::get_compiled() + { + if (!is_compiled) + { + compiled_resources = image_view::get_compiled(); + } + + update_animation_frame(compiled_resources); + return compiled_resources; + } + } +} diff --git a/rpcs3/Emu/RSX/Overlays/overlay_animated_icon.h b/rpcs3/Emu/RSX/Overlays/overlay_animated_icon.h new file mode 100644 index 0000000000..68a8aecb5a --- /dev/null +++ b/rpcs3/Emu/RSX/Overlays/overlay_animated_icon.h @@ -0,0 +1,38 @@ +#pragma once + +#include "overlays.h" + +namespace rsx +{ + namespace overlays + { + class animated_icon : public image_view + { + std::unique_ptr m_icon; + + protected: + // Some layout and frame data + u16 m_start_x = 0; // X and Y offset of frame 0 + u16 m_start_y = 0; + u16 m_frame_width = 32; // W and H of each animation frame + u16 m_frame_height = 32; + u16 m_spacing_x = 8; // Spacing between frames in X and Y + u16 m_spacing_y = 8; + u16 m_row_length = 12; // Number of animation frames in the X direction in case of a 2D grid of frames + u16 m_total_frames = 12; // Total number of available frames + u64 m_frame_duration = 100'000; // Hold duration for each frame + + // Animation playback variables + int m_current_frame = 0; + u64 m_current_frame_duration = 0; + u64 m_last_update_timestamp = 0; + + public: + animated_icon(const char* icon_name); + + void update_animation_frame(compiled_resource& result); + compiled_resource& get_compiled() override; + }; + } +} + diff --git a/rpcs3/Emu/RSX/Overlays/overlay_loading_icon.hpp b/rpcs3/Emu/RSX/Overlays/overlay_loading_icon.hpp new file mode 100644 index 0000000000..f012346a0d --- /dev/null +++ b/rpcs3/Emu/RSX/Overlays/overlay_loading_icon.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "overlay_animated_icon.h" + +namespace rsx +{ + namespace overlays + { + struct loading_icon24 : public animated_icon + { + loading_icon24() + : animated_icon("spinner-24.png") + { + m_frame_width = m_frame_height = 24; + m_spacing_x = m_spacing_y = 6; + + set_size(24, 30); + set_padding(4, 0, 2, 8); + } + }; + } +} + diff --git a/rpcs3/Emu/RSX/Overlays/overlay_shader_compile_notification.cpp b/rpcs3/Emu/RSX/Overlays/overlay_shader_compile_notification.cpp deleted file mode 100644 index 4d532437b3..0000000000 --- a/rpcs3/Emu/RSX/Overlays/overlay_shader_compile_notification.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "stdafx.h" -#include "overlay_shader_compile_notification.h" -#include "Emu/system_config.h" - -namespace rsx -{ - namespace overlays - { - shader_compile_notification::shader_compile_notification() - { - const u16 pos_x = g_cfg.video.shader_compilation_hint.pos_x; - const u16 pos_y = g_cfg.video.shader_compilation_hint.pos_y; - - m_text.set_font("Arial", 16); - m_text.set_text(localized_string_id::RSX_OVERLAYS_COMPILING_SHADERS); - m_text.auto_resize(); - m_text.set_pos(pos_x, pos_y); - - m_text.back_color.a = 0.f; - - for (int n = 0; n < 3; ++n) - { - dots[n].set_size(2, 2); - dots[n].back_color = color4f(1.f, 1.f, 1.f, 1.f); - dots[n].set_pos(m_text.w + pos_x + 5 + (6 * n), pos_y + 20); - } - - creation_time = get_system_time(); - expire_time = creation_time + 1000000; - - // Disable forced refresh unless fps dips below 4 - min_refresh_duration_us = 250000; - visible = true; - } - - void shader_compile_notification::update_animation(u64 t) - { - // Update rate is twice per second - auto elapsed = t - creation_time; - elapsed /= 500000; - - auto old_dot = current_dot; - current_dot = elapsed % 3; - - if (old_dot != current_dot) - { - if (old_dot != 255) - { - dots[old_dot].set_size(2, 2); - dots[old_dot].translate(0, 1); - } - - dots[current_dot].translate(0, -1); - dots[current_dot].set_size(3, 3); - } - } - - // Extends visible time by half a second. Also updates the screen - void shader_compile_notification::touch() - { - if (urgency_ctr == 0 || urgency_ctr > 8) - { - refresh(); - urgency_ctr = 0; - } - - expire_time = get_system_time() + 500000; - urgency_ctr++; - } - - void shader_compile_notification::update() - { - auto current_time = get_system_time(); - if (current_time > expire_time) - close(false, false); - - update_animation(current_time); - - // Usually this method is called during a draw-to-screen operation. Reset urgency ctr - urgency_ctr = 1; - } - - compiled_resource shader_compile_notification::get_compiled() - { - if (!visible) - { - return {}; - } - - auto compiled = m_text.get_compiled(); - compiled.add(dots[0].get_compiled()); - compiled.add(dots[1].get_compiled()); - compiled.add(dots[2].get_compiled()); - - return compiled; - } - } // namespace overlays -} // namespace rsx diff --git a/rpcs3/Emu/RSX/Overlays/overlay_shader_compile_notification.h b/rpcs3/Emu/RSX/Overlays/overlay_shader_compile_notification.h index fec0cfb2c7..a0b76f5e55 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_shader_compile_notification.h +++ b/rpcs3/Emu/RSX/Overlays/overlay_shader_compile_notification.h @@ -1,29 +1,21 @@ #pragma once #include "overlays.h" +#include "overlay_message.h" +#include "overlay_loading_icon.hpp" namespace rsx { namespace overlays { - struct shader_compile_notification : user_interface + static inline void show_shader_compile_notification() { - label m_text; - - overlay_element dots[3]; - u8 current_dot = 255; - - u64 creation_time = 0; - u64 expire_time = 0; // Time to end the prompt - u64 urgency_ctr = 0; // How critical it is to show to the user - - shader_compile_notification(); - - void update_animation(u64 t); - void touch(); - void update() override; - - compiled_resource get_compiled() override; - }; + queue_message( + localized_string_id::RSX_OVERLAYS_COMPILING_SHADERS, + 15'000'000, + {}, + message_pin_location::bottom, + std::make_unique()); + } } } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 10a8aea128..86ede14cad 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -2008,16 +2008,7 @@ bool VKGSRender::load_program() { if (m_overlay_manager) { - if (auto dlg = m_overlay_manager->get()) - { - // Extend duration - dlg->touch(); - } - else - { - // Create dialog but do not show immediately - m_overlay_manager->create(); - } + rsx::overlays::show_shader_compile_notification(); } } } diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index af049c9aab..239a29c477 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -84,6 +84,7 @@ + @@ -400,7 +401,6 @@ - @@ -534,10 +534,12 @@ + + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 8044936cf2..24dc515e65 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -843,9 +843,6 @@ Emu\GPU\RSX\Overlays - - Emu\GPU\RSX\Overlays - Emu\GPU\RSX\Overlays @@ -1114,6 +1111,9 @@ Emu\GPU\RSX\Overlays + + Emu\GPU\RSX\Overlays + @@ -2242,6 +2242,12 @@ Emu\GPU\RSX\Overlays + + Emu\GPU\RSX\Overlays + + + Emu\GPU\RSX\Overlays +