mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-06-02 21:05:13 -06:00
ImGui:: Add position and icon arguments for notifications (#4383)
* add position arg * add icon args * fixup * fix the fixup
This commit is contained in:
parent
ac61f4aee2
commit
c79abb6df4
@ -15,17 +15,16 @@ std::optional<NotificationsUI> current_notif;
|
|||||||
std::queue<NotificationInfo> notif_queue;
|
std::queue<NotificationInfo> notif_queue;
|
||||||
std::mutex queueMtx;
|
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) {
|
NotificationsUI::NotificationsUI(NotificationInfo info) {
|
||||||
AddLayer(this);
|
AddLayer(this);
|
||||||
|
currentInfo = info;
|
||||||
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
|
// Resetting the animation
|
||||||
elapsed_time = 0.0f; // Resetting animation time
|
elapsed_time = 0.0f; // Resetting animation time
|
||||||
@ -38,32 +37,47 @@ NotificationsUI::~NotificationsUI() {
|
|||||||
|
|
||||||
void NotificationsUI::Draw() {
|
void NotificationsUI::Draw() {
|
||||||
auto& io = ImGui::GetIO();
|
auto& io = ImGui::GetIO();
|
||||||
currentNotification.timer -= io.DeltaTime;
|
currentInfo.timer -= io.DeltaTime;
|
||||||
|
|
||||||
float AdjustWidth = io.DisplaySize.x / 1920;
|
float AdjustWidth = io.DisplaySize.x / 1920;
|
||||||
float AdjustHeight = io.DisplaySize.y / 1080;
|
float AdjustHeight = io.DisplaySize.y / 1080;
|
||||||
|
|
||||||
ImVec2 padding = ImGui::GetStyle().WindowPadding;
|
ImVec2 padding = ImGui::GetStyle().WindowPadding;
|
||||||
|
|
||||||
float wrapWidth = 300 * AdjustWidth - padding.x * 2; // 350 window size - 50 image size
|
float wrapWidth = 300 * AdjustWidth - padding.x * 2; // 350 window size - 50 image size
|
||||||
float textHeight =
|
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),
|
ImVec2 window_size{(350 * AdjustWidth),
|
||||||
std::max({70 * AdjustHeight, (textHeight + padding.y * 2.0f)})};
|
std::max({70 * AdjustHeight, (textHeight + padding.y * 2.0f)})};
|
||||||
|
|
||||||
elapsed_time += io.DeltaTime;
|
elapsed_time += io.DeltaTime;
|
||||||
float progress = std::min(elapsed_time / animation_duration, 1.0f);
|
float progress = std::min(elapsed_time / animation_duration, 1.0f);
|
||||||
float final_pos_x, start_x;
|
float final_pos_x, start_x;
|
||||||
|
float height;
|
||||||
|
|
||||||
start_x = io.DisplaySize.x;
|
if (currentInfo.pos == position::TopLeft) {
|
||||||
final_pos_x = io.DisplaySize.x - window_size.x - 20 * AdjustWidth;
|
start_x = -window_size.x;
|
||||||
ImVec2 current_pos = ImVec2(start_x + (final_pos_x - start_x) * progress,
|
final_pos_x = 20 * AdjustWidth;
|
||||||
io.DisplaySize.y - window_size.y - 50 * AdjustHeight);
|
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);
|
ImGui::SetNextWindowPos(current_pos);
|
||||||
|
|
||||||
// If the remaining time of the notif is less than or equal to 1 second, the fade-out begins.
|
// If the remaining time of the notif is less than or equal to 1 second, the fade-out begins.
|
||||||
if (currentNotification.timer <= 1.0f) {
|
if (currentInfo.timer <= 1.0f) {
|
||||||
float fade_out_time = 1.0f - (currentNotification.timer / 1.0f);
|
float fade_out_time = 1.0f - (currentInfo.timer / 1.0f);
|
||||||
fade_opacity = 1.0f - fade_out_time;
|
fade_opacity = 1.0f - fade_out_time;
|
||||||
} else {
|
} else {
|
||||||
// Fade in , 0 to 1
|
// Fade in , 0 to 1
|
||||||
@ -83,19 +97,24 @@ void NotificationsUI::Draw() {
|
|||||||
ImGuiWindowFlags_NoInputs)) {
|
ImGuiWindowFlags_NoInputs)) {
|
||||||
ImGui::GetColorU32(ImVec4{0.7f});
|
ImGui::GetColorU32(ImVec4{0.7f});
|
||||||
|
|
||||||
if (shadIcon.GetTexture().im_id) {
|
if (currentInfo.icon.GetTexture().im_id) {
|
||||||
ImGui::Image(shadIcon.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)));
|
ImVec2((50 * AdjustWidth), (50 * AdjustHeight)));
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
ImGui::TextWrapped("%s", currentInfo.message.c_str());
|
||||||
ImGui::TextWrapped("%s", currentNotification.message.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
if (currentNotification.timer <= 0) {
|
if (currentInfo.timer <= 0) {
|
||||||
std::lock_guard<std::mutex> lock(queueMtx);
|
std::lock_guard<std::mutex> lock(queueMtx);
|
||||||
if (!notif_queue.empty()) {
|
if (!notif_queue.empty()) {
|
||||||
NotificationInfo next = notif_queue.front();
|
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);
|
std::lock_guard<std::mutex> lock(queueMtx);
|
||||||
|
|
||||||
NotificationInfo info;
|
NotificationInfo info;
|
||||||
info.message = message;
|
info.message = message;
|
||||||
info.timer = timer;
|
info.timer = timer;
|
||||||
|
info.pos = pos;
|
||||||
|
info.icon = ImGui::RefCountedTexture::DecodePngTexture(pngData);
|
||||||
|
info.addIconBackground = addBackground;
|
||||||
|
|
||||||
if (!current_notif.has_value()) {
|
if (!current_notif.has_value()) {
|
||||||
current_notif.emplace(info);
|
current_notif.emplace(info);
|
||||||
|
|||||||
@ -8,9 +8,26 @@
|
|||||||
|
|
||||||
namespace shadNotifications {
|
namespace shadNotifications {
|
||||||
|
|
||||||
|
enum class position {
|
||||||
|
TopLeft,
|
||||||
|
TopRight,
|
||||||
|
BottomLeft,
|
||||||
|
BottomRight,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class stockIcons {
|
||||||
|
shadPS4,
|
||||||
|
Settings,
|
||||||
|
Profiles,
|
||||||
|
Input,
|
||||||
|
};
|
||||||
|
|
||||||
struct NotificationInfo {
|
struct NotificationInfo {
|
||||||
std::string message;
|
std::string message;
|
||||||
float timer;
|
float timer;
|
||||||
|
position pos;
|
||||||
|
ImGui::RefCountedTexture icon;
|
||||||
|
bool addIconBackground; // adds gray background (mostly for black icons)
|
||||||
};
|
};
|
||||||
|
|
||||||
class NotificationsUI final : public ImGui::Layer {
|
class NotificationsUI final : public ImGui::Layer {
|
||||||
@ -21,8 +38,7 @@ public:
|
|||||||
void Draw() override;
|
void Draw() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ImGui::RefCountedTexture shadIcon;
|
NotificationInfo currentInfo;
|
||||||
NotificationInfo currentNotification;
|
|
||||||
|
|
||||||
// notification animation
|
// notification animation
|
||||||
const float animation_duration = 0.5f; // Animation duration
|
const float animation_duration = 0.5f; // Animation duration
|
||||||
@ -31,6 +47,9 @@ private:
|
|||||||
float elapsed_time = 0.0f; // Animation time
|
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
|
}; // namespace shadNotifications
|
||||||
|
|||||||
@ -453,7 +453,15 @@ static void SavePendingScreenshots(const std::vector<ScreenshotReadback>& readba
|
|||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO(Render_Vulkan, "Saved screenshot: {}", primary_path.string());
|
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) {
|
for (size_t i = 1; i < readback.paths.size(); ++i) {
|
||||||
const auto& path = readback.paths[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());
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user