use the dynamic notifications timing

This commit is contained in:
otavepto 2024-06-20 05:57:30 +03:00
parent fcb40ac86d
commit d30a5bf081
2 changed files with 63 additions and 19 deletions

View File

@ -54,7 +54,7 @@ struct Friend_Less
enum class notification_type
{
message = 0,
message,
invite,
achievement,
achievement_progress,
@ -86,10 +86,11 @@ struct Overlay_Achievement
struct Notification
{
static constexpr float width_percent = 0.25f; // percentage from total width
static constexpr std::chrono::milliseconds show_time = std::chrono::milliseconds(6000);
static constexpr std::chrono::milliseconds default_show_time = std::chrono::milliseconds(6000);
int id{};
uint8 type{};
bool expired = false;
std::chrono::milliseconds start_time{};
std::string message{};
std::pair<const Friend, friend_window_state>* frd{};
@ -214,10 +215,11 @@ class Steam_Overlay
void build_friend_context_menu(Friend const& frd, friend_window_state &state);
// Double click on friend
void build_friend_window(Friend const& frd, friend_window_state &state);
std::chrono::milliseconds get_notification_duration(notification_type type);
// Notifications like achievements, chat and invitations
void set_next_notification_pos(std::pair<float, float> scrn_size, std::chrono::milliseconds elapsed, const Notification &noti, struct NotificationsCoords &coords);
void set_next_notification_pos(std::pair<float, float> scrn_size, std::chrono::milliseconds elapsed, std::chrono::milliseconds duration, const Notification &noti, struct NotificationsCoords &coords);
// factor controlling the amount of sliding during the animation, 0 means disabled
float animate_factor(std::chrono::milliseconds elapsed);
float animate_factor(std::chrono::milliseconds elapsed, std::chrono::milliseconds duration);
void add_ach_progressbar(const Overlay_Achievement &ach);
ImVec4 get_notification_bg_rgba_safe();
void build_notifications(float width, float height);

View File

@ -869,8 +869,33 @@ void Steam_Overlay::build_friend_window(Friend const& frd, friend_window_state&
ImGui::End();
}
std::chrono::milliseconds Steam_Overlay::get_notification_duration(notification_type type)
{
switch (type)
{
case notification_type::message:
return std::chrono::milliseconds(settings->overlay_appearance.notification_duration_chat);
case notification_type::invite:
return std::chrono::milliseconds(settings->overlay_appearance.notification_duration_invitation);
case notification_type::achievement:
return std::chrono::milliseconds(settings->overlay_appearance.notification_duration_achievement);
case notification_type::achievement_progress:
return std::chrono::milliseconds(settings->overlay_appearance.notification_duration_progress);
case notification_type::auto_accept_invite:
return Notification::default_show_time;
}
PRINT_DEBUG("ERROR unhandled type %i", (int)type);
return Notification::default_show_time;
}
// set the position of the next notification
void Steam_Overlay::set_next_notification_pos(std::pair<float, float> scrn_size, std::chrono::milliseconds elapsed, const Notification &noti, struct NotificationsCoords &coords)
void Steam_Overlay::set_next_notification_pos(std::pair<float, float> scrn_size, std::chrono::milliseconds elapsed, std::chrono::milliseconds duration, const Notification &noti, struct NotificationsCoords &coords)
{
const float scrn_width = scrn_size.first;
const float scrn_height = scrn_size.second;
@ -932,19 +957,19 @@ void Steam_Overlay::set_next_notification_pos(std::pair<float, float> scrn_size,
switch (pos) {
// top
case Overlay_Appearance::NotificationPosition::top_left:
animate_size = animate_factor(elapsed) * noti_width;
animate_size = animate_factor(elapsed, duration) * noti_width;
x = margin_x - animate_size;
y = coords.top_left.second + margin_y;
coords.top_left.second = y + noti_height;
break;
case Overlay_Appearance::NotificationPosition::top_center:
animate_size = animate_factor(elapsed) * noti_height;
animate_size = animate_factor(elapsed, duration) * noti_height;
x = (scrn_width / 2) - (noti_width / 2);
y = coords.top_center.second + margin_y - animate_size;
coords.top_center.second = y + noti_height;
break;
case Overlay_Appearance::NotificationPosition::top_right:
animate_size = animate_factor(elapsed) * noti_width;
animate_size = animate_factor(elapsed, duration) * noti_width;
x = (scrn_width - noti_width - margin_x) + animate_size;
y = coords.top_right.second + margin_y;
coords.top_right.second = y + noti_height;
@ -952,19 +977,19 @@ void Steam_Overlay::set_next_notification_pos(std::pair<float, float> scrn_size,
// bot
case Overlay_Appearance::NotificationPosition::bot_left:
animate_size = animate_factor(elapsed) * noti_width;
animate_size = animate_factor(elapsed, duration) * noti_width;
x = margin_x - animate_size;
y = scrn_height - coords.bot_left.second - margin_y - noti_height;
coords.bot_left.second = scrn_height - y;
break;
case Overlay_Appearance::NotificationPosition::bot_center:
animate_size = animate_factor(elapsed) * noti_height;
animate_size = animate_factor(elapsed, duration) * noti_height;
x = (scrn_width / 2) - (noti_width / 2);
y = scrn_height - coords.bot_center.second - margin_y - noti_height + animate_size;
coords.bot_center.second = scrn_height - y;
break;
case Overlay_Appearance::NotificationPosition::bot_right:
animate_size = animate_factor(elapsed) * noti_width;
animate_size = animate_factor(elapsed, duration) * noti_width;
x = (scrn_width - noti_width - margin_x) + animate_size;
y = scrn_height - coords.bot_right.second - margin_y - noti_height;
coords.bot_right.second = scrn_height - y;
@ -977,12 +1002,12 @@ void Steam_Overlay::set_next_notification_pos(std::pair<float, float> scrn_size,
ImGui::SetNextWindowSize(ImVec2(noti_width, noti_height));
}
float Steam_Overlay::animate_factor(std::chrono::milliseconds elapsed)
float Steam_Overlay::animate_factor(std::chrono::milliseconds elapsed, std::chrono::milliseconds duration)
{
if (settings->overlay_appearance.notification_animation <= 0) return 0.0f; // no animation
std::chrono::milliseconds animation_duration(settings->overlay_appearance.notification_animation);
// PRINT_DEBUG("ELAPSED %u/%u", (uint32)elapsed.count(), (uint32)animation_duration.count());
// PRINT_DEBUG("ELAPSED %u/%u/%u", (uint32)elapsed.count(), (uint32)duration.count(), (uint32)animation_duration.count());
float factor = 0.0f;
if (elapsed < animation_duration) { // sliding in
@ -990,9 +1015,14 @@ float Steam_Overlay::animate_factor(std::chrono::milliseconds elapsed)
// PRINT_DEBUG("SHOW FACTOR %f", factor);
} else {
// time between sliding in/out animation
auto steady_time = Notification::show_time - animation_duration;
// here we add the animation duration because we want to count after the animation
// if we have 1 sec animation & 2 sec show time:
// the duration will start at < 1 sec during the initial animation
// after the animation (1 sec), the duration will be >= 1 sec
// but since we want 2 sec show time, the duration must last 3 sec
auto steady_time = animation_duration + duration;
if (elapsed > steady_time) {
factor = 1.0f - static_cast<float>((Notification::show_time - elapsed).count()) / animation_duration.count();
factor = static_cast<float>((elapsed - steady_time).count()) / animation_duration.count();
// PRINT_DEBUG("HIDE FACTOR %f", factor);
}
}
@ -1044,9 +1074,19 @@ void Steam_Overlay::build_notifications(float width, float height)
NotificationsCoords coords{};
for (auto it = notifications.begin(); it != notifications.end(); ++it) {
auto elapsed_notif = now - it->start_time;
auto noti_duration = get_notification_duration((notification_type)it->type);
if (noti_duration.count() <= 0) {
it->expired = true;
continue;
}
set_next_notification_pos({width, height}, elapsed_notif, *it, coords);
// *2 for sliding in & out animation
auto total_allowed_duration = noti_duration + std::chrono::milliseconds(settings->overlay_appearance.notification_animation * 2);
auto elapsed_notif = now - it->start_time;
if (elapsed_notif > total_allowed_duration) {
it->expired = true;
continue;
}
float settings_noti_alpha = settings->overlay_appearance.notification_a >= 0.0f && settings->overlay_appearance.notification_a <= 1.0f
? settings->overlay_appearance.notification_a
@ -1078,6 +1118,8 @@ void Steam_Overlay::build_notifications(float width, float height)
}
std::string wnd_name = "NotiPopupShow" + std::to_string(it->id);
set_next_notification_pos({width, height}, elapsed_notif, noti_duration, *it, coords);
if (ImGui::Begin(wnd_name.c_str(), nullptr,
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize | extra_flags)) {
switch ((notification_type)it->type) {
@ -1142,8 +1184,8 @@ void Steam_Overlay::build_notifications(float width, float height)
ImGui::PopFont();
// erase all notifications whose visible time exceeded the max
notifications.erase(std::remove_if(notifications.begin(), notifications.end(), [this, &now](Notification &item) {
if ((now - item.start_time) > Notification::show_time) {
notifications.erase(std::remove_if(notifications.begin(), notifications.end(), [this](const Notification &item) {
if (item.expired) {
PRINT_DEBUG("removing a notification");
allow_renderer_frame_processing(false);
// uncomment this block to restore app input focus