ImGui:: Add position and icon arguments for notifications (#4383)

* add position arg

* add icon args

* fixup

* fix the fixup
This commit is contained in:
rainmakerv2 2026-05-10 01:29:31 +08:00 committed by GitHub
parent ac61f4aee2
commit c79abb6df4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 102 additions and 30 deletions

View File

@ -15,17 +15,16 @@ std::optional<NotificationsUI> current_notif;
std::queue<NotificationInfo> notif_queue;
std::mutex queueMtx;
const std::map<shadNotifications::stockIcons, std::string> 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<u8> imgdata = std::vector<u8>(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<std::mutex> 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<u8> imgdata = std::vector<u8>(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<u8> pngData,
bool addBackground) {
std::lock_guard<std::mutex> 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);

View File

@ -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<u8> pngData,
bool iconBackground = false);
}; // namespace shadNotifications

View File

@ -453,7 +453,15 @@ 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);
std::ifstream file(primary_path, std::ios::binary);
std::vector<u8> imgdata;
if (file) {
imgdata = std::vector<u8>(std::istreambuf_iterator<char>(file),
std::istreambuf_iterator<char>());
}
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<ScreenshotReadback>& 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<u8> imgdata;
if (file) {
imgdata = std::vector<u8>(std::istreambuf_iterator<char>(file),
std::istreambuf_iterator<char>());
}
shadNotifications::QueueNotification("Saved screenshot:\n" + path.string(), 3.0f,
shadNotifications::position::BottomRight, imgdata);
}
}
}