From c79abb6df407136020a37b6eaab14868fdc511ec Mon Sep 17 00:00:00 2001 From: rainmakerv2 <30595646+rainmakerv3@users.noreply.github.com> Date: Sun, 10 May 2026 01:29:31 +0800 Subject: [PATCH] ImGui:: Add position and icon arguments for notifications (#4383) * add position arg * add icon args * fixup * fix the fixup --- src/imgui/notifications_layer.cpp | 88 +++++++++++++------ src/imgui/notifications_layer.h | 25 +++++- .../renderer_vulkan/vk_presenter.cpp | 19 +++- 3 files changed, 102 insertions(+), 30 deletions(-) diff --git a/src/imgui/notifications_layer.cpp b/src/imgui/notifications_layer.cpp index 76ce2fe34..f136313f0 100644 --- a/src/imgui/notifications_layer.cpp +++ b/src/imgui/notifications_layer.cpp @@ -15,17 +15,16 @@ std::optional current_notif; std::queue notif_queue; std::mutex queueMtx; +const std::map iconMap = { + {shadNotifications::stockIcons::shadPS4, "src/images/shadps4.png"}, + {shadNotifications::stockIcons::Settings, "src/images/big_picture/settings.png"}, + {shadNotifications::stockIcons::Profiles, "src/images/big_picture/profiles.png"}, + {shadNotifications::stockIcons::Input, "src/images/big_picture/controller.png"}, +}; + NotificationsUI::NotificationsUI(NotificationInfo info) { AddLayer(this); - - if (shadIcon.GetTexture().im_id == nullptr) { - auto resource = cmrc::res::get_filesystem(); - auto file = resource.open("src/images/shadps4.png"); - std::vector imgdata = std::vector(file.begin(), file.end()); - shadIcon = ImGui::RefCountedTexture::DecodePngTexture(imgdata); - } - - currentNotification = info; + currentInfo = info; // Resetting the animation elapsed_time = 0.0f; // Resetting animation time @@ -38,32 +37,47 @@ NotificationsUI::~NotificationsUI() { void NotificationsUI::Draw() { auto& io = ImGui::GetIO(); - currentNotification.timer -= io.DeltaTime; + currentInfo.timer -= io.DeltaTime; float AdjustWidth = io.DisplaySize.x / 1920; float AdjustHeight = io.DisplaySize.y / 1080; - ImVec2 padding = ImGui::GetStyle().WindowPadding; + float wrapWidth = 300 * AdjustWidth - padding.x * 2; // 350 window size - 50 image size float textHeight = - ImGui::CalcTextSize(currentNotification.message.c_str(), nullptr, false, wrapWidth).y; - + ImGui::CalcTextSize(currentInfo.message.c_str(), nullptr, false, wrapWidth).y; ImVec2 window_size{(350 * AdjustWidth), std::max({70 * AdjustHeight, (textHeight + padding.y * 2.0f)})}; elapsed_time += io.DeltaTime; float progress = std::min(elapsed_time / animation_duration, 1.0f); float final_pos_x, start_x; + float height; - start_x = io.DisplaySize.x; - final_pos_x = io.DisplaySize.x - window_size.x - 20 * AdjustWidth; - ImVec2 current_pos = ImVec2(start_x + (final_pos_x - start_x) * progress, - io.DisplaySize.y - window_size.y - 50 * AdjustHeight); + if (currentInfo.pos == position::TopLeft) { + start_x = -window_size.x; + final_pos_x = 20 * AdjustWidth; + height = 20 * AdjustHeight; + } else if (currentInfo.pos == position::TopRight) { + start_x = io.DisplaySize.x; + final_pos_x = io.DisplaySize.x - window_size.x - 20 * AdjustWidth; + height = 20 * AdjustHeight; + } else if (currentInfo.pos == position::BottomLeft) { + start_x = -window_size.x; + final_pos_x = 20 * AdjustWidth; + height = io.DisplaySize.y - window_size.y - 20 * AdjustHeight; + } else if (currentInfo.pos == position::BottomRight) { + start_x = io.DisplaySize.x; + final_pos_x = io.DisplaySize.x - window_size.x - 20 * AdjustWidth; + height = io.DisplaySize.y - window_size.y - 20 * AdjustHeight; + } + + ImVec2 current_pos = ImVec2(start_x + (final_pos_x - start_x) * progress, height); ImGui::SetNextWindowPos(current_pos); // If the remaining time of the notif is less than or equal to 1 second, the fade-out begins. - if (currentNotification.timer <= 1.0f) { - float fade_out_time = 1.0f - (currentNotification.timer / 1.0f); + if (currentInfo.timer <= 1.0f) { + float fade_out_time = 1.0f - (currentInfo.timer / 1.0f); fade_opacity = 1.0f - fade_out_time; } else { // Fade in , 0 to 1 @@ -83,19 +97,24 @@ void NotificationsUI::Draw() { ImGuiWindowFlags_NoInputs)) { ImGui::GetColorU32(ImVec4{0.7f}); - if (shadIcon.GetTexture().im_id) { - ImGui::Image(shadIcon.GetTexture().im_id, + if (currentInfo.icon.GetTexture().im_id) { + if (currentInfo.addIconBackground) { + ImVec2 pos = ImGui::GetCursorScreenPos(); + ImGui::GetWindowDrawList()->AddRectFilled( + pos, ImVec2(pos.x + 50 * AdjustWidth, pos.y + 50 * AdjustHeight), + IM_COL32(211, 211, 211, 255)); + } + ImGui::Image(currentInfo.icon.GetTexture().im_id, ImVec2((50 * AdjustWidth), (50 * AdjustHeight))); } ImGui::SameLine(); - - ImGui::TextWrapped("%s", currentNotification.message.c_str()); + ImGui::TextWrapped("%s", currentInfo.message.c_str()); } ImGui::PopStyleVar(); ImGui::End(); - if (currentNotification.timer <= 0) { + if (currentInfo.timer <= 0) { std::lock_guard lock(queueMtx); if (!notif_queue.empty()) { NotificationInfo next = notif_queue.front(); @@ -107,12 +126,31 @@ void NotificationsUI::Draw() { } } -void QueueNotification(std::string message, float timer) { +void QueueNotification(std::string message, float timer, position pos, stockIcons icon) { + auto resource = cmrc::res::get_filesystem(); + auto file = resource.open(iconMap.at(icon)); + std::vector imgdata = std::vector(file.begin(), file.end()); + + bool addBackground = false; + if (icon == shadNotifications::stockIcons::Input || + icon == shadNotifications::stockIcons::Settings || + icon == shadNotifications::stockIcons::Profiles) { + addBackground = true; + } + + QueueNotification(message, timer, pos, imgdata, addBackground); +} + +void QueueNotification(std::string message, float timer, position pos, std::vector pngData, + bool addBackground) { std::lock_guard lock(queueMtx); NotificationInfo info; info.message = message; info.timer = timer; + info.pos = pos; + info.icon = ImGui::RefCountedTexture::DecodePngTexture(pngData); + info.addIconBackground = addBackground; if (!current_notif.has_value()) { current_notif.emplace(info); diff --git a/src/imgui/notifications_layer.h b/src/imgui/notifications_layer.h index 6affb9a8d..9eccac5cf 100644 --- a/src/imgui/notifications_layer.h +++ b/src/imgui/notifications_layer.h @@ -8,9 +8,26 @@ namespace shadNotifications { +enum class position { + TopLeft, + TopRight, + BottomLeft, + BottomRight, +}; + +enum class stockIcons { + shadPS4, + Settings, + Profiles, + Input, +}; + struct NotificationInfo { std::string message; float timer; + position pos; + ImGui::RefCountedTexture icon; + bool addIconBackground; // adds gray background (mostly for black icons) }; class NotificationsUI final : public ImGui::Layer { @@ -21,8 +38,7 @@ public: void Draw() override; private: - ImGui::RefCountedTexture shadIcon; - NotificationInfo currentNotification; + NotificationInfo currentInfo; // notification animation const float animation_duration = 0.5f; // Animation duration @@ -31,6 +47,9 @@ private: float elapsed_time = 0.0f; // Animation time }; -void QueueNotification(std::string message, float timer); +void QueueNotification(std::string message, float timer, position pos, + stockIcons = shadNotifications::stockIcons::shadPS4); +void QueueNotification(std::string message, float timer, position pos, std::vector pngData, + bool iconBackground = false); }; // namespace shadNotifications diff --git a/src/video_core/renderer_vulkan/vk_presenter.cpp b/src/video_core/renderer_vulkan/vk_presenter.cpp index d04a70cea..69bb441bc 100644 --- a/src/video_core/renderer_vulkan/vk_presenter.cpp +++ b/src/video_core/renderer_vulkan/vk_presenter.cpp @@ -453,7 +453,15 @@ static void SavePendingScreenshots(const std::vector& readba } LOG_INFO(Render_Vulkan, "Saved screenshot: {}", primary_path.string()); - shadNotifications::QueueNotification("Saved screenshot:\n" + primary_path.string(), 3.0f); + + std::ifstream file(primary_path, std::ios::binary); + std::vector imgdata; + if (file) { + imgdata = std::vector(std::istreambuf_iterator(file), + std::istreambuf_iterator()); + } + shadNotifications::QueueNotification("Saved screenshot:\n" + primary_path.string(), 3.0f, + shadNotifications::position::BottomRight, imgdata); for (size_t i = 1; i < readback.paths.size(); ++i) { const auto& path = readback.paths[i]; @@ -469,7 +477,14 @@ static void SavePendingScreenshots(const std::vector& readba } LOG_INFO(Render_Vulkan, "Saved screenshot: {}", path.string()); - shadNotifications::QueueNotification("Saved screenshot:\n" + path.string(), 3.0f); + std::ifstream file(path, std::ios::binary); + std::vector imgdata; + if (file) { + imgdata = std::vector(std::istreambuf_iterator(file), + std::istreambuf_iterator()); + } + shadNotifications::QueueNotification("Saved screenshot:\n" + path.string(), 3.0f, + shadNotifications::position::BottomRight, imgdata); } } }