From fcd219bf223afb16e0e2410e93f6ddb7d9a9ac68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Tue, 11 Jul 2023 19:32:41 +0200 Subject: [PATCH] Support showing multiple different error messages in editor Previously the same message popup context was used for all error messages. While multiple message popups could be opened at the same time, the message would always be the same for all, as the same buffer was used for all popups. This is fixed by creating and destroying the message popup contexts dynamically, so there can be any number of message popups with different messages. Additionally, if a popup with an identical message is already open, it will first be closed and then reopened at the new position, to prevent duplicate message popups. --- src/game/editor/editor.cpp | 39 ++++++++++++++++++++++++++++++++++---- src/game/editor/editor.h | 10 ++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 969cdf436..12f390b1c 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -5252,13 +5252,27 @@ void CEditor::InvokeFileDialog(int StorageType, int FileType, const char *pTitle void CEditor::ShowFileDialogError(const char *pFormat, ...) { - static CUI::SMessagePopupContext s_MessagePopupContext; - s_MessagePopupContext.ErrorColor(); + char aMessage[1024]; va_list VarArgs; va_start(VarArgs, pFormat); - str_format_v(s_MessagePopupContext.m_aMessage, sizeof(s_MessagePopupContext.m_aMessage), pFormat, VarArgs); + str_format_v(aMessage, sizeof(aMessage), pFormat, VarArgs); va_end(VarArgs); - UI()->ShowPopupMessage(UI()->MouseX(), UI()->MouseY(), &s_MessagePopupContext); + + auto ContextIterator = m_PopupMessageContexts.find(aMessage); + CUI::SMessagePopupContext *pContext; + if(ContextIterator != m_PopupMessageContexts.end()) + { + pContext = ContextIterator->second; + UI()->ClosePopupMenu(pContext); + } + else + { + pContext = new CUI::SMessagePopupContext(); + pContext->ErrorColor(); + str_copy(pContext->m_aMessage, aMessage); + m_PopupMessageContexts[pContext->m_aMessage] = pContext; + } + UI()->ShowPopupMessage(UI()->MouseX(), UI()->MouseY(), pContext); } void CEditor::RenderModebar(CUIRect View) @@ -6504,6 +6518,7 @@ void CEditor::Render() // Popup menus must be rendered before the statusbar, because UI elements in // popup menus can set tooltips, which are rendered in the status bar. UI()->RenderPopupMenus(); + FreeDynamicPopupMenus(); if(m_GuiActive) RenderStatusbar(StatusBar); @@ -6544,6 +6559,22 @@ void CEditor::RenderSavingIndicator(CUIRect View) UI()->DoLabel(&Label, "Saving…", 24.0f, TEXTALIGN_BR); } +void CEditor::FreeDynamicPopupMenus() +{ + auto Iterator = m_PopupMessageContexts.begin(); + while(Iterator != m_PopupMessageContexts.end()) + { + if(!UI()->IsPopupOpen(Iterator->second)) + { + CUI::SMessagePopupContext *pContext = Iterator->second; + Iterator = m_PopupMessageContexts.erase(Iterator); + delete pContext; + } + else + ++Iterator; + } +} + void CEditor::RenderMousePointer() { if(!m_ShowMousePointer) diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index 640dbcbef..d9ab9e35d 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -890,6 +891,14 @@ public: void InvokeFileDialog(int StorageType, int FileType, const char *pTitle, const char *pButtonText, const char *pBasepath, const char *pDefaultName, bool (*pfnFunc)(const char *pFilename, int StorageType, void *pUser), void *pUser); + struct SStringKeyComparator + { + bool operator()(char const *pLhs, char const *pRhs) const + { + return str_comp(pLhs, pRhs) < 0; + } + }; + std::map m_PopupMessageContexts; void ShowFileDialogError(const char *pFormat, ...) GNUC_ATTRIBUTE((format(printf, 2, 3))); @@ -902,6 +911,7 @@ public: void RenderPressedKeys(CUIRect View); void RenderSavingIndicator(CUIRect View); + void FreeDynamicPopupMenus(); void RenderMousePointer(); void ResetMenuBackgroundPositions();