6503: Move generic popup handling to UI (port from editor and upstream) r=def- a=Robyt3

Support using editor popup rendering in game client.

Support unlimited number of popup menus instead of maximum of 8.

Fix non-active popups handling key events. Add `Active` parameter to popup function, so key events are only processed by the active (top-most) popup. Previously the "New folder" popup could be confirmed with enter while an error message is shown, which causes multiple error messages to stack.

Allow popups to close without closing their child popups. Previously a popup could not open another popup and close itself immediately afterwards, as this was causing the newly opened popup to be closed instead.

Support using return/enter keys to confirm binary choice popups and to close message popups for more convenient usage.

## Checklist

- [X] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test (especially base/) or added coverage to integration test
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: Robert Müller <robytemueller@gmail.com>
This commit is contained in:
bors[bot] 2023-04-07 17:29:41 +00:00 committed by GitHub
commit 3bc27c2535
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 663 additions and 495 deletions

View file

@ -1455,9 +1455,6 @@ int CMenus::Render()
}
else
{
// make sure that other windows doesn't do anything funnay!
//UI()->SetHotItem(0);
//UI()->SetActiveItem(nullptr);
char aBuf[1536];
const char *pTitle = "";
const char *pExtraText = "";
@ -2162,6 +2159,9 @@ int CMenus::Render()
if(m_Popup == POPUP_NONE)
UI()->SetActiveItem(nullptr);
}
UI()->RenderPopupMenus();
return 0;
}

View file

@ -12,6 +12,7 @@
#include <engine/shared/config.h>
#include <game/client/lineinput.h>
#include <game/localization.h>
#include <limits>
@ -1148,6 +1149,19 @@ bool CUI::DoClearableEditBox(const void *pID, const void *pClearID, const CUIRec
return ReturnValue;
}
int CUI::DoButton_PopupMenu(CButtonContainer *pButtonContainer, const char *pText, const CUIRect *pRect, int Align)
{
pRect->Draw(ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f * ButtonColorMul(pButtonContainer)), IGraphics::CORNER_ALL, 3.0f);
CUIRect Label;
pRect->VMargin(2.0f, &Label);
SLabelProperties Props;
Props.m_AlignVertically = 0;
DoLabel(&Label, pText, 10.0f, Align, Props);
return DoButtonLogic(pButtonContainer, 0, pRect);
}
float CUI::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current)
{
Current = clamp(Current, 0.0f, 1.0f);
@ -1390,3 +1404,248 @@ void CUI::DoScrollbarOptionLabeled(const void *pID, int *pOption, const CUIRect
*pOption = clamp(Value, 0, Max);
}
void CUI::DoPopupMenu(const SPopupMenuId *pID, int X, int Y, int Width, int Height, void *pContext, FPopupMenuFunction pfnFunc, int Corners)
{
constexpr float Margin = SPopupMenu::POPUP_BORDER + SPopupMenu::POPUP_MARGIN;
if(X + Width > Screen()->w - Margin)
X = maximum<float>(X - Width, Margin);
if(Y + Height > Screen()->h - Margin)
Y = maximum<float>(Y - Height, Margin);
m_vPopupMenus.emplace_back();
SPopupMenu *pNewMenu = &m_vPopupMenus.back();
pNewMenu->m_pID = pID;
pNewMenu->m_Rect.x = X;
pNewMenu->m_Rect.y = Y;
pNewMenu->m_Rect.w = Width;
pNewMenu->m_Rect.h = Height;
pNewMenu->m_Corners = Corners;
pNewMenu->m_pContext = pContext;
pNewMenu->m_pfnFunc = pfnFunc;
}
void CUI::RenderPopupMenus()
{
for(size_t i = 0; i < m_vPopupMenus.size(); ++i)
{
const SPopupMenu &PopupMenu = m_vPopupMenus[i];
const bool Inside = MouseInside(&PopupMenu.m_Rect);
const bool Active = i == m_vPopupMenus.size() - 1;
if(Active)
SetHotItem(PopupMenu.m_pID);
if(CheckActiveItem(PopupMenu.m_pID))
{
if(!MouseButton(0))
{
if(!Inside)
{
ClosePopupMenu(PopupMenu.m_pID);
}
SetActiveItem(nullptr);
}
}
else if(HotItem() == PopupMenu.m_pID)
{
if(MouseButton(0))
SetActiveItem(PopupMenu.m_pID);
}
CUIRect PopupRect = PopupMenu.m_Rect;
PopupRect.Draw(ColorRGBA(0.5f, 0.5f, 0.5f, 0.75f), PopupMenu.m_Corners, 3.0f);
PopupRect.Margin(SPopupMenu::POPUP_BORDER, &PopupRect);
PopupRect.Draw(ColorRGBA(0.0f, 0.0f, 0.0f, 0.75f), PopupMenu.m_Corners, 3.0f);
PopupRect.Margin(SPopupMenu::POPUP_MARGIN, &PopupRect);
EPopupMenuFunctionResult Result = PopupMenu.m_pfnFunc(PopupMenu.m_pContext, PopupRect, Active);
if(Result != POPUP_KEEP_OPEN || (Active && ConsumeHotkey(HOTKEY_ESCAPE)))
ClosePopupMenu(PopupMenu.m_pID, Result == POPUP_CLOSE_CURRENT_AND_DESCENDANTS);
}
}
void CUI::ClosePopupMenu(const SPopupMenuId *pID, bool IncludeDescendants)
{
auto PopupMenuToClose = std::find_if(m_vPopupMenus.begin(), m_vPopupMenus.end(), [pID](const SPopupMenu PopupMenu) { return PopupMenu.m_pID == pID; });
if(PopupMenuToClose != m_vPopupMenus.end())
{
if(IncludeDescendants)
m_vPopupMenus.erase(PopupMenuToClose, m_vPopupMenus.end());
else
m_vPopupMenus.erase(PopupMenuToClose);
SetActiveItem(nullptr);
if(m_pfnPopupMenuClosedCallback)
m_pfnPopupMenuClosedCallback();
}
}
void CUI::ClosePopupMenus()
{
if(m_vPopupMenus.empty())
return;
m_vPopupMenus.clear();
SetActiveItem(nullptr);
if(m_pfnPopupMenuClosedCallback)
m_pfnPopupMenuClosedCallback();
}
bool CUI::IsPopupOpen() const
{
return !m_vPopupMenus.empty();
}
bool CUI::IsPopupOpen(const SPopupMenuId *pID) const
{
return std::any_of(m_vPopupMenus.begin(), m_vPopupMenus.end(), [pID](const SPopupMenu PopupMenu) { return PopupMenu.m_pID == pID; });
}
bool CUI::IsPopupHovered() const
{
return std::any_of(m_vPopupMenus.begin(), m_vPopupMenus.end(), [this](const SPopupMenu PopupMenu) { return MouseHovered(&PopupMenu.m_Rect); });
}
void CUI::SetPopupMenuClosedCallback(FPopupMenuClosedCallback pfnCallback)
{
m_pfnPopupMenuClosedCallback = std::move(pfnCallback);
}
void CUI::SMessagePopupContext::DefaultColor(ITextRender *pTextRender)
{
m_TextColor = pTextRender->DefaultTextColor();
}
void CUI::SMessagePopupContext::ErrorColor()
{
m_TextColor = ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f);
}
CUI::EPopupMenuFunctionResult CUI::PopupMessage(void *pContext, CUIRect View, bool Active)
{
SMessagePopupContext *pMessagePopup = static_cast<SMessagePopupContext *>(pContext);
CUI *pUI = pMessagePopup->m_pUI;
CTextCursor Cursor;
pUI->TextRender()->SetCursor(&Cursor, View.x, View.y, SMessagePopupContext::POPUP_FONT_SIZE, TEXTFLAG_RENDER);
Cursor.m_LineWidth = View.w;
pUI->TextRender()->TextColor(pMessagePopup->m_TextColor);
pUI->TextRender()->TextEx(&Cursor, pMessagePopup->m_aMessage, -1);
pUI->TextRender()->TextColor(pUI->TextRender()->DefaultTextColor());
return (Active && pUI->ConsumeHotkey(HOTKEY_ENTER)) ? CUI::POPUP_CLOSE_CURRENT : CUI::POPUP_KEEP_OPEN;
}
CUI::SConfirmPopupContext::SConfirmPopupContext()
{
Reset();
}
void CUI::SConfirmPopupContext::Reset()
{
m_Result = SConfirmPopupContext::UNSET;
}
void CUI::SConfirmPopupContext::YesNoButtons()
{
str_copy(m_aPositiveButtonLabel, Localize("Yes"));
str_copy(m_aNegativeButtonLabel, Localize("No"));
}
void CUI::ShowPopupConfirm(float X, float Y, SConfirmPopupContext *pContext)
{
const float TextWidth = minimum(TextRender()->TextWidth(SConfirmPopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, -1, -1.0f), SConfirmPopupContext::POPUP_MAX_WIDTH);
const int LineCount = TextRender()->TextLineCount(SConfirmPopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, TextWidth);
const float PopupHeight = LineCount * SConfirmPopupContext::POPUP_FONT_SIZE + SConfirmPopupContext::POPUP_BUTTON_HEIGHT + SConfirmPopupContext::POPUP_BUTTON_SPACING + 10.0f;
pContext->m_pUI = this;
pContext->m_Result = SConfirmPopupContext::UNSET;
DoPopupMenu(pContext, X, Y, TextWidth + 10.0f, PopupHeight, pContext, PopupConfirm);
}
CUI::EPopupMenuFunctionResult CUI::PopupConfirm(void *pContext, CUIRect View, bool Active)
{
SConfirmPopupContext *pConfirmPopup = static_cast<SConfirmPopupContext *>(pContext);
CUI *pUI = pConfirmPopup->m_pUI;
CUIRect Label, ButtonBar, CancelButton, ConfirmButton;
View.HSplitBottom(SConfirmPopupContext::POPUP_BUTTON_HEIGHT, &Label, &ButtonBar);
ButtonBar.VSplitMid(&CancelButton, &ConfirmButton, SConfirmPopupContext::POPUP_BUTTON_SPACING);
CTextCursor Cursor;
pUI->TextRender()->SetCursor(&Cursor, Label.x, Label.y, SConfirmPopupContext::POPUP_FONT_SIZE, TEXTFLAG_RENDER);
Cursor.m_LineWidth = Label.w;
pUI->TextRender()->TextEx(&Cursor, pConfirmPopup->m_aMessage, -1);
static CButtonContainer s_CancelButton;
if(pUI->DoButton_PopupMenu(&s_CancelButton, pConfirmPopup->m_aNegativeButtonLabel, &CancelButton, TEXTALIGN_CENTER))
{
pConfirmPopup->m_Result = SConfirmPopupContext::CANCELED;
return CUI::POPUP_CLOSE_CURRENT;
}
static CButtonContainer s_ConfirmButton;
if(pUI->DoButton_PopupMenu(&s_ConfirmButton, pConfirmPopup->m_aPositiveButtonLabel, &ConfirmButton, TEXTALIGN_CENTER) || (Active && pUI->ConsumeHotkey(HOTKEY_ENTER)))
{
pConfirmPopup->m_Result = SConfirmPopupContext::CONFIRMED;
return CUI::POPUP_CLOSE_CURRENT;
}
return CUI::POPUP_KEEP_OPEN;
}
void CUI::ShowPopupMessage(float X, float Y, SMessagePopupContext *pContext)
{
const float TextWidth = minimum(TextRender()->TextWidth(SMessagePopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, -1, -1.0f), SMessagePopupContext::POPUP_MAX_WIDTH);
const int LineCount = TextRender()->TextLineCount(SMessagePopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, TextWidth);
pContext->m_pUI = this;
DoPopupMenu(pContext, X, Y, TextWidth + 10.0f, LineCount * SMessagePopupContext::POPUP_FONT_SIZE + 10.0f, pContext, PopupMessage);
}
CUI::SSelectionPopupContext::SSelectionPopupContext()
{
Reset();
}
void CUI::SSelectionPopupContext::Reset()
{
m_pSelection = nullptr;
m_Entries.clear();
}
CUI::EPopupMenuFunctionResult CUI::PopupSelection(void *pContext, CUIRect View, bool Active)
{
SSelectionPopupContext *pSelectionPopup = static_cast<SSelectionPopupContext *>(pContext);
CUI *pUI = pSelectionPopup->m_pUI;
CUIRect Slot;
const int LineCount = pUI->TextRender()->TextLineCount(SSelectionPopupContext::POPUP_FONT_SIZE, pSelectionPopup->m_aMessage, SSelectionPopupContext::POPUP_MAX_WIDTH);
View.HSplitTop(LineCount * SSelectionPopupContext::POPUP_FONT_SIZE, &Slot, &View);
CTextCursor Cursor;
pUI->TextRender()->SetCursor(&Cursor, Slot.x, Slot.y, SSelectionPopupContext::POPUP_FONT_SIZE, TEXTFLAG_RENDER);
Cursor.m_LineWidth = Slot.w;
pUI->TextRender()->TextEx(&Cursor, pSelectionPopup->m_aMessage, -1);
pSelectionPopup->m_vButtonContainers.resize(pSelectionPopup->m_Entries.size());
size_t Index = 0;
for(const auto &Entry : pSelectionPopup->m_Entries)
{
View.HSplitTop(SSelectionPopupContext::POPUP_ENTRY_SPACING, nullptr, &View);
View.HSplitTop(SSelectionPopupContext::POPUP_ENTRY_HEIGHT, &Slot, &View);
if(pUI->DoButton_PopupMenu(&pSelectionPopup->m_vButtonContainers[Index], Entry.c_str(), &Slot, TEXTALIGN_LEFT))
pSelectionPopup->m_pSelection = &Entry;
++Index;
}
return pSelectionPopup->m_pSelection == nullptr ? CUI::POPUP_KEEP_OPEN : CUI::POPUP_CLOSE_CURRENT;
}
void CUI::ShowPopupSelection(float X, float Y, SSelectionPopupContext *pContext)
{
const int LineCount = TextRender()->TextLineCount(SSelectionPopupContext::POPUP_FONT_SIZE, pContext->m_aMessage, SSelectionPopupContext::POPUP_MAX_WIDTH);
const float PopupHeight = LineCount * SSelectionPopupContext::POPUP_FONT_SIZE + pContext->m_Entries.size() * (SSelectionPopupContext::POPUP_ENTRY_HEIGHT + SSelectionPopupContext::POPUP_ENTRY_SPACING) + 10.0f;
pContext->m_pUI = this;
pContext->m_pSelection = nullptr;
DoPopupMenu(pContext, X, Y, SSelectionPopupContext::POPUP_MAX_WIDTH + 10.0f, PopupHeight, pContext, PopupSelection);
}

View file

@ -9,6 +9,7 @@
#include <engine/textrender.h>
#include <chrono>
#include <set>
#include <string>
#include <vector>
@ -177,8 +178,55 @@ class CButtonContainer
{
};
/**
* Type safe UI ID for popup menus.
*/
struct SPopupMenuId
{
};
class CUI
{
public:
/**
* These enum values are returned by popup menu functions to specify the behavior.
*/
enum EPopupMenuFunctionResult
{
/**
* The current popup menu will be kept open.
*/
POPUP_KEEP_OPEN = 0,
/**
* The current popup menu will be closed.
*/
POPUP_CLOSE_CURRENT = 1,
/**
* The current popup menu and all popup menus above it will be closed.
*/
POPUP_CLOSE_CURRENT_AND_DESCENDANTS = 2,
};
/**
* Callback that draws a popup menu.
*
* @param pContext The context object of the popup menu.
* @param View The UI rect where the popup menu's contents should be drawn.
* @param Active Whether this popup is active (the top-most popup).
* Only the active popup should handle key and mouse events.
*
* @return Value from the @link EPopupMenuFunctionResult @endlink enum.
*/
typedef EPopupMenuFunctionResult (*FPopupMenuFunction)(void *pContext, CUIRect View, bool Active);
/**
* Callback that is called when one or more popups are closed.
*/
typedef std::function<void()> FPopupMenuClosedCallback;
private:
bool m_Enabled;
const void *m_pHotItem;
@ -217,6 +265,24 @@ class CUI
std::vector<CUIRect> m_vClips;
void UpdateClipping();
struct SPopupMenu
{
static constexpr float POPUP_BORDER = 1.0f;
static constexpr float POPUP_MARGIN = 4.0f;
const SPopupMenuId *m_pID;
CUIRect m_Rect;
int m_Corners;
void *m_pContext;
FPopupMenuFunction m_pfnFunc;
};
std::vector<SPopupMenu> m_vPopupMenus;
FPopupMenuClosedCallback m_pfnPopupMenuClosedCallback = nullptr;
static CUI::EPopupMenuFunctionResult PopupMessage(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupConfirm(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupSelection(void *pContext, CUIRect View, bool Active);
IClient *m_pClient;
IGraphics *m_pGraphics;
IInput *m_pInput;
@ -326,9 +392,9 @@ public:
void ClearHotkeys() { m_HotkeysPressed = 0; }
bool OnInput(const IInput::CEvent &Event);
float ButtonColorMulActive() { return 0.5f; }
float ButtonColorMulHot() { return 1.5f; }
float ButtonColorMulDefault() { return 1.0f; }
constexpr float ButtonColorMulActive() const { return 0.5f; }
constexpr float ButtonColorMulHot() const { return 1.5f; }
constexpr float ButtonColorMulDefault() const { return 1.0f; }
float ButtonColorMul(const void *pID);
const CUIRect *Screen();
@ -355,6 +421,8 @@ public:
bool DoEditBox(const void *pID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden = false, int Corners = IGraphics::CORNER_ALL, const SUIExEditBoxProperties &Properties = {});
bool DoClearableEditBox(const void *pID, const void *pClearID, const CUIRect *pRect, char *pStr, unsigned StrSize, float FontSize, float *pOffset, bool Hidden = false, int Corners = IGraphics::CORNER_ALL, const SUIExEditBoxProperties &Properties = {});
int DoButton_PopupMenu(CButtonContainer *pButtonContainer, const char *pText, const CUIRect *pRect, int Align);
enum
{
SCROLLBAR_OPTION_INFINITE = 1,
@ -364,6 +432,73 @@ public:
float DoScrollbarH(const void *pID, const CUIRect *pRect, float Current, const ColorRGBA *pColorInner = nullptr);
void DoScrollbarOption(const void *pID, int *pOption, const CUIRect *pRect, const char *pStr, int Min, int Max, const IScrollbarScale *pScale = &ms_LinearScrollbarScale, unsigned Flags = 0u);
void DoScrollbarOptionLabeled(const void *pID, int *pOption, const CUIRect *pRect, const char *pStr, const char **ppLabels, int NumLabels, const IScrollbarScale *pScale = &ms_LinearScrollbarScale);
// popup menu
void DoPopupMenu(const SPopupMenuId *pID, int X, int Y, int Width, int Height, void *pContext, FPopupMenuFunction pfnFunc, int Corners = IGraphics::CORNER_ALL);
void RenderPopupMenus();
void ClosePopupMenu(const SPopupMenuId *pID, bool IncludeDescendants = false);
void ClosePopupMenus();
bool IsPopupOpen() const;
bool IsPopupOpen(const SPopupMenuId *pID) const;
bool IsPopupHovered() const;
void SetPopupMenuClosedCallback(FPopupMenuClosedCallback pfnCallback);
struct SMessagePopupContext : public SPopupMenuId
{
static constexpr float POPUP_MAX_WIDTH = 200.0f;
static constexpr float POPUP_FONT_SIZE = 10.0f;
CUI *m_pUI; // set by CUI when popup is shown
char m_aMessage[1024];
ColorRGBA m_TextColor;
void DefaultColor(class ITextRender *pTextRender);
void ErrorColor();
};
void ShowPopupMessage(float X, float Y, SMessagePopupContext *pContext);
struct SConfirmPopupContext : public SPopupMenuId
{
enum EConfirmationResult
{
UNSET = 0,
CONFIRMED,
CANCELED,
};
static constexpr float POPUP_MAX_WIDTH = 200.0f;
static constexpr float POPUP_FONT_SIZE = 10.0f;
static constexpr float POPUP_BUTTON_HEIGHT = 12.0f;
static constexpr float POPUP_BUTTON_SPACING = 5.0f;
CUI *m_pUI; // set by CUI when popup is shown
char m_aPositiveButtonLabel[128];
char m_aNegativeButtonLabel[128];
char m_aMessage[1024];
EConfirmationResult m_Result;
SConfirmPopupContext();
void Reset();
void YesNoButtons();
};
void ShowPopupConfirm(float X, float Y, SConfirmPopupContext *pContext);
struct SSelectionPopupContext : public SPopupMenuId
{
static constexpr float POPUP_MAX_WIDTH = 300.0f;
static constexpr float POPUP_FONT_SIZE = 10.0f;
static constexpr float POPUP_ENTRY_HEIGHT = 12.0f;
static constexpr float POPUP_ENTRY_SPACING = 5.0f;
CUI *m_pUI; // set by CUI when popup is shown
char m_aMessage[256];
std::set<std::string> m_Entries;
std::vector<CButtonContainer> m_vButtonContainers;
const std::string *m_pSelection;
SSelectionPopupContext();
void Reset();
};
void ShowPopupSelection(float X, float Y, SSelectionPopupContext *pContext);
};
#endif

View file

@ -1021,8 +1021,8 @@ void CEditor::DoToolbar(CUIRect ToolBar)
Storage()->ListDirectory(IStorage::TYPE_ALL, "editor/entities", EntitiesListdirCallback, this);
std::sort(m_vSelectEntitiesFiles.begin(), m_vSelectEntitiesFiles.end());
static int s_PopupEntitiesId;
UiInvokePopupMenu(&s_PopupEntitiesId, 0, Button.x, Button.y + Button.h, 250, m_vSelectEntitiesFiles.size() * 14.0f + 10.0f, PopupEntities);
static SPopupMenuId s_PopupEntitiesId;
UI()->DoPopupMenu(&s_PopupEntitiesId, Button.x, Button.y + Button.h, 250, m_vSelectEntitiesFiles.size() * 14.0f + 10.0f, this, PopupEntities);
}
TB_Top.VSplitLeft(5.0f, nullptr, &TB_Top);
@ -1203,8 +1203,8 @@ void CEditor::DoToolbar(CUIRect ToolBar)
static int s_GotoButton = 0;
if(DoButton_Editor(&s_GotoButton, "Goto XY", 0, &Button, 0, "Go to a specified coordinate point on the map"))
{
static int s_PopupGotoId;
UiInvokePopupMenu(&s_PopupGotoId, 0, Button.x, Button.y + Button.h, 120, 52, PopupGoto);
static SPopupMenuId s_PopupGotoId;
UI()->DoPopupMenu(&s_PopupGotoId, Button.x, Button.y + Button.h, 120, 52, this, PopupGoto);
}
TB_Bottom.VSplitLeft(5.0f, nullptr, &TB_Bottom);
}
@ -1230,7 +1230,7 @@ void CEditor::DoToolbar(CUIRect ToolBar)
if(pS)
{
const char *pButtonName = nullptr;
int (*pfnPopupFunc)(CEditor * pEditor, CUIRect View, void *pContext) = nullptr;
CUI::FPopupMenuFunction pfnPopupFunc = nullptr;
int Rows = 0;
if(pS == m_Map.m_pSwitchLayer)
{
@ -1259,17 +1259,17 @@ void CEditor::DoToolbar(CUIRect ToolBar)
if(pButtonName != nullptr)
{
static char aBuf[64];
str_format(aBuf, sizeof(aBuf), "[ctrl+t] %s", pButtonName);
static char s_aButtonTooltip[64];
str_format(s_aButtonTooltip, sizeof(s_aButtonTooltip), "[ctrl+t] %s", pButtonName);
TB_Bottom.VSplitLeft(60.0f, &Button, &TB_Bottom);
static int s_ModifierButton = 0;
if(DoButton_Ex(&s_ModifierButton, pButtonName, 0, &Button, 0, aBuf, IGraphics::CORNER_ALL) || (m_Dialog == DIALOG_NONE && m_EditBoxActive == 0 && ModPressed && Input()->KeyPress(KEY_T)))
if(DoButton_Ex(&s_ModifierButton, pButtonName, 0, &Button, 0, s_aButtonTooltip, IGraphics::CORNER_ALL) || (m_Dialog == DIALOG_NONE && m_EditBoxActive == 0 && ModPressed && Input()->KeyPress(KEY_T)))
{
static int s_PopupModifierId;
if(!UiPopupExists(&s_PopupModifierId))
static SPopupMenuId s_PopupModifierId;
if(!UI()->IsPopupOpen(&s_PopupModifierId))
{
UiInvokePopupMenu(&s_PopupModifierId, 0, Button.x, Button.y + Button.h, 120, 10.0f + Rows * 13.0f, pfnPopupFunc);
UI()->DoPopupMenu(&s_PopupModifierId, Button.x, Button.y + Button.h, 120, 10.0f + Rows * 13.0f, this, pfnPopupFunc);
}
}
TB_Bottom.VSplitLeft(5.0f, nullptr, &TB_Bottom);
@ -1412,8 +1412,8 @@ void CEditor::DoSoundSource(CSoundSource *pSource, int Index)
{
if(m_vSelectedLayers.size() == 1)
{
static int s_PopupSourceId;
UiInvokePopupMenu(&s_PopupSourceId, 0, UI()->MouseX(), UI()->MouseY(), 120, 200, PopupSource);
static SPopupMenuId s_PopupSourceId;
UI()->DoPopupMenu(&s_PopupSourceId, UI()->MouseX(), UI()->MouseY(), 120, 200, this, PopupSource);
m_LockMouse = false;
}
s_Operation = OP_NONE;
@ -1563,8 +1563,8 @@ void CEditor::DoQuad(CQuad *pQuad, int Index)
{
m_SelectedQuadIndex = FindSelectedQuadIndex(Index);
static int s_PopupQuadId;
UiInvokePopupMenu(&s_PopupQuadId, 0, UI()->MouseX(), UI()->MouseY(), 120, 198, PopupQuad);
static SPopupMenuId s_PopupQuadId;
UI()->DoPopupMenu(&s_PopupQuadId, UI()->MouseX(), UI()->MouseY(), 120, 198, this, PopupQuad);
m_LockMouse = false;
}
s_Operation = OP_NONE;
@ -1776,8 +1776,8 @@ void CEditor::DoQuadPoint(CQuad *pQuad, int QuadIndex, int V)
m_SelectedQuadPoint = V;
m_SelectedQuadIndex = FindSelectedQuadIndex(QuadIndex);
static int s_PopupPointId;
UiInvokePopupMenu(&s_PopupPointId, 0, UI()->MouseX(), UI()->MouseY(), 120, 150, PopupPoint);
static SPopupMenuId s_PopupPointId;
UI()->DoPopupMenu(&s_PopupPointId, UI()->MouseX(), UI()->MouseY(), 120, 150, this, PopupPoint);
}
UI()->SetActiveItem(nullptr);
}
@ -3272,8 +3272,8 @@ int CEditor::DoProperties(CUIRect *pToolBox, CProperty *pProps, int *pIDs, int *
if(DoButton_ColorPicker(&s_ColorPicker, &ColorBox, &ColorPick))
{
ms_PickerColor = color_cast<ColorHSVA>(ColorPick);
static int s_PopupColorPickerId;
UiInvokePopupMenu(&s_PopupColorPickerId, 0, UI()->MouseX(), UI()->MouseY(), 180, 150, PopupColorPicker);
static SPopupMenuId s_PopupColorPickerId;
UI()->DoPopupMenu(&s_PopupColorPickerId, UI()->MouseX(), UI()->MouseY(), 180, 150, this, PopupColorPicker);
}
if(UI()->HotItem() == &ms_SVPicker || UI()->HotItem() == &ms_HuePicker)
@ -3605,8 +3605,8 @@ void CEditor::RenderLayers(CUIRect LayersBox)
if(Result == 2)
{
static int s_PopupGroupId;
UiInvokePopupMenu(&s_PopupGroupId, 0, UI()->MouseX(), UI()->MouseY(), 145, 256, PopupGroup);
static SPopupMenuId s_PopupGroupId;
UI()->DoPopupMenu(&s_PopupGroupId, UI()->MouseX(), UI()->MouseY(), 145, 256, this, PopupGroup);
}
if(!m_Map.m_vpGroups[g]->m_vpLayers.empty() && Input()->MouseDoubleClick())
@ -3760,7 +3760,8 @@ void CEditor::RenderLayers(CUIRect LayersBox)
if(s_Operation == OP_CLICK && Clicked)
{
static CLayerPopupContext s_LayerPopupContext = {};
static SLayerPopupContext s_LayerPopupContext = {};
s_LayerPopupContext.m_pEditor = this;
if(Result == 1)
{
if(Input()->ShiftIsPressed() && m_SelectedGroup == g)
@ -3801,7 +3802,7 @@ void CEditor::RenderLayers(CUIRect LayersBox)
else
s_LayerPopupContext.m_vpLayers.clear();
UiInvokePopupMenu(&s_LayerPopupContext, 0, UI()->MouseX(), UI()->MouseY(), 120, 320, PopupLayer, &s_LayerPopupContext);
UI()->DoPopupMenu(&s_LayerPopupContext, UI()->MouseX(), UI()->MouseY(), 120, 320, &s_LayerPopupContext, PopupLayer);
}
s_Operation = OP_NONE;
@ -4460,8 +4461,8 @@ void CEditor::RenderImagesList(CUIRect ToolBox)
{
const CEditorImage *pImg = m_Map.m_vpImages[m_SelectedImage];
const int Height = pImg->m_External || IsVanillaImage(pImg->m_aName) ? 73 : 56;
static int s_PopupImageId;
UiInvokePopupMenu(&s_PopupImageId, 0, UI()->MouseX(), UI()->MouseY(), 120, Height, PopupImage);
static SPopupMenuId s_PopupImageId;
UI()->DoPopupMenu(&s_PopupImageId, UI()->MouseX(), UI()->MouseY(), 120, Height, this, PopupImage);
}
}
}
@ -4578,8 +4579,8 @@ void CEditor::RenderSounds(CUIRect ToolBox)
if(Result == 2)
{
static int s_PopupSoundId;
UiInvokePopupMenu(&s_PopupSoundId, 0, UI()->MouseX(), UI()->MouseY(), 120, 56, PopupSound);
static SPopupMenuId s_PopupSoundId;
UI()->DoPopupMenu(&s_PopupSoundId, UI()->MouseX(), UI()->MouseY(), 120, 56, this, PopupSound);
}
}
}
@ -4751,7 +4752,7 @@ void CEditor::RenderFileDialog()
// filebox
static CListBox s_ListBox;
static bool s_ListBoxUsed = false;
s_ListBoxUsed = !UiPopupOpen();
s_ListBoxUsed = !UI()->IsPopupOpen();
if(m_FileDialogStorageType == IStorage::TYPE_SAVE)
{
@ -5049,16 +5050,17 @@ void CEditor::RenderFileDialog()
ButtonBar.VSplitRight(ButtonSpacing, &ButtonBar, nullptr);
ButtonBar.VSplitRight(50.0f, &ButtonBar, &Button);
static SConfirmPopupContext s_ConfirmDeletePopupContext;
static CUI::SConfirmPopupContext s_ConfirmDeletePopupContext;
if(m_FilesSelectedIndex >= 0 && m_vpFilteredFileList[m_FilesSelectedIndex]->m_StorageType == IStorage::TYPE_SAVE && !m_vpFilteredFileList[m_FilesSelectedIndex]->m_IsLink && str_comp(m_vpFilteredFileList[m_FilesSelectedIndex]->m_aFilename, "..") != 0)
{
if(DoButton_Editor(&s_DeleteButton, "Delete", 0, &Button, 0, nullptr) || (s_ListBoxUsed && UI()->ConsumeHotkey(CUI::HOTKEY_DELETE)))
{
s_ConfirmDeletePopupContext.Reset();
s_ConfirmDeletePopupContext.YesNoButtons();
str_format(s_ConfirmDeletePopupContext.m_aMessage, sizeof(s_ConfirmDeletePopupContext.m_aMessage), "Are you sure that you want to delete the %s '%s/%s'?", IsDir ? "folder" : "file", m_pFileDialogPath, m_vpFilteredFileList[m_FilesSelectedIndex]->m_aFilename);
ShowPopupConfirm(UI()->MouseX(), UI()->MouseY(), &s_ConfirmDeletePopupContext);
UI()->ShowPopupConfirm(UI()->MouseX(), UI()->MouseY(), &s_ConfirmDeletePopupContext);
}
if(s_ConfirmDeletePopupContext.m_Result == SConfirmPopupContext::CONFIRMED)
if(s_ConfirmDeletePopupContext.m_Result == CUI::SConfirmPopupContext::CONFIRMED)
{
char aDeleteFilePath[IO_MAX_PATH_LENGTH];
str_format(aDeleteFilePath, sizeof(aDeleteFilePath), "%s/%s", m_pFileDialogPath, m_vpFilteredFileList[m_FilesSelectedIndex]->m_aFilename);
@ -5077,7 +5079,7 @@ void CEditor::RenderFileDialog()
ShowFileDialogError("Failed to delete file '%s'.", aDeleteFilePath);
}
}
if(s_ConfirmDeletePopupContext.m_Result != SConfirmPopupContext::UNSET)
if(s_ConfirmDeletePopupContext.m_Result != CUI::SConfirmPopupContext::UNSET)
s_ConfirmDeletePopupContext.Reset();
}
else
@ -5089,10 +5091,10 @@ void CEditor::RenderFileDialog()
if(DoButton_Editor(&s_NewFolderButton, "New folder", 0, &Button, 0, nullptr))
{
m_aFileDialogNewFolderName[0] = 0;
static int s_PopupNewFolderId;
static SPopupMenuId s_PopupNewFolderId;
constexpr float PopupWidth = 400.0f;
constexpr float PopupHeight = 110.0f;
UiInvokePopupMenu(&s_PopupNewFolderId, 0, Width / 2.0f - PopupWidth / 2.0f, Height / 2.0f - PopupHeight / 2.0f, PopupWidth, PopupHeight, PopupNewFolder);
UI()->DoPopupMenu(&s_PopupNewFolderId, Width / 2.0f - PopupWidth / 2.0f, Height / 2.0f - PopupHeight / 2.0f, PopupWidth, PopupHeight, this, PopupNewFolder);
UI()->SetActiveItem(nullptr);
}
}
@ -5163,7 +5165,7 @@ void CEditor::InvokeFileDialog(int StorageType, int FileType, const char *pTitle
const char *pBasePath, const char *pDefaultName,
bool (*pfnFunc)(const char *pFileName, int StorageType, void *pUser), void *pUser)
{
UiClosePopupMenus();
UI()->ClosePopupMenus();
m_FileDialogStorageType = StorageType;
m_pFileDialogTitle = pTitle;
m_pFileDialogButtonText = pButtonText;
@ -5191,13 +5193,13 @@ void CEditor::InvokeFileDialog(int StorageType, int FileType, const char *pTitle
void CEditor::ShowFileDialogError(const char *pFormat, ...)
{
static SMessagePopupContext s_MessagePopupContext;
static CUI::SMessagePopupContext s_MessagePopupContext;
s_MessagePopupContext.ErrorColor();
va_list VarArgs;
va_start(VarArgs, pFormat);
str_format_v(s_MessagePopupContext.m_aMessage, sizeof(s_MessagePopupContext.m_aMessage), pFormat, VarArgs);
va_end(VarArgs);
ShowPopupMessage(UI()->MouseX(), UI()->MouseY(), &s_MessagePopupContext);
UI()->ShowPopupMessage(UI()->MouseX(), UI()->MouseY(), &s_MessagePopupContext);
}
void CEditor::RenderModebar(CUIRect View)
@ -6029,7 +6031,10 @@ void CEditor::RenderMenubar(CUIRect MenuBar)
static int s_FileButton = 0;
MenuBar.VSplitLeft(60.0f, &FileButton, &MenuBar);
if(DoButton_Menu(&s_FileButton, "File", 0, &FileButton, 0, nullptr))
UiInvokePopupMenu(&s_FileButton, 1, FileButton.x, FileButton.y + FileButton.h - 1.0f, 120.0f, 174.0f, PopupMenuFile, this);
{
static SPopupMenuId s_PopupMenuFileId;
UI()->DoPopupMenu(&s_PopupMenuFileId, FileButton.x, FileButton.y + FileButton.h - 1.0f, 120.0f, 174.0f, this, PopupMenuFile, IGraphics::CORNER_R | IGraphics::CORNER_B);
}
MenuBar.VSplitLeft(5.0f, nullptr, &MenuBar);
@ -6037,7 +6042,10 @@ void CEditor::RenderMenubar(CUIRect MenuBar)
static int s_ToolsButton = 0;
MenuBar.VSplitLeft(60.0f, &ToolsButton, &MenuBar);
if(DoButton_Menu(&s_ToolsButton, "Tools", 0, &ToolsButton, 0, nullptr))
UiInvokePopupMenu(&s_ToolsButton, 1, ToolsButton.x, ToolsButton.y + ToolsButton.h - 1.0f, 200.0f, 22.0f, PopupMenuTools, this);
{
static SPopupMenuId s_PopupMenuToolsId;
UI()->DoPopupMenu(&s_PopupMenuToolsId, ToolsButton.x, ToolsButton.y + ToolsButton.h - 1.0f, 200.0f, 22.0f, this, PopupMenuTools, IGraphics::CORNER_R | IGraphics::CORNER_B);
}
CUIRect Info, Close;
MenuBar.VSplitLeft(5.0f, nullptr, &MenuBar);
@ -6055,7 +6063,7 @@ void CEditor::RenderMenubar(CUIRect MenuBar)
UI()->DoLabel(&Info, aBuf, 10.0f, TEXTALIGN_RIGHT);
static int s_CloseButton = 0;
if(DoButton_Editor(&s_CloseButton, "×", 0, &Close, 0, "Exits from the editor", 0) || (m_Dialog == DIALOG_NONE && !UiPopupOpen() && !m_PopupEventActivated && Input()->KeyPress(KEY_ESCAPE)))
if(DoButton_Editor(&s_CloseButton, "×", 0, &Close, 0, "Exits from the editor", 0) || (m_Dialog == DIALOG_NONE && !UI()->IsPopupOpen() && !m_PopupEventActivated && Input()->KeyPress(KEY_ESCAPE)))
g_Config.m_ClEditor = 0;
}
@ -6349,17 +6357,15 @@ void CEditor::Render()
if(m_PopupEventActivated)
{
static int s_PopupEventId;
static SPopupMenuId s_PopupEventId;
constexpr float PopupWidth = 400.0f;
constexpr float PopupHeight = 150.0f;
UiInvokePopupMenu(&s_PopupEventId, 0, Width / 2.0f - PopupWidth / 2.0f, Height / 2.0f - PopupHeight / 2.0f, PopupWidth, PopupHeight, PopupEvent);
UI()->DoPopupMenu(&s_PopupEventId, Width / 2.0f - PopupWidth / 2.0f, Height / 2.0f - PopupHeight / 2.0f, PopupWidth, PopupHeight, this, PopupEvent);
m_PopupEventActivated = false;
m_PopupEventWasActivated = true;
}
UiDoPopupMenu();
if(m_Dialog == DIALOG_NONE && !m_MouseInsidePopup && (!m_GuiActive || UI()->MouseInside(&View)))
if(m_Dialog == DIALOG_NONE && !UI()->IsPopupHovered() && (!m_GuiActive || UI()->MouseInside(&View)))
{
if(Input()->KeyPress(KEY_MOUSE_WHEEL_DOWN))
ChangeZoom(20.0f);
@ -6369,6 +6375,10 @@ void CEditor::Render()
UpdateZoom();
// 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();
if(m_GuiActive)
RenderStatusbar(StatusBar);
@ -6407,8 +6417,6 @@ void CEditor::Render()
Graphics()->QuadsEnd();
Graphics()->WrapNormal();
}
m_MouseInsidePopup = false;
}
void CEditor::Reset(bool CreateDefault)
@ -6778,6 +6786,10 @@ void CEditor::Init()
m_pStorage = Kernel()->RequestInterface<IStorage>();
m_pSound = Kernel()->RequestInterface<ISound>();
m_UI.Init(Kernel());
m_UI.SetPopupMenuClosedCallback([this]() {
m_LockMouse = false;
m_PopupEventWasActivated = false;
});
m_RenderTools.Init(m_pGraphics, m_pTextRender);
m_Map.m_pEditor = this;

View file

@ -17,7 +17,6 @@
#include "auto_map.h"
#include <chrono>
#include <set>
#include <string>
#include <vector>
@ -156,7 +155,7 @@ public:
virtual bool IsEntitiesLayer() const { return false; }
virtual void Render(bool Tileset = false) {}
virtual int RenderProperties(CUIRect *pToolbox) { return 0; }
virtual CUI::EPopupMenuFunctionResult RenderProperties(CUIRect *pToolbox) { return CUI::POPUP_KEEP_OPEN; }
virtual void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc) {}
virtual void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc) {}
@ -628,7 +627,7 @@ public:
CLayer *Duplicate() const override;
virtual void ShowInfo();
int RenderProperties(CUIRect *pToolbox) override;
CUI::EPopupMenuFunctionResult RenderProperties(CUIRect *pToolbox) override;
struct SCommonPropState
{
@ -642,7 +641,7 @@ public:
int m_Height = -1;
int m_Color = 0;
};
static int RenderCommonProperties(SCommonPropState &State, CEditor *pEditor, CUIRect *pToolbox, std::vector<CLayerTiles *> &vpLayers);
static CUI::EPopupMenuFunctionResult RenderCommonProperties(SCommonPropState &State, CEditor *pEditor, CUIRect *pToolbox, std::vector<CLayerTiles *> &vpLayers);
void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc) override;
void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc) override;
@ -698,7 +697,7 @@ public:
void BrushFlipY() override;
void BrushRotate(float Amount) override;
int RenderProperties(CUIRect *pToolbox) override;
CUI::EPopupMenuFunctionResult RenderProperties(CUIRect *pToolbox) override;
void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc) override;
void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc) override;
@ -719,7 +718,7 @@ public:
CTile GetTile(int x, int y) override;
void SetTile(int x, int y, CTile tile) override;
int RenderProperties(CUIRect *pToolbox) override;
CUI::EPopupMenuFunctionResult RenderProperties(CUIRect *pToolbox) override;
};
class CEditor : public IEditor
@ -798,7 +797,6 @@ public:
m_PopupEventActivated = false;
m_PopupEventWasActivated = false;
m_MouseInsidePopup = false;
m_FileDialogStorageType = 0;
m_FileDialogLastPopulatedStorageType = 0;
@ -957,7 +955,6 @@ public:
int m_PopupEventType;
int m_PopupEventActivated;
int m_PopupEventWasActivated;
bool m_MouseInsidePopup;
bool m_LargeLayerWasWarned;
bool m_PreventUnusedTilesWasWarned;
int m_AllowPlaceUnusedTiles;
@ -1183,92 +1180,37 @@ public:
void RenderGrid(CLayerGroup *pGroup);
void SnapToGrid(float &x, float &y);
void UiInvokePopupMenu(void *pID, int Flags, float X, float Y, float W, float H, int (*pfnFunc)(CEditor *pEditor, CUIRect Rect, void *pContext), void *pContext = nullptr);
void UiDoPopupMenu();
void UiClosePopupMenus(int Menus = 0);
bool UiPopupExists(void *pID);
bool UiPopupOpen();
int UiDoValueSelector(void *pID, CUIRect *pRect, const char *pLabel, int Current, int Min, int Max, int Step, float Scale, const char *pToolTip, bool IsDegree = false, bool IsHex = false, int corners = IGraphics::CORNER_ALL, ColorRGBA *pColor = nullptr, bool ShowValue = true);
static int PopupMenuFile(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupMenuTools(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupGroup(CEditor *pEditor, CUIRect View, void *pContext);
struct CLayerPopupContext
static CUI::EPopupMenuFunctionResult PopupMenuFile(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupMenuTools(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupGroup(void *pContext, CUIRect View, bool Active);
struct SLayerPopupContext : public SPopupMenuId
{
CEditor *m_pEditor;
std::vector<CLayerTiles *> m_vpLayers;
CLayerTiles::SCommonPropState m_CommonPropState;
};
static int PopupLayer(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupQuad(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupPoint(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupNewFolder(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupMapInfo(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupEvent(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupSelectImage(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupSelectSound(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupSelectGametileOp(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupImage(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupSelectConfigAutoMap(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupSound(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupSource(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupColorPicker(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupEntities(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupTele(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupSpeedup(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupSwitch(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupTune(CEditor *pEditor, CUIRect View, void *pContext);
static int PopupGoto(CEditor *pEditor, CUIRect View, void *pContext);
struct SMessagePopupContext
{
static constexpr float POPUP_MAX_WIDTH = 200.0f;
static constexpr float POPUP_FONT_SIZE = 10.0f;
char m_aMessage[1024];
ColorRGBA m_TextColor;
void DefaultColor(class ITextRender *pTextRender);
void ErrorColor();
};
static int PopupMessage(CEditor *pEditor, CUIRect View, void *pContext);
void ShowPopupMessage(float X, float Y, SMessagePopupContext *pContext);
struct SConfirmPopupContext
{
enum EConfirmationResult
{
UNSET = 0,
CONFIRMED,
CANCELED
};
static constexpr float POPUP_MAX_WIDTH = 200.0f;
static constexpr float POPUP_FONT_SIZE = 10.0f;
static constexpr float POPUP_BUTTON_HEIGHT = 12.0f;
static constexpr float POPUP_BUTTON_SPACING = 5.0f;
char m_aMessage[256];
EConfirmationResult m_Result;
SConfirmPopupContext();
void Reset();
};
static int PopupConfirm(CEditor *pEditor, CUIRect View, void *pContext);
void ShowPopupConfirm(float X, float Y, SConfirmPopupContext *pContext);
struct SSelectionPopupContext
{
static constexpr float POPUP_MAX_WIDTH = 300.0f;
static constexpr float POPUP_FONT_SIZE = 10.0f;
static constexpr float POPUP_ENTRY_HEIGHT = 12.0f;
static constexpr float POPUP_ENTRY_SPACING = 5.0f;
char m_aMessage[256];
std::set<std::string> m_Entries;
const std::string *m_pSelection;
SSelectionPopupContext();
void Reset();
};
static int PopupSelection(CEditor *pEditor, CUIRect View, void *pContext);
void ShowPopupSelection(float X, float Y, SSelectionPopupContext *pContext);
static CUI::EPopupMenuFunctionResult PopupLayer(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupQuad(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupSource(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupPoint(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupImage(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupSound(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupNewFolder(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupMapInfo(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupEvent(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupSelectImage(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupSelectSound(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupSelectGametileOp(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupSelectConfigAutoMap(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupTele(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupSpeedup(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupSwitch(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupTune(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupGoto(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupColorPicker(void *pContext, CUIRect View, bool Active);
static CUI::EPopupMenuFunctionResult PopupEntities(void *pContext, CUIRect View, bool Active);
static bool CallbackOpenMap(const char *pFileName, int StorageType, void *pUser);
static bool CallbackAppendMap(const char *pFileName, int StorageType, void *pUser);
@ -1552,7 +1494,7 @@ public:
int BrushGrab(CLayerGroup *pBrush, CUIRect Rect) override;
void BrushPlace(CLayer *pBrush, float wx, float wy) override;
int RenderProperties(CUIRect *pToolbox) override;
CUI::EPopupMenuFunctionResult RenderProperties(CUIRect *pToolbox) override;
void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc) override;
void ModifySoundIndex(INDEX_MODIFY_FUNC pfnFunc) override;

View file

@ -64,9 +64,9 @@ void CLayerGame::SetTile(int x, int y, CTile tile)
}
}
int CLayerGame::RenderProperties(CUIRect *pToolbox)
CUI::EPopupMenuFunctionResult CLayerGame::RenderProperties(CUIRect *pToolbox)
{
int r = CLayerTiles::RenderProperties(pToolbox);
const CUI::EPopupMenuFunctionResult Result = CLayerTiles::RenderProperties(pToolbox);
m_Image = -1;
return r;
return Result;
}

View file

@ -218,7 +218,7 @@ void CLayerQuads::GetSize(float *pWidth, float *pHeight)
}
}
int CLayerQuads::RenderProperties(CUIRect *pToolBox)
CUI::EPopupMenuFunctionResult CLayerQuads::RenderProperties(CUIRect *pToolBox)
{
enum
{
@ -235,7 +235,9 @@ int CLayerQuads::RenderProperties(CUIRect *pToolBox)
int NewVal = 0;
int Prop = m_pEditor->DoProperties(pToolBox, aProps, s_aIds, &NewVal);
if(Prop != -1)
{
m_pEditor->m_Map.m_Modified = true;
}
if(Prop == PROP_IMAGE)
{
@ -245,7 +247,7 @@ int CLayerQuads::RenderProperties(CUIRect *pToolBox)
m_Image = -1;
}
return 0;
return CUI::POPUP_KEEP_OPEN;
}
void CLayerQuads::ModifyImageIndex(INDEX_MODIFY_FUNC Func)

View file

@ -182,7 +182,7 @@ void CLayerSounds::BrushPlace(CLayer *pBrush, float wx, float wy)
m_pEditor->m_Map.m_Modified = true;
}
int CLayerSounds::RenderProperties(CUIRect *pToolBox)
CUI::EPopupMenuFunctionResult CLayerSounds::RenderProperties(CUIRect *pToolBox)
{
enum
{
@ -199,7 +199,9 @@ int CLayerSounds::RenderProperties(CUIRect *pToolBox)
int NewVal = 0;
int Prop = m_pEditor->DoProperties(pToolBox, aProps, s_aIds, &NewVal);
if(Prop != -1)
{
m_pEditor->m_Map.m_Modified = true;
}
if(Prop == PROP_SOUND)
{
@ -209,7 +211,7 @@ int CLayerSounds::RenderProperties(CUIRect *pToolBox)
m_Sound = -1;
}
return 0;
return CUI::POPUP_KEEP_OPEN;
}
void CLayerSounds::ModifySoundIndex(INDEX_MODIFY_FUNC Func)

View file

@ -685,7 +685,7 @@ void CLayerTiles::ShowInfo()
Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1);
}
int CLayerTiles::RenderProperties(CUIRect *pToolBox)
CUI::EPopupMenuFunctionResult CLayerTiles::RenderProperties(CUIRect *pToolBox)
{
CUIRect Button;
@ -794,7 +794,7 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox)
}
}
return 1;
return CUI::POPUP_CLOSE_CURRENT;
}
}
@ -821,7 +821,7 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox)
if(m_pEditor->DoButton_Editor(&s_AutoMapperButton, "Automap", 0, &Button, 0, "Run the automapper"))
{
m_pEditor->m_Map.m_vpImages[m_Image]->m_AutoMapper.Proceed(this, m_AutoMapperConfig, m_Seed);
return 1;
return CUI::POPUP_CLOSE_CURRENT;
}
}
}
@ -972,10 +972,10 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox)
FlagModified(0, 0, m_Width, m_Height);
}
return 0;
return CUI::POPUP_KEEP_OPEN;
}
int CLayerTiles::RenderCommonProperties(SCommonPropState &State, CEditor *pEditor, CUIRect *pToolbox, std::vector<CLayerTiles *> &vpLayers)
CUI::EPopupMenuFunctionResult CLayerTiles::RenderCommonProperties(SCommonPropState &State, CEditor *pEditor, CUIRect *pToolbox, std::vector<CLayerTiles *> &vpLayers)
{
if(State.m_Modified)
{
@ -1092,7 +1092,7 @@ int CLayerTiles::RenderCommonProperties(SCommonPropState &State, CEditor *pEdito
State.m_Modified |= SCommonPropState::MODIFIED_COLOR;
}
return 0;
return CUI::POPUP_KEEP_OPEN;
}
void CLayerTiles::FlagModified(int x, int y, int w, int h)

File diff suppressed because it is too large Load diff