diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index 3278a5a6e3..9b01cb2fc1 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -1369,7 +1369,21 @@ void NotificationManager::push_hint_notification(bool open_next) } NotificationData data{ NotificationType::DidYouKnowHint, NotificationLevel::RegularNotification, 300, "" }; - push_notification_data(std::make_unique(data, m_id_provider, m_evt_handler, open_next), 0); + // from user + if (!open_next) { + push_notification_data(std::make_unique(data, m_id_provider, m_evt_handler, open_next), 0); + // delete from delayed list + for (auto it = m_waiting_notifications.begin(); it != m_waiting_notifications.end();) { + if ((*it).notification->get_type() == NotificationType::DidYouKnowHint) { + it = m_waiting_notifications.erase(it); + } else { + ++it; + } + } + // at startup + } else { + push_delayed_notification(std::make_unique(data, m_id_provider, m_evt_handler, open_next), 500, 30000); + } } bool NotificationManager::is_hint_notification_open() @@ -1425,6 +1439,16 @@ bool NotificationManager::push_notification_data(std::unique_ptr notification, int64_t initial_delay, int64_t delay_interval) +{ + if (initial_delay == 0 && m_pop_notifications.empty()) { + push_notification_data(std::move(notification), 0); + } else { + m_waiting_notifications.emplace_back(std::move(notification), initial_delay, delay_interval); + wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(initial_delay); + } +} + void NotificationManager::render_notifications(GLCanvas3D& canvas, float overlay_width) { sort_notifications(); @@ -1477,6 +1501,25 @@ bool NotificationManager::update_notifications(GLCanvas3D& canvas) ++it; } + // delayed notifications + for (auto it = m_waiting_notifications.begin(); it != m_waiting_notifications.end();) { + // substract time + if ((*it).remaining_time > 0) + (*it).remaining_time -= time_since_render; + if ((*it).remaining_time <= 0) { + if (m_pop_notifications.empty()) { // push notification, erase it from waiting list (frame is scheduled by push) + (*it).notification->reset_timer(); + push_notification_data(std::move((*it).notification), 0); + it = m_waiting_notifications.erase(it); + continue; + } else { // not possible to push, delay for delay_interval + (*it).remaining_time = (*it).delay_interval; + } + } + next_render = std::min(next_render, (*it).remaining_time); + ++it; + } + // request next frame in future if (next_render < max) canvas.schedule_extra_frame(int(next_render)); diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 038290f823..d2a2eb5a78 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -262,6 +262,8 @@ private: EState get_state() const { return m_state; } bool is_hovered() const { return m_state == EState::Hovered; } void set_hovered() { if (m_state != EState::Finished && m_state != EState::ClosePending && m_state != EState::Hidden && m_state != EState::Unknown) m_state = EState::Hovered; } + // set start of notification to now. Used by delayed notifications + void reset_timer() { m_notification_start = GLCanvas3D::timestamp_now(); m_state = EState::Shown; } protected: // Call after every size change virtual void init(); @@ -515,10 +517,25 @@ private: // in HintNotification.hpp class HintNotification; + // Data of waiting notifications + struct DelayedNotification + { + std::unique_ptr notification; + int64_t remaining_time; + int64_t delay_interval; + DelayedNotification(std::unique_ptr n, int64_t r, int64_t d) + : notification(std::move(n)) + , remaining_time(r) + , delay_interval(d) + {} + }; + //pushes notification into the queue of notifications that are rendered //can be used to create custom notification bool push_notification_data(const NotificationData& notification_data, int timestamp); bool push_notification_data(std::unique_ptr notification, int timestamp); + // Delayed notifications goes first to the m_waiting_notifications vector and only after remaining time is <= 0 and m_pop_notifications are empty, notification is regular pushed. Otherwise another delay interval waiting. Timestamp is 0. + void push_delayed_notification(std::unique_ptr notification, int64_t initial_delay, int64_t delay_interval); //finds older notification of same type and moves it to the end of queue. returns true if found bool activate_existing(const NotificationManager::PopNotification* notification); // Put the more important notifications to the bottom of the list. @@ -531,6 +548,8 @@ private: // Cache of IDs to identify and reuse ImGUI windows. NotificationIDProvider m_id_provider; std::deque> m_pop_notifications; + // delayed waiting notifications, first is remaining time + std::deque m_waiting_notifications; //timestamps used for slicing finished - notification could be gone so it needs to be stored here std::unordered_set m_used_timestamps; // True if G-code preview is active. False if the Plater is active.