mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-05-12 16:09:42 -06:00
parent
8bcc19248e
commit
82c760135f
@ -1092,6 +1092,8 @@ set(IMGUI src/imgui/imgui_config.h
|
||||
src/imgui/imgui_texture.h
|
||||
src/imgui/imgui_translations.cpp
|
||||
src/imgui/imgui_translations.h
|
||||
src/imgui/notifications_layer.cpp
|
||||
src/imgui/notifications_layer.h
|
||||
src/imgui/renderer/imgui_core.cpp
|
||||
src/imgui/renderer/imgui_core.h
|
||||
src/imgui/renderer/imgui_impl_sdl3.cpp
|
||||
@ -1275,6 +1277,7 @@ include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/CMakeRC.cmake")
|
||||
cmrc_add_resource_library(embedded-resources
|
||||
ALIAS res::embedded
|
||||
NAMESPACE res
|
||||
src/images/shadps4.png
|
||||
src/images/big_picture/folder.png
|
||||
src/images/big_picture/settings.png
|
||||
src/images/big_picture/experimental.png
|
||||
|
||||
124
src/imgui/notifications_layer.cpp
Normal file
124
src/imgui/notifications_layer.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025-2026 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <cmrc/cmrc.hpp>
|
||||
#include <imgui.h>
|
||||
#include <queue>
|
||||
|
||||
#include "imgui/imgui_std.h"
|
||||
#include "notifications_layer.h"
|
||||
|
||||
CMRC_DECLARE(res);
|
||||
namespace shadNotifications {
|
||||
|
||||
std::optional<NotificationsUI> current_notif;
|
||||
std::queue<NotificationInfo> notif_queue;
|
||||
std::mutex queueMtx;
|
||||
|
||||
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<u8> imgdata = std::vector<u8>(file.begin(), file.end());
|
||||
shadIcon = ImGui::RefCountedTexture::DecodePngTexture(imgdata);
|
||||
}
|
||||
|
||||
currentNotification = info;
|
||||
|
||||
// Resetting the animation
|
||||
elapsed_time = 0.0f; // Resetting animation time
|
||||
fade_opacity = 0.0f; // Starts invisible
|
||||
}
|
||||
|
||||
NotificationsUI::~NotificationsUI() {
|
||||
RemoveLayer(this);
|
||||
}
|
||||
|
||||
void NotificationsUI::Draw() {
|
||||
auto& io = ImGui::GetIO();
|
||||
currentNotification.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;
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
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);
|
||||
fade_opacity = 1.0f - fade_out_time;
|
||||
} else {
|
||||
// Fade in , 0 to 1
|
||||
fade_opacity = 1.0f;
|
||||
}
|
||||
|
||||
fade_opacity = std::max(0.0f, std::min(fade_opacity, 1.0f));
|
||||
|
||||
ImGui::SetNextWindowSize(window_size);
|
||||
ImGui::SetNextWindowPos(current_pos);
|
||||
ImGui::SetNextWindowCollapsed(false);
|
||||
ImGui::KeepNavHighlight();
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, fade_opacity);
|
||||
|
||||
if (ImGui::Begin("Notification Window", nullptr,
|
||||
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings |
|
||||
ImGuiWindowFlags_NoInputs)) {
|
||||
ImGui::GetColorU32(ImVec4{0.7f});
|
||||
|
||||
if (shadIcon.GetTexture().im_id) {
|
||||
ImGui::Image(shadIcon.GetTexture().im_id,
|
||||
ImVec2((50 * AdjustWidth), (50 * AdjustHeight)));
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::TextWrapped("%s", currentNotification.message.c_str());
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::End();
|
||||
|
||||
if (currentNotification.timer <= 0) {
|
||||
std::lock_guard<std::mutex> lock(queueMtx);
|
||||
if (!notif_queue.empty()) {
|
||||
NotificationInfo next = notif_queue.front();
|
||||
notif_queue.pop();
|
||||
current_notif.emplace(next);
|
||||
} else {
|
||||
current_notif.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QueueNotification(std::string message, float timer) {
|
||||
std::lock_guard<std::mutex> lock(queueMtx);
|
||||
|
||||
NotificationInfo info;
|
||||
info.message = message;
|
||||
info.timer = timer;
|
||||
|
||||
if (!current_notif.has_value()) {
|
||||
current_notif.emplace(info);
|
||||
} else {
|
||||
notif_queue.push(info);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace shadNotifications
|
||||
36
src/imgui/notifications_layer.h
Normal file
36
src/imgui/notifications_layer.h
Normal file
@ -0,0 +1,36 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "imgui/imgui_layer.h"
|
||||
#include "imgui/imgui_texture.h"
|
||||
|
||||
namespace shadNotifications {
|
||||
|
||||
struct NotificationInfo {
|
||||
std::string message;
|
||||
float timer;
|
||||
};
|
||||
|
||||
class NotificationsUI final : public ImGui::Layer {
|
||||
public:
|
||||
NotificationsUI(NotificationInfo info);
|
||||
~NotificationsUI() override;
|
||||
|
||||
void Draw() override;
|
||||
|
||||
private:
|
||||
ImGui::RefCountedTexture shadIcon;
|
||||
NotificationInfo currentNotification;
|
||||
|
||||
// notification animation
|
||||
const float animation_duration = 0.5f; // Animation duration
|
||||
const float fade_out_duration = 0.5f; // Final fade duration
|
||||
float fade_opacity = 0.0f; // Initial opacity (invisible)
|
||||
float elapsed_time = 0.0f; // Animation time
|
||||
};
|
||||
|
||||
void QueueNotification(std::string message, float timer);
|
||||
|
||||
}; // namespace shadNotifications
|
||||
@ -10,6 +10,7 @@
|
||||
#include "core/devtools/layer.h"
|
||||
#include "core/emulator_settings.h"
|
||||
#include "core/libraries/system/systemservice.h"
|
||||
#include "imgui/notifications_layer.h"
|
||||
#include "imgui/renderer/imgui_core.h"
|
||||
#include "imgui/renderer/imgui_impl_vulkan.h"
|
||||
#include "sdl_window.h"
|
||||
@ -452,6 +453,7 @@ static void SavePendingScreenshots(const std::vector<ScreenshotReadback>& readba
|
||||
}
|
||||
|
||||
LOG_INFO(Render_Vulkan, "Saved screenshot: {}", primary_path.string());
|
||||
shadNotifications::QueueNotification("Saved screenshot:\n" + primary_path.string(), 3.0f);
|
||||
|
||||
for (size_t i = 1; i < readback.paths.size(); ++i) {
|
||||
const auto& path = readback.paths[i];
|
||||
@ -467,6 +469,7 @@ static void SavePendingScreenshots(const std::vector<ScreenshotReadback>& readba
|
||||
}
|
||||
|
||||
LOG_INFO(Render_Vulkan, "Saved screenshot: {}", path.string());
|
||||
shadNotifications::QueueNotification("Saved screenshot:\n" + path.string(), 3.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user