summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--src/base/system.c15
-rw-r--r--src/base/system.h9
-rw-r--r--src/engine/shared/console.cpp61
-rw-r--r--src/engine/shared/console.h2
-rw-r--r--src/game/client/components/camera.cpp4
-rw-r--r--src/game/client/components/menus.cpp7
-rw-r--r--src/game/client/components/menus.h4
-rw-r--r--src/game/client/components/menus_popups.cpp90
-rw-r--r--src/game/client/ui.cpp124
-rw-r--r--src/game/client/ui.h30
-rw-r--r--src/game/editor/editor.cpp45
-rw-r--r--src/game/editor/editor.h33
-rw-r--r--src/game/editor/popups.cpp236
-rw-r--r--src/test/str.cpp18
15 files changed, 289 insertions, 390 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f7e27eb48..7d68db960 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1469,7 +1469,6 @@ if(CLIENT)
components/menus_demo.cpp
components/menus_ingame.cpp
components/menus_listbox.cpp
- components/menus_popups.cpp
components/menus_scrollregion.cpp
components/menus_settings.cpp
components/menus_start.cpp
diff --git a/src/base/system.c b/src/base/system.c
index 7199cb170..f77760507 100644
--- a/src/base/system.c
+++ b/src/base/system.c
@@ -2705,20 +2705,17 @@ void str_utf8_copy_num(char *dst, const char *src, int dst_size, int num)
str_copy(dst, src, cursor < dst_size ? cursor+1 : dst_size);
}
-void str_utf8_stats(const char *str, int max_size, int *size, int *count)
+void str_utf8_stats(const char *str, int max_size, int max_count, int *size, int *count)
{
*size = 0;
*count = 0;
- while(str[*size] && *size < max_size)
+ while(*size < max_size && *count < max_count)
{
int new_size = str_utf8_forward(str, *size);
- if(new_size != *size)
- {
- if(new_size >= max_size)
- break;
- *size = new_size;
- ++(*count);
- }
+ if(new_size == *size || new_size >= max_size)
+ break;
+ *size = new_size;
+ ++(*count);
}
}
diff --git a/src/base/system.h b/src/base/system.h
index 3c31854f0..0a4cc4764 100644
--- a/src/base/system.h
+++ b/src/base/system.h
@@ -1748,19 +1748,20 @@ void str_utf8_copy_num(char *dst, const char *src, int dst_size, int num);
/*
Function: str_utf8_stats
- Determines the byte size and utf8 character count of a string.
+ Determines the byte size and utf8 character count of a utf8 string.
Parameters:
str - Pointer to the string.
max_size - Maximum number of bytes to count.
+ max_count - Maximum number of utf8 characters to count.
size - Pointer to store size (number of non-zero bytes) of the string.
count - Pointer to store count of utf8 characters of the string.
Remarks:
- - Assumes nothing about the encoding of the string.
- It's the users responsibility to make sure the bounds are aligned.
+ - The string is treated as zero-terminated utf8 string.
+ - It's the user's responsibility to make sure the bounds are aligned.
*/
-void str_utf8_stats(const char *str, int max_size, int *size, int *count);
+void str_utf8_stats(const char *str, int max_size, int max_count, int *size, int *count);
/*
Function: secure_random_init
diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp
index 80f6176de..369087d6d 100644
--- a/src/engine/shared/console.cpp
+++ b/src/engine/shared/console.cpp
@@ -683,9 +683,19 @@ static void StrVariableCommand(IConsole::IResult *pResult, void *pUserData)
}
}
+void CConsole::TraverseChain(FCommandCallback *ppfnCallback, void **ppUserData)
+{
+ while(*ppfnCallback == Con_Chain)
+ {
+ CChain *pChainInfo = static_cast<CChain *>(*ppUserData);
+ *ppfnCallback = pChainInfo->m_pfnCallback;
+ *ppUserData = pChainInfo->m_pCallbackUserData;
+ }
+}
+
void CConsole::Con_EvalIf(IResult *pResult, void *pUserData)
{
- CConsole* pConsole = static_cast<CConsole *>(pUserData);
+ CConsole *pConsole = static_cast<CConsole *>(pUserData);
CCommand *pCommand = pConsole->FindCommand(pResult->GetString(0), pConsole->m_FlagMask);
char aBuf[128];
if(!pCommand)
@@ -694,16 +704,19 @@ void CConsole::Con_EvalIf(IResult *pResult, void *pUserData)
pConsole->Print(OUTPUT_LEVEL_STANDARD, "console", aBuf);
return;
}
+ FCommandCallback pfnCallback = pCommand->m_pfnCallback;
+ void *pCallbackUserData = pCommand->m_pUserData;
+ pConsole->TraverseChain(&pfnCallback, &pCallbackUserData);
CResult Result;
- pCommand->m_pfnCallback(&Result, pCommand->m_pUserData);
+ pfnCallback(&Result, pCallbackUserData);
bool Condition = false;
- if(pCommand->m_pfnCallback == IntVariableCommand)
+ if(pfnCallback == IntVariableCommand)
Condition = Result.m_Value == atoi(pResult->GetString(2));
else
Condition = !str_comp_nocase(Result.m_aValue, pResult->GetString(2));
if(!str_comp(pResult->GetString(1), "!="))
Condition = !Condition;
- else if(str_comp(pResult->GetString(1), "==") && pCommand->m_pfnCallback == StrVariableCommand)
+ else if(str_comp(pResult->GetString(1), "==") && pfnCallback == StrVariableCommand)
pConsole->Print(OUTPUT_LEVEL_STANDARD, "console", "Error: invalid comperator for type string");
else if(!str_comp(pResult->GetString(1), ">"))
Condition = Result.m_Value > atoi(pResult->GetString(2));
@@ -727,22 +740,14 @@ void CConsole::Con_EvalIf(IResult *pResult, void *pUserData)
void CConsole::ConToggle(IConsole::IResult *pResult, void *pUser)
{
- CConsole* pConsole = static_cast<CConsole *>(pUser);
+ CConsole *pConsole = static_cast<CConsole *>(pUser);
char aBuf[128] = {0};
CCommand *pCommand = pConsole->FindCommand(pResult->GetString(0), pConsole->m_FlagMask);
if(pCommand)
{
FCommandCallback pfnCallback = pCommand->m_pfnCallback;
void *pUserData = pCommand->m_pUserData;
-
- // check for chain
- if(pCommand->m_pfnCallback == Con_Chain)
- {
- CChain *pChainInfo = static_cast<CChain *>(pCommand->m_pUserData);
- pfnCallback = pChainInfo->m_pfnCallback;
- pUserData = pChainInfo->m_pCallbackUserData;
- }
-
+ pConsole->TraverseChain(&pfnCallback, &pUserData);
if(pfnCallback == IntVariableCommand)
{
CIntVariableData *pData = static_cast<CIntVariableData *>(pUserData);
@@ -757,26 +762,20 @@ void CConsole::ConToggle(IConsole::IResult *pResult, void *pUser)
else
str_format(aBuf, sizeof(aBuf), "No such command: '%s'.", pResult->GetString(0));
- if(aBuf[0] != 0)
+ if(aBuf[0])
pConsole->Print(OUTPUT_LEVEL_STANDARD, "console", aBuf);
}
void CConsole::ConToggleStroke(IConsole::IResult *pResult, void *pUser)
{
- CConsole* pConsole = static_cast<CConsole *>(pUser);
+ CConsole *pConsole = static_cast<CConsole *>(pUser);
char aBuf[128] = {0};
CCommand *pCommand = pConsole->FindCommand(pResult->GetString(1), pConsole->m_FlagMask);
if(pCommand)
{
FCommandCallback pfnCallback = pCommand->m_pfnCallback;
-
- // check for chain
- if(pCommand->m_pfnCallback == Con_Chain)
- {
- CChain *pChainInfo = static_cast<CChain *>(pCommand->m_pUserData);
- pfnCallback = pChainInfo->m_pfnCallback;
- }
-
+ void *pUserData = pCommand->m_pUserData;
+ pConsole->TraverseChain(&pfnCallback, &pUserData);
if(pfnCallback == IntVariableCommand)
{
int Val = pResult->GetInteger(0)==0 ? pResult->GetInteger(3) : pResult->GetInteger(2);
@@ -790,7 +789,7 @@ void CConsole::ConToggleStroke(IConsole::IResult *pResult, void *pUser)
else
str_format(aBuf, sizeof(aBuf), "No such command: '%s'.", pResult->GetString(1));
- if(aBuf[0] != 0)
+ if(aBuf[0])
pConsole->Print(OUTPUT_LEVEL_STANDARD, "console", aBuf);
}
@@ -834,8 +833,16 @@ CConsole::~CConsole()
{
CCommand *pNext = pCommand->m_pNext;
- if(pCommand->m_pfnCallback == Con_Chain)
- mem_free(static_cast<CChain *>(pCommand->m_pUserData));
+ FCommandCallback pfnCallback = pCommand->m_pfnCallback;
+ void *pUserData = pCommand->m_pUserData;
+ while(pfnCallback == Con_Chain)
+ {
+ CChain *pChainInfo = static_cast<CChain *>(pUserData);
+ pfnCallback = pChainInfo->m_pfnCallback;
+ pUserData = pChainInfo->m_pCallbackUserData;
+ mem_free(pChainInfo);
+ }
+
mem_free(pCommand);
pCommand = pNext;
diff --git a/src/engine/shared/console.h b/src/engine/shared/console.h
index 3ea9c429b..7976d72ed 100644
--- a/src/engine/shared/console.h
+++ b/src/engine/shared/console.h
@@ -54,6 +54,8 @@ class CConsole : public IConsole
CCommand *m_pRecycleList;
CHeap m_TempCommands;
+ void TraverseChain(FCommandCallback *ppfnCallback, void **ppUserData);
+
static void Con_Chain(IResult *pResult, void *pUserData);
static void Con_Echo(IResult *pResult, void *pUserData);
static void Con_Exec(IResult *pResult, void *pUserData);
diff --git a/src/game/client/components/camera.cpp b/src/game/client/components/camera.cpp
index 5a85bbe15..337fa8e7b 100644
--- a/src/game/client/components/camera.cpp
+++ b/src/game/client/components/camera.cpp
@@ -138,8 +138,12 @@ void CCamera::OnRender()
void CCamera::ChangePosition(int PositionNumber)
{
+ if(m_pClient->Client()->State() == IClient::STATE_ONLINE)
+ return; //Do not change Main Menu Camera Positions while we are changing settings in-game
+
if(PositionNumber < 0 || PositionNumber > NUM_POS-1)
return;
+
m_AnimationStartPos = m_Center;
m_RotationCenter = m_Positions[PositionNumber];
m_CurrentPosition = PositionNumber;
diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp
index 5490455ed..f56c9412c 100644
--- a/src/game/client/components/menus.cpp
+++ b/src/game/client/components/menus.cpp
@@ -76,8 +76,6 @@ CMenus::CMenus()
SetMenuPage(PAGE_START);
m_MenuPageOld = PAGE_START;
- m_PopupActive = false;
-
m_aDemoLoadingFile[0] = 0;
m_DemoLoadingPopupRendered = false;
@@ -1166,8 +1164,7 @@ void CMenus::RenderMenu(CUIRect Screen)
}
}
- // do overlay popups
- DoPopupMenu();
+ UI()->RenderPopupMenus();
}
else
{
@@ -1826,7 +1823,7 @@ void CMenus::OnRender()
bool CMenus::CheckHotKey(int Key) const
{
- return !m_KeyReaderIsActive && !m_KeyReaderWasActive && !UI()->IsInputActive() && !m_PopupActive
+ return !m_KeyReaderIsActive && !m_KeyReaderWasActive && !UI()->IsInputActive() && !UI()->IsPopupActive()
&& !Input()->KeyIsPressed(KEY_LSHIFT) && !Input()->KeyIsPressed(KEY_RSHIFT)
&& !Input()->KeyIsPressed(KEY_LCTRL) && !Input()->KeyIsPressed(KEY_RCTRL)
&& !Input()->KeyIsPressed(KEY_LALT)
diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h
index 3a82bec73..bdc8bc73d 100644
--- a/src/game/client/components/menus.h
+++ b/src/game/client/components/menus.h
@@ -278,7 +278,6 @@ private:
bool m_MenuActive;
vec2 m_MousePos;
vec2 m_PrevMousePos;
- bool m_PopupActive;
int m_ActiveListBox;
int m_PopupCountrySelection;
bool m_SkinModified;
@@ -771,9 +770,6 @@ private:
void SetActive(bool Active);
- void InvokePopupMenu(void *pID, int Flags, float X, float Y, float W, float H, int (*pfnFunc)(CMenus *pMenu, CUIRect Rect), void *pExtra=0);
- void DoPopupMenu();
-
// loading
int m_LoadCurrent;
int m_LoadTotal;
diff --git a/src/game/client/components/menus_popups.cpp b/src/game/client/components/menus_popups.cpp
deleted file mode 100644
index ef9e1042c..000000000
--- a/src/game/client/components/menus_popups.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
-/* If you are missing that file, acquire a complete release at teeworlds.com. */
-
-#include <base/tl/array.h>
-
-#include <engine/shared/config.h>
-
-#include <engine/console.h>
-#include <engine/graphics.h>
-#include <engine/input.h>
-#include <engine/keys.h>
-#include <engine/storage.h>
-#include <engine/serverbrowser.h>
-#include <engine/textrender.h>
-
-#include <generated/client_data.h>
-#include <generated/protocol.h>
-
-#include "countryflags.h"
-#include "menus.h"
-
-
-// popup menu handling
-static struct
-{
- CUIRect m_Rect;
- void *m_pId;
- int (*m_pfnFunc)(CMenus *pMenu, CUIRect Rect);
- int m_IsMenu;
- void *m_pExtra;
-} s_Popups;
-
-void CMenus::InvokePopupMenu(void *pID, int Flags, float x, float y, float Width, float Height, int (*pfnFunc)(CMenus *pMenu, CUIRect Rect), void *pExtra)
-{
- if(m_PopupActive)
- return;
- if(x + Width > UI()->Screen()->w)
- x = UI()->Screen()->w - Width;
- if(y + Height > UI()->Screen()->h)
- y = UI()->Screen()->h - Height;
- s_Popups.m_pId = pID;
- s_Popups.m_IsMenu = Flags;
- s_Popups.m_Rect.x = x;
- s_Popups.m_Rect.y = y;
- s_Popups.m_Rect.w = Width;
- s_Popups.m_Rect.h = Height;
- s_Popups.m_pfnFunc = pfnFunc;
- s_Popups.m_pExtra = pExtra;
- m_PopupActive = true;
-}
-
-void CMenus::DoPopupMenu()
-{
- if(m_PopupActive)
- {
- UI()->SetHotItem(&s_Popups.m_pId);
-
- if(UI()->CheckActiveItem(&s_Popups.m_pId))
- {
- if(!UI()->MouseButton(0))
- {
- if(!UI()->MouseHovered(&s_Popups.m_Rect))
- m_PopupActive = false;
- UI()->SetActiveItem(0);
- }
- }
- else if(UI()->HotItem() == &s_Popups.m_pId)
- {
- if(UI()->MouseButton(0))
- UI()->SetActiveItem(&s_Popups.m_pId);
- }
-
- int Corners = CUIRect::CORNER_ALL;
- if(s_Popups.m_IsMenu)
- Corners = CUIRect::CORNER_R|CUIRect::CORNER_B;
-
- CUIRect r = s_Popups.m_Rect;
- r.Draw(vec4(0.5f,0.5f,0.5f,0.75f), 3.0f, Corners);
- r.Margin(1.0f, &r);
- r.Draw(vec4(0,0,0,0.75f), 3.0f, Corners);
- r.Margin(4.0f, &r);
-
- if(s_Popups.m_pfnFunc(this, r))
- m_PopupActive = false;
-
- if(UI()->KeyPress(KEY_ESCAPE))
- m_PopupActive = false;
- }
-}
-
diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp
index ea8d981ac..332d2b529 100644
--- a/src/game/client/ui.cpp
+++ b/src/game/client/ui.cpp
@@ -44,6 +44,8 @@ CUI::CUI()
m_Screen.y = 0;
m_NumClips = 0;
+
+ m_NumPopupMenus = 0;
}
void CUI::Init(class CConfig *pConfig, class IGraphics *pGraphics, class IInput *pInput, class ITextRender *pTextRender)
@@ -491,20 +493,20 @@ void CUI::DoEditBoxOption(CLineInput *pLineInput, const CUIRect *pRect, const ch
float CUI::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current)
{
- // layout
- CUIRect Handle;
- pRect->HSplitTop(minimum(pRect->h/8.0f, 33.0f), &Handle, 0);
- Handle.y += (pRect->h-Handle.h)*Current;
- Handle.VMargin(5.0f, &Handle);
+ Current = clamp(Current, 0.0f, 1.0f);
+ // layout
CUIRect Rail;
pRect->VMargin(5.0f, &Rail);
+ CUIRect Handle;
+ Rail.HSplitTop(clamp(33.0f, Rail.w, Rail.h / 8.0f), &Handle, 0);
+ Handle.y += (Rail.h - Handle.h) * Current;
+
// logic
static float s_OffsetY;
const bool InsideHandle = MouseHovered(&Handle);
const bool InsideRail = MouseHovered(&Rail);
- float ReturnValue = Current;
bool Grabbed = false; // whether to apply the offset
if(CheckActiveItem(pID))
@@ -518,14 +520,14 @@ float CUI::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current)
{
if(MouseButton(0))
{
- s_OffsetY = MouseY()-Handle.y;
+ s_OffsetY = MouseY() - Handle.y;
SetActiveItem(pID);
Grabbed = true;
}
}
else if(MouseButtonClicked(0) && !InsideHandle && InsideRail)
{
- s_OffsetY = Handle.h * 0.5f;
+ s_OffsetY = Handle.h / 2.0f;
SetActiveItem(pID);
Grabbed = true;
}
@@ -535,45 +537,38 @@ float CUI::DoScrollbarV(const void *pID, const CUIRect *pRect, float Current)
SetHotItem(pID);
}
+ float ReturnValue = Current;
if(Grabbed)
{
- const float Min = pRect->y;
- const float Max = pRect->h-Handle.h;
- const float Cur = MouseY()-s_OffsetY;
- ReturnValue = clamp((Cur-Min)/Max, 0.0f, 1.0f);
+ const float Min = Rail.y;
+ const float Max = Rail.h - Handle.h;
+ const float Cur = MouseY() - s_OffsetY;
+ ReturnValue = clamp((Cur - Min) / Max, 0.0f, 1.0f);
}
// render
- Rail.Draw(vec4(1.0f, 1.0f, 1.0f, 0.25f), Rail.w/2.0f);
-
- vec4 Color;
- if(Grabbed)
- Color = vec4(0.9f, 0.9f, 0.9f, 1.0f);
- else if(InsideHandle)
- Color = vec4(1.0f, 1.0f, 1.0f, 1.0f);
- else
- Color = vec4(0.8f, 0.8f, 0.8f, 1.0f);
- Handle.Draw(Color, Handle.w/2.0f);
+ Rail.Draw(vec4(1.0f, 1.0f, 1.0f, 0.25f), Rail.w / 2.0f);
+ Handle.Draw(ScrollBarColorFunction.GetColor(Grabbed, InsideHandle), Handle.w / 2.0f);
return ReturnValue;
}
float CUI::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current)
{
- // layout
- CUIRect Handle;
- pRect->VSplitLeft(maximum(minimum(pRect->w/8.0f, 33.0f), pRect->h), &Handle, 0);
- Handle.x += (pRect->w-Handle.w)*clamp(Current, 0.0f, 1.0f);
- Handle.HMargin(5.0f, &Handle);
+ Current = clamp(Current, 0.0f, 1.0f);
+ // layout
CUIRect Rail;
pRect->HMargin(5.0f, &Rail);
+ CUIRect Handle;
+ Rail.VSplitLeft(clamp(33.0f, Rail.h, Rail.w / 8.0f), &Handle, 0);
+ Handle.x += (Rail.w - Handle.w) * Current;
+
// logic
static float s_OffsetX;
const bool InsideHandle = MouseHovered(&Handle);
const bool InsideRail = MouseHovered(&Rail);
- float ReturnValue = Current;
bool Grabbed = false; // whether to apply the offset
if(CheckActiveItem(pID))
@@ -587,14 +582,14 @@ float CUI::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current)
{
if(MouseButton(0))
{
- s_OffsetX = MouseX()-Handle.x;
+ s_OffsetX = MouseX() - Handle.x;
SetActiveItem(pID);
Grabbed = true;
}
}
else if(MouseButtonClicked(0) && !InsideHandle && InsideRail)
{
- s_OffsetX = Handle.w * 0.5f;
+ s_OffsetX = Handle.w / 2.0f;
SetActiveItem(pID);
Grabbed = true;
}
@@ -604,25 +599,18 @@ float CUI::DoScrollbarH(const void *pID, const CUIRect *pRect, float Current)
SetHotItem(pID);
}
+ float ReturnValue = Current;
if(Grabbed)
{
- const float Min = pRect->x;
- const float Max = pRect->w-Handle.w;
- const float Cur = MouseX()-s_OffsetX;
- ReturnValue = clamp((Cur-Min)/Max, 0.0f, 1.0f);
+ const float Min = Rail.x;
+ const float Max = Rail.w - Handle.w;
+ const float Cur = MouseX() - s_OffsetX;
+ ReturnValue = clamp((Cur - Min) / Max, 0.0f, 1.0f);
}
// render
- Rail.Draw(vec4(1.0f, 1.0f, 1.0f, 0.25f), Rail.h/2.0f);
-
- vec4 Color;
- if(Grabbed)
- Color = vec4(0.9f, 0.9f, 0.9f, 1.0f);
- else if(InsideHandle)
- Color = vec4(1.0f, 1.0f, 1.0f, 1.0f);
- else
- Color = vec4(0.8f, 0.8f, 0.8f, 1.0f);
- Handle.Draw(Color, Handle.h/2.0f);
+ Rail.Draw(vec4(1.0f, 1.0f, 1.0f, 0.25f), Rail.h / 2.0f);
+ Handle.Draw(ScrollBarColorFunction.GetColor(Grabbed, InsideHandle), Handle.h / 2.0f);
return ReturnValue;
}
@@ -726,6 +714,54 @@ float CUI::DrawClientID(float FontSize, vec2 CursorPosition, int ID, const vec4&
return Width + 0.2f * FontSize;
}
+void CUI::DoPopupMenu(int X, int Y, int Width, int Height, void *pContext, bool (*pfnFunc)(void *pContext, CUIRect View), int Corners)
+{
+ dbg_assert(m_NumPopupMenus < MAX_POPUP_MENUS, "max popup menus exceeded");
+
+ if(X + Width > Screen()->w)
+ X = Screen()->w - Width;
+ if(Y + Height > Screen()->h)
+ Y = Screen()->h - Height;
+
+ m_aPopupMenus[m_NumPopupMenus].m_Rect.x = X;
+ m_aPopupMenus[m_NumPopupMenus].m_Rect.y = Y;
+ m_aPopupMenus[m_NumPopupMenus].m_Rect.w = Width;
+ m_aPopupMenus[m_NumPopupMenus].m_Rect.h = Height;
+ m_aPopupMenus[m_NumPopupMenus].m_pContext = pContext;
+ m_aPopupMenus[m_NumPopupMenus].m_pfnFunc = pfnFunc;
+ m_aPopupMenus[m_NumPopupMenus].m_Corners = Corners;
+ m_NumPopupMenus++;
+}
+
+void CUI::RenderPopupMenus()
+{
+ const bool MousePressed = MouseButton(0) || MouseButton(1);
+ static bool s_MousePressed = MousePressed;
+
+ for(unsigned i = 0; i < m_NumPopupMenus; i++)
+ {
+ const bool Inside = MouseInside(&m_aPopupMenus[i].m_Rect);
+ const bool Active = i == m_NumPopupMenus - 1;
+
+ // prevent activation of UI elements outside of active popup
+ if(Active)
+ SetHotItem(&m_aPopupMenus[i]);
+
+ CUIRect PopupRect = m_aPopupMenus[i].m_Rect;
+ PopupRect.Draw(vec4(0.5f, 0.5f, 0.5f, 0.75f), 3.0f, m_aPopupMenus[i].m_Corners);
+ PopupRect.Margin(1.0f, &PopupRect);
+ PopupRect.Draw(vec4(0.0f, 0.0f, 0.0f, 0.75f), 3.0f, m_aPopupMenus[i].m_Corners);
+ PopupRect.Margin(4.0f, &PopupRect);
+
+ if(m_aPopupMenus[i].m_pfnFunc(m_aPopupMenus[i].m_pContext, PopupRect))
+ m_NumPopupMenus = i; // close this popup and all above it
+ if(Active && ((!Inside && s_MousePressed && !MousePressed) || ConsumeHotkey(HOTKEY_ESCAPE)))
+ m_NumPopupMenus--; // close top-most popup by clicking outside and with escape
+ }
+
+ s_MousePressed = MousePressed;
+}
+
float CUI::GetClientIDRectWidth(float FontSize)
{
if(!m_pConfig->m_ClShowUserId)
diff --git a/src/game/client/ui.h b/src/game/client/ui.h
index 2f6800ad5..397886f67 100644
--- a/src/game/client/ui.h
+++ b/src/game/client/ui.h
@@ -87,13 +87,26 @@ public:
return vec4(1.0f, 1.0f, 1.0f, 0.5f);
}
} const LightButtonColorFunction;
+static class CScrollBarColorFunction : public IButtonColorFunction
+{
+public:
+ vec4 GetColor(bool Active, bool Hovered) const
+ {
+ if(Active)
+ return vec4(0.9f, 0.9f, 0.9f, 1.0f);
+ else if(Hovered)
+ return vec4(1.0f, 1.0f, 1.0f, 1.0f);
+ return vec4(0.8f, 0.8f, 0.8f, 1.0f);
+ }
+} const ScrollBarColorFunction;
class CUI
{
enum
{
- MAX_CLIP_NESTING_DEPTH = 16
+ MAX_CLIP_NESTING_DEPTH = 16,
+ MAX_POPUP_MENUS = 8,
};
bool m_Enabled;
@@ -118,6 +131,16 @@ class CUI
unsigned m_NumClips;
void UpdateClipping();
+ class
+ {
+ public:
+ CUIRect m_Rect;
+ int m_Corners;
+ void *m_pContext;
+ bool (*m_pfnFunc)(void *pContext, CUIRect View); // returns true to close popup
+ } m_aPopupMenus[MAX_POPUP_MENUS];
+ unsigned m_NumPopupMenus;
+
class CConfig *m_pConfig;
class IGraphics *m_pGraphics;
class IInput *m_pInput;
@@ -221,6 +244,11 @@ public:
void DoScrollbarOption(const void *pID, int *pOption, const CUIRect *pRect, const char *pStr, int Min, int Max, const IScrollbarScale *pScale = &LinearScrollbarScale, bool Infinite = false);
void DoScrollbarOptionLabeled(const void *pID, int *pOption, const CUIRect *pRect, const char *pStr, const char *apLabels[], int NumLabels, const IScrollbarScale *pScale = &LinearScrollbarScale);
+ // popup menu
+ void DoPopupMenu(int X, int Y, int Width, int Height, void *pContext, bool (*pfnFunc)(void *pContext, CUIRect View), int Corners = CUIRect::CORNER_ALL);
+ void RenderPopupMenus();
+ bool IsPopupActive() const { return m_NumPopupMenus > 0; }
+
// client ID
float DrawClientID(float FontSize, vec2 Position, int ID,
const vec4& BgColor = vec4(1.0f, 1.0f, 1.0f, 0.5f), const vec4& TextColor = vec4(0.1f, 0.1f, 0.1f, 1.0f));
diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp
index adb09ddca..dcede0f4d 100644
--- a/src/game/editor/editor.cpp
+++ b/src/game/editor/editor.cpp
@@ -1068,8 +1068,7 @@ void CEditor::DoQuad(CQuad *q, int Index)
{
if(!UI()->MouseButton(1))
{
- static int s_QuadPopupID = 0;
- UiInvokePopupMenu(&s_QuadPopupID, 0, UI()->MouseX(), UI()->MouseY(), 120, 180, PopupQuad);
+ UI()->DoPopupMenu(UI()->MouseX(), UI()->MouseY(), 120, 180, this, PopupQuad);
m_LockMouse = false;
s_Operation = OP_NONE;
UI()->SetActiveItem(0);
@@ -1245,8 +1244,7 @@ void CEditor::DoQuadPoint(CQuad *pQuad, int QuadIndex, int V)
{
if(!UI()->MouseButton(1))
{
- static int s_PointPopupID = 0;
- UiInvokePopupMenu(&s_PointPopupID, 0, UI()->MouseX(), UI()->MouseY(), 120, 150, PopupPoint);
+ UI()->DoPopupMenu(UI()->MouseX(), UI()->MouseY(), 120, 150, this, PopupPoint);
UI()->SetActiveItem(0);
}
}
@@ -2258,14 +2256,13 @@ int CEditor::DoProperties(CUIRect *pToolBox, CProperty *pProps, int *pIDs, int *
((pProps[i].m_Value >> s_aShift[2])&0xff)/255.0f,
1.0f);
- static int s_ColorPicker, s_ColorPickerID;
-
ColorBox.Draw(Color, 0.0f, CUIRect::CORNER_NONE);
+ static int s_ColorPicker;
if(DoButton_Editor_Common(&s_ColorPicker, 0x0, 0, &ColorBox, 0, 0x0))
{
m_InitialPickerColor = RgbToHsv(vec3(Color.r, Color.g, Color.b));
m_SelectedPickerColor = m_InitialPickerColor;
- UiInvokePopupMenu(&s_ColorPickerID, 0, UI()->MouseX(), UI()->MouseY(), 180, 180, PopupColorPicker);
+ UI()->DoPopupMenu(UI()->MouseX(), UI()->MouseY(), 180, 180, this, PopupColorPicker);
}
if(m_InitialPickerColor != m_SelectedPickerColor)
@@ -2418,9 +2415,8 @@ void CEditor::RenderLayers(CUIRect ToolBox, CUIRect View)
m_SelectedGroup = g;
m_SelectedLayer = 0;
- static int s_GroupPopupId = 0;
if(Result == 2)
- UiInvokePopupMenu(&s_GroupPopupId, 0, UI()->MouseX(), UI()->MouseY(), 145, 220, PopupGroup);
+ UI()->DoPopupMenu(UI()->MouseX(), UI()->MouseY(), 145, 220, this, PopupGroup);
if(m_Map.m_lGroups[g]->m_lLayers.size() && Input()->MouseDoubleClick())
m_Map.m_lGroups[g]->m_Collapse ^= 1;
@@ -2469,9 +2465,8 @@ void CEditor::RenderLayers(CUIRect ToolBox, CUIRect View)
{
m_SelectedLayer = i;
m_SelectedGroup = g;
- static int s_LayerPopupID = 0;
if(Result == 2)
- UiInvokePopupMenu(&s_LayerPopupID, 0, UI()->MouseX(), UI()->MouseY(), 120, 245, PopupLayer);
+ UI()->DoPopupMenu(UI()->MouseX(), UI()->MouseY(), 120, 245, this, PopupLayer);
}
LayerCur += 14.0f;
@@ -2717,9 +2712,8 @@ void CEditor::RenderImagesList(CUIRect ToolBox)
{
m_SelectedImage = i;
- static int s_PopupImageID = 0;
if(Result == 2)
- UiInvokePopupMenu(&s_PopupImageID, 0, UI()->MouseX(), UI()->MouseY(), 120, 80, PopupImage);
+ UI()->DoPopupMenu(UI()->MouseX(), UI()->MouseY(), 120, 80, this, PopupImage);
}
ToolBox.HSplitTop(2.0f, 0, &ToolBox);
@@ -3110,8 +3104,7 @@ void CEditor::RenderFileDialog()
{
m_aFileDialogNewFolderName[0] = 0;
m_aFileDialogErrString[0] = 0;
- static int s_NewFolderPopupID = 0;
- UiInvokePopupMenu(&s_NewFolderPopupID, 0, Width/2.0f-200.0f, Height/2.0f-100.0f, 400.0f, 200.0f, PopupNewFolder);
+ UI()->DoPopupMenu(Width/2.0f-200.0f, Height/2.0f-100.0f, 400.0f, 200.0f, this, PopupNewFolder);
UI()->SetActiveItem(0);
}
}
@@ -3126,8 +3119,7 @@ void CEditor::RenderFileDialog()
str_copy(m_Map.m_MapInfoTmp.m_aVersion, m_Map.m_MapInfo.m_aVersion, sizeof(m_Map.m_MapInfoTmp.m_aVersion));
str_copy(m_Map.m_MapInfoTmp.m_aCredits, m_Map.m_MapInfo.m_aCredits, sizeof(m_Map.m_MapInfoTmp.m_aCredits));
str_copy(m_Map.m_MapInfoTmp.m_aLicense, m_Map.m_MapInfo.m_aLicense, sizeof(m_Map.m_MapInfoTmp.m_aLicense));
- static int s_MapInfoPopupID = 0;
- UiInvokePopupMenu(&s_MapInfoPopupID, 0, Width/2.0f-200.0f, Height/2.0f-100.0f, 400.0f, 200.0f, PopupMapInfo);
+ UI()->DoPopupMenu(Width/2.0f-200.0f, Height/2.0f-100.0f, 400.0f, 200.0f, this, PopupMapInfo);
UI()->SetActiveItem(0);
}
}
@@ -3869,14 +3861,13 @@ void CEditor::RenderEnvelopeEditor(CUIRect View)
void CEditor::RenderMenubar(CUIRect MenuBar)
{
- CUIRect ExitButton;
- static CUIRect s_File /*, view, help*/;
-
- MenuBar.VSplitLeft(60.0f, &s_File, &MenuBar);
- if(DoButton_Menu(&s_File, "File", 0, &s_File, 0, 0))
- UiInvokePopupMenu(&s_File, 1, s_File.x, s_File.y+s_File.h-1.0f, 120, 150, PopupMenuFile, this);
+ CUIRect FileButton;
+ static int s_FileButton;
+ MenuBar.VSplitLeft(60.0f, &FileButton, &MenuBar);
+ if(DoButton_Menu(&s_FileButton, "File", 0, &FileButton, 0, 0))
+ UI()->DoPopupMenu(FileButton.x, FileButton.y+FileButton.h-1.0f, 120, 150, this, PopupMenuFile, CUIRect::CORNER_R|CUIRect::CORNER_B);
- CUIRect Info;
+ CUIRect Info, ExitButton;
MenuBar.VSplitRight(20.f, &MenuBar, &ExitButton);
MenuBar.VSplitLeft(40.0f, 0, &MenuBar);
MenuBar.VSplitLeft(MenuBar.w*0.75f, &MenuBar, &Info);
@@ -4032,14 +4023,12 @@ void CEditor::Render()
if(m_PopupEventActivated)
{
- static int s_PopupID = 0;
- UiInvokePopupMenu(&s_PopupID, 0, Width/2.0f-200.0f, Height/2.0f-100.0f, 400.0f, 200.0f, PopupEvent);
+ UI()->DoPopupMenu(Width/2.0f-200.0f, Height/2.0f-100.0f, 400.0f, 200.0f, this, PopupEvent);
m_PopupEventActivated = false;
m_PopupEventWasActivated = true;
}
-
- UiDoPopupMenu();
+ UI()->RenderPopupMenus();
if(m_GuiActive)
RenderStatusbar(StatusBar);
diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h
index 5271a7149..d90a86eab 100644
--- a/src/game/editor/editor.h
+++ b/src/game/editor/editor.h
@@ -781,26 +781,23 @@ public:
void RenderGrid(CLayerGroup *pGroup);
- void UiInvokePopupMenu(void *pID, int Flags, float X, float Y, float W, float H, int (*pfnFunc)(CEditor *pEditor, CUIRect Rect), void *pExtra=0);
- void UiDoPopupMenu();
-
int UiDoValueSelector(void *pID, CUIRect *pRect, const char *pLabel, int Current, int Min, int Max, int Step, float Scale, const char *pToolTip);
- static int PopupGroup(CEditor *pEditor, CUIRect View);
- static int PopupLayer(CEditor *pEditor, CUIRect View);
- static int PopupQuad(CEditor *pEditor, CUIRect View);
- static int PopupPoint(CEditor *pEditor, CUIRect View);
- static int PopupNewFolder(CEditor *pEditor, CUIRect View);
- static int PopupMapInfo(CEditor *pEditor, CUIRect View);
- static int PopupEvent(CEditor *pEditor, CUIRect View);
- static int PopupSelectImage(CEditor *pEditor, CUIRect View);
- static int PopupSelectGametileOp(CEditor *pEditor, CUIRect View);
- static int PopupImage(CEditor *pEditor, CUIRect View);
- static int PopupMenuFile(CEditor *pEditor, CUIRect View);
- static int PopupSelectConfigAutoMap(CEditor *pEditor, CUIRect View);
- static int PopupSelectDoodadRuleSet(CEditor *pEditor, CUIRect View);
- static int PopupDoodadAutoMap(CEditor *pEditor, CUIRect View);
- static int PopupColorPicker(CEditor *pEditor, CUIRect View);
+ static bool PopupGroup(void *pContext, CUIRect View);
+ static bool PopupLayer(void *pContext, CUIRect View);
+ static bool PopupQuad(void *pContext, CUIRect View);
+ static bool PopupPoint(void *pContext, CUIRect View);
+ static bool PopupNewFolder(void *pContext, CUIRect View);
+ static bool PopupMapInfo(void *pContext, CUIRect View);
+ static bool PopupEvent(void *pContext, CUIRect View);
+ static bool PopupSelectImage(void *pContext, CUIRect View);
+ static bool PopupSelectGametileOp(void *pContext, CUIRect View);
+ static bool PopupImage(void *pContext, CUIRect View);
+ static bool PopupMenuFile(void *pContext, CUIRect View);
+ static bool PopupSelectConfigAutoMap(void *pContext, CUIRect View);
+ static bool PopupSelectDoodadRuleSet(void *pContext, CUIRect View);
+ static bool PopupDoodadAutoMap(void *pContext, CUIRect View);
+ static bool PopupColorPicker(void *pContext, CUIRect View);
static void CallbackOpenMap(const char *pFileName, int StorageType, void *pUser);
static void CallbackAppendMap(const char *pFileName, int StorageType, void *pUser);
diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp
index a0ecd36a4..aac6aa68b 100644
--- a/src/game/editor/popups.cpp
+++ b/src/game/editor/popups.cpp
@@ -13,85 +13,9 @@
#include "editor.h"
-
-// popup menu handling
-static struct
-{
- CUIRect m_Rect;
- void *m_pId;
- int (*m_pfnFunc)(CEditor *pEditor, CUIRect Rect);
- int m_IsMenu;
- void *m_pExtra;
-} s_UiPopups[8];
-
-static int g_UiNumPopups = 0;
-
-void CEditor::UiInvokePopupMenu(void *pID, int Flags, float x, float y, float Width, float Height, int (*pfnFunc)(CEditor *pEditor, CUIRect Rect), void *pExtra)
-{
- if(x + Width > UI()->Screen()->w)
- x -= Width;
- if(y + Height > UI()->Screen()->h)
- y -= Height;
- s_UiPopups[g_UiNumPopups].m_pId = pID;
- s_UiPopups[g_UiNumPopups].m_IsMenu = Flags;
- s_UiPopups[g_UiNumPopups].m_Rect.x = x;
- s_UiPopups[g_UiNumPopups].m_Rect.y = y;
- s_UiPopups[g_UiNumPopups].m_Rect.w = Width;
- s_UiPopups[g_UiNumPopups].m_Rect.h = Height;
- s_UiPopups[g_UiNumPopups].m_pfnFunc = pfnFunc;
- s_UiPopups[g_UiNumPopups].m_pExtra = pExtra;
- g_UiNumPopups++;
-}
-
-void CEditor::UiDoPopupMenu()
-{
- for(int i = 0; i < g_UiNumPopups; i++)
- {
- bool Inside = UI()->MouseInside(&s_UiPopups[i].m_Rect);
- UI()->SetHotItem(&s_UiPopups[i].m_pId);
-
- if(UI()->CheckActiveItem(&s_UiPopups[i].m_pId))
- {
- if(!UI()->MouseButton(0))
- {
- if(!Inside)
- g_UiNumPopups--;
- UI()->SetActiveItem(0);
- }
- }
- else if(UI()->HotItem() == &s_UiPopups[i].m_pId)
- {
- if(UI()->MouseButton(0))
- UI()->SetActiveItem(&s_UiPopups[i].m_pId);
- }
-
- int Corners = CUIRect::CORNER_ALL;
- if(s_UiPopups[i].m_IsMenu)
- Corners = CUIRect::CORNER_R|CUIRect::CORNER_B;
-
- CUIRect r = s_UiPopups[i].m_Rect;
- r.Draw(vec4(0.5f,0.5f,0.5f,0.75f), 3.0f, Corners);
- r.Margin(1.0f, &r);
- r.Draw(vec4(0,0,0,0.75f), 3.0f, Corners);
- r.Margin(4.0f, &r);
-
- if(s_UiPopups[i].m_pfnFunc(this, r))
- {
- g_UiNumPopups--;
- UI()->SetActiveItem(0);
- }
-
- if(Input()->KeyPress(KEY_ESCAPE))
- {
- g_UiNumPopups--;
- UI()->SetActiveItem(0);
- }
- }
-}
-
-
-int CEditor::PopupGroup(CEditor *pEditor, CUIRect View)
+bool CEditor::PopupGroup(void *pContext, CUIRect View)
{
+ CEditor *pEditor = (CEditor *)pContext;
// remove group button
CUIRect Button;
View.HSplitBottom(12.0f, &View, &Button);
@@ -104,7 +28,7 @@ int CEditor::PopupGroup(CEditor *pEditor, CUIRect View)
{
pEditor->m_Map.DeleteGroup(pEditor->m_SelectedGroup);
pEditor->m_SelectedGroup = maximum(0, pEditor->m_SelectedGroup-1);
- return 1;
+ return true;
}
}
else
@@ -144,7 +68,7 @@ int CEditor::PopupGroup(CEditor *pEditor, CUIRect View)
}
}
- return 1;
+ return true;
}
}
@@ -159,7 +83,7 @@ int CEditor::PopupGroup(CEditor *pEditor, CUIRect View)
pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->AddLayer(l);
pEditor->m_SelectedLayer = pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_lLayers.size()-1;
pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_Collapse = false;
- return 1;
+ return true;
}
// new tile layer
@@ -173,7 +97,7 @@ int CEditor::PopupGroup(CEditor *pEditor, CUIRect View)
pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->AddLayer(l);
pEditor->m_SelectedLayer = pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_lLayers.size()-1;
pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_Collapse = false;
- return 1;
+ return true;
}
// group name
@@ -247,11 +171,12 @@ int CEditor::PopupGroup(CEditor *pEditor, CUIRect View)
else if(Prop == PROP_CLIP_H) pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->m_ClipH = NewVal;
}
- return 0;
+ return false;
}
-int CEditor::PopupLayer(CEditor *pEditor, CUIRect View)
+bool CEditor::PopupLayer(void *pContext, CUIRect View)
{
+ CEditor *pEditor = (CEditor *)pContext;
CLayer *pCurrentLayer = pEditor->GetSelectedLayer(0);
bool IsGameLayer = pEditor->m_Map.m_pGameLayer == pCurrentLayer;
@@ -264,7 +189,7 @@ int CEditor::PopupLayer(CEditor *pEditor, CUIRect View)
if(!IsGameLayer && pEditor->DoButton_Editor(&s_DeleteButton, "Delete layer", 0, &Button, 0, "Deletes the layer"))
{
pEditor->m_Map.m_lGroups[pEditor->m_SelectedGroup]->DeleteLayer(pEditor->m_SelectedLayer);
- return 1;
+ return true;
}
// layer name
@@ -333,8 +258,9 @@ int CEditor::PopupLayer(CEditor *pEditor, CUIRect View)
return pCurrentLayer->RenderProperties(&View);
}
-int CEditor::PopupQuad(CEditor *pEditor, CUIRect View)
+bool CEditor::PopupQuad(void *pContext, CUIRect View)
{
+ CEditor *pEditor = (CEditor *)pContext;
CQuad *pQuad = pEditor->GetSelectedQuad();
CUIRect Button;
@@ -351,7 +277,7 @@ int CEditor::PopupQuad(CEditor *pEditor, CUIRect View)
pLayer->m_lQuads.remove_index(pEditor->m_SelectedQuad);
pEditor->m_SelectedQuad--;
}
- return 1;
+ return true;
}
// aspect ratio button
@@ -381,7 +307,7 @@ int CEditor::PopupQuad(CEditor *pEditor, CUIRect View)
pQuad->m_aPoints[2].x = Left; pQuad->m_aPoints[2].y = Top+Height;
pQuad->m_aPoints[3].x = Right; pQuad->m_aPoints[3].y = Top+Height;
pEditor->m_Map.m_Modified = true;
- return 1;
+ return true;
}
}
@@ -397,7 +323,7 @@ int CEditor::PopupQuad(CEditor *pEditor, CUIRect View)
pQuad->m_aPoints[k].y = 1000.0f * (int(pQuad->m_aPoints[k].y) / 1000);
}
pEditor->m_Map.m_Modified = true;
- return 1;
+ return true;
}
// square button
@@ -424,7 +350,7 @@ int CEditor::PopupQuad(CEditor *pEditor, CUIRect View)
pQuad->m_aPoints[2].x = Left; pQuad->m_aPoints[2].y = Bottom;
pQuad->m_aPoints[3].x = Right; pQuad->m_aPoints[3].y = Bottom;
pEditor->m_Map.m_Modified = true;
- return 1;
+ return true;
}
// center pivot button
@@ -449,7 +375,7 @@ int CEditor::PopupQuad(CEditor *pEditor, CUIRect View)
pQuad->m_aPoints[4].x = Left+int((Right-Left)/2);
pQuad->m_aPoints[4].y = Top+int((Bottom-Top)/2);
pEditor->m_Map.m_Modified = true;
- return 1;
+ return true;
}
enum
@@ -523,11 +449,12 @@ int CEditor::PopupQuad(CEditor *pEditor, CUIRect View)
}
if(Prop == PROP_COLOR_ENV_OFFSET) pQuad->m_ColorEnvOffset = NewVal;
- return 0;
+ return false;
}
-int CEditor::PopupPoint(CEditor *pEditor, CUIRect View)
+bool CEditor::PopupPoint(void *pContext, CUIRect View)
{
+ CEditor *pEditor = (CEditor *)pContext;
CQuad *pQuad = pEditor->GetSelectedQuad();
enum
@@ -615,11 +542,12 @@ int CEditor::PopupPoint(CEditor *pEditor, CUIRect View)
pQuad->m_aTexcoords[v].y = f2fx(NewVal/1024.0f);
}
- return 0;
+ return false;
}
-int CEditor::PopupNewFolder(CEditor *pEditor, CUIRect View)
+bool CEditor::PopupNewFolder(void *pContext, CUIRect View)
{
+ CEditor *pEditor = (CEditor *)pContext;
CUIRect Label, ButtonBar;
// title
@@ -655,7 +583,7 @@ int CEditor::PopupNewFolder(CEditor *pEditor, CUIRect View)
if(pEditor->Storage()->CreateFolder(aBuf, IStorage::TYPE_SAVE))
{
pEditor->FilelistPopulate(IStorage::TYPE_SAVE);
- return 1;
+ return true;
}
else
str_copy(pEditor->m_aFileDialogErrString, "Unable to create the folder", sizeof(pEditor->m_aFileDialogErrString));
@@ -665,7 +593,7 @@ int CEditor::PopupNewFolder(CEditor *pEditor, CUIRect View)
ButtonBar.VSplitRight(110.0f, &ButtonBar, &Label);
static int s_AbortButton = 0;
if(pEditor->DoButton_Editor(&s_AbortButton, "Abort", 0, &Label, 0, 0))
- return 1;
+ return true;
}
else
{
@@ -681,14 +609,15 @@ int CEditor::PopupNewFolder(CEditor *pEditor, CUIRect View)
ButtonBar.VMargin(ButtonBar.w/2.0f-55.0f, &ButtonBar);
static int s_CreateButton = 0;
if(pEditor->DoButton_Editor(&s_CreateButton, "Ok", 0, &ButtonBar, 0, 0))
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-int CEditor::PopupMapInfo(CEditor *pEditor, CUIRect View)
+bool CEditor::PopupMapInfo(void *pContext, CUIRect View)
{
+ CEditor *pEditor = (CEditor *)pContext;
CUIRect Label, ButtonBar, Button;
// title
@@ -747,20 +676,21 @@ int CEditor::PopupMapInfo(CEditor *pEditor, CUIRect View)
str_copy(pEditor->m_Map.m_MapInfo.m_aVersion, pEditor->m_Map.m_MapInfoTmp.m_aVersion, sizeof(pEditor->m_Map.m_MapInfo.m_aVersion));
str_copy(pEditor->m_Map.m_MapInfo.m_aCredits, pEditor->m_Map.m_MapInfoTmp.m_aCredits, sizeof(pEditor->m_Map.m_MapInfo.m_aCredits));
str_copy(pEditor->m_Map.m_MapInfo.m_aLicense, pEditor->m_Map.m_MapInfoTmp.m_aLicense, sizeof(pEditor->m_Map.m_MapInfo.m_aLicense));
- return 1;
+ return true;
}
ButtonBar.VSplitRight(30.0f, &ButtonBar, 0);
ButtonBar.VSplitRight(110.0f, &ButtonBar, &Label);
static int s_AbortButton = 0;
if(pEditor->DoButton_Editor(&s_AbortButton, "Abort", 0, &Label, 0, 0))
- return 1;
+ return true;
- return 0;
+ return false;
}
-int CEditor::PopupEvent(CEditor *pEditor, CUIRect View)
+bool CEditor::PopupEvent(void *pContext, CUIRect View)
{
+ CEditor *pEditor = (CEditor *)pContext;
CUIRect Label, ButtonBar;
// title
@@ -815,7 +745,7 @@ int CEditor::PopupEvent(CEditor *pEditor, CUIRect View)
else if(pEditor->m_PopupEventType == POPEVENT_SAVE)
pEditor->CallbackSaveMap(pEditor->m_aFileSaveName, IStorage::TYPE_SAVE, pEditor);
pEditor->m_PopupEventWasActivated = false;
- return 1;
+ return true;
}
ButtonBar.VSplitRight(30.0f, &ButtonBar, 0);
ButtonBar.VSplitRight(110.0f, &ButtonBar, &Label);
@@ -823,24 +753,27 @@ int CEditor::PopupEvent(CEditor *pEditor, CUIRect View)
if(pEditor->DoButton_Editor(&s_AbortButton, "Abort", 0, &Label, 0, 0))
{
pEditor->m_PopupEventWasActivated = false;
- return 1;
+ return true;
}
- return 0;
+ return false;
}
static int g_SelectImageSelected = -100;
static int g_SelectImageCurrent = -100;
-int CEditor::PopupSelectImage(CEditor *pEditor, CUIRect View)
+bool CEditor::PopupSelectImage(void *pContext, CUIRect View)
{
+ CEditor *pEditor = (CEditor *)pContext;
CUIRect ButtonBar, ImageView;
View.VSplitLeft(80.0f, &ButtonBar, &View);
View.Margin(10.0f, &ImageView);
int ShowImage = g_SelectImageCurrent;
+ bool ClosePopup = false;
+ static int s_NoImageButton;
for(int i = -1; i < pEditor->m_Map.m_lImages.size(); i++)
{
CUIRect Button;
@@ -850,15 +783,10 @@ int CEditor::PopupSelectImage(CEditor *pEditor, CUIRect View)
if(pEditor->UI()->MouseInside(&Button))
ShowImage = i;
- if(i == -1)
- {
- if(pEditor->DoButton_MenuItem(&pEditor->m_Map.m_lImages[i], "None", i==g_SelectImageCurrent, &Button))
- g_SelectImageSelected = -1;
- }
- else
+ if(pEditor->DoButton_MenuItem(i == -1 ? (void *)&s_NoImageButton : &pEditor->m_Map.m_lImages[i], i == -1 ? "None" : pEditor->m_Map.m_lImages[i]->m_aName, i == g_SelectImageCurrent, &Button))
{
- if(pEditor->DoButton_MenuItem(&pEditor->m_Map.m_lImages[i], pEditor->m_Map.m_lImages[i]->m_aName, i==g_SelectImageCurrent, &Button))
- g_SelectImageSelected = i;
+ g_SelectImageSelected = i;
+ ClosePopup |= pEditor->Input()->MouseDoubleClick();
}
}
@@ -881,15 +809,14 @@ int CEditor::PopupSelectImage(CEditor *pEditor, CUIRect View)
pEditor->Graphics()->WrapNormal();
}
- return 0;
+ return ClosePopup;
}
void CEditor::PopupSelectImageInvoke(int Current, float x, float y)
{
- static int s_SelectImagePopupId = 0;
g_SelectImageSelected = -100;
g_SelectImageCurrent = Current;
- UiInvokePopupMenu(&s_SelectImagePopupId, 0, x, y, 400, 300, PopupSelectImage);
+ UI()->DoPopupMenu(x, y, 400, 300, this, PopupSelectImage);
}
int CEditor::PopupSelectImageResult()
@@ -904,8 +831,9 @@ int CEditor::PopupSelectImageResult()
static int s_GametileOpSelected = -1;
-int CEditor::PopupSelectGametileOp(CEditor *pEditor, CUIRect View)
+bool CEditor::PopupSelectGametileOp(void *pContext, CUIRect View)
{
+ CEditor *pEditor = (CEditor *)pContext;
static const char *s_pButtonNames[] = { "Clear", "Collision", "Death", "Unhookable" };
static unsigned s_NumButtons = sizeof(s_pButtonNames) / sizeof(char*);
CUIRect Button;
@@ -918,14 +846,13 @@ int CEditor::PopupSelectGametileOp(CEditor *pEditor, CUIRect View)
s_GametileOpSelected = i;
}
- return 0;
+ return false;
}
void CEditor::PopupSelectGametileOpInvoke(float x, float y)
{
- static int s_SelectGametileOpPopupId = 0;
s_GametileOpSelected = -1;
- UiInvokePopupMenu(&s_SelectGametileOpPopupId, 0, x, y, 120.0f, 70.0f, PopupSelectGametileOp);
+ UI()->DoPopupMenu(x, y, 120.0f, 70.0f, this, PopupSelectGametileOp);
}
int CEditor::PopupSelectGameTileOpResult()
@@ -940,8 +867,9 @@ int CEditor::PopupSelectGameTileOpResult()
static bool s_AutoMapProceedOrder = false;
-int CEditor::PopupDoodadAutoMap(CEditor *pEditor, CUIRect View)
+bool CEditor::PopupDoodadAutoMap(void *pContext, CUIRect View)
{
+ CEditor *pEditor = (CEditor *)pContext;
CLayerTiles *pLayer = static_cast<CLayerTiles*>(pEditor->GetSelectedLayer(0));
IAutoMapper *pMapper = pEditor->m_Map.m_lImages[pLayer->m_Image]->m_pAutoMapper;
CUIRect Rect;
@@ -951,8 +879,8 @@ int CEditor::PopupDoodadAutoMap(CEditor *pEditor, CUIRect View)
// ruleset selection
static int s_ChooseDoodadRuleset = 0;
if(pEditor->DoButton_Editor(&s_ChooseDoodadRuleset, pMapper->GetRuleSetName(pLayer->m_SelectedRuleSet), 0, &Rect, 0, 0))
- pEditor->UiInvokePopupMenu(&s_ChooseDoodadRuleset, 0, pEditor->UI()->MouseX(), pEditor->UI()->MouseY(),
- 120.0f, 12.0f+14.0f*pMapper->RuleSetNum(), PopupSelectDoodadRuleSet);
+ pEditor->UI()->DoPopupMenu(pEditor->UI()->MouseX(), pEditor->UI()->MouseY(),
+ 120.0f, 12.0f+14.0f*pMapper->RuleSetNum(), pEditor, PopupSelectDoodadRuleSet);
View.HMargin(3.f, &View);
View.HSplitTop(15.0f, &Rect, &View);
@@ -973,11 +901,12 @@ int CEditor::PopupDoodadAutoMap(CEditor *pEditor, CUIRect View)
if(pEditor->DoButton_Editor(&s_ButtonDoodadGenerate, "Generate", 0, &Rect, 0, 0))
s_AutoMapProceedOrder = true;
- return 0;
+ return false;
}
-int CEditor::PopupSelectDoodadRuleSet(CEditor *pEditor, CUIRect View)
+bool CEditor::PopupSelectDoodadRuleSet(void *pContext, CUIRect View)
{
+ CEditor *pEditor = (CEditor *)pContext;
CLayerTiles *pLayer = static_cast<CLayerTiles*>(pEditor->GetSelectedLayer(0));
CUIRect Button;
static int s_AutoMapperDoodadButtons[IAutoMapper::MAX_RULES];
@@ -990,15 +919,16 @@ int CEditor::PopupSelectDoodadRuleSet(CEditor *pEditor, CUIRect View)
if(pEditor->DoButton_Editor(&s_AutoMapperDoodadButtons[i], pMapper->GetRuleSetName(i), 0, &Button, 0, 0))
{
pLayer->m_SelectedRuleSet = i;
- return 1; // close the popup
+ return true; // close the popup
}
}
- return 0;
+ return false;
}
-int CEditor::PopupSelectConfigAutoMap(CEditor *pEditor, CUIRect View)
+bool CEditor::PopupSelectConfigAutoMap(void *pContext, CUIRect View)
{
+ CEditor *pEditor = (CEditor *)pContext;
CLayerTiles *pLayer = static_cast<CLayerTiles*>(pEditor->GetSelectedLayer(0));
CUIRect Button;
static int s_AutoMapperConfigButtons[IAutoMapper::MAX_RULES];
@@ -1034,21 +964,20 @@ int CEditor::PopupSelectConfigAutoMap(CEditor *pEditor, CUIRect View)
pLayer->m_LiveAutoMap = true;
}
- return 0;
+ return false;
}
void CEditor::PopupSelectConfigAutoMapInvoke(float x, float y)
{
- static int s_AutoMapConfigSelectID = 0;
CLayerTiles *pLayer = static_cast<CLayerTiles*>(GetSelectedLayer(0));
if(pLayer && pLayer->m_Image >= 0 && pLayer->m_Image < m_Map.m_lImages.size() &&
m_Map.m_lImages[pLayer->m_Image]->m_pAutoMapper->RuleSetNum())
{
if(m_Map.m_lImages[pLayer->m_Image]->m_pAutoMapper->GetType() == IAutoMapper::TYPE_TILESET)
- UiInvokePopupMenu(&s_AutoMapConfigSelectID, 0, x, y, 120.0f, 12.0f+14.0f*m_Map.m_lImages[pLayer->m_Image]->m_pAutoMapper->RuleSetNum()+14.0f, PopupSelectConfigAutoMap);
+ UI()->DoPopupMenu(x, y, 120.0f, 12.0f+14.0f*m_Map.m_lImages[pLayer->m_Image]->m_pAutoMapper->RuleSetNum()+14.0f, this, PopupSelectConfigAutoMap);
else if(m_Map.m_lImages[pLayer->m_Image]->m_pAutoMapper->GetType() == IAutoMapper::TYPE_DOODADS)
- UiInvokePopupMenu(&s_AutoMapConfigSelectID, 0, x, y, 120.0f, 60.0f, PopupDoodadAutoMap);
+ UI()->DoPopupMenu(x, y, 120.0f, 60.0f, this, PopupDoodadAutoMap);
}
}
@@ -1064,8 +993,9 @@ bool CEditor::PopupAutoMapProceedOrder()
return false;
}
-int CEditor::PopupColorPicker(CEditor *pEditor, CUIRect View)
+bool CEditor::PopupColorPicker(void *pContext, CUIRect View)
{
+ CEditor *pEditor = (CEditor *)pContext;
CUIRect SVPicker, HuePicker, Palette;
View.HSplitBottom(20.0f, &SVPicker, &Palette);
SVPicker.VSplitRight(20.0f, &SVPicker, &HuePicker);
@@ -1176,7 +1106,7 @@ int CEditor::PopupColorPicker(CEditor *pEditor, CUIRect View)
pEditor->m_SelectedPickerColor = hsv;
- return 0;
+ return false;
}
@@ -1189,8 +1119,9 @@ static void ModifyIndexDeleted(int *pIndex)
*pIndex = *pIndex - 1;
}
-int CEditor::PopupImage(CEditor *pEditor, CUIRect View)
+bool CEditor::PopupImage(void *pContext, CUIRect View)
{
+ CEditor *pEditor = (CEditor *)pContext;
static int s_ReplaceButton = 0;
static int s_RemoveButton = 0;
@@ -1205,7 +1136,7 @@ int CEditor::PopupImage(CEditor *pEditor, CUIRect View)
if(pEditor->DoButton_MenuItem(&s_ExternalButton, "Embed", 0, &Slot, 0, "Embeds the image into the map file."))
{
pImg->m_External = 0;
- return 1;
+ return true;
}
}
else
@@ -1213,7 +1144,7 @@ int CEditor::PopupImage(CEditor *pEditor, CUIRect View)
if(pEditor->DoButton_MenuItem(&s_ExternalButton, "Make external", 0, &Slot, 0, "Removes the image from the map file."))
{
pImg->m_External = 1;
- return 1;
+ return true;
}
}
@@ -1222,7 +1153,7 @@ int CEditor::PopupImage(CEditor *pEditor, CUIRect View)
if(pEditor->DoButton_MenuItem(&s_ReplaceButton, "Replace", 0, &Slot, 0, "Replaces the image with a new one"))
{
pEditor->InvokeFileDialog(IStorage::TYPE_ALL, FILETYPE_IMG, "Replace Image", "Replace", "mapres", "", ReplaceImage, pEditor);
- return 1;
+ return true;
}
View.HSplitTop(10.0f, &Slot, &View);
@@ -1233,14 +1164,15 @@ int CEditor::PopupImage(CEditor *pEditor, CUIRect View)
pEditor->m_Map.m_lImages.remove_index(pEditor->m_SelectedImage);
gs_ModifyIndexDeletedIndex = pEditor->m_SelectedImage;
pEditor->m_Map.ModifyImageIndex(ModifyIndexDeleted);
- return 1;
+ return true;
}
- return 0;
+ return false;
}
-int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View)
+bool CEditor::PopupMenuFile(void *pContext, CUIRect View)
{
+ CEditor *pEditor = (CEditor *)pContext;
static int s_NewMapButton = 0;
static int s_SaveButton = 0;
static int s_SaveAsButton = 0;
@@ -1264,7 +1196,7 @@ int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View)
pEditor->Reset();
pEditor->m_aFileName[0] = 0;
}
- return 1;
+ return true;
}
View.HSplitTop(10.0f, &Slot, &View);
@@ -1278,7 +1210,7 @@ int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View)
}
else
pEditor->InvokeFileDialog(IStorage::TYPE_ALL, FILETYPE_MAP, "Load map", "Load", "maps", "", pEditor->CallbackOpenMap, pEditor);
- return 1;
+ return true;
}
if(pEditor->Client()->State() == IClient::STATE_ONLINE)
@@ -1294,7 +1226,7 @@ int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View)
}
else
pEditor->LoadCurrentMap();
- return 1;
+ return true;
}
}
@@ -1303,7 +1235,7 @@ int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View)
if(pEditor->DoButton_MenuItem(&s_AppendButton, "Append", 0, &Slot, 0, "Opens a map and adds everything from that map to the current one"))
{
pEditor->InvokeFileDialog(IStorage::TYPE_ALL, FILETYPE_MAP, "Append map", "Append", "maps", "", pEditor->CallbackAppendMap, pEditor);
- return 1;
+ return true;
}
View.HSplitTop(10.0f, &Slot, &View);
@@ -1318,7 +1250,7 @@ int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View)
}
else
pEditor->InvokeFileDialog(IStorage::TYPE_SAVE, FILETYPE_MAP, "Save map", "Save", "maps", "", pEditor->CallbackSaveMap, pEditor);
- return 1;
+ return true;
}
View.HSplitTop(2.0f, &Slot, &View);
@@ -1326,7 +1258,7 @@ int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View)
if(pEditor->DoButton_MenuItem(&s_SaveAsButton, "Save As", 0, &Slot, 0, "Saves the current map under a new name"))
{
pEditor->InvokeFileDialog(IStorage::TYPE_SAVE, FILETYPE_MAP, "Save map", "Save", "maps", "", pEditor->CallbackSaveMap, pEditor);
- return 1;
+ return true;
}
View.HSplitTop(10.0f, &Slot, &View);
@@ -1340,8 +1272,8 @@ int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View)
}
else
pEditor->Config()->m_ClEditor = 0;
- return 1;
+ return true;
}
- return 0;
+ return false;
}
diff --git a/src/test/str.cpp b/src/test/str.cpp
index c8adb8471..6d066299d 100644
--- a/src/test/str.cpp
+++ b/src/test/str.cpp
@@ -129,31 +129,35 @@ TEST(Str, Utf8Stats)
{
int Size, Count;
- str_utf8_stats("abc", 4, &Size, &Count);
+ str_utf8_stats("abc", 4, 3, &Size, &Count);
EXPECT_EQ(Size, 3);
EXPECT_EQ(Count, 3);
- str_utf8_stats("abc", 2, &Size, &Count);
+ str_utf8_stats("abc", 2, 3, &Size, &Count);
EXPECT_EQ(Size, 1);
EXPECT_EQ(Count, 1);
- str_utf8_stats("", 1, &Size, &Count);
+ str_utf8_stats("", 1, 0, &Size, &Count);
EXPECT_EQ(Size, 0);
EXPECT_EQ(Count, 0);
- str_utf8_stats("abcde", 6, &Size, &Count);
+ str_utf8_stats("abcde", 6, 5, &Size, &Count);
EXPECT_EQ(Size, 5);
EXPECT_EQ(Count, 5);
- str_utf8_stats("любовь", 13, &Size, &Count);
+ str_utf8_stats("любовь", 13, 6, &Size, &Count);
EXPECT_EQ(Size, 12);
EXPECT_EQ(Count, 6);
- str_utf8_stats("abc愛", 7, &Size, &Count);
+ str_utf8_stats("abc愛", 7, 4, &Size, &Count);
EXPECT_EQ(Size, 6);
EXPECT_EQ(Count, 4);
- str_utf8_stats("abc愛", 6, &Size, &Count);
+ str_utf8_stats("abc愛", 6, 4, &Size, &Count);
EXPECT_EQ(Size, 3);
EXPECT_EQ(Count, 3);
+
+ str_utf8_stats("любовь", 13, 3, &Size, &Count);
+ EXPECT_EQ(Size, 6);
+ EXPECT_EQ(Count, 3);
}