UI Elements

This commit is contained in:
Jupeyy 2020-10-12 12:29:47 +02:00
parent aca143cb7d
commit 74515d4b95
14 changed files with 466 additions and 50 deletions

View file

@ -1091,7 +1091,7 @@ public:
pCursor->m_Y = DrawY;
}
virtual int CreateTextContainer(CTextCursor *pCursor, const char *pText)
virtual int CreateTextContainer(CTextCursor *pCursor, const char *pText, int Length = -1)
{
CFont *pFont = pCursor->m_pFont;
@ -1144,7 +1144,7 @@ public:
TextContainer.m_FontSize = pSizeData->m_FontSize;
AppendTextContainer(pCursor, ContainerIndex, pText);
AppendTextContainer(pCursor, ContainerIndex, pText, Length);
if(TextContainer.m_StringInfo.m_CharacterQuads.size() == 0)
{
@ -1181,7 +1181,7 @@ public:
return ContainerIndex;
}
virtual void AppendTextContainer(CTextCursor *pCursor, int TextContainerIndex, const char *pText)
virtual void AppendTextContainer(CTextCursor *pCursor, int TextContainerIndex, const char *pText, int Length = -1)
{
STextContainer &TextContainer = GetTextContainer(TextContainerIndex);
@ -1218,7 +1218,8 @@ public:
pSizeData = TextContainer.m_pFont->GetFontSize(TextContainer.m_FontSize);
// string length
int Length = str_length(pText);
if(Length < 0)
Length = str_length(pText);
float Scale = 1.0f / pSizeData->m_FontSize;
@ -1443,19 +1444,19 @@ public:
}
// just deletes and creates text container
virtual void RecreateTextContainer(CTextCursor *pCursor, int TextContainerIndex, const char *pText)
virtual void RecreateTextContainer(CTextCursor *pCursor, int TextContainerIndex, const char *pText, int Length = -1)
{
DeleteTextContainer(TextContainerIndex);
CreateTextContainer(pCursor, pText);
CreateTextContainer(pCursor, pText, Length);
}
virtual void RecreateTextContainerSoft(CTextCursor *pCursor, int TextContainerIndex, const char *pText)
virtual void RecreateTextContainerSoft(CTextCursor *pCursor, int TextContainerIndex, const char *pText, int Length = -1)
{
STextContainer &TextContainer = GetTextContainer(TextContainerIndex);
TextContainer.m_StringInfo.m_CharacterQuads.clear();
TextContainer.m_StringInfo.m_QuadNum = 0;
// the text buffer gets then recreated by the appended quads
AppendTextContainer(pCursor, TextContainerIndex, pText);
AppendTextContainer(pCursor, TextContainerIndex, pText, Length);
}
virtual void SetTextContainerSelection(int TextContainerIndex, const char *pText, int CursorPos, int SelectionStart, int SelectionEnd)

View file

@ -5,6 +5,7 @@
#include <engine/map.h>
#include <engine/shared/protocol.h>
#include <game/client/ui.h>
#include "kernel.h"
@ -61,6 +62,8 @@ public:
char m_aAddress[NETADDR_MAXSTRSIZE];
CClient m_aClients[MAX_CLIENTS];
mutable int m_NumFilteredPlayers;
mutable CUIElement *m_pUIElement;
};
bool IsVanilla(const CServerInfo *pInfo);

View file

@ -61,6 +61,10 @@ struct STextRenderColor
{
Set(r, g, b, a);
}
STextRenderColor(const ColorRGBA &TextColorRGBA)
{
Set(TextColorRGBA.r, TextColorRGBA.g, TextColorRGBA.b, TextColorRGBA.a);
}
void Set(float r, float g, float b, float a)
{
@ -89,13 +93,16 @@ public:
virtual void SetRenderFlags(unsigned int Flags) = 0;
ColorRGBA DefaultTextColor() { return ColorRGBA(1, 1, 1, 1); }
ColorRGBA DefaultTextOutlineColor() { return ColorRGBA(0, 0, 0, 0.3f); }
//
virtual void TextEx(CTextCursor *pCursor, const char *pText, int Length) = 0;
virtual int CreateTextContainer(CTextCursor *pCursor, const char *pText) = 0;
virtual void AppendTextContainer(CTextCursor *pCursor, int TextContainerIndex, const char *pText) = 0;
virtual int CreateTextContainer(CTextCursor *pCursor, const char *pText, int Length = -1) = 0;
virtual void AppendTextContainer(CTextCursor *pCursor, int TextContainerIndex, const char *pText, int Length = -1) = 0;
// just deletes and creates text container
virtual void RecreateTextContainer(CTextCursor *pCursor, int TextContainerIndex, const char *pText) = 0;
virtual void RecreateTextContainerSoft(CTextCursor *pCursor, int TextContainerIndex, const char *pText) = 0;
virtual void RecreateTextContainer(CTextCursor *pCursor, int TextContainerIndex, const char *pText, int Length = -1) = 0;
virtual void RecreateTextContainerSoft(CTextCursor *pCursor, int TextContainerIndex, const char *pText, int Length = -1) = 0;
virtual void SetTextContainerSelection(int TextContainerIndex, const char *pText, int CursorPos, int SelectionStart, int SelectionEnd) = 0;
virtual void DeleteTextContainer(int TextContainerIndex) = 0;
@ -110,6 +117,7 @@ public:
virtual void TextColor(float r, float g, float b, float a) = 0;
virtual void TextColor(ColorRGBA rgb) = 0;
virtual void TextOutlineColor(float r, float g, float b, float a) = 0;
virtual void TextOutlineColor(ColorRGBA rgb) = 0;
virtual void Text(void *pFontSetV, float x, float y, float Size, const char *pText, float LineWidth) = 0;
virtual float TextWidth(void *pFontSetV, float Size, const char *pText, int StrLength, float LineWidth, float *pAlignedHeight = NULL, float *pMaxCharacterHeightInLine = NULL) = 0;
virtual int TextLineCount(void *pFontSetV, float Size, const char *pText, float LineWidth) = 0;

View file

@ -99,10 +99,10 @@ CMenus::CMenus()
float CMenus::ButtonColorMul(const void *pID)
{
if(UI()->ActiveItem() == pID)
return 0.5f;
return ButtonColorMulActive();
else if(UI()->HotItem() == pID)
return 1.5f;
return 1;
return ButtonColorMulHot();
return ButtonColorMulDefault();
}
int CMenus::DoButton_Icon(int ImageId, int SpriteId, const CUIRect *pRect)
@ -1107,6 +1107,9 @@ void CMenus::OnInit()
if(g_Config.m_ClSkipStartMenu)
m_ShowStart = false;
m_RefreshButton.Init(UI());
m_ConnectButton.Init(UI());
Console()->Chain("add_favorite", ConchainServerbrowserUpdate, this);
Console()->Chain("remove_favorite", ConchainServerbrowserUpdate, this);
Console()->Chain("add_friend", ConchainFriendlistUpdate, this);

View file

@ -10,6 +10,7 @@
#include <engine/friends.h>
#include <engine/shared/config.h>
#include <engine/shared/linereader.h>
#include <engine/textrender.h>
#include <game/client/components/mapimages.h>
#include <game/client/component.h>
@ -48,6 +49,11 @@ class CMenus : public CComponent
static ColorRGBA ms_ColorTabbarActive;
static ColorRGBA ms_ColorTabbarHover;
char m_aLocalStringHelper[1024];
float ButtonColorMulActive() { return 0.5f; }
float ButtonColorMulHot() { return 1.5f; }
float ButtonColorMulDefault() { return 1.0f; }
float ButtonColorMul(const void *pID);
int DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
@ -88,6 +94,95 @@ class CMenus : public CComponent
//static int ui_do_key_reader(void *id, const CUIRect *rect, int key);
void UiDoGetButtons(int Start, int Stop, CUIRect View, CUIRect ScopeView);
// new gui with gui elements
template<typename T>
int DoButtonMenu(CUIElement &UIElement, const void *pID, T &&GetTextLambda, int Checked, const CUIRect *pRect, bool HintRequiresStringCheck, bool HintCanChangePositionOrSize = false, int Corners = CUI::CORNER_ALL, float r = 5.0f, float FontFactor = 0.0f, vec4 ColorHot = vec4(1.0f, 1.0f, 1.0f, 0.75f), vec4 Color = vec4(1, 1, 1, 0.5f), int AlignVertically = 1)
{
CUIRect Text = *pRect;
Text.HMargin(pRect->h >= 20.0f ? 2.0f : 1.0f, &Text);
Text.HMargin((Text.h * FontFactor) / 2.0f, &Text);
if(UIElement.Size() != 3 || HintRequiresStringCheck || HintCanChangePositionOrSize)
{
bool NeedsRecalc = UIElement.Size() != 3;
if(HintCanChangePositionOrSize)
{
if(UIElement.Size() == 3)
{
if(UIElement.Get(0)->m_X != pRect->x || UIElement.Get(0)->m_Y != pRect->y || UIElement.Get(0)->m_Width != pRect->w || UIElement.Get(0)->m_Y != pRect->h)
{
NeedsRecalc = true;
}
}
}
const char *pText = NULL;
if(HintRequiresStringCheck)
{
if(UIElement.Size() == 3)
{
pText = GetTextLambda();
if(str_comp(UIElement.Get(0)->m_Text.c_str(), pText) != 0)
{
NeedsRecalc = true;
}
}
}
if(NeedsRecalc)
{
if(UIElement.Size() > 0)
{
UI()->ResetUIElement(UIElement);
}
vec4 RealColor = Color;
for(int i = 0; i < 3; ++i)
{
Color.a = RealColor.a;
if(i == 0)
Color.a *= ButtonColorMulActive();
else if(i == 1)
Color.a *= ButtonColorMulHot();
else if(i == 2)
Color.a *= ButtonColorMulDefault();
Graphics()->SetColor(Color);
CUIElement::SUIElementRect NewRect;
NewRect.m_UIRectQuadContainer = RenderTools()->CreateRoundRectQuadContainer(pRect->x, pRect->y, pRect->w, pRect->h, r, Corners);
NewRect.m_X = pRect->x;
NewRect.m_Y = pRect->y;
NewRect.m_Width = pRect->w;
NewRect.m_Height = pRect->h;
if(i == 0)
{
if(pText == NULL)
pText = GetTextLambda();
NewRect.m_Text = pText;
UI()->DoLabel(NewRect, &Text, pText, Text.h * ms_FontmodHeight, 0, -1, AlignVertically);
}
UIElement.Add(NewRect);
}
Graphics()->SetColor(1, 1, 1, 1);
}
}
// render
size_t Index = 2;
if(UI()->ActiveItem() == pID)
Index = 0;
else if(UI()->HotItem() == pID)
Index = 1;
Graphics()->TextureClear();
Graphics()->RenderQuadContainer(UIElement.Get(Index)->m_UIRectQuadContainer, -1);
STextRenderColor ColorText(TextRender()->DefaultTextColor());
STextRenderColor ColorTextOutline(TextRender()->DefaultTextOutlineColor());
if(UIElement.Get(0)->m_UITextContainer != -1)
TextRender()->RenderTextContainer(UIElement.Get(0)->m_UITextContainer, &ColorText, &ColorTextOutline);
return UI()->DoButtonLogic(pID, Checked, pRect);
}
struct CListboxItem
{
int m_Visible;
@ -186,6 +281,9 @@ protected:
char m_aMessageBody[512];
char m_aMessageButton[512];
CUIElement m_RefreshButton;
CUIElement m_ConnectButton;
void PopupMessage(const char *pTopic, const char *pBody, const char *pButton);
// TODO: this is a bit ugly but.. well.. yeah

View file

@ -21,6 +21,16 @@
#include "menus.h"
static const int g_OffsetColFlagLock = 2;
static const int g_OffsetColFav = g_OffsetColFlagLock + 3;
static const int g_OffsetColOff = g_OffsetColFav + 3;
static const int g_OffsetColName = g_OffsetColOff + 3;
static const int g_OffsetColGameType = g_OffsetColName + 3;
static const int g_OffsetColMap = g_OffsetColGameType + 3;
static const int g_OffsetColPlayers = g_OffsetColMap + 3;
static const int g_OffsetColPing = g_OffsetColPlayers + 3;
static const int g_OffsetColVersion = g_OffsetColPing + 3;
void CMenus::RenderServerbrowserServerList(CUIRect View)
{
CUIRect Headers;
@ -261,6 +271,25 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
CUIRect Row;
CUIRect SelectHitBox;
//initialize
if(pItem->m_pUIElement == NULL)
{
pItem->m_pUIElement = UI()->GetNewUIElement();
}
const int UIRectCount = 2 + (COL_VERSION + 1) * 3;
if(pItem->m_pUIElement->Size() != UIRectCount)
{
UI()->ResetUIElement(*pItem->m_pUIElement);
for(int UIElIndex = 0; UIElIndex < UIRectCount; ++UIElIndex)
{
CUIElement::SUIElementRect AddRect;
pItem->m_pUIElement->Add(AddRect);
}
}
int Selected = str_comp(pItem->m_aAddress, g_Config.m_UiServerAddress) == 0; //selected_index==ItemIndex;
View.HSplitTop(ms_ListheaderHeight, &Row, &View);
@ -299,7 +328,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
{
CUIRect r = Row;
r.Margin(0.5f, &r);
RenderTools()->DrawUIRect(&r, ColorRGBA(1, 1, 1, 0.5f), CUI::CORNER_ALL, 4.0f);
RenderTools()->DrawUIElRect(*pItem->m_pUIElement->Get(0), &r, ColorRGBA(1, 1, 1, 0.5f), CUI::CORNER_ALL, 4.0f);
}
// clip the selection
@ -315,7 +344,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
{
CUIRect r = Row;
r.Margin(0.5f, &r);
RenderTools()->DrawUIRect(&r, ColorRGBA(1, 1, 1, 0.25f), CUI::CORNER_ALL, 4.0f);
RenderTools()->DrawUIElRect(*pItem->m_pUIElement->Get(1), &r, ColorRGBA(1, 1, 1, 0.25f), CUI::CORNER_ALL, 4.0f);
}
if(UI()->DoButtonLogic(pItem, "", Selected, &SelectHitBox))
@ -364,10 +393,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
}
else if(ID == COL_NAME)
{
CTextCursor Cursor;
float FontSize = 12.0f * UI()->Scale();
TextRender()->SetCursor(&Cursor, Button.x, Button.y + (Button.h - FontSize) / 2.f, FontSize, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Button.w;
if(g_Config.m_BrFilterString[0] && (pItem->m_QuickSearchHit & IServerBrowser::QUICK_SERVERNAME))
{
@ -375,17 +401,17 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
const char *pStr = str_find_nocase(pItem->m_aName, g_Config.m_BrFilterString);
if(pStr)
{
TextRender()->TextEx(&Cursor, pItem->m_aName, (int)(pStr - pItem->m_aName));
UI()->DoLabelStreamed(*pItem->m_pUIElement->Get(g_OffsetColName + 0), &Button, pItem->m_aName, FontSize, -1, Button.w, 1, true, (int)(pStr - pItem->m_aName));
TextRender()->TextColor(0.4f, 0.4f, 1.0f, 1);
TextRender()->TextEx(&Cursor, pStr, str_length(g_Config.m_BrFilterString));
UI()->DoLabelStreamed(*pItem->m_pUIElement->Get(g_OffsetColName + 1), &Button, pStr, FontSize, -1, Button.w, 1, true, (int)str_length(g_Config.m_BrFilterString), &pItem->m_pUIElement->Get(g_OffsetColName + 0)->m_Cursor);
TextRender()->TextColor(1, 1, 1, 1);
TextRender()->TextEx(&Cursor, pStr + str_length(g_Config.m_BrFilterString), -1);
UI()->DoLabelStreamed(*pItem->m_pUIElement->Get(g_OffsetColName + 2), &Button, pStr + str_length(g_Config.m_BrFilterString), FontSize, -1, Button.w, 1, true, -1, &pItem->m_pUIElement->Get(g_OffsetColName + 1)->m_Cursor);
}
else
TextRender()->TextEx(&Cursor, pItem->m_aName, -1);
UI()->DoLabelStreamed(*pItem->m_pUIElement->Get(g_OffsetColName), &Button, pItem->m_aName, FontSize, -1, Button.w, 1, true);
}
else
TextRender()->TextEx(&Cursor, pItem->m_aName, -1);
UI()->DoLabelStreamed(*pItem->m_pUIElement->Get(g_OffsetColName), &Button, pItem->m_aName, FontSize, -1, Button.w, 1, true);
}
else if(ID == COL_MAP)
{
@ -400,10 +426,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
DoButton_Icon(IMAGE_BROWSEICONS, SPRITE_BROWSE_RANK, &Icon);
}
CTextCursor Cursor;
float FontSize = 12.0f * UI()->Scale();
TextRender()->SetCursor(&Cursor, Button.x, Button.y + (Button.h - FontSize) / 2.f, 12.0f * UI()->Scale(), TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Button.w;
if(g_Config.m_BrFilterString[0] && (pItem->m_QuickSearchHit & IServerBrowser::QUICK_MAPNAME))
{
@ -411,17 +434,17 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
const char *pStr = str_find_nocase(pItem->m_aMap, g_Config.m_BrFilterString);
if(pStr)
{
TextRender()->TextEx(&Cursor, pItem->m_aMap, (int)(pStr - pItem->m_aMap));
UI()->DoLabelStreamed(*pItem->m_pUIElement->Get(g_OffsetColMap + 0), &Button, pItem->m_aMap, FontSize, -1, Button.w, 1, true, (int)(pStr - pItem->m_aMap));
TextRender()->TextColor(0.4f, 0.4f, 1.0f, 1);
TextRender()->TextEx(&Cursor, pStr, str_length(g_Config.m_BrFilterString));
UI()->DoLabelStreamed(*pItem->m_pUIElement->Get(g_OffsetColMap + 1), &Button, pStr, FontSize, -1, Button.w, 1, true, (int)str_length(g_Config.m_BrFilterString), &pItem->m_pUIElement->Get(g_OffsetColMap + 0)->m_Cursor);
TextRender()->TextColor(1, 1, 1, 1);
TextRender()->TextEx(&Cursor, pStr + str_length(g_Config.m_BrFilterString), -1);
UI()->DoLabelStreamed(*pItem->m_pUIElement->Get(g_OffsetColMap + 2), &Button, pStr + str_length(g_Config.m_BrFilterString), FontSize, -1, Button.w, 1, true, -1, &pItem->m_pUIElement->Get(g_OffsetColMap + 1)->m_Cursor);
}
else
TextRender()->TextEx(&Cursor, pItem->m_aMap, -1);
UI()->DoLabelStreamed(*pItem->m_pUIElement->Get(g_OffsetColMap), &Button, pItem->m_aMap, FontSize, -1, Button.w, 1, true);
}
else
TextRender()->TextEx(&Cursor, pItem->m_aMap, -1);
UI()->DoLabelStreamed(*pItem->m_pUIElement->Get(g_OffsetColMap), &Button, pItem->m_aMap, FontSize, -1, Button.w, 1, true);
}
else if(ID == COL_PLAYERS)
{
@ -437,7 +460,8 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
str_format(aTemp, sizeof(aTemp), "%i/%i", pItem->m_NumFilteredPlayers, ServerBrowser()->Max(*pItem));
if(g_Config.m_BrFilterString[0] && (pItem->m_QuickSearchHit & IServerBrowser::QUICK_PLAYER))
TextRender()->TextColor(0.4f, 0.4f, 1.0f, 1);
UI()->DoLabelScaled(&Button, aTemp, 12.0f, 1);
float FontSize = 12.0f * UI()->Scale();
UI()->DoLabelStreamed(*pItem->m_pUIElement->Get(g_OffsetColPlayers), &Button, aTemp, FontSize, -1, Button.w, 1, true);
TextRender()->TextColor(1, 1, 1, 1);
}
else if(ID == COL_PING)
@ -449,20 +473,19 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
TextRender()->TextColor(rgb);
}
UI()->DoLabelScaled(&Button, aTemp, 12.0f, 1);
float FontSize = 12.0f * UI()->Scale();
UI()->DoLabelStreamed(*pItem->m_pUIElement->Get(g_OffsetColPing), &Button, aTemp, FontSize, -1, Button.w, 1, true);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
}
else if(ID == COL_VERSION)
{
const char *pVersion = pItem->m_aVersion;
UI()->DoLabelScaled(&Button, pVersion, 12.0f, 1);
float FontSize = 12.0f * UI()->Scale();
UI()->DoLabelStreamed(*pItem->m_pUIElement->Get(g_OffsetColVersion), &Button, pVersion, FontSize, -1, Button.w, 1, true);
}
else if(ID == COL_GAMETYPE)
{
CTextCursor Cursor;
float FontSize = 12.0f * UI()->Scale();
TextRender()->SetCursor(&Cursor, Button.x, Button.y + (Button.h - FontSize) / 2.f, 12.0f * UI()->Scale(), TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Button.w;
if(g_Config.m_UiColorizeGametype)
{
@ -485,11 +508,11 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
ColorRGBA rgb = color_cast<ColorRGBA>(hsl);
TextRender()->TextColor(rgb);
TextRender()->TextEx(&Cursor, pItem->m_aGameType, -1);
UI()->DoLabelStreamed(*pItem->m_pUIElement->Get(g_OffsetColGameType), &Button, pItem->m_aGameType, FontSize, -1, Button.w, 1, true);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
}
else
TextRender()->TextEx(&Cursor, pItem->m_aGameType, -1);
UI()->DoLabelStreamed(*pItem->m_pUIElement->Get(g_OffsetColGameType), &Button, pItem->m_aGameType, FontSize, -1, Button.w, 1, true);
}
}
}
@ -620,13 +643,16 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
ButtonConnect.VSplitLeft(5.0f, NULL, &ButtonConnect);
static int s_RefreshButton = 0;
char aBuf[64];
auto Func = [this]() mutable -> const char * {
if(ServerBrowser()->IsRefreshing())
str_format(aBuf, sizeof(aBuf), "%s (%d%%)", Localize("Refresh"), ServerBrowser()->LoadingProgression());
str_format(m_aLocalStringHelper, sizeof(m_aLocalStringHelper), "%s (%d%%)", Localize("Refresh"), ServerBrowser()->LoadingProgression());
else
str_copy(aBuf, Localize("Refresh"), sizeof(aBuf));
str_copy(m_aLocalStringHelper, Localize("Refresh"), sizeof(m_aLocalStringHelper));
if(DoButton_Menu(&s_RefreshButton, aBuf, 0, &ButtonRefresh, NULL, CUI::CORNER_ALL) || Input()->KeyPress(KEY_F5) || (Input()->KeyPress(KEY_R) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL))))
return m_aLocalStringHelper;
};
if(DoButtonMenu(m_RefreshButton, &s_RefreshButton, Func, 0, &ButtonRefresh, true, false, CUI::CORNER_ALL) || Input()->KeyPress(KEY_F5) || (Input()->KeyPress(KEY_R) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL))))
{
if(g_Config.m_UiPage == PAGE_INTERNET)
ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET);
@ -650,7 +676,10 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
}
static int s_JoinButton = 0;
if(DoButton_Menu(&s_JoinButton, Localize("Connect"), 0, &ButtonConnect, NULL, CUI::CORNER_ALL, 5, 0, vec4(0.7f, 1, 0.7f, 0.1f), vec4(0.7f, 1, 0.7f, 0.2f)) || m_EnterPressed)
if(DoButtonMenu(
m_ConnectButton, &s_JoinButton, []() -> const char * { return Localize("Connect"); }, 0, &ButtonConnect, false, false, CUI::CORNER_ALL, 5, 0, vec4(0.7f, 1, 0.7f, 0.1f), vec4(0.7f, 1, 0.7f, 0.2f)) ||
m_EnterPressed)
{
Client()->Connect(g_Config.m_UiServerAddress);
m_EnterPressed = false;

View file

@ -1443,6 +1443,7 @@ void CMenus::RenderLanguageSelection(CUIRect MainView)
{
str_copy(g_Config.m_ClLanguagefile, s_Languages[s_SelectedLanguage].m_FileName, sizeof(g_Config.m_ClLanguagefile));
g_Localization.Load(s_Languages[s_SelectedLanguage].m_FileName, Storage(), Console());
GameClient()->OnLanguageChange();
}
}

View file

@ -202,8 +202,8 @@ void CNamePlates::RenderNameplatePos(vec2 Position, const CNetObj_PlayerInfo *pP
}
}
TextRender()->TextColor(1, 1, 1, 1);
TextRender()->TextOutlineColor(0.0f, 0.0f, 0.0f, 0.3f);
TextRender()->TextColor(TextRender()->DefaultTextColor());
TextRender()->TextOutlineColor(TextRender()->DefaultTextOutlineColor());
TextRender()->SetRenderFlags(0);
}

View file

@ -948,6 +948,7 @@ void CGameClient::OnWindowResize()
for(int i = 0; i < m_All.m_Num; i++)
m_All.m_paComponents[i]->OnWindowResize();
UI()->OnWindowResize();
TextRender()->OnWindowResize();
}
@ -957,6 +958,11 @@ void CGameClient::OnWindowResizeCB(void *pUser)
pClient->OnWindowResize();
}
void CGameClient::OnLanguageChange()
{
UI()->OnLanguageChange();
}
void CGameClient::OnRconType(bool UsernameReq)
{
m_pGameConsole->RequireUsername(UsernameReq);

View file

@ -378,6 +378,8 @@ public:
void OnWindowResize();
static void OnWindowResizeCB(void *pUser);
void OnLanguageChange();
virtual const char *GetItemName(int Type);
virtual const char *Version();
virtual const char *NetVersion();

View file

@ -455,6 +455,31 @@ int CRenderTools::CreateRoundRectQuadContainer(float x, float y, float w, float
return ContainerIndex;
}
void CRenderTools::DrawUIElRect(CUIElement::SUIElementRect &ElUIRect, const CUIRect *pRect, ColorRGBA Color, int Corners, float Rounding)
{
bool NeedsRecreate = false;
if(ElUIRect.m_UIRectQuadContainer == -1 || ElUIRect.m_X != pRect->x || ElUIRect.m_Y != pRect->y || ElUIRect.m_Width != pRect->w || ElUIRect.m_Height != pRect->h)
{
if(ElUIRect.m_UIRectQuadContainer != -1)
Graphics()->DeleteQuadContainer(ElUIRect.m_UIRectQuadContainer);
NeedsRecreate = true;
}
if(NeedsRecreate)
{
ElUIRect.m_X = pRect->x;
ElUIRect.m_Y = pRect->y;
ElUIRect.m_Width = pRect->w;
ElUIRect.m_Height = pRect->h;
Graphics()->SetColor(Color);
ElUIRect.m_UIRectQuadContainer = CreateRoundRectQuadContainer(pRect->x, pRect->y, pRect->w, pRect->h, Rounding, Corners);
Graphics()->SetColor(1, 1, 1, 1);
}
Graphics()->TextureClear();
Graphics()->RenderQuadContainer(ElUIRect.m_UIRectQuadContainer, -1);
}
void CRenderTools::DrawRoundRect(float x, float y, float w, float h, float r)
{
DrawRoundRectExt(x, y, w, h, r, 0xf);

View file

@ -84,6 +84,8 @@ public:
int CreateRoundRectQuadContainer(float x, float y, float w, float h, float r, int Corners);
void DrawUIElRect(CUIElement::SUIElementRect &ElUIRect, const CUIRect *pRect, ColorRGBA Color, int Corners, float Rounding);
void DrawUIRect(const CUIRect *pRect, ColorRGBA Color, int Corners, float Rounding);
void DrawUIRect4(const CUIRect *pRect, vec4 ColorTopLeft, vec4 ColorTopRight, vec4 ColorBottomLeft, vec4 ColorBottomRight, int Corners, float Rounding);

View file

@ -8,6 +8,11 @@
#include <engine/shared/config.h>
#include <engine/textrender.h>
void CUIElement::Init(CUI *pUI)
{
pUI->AddUIElement(this);
}
/********************************************************
UI
*********************************************************/
@ -32,6 +37,62 @@ CUI::CUI()
m_Screen.h = 480.0f;
}
CUI::~CUI()
{
for(CUIElement *&pEl : m_OwnUIElements)
{
delete pEl;
}
m_OwnUIElements.clear();
}
CUIElement *CUI::GetNewUIElement()
{
CUIElement *pNewEl = new CUIElement(this);
m_OwnUIElements.push_back(pNewEl);
return pNewEl;
}
void CUI::AddUIElement(CUIElement *pElement)
{
m_UIElements.push_back(pElement);
}
void CUI::ResetUIElement(CUIElement &UIElement)
{
for(CUIElement::SUIElementRect &Rect : UIElement.m_UIRects)
{
if(Rect.m_UIRectQuadContainer != -1)
Graphics()->DeleteQuadContainer(Rect.m_UIRectQuadContainer);
Rect.m_UIRectQuadContainer = -1;
if(Rect.m_UITextContainer != -1)
TextRender()->DeleteTextContainer(Rect.m_UITextContainer);
Rect.m_UITextContainer = -1;
}
UIElement.Clear();
}
void CUI::OnElementsReset()
{
for(CUIElement *pEl : m_UIElements)
{
ResetUIElement(*pEl);
}
}
void CUI::OnWindowResize()
{
OnElementsReset();
}
void CUI::OnLanguageChange()
{
OnElementsReset();
}
int CUI::Update(float Mx, float My, float Mwx, float Mwy, int Buttons)
{
m_MouseX = Mx;
@ -274,6 +335,11 @@ void CUIRect::HMargin(float Cut, CUIRect *pOtherRect) const
}
int CUI::DoButtonLogic(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
{
return DoButtonLogic(pID, Checked, pRect);
}
int CUI::DoButtonLogic(const void *pID, int Checked, const CUIRect *pRect)
{
// logic
int ReturnValue = 0;
@ -403,3 +469,94 @@ void CUI::DoLabelScaled(const CUIRect *r, const char *pText, float Size, int Ali
{
DoLabel(r, pText, Size * Scale(), Align, MaxWidth, AlignVertically);
}
void CUI::DoLabel(CUIElement::SUIElementRect &RectEl, const CUIRect *pRect, const char *pText, float Size, int Align, int MaxWidth, int AlignVertically, bool StopAtEnd, int StrLen, CTextCursor *pReadCursor)
{
float AlignedSize = 0;
float MaxCharacterHeightInLine = 0;
float tw = TextRender()->TextWidth(0, Size, pText, -1, MaxWidth, &AlignedSize, &MaxCharacterHeightInLine);
float AlignmentVert = pRect->y + (pRect->h - AlignedSize) / 2.f;
float AlignmentHori = 0;
CTextCursor Cursor;
int Flags = TEXTFLAG_RENDER | (StopAtEnd ? TEXTFLAG_STOP_AT_END : 0);
if(AlignVertically == 0)
{
AlignmentVert = pRect->y + (pRect->h - AlignedSize) / 2.f - (AlignedSize - MaxCharacterHeightInLine) / 2.f;
}
if(Align == 0)
{
AlignmentHori = pRect->x + (pRect->w - tw) / 2.f;
}
else if(Align < 0)
{
AlignmentHori = pRect->x;
}
else if(Align > 0)
{
AlignmentHori = pRect->x + pRect->w - tw;
}
if(pReadCursor)
{
Cursor = *pReadCursor;
}
else
{
TextRender()->SetCursor(&Cursor, AlignmentHori, AlignmentVert, Size, Flags);
}
Cursor.m_LineWidth = MaxWidth;
RectEl.m_UITextContainer = TextRender()->CreateTextContainer(&Cursor, pText, StrLen);
RectEl.m_Cursor = Cursor;
}
void CUI::DoLabelStreamed(CUIElement::SUIElementRect &RectEl, const CUIRect *pRect, const char *pText, float Size, int Align, int MaxWidth, int AlignVertically, bool StopAtEnd, int StrLen, CTextCursor *pReadCursor)
{
bool NeedsRecreate = false;
if(RectEl.m_UITextContainer == -1 || RectEl.m_X != pRect->x || RectEl.m_Y != pRect->y || RectEl.m_Width != pRect->w || RectEl.m_Height != pRect->h)
{
NeedsRecreate = true;
}
else
{
if(StrLen <= -1)
{
if(str_comp(RectEl.m_Text.c_str(), pText) != 0)
NeedsRecreate = true;
}
else
{
if(StrLen != (int)RectEl.m_Text.size() || str_comp_num(RectEl.m_Text.c_str(), pText, StrLen) != 0)
NeedsRecreate = true;
}
}
if(NeedsRecreate)
{
if(RectEl.m_UITextContainer != -1)
TextRender()->DeleteTextContainer(RectEl.m_UITextContainer);
RectEl.m_UITextContainer = -1;
RectEl.m_X = pRect->x;
RectEl.m_Y = pRect->y;
RectEl.m_Width = pRect->w;
RectEl.m_Height = pRect->h;
if(StrLen > 0)
RectEl.m_Text = std::string(pText, StrLen);
else if(StrLen < 0)
RectEl.m_Text = pText;
else
RectEl.m_Text.clear();
DoLabel(RectEl, pRect, pText, Size, Align, MaxWidth, AlignVertically, StopAtEnd, StrLen, pReadCursor);
}
STextRenderColor ColorText(TextRender()->DefaultTextColor());
STextRenderColor ColorTextOutline(TextRender()->DefaultTextOutlineColor());
if(RectEl.m_UITextContainer != -1)
TextRender()->RenderTextContainer(RectEl.m_UITextContainer, &ColorText, &ColorTextOutline);
}

View file

@ -3,6 +3,11 @@
#ifndef GAME_CLIENT_UI_H
#define GAME_CLIENT_UI_H
#include <base/system.h>
#include <engine/textrender.h>
#include <string>
#include <vector>
class CUIRect
{
// TODO: Refactor: Redo UI scaling
@ -97,6 +102,65 @@ public:
void HMargin(float Cut, CUIRect *pOtherRect) const;
};
class CUI;
class CUIElement
{
friend class CUI;
CUIElement(CUI *pUI) { Init(pUI); }
public:
struct SUIElementRect
{
public:
int m_UIRectQuadContainer;
int m_UITextContainer;
float m_X;
float m_Y;
float m_Width;
float m_Height;
std::string m_Text;
CTextCursor m_Cursor;
SUIElementRect() :
m_UIRectQuadContainer(-1), m_UITextContainer(-1), m_X(-1), m_Y(-1), m_Width(-1), m_Height(-1)
{
}
};
protected:
std::vector<SUIElementRect> m_UIRects;
// used for marquees or other user implemented things
int64 m_ElementTime;
public:
CUIElement() = default;
void Init(CUI *pUI);
SUIElementRect *Get(size_t Index)
{
return &m_UIRects[Index];
}
size_t Size()
{
return m_UIRects.size();
}
void Clear() { m_UIRects.clear(); }
void Add(SUIElementRect &ElRect)
{
m_UIRects.push_back(ElRect);
}
};
class CUI
{
const void *m_pHotItem;
@ -112,6 +176,9 @@ class CUI
class IGraphics *m_pGraphics;
class ITextRender *m_pTextRender;
std::vector<CUIElement *> m_OwnUIElements; // ui elements maintained by CUI class
std::vector<CUIElement *> m_UIElements;
public:
// TODO: Refactor: Fill this in
void SetGraphics(class IGraphics *pGraphics, class ITextRender *pTextRender)
@ -123,6 +190,16 @@ public:
class ITextRender *TextRender() { return m_pTextRender; }
CUI();
~CUI();
void ResetUIElement(CUIElement &UIElement);
CUIElement *GetNewUIElement();
void AddUIElement(CUIElement *pElement);
void OnElementsReset();
void OnWindowResize();
void OnLanguageChange();
enum
{
@ -173,12 +250,16 @@ public:
void SetScale(float s);
float Scale();
int DoButtonLogic(const void *pID, int Checked, const CUIRect *pRect);
int DoButtonLogic(const void *pID, const char *pText /* TODO: Refactor: Remove */, int Checked, const CUIRect *pRect);
int DoPickerLogic(const void *pID, const CUIRect *pRect, float *pX, float *pY);
// TODO: Refactor: Remove this?
void DoLabel(const CUIRect *pRect, const char *pText, float Size, int Align, int MaxWidth = -1, int AlignVertically = 1);
void DoLabelScaled(const CUIRect *pRect, const char *pText, float Size, int Align, int MaxWidth = -1, int AlignVertically = 1);
void DoLabel(CUIElement::SUIElementRect &RectEl, const CUIRect *pRect, const char *pText, float Size, int Align, int MaxWidth = -1, int AlignVertically = 1, bool StopAtEnd = false, int StrLen = -1, class CTextCursor *pReadCursor = NULL);
void DoLabelStreamed(CUIElement::SUIElementRect &RectEl, const CUIRect *pRect, const char *pText, float Size, int Align, int MaxWidth = -1, int AlignVertically = 1, bool StopAtEnd = false, int StrLen = -1, class CTextCursor *pReadCursor = NULL);
};
#endif