From d6f0ab6a7ed7c167b317e3ffc7b9a87ade04e4b2 Mon Sep 17 00:00:00 2001 From: Gliniak Date: Sun, 25 Aug 2024 14:00:34 +0200 Subject: [PATCH] [UI] Implemented Host Notifications Splitted clases into: - ImGuiNotification - ImGuiHostNotification - ImGuiGuestNotification To differentiate between Xenia toast notifications and notifications from titles itself Adhoc: Changed Screenshot into toast notification and switched from being binded to F10 to F12 --- src/xenia/app/emulator_window.cc | 15 +- src/xenia/kernel/achievement_manager.cc | 2 +- src/xenia/ui/imgui_drawer.cc | 18 ++- src/xenia/ui/imgui_guest_notification.cc | 184 ++++++++++++++++++++++ src/xenia/ui/imgui_guest_notification.h | 82 ++++++++++ src/xenia/ui/imgui_host_notification.cc | 84 ++++++++++ src/xenia/ui/imgui_host_notification.h | 49 ++++++ src/xenia/ui/imgui_notification.cc | 190 +++-------------------- src/xenia/ui/imgui_notification.h | 64 +++----- 9 files changed, 470 insertions(+), 218 deletions(-) create mode 100644 src/xenia/ui/imgui_guest_notification.cc create mode 100644 src/xenia/ui/imgui_guest_notification.h create mode 100644 src/xenia/ui/imgui_host_notification.cc create mode 100644 src/xenia/ui/imgui_host_notification.h diff --git a/src/xenia/app/emulator_window.cc b/src/xenia/app/emulator_window.cc index d44f0890d..c2a22761b 100644 --- a/src/xenia/app/emulator_window.cc +++ b/src/xenia/app/emulator_window.cc @@ -41,6 +41,7 @@ #include "xenia/ui/graphics_provider.h" #include "xenia/ui/imgui_dialog.h" #include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/imgui_host_notification.h" #include "xenia/ui/immediate_drawer.h" #include "xenia/ui/presenter.h" #include "xenia/ui/ui_event.h" @@ -654,7 +655,7 @@ bool EmulatorWindow::Initialize() { MenuItem::Create(MenuItem::Type::kString, "&Fullscreen", "F11", std::bind(&EmulatorWindow::ToggleFullscreen, this))); display_menu->AddChild( - MenuItem::Create(MenuItem::Type::kString, "&Take Screenshot", "F10", + MenuItem::Create(MenuItem::Type::kString, "&Take Screenshot", "F12", std::bind(&EmulatorWindow::TakeScreenshot, this))); } main_menu->AddChild(std::move(display_menu)); @@ -840,7 +841,7 @@ void EmulatorWindow::OnKeyDown(ui::KeyEvent& e) { case ui::VirtualKey::kF11: { ToggleFullscreen(); } break; - case ui::VirtualKey::kF10: { + case ui::VirtualKey::kF12: { TakeScreenshot(); } break; @@ -939,9 +940,13 @@ void EmulatorWindow::ExportScreenshot(const xe::ui::RawImage& image) { std::string filename = fmt::format("{} - {}.png", title_id, datetime); SaveImage(screenshot_path / filename, image); - xe::ui::ImGuiDialog::ShowMessageBox( - imgui_drawer_.get(), "Screenshot saved", - fmt::format("Screenshot saved to {}", xe::path_to_utf8(screenshot_path))); + const std::string notification_text = + fmt::format("Screenshot saved: {}", filename); + + app_context_.CallInUIThread([&, notification_text]() { + new xe::ui::HostNotificationWindow(imgui_drawer(), "Screenshot Created!", + notification_text, 0); + }); } // Converts a RawImage into a PNG file diff --git a/src/xenia/kernel/achievement_manager.cc b/src/xenia/kernel/achievement_manager.cc index 92ccec063..a555ada39 100644 --- a/src/xenia/kernel/achievement_manager.cc +++ b/src/xenia/kernel/achievement_manager.cc @@ -12,7 +12,7 @@ #include "xenia/gpu/graphics_system.h" #include "xenia/kernel/kernel_state.h" #include "xenia/kernel/util/shim_utils.h" -#include "xenia/ui/imgui_notification.h" +#include "xenia/ui/imgui_guest_notification.h" DEFINE_bool(show_achievement_notification, false, "Show achievement notification on screen.", "UI"); diff --git a/src/xenia/ui/imgui_drawer.cc b/src/xenia/ui/imgui_drawer.cc index 00c9917ed..735f4ca4f 100644 --- a/src/xenia/ui/imgui_drawer.cc +++ b/src/xenia/ui/imgui_drawer.cc @@ -467,8 +467,22 @@ void ImGuiDrawer::Draw(UIDrawContext& ui_draw_context) { dialog_loop_next_index_ = SIZE_MAX; if (!notifications_.empty()) { - // We only care about drawing next notification. - notifications_.at(0)->Draw(); + bool was_guest_notification_drawn = false; + bool was_host_notification_drawn = false; + + for (const auto& notification : notifications_) { + if (notification->GetNotificationType() == NotificationType::Guest && + !was_guest_notification_drawn) { + was_guest_notification_drawn = true; + notification->Draw(); + } + + if (notification->GetNotificationType() == NotificationType::Host && + !was_host_notification_drawn) { + was_host_notification_drawn = true; + notification->Draw(); + } + } } ImGui::Render(); diff --git a/src/xenia/ui/imgui_guest_notification.cc b/src/xenia/ui/imgui_guest_notification.cc new file mode 100644 index 000000000..1e66c8f1d --- /dev/null +++ b/src/xenia/ui/imgui_guest_notification.cc @@ -0,0 +1,184 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2023 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include +#include + +#include "xenia/base/logging.h" +#include "xenia/base/platform.h" +#include "xenia/ui/imgui_guest_notification.h" +#include "xenia/ui/imgui_notification.h" + +#if XE_PLATFORM_WIN32 +#include +#endif + +DEFINE_string(notification_sound_path, "", + "Path (including filename) to selected notification sound. Sound " + "MUST be in wav format!", + "General"); + +namespace xe { +namespace ui { + +ImGuiGuestNotification::ImGuiGuestNotification(ui::ImGuiDrawer* imgui_drawer, + std::string& title, + std::string& description, + uint8_t user_index, + uint8_t position_id) + : ImGuiNotification(imgui_drawer, NotificationType::Guest, title, + description, user_index, position_id), + current_stage_(NotificationStage::Awaiting), + notification_draw_progress_(0.0f) { + imgui_drawer->AddNotification(this); +} + +ImGuiGuestNotification::~ImGuiGuestNotification() {} + +void ImGuiGuestNotification::UpdateNotificationState() { + switch (current_stage_) { + case NotificationStage::Awaiting: + // TODO(Gliniak): Implement delayed notifications. + current_stage_ = NotificationStage::FazeIn; + notification_draw_progress_ = 0.2f; +#if XE_PLATFORM_WIN32 + if (!cvars::notification_sound_path.empty()) { + auto notification_sound_path = cvars::notification_sound_path; + if (std::filesystem::exists(notification_sound_path)) { + PlaySound(std::wstring(notification_sound_path.begin(), + notification_sound_path.end()) + .c_str(), + NULL, + SND_FILENAME | SND_NODEFAULT | SND_NOSTOP | SND_ASYNC); + } + } +#endif + + break; + case NotificationStage::FazeIn: { + SetCreationTime(Clock::QueryHostUptimeMillis()); + if (notification_draw_progress_ < 1.1f) { + notification_draw_progress_ += 0.02f; + } + + // Mimics a bit original console behaviour when it makes window a bit + // longer for few frames then decreases size + if (notification_draw_progress_ >= 1.1f) { + current_stage_ = NotificationStage::Present; + notification_draw_progress_ = 1.0f; + } + break; + } + case NotificationStage::Present: + if (IsNotificationClosingTime()) { + current_stage_ = NotificationStage::FazeOut; + } + break; + case NotificationStage::FazeOut: { + if (notification_draw_progress_ > 0.2f) { + notification_draw_progress_ -= 0.02f; + } else { + current_stage_ = NotificationStage::Finished; + } + break; + } + default: + break; + } +} + +const ImVec2 ImGuiGuestNotification::CalculateNotificationSize(ImVec2 text_size, + float scale) { + const ImVec2 result = + ImVec2(std::floorf((default_notification_icon_size.x + + default_notification_margin_size.x) * + scale) + + text_size.x, + std::floorf((default_notification_icon_size.y + + default_notification_margin_size.y) * + scale)); + + return result; +} + +void AchievementNotificationWindow::OnDraw(ImGuiIO& io) { + UpdateNotificationState(); + + if (IsNotificationExpired()) { + delete this; + return; + } + + const std::string longest_notification_text_line = + GetTitle().size() > GetDescription().size() ? GetTitle().c_str() + : GetDescription().c_str(); + + const ImVec2 screen_size = io.DisplaySize; + const float window_scale = + std::fminf(screen_size.x / default_drawing_resolution.x, + screen_size.y / default_drawing_resolution.y); + const float font_scale = default_font_size / io.Fonts->Fonts[0]->FontSize; + const ImVec2 text_size = io.Fonts->Fonts[0]->CalcTextSizeA( + default_font_size * default_notification_text_scale * window_scale, + FLT_MAX, -1.0f, longest_notification_text_line.c_str()); + + const ImVec2 final_notification_size = + CalculateNotificationSize(text_size, window_scale); + + const ImVec2 notification_position = CalculateNotificationScreenPosition( + screen_size, final_notification_size, GetPositionId()); + + if (isnan(notification_position.x) || isnan(notification_position.y)) { + return; + } + + ImVec2 current_notification_size = final_notification_size; + current_notification_size.x *= notification_draw_progress_; + current_notification_size.x = std::floorf(current_notification_size.x); + + // Initialize position and window size + ImGui::SetNextWindowSize(current_notification_size); + ImGui::SetNextWindowPos(notification_position); + + // Set new window style before drawing window + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, + default_notification_rounding * window_scale); + ImGui::PushStyleColor(ImGuiCol_WindowBg, + default_notification_background_color); + ImGui::PushStyleColor(ImGuiCol_Separator, + default_notification_background_color); + ImGui::PushStyleColor(ImGuiCol_Border, default_notification_border_color); + + ImGui::Begin("Notification Window", NULL, NOTIFY_TOAST_FLAGS); + { + ImGui::SetWindowFontScale(default_notification_text_scale * font_scale * + window_scale); + // Set offset to image to prevent it from being right on border. + ImGui::SetCursorPos(ImVec2(final_notification_size.x * 0.005f, + final_notification_size.y * 0.05f)); + // Elements of window + ImGui::Image(reinterpret_cast( + GetDrawer()->GetNotificationIcon(GetUserIndex())), + ImVec2(default_notification_icon_size.x * window_scale, + default_notification_icon_size.y * window_scale)); + + ImGui::SameLine(); + if (notification_draw_progress_ > 0.5f) { + ImGui::TextColored(white_color, GetNotificationText().c_str()); + } + } + // Restore previous style + ImGui::PopStyleVar(); + ImGui::PopStyleColor(3); + + ImGui::End(); +} + +} // namespace ui +} // namespace xe \ No newline at end of file diff --git a/src/xenia/ui/imgui_guest_notification.h b/src/xenia/ui/imgui_guest_notification.h new file mode 100644 index 000000000..79b229cc4 --- /dev/null +++ b/src/xenia/ui/imgui_guest_notification.h @@ -0,0 +1,82 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2023 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_IMGUI_GUEST_NOTIFICATION_H_ +#define XENIA_UI_IMGUI_GUEST_NOTIFICATION_H_ + +#include "third_party/imgui/imgui.h" +#include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/imgui_notification.h" + +/* + +*/ + +namespace xe { +namespace ui { +class ImGuiGuestNotification : public ImGuiNotification { + public: + ImGuiGuestNotification(ui::ImGuiDrawer* imgui_drawer, std::string& title, + std::string& description, uint8_t user_index, + uint8_t position_id = 0); + + ~ImGuiGuestNotification(); + + protected: + const ImVec2 default_notification_icon_size = ImVec2(58.0f, 58.0f); + const ImVec2 default_notification_margin_size = ImVec2(50.f, 5.f); + const float default_notification_text_scale = 2.3f; + const float default_notification_rounding = 30.f; + const float default_font_size = 12.f; + + const ImVec4 white_color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); + + const ImVec4 default_notification_background_color = + ImVec4(0.215f, 0.215f, 0.215f, 1.0f); + const ImVec4 default_notification_border_color = white_color; + + enum class NotificationStage : uint8_t { + Awaiting = 0, + FazeIn = 1, + Present = 2, + FazeOut = 3, + Finished = 4 + }; + + const bool IsNotificationExpired() { + return current_stage_ == NotificationStage::Finished; + } + + void UpdateNotificationState(); + const ImVec2 CalculateNotificationSize(ImVec2 text_size, + float scale) override; + + virtual void OnDraw(ImGuiIO& io) {} + + float notification_draw_progress_; + + private: + NotificationStage current_stage_; +}; + +class AchievementNotificationWindow final : ImGuiGuestNotification { + public: + AchievementNotificationWindow(ui::ImGuiDrawer* imgui_drawer, + std::string title, std::string description, + uint8_t user_index, uint8_t position_id = 0) + : ImGuiGuestNotification(imgui_drawer, title, description, user_index, + position_id) {}; + + void OnDraw(ImGuiIO& io) override; +}; + +} // namespace ui +} // namespace xe + +#endif \ No newline at end of file diff --git a/src/xenia/ui/imgui_host_notification.cc b/src/xenia/ui/imgui_host_notification.cc new file mode 100644 index 000000000..af8371a2d --- /dev/null +++ b/src/xenia/ui/imgui_host_notification.cc @@ -0,0 +1,84 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2023 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include +#include + +#include "xenia/base/logging.h" +#include "xenia/base/platform.h" +#include "xenia/ui/imgui_host_notification.h" +#include "xenia/ui/imgui_notification.h" + +namespace xe { +namespace ui { + +ImGuiHostNotification::ImGuiHostNotification(ui::ImGuiDrawer* imgui_drawer, + std::string& title, + std::string& description, + uint8_t user_index, + uint8_t position_id) + : ImGuiNotification(imgui_drawer, NotificationType::Host, title, + description, user_index, position_id) { + SetCreationTime(Clock::QueryHostUptimeMillis()); + imgui_drawer->AddNotification(this); +} + +ImGuiHostNotification::~ImGuiHostNotification() {} + +const ImVec2 ImGuiHostNotification::CalculateNotificationSize(ImVec2 text_size, + float scale) { + const ImVec2 result = ImVec2(text_size.x * scale, text_size.y * scale); + + return result; +} + +void HostNotificationWindow::OnDraw(ImGuiIO& io) { + if (IsNotificationClosingTime()) { + delete this; + return; + } + + const std::string longest_notification_text_line = + GetTitle().size() > GetDescription().size() ? GetTitle().c_str() + : GetDescription().c_str(); + + const ImVec2 screen_size = io.DisplaySize; + const float window_scale = + std::fminf(screen_size.x / default_drawing_resolution.x, + screen_size.y / default_drawing_resolution.y); + const float font_size = io.Fonts->Fonts[0]->FontSize; + const ImVec2 text_size = io.Fonts->Fonts[0]->CalcTextSizeA( + font_size * window_scale, FLT_MAX, -1.0f, + longest_notification_text_line.c_str()); + + const ImVec2 notification_size = + CalculateNotificationSize(text_size, window_scale); + + const ImVec2 notification_position = CalculateNotificationScreenPosition( + screen_size, notification_size, GetPositionId()); + + if (isnan(notification_position.x) || isnan(notification_position.y)) { + return; + } + + ImGui::SetNextWindowPos(notification_position); + + ImGui::Begin("Notification Window", NULL, NOTIFY_TOAST_FLAGS); + { + ImGui::SetWindowFontScale(window_scale); + + ImGui::Text(GetTitle().c_str()); + ImGui::Separator(); + ImGui::Text(GetDescription().c_str()); + } + ImGui::End(); +} + +} // namespace ui +} // namespace xe \ No newline at end of file diff --git a/src/xenia/ui/imgui_host_notification.h b/src/xenia/ui/imgui_host_notification.h new file mode 100644 index 000000000..58983826a --- /dev/null +++ b/src/xenia/ui/imgui_host_notification.h @@ -0,0 +1,49 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2023 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_IMGUI_HOST_NOTIFICATION_H_ +#define XENIA_UI_IMGUI_HOST_NOTIFICATION_H_ + +#include "third_party/imgui/imgui.h" +#include "xenia/ui/imgui_dialog.h" +#include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/imgui_notification.h" + +namespace xe { +namespace ui { +class ImGuiHostNotification : public ImGuiNotification { + public: + ImGuiHostNotification(ui::ImGuiDrawer* imgui_drawer, std::string& title, + std::string& description, uint8_t user_index, + uint8_t position_id = 10); + + ~ImGuiHostNotification(); + + protected: + const ImVec2 CalculateNotificationSize(ImVec2 text_size, + float scale) override; + + virtual void OnDraw(ImGuiIO& io) {} +}; + +class HostNotificationWindow final : ImGuiHostNotification { + public: + HostNotificationWindow(ui::ImGuiDrawer* imgui_drawer, std::string title, + std::string description, uint8_t user_index, + uint8_t position_id = 10) + : ImGuiHostNotification(imgui_drawer, title, description, user_index, + position_id) {}; + + void OnDraw(ImGuiIO& io) override; +}; + +} // namespace ui +} // namespace xe + +#endif \ No newline at end of file diff --git a/src/xenia/ui/imgui_notification.cc b/src/xenia/ui/imgui_notification.cc index d22ac032a..410c9766c 100644 --- a/src/xenia/ui/imgui_notification.cc +++ b/src/xenia/ui/imgui_notification.cc @@ -14,19 +14,29 @@ #include "xenia/base/platform.h" #include "xenia/ui/imgui_notification.h" -#if XE_PLATFORM_WIN32 -#include -#endif - -DEFINE_string(notification_sound_path, "", - "Path (including filename) to selected notification sound. Sound " - "MUST be in wav format!", - "General"); - namespace xe { namespace ui { -const NotificationAlignment GetNotificationAlignment( +ImGuiNotification::ImGuiNotification(ui::ImGuiDrawer* imgui_drawer, + NotificationType notification_type, + std::string& title, + std::string& description, + uint8_t user_index, uint8_t position_id) + : imgui_drawer_(imgui_drawer), + notification_type_(notification_type), + title_(title), + description_(description), + user_index_(user_index), + position_(position_id), + creation_time_(0) {} + +ImGuiNotification::~ImGuiNotification() { + imgui_drawer_->RemoveNotification(this); +} + +void ImGuiNotification::Draw() { OnDraw(imgui_drawer_->GetIO()); } + +const NotificationAlignment ImGuiNotification::GetNotificationAlignment( const uint8_t notification_position_id) { NotificationAlignment alignment = NotificationAlignment::kAlignUnknown; @@ -49,7 +59,7 @@ const NotificationAlignment GetNotificationAlignment( return alignment; } -const ImVec2 CalculateNotificationScreenPosition( +const ImVec2 ImGuiNotification::CalculateNotificationScreenPosition( ImVec2 screen_size, ImVec2 window_size, uint8_t notification_position_id) { ImVec2 result = {NAN, NAN}; @@ -88,163 +98,5 @@ const ImVec2 CalculateNotificationScreenPosition( return result; } -const ImVec2 CalculateNotificationSize(ImVec2 text_size, float scale) { - const ImVec2 result = - ImVec2(std::floorf((default_notification_icon_size.x + - default_notification_margin_size.x) * - scale) + - text_size.x, - std::floorf((default_notification_icon_size.y + - default_notification_margin_size.y) * - scale)); - - return result; -} - -ImGuiNotification::ImGuiNotification(ui::ImGuiDrawer* imgui_drawer, - std::string title, std::string description, - uint8_t user_index, uint8_t position_id) - : imgui_drawer_(imgui_drawer), - title_(title), - description_(description), - user_index_(user_index), - position_(position_id), - creation_time_(0), - current_stage_(NotificationStage::kAwaiting), - notification_draw_progress_(0.0f) { - imgui_drawer->AddNotification(this); -} - -ImGuiNotification::~ImGuiNotification() { - imgui_drawer_->RemoveNotification(this); -} - -void ImGuiNotification::Draw() { OnDraw(imgui_drawer_->GetIO()); } - -void ImGuiNotification::UpdateNotificationState() { - switch (current_stage_) { - case NotificationStage::kAwaiting: - // TODO(Gliniak): Implement delayed notifications. - current_stage_ = NotificationStage::kFazeIn; - notification_draw_progress_ = 0.2f; -#if XE_PLATFORM_WIN32 - if (!cvars::notification_sound_path.empty()) { - auto notification_sound_path = cvars::notification_sound_path; - if (std::filesystem::exists(notification_sound_path)) { - PlaySound(std::wstring(notification_sound_path.begin(), - notification_sound_path.end()) - .c_str(), - NULL, - SND_FILENAME | SND_NODEFAULT | SND_NOSTOP | SND_ASYNC); - } - } -#endif - - break; - case NotificationStage::kFazeIn: { - creation_time_ = Clock::QueryHostUptimeMillis(); - if (notification_draw_progress_ < 1.1f) { - notification_draw_progress_ += 0.02f; - } - - // Mimics a bit original console behaviour when it makes window a bit - // longer for few frames then decreases size - if (notification_draw_progress_ >= 1.1f) { - current_stage_ = NotificationStage::kPresent; - notification_draw_progress_ = 1.0f; - } - break; - } - case NotificationStage::kPresent: - if (IsNotificationClosingTime()) { - current_stage_ = NotificationStage::kFazeOut; - } - break; - case NotificationStage::kFazeOut: { - if (notification_draw_progress_ > 0.2f) { - notification_draw_progress_ -= 0.02f; - } else { - current_stage_ = NotificationStage::kFinished; - } - break; - } - default: - break; - } -} - -void AchievementNotificationWindow::OnDraw(ImGuiIO& io) { - UpdateNotificationState(); - - if (IsNotificationExpired()) { - delete this; - return; - } - - const std::string longest_notification_text_line = - GetTitle().size() > GetDescription().size() ? GetTitle().c_str() - : GetDescription().c_str(); - - const ImVec2 screen_size = io.DisplaySize; - const float window_scale = - std::fminf(screen_size.x / default_drawing_resolution.x, - screen_size.y / default_drawing_resolution.y); - const float font_scale = default_font_size / io.Fonts->Fonts[0]->FontSize; - const ImVec2 text_size = io.Fonts->Fonts[0]->CalcTextSizeA( - default_font_size * default_notification_text_scale * window_scale, - FLT_MAX, -1.0f, longest_notification_text_line.c_str()); - - const ImVec2 final_notification_size = - CalculateNotificationSize(text_size, window_scale); - - const ImVec2 notification_position = CalculateNotificationScreenPosition( - screen_size, final_notification_size, GetPositionId()); - - if (isnan(notification_position.x) || isnan(notification_position.y)) { - return; - } - - ImVec2 current_notification_size = final_notification_size; - current_notification_size.x *= notification_draw_progress_; - current_notification_size.x = std::floorf(current_notification_size.x); - - // Initialize position and window size - ImGui::SetNextWindowSize(current_notification_size); - ImGui::SetNextWindowPos(notification_position); - - // Set new window style before drawing window - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, - default_notification_rounding * window_scale); - ImGui::PushStyleColor(ImGuiCol_WindowBg, - default_notification_background_color); - ImGui::PushStyleColor(ImGuiCol_Separator, - default_notification_background_color); - ImGui::PushStyleColor(ImGuiCol_Border, default_notification_border_color); - - ImGui::Begin("Notification Window", NULL, NOTIFY_TOAST_FLAGS); - { - ImGui::SetWindowFontScale(default_notification_text_scale * font_scale * - window_scale); - // Set offset to image to prevent it from being right on border. - ImGui::SetCursorPos(ImVec2(final_notification_size.x * 0.005f, - final_notification_size.y * 0.05f)); - // Elements of window - ImGui::Image(reinterpret_cast( - GetDrawer()->GetNotificationIcon(GetUserIndex())), - ImVec2(default_notification_icon_size.x * window_scale, - default_notification_icon_size.y * window_scale)); - - ImGui::SameLine(); - if (notification_draw_progress_ > 0.5f) { - ImGui::TextColored(white_color, GetNotificationText().c_str()); - } - } - // Restore previous style - ImGui::PopStyleVar(); - ImGui::PopStyleColor(3); - - ImGui::End(); -} - } // namespace ui } // namespace xe \ No newline at end of file diff --git a/src/xenia/ui/imgui_notification.h b/src/xenia/ui/imgui_notification.h index f412f032c..7212235cc 100644 --- a/src/xenia/ui/imgui_notification.h +++ b/src/xenia/ui/imgui_notification.h @@ -23,18 +23,6 @@ // Parameters based on 1280x720 resolution constexpr ImVec2 default_drawing_resolution = ImVec2(1280.f, 720.f); -constexpr ImVec2 default_notification_icon_size = ImVec2(58.0f, 58.0f); -constexpr ImVec2 default_notification_margin_size = ImVec2(50.f, 5.f); -constexpr float default_notification_text_scale = 2.3f; -constexpr float default_notification_rounding = 30.f; -constexpr float default_font_size = 12.f; - -constexpr ImVec4 white_color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); - -constexpr ImVec4 default_notification_background_color = - ImVec4(0.215f, 0.215f, 0.215f, 1.0f); -constexpr ImVec4 default_notification_border_color = white_color; - enum class NotificationAlignment : uint8_t { kAlignLeft = 0, kAlignRight = 1, @@ -56,37 +44,32 @@ const static std::vector notification_position_id_screen_offset = { {0.93f, 0.80f} // RIGHT-BOTTOM - 10 }; +enum class NotificationType : uint8_t { Guest = 0, Host = 1 }; + namespace xe { namespace ui { class ImGuiNotification { public: - ImGuiNotification(ui::ImGuiDrawer* imgui_drawer, std::string title, - std::string description, uint8_t user_index, + ImGuiNotification(ui::ImGuiDrawer* imgui_drawer, + NotificationType notification_type, std::string& title, + std::string& description, uint8_t user_index, uint8_t position_id = 0); ~ImGuiNotification(); void Draw(); - protected: - enum class NotificationStage : uint8_t { - kAwaiting = 0, - kFazeIn = 1, - kPresent = 2, - kFazeOut = 3, - kFinished = 4 - }; + const NotificationType GetNotificationType() const { + return notification_type_; + } + protected: ImGuiDrawer* GetDrawer() { return imgui_drawer_; } const bool IsNotificationClosingTime() { return Clock::QueryHostUptimeMillis() - creation_time_ > time_to_close_; } - const bool IsNotificationExpired() { - return current_stage_ == NotificationStage::kFinished; - } - const std::string GetNotificationText() { std::string text = title_; @@ -96,20 +79,30 @@ class ImGuiNotification { return text; } + void SetCreationTime(uint64_t new_creation_time) { + creation_time_ = new_creation_time; + } + const std::string GetTitle() { return title_; } const std::string GetDescription() { return description_; } const uint8_t GetPositionId() { return position_; } const uint8_t GetUserIndex() { return user_index_; } - void UpdateNotificationState(); + const NotificationAlignment GetNotificationAlignment( + const uint8_t notification_position_id); + + const ImVec2 CalculateNotificationScreenPosition( + ImVec2 screen_size, ImVec2 window_size, uint8_t notification_position_id); + + virtual const ImVec2 CalculateNotificationSize(ImVec2 text_size, + float scale) = 0; virtual void OnDraw(ImGuiIO& io) {} - float notification_draw_progress_; - private: - NotificationStage current_stage_; + NotificationType notification_type_; + uint8_t position_; uint8_t user_index_; @@ -124,17 +117,6 @@ class ImGuiNotification { ImGuiDrawer* imgui_drawer_ = nullptr; }; -class AchievementNotificationWindow final : ImGuiNotification { - public: - AchievementNotificationWindow(ui::ImGuiDrawer* imgui_drawer, - std::string title, std::string description, - uint8_t user_index, uint8_t position_id = 0) - : ImGuiNotification(imgui_drawer, title, description, user_index, - position_id) {}; - - void OnDraw(ImGuiIO& io) override; -}; - } // namespace ui } // namespace xe