From 855da86feae1a5cc14dc2d486ccf115f484dbc2e Mon Sep 17 00:00:00 2001 From: rtk0c Date: Mon, 25 Apr 2022 20:22:07 -0700 Subject: Changeset: 16 Initial work on rendering sprites to screen --- source/EditorNotification.cpp | 385 +++++++++++++++++++++--------------------- 1 file changed, 194 insertions(+), 191 deletions(-) (limited to 'source/EditorNotification.cpp') diff --git a/source/EditorNotification.cpp b/source/EditorNotification.cpp index 1fdd93a..e4a869e 100644 --- a/source/EditorNotification.cpp +++ b/source/EditorNotification.cpp @@ -3,7 +3,9 @@ #include "Macros.hpp" -// #include +#define IMGUI_DEFINE_MATH_OPERATORS +#include + #include #include #include @@ -11,163 +13,163 @@ #include ImGuiToast::ImGuiToast(ImGuiToastType type, int dismissTime) { - IM_ASSERT(type < ImGuiToastType_COUNT); + IM_ASSERT(type < ImGuiToastType_COUNT); - mType = type; - mDismissTime = dismissTime; + mType = type; + mDismissTime = dismissTime; - using namespace std::chrono; - auto timeStamp = system_clock::now().time_since_epoch(); - mCreationTime = duration_cast(timeStamp).count(); + using namespace std::chrono; + auto timeStamp = system_clock::now().time_since_epoch(); + mCreationTime = duration_cast(timeStamp).count(); - memset(mTitle, 0, sizeof(mTitle)); - memset(mContent, 0, sizeof(mContent)); + memset(mTitle, 0, sizeof(mTitle)); + memset(mContent, 0, sizeof(mContent)); } ImGuiToast::ImGuiToast(ImGuiToastType type, const char* format, ...) - : ImGuiToast(type) { - if (format) { - va_list args; - va_start(args, format); - SetContent(format, args); - va_end(args); - } + : ImGuiToast(type) { + if (format) { + va_list args; + va_start(args, format); + SetContent(format, args); + va_end(args); + } } ImGuiToast::ImGuiToast(ImGuiToastType type, int dismissTime, const char* format, ...) - : ImGuiToast(type, dismissTime) { - if (format) { - va_list args; - va_start(args, format); - SetContent(format, args); - va_end(args); - } + : ImGuiToast(type, dismissTime) { + if (format) { + va_list args; + va_start(args, format); + SetContent(format, args); + va_end(args); + } } void ImGuiToast::SetTitle(const char* format, ...) { - if (format) { - va_list args; - va_start(args, format); - SetTitle(format, args); - va_end(args); - } + if (format) { + va_list args; + va_start(args, format); + SetTitle(format, args); + va_end(args); + } } void ImGuiToast::SetContent(const char* format, ...) { - if (format) { - va_list args; - va_start(args, format); - SetContent(format, args); - va_end(args); - } + if (format) { + va_list args; + va_start(args, format); + SetContent(format, args); + va_end(args); + } } void ImGuiToast::SetType(const ImGuiToastType& type) { - IM_ASSERT(type < ImGuiToastType_COUNT); - mType = type; + IM_ASSERT(type < ImGuiToastType_COUNT); + mType = type; } const char* ImGuiToast::GetTitle() { - return mTitle; + return mTitle; } const char* ImGuiToast::GetDefaultTitle() { - if (!strlen(mTitle)) { - switch (mType) { - case ImGuiToastType_None: return nullptr; - case ImGuiToastType_Success: return "Success"; - case ImGuiToastType_Warning: return "Warning"; - case ImGuiToastType_Error: return "Error"; - case ImGuiToastType_Info: return "Info"; - case ImGuiToastType_COUNT: UNREACHABLE; - } - } - - return mTitle; + if (!strlen(mTitle)) { + switch (mType) { + case ImGuiToastType_None: return nullptr; + case ImGuiToastType_Success: return "Success"; + case ImGuiToastType_Warning: return "Warning"; + case ImGuiToastType_Error: return "Error"; + case ImGuiToastType_Info: return "Info"; + case ImGuiToastType_COUNT: UNREACHABLE; + } + } + + return mTitle; } ImGuiToastType ImGuiToast::GetType() { - return mType; + return mType; } ImVec4 ImGuiToast::GetColor() { - switch (mType) { - case ImGuiToastType_None: return ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // White - case ImGuiToastType_Success: return ImVec4(0, 1.0f, 0, 1.0f); // Green - case ImGuiToastType_Warning: return ImVec4(1.0f, 1.0f, 0, 1.0f); // Yellow - case ImGuiToastType_Error: return ImVec4(1.0f, 0, 0, 1.0f); // Red - case ImGuiToastType_Info: return ImVec4(0, 0.616, 1.0f, 1.0f); // Blue - case ImGuiToastType_COUNT: UNREACHABLE; - } - return ImVec4(); + switch (mType) { + case ImGuiToastType_None: return ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // White + case ImGuiToastType_Success: return ImVec4(0, 1.0f, 0, 1.0f); // Green + case ImGuiToastType_Warning: return ImVec4(1.0f, 1.0f, 0, 1.0f); // Yellow + case ImGuiToastType_Error: return ImVec4(1.0f, 0, 0, 1.0f); // Red + case ImGuiToastType_Info: return ImVec4(0, 0.616, 1.0f, 1.0f); // Blue + case ImGuiToastType_COUNT: UNREACHABLE; + } + return ImVec4(); } const char* ImGuiToast::GetIcon() { - switch (mType) { - case ImGuiToastType_None: return nullptr; + switch (mType) { + case ImGuiToastType_None: return nullptr; #if 1 - // TODO add IconFontHeaders and replace with proper icons - case ImGuiToastType_Success: return nullptr; - case ImGuiToastType_Warning: return nullptr; - case ImGuiToastType_Error: return nullptr; - case ImGuiToastType_Info: return nullptr; + // TODO add IconFontHeaders and replace with proper icons + case ImGuiToastType_Success: return nullptr; + case ImGuiToastType_Warning: return nullptr; + case ImGuiToastType_Error: return nullptr; + case ImGuiToastType_Info: return nullptr; #else - case ImGuiToastType_Success: return ICON_FA_CHECK_CIRCLE; - case ImGuiToastType_Warning: return ICON_FA_EXCLAMATION_TRIANGLE; - case ImGuiToastType_Error: return ICON_FA_TIMES_CIRCLE; - case ImGuiToastType_Info: return ICON_FA_INFO_CIRCLE; + case ImGuiToastType_Success: return ICON_FA_CHECK_CIRCLE; + case ImGuiToastType_Warning: return ICON_FA_EXCLAMATION_TRIANGLE; + case ImGuiToastType_Error: return ICON_FA_TIMES_CIRCLE; + case ImGuiToastType_Info: return ICON_FA_INFO_CIRCLE; #endif - case ImGuiToastType_COUNT: UNREACHABLE; - } - return nullptr; + case ImGuiToastType_COUNT: UNREACHABLE; + } + return nullptr; } const char* ImGuiToast::GetContent() { - return this->mContent; + return this->mContent; } uint64_t ImGuiToast::GetElapsedTime() { - using namespace std::chrono; - auto timeStamp = system_clock::now().time_since_epoch(); - auto timeStampI = duration_cast(timeStamp).count(); - return timeStampI - mCreationTime; + using namespace std::chrono; + auto timeStamp = system_clock::now().time_since_epoch(); + auto timeStampI = duration_cast(timeStamp).count(); + return timeStampI - mCreationTime; } ImGuiToastPhase ImGuiToast::GetPhase() { - const auto elapsed = GetElapsedTime(); - - if (elapsed > kNotifyFadeInOutTime + mDismissTime + kNotifyFadeInOutTime) { - return ImGuiToastPhase_Expired; - } else if (elapsed > kNotifyFadeInOutTime + mDismissTime) { - return ImGuiToastPhase_FadeOut; - } else if (elapsed > kNotifyFadeInOutTime) { - return ImGuiToastPhase_Wait; - } else { - return ImGuiToastPhase_FadeIn; - } + const auto elapsed = GetElapsedTime(); + + if (elapsed > kNotifyFadeInOutTime + mDismissTime + kNotifyFadeInOutTime) { + return ImGuiToastPhase_Expired; + } else if (elapsed > kNotifyFadeInOutTime + mDismissTime) { + return ImGuiToastPhase_FadeOut; + } else if (elapsed > kNotifyFadeInOutTime) { + return ImGuiToastPhase_Wait; + } else { + return ImGuiToastPhase_FadeIn; + } } float ImGuiToast::GetFadePercent() { - const auto phase = GetPhase(); - const auto elapsed = GetElapsedTime(); - - if (phase == ImGuiToastPhase_FadeIn) - { - return ((float)elapsed / (float)kNotifyFadeInOutTime) * kNotifyOpacity; - } else if (phase == ImGuiToastPhase_FadeOut) - { - return (1.0f - (((float)elapsed - (float)kNotifyFadeInOutTime - (float)mDismissTime) / (float)kNotifyFadeInOutTime)) * kNotifyOpacity; - } - - return 1.0f * kNotifyOpacity; + const auto phase = GetPhase(); + const auto elapsed = GetElapsedTime(); + + if (phase == ImGuiToastPhase_FadeIn) + { + return ((float)elapsed / (float)kNotifyFadeInOutTime) * kNotifyOpacity; + } else if (phase == ImGuiToastPhase_FadeOut) + { + return (1.0f - (((float)elapsed - (float)kNotifyFadeInOutTime - (float)mDismissTime) / (float)kNotifyFadeInOutTime)) * kNotifyOpacity; + } + + return 1.0f * kNotifyOpacity; } void ImGuiToast::SetTitle(const char* format, va_list args) { - vsnprintf(mTitle, sizeof(mTitle), format, args); + vsnprintf(mTitle, sizeof(mTitle), format, args); } void ImGuiToast::SetContent(const char* format, va_list args) { - vsnprintf(mContent, sizeof(mContent), format, args); + vsnprintf(mContent, sizeof(mContent), format, args); } namespace ImGui { @@ -175,100 +177,101 @@ static std::vector notifications; } static bool IsNullOrEmpty(const char* str) { - return !str || !strlen(str); + return !str || !strlen(str); } void ImGui::AddNotification(ImGuiToast toast) { - notifications.push_back(std::move(toast)); + notifications.push_back(std::move(toast)); } void ImGui::RemoveNotification(int index) { - notifications.erase(notifications.begin() + index); + notifications.erase(notifications.begin() + index); } void ImGui::ShowNotifications() { - auto vpSize = GetMainViewport()->Size; - - float height = 0.0f; - for (auto i = 0; i < notifications.size(); i++) { - auto* currentToast = ¬ifications[i]; - - // Remove toast if expired - if (currentToast->GetPhase() == ImGuiToastPhase_Expired) { - RemoveNotification(i); - continue; - } - - // Get icon, title and other data - const auto icon = currentToast->GetIcon(); - const auto title = currentToast->GetTitle(); - const auto content = currentToast->GetContent(); - const auto defaultTitle = currentToast->GetDefaultTitle(); - const auto opacity = currentToast->GetFadePercent(); // Get opacity based of the current phase - - // Window rendering - auto textColor = currentToast->GetColor(); - textColor.w = opacity; - - // Generate new unique name for this toast - char windowName[50]; - snprintf(windowName, std::size(windowName), "##TOAST%d", i); - - SetNextWindowBgAlpha(opacity); - SetNextWindowPos(ImVec2(vpSize.x - kNotifyPaddingX, vpSize.y - kNotifyPaddingY - height), ImGuiCond_Always, ImVec2(1.0f, 1.0f)); - Begin(windowName, nullptr, kNotifyToastFlags); - - // Here we render the toast content - { - PushTextWrapPos(vpSize.x / 3.0f); // We want to support multi-line text, this will wrap the text after 1/3 of the screen width - - bool wasTitleRendered = false; - - // If an icon is set - if (!::IsNullOrEmpty(icon)) { - // Render icon text - PushStyleColor(ImGuiCol_Text, textColor); - TextUnformatted(icon); - PopStyleColor(); - wasTitleRendered = true; - } - - // If a title is set - if (!::IsNullOrEmpty(title)) { - // If a title and an icon is set, we want to render on same line - if (!::IsNullOrEmpty(icon)) - SameLine(); - - TextUnformatted(title); // Render title text - wasTitleRendered = true; - } else if (!::IsNullOrEmpty(defaultTitle)) { - if (!::IsNullOrEmpty(icon)) - SameLine(); - - TextUnformatted(defaultTitle); // Render default title text (ImGuiToastType_Success -> "Success", etc...) - wasTitleRendered = true; - } - - // In case ANYTHING was rendered in the top, we want to add a small padding so the text (or icon) looks centered vertically - if (wasTitleRendered && !::IsNullOrEmpty(content)) { - SetCursorPosY(GetCursorPosY() + 5.0f); // Must be a better way to do this!!!! - } - - // If a content is set - if (!::IsNullOrEmpty(content)) { - if (wasTitleRendered) { - Separator(); - } - - TextUnformatted(content); // Render content text - } - - PopTextWrapPos(); - } - - // Save height for next toasts - height += GetWindowHeight() + kNotifyPaddingMessageY; - - End(); - } + auto vpSize = GetMainViewport()->Size; + + float height = 0.0f; + for (auto i = 0; i < notifications.size(); i++) { + auto* currentToast = ¬ifications[i]; + + // Remove toast if expired + if (currentToast->GetPhase() == ImGuiToastPhase_Expired) { + RemoveNotification(i); + continue; + } + + // Get icon, title and other data + const auto icon = currentToast->GetIcon(); + const auto title = currentToast->GetTitle(); + const auto content = currentToast->GetContent(); + const auto defaultTitle = currentToast->GetDefaultTitle(); + const auto opacity = currentToast->GetFadePercent(); // Get opacity based of the current phase + + // Window rendering + auto textColor = currentToast->GetColor(); + textColor.w = opacity; + + // Generate new unique name for this toast + char windowName[50]; + snprintf(windowName, std::size(windowName), "##TOAST%d", i); + + SetNextWindowBgAlpha(opacity); + SetNextWindowPos(ImVec2(vpSize.x - kNotifyPaddingX, vpSize.y - kNotifyPaddingY - height), ImGuiCond_Always, ImVec2(1.0f, 1.0f)); + Begin(windowName, nullptr, kNotifyToastFlags); + BringWindowToDisplayFront(GetCurrentWindow()); + + // Here we render the toast content + { + PushTextWrapPos(vpSize.x / 3.0f); // We want to support multi-line text, this will wrap the text after 1/3 of the screen width + + bool wasTitleRendered = false; + + // If an icon is set + if (!::IsNullOrEmpty(icon)) { + // Render icon text + PushStyleColor(ImGuiCol_Text, textColor); + TextUnformatted(icon); + PopStyleColor(); + wasTitleRendered = true; + } + + // If a title is set + if (!::IsNullOrEmpty(title)) { + // If a title and an icon is set, we want to render on same line + if (!::IsNullOrEmpty(icon)) + SameLine(); + + TextUnformatted(title); // Render title text + wasTitleRendered = true; + } else if (!::IsNullOrEmpty(defaultTitle)) { + if (!::IsNullOrEmpty(icon)) + SameLine(); + + TextUnformatted(defaultTitle); // Render default title text (ImGuiToastType_Success -> "Success", etc...) + wasTitleRendered = true; + } + + // In case ANYTHING was rendered in the top, we want to add a small padding so the text (or icon) looks centered vertically + if (wasTitleRendered && !::IsNullOrEmpty(content)) { + SetCursorPosY(GetCursorPosY() + 5.0f); // Must be a better way to do this!!!! + } + + // If a content is set + if (!::IsNullOrEmpty(content)) { + if (wasTitleRendered) { + Separator(); + } + + TextUnformatted(content); // Render content text + } + + PopTextWrapPos(); + } + + // Save height for next toasts + height += GetWindowHeight() + kNotifyPaddingMessageY; + + End(); + } } -- cgit v1.2.3-70-g09d2