ddnet/src/game/client/components/menus_browser.cpp

1447 lines
49 KiB
C++
Raw Normal View History

2010-11-20 10:37:14 +00:00
/* (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. */
2011-03-23 12:06:35 +00:00
#include <engine/config.h>
#include <engine/friends.h>
#include <engine/graphics.h>
#include <engine/keys.h>
2010-05-29 07:25:38 +00:00
#include <engine/serverbrowser.h>
#include <engine/textrender.h>
#include <engine/updater.h>
2010-05-29 07:25:38 +00:00
#include <engine/shared/config.h>
2010-05-29 07:25:38 +00:00
#include <game/generated/client_data.h>
#include <game/generated/protocol.h>
2010-05-29 07:25:38 +00:00
#include <game/localization.h>
#include <game/version.h>
#include <game/client/render.h>
#include <game/client/ui.h>
#include <game/client/components/countryflags.h>
#include <game/client/components/console.h>
#include "menus.h"
2010-05-29 07:25:38 +00:00
void CMenus::RenderServerbrowserServerList(CUIRect View)
{
CUIRect Headers;
CUIRect Status;
2010-05-29 07:25:38 +00:00
View.HSplitTop(ms_ListheaderHeight, &Headers, &View);
View.HSplitBottom(28.0f, &View, &Status);
// split of the scrollbar
2010-05-29 07:25:38 +00:00
RenderTools()->DrawUIRect(&Headers, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f);
Headers.VSplitRight(20.0f, &Headers, 0);
struct CColumn
{
int m_ID;
2010-05-29 07:25:38 +00:00
int m_Sort;
CLocConstString m_Caption;
int m_Direction;
float m_Width;
int m_Flags;
CUIRect m_Rect;
CUIRect m_Spacer;
};
2010-05-29 07:25:38 +00:00
enum
{
FIXED=1,
SPACER=2,
2010-05-29 07:25:38 +00:00
COL_FLAG_LOCK=0,
COL_FLAG_FAV,
COL_NAME,
COL_GAMETYPE,
COL_MAP,
COL_PLAYERS,
COL_PING,
COL_VERSION,
};
2010-05-29 07:25:38 +00:00
CColumn s_aCols[] = {
{-1, -1, " ", -1, 2.0f, 0, {0}, {0}},
{COL_FLAG_LOCK, -1, " ", -1, 14.0f, 0, {0}, {0}},
{COL_FLAG_FAV, -1, " ", -1, 14.0f, 0, {0}, {0}},
2014-12-15 20:24:04 +00:00
{COL_NAME, IServerBrowser::SORT_NAME, "Name", 0, 50.0f, 0, {0}, {0}}, // Localize - these strings are localized within CLocConstString
2010-05-31 11:07:58 +00:00
{COL_GAMETYPE, IServerBrowser::SORT_GAMETYPE, "Type", 1, 50.0f, 0, {0}, {0}},
{COL_MAP, IServerBrowser::SORT_MAP, "Map", 1, 120.0f + (Headers.w - 480) / 8, 0, {0}, {0}},
2010-05-31 11:07:58 +00:00
{COL_PLAYERS, IServerBrowser::SORT_NUMPLAYERS, "Players", 1, 60.0f, 0, {0}, {0}},
{-1, -1, " ", 1, 10.0f, 0, {0}, {0}},
2010-05-31 11:07:58 +00:00
{COL_PING, IServerBrowser::SORT_PING, "Ping", 1, 40.0f, FIXED, {0}, {0}},
2014-06-16 11:29:18 +00:00
#if defined(__ANDROID__)
{-1, -1, " ", 1, 50.0f, 0, {0}, {0}}, // Scrollbar
#endif
};
2010-08-08 22:35:37 +00:00
// This is just for scripts/update_localization.py to work correctly (all other strings are already Localize()'d somewhere else). Don't remove!
// Localize("Type");
2010-05-29 07:25:38 +00:00
int NumCols = sizeof(s_aCols)/sizeof(CColumn);
// do layout
2010-05-29 07:25:38 +00:00
for(int i = 0; i < NumCols; i++)
{
2010-05-29 07:25:38 +00:00
if(s_aCols[i].m_Direction == -1)
{
2010-05-29 07:25:38 +00:00
Headers.VSplitLeft(s_aCols[i].m_Width, &s_aCols[i].m_Rect, &Headers);
if(i+1 < NumCols)
{
2010-05-29 07:25:38 +00:00
//Cols[i].flags |= SPACER;
Headers.VSplitLeft(2, &s_aCols[i].m_Spacer, &Headers);
}
}
}
2010-05-29 07:25:38 +00:00
for(int i = NumCols-1; i >= 0; i--)
{
2010-05-29 07:25:38 +00:00
if(s_aCols[i].m_Direction == 1)
{
2010-05-29 07:25:38 +00:00
Headers.VSplitRight(s_aCols[i].m_Width, &Headers, &s_aCols[i].m_Rect);
Headers.VSplitRight(2, &Headers, &s_aCols[i].m_Spacer);
}
}
2010-05-29 07:25:38 +00:00
for(int i = 0; i < NumCols; i++)
{
2010-05-29 07:25:38 +00:00
if(s_aCols[i].m_Direction == 0)
s_aCols[i].m_Rect = Headers;
}
2010-05-29 07:25:38 +00:00
// do headers
2010-05-29 07:25:38 +00:00
for(int i = 0; i < NumCols; i++)
{
2010-05-29 07:25:38 +00:00
if(DoButton_GridHeader(s_aCols[i].m_Caption, s_aCols[i].m_Caption, g_Config.m_BrSort == s_aCols[i].m_Sort, &s_aCols[i].m_Rect))
{
2010-05-29 07:25:38 +00:00
if(s_aCols[i].m_Sort != -1)
{
2010-05-29 07:25:38 +00:00
if(g_Config.m_BrSort == s_aCols[i].m_Sort)
g_Config.m_BrSortOrder ^= 1;
else
2010-05-29 07:25:38 +00:00
g_Config.m_BrSortOrder = 0;
g_Config.m_BrSort = s_aCols[i].m_Sort;
}
}
}
2010-05-29 07:25:38 +00:00
RenderTools()->DrawUIRect(&View, vec4(0,0,0,0.15f), 0, 0);
CUIRect Scroll;
2014-06-16 11:29:18 +00:00
#if defined(__ANDROID__)
View.VSplitRight(50, &View, &Scroll);
#else
2010-05-29 07:25:38 +00:00
View.VSplitRight(15, &View, &Scroll);
2014-06-16 11:29:18 +00:00
#endif
2010-05-29 07:25:38 +00:00
int NumServers = ServerBrowser()->NumSortedServers();
// display important messages in the middle of the screen so no
// users misses it
{
2010-05-29 07:25:38 +00:00
CUIRect MsgBox = View;
if(m_ActivePage == PAGE_INTERNET && ServerBrowser()->IsRefreshingMasters())
UI()->DoLabelScaled(&MsgBox, Localize("Refreshing master servers"), 16.0f, 0);
2010-05-29 07:25:38 +00:00
else if(!ServerBrowser()->NumServers())
UI()->DoLabelScaled(&MsgBox, Localize("No servers found"), 16.0f, 0);
2010-05-29 07:25:38 +00:00
else if(ServerBrowser()->NumServers() && !NumServers)
UI()->DoLabelScaled(&MsgBox, Localize("No servers match your filter criteria"), 16.0f, 0);
}
2008-09-07 21:13:24 +00:00
2010-09-29 22:32:45 +00:00
int Num = (int)(View.h/s_aCols[0].m_Rect.h) + 1;
2010-05-29 07:25:38 +00:00
static int s_ScrollBar = 0;
static float s_ScrollValue = 0;
Scroll.HMargin(5.0f, &Scroll);
s_ScrollValue = DoScrollbarV(&s_ScrollBar, &Scroll, s_ScrollValue);
2010-09-29 22:32:45 +00:00
int ScrollNum = NumServers-Num+1;
2010-05-29 07:25:38 +00:00
if(ScrollNum > 0)
{
if(m_ScrollOffset >= 0)
2011-06-26 15:10:13 +00:00
{
s_ScrollValue = (float)(m_ScrollOffset)/ScrollNum;
m_ScrollOffset = -1;
2011-06-26 15:10:13 +00:00
}
if(Input()->KeyPress(KEY_MOUSE_WHEEL_UP) && UI()->MouseInside(&View))
s_ScrollValue -= 3.0f/ScrollNum;
if(Input()->KeyPress(KEY_MOUSE_WHEEL_DOWN) && UI()->MouseInside(&View))
s_ScrollValue += 3.0f/ScrollNum;
}
else
2010-05-29 07:25:38 +00:00
ScrollNum = 0;
if(Input()->KeyPress(KEY_TAB) && m_pClient->m_pGameConsole->IsClosed())
2015-06-28 13:43:34 +00:00
{
if(Input()->KeyIsPressed(KEY_LSHIFT) || Input()->KeyIsPressed(KEY_RSHIFT))
2015-06-28 13:43:34 +00:00
g_Config.m_UiToolboxPage = (g_Config.m_UiToolboxPage + 3 - 1) % 3;
else
g_Config.m_UiToolboxPage = (g_Config.m_UiToolboxPage + 3 + 1) % 3;
}
2015-08-27 14:42:21 +00:00
if(m_SelectedIndex > -1)
2010-05-29 07:25:38 +00:00
{
for(int i = 0; i < m_NumInputEvents; i++)
{
int NewIndex = -1;
if(m_aInputEvents[i].m_Flags&IInput::FLAG_PRESS)
{
if(m_aInputEvents[i].m_Key == KEY_DOWN) NewIndex = m_SelectedIndex + 1;
else if(m_aInputEvents[i].m_Key == KEY_UP) NewIndex = m_SelectedIndex - 1;
else if(m_aInputEvents[i].m_Key == KEY_PAGEUP) NewIndex = max(m_SelectedIndex - 25, 0);
else if(m_aInputEvents[i].m_Key == KEY_PAGEDOWN) NewIndex = min(m_SelectedIndex + 25, NumServers - 1);
else if(m_aInputEvents[i].m_Key == KEY_HOME) NewIndex = 0;
else if(m_aInputEvents[i].m_Key == KEY_END) NewIndex = NumServers - 1;
2010-05-29 07:25:38 +00:00
}
if(NewIndex > -1 && NewIndex < NumServers)
{
//scroll
float IndexY = View.y - s_ScrollValue*ScrollNum*s_aCols[0].m_Rect.h + NewIndex*s_aCols[0].m_Rect.h;
int Scroll = View.y > IndexY ? -1 : View.y+View.h < IndexY+s_aCols[0].m_Rect.h ? 1 : 0;
if(Scroll)
{
if(Scroll < 0)
{
int NumScrolls = (View.y-IndexY+s_aCols[0].m_Rect.h-1.0f)/s_aCols[0].m_Rect.h;
s_ScrollValue -= (1.0f/ScrollNum)*NumScrolls;
}
else
{
int NumScrolls = (IndexY+s_aCols[0].m_Rect.h-(View.y+View.h)+s_aCols[0].m_Rect.h-1.0f)/s_aCols[0].m_Rect.h;
s_ScrollValue += (1.0f/ScrollNum)*NumScrolls;
}
}
2010-05-29 07:25:38 +00:00
m_SelectedIndex = NewIndex;
2010-05-29 07:25:38 +00:00
const CServerInfo *pItem = ServerBrowser()->SortedGet(m_SelectedIndex);
str_copy(g_Config.m_UiServerAddress, pItem->m_aAddress, sizeof(g_Config.m_UiServerAddress));
}
}
2015-08-27 14:42:21 +00:00
}
if(s_ScrollValue < 0) s_ScrollValue = 0;
if(s_ScrollValue > 1) s_ScrollValue = 1;
// set clipping
2010-05-29 07:25:38 +00:00
UI()->ClipEnable(&View);
CUIRect OriginalView = View;
View.y -= s_ScrollValue*ScrollNum*s_aCols[0].m_Rect.h;
2010-05-29 07:25:38 +00:00
int NewSelected = -1;
2014-06-16 11:29:18 +00:00
int DoubleClicked = 0;
2010-05-29 07:25:38 +00:00
int NumPlayers = 0;
2008-09-04 18:42:26 +00:00
2010-05-29 07:25:38 +00:00
m_SelectedIndex = -1;
2011-06-26 15:10:13 +00:00
// reset friend counter
for(int i = 0; i < m_lFriends.size(); m_lFriends[i++].m_NumFound = 0);
2010-05-29 07:25:38 +00:00
for(int i = 0; i < NumServers; i++)
{
2010-05-29 07:25:38 +00:00
int ItemIndex = i;
const CServerInfo *pItem = ServerBrowser()->SortedGet(ItemIndex);
2018-10-29 21:03:57 +00:00
NumPlayers += pItem->m_NumFilteredPlayers;
2010-05-29 07:25:38 +00:00
CUIRect Row;
CUIRect SelectHitBox;
2010-05-29 07:25:38 +00:00
int Selected = str_comp(pItem->m_aAddress, g_Config.m_UiServerAddress) == 0; //selected_index==ItemIndex;
2014-06-16 11:29:18 +00:00
View.HSplitTop(ms_ListheaderHeight, &Row, &View);
2010-05-29 07:25:38 +00:00
SelectHitBox = Row;
if(Selected)
m_SelectedIndex = i;
2011-06-26 15:10:13 +00:00
// update friend counter
if(pItem->m_FriendState != IFriends::FRIEND_NO)
{
for(int j = 0; j < pItem->m_NumReceivedClients; ++j)
2011-06-26 15:10:13 +00:00
{
if(pItem->m_aClients[j].m_FriendState != IFriends::FRIEND_NO)
{
unsigned NameHash = str_quickhash(pItem->m_aClients[j].m_aName);
unsigned ClanHash = str_quickhash(pItem->m_aClients[j].m_aClan);
for(int f = 0; f < m_lFriends.size(); ++f)
{
2017-04-12 09:13:54 +00:00
if(((g_Config.m_ClFriendsIgnoreClan && m_lFriends[f].m_pFriendInfo->m_aName[0]) || (ClanHash == m_lFriends[f].m_pFriendInfo->m_ClanHash && !str_comp(m_lFriends[f].m_pFriendInfo->m_aClan, pItem->m_aClients[j].m_aClan))) &&
(!m_lFriends[f].m_pFriendInfo->m_aName[0] || (NameHash == m_lFriends[f].m_pFriendInfo->m_NameHash && !str_comp(m_lFriends[f].m_pFriendInfo->m_aName, pItem->m_aClients[j].m_aName))))
2011-06-26 15:10:13 +00:00
{
m_lFriends[f].m_NumFound++;
if(m_lFriends[f].m_pFriendInfo->m_aName[0])
break;
2011-06-26 15:10:13 +00:00
}
}
}
}
}
// make sure that only those in view can be selected
2010-05-29 07:25:38 +00:00
if(Row.y+Row.h > OriginalView.y && Row.y < OriginalView.y+OriginalView.h)
{
2010-05-29 07:25:38 +00:00
if(Selected)
{
CUIRect r = Row;
r.Margin(0.5f, &r);
2010-05-29 07:25:38 +00:00
RenderTools()->DrawUIRect(&r, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 4.0f);
}
// clip the selection
if(SelectHitBox.y < OriginalView.y) // top
{
2010-05-29 07:25:38 +00:00
SelectHitBox.h -= OriginalView.y-SelectHitBox.y;
SelectHitBox.y = OriginalView.y;
}
2010-05-29 07:25:38 +00:00
else if(SelectHitBox.y+SelectHitBox.h > OriginalView.y+OriginalView.h) // bottom
SelectHitBox.h = OriginalView.y+OriginalView.h-SelectHitBox.y;
if(UI()->DoButtonLogic(pItem, "", Selected, &SelectHitBox))
{
2010-05-29 07:25:38 +00:00
NewSelected = ItemIndex;
2014-06-16 11:29:18 +00:00
if(NewSelected == m_DoubleClickIndex)
DoubleClicked = 1;
m_DoubleClickIndex = NewSelected;
}
}
2010-05-29 07:25:38 +00:00
else
{
// reset active item, if not visible
if(UI()->ActiveItem() == pItem)
UI()->SetActiveItem(0);
2010-05-29 07:25:38 +00:00
// don't render invisible items
continue;
}
for(int c = 0; c < NumCols; c++)
{
2010-05-29 07:25:38 +00:00
CUIRect Button;
char aTemp[64];
Button.x = s_aCols[c].m_Rect.x;
Button.y = Row.y;
Button.h = Row.h;
Button.w = s_aCols[c].m_Rect.w;
int ID = s_aCols[c].m_ID;
2010-05-29 07:25:38 +00:00
if(ID == COL_FLAG_LOCK)
{
2010-05-29 07:25:38 +00:00
if(pItem->m_Flags & SERVER_FLAG_PASSWORD)
DoButton_Icon(IMAGE_BROWSEICONS, SPRITE_BROWSE_LOCK, &Button);
}
else if(ID == COL_FLAG_FAV)
{
2010-05-29 07:25:38 +00:00
if(pItem->m_Favorite)
DoButton_Icon(IMAGE_BROWSEICONS, SPRITE_BROWSE_HEART, &Button);
}
else if(ID == COL_NAME)
{
2010-05-29 07:25:38 +00:00
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);
2010-05-29 07:25:38 +00:00
Cursor.m_LineWidth = Button.w;
if(g_Config.m_BrFilterString[0] && (pItem->m_QuickSearchHit&IServerBrowser::QUICK_SERVERNAME))
{
// highlight the parts that matches
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));
2010-05-29 07:25:38 +00:00
TextRender()->TextColor(0.4f,0.4f,1.0f,1);
TextRender()->TextEx(&Cursor, pStr, str_length(g_Config.m_BrFilterString));
2010-05-29 07:25:38 +00:00
TextRender()->TextColor(1,1,1,1);
TextRender()->TextEx(&Cursor, pStr+str_length(g_Config.m_BrFilterString), -1);
}
else
2010-05-29 07:25:38 +00:00
TextRender()->TextEx(&Cursor, pItem->m_aName, -1);
}
else
2010-05-29 07:25:38 +00:00
TextRender()->TextEx(&Cursor, pItem->m_aName, -1);
}
else if(ID == COL_MAP)
{
if(g_Config.m_UiPage == PAGE_DDNET)
{
CUIRect Icon;
Button.VMargin(4.0f, &Button);
Button.VSplitLeft(Button.h, &Icon, &Button);
Icon.Margin(2.0f, &Icon);
2017-08-30 19:50:09 +00:00
if(pItem->m_HasRank == 1)
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))
{
// highlight the parts that matches
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));
TextRender()->TextColor(0.4f,0.4f,1.0f,1);
TextRender()->TextEx(&Cursor, pStr, str_length(g_Config.m_BrFilterString));
TextRender()->TextColor(1,1,1,1);
TextRender()->TextEx(&Cursor, pStr+str_length(g_Config.m_BrFilterString), -1);
}
else
TextRender()->TextEx(&Cursor, pItem->m_aMap, -1);
}
else
TextRender()->TextEx(&Cursor, pItem->m_aMap, -1);
}
else if(ID == COL_PLAYERS)
{
2011-06-26 15:10:13 +00:00
CUIRect Icon;
Button.VMargin(4.0f, &Button);
if(pItem->m_FriendState != IFriends::FRIEND_NO)
{
Button.VSplitLeft(Button.h, &Icon, &Button);
Icon.Margin(2.0f, &Icon);
DoButton_Icon(IMAGE_BROWSEICONS, SPRITE_BROWSE_HEART, &Icon);
}
2018-10-29 21:03:57 +00:00
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))
2010-05-29 07:25:38 +00:00
TextRender()->TextColor(0.4f,0.4f,1.0f,1);
UI()->DoLabelScaled(&Button, aTemp, 12.0f, 1);
2010-05-29 07:25:38 +00:00
TextRender()->TextColor(1,1,1,1);
}
else if(ID == COL_PING)
{
2010-05-29 07:25:38 +00:00
str_format(aTemp, sizeof(aTemp), "%i", pItem->m_Latency);
if(g_Config.m_UiColorizePing)
{
vec3 rgb = HslToRgb(vec3((300.0f - clamp(pItem->m_Latency, 0, 300)) / 1000.0f, 1.0f, 0.5f));
TextRender()->TextColor(rgb.r, rgb.g, rgb.b, 1.0f);
}
UI()->DoLabelScaled(&Button, aTemp, 12.0f, 1);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
}
else if(ID == COL_VERSION)
{
2010-05-29 07:25:38 +00:00
const char *pVersion = pItem->m_aVersion;
UI()->DoLabelScaled(&Button, pVersion, 12.0f, 1);
2010-05-29 07:25:38 +00:00
}
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;
2008-10-21 18:50:23 +00:00
if(g_Config.m_UiColorizeGametype)
{
vec3 hsl = vec3(1.0f, 1.0f, 1.0f);
if(IsVanilla(pItem))
hsl = vec3(0.33f, 1.0f, 0.75f);
else if(IsCatch(pItem))
hsl = vec3(0.17f, 1.0f, 0.75f);
else if(IsInsta(pItem))
hsl = vec3(0.00f, 1.0f, 0.75f);
else if(IsFNG(pItem))
hsl = vec3(0.83f, 1.0f, 0.75f);
else if(IsDDNet(pItem))
hsl = vec3(0.58f, 1.0f, 0.75f);
else if(IsDDRace(pItem))
hsl = vec3(0.75f, 1.0f, 0.75f);
else if(IsRace(pItem))
hsl = vec3(0.46f, 1.0f, 0.75f);
vec3 rgb = HslToRgb(hsl);
TextRender()->TextColor(rgb.r, rgb.g, rgb.b, 1.0f);
TextRender()->TextEx(&Cursor, pItem->m_aGameType, -1);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
}
else
TextRender()->TextEx(&Cursor, pItem->m_aGameType, -1);
}
}
}
2009-10-27 14:38:53 +00:00
UI()->ClipDisable();
2010-05-29 07:25:38 +00:00
if(NewSelected != -1)
{
// select the new server
2010-05-29 07:25:38 +00:00
const CServerInfo *pItem = ServerBrowser()->SortedGet(NewSelected);
str_copy(g_Config.m_UiServerAddress, pItem->m_aAddress, sizeof(g_Config.m_UiServerAddress));
2014-06-16 11:29:18 +00:00
#if defined(__ANDROID__)
if(DoubleClicked)
#else
if(Input()->MouseDoubleClick() && DoubleClicked)
2014-06-16 11:29:18 +00:00
#endif
2010-05-29 07:25:38 +00:00
Client()->Connect(g_Config.m_UiServerAddress);
}
2010-05-29 07:25:38 +00:00
RenderTools()->DrawUIRect(&Status, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f);
Status.Margin(5.0f, &Status);
CUIRect QuickSearch, QuickExclude, Button, Status2, Status3;
2015-03-22 18:21:41 +00:00
Status.VSplitRight(250.0f, &Status2, &Status3);
Status2.VSplitMid(&QuickSearch, &QuickExclude);
QuickExclude.VSplitLeft(5.0f, 0, &QuickExclude);
2009-01-21 18:09:06 +00:00
// render quick search
{
const char *pLabel = "\xEE\xA2\xB6"; // U+0e8b6
TextRender()->SetCurFont(TextRender()->GetFont(TEXT_FONT_ICON_FONT));
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
UI()->DoLabelScaled(&QuickSearch, pLabel, 16.0f, -1);
float w = TextRender()->TextWidth(0, 16.0f, pLabel, -1);
TextRender()->SetRenderFlags(0);
TextRender()->SetCurFont(NULL);
QuickSearch.VSplitLeft(w, 0, &QuickSearch);
QuickSearch.VSplitLeft(5.0f, 0, &QuickSearch);
static float Offset = 0.0f;
if(Input()->KeyPress(KEY_F) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL)))
UI()->SetActiveItem(&g_Config.m_BrFilterString);
2010-05-29 07:25:38 +00:00
static int s_ClearButton = 0;
if(DoClearableEditBox(&g_Config.m_BrFilterString, &s_ClearButton, &QuickSearch, g_Config.m_BrFilterString, sizeof(g_Config.m_BrFilterString), 12.0f, &Offset, false, CUI::CORNER_ALL, Localize("Search")))
Client()->ServerBrowserUpdate();
2010-05-29 07:25:38 +00:00
}
// render quick exclude
{
const char *pLabel = Localize("\xEE\x85\x8B"); // U+0e14b
TextRender()->SetCurFont(TextRender()->GetFont(TEXT_FONT_ICON_FONT));
TextRender()->SetRenderFlags(ETextRenderFlags::TEXT_RENDER_FLAG_ONLY_ADVANCE_WIDTH | ETextRenderFlags::TEXT_RENDER_FLAG_NO_X_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_Y_BEARING | ETextRenderFlags::TEXT_RENDER_FLAG_NO_OVERSIZE);
UI()->DoLabelScaled(&QuickExclude, pLabel, 16.0f, -1);
float w = TextRender()->TextWidth(0, 16.0f, pLabel, -1);
TextRender()->SetRenderFlags(0);
TextRender()->SetCurFont(NULL);
QuickExclude.VSplitLeft(w, 0, &QuickExclude);
QuickExclude.VSplitLeft(5.0f, 0, &QuickExclude);
QuickExclude.VSplitLeft(QuickExclude.w-15.0f, &QuickExclude, &Button);
static int s_ClearButton = 0;
static float Offset = 0.0f;
if(Input()->KeyPress(KEY_X) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL)))
UI()->SetActiveItem(&g_Config.m_BrExcludeString);
if(DoClearableEditBox(&g_Config.m_BrExcludeString, &s_ClearButton, &QuickExclude, g_Config.m_BrExcludeString, sizeof(g_Config.m_BrExcludeString), 12.0f, &Offset, false, CUI::CORNER_ALL, Localize("Exclude")))
Client()->ServerBrowserUpdate();
}
// render status
char aBuf[128];
str_format(aBuf, sizeof(aBuf), Localize("%d of %d servers, %d players"), ServerBrowser()->NumSortedServers(), ServerBrowser()->NumServers(), NumPlayers);
Status3.VSplitRight(TextRender()->TextWidth(0, 14.0f, aBuf, -1), 0, &Status3);
UI()->DoLabelScaled(&Status3, aBuf, 14.0f, -1);
2008-09-04 18:42:26 +00:00
}
2010-05-29 07:25:38 +00:00
void CMenus::RenderServerbrowserFilters(CUIRect View)
2008-09-04 18:42:26 +00:00
{
CUIRect ServerFilter = View, FilterHeader;
const float FontSize = 12.0f;
2014-09-20 09:47:51 +00:00
ServerFilter.HSplitBottom(0.0f, &ServerFilter, 0);
// server filter
ServerFilter.HSplitTop(ms_ListheaderHeight, &FilterHeader, &ServerFilter);
RenderTools()->DrawUIRect(&FilterHeader, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f);
RenderTools()->DrawUIRect(&ServerFilter, vec4(0,0,0,0.15f), CUI::CORNER_B, 4.0f);
UI()->DoLabelScaled(&FilterHeader, Localize("Server filter"), FontSize+2.0f, 0);
2014-12-14 15:45:18 +00:00
CUIRect Button, Button2;
2008-09-04 18:42:26 +00:00
ServerFilter.VSplitLeft(5.0f, 0, &ServerFilter);
ServerFilter.Margin(3.0f, &ServerFilter);
ServerFilter.VMargin(5.0f, &ServerFilter);
2008-09-04 18:42:26 +00:00
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
if(DoButton_CheckBox(&g_Config.m_BrFilterEmpty, Localize("Has people playing"), g_Config.m_BrFilterEmpty, &Button))
2010-05-29 07:25:38 +00:00
g_Config.m_BrFilterEmpty ^= 1;
2008-09-04 18:42:26 +00:00
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
if(DoButton_CheckBox(&g_Config.m_BrFilterSpectators, Localize("Count players only"), g_Config.m_BrFilterSpectators, &Button))
g_Config.m_BrFilterSpectators ^= 1;
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
if(DoButton_CheckBox(&g_Config.m_BrFilterFull, Localize("Server not full"), g_Config.m_BrFilterFull, &Button))
2010-05-29 07:25:38 +00:00
g_Config.m_BrFilterFull ^= 1;
2008-09-04 18:42:26 +00:00
2011-03-23 12:06:35 +00:00
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
if(DoButton_CheckBox(&g_Config.m_BrFilterFriends, Localize("Show friends only"), g_Config.m_BrFilterFriends, &Button))
2011-03-23 12:06:35 +00:00
g_Config.m_BrFilterFriends ^= 1;
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
if(DoButton_CheckBox(&g_Config.m_BrFilterPw, Localize("No password"), g_Config.m_BrFilterPw, &Button))
2010-05-29 07:25:38 +00:00
g_Config.m_BrFilterPw ^= 1;
2008-09-04 18:42:26 +00:00
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
if(DoButton_CheckBox(&g_Config.m_BrFilterCompatversion, Localize("Compatible version"), g_Config.m_BrFilterCompatversion, &Button))
2010-05-29 07:25:38 +00:00
g_Config.m_BrFilterCompatversion ^= 1;
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
if(DoButton_CheckBox(&g_Config.m_BrFilterPure, Localize("Standard gametype"), g_Config.m_BrFilterPure, &Button))
2010-05-29 07:25:38 +00:00
g_Config.m_BrFilterPure ^= 1;
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
if(DoButton_CheckBox(&g_Config.m_BrFilterPureMap, Localize("Standard map"), g_Config.m_BrFilterPureMap, &Button))
2010-05-29 07:25:38 +00:00
g_Config.m_BrFilterPureMap ^= 1;
2011-08-11 08:59:14 +00:00
2011-04-17 09:57:33 +00:00
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
if(DoButton_CheckBox(&g_Config.m_BrFilterGametypeStrict, Localize("Strict gametype filter"), g_Config.m_BrFilterGametypeStrict, &Button))
2011-04-17 09:57:33 +00:00
g_Config.m_BrFilterGametypeStrict ^= 1;
ServerFilter.HSplitTop(5.0f, 0, &ServerFilter);
2010-05-29 07:25:38 +00:00
ServerFilter.HSplitTop(19.0f, &Button, &ServerFilter);
UI()->DoLabelScaled(&Button, Localize("Game types:"), FontSize, -1);
Button.VSplitRight(60.0f, 0, &Button);
ServerFilter.HSplitTop(3.0f, 0, &ServerFilter);
static float Offset = 0.0f;
if(DoEditBox(&g_Config.m_BrFilterGametype, &Button, g_Config.m_BrFilterGametype, sizeof(g_Config.m_BrFilterGametype), FontSize, &Offset))
Client()->ServerBrowserUpdate();
2008-09-04 18:42:26 +00:00
{
ServerFilter.HSplitTop(19.0f, &Button, &ServerFilter);
2010-05-29 07:25:38 +00:00
CUIRect EditBox;
Button.VSplitRight(60.0f, &Button, &EditBox);
UI()->DoLabelScaled(&Button, Localize("Maximum ping:"), FontSize, -1);
2010-05-29 07:25:38 +00:00
char aBuf[5];
str_format(aBuf, sizeof(aBuf), "%d", g_Config.m_BrFilterPing);
static float Offset = 0.0f;
DoEditBox(&g_Config.m_BrFilterPing, &EditBox, aBuf, sizeof(aBuf), FontSize, &Offset);
g_Config.m_BrFilterPing = clamp(str_toint(aBuf), 0, 999);
}
2010-05-29 07:25:38 +00:00
// server address
ServerFilter.HSplitTop(3.0f, 0, &ServerFilter);
ServerFilter.HSplitTop(19.0f, &Button, &ServerFilter);
UI()->DoLabelScaled(&Button, Localize("Server address:"), FontSize, -1);
Button.VSplitRight(60.0f, 0, &Button);
static float OffsetAddr = 0.0f;
if(DoEditBox(&g_Config.m_BrFilterServerAddress, &Button, g_Config.m_BrFilterServerAddress, sizeof(g_Config.m_BrFilterServerAddress), FontSize, &OffsetAddr))
Client()->ServerBrowserUpdate();
// player country
{
CUIRect Rect;
ServerFilter.HSplitTop(3.0f, 0, &ServerFilter);
ServerFilter.HSplitTop(26.0f, &Button, &ServerFilter);
Button.VSplitRight(60.0f, &Button, &Rect);
Button.HMargin(3.0f, &Button);
if(DoButton_CheckBox(&g_Config.m_BrFilterCountry, Localize("Player country:"), g_Config.m_BrFilterCountry, &Button))
g_Config.m_BrFilterCountry ^= 1;
2011-08-11 08:59:14 +00:00
float OldWidth = Rect.w;
Rect.w = Rect.h*2;
Rect.x += (OldWidth-Rect.w)/2.0f;
vec4 Color(1.0f, 1.0f, 1.0f, g_Config.m_BrFilterCountry?1.0f: 0.5f);
m_pClient->m_pCountryFlags->Render(g_Config.m_BrFilterCountryIndex, &Color, Rect.x, Rect.y, Rect.w, Rect.h);
if(g_Config.m_BrFilterCountry && UI()->DoButtonLogic(&g_Config.m_BrFilterCountryIndex, "", 0, &Rect))
m_Popup = POPUP_COUNTRY;
}
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
if(DoButton_CheckBox(&g_Config.m_BrFilterConnectingPlayers, Localize("Filter connecting players"), g_Config.m_BrFilterConnectingPlayers, &Button))
g_Config.m_BrFilterConnectingPlayers ^= 1;
2014-12-14 15:45:18 +00:00
CUIRect ResetButton;
//ServerFilter.HSplitBottom(5.0f, &ServerFilter, 0);
ServerFilter.HSplitBottom(ms_ButtonHeight-2.0f, &ServerFilter, &ResetButton);
2014-09-19 21:52:09 +00:00
// ddnet country filters
if(g_Config.m_UiPage == PAGE_DDNET)
{
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
if(DoButton_CheckBox(&g_Config.m_BrIndicateFinished, Localize("Indicate map finish"), g_Config.m_BrIndicateFinished, &Button))
g_Config.m_BrIndicateFinished ^= 1;
if(g_Config.m_BrIndicateFinished)
{
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
if(DoButton_CheckBox(&g_Config.m_BrFilterUnfinishedMap, Localize("Unfinished map"), g_Config.m_BrFilterUnfinishedMap, &Button))
g_Config.m_BrFilterUnfinishedMap ^= 1;
}
else
{
g_Config.m_BrFilterUnfinishedMap = 0;
}
2014-09-19 21:52:09 +00:00
// add more space
2014-12-14 15:45:18 +00:00
ServerFilter.HSplitTop(10.0f, 0, &ServerFilter);
ServerFilter.HSplitTop(20.0f, &Button, &ServerFilter);
ServerFilter.HSplitTop(95.0f, &ServerFilter, 0);
2014-09-19 21:52:09 +00:00
2014-12-14 15:45:18 +00:00
RenderTools()->DrawUIRect(&ServerFilter, ms_ColorTabbarActive, CUI::CORNER_B, 10.0f);
2014-09-19 21:52:09 +00:00
2014-12-14 15:45:18 +00:00
Button.VSplitMid(&Button, &Button2);
2014-09-19 21:52:09 +00:00
2014-12-14 15:45:18 +00:00
static int s_ActivePage = 0;
2014-09-19 21:52:09 +00:00
2014-12-14 15:45:18 +00:00
static int s_CountriesButton = 0;
if(DoButton_MenuTab(&s_CountriesButton, Localize("Countries"), s_ActivePage == 0, &Button, CUI::CORNER_TL))
{
s_ActivePage = 0;
}
2014-09-19 21:52:09 +00:00
2014-12-14 15:45:18 +00:00
static int s_TypesButton = 0;
if(DoButton_MenuTab(&s_TypesButton, Localize("Types"), s_ActivePage == 1, &Button2, CUI::CORNER_TR))
2014-09-19 21:52:09 +00:00
{
2014-12-14 15:45:18 +00:00
s_ActivePage = 1;
}
2014-11-21 13:11:04 +00:00
2014-12-14 15:45:18 +00:00
if(s_ActivePage == 1)
{
int MaxTypes = ServerBrowser()->NumDDNetTypes();
int NumTypes = ServerBrowser()->NumDDNetTypes();
int PerLine = 3;
2014-09-19 21:52:09 +00:00
ServerFilter.HSplitTop(4.0f, 0, &ServerFilter);
ServerFilter.HSplitBottom(4.0f, &ServerFilter, 0);
2014-09-19 21:52:09 +00:00
2014-12-14 15:45:18 +00:00
const float TypesWidth = 40.0f;
const float TypesHeight = ServerFilter.h / ceil(MaxTypes / (float)PerLine);
2014-09-19 21:52:09 +00:00
2014-12-14 15:45:18 +00:00
CUIRect TypesRect, Left, Right;
2014-09-19 21:52:09 +00:00
2014-12-14 15:45:18 +00:00
static int s_aTypeButtons[64];
2014-09-19 21:52:09 +00:00
2014-12-14 15:45:18 +00:00
while(NumTypes > 0)
{
ServerFilter.HSplitTop(TypesHeight, &TypesRect, &ServerFilter);
TypesRect.VSplitMid(&Left, &Right);
for(int i = 0; i < PerLine && NumTypes > 0; i++, NumTypes--)
2014-09-19 21:52:09 +00:00
{
2014-12-14 15:45:18 +00:00
int TypeIndex = MaxTypes - NumTypes;
const char *pName = ServerBrowser()->GetDDNetType(TypeIndex);
bool Active = !ServerBrowser()->DDNetFiltered(g_Config.m_BrFilterExcludeTypes, pName);
2014-09-19 21:52:09 +00:00
2017-03-21 10:24:44 +00:00
vec2 Pos = vec2(TypesRect.x+TypesRect.w*((i+0.5f)/(float)PerLine), TypesRect.y);
2014-12-14 15:45:18 +00:00
// correct pos
Pos.x -= TypesWidth / 2.0f;
// create button logic
CUIRect Rect;
Rect.x = Pos.x;
Rect.y = Pos.y;
Rect.w = TypesWidth;
Rect.h = TypesHeight;
int Button = UI()->DoButtonLogic(&s_aTypeButtons[TypeIndex], "", 0, &Rect);
if(Button == 1)
2014-12-14 15:45:18 +00:00
{
// left click to toggle flag filter
if(Active)
2014-12-14 15:45:18 +00:00
ServerBrowser()->DDNetFilterAdd(g_Config.m_BrFilterExcludeTypes, pName);
else
ServerBrowser()->DDNetFilterRem(g_Config.m_BrFilterExcludeTypes, pName);
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET);
}
else if(Button == 2)
{
// right click to exclusively activate one
g_Config.m_BrFilterExcludeTypes[0] = '\0';
for(int j = 0; j < MaxTypes; ++j)
{
if(j != TypeIndex)
ServerBrowser()->DDNetFilterAdd(g_Config.m_BrFilterExcludeTypes, ServerBrowser()->GetDDNetType(j));
}
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET);
}
else if(Button == 3)
{
2018-07-10 09:29:02 +00:00
// middle click to reset (re-enable all)
g_Config.m_BrFilterExcludeTypes[0] = '\0';
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET);
}
2014-12-14 15:45:18 +00:00
vec4 Color(1.0f, 1.0f, 1.0f, 1.0f);
if(!Active)
2014-12-14 15:45:18 +00:00
Color.a = 0.2f;
TextRender()->TextColor(Color.r, Color.g, Color.b, Color.a);
UI()->DoLabelScaled(&Rect, pName, FontSize, 0);
TextRender()->TextColor(1.0, 1.0, 1.0, 1.0f);
2014-09-19 21:52:09 +00:00
}
2014-12-14 15:45:18 +00:00
}
}
else
{
ServerFilter.HSplitTop(17.0f, &ServerFilter, &ServerFilter);
vec4 Color(1.0f, 1.0f, 1.0f, 1.0f);
const float FlagWidth = 40.0f;
const float FlagHeight = 20.0f;
int MaxFlags = ServerBrowser()->NumDDNetCountries();
int NumFlags = ServerBrowser()->NumDDNetCountries();
int PerLine = MaxFlags > 9 ? 4 : 3;
CUIRect FlagsRect;
static int s_aFlagButtons[64];
while(NumFlags > 0)
{
ServerFilter.HSplitTop(30.0f, &FlagsRect, &ServerFilter);
2014-09-19 21:52:09 +00:00
2014-12-14 15:45:18 +00:00
for(int i = 0; i < PerLine && NumFlags > 0; i++, NumFlags--)
{
int CountryIndex = MaxFlags - NumFlags;
const char *pName = ServerBrowser()->GetDDNetCountryName(CountryIndex);
bool Active = !ServerBrowser()->DDNetFiltered(g_Config.m_BrFilterExcludeCountries, pName);
int FlagID = ServerBrowser()->GetDDNetCountryFlag(CountryIndex);
2017-03-21 10:24:44 +00:00
vec2 Pos = vec2(FlagsRect.x+FlagsRect.w*((i+0.5f)/(float)PerLine), FlagsRect.y);
2014-12-14 15:45:18 +00:00
// correct pos
Pos.x -= FlagWidth / 2.0f;
Pos.y -= FlagHeight / 2.0f;
// create button logic
CUIRect Rect;
Rect.x = Pos.x;
Rect.y = Pos.y;
Rect.w = FlagWidth;
Rect.h = FlagHeight;
2014-09-19 21:52:09 +00:00
int Button = UI()->DoButtonLogic(&s_aFlagButtons[CountryIndex], "", 0, &Rect);
if(Button == 1)
2014-12-14 15:45:18 +00:00
{
// left click to toggle flag filter
if(Active)
2014-12-14 15:45:18 +00:00
ServerBrowser()->DDNetFilterAdd(g_Config.m_BrFilterExcludeCountries, pName);
else
ServerBrowser()->DDNetFilterRem(g_Config.m_BrFilterExcludeCountries, pName);
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET);
}
else if(Button == 2)
{
// right click to exclusively activate one
g_Config.m_BrFilterExcludeCountries[0] = '\0';
for(int j = 0; j < MaxFlags; ++j)
{
if(j != CountryIndex)
ServerBrowser()->DDNetFilterAdd(g_Config.m_BrFilterExcludeCountries, ServerBrowser()->GetDDNetCountryName(j));
}
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET);
}
else if(Button == 3)
{
2018-07-10 09:29:02 +00:00
// middle click to reset (re-enable all)
g_Config.m_BrFilterExcludeCountries[0] = '\0';
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET);
}
2014-09-19 21:52:09 +00:00
2014-12-14 15:45:18 +00:00
vec4 Color(1.0f, 1.0f, 1.0f, 1.0f);
2014-09-19 21:52:09 +00:00
if(!Active)
2014-12-14 15:45:18 +00:00
Color.a = 0.2f;
m_pClient->m_pCountryFlags->Render(FlagID, &Color, Pos.x, Pos.y, FlagWidth, FlagHeight);
}
2014-09-19 21:52:09 +00:00
}
}
}
2010-05-29 07:25:38 +00:00
static int s_ClearButton = 0;
2014-12-14 15:45:18 +00:00
if(DoButton_Menu(&s_ClearButton, Localize("Reset filter"), 0, &ResetButton))
2008-09-04 18:42:26 +00:00
{
g_Config.m_BrFilterString[0] = 0;
g_Config.m_BrExcludeString[0] = 0;
2010-05-29 07:25:38 +00:00
g_Config.m_BrFilterFull = 0;
g_Config.m_BrFilterEmpty = 0;
g_Config.m_BrFilterSpectators = 0;
g_Config.m_BrFilterFriends = 0;
g_Config.m_BrFilterCountry = 0;
g_Config.m_BrFilterCountryIndex = -1;
2010-05-29 07:25:38 +00:00
g_Config.m_BrFilterPw = 0;
g_Config.m_BrFilterPing = 999;
g_Config.m_BrFilterGametype[0] = 0;
g_Config.m_BrFilterGametypeStrict = 0;
g_Config.m_BrFilterConnectingPlayers = 1;
g_Config.m_BrFilterUnfinishedMap = 0;
g_Config.m_BrFilterServerAddress[0] = 0;
2011-04-15 04:40:42 +00:00
g_Config.m_BrFilterPure = 0;
g_Config.m_BrFilterPureMap = 0;
g_Config.m_BrFilterCompatversion = 0;
g_Config.m_BrFilterExcludeCountries[0] = 0;
g_Config.m_BrFilterExcludeTypes[0] = 0;
Client()->ServerBrowserUpdate();
}
2008-09-04 18:42:26 +00:00
}
2010-05-29 07:25:38 +00:00
void CMenus::RenderServerbrowserServerDetail(CUIRect View)
2008-09-04 18:42:26 +00:00
{
2010-05-29 07:25:38 +00:00
CUIRect ServerDetails = View;
CUIRect ServerScoreBoard, ServerHeader;
const CServerInfo *pSelectedServer = ServerBrowser()->SortedGet(m_SelectedIndex);
2008-09-04 18:42:26 +00:00
// split off a piece to use for scoreboard
2011-03-23 12:06:35 +00:00
ServerDetails.HSplitTop(90.0f, &ServerDetails, &ServerScoreBoard);
ServerDetails.HSplitBottom(2.5f, &ServerDetails, 0x0);
2008-09-04 18:42:26 +00:00
// server details
CTextCursor Cursor;
2010-05-29 07:25:38 +00:00
const float FontSize = 12.0f;
ServerDetails.HSplitTop(ms_ListheaderHeight, &ServerHeader, &ServerDetails);
2010-05-29 07:25:38 +00:00
RenderTools()->DrawUIRect(&ServerHeader, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f);
RenderTools()->DrawUIRect(&ServerDetails, vec4(0,0,0,0.15f), CUI::CORNER_B, 4.0f);
UI()->DoLabelScaled(&ServerHeader, Localize("Server details"), FontSize+2.0f, 0);
if(pSelectedServer)
2008-09-04 18:42:26 +00:00
{
ServerDetails.VSplitLeft(5.0f, 0, &ServerDetails);
ServerDetails.Margin(3.0f, &ServerDetails);
2010-05-29 07:25:38 +00:00
CUIRect Row;
static CLocConstString s_aLabels[] = {
2010-05-31 11:07:58 +00:00
"Version", // Localize - these strings are localized within CLocConstString
"Game type",
"Ping"};
2010-05-29 07:25:38 +00:00
CUIRect LeftColumn;
CUIRect RightColumn;
2010-05-29 07:25:38 +00:00
//
{
2010-05-29 07:25:38 +00:00
CUIRect Button;
ServerDetails.HSplitBottom(20.0f, &ServerDetails, &Button);
Button.VSplitLeft(5.0f, 0, &Button);
2010-05-29 07:25:38 +00:00
static int s_AddFavButton = 0;
if(DoButton_CheckBox(&s_AddFavButton, Localize("Favorite"), pSelectedServer->m_Favorite, &Button))
{
2010-05-29 07:25:38 +00:00
if(pSelectedServer->m_Favorite)
ServerBrowser()->RemoveFavorite(pSelectedServer->m_NetAddr);
2008-09-04 18:42:26 +00:00
else
2010-05-29 07:25:38 +00:00
ServerBrowser()->AddFavorite(pSelectedServer->m_NetAddr);
}
2008-09-04 18:42:26 +00:00
}
2010-05-29 07:25:38 +00:00
ServerDetails.VSplitLeft(5.0f, 0x0, &ServerDetails);
ServerDetails.VSplitLeft(80.0f, &LeftColumn, &RightColumn);
for(unsigned int i = 0; i < sizeof(s_aLabels) / sizeof(s_aLabels[0]); i++)
2008-09-04 18:42:26 +00:00
{
2010-05-29 07:25:38 +00:00
LeftColumn.HSplitTop(15.0f, &Row, &LeftColumn);
UI()->DoLabelScaled(&Row, s_aLabels[i], FontSize, -1);
2008-09-04 18:42:26 +00:00
}
2010-05-29 07:25:38 +00:00
RightColumn.HSplitTop(15.0f, &Row, &RightColumn);
2018-04-04 00:40:30 +00:00
TextRender()->SetCursor(&Cursor, Row.x, Row.y + (15.f - FontSize) / 2.f, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Row.w;
TextRender()->TextEx(&Cursor, pSelectedServer->m_aVersion, -1);
2010-05-29 07:25:38 +00:00
RightColumn.HSplitTop(15.0f, &Row, &RightColumn);
2018-04-04 00:40:30 +00:00
TextRender()->SetCursor(&Cursor, Row.x, Row.y + (15.f - FontSize) / 2.f, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Row.w;
TextRender()->TextEx(&Cursor, pSelectedServer->m_aGameType, -1);
2010-05-29 07:25:38 +00:00
char aTemp[16];
str_format(aTemp, sizeof(aTemp), "%d", pSelectedServer->m_Latency);
RightColumn.HSplitTop(15.0f, &Row, &RightColumn);
2018-04-04 00:40:30 +00:00
TextRender()->SetCursor(&Cursor, Row.x, Row.y + (15.f - FontSize) / 2.f, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Row.w;
TextRender()->TextEx(&Cursor, aTemp, -1);
2008-09-04 18:42:26 +00:00
}
2010-05-29 07:25:38 +00:00
2008-09-04 18:42:26 +00:00
// server scoreboard
2014-01-10 11:22:48 +00:00
//ServerScoreBoard.HSplitBottom(20.0f, &ServerScoreBoard, 0x0);
2010-05-29 07:25:38 +00:00
2011-06-26 15:10:13 +00:00
if(pSelectedServer)
2008-09-04 18:42:26 +00:00
{
2014-01-08 05:15:56 +00:00
static int s_VoteList = 0;
static float s_ScrollValue = 0;
UiDoListboxStart(&s_VoteList, &ServerScoreBoard, 26.0f, Localize("Scoreboard"), "", pSelectedServer->m_NumReceivedClients, 1, -1, s_ScrollValue);
2014-01-08 05:15:56 +00:00
for(int i = 0; i < pSelectedServer->m_NumReceivedClients; i++)
{
CListboxItem Item = UiDoListboxNextItem(&i);
2014-01-08 05:15:56 +00:00
if(!Item.m_Visible)
continue;
CUIRect Name, Clan, Score, Flag;
2014-01-08 05:15:56 +00:00
Item.m_Rect.HSplitTop(25.0f, &Name, &Item.m_Rect);
2011-06-26 15:10:13 +00:00
if(UI()->DoButtonLogic(&pSelectedServer->m_aClients[i], "", 0, &Name))
{
if(pSelectedServer->m_aClients[i].m_FriendState == IFriends::FRIEND_PLAYER)
m_pClient->Friends()->RemoveFriend(pSelectedServer->m_aClients[i].m_aName, pSelectedServer->m_aClients[i].m_aClan);
else
m_pClient->Friends()->AddFriend(pSelectedServer->m_aClients[i].m_aName, pSelectedServer->m_aClients[i].m_aClan);
FriendlistOnUpdate();
Client()->ServerBrowserUpdate();
}
vec4 Colour = pSelectedServer->m_aClients[i].m_FriendState == IFriends::FRIEND_NO ? vec4(1.0f, 1.0f, 1.0f, (i%2+1)*0.05f) :
vec4(0.5f, 1.0f, 0.5f, 0.15f+(i%2+1)*0.05f);
RenderTools()->DrawUIRect(&Name, Colour, CUI::CORNER_ALL, 4.0f);
Name.VSplitLeft(5.0f, 0, &Name);
Name.VSplitLeft(34.0f, &Score, &Name);
Name.VSplitRight(34.0f, &Name, &Flag);
Flag.HMargin(4.0f, &Flag);
Name.HSplitTop(12.0f, &Name, &Clan);
// score
2014-02-19 13:24:26 +00:00
char aTemp[16];
2014-02-19 13:24:26 +00:00
if(!pSelectedServer->m_aClients[i].m_Player)
str_copy(aTemp, "SPEC", sizeof(aTemp));
2019-03-12 18:33:47 +00:00
else if(IsRace(pSelectedServer) && g_Config.m_ClDDRaceScoreBoard)
2014-02-19 13:24:26 +00:00
{
if(pSelectedServer->m_aClients[i].m_Score == -9999 || pSelectedServer->m_aClients[i].m_Score == 0)
aTemp[0] = 0;
else
{
2014-02-19 13:24:26 +00:00
int Time = abs(pSelectedServer->m_aClients[i].m_Score);
str_format(aTemp, sizeof(aTemp), "%02d:%02d", Time/60, Time%60);
}
}
2014-02-19 13:24:26 +00:00
else
str_format(aTemp, sizeof(aTemp), "%d", pSelectedServer->m_aClients[i].m_Score);
TextRender()->SetCursor(&Cursor, Score.x, Score.y+(Score.h-FontSize)/2.0f, FontSize, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END);
2014-02-19 13:24:26 +00:00
Cursor.m_LineWidth = Score.w;
TextRender()->TextEx(&Cursor, aTemp, -1);
// name
TextRender()->SetCursor(&Cursor, Name.x, Name.y + (Name.h - (FontSize - 2)) / 2.f, FontSize - 2, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Name.w;
const char *pName = pSelectedServer->m_aClients[i].m_aName;
2010-05-29 07:25:38 +00:00
if(g_Config.m_BrFilterString[0])
2008-09-04 18:42:26 +00:00
{
// highlight the parts that matches
2010-05-29 07:25:38 +00:00
const char *s = str_find_nocase(pName, g_Config.m_BrFilterString);
2008-09-04 18:42:26 +00:00
if(s)
{
2010-05-29 07:25:38 +00:00
TextRender()->TextEx(&Cursor, pName, (int)(s-pName));
TextRender()->TextColor(0.4f, 0.4f, 1.0f, 1.0f);
2010-05-29 07:25:38 +00:00
TextRender()->TextEx(&Cursor, s, str_length(g_Config.m_BrFilterString));
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
2010-05-29 07:25:38 +00:00
TextRender()->TextEx(&Cursor, s+str_length(g_Config.m_BrFilterString), -1);
}
else
2010-05-29 07:25:38 +00:00
TextRender()->TextEx(&Cursor, pName, -1);
}
2008-09-04 18:42:26 +00:00
else
2010-05-29 07:25:38 +00:00
TextRender()->TextEx(&Cursor, pName, -1);
// clan
TextRender()->SetCursor(&Cursor, Clan.x, Clan.y + (Clan.h - (FontSize - 2)) / 2.f, FontSize - 2, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Clan.w;
const char *pClan = pSelectedServer->m_aClients[i].m_aClan;
if(g_Config.m_BrFilterString[0])
{
// highlight the parts that matches
const char *s = str_find_nocase(pClan, g_Config.m_BrFilterString);
if(s)
{
TextRender()->TextEx(&Cursor, pClan, (int)(s-pClan));
TextRender()->TextColor(0.4f, 0.4f, 1.0f, 1.0f);
TextRender()->TextEx(&Cursor, s, str_length(g_Config.m_BrFilterString));
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
TextRender()->TextEx(&Cursor, s+str_length(g_Config.m_BrFilterString), -1);
}
else
TextRender()->TextEx(&Cursor, pClan, -1);
}
else
TextRender()->TextEx(&Cursor, pClan, -1);
// flag
vec4 Color(1.0f, 1.0f, 1.0f, 0.5f);
m_pClient->m_pCountryFlags->Render(pSelectedServer->m_aClients[i].m_Country, &Color, Flag.x, Flag.y, Flag.w, Flag.h);
}
2014-01-10 11:22:48 +00:00
UiDoListboxEnd(&s_ScrollValue, 0);
}
2008-09-04 18:42:26 +00:00
}
2011-06-26 15:10:13 +00:00
void CMenus::FriendlistOnUpdate()
{
m_lFriends.clear();
for(int i = 0; i < m_pClient->Friends()->NumFriends(); ++i)
{
CFriendItem Item;
Item.m_pFriendInfo = m_pClient->Friends()->GetFriend(i);
Item.m_NumFound = 0;
m_lFriends.add_unsorted(Item);
}
m_lFriends.sort_range();
}
2011-03-23 12:06:35 +00:00
void CMenus::RenderServerbrowserFriends(CUIRect View)
2008-09-04 18:42:26 +00:00
{
2011-06-26 15:10:13 +00:00
static int s_Inited = 0;
if(!s_Inited)
{
FriendlistOnUpdate();
s_Inited = 1;
}
2011-03-23 12:06:35 +00:00
CUIRect ServerFriends = View, FilterHeader;
2011-06-26 15:10:13 +00:00
const float FontSize = 10.0f;
2011-03-23 12:06:35 +00:00
// header
ServerFriends.HSplitTop(ms_ListheaderHeight, &FilterHeader, &ServerFriends);
RenderTools()->DrawUIRect(&FilterHeader, vec4(1,1,1,0.25f), CUI::CORNER_T, 4.0f);
RenderTools()->DrawUIRect(&ServerFriends, vec4(0,0,0,0.15f), 0, 4.0f);
2011-06-26 15:10:13 +00:00
UI()->DoLabelScaled(&FilterHeader, Localize("Friends"), FontSize+4.0f, 0);
2011-03-23 12:06:35 +00:00
CUIRect Button, List;
2010-05-29 07:25:38 +00:00
2011-03-23 12:06:35 +00:00
ServerFriends.Margin(3.0f, &ServerFriends);
2011-06-26 15:10:13 +00:00
ServerFriends.VMargin(3.0f, &ServerFriends);
2011-03-23 12:06:35 +00:00
ServerFriends.HSplitBottom(100.0f, &List, &ServerFriends);
2010-05-29 07:25:38 +00:00
2011-03-23 12:06:35 +00:00
// friends list(remove friend)
static float s_ScrollValue = 0;
if(m_FriendlistSelectedIndex >= m_lFriends.size())
m_FriendlistSelectedIndex = m_lFriends.size()-1;
2014-06-16 11:29:18 +00:00
#if defined(__ANDROID__)
UiDoListboxStart(&m_lFriends, &List, 50.0f, "", "", m_lFriends.size(), 1, m_FriendlistSelectedIndex, s_ScrollValue);
#else
2011-06-26 15:10:13 +00:00
UiDoListboxStart(&m_lFriends, &List, 30.0f, "", "", m_lFriends.size(), 1, m_FriendlistSelectedIndex, s_ScrollValue);
2014-06-16 11:29:18 +00:00
#endif
2011-06-26 15:10:13 +00:00
m_lFriends.sort_range();
for(int i = 0; i < m_lFriends.size(); ++i)
2011-03-23 12:06:35 +00:00
{
CListboxItem Item = UiDoListboxNextItem(&m_lFriends[i], false, false);
2011-03-23 12:06:35 +00:00
if(Item.m_Visible)
{
2011-06-26 15:10:13 +00:00
Item.m_Rect.Margin(1.5f, &Item.m_Rect);
CUIRect OnState;
Item.m_Rect.VSplitRight(30.0f, &Item.m_Rect, &OnState);
RenderTools()->DrawUIRect(&Item.m_Rect, vec4(1.0f, 1.0f, 1.0f, 0.1f), CUI::CORNER_L, 4.0f);
Item.m_Rect.VMargin(2.5f, &Item.m_Rect);
Item.m_Rect.HSplitTop(12.0f, &Item.m_Rect, &Button);
UI()->DoLabelScaled(&Item.m_Rect, m_lFriends[i].m_pFriendInfo->m_aName, FontSize, -1);
UI()->DoLabelScaled(&Button, m_lFriends[i].m_pFriendInfo->m_aClan, FontSize, -1);
RenderTools()->DrawUIRect(&OnState, m_lFriends[i].m_NumFound ? vec4(0.0f, 1.0f, 0.0f, 0.25f) : vec4(1.0f, 0.0f, 0.0f, 0.25f), CUI::CORNER_R, 4.0f);
OnState.HMargin((OnState.h-FontSize)/3, &OnState);
OnState.VMargin(5.0f, &OnState);
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "%i", m_lFriends[i].m_NumFound);
UI()->DoLabelScaled(&OnState, aBuf, FontSize+2, 1);
2011-03-23 12:06:35 +00:00
}
}
2011-06-26 15:10:13 +00:00
bool Activated = false;
m_FriendlistSelectedIndex = UiDoListboxEnd(&s_ScrollValue, &Activated);
// activate found server with friend
if(Activated && !m_EnterPressed && m_lFriends[m_FriendlistSelectedIndex].m_NumFound)
{
bool Found = false;
int NumServers = ServerBrowser()->NumSortedServers();
for(int i = 0; i < NumServers && !Found; i++)
2011-06-26 15:10:13 +00:00
{
int ItemIndex = m_SelectedIndex != -1 ? (m_SelectedIndex+i+1)%NumServers : i;
const CServerInfo *pItem = ServerBrowser()->SortedGet(ItemIndex);
if(pItem->m_FriendState != IFriends::FRIEND_NO)
{
for(int j = 0; j < pItem->m_NumReceivedClients && !Found; ++j)
2011-06-26 15:10:13 +00:00
{
if(pItem->m_aClients[j].m_FriendState != IFriends::FRIEND_NO &&
((g_Config.m_ClFriendsIgnoreClan && m_lFriends[m_FriendlistSelectedIndex].m_pFriendInfo->m_aName[0]) || str_quickhash(pItem->m_aClients[j].m_aClan) == m_lFriends[m_FriendlistSelectedIndex].m_pFriendInfo->m_ClanHash) &&
2011-06-26 15:10:13 +00:00
(!m_lFriends[m_FriendlistSelectedIndex].m_pFriendInfo->m_aName[0] ||
str_quickhash(pItem->m_aClients[j].m_aName) == m_lFriends[m_FriendlistSelectedIndex].m_pFriendInfo->m_NameHash))
{
str_copy(g_Config.m_UiServerAddress, pItem->m_aAddress, sizeof(g_Config.m_UiServerAddress));
m_ScrollOffset = ItemIndex;
m_SelectedIndex = ItemIndex;
Found = true;
}
}
}
}
}
2011-03-23 12:06:35 +00:00
ServerFriends.HSplitTop(2.5f, 0, &ServerFriends);
ServerFriends.HSplitTop(20.0f, &Button, &ServerFriends);
if(m_FriendlistSelectedIndex != -1)
{
static int s_RemoveButton = 0;
if(DoButton_Menu(&s_RemoveButton, Localize("Remove"), 0, &Button))
m_Popup = POPUP_REMOVE_FRIEND;
}
// add friend
if(m_pClient->Friends()->NumFriends() < IFriends::MAX_FRIENDS)
{
ServerFriends.HSplitTop(10.0f, 0, &ServerFriends);
ServerFriends.HSplitTop(19.0f, &Button, &ServerFriends);
char aBuf[64];
str_format(aBuf, sizeof(aBuf), "%s:", Localize("Name"));
UI()->DoLabelScaled(&Button, aBuf, FontSize, -1);
Button.VSplitLeft(80.0f, 0, &Button);
static char s_aName[MAX_NAME_LENGTH] = {0};
static float s_OffsetName = 0.0f;
DoEditBox(&s_aName, &Button, s_aName, sizeof(s_aName), FontSize, &s_OffsetName);
ServerFriends.HSplitTop(3.0f, 0, &ServerFriends);
ServerFriends.HSplitTop(19.0f, &Button, &ServerFriends);
str_format(aBuf, sizeof(aBuf), "%s:", Localize("Clan"));
UI()->DoLabelScaled(&Button, aBuf, FontSize, -1);
Button.VSplitLeft(80.0f, 0, &Button);
static char s_aClan[MAX_CLAN_LENGTH] = {0};
static float s_OffsetClan = 0.0f;
DoEditBox(&s_aClan, &Button, s_aClan, sizeof(s_aClan), FontSize, &s_OffsetClan);
ServerFriends.HSplitTop(3.0f, 0, &ServerFriends);
ServerFriends.HSplitTop(20.0f, &Button, &ServerFriends);
2011-06-26 15:10:13 +00:00
static int s_AddButton = 0;
if(DoButton_Menu(&s_AddButton, Localize("Add Friend"), 0, &Button))
2011-03-23 12:06:35 +00:00
{
m_pClient->Friends()->AddFriend(s_aName, s_aClan);
2011-06-26 15:10:13 +00:00
FriendlistOnUpdate();
2011-03-23 12:06:35 +00:00
Client()->ServerBrowserUpdate();
}
}
}
2010-05-29 07:25:38 +00:00
void CMenus::RenderServerbrowser(CUIRect MainView)
2008-09-04 18:42:26 +00:00
{
/*
+-----------------+ +-------+
| | | |
| | | tool |
| server list | | box |
| | | |
| | | |
+-----------------+ | |
status box tab +-------+
2008-09-04 18:42:26 +00:00
*/
2010-05-29 07:25:38 +00:00
CUIRect ServerList, ToolBox, StatusBox, TabBar;
2010-05-29 07:25:38 +00:00
// background
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f);
MainView.Margin(10.0f, &MainView);
// create server list, status box, tab bar and tool box area
MainView.VSplitRight(205.0f, &ServerList, &ToolBox);
ServerList.HSplitBottom(70.0f, &ServerList, &StatusBox);
StatusBox.VSplitRight(100.0f, &StatusBox, &TabBar);
ServerList.VSplitRight(5.0f, &ServerList, 0);
2008-09-04 18:42:26 +00:00
// server list
{
RenderServerbrowserServerList(ServerList);
}
2010-05-29 07:25:38 +00:00
int ToolboxPage = g_Config.m_UiToolboxPage;
// tab bar
2008-09-04 18:42:26 +00:00
{
2011-03-23 12:06:35 +00:00
CUIRect TabButton0, TabButton1, TabButton2;
TabBar.HSplitTop(5.0f, 0, &TabBar);
TabBar.HSplitTop(20.0f, &TabButton0, &TabBar);
2011-03-23 12:06:35 +00:00
TabBar.HSplitTop(2.5f, 0, &TabBar);
TabBar.HSplitTop(20.0f, &TabButton1, &TabBar);
TabBar.HSplitTop(2.5f, 0, &TabBar);
TabBar.HSplitTop(20.0f, &TabButton2, 0);
vec4 Active = ms_ColorTabbarActive;
vec4 InActive = ms_ColorTabbarInactive;
ms_ColorTabbarActive = vec4(0.0f, 0.0f, 0.0f, 0.3f);
ms_ColorTabbarInactive = vec4(0.0f, 0.0f, 0.0f, 0.15f);
2010-05-29 07:25:38 +00:00
static int s_FiltersTab = 0;
if(DoButton_MenuTab(&s_FiltersTab, Localize("Filter"), ToolboxPage==0, &TabButton0, CUI::CORNER_L))
2010-05-29 07:25:38 +00:00
ToolboxPage = 0;
static int s_InfoTab = 0;
if(DoButton_MenuTab(&s_InfoTab, Localize("Info"), ToolboxPage==1, &TabButton1, CUI::CORNER_L))
2010-05-29 07:25:38 +00:00
ToolboxPage = 1;
2008-09-04 18:42:26 +00:00
2011-03-23 12:06:35 +00:00
static int s_FriendsTab = 0;
if(DoButton_MenuTab(&s_FriendsTab, Localize("Friends"), ToolboxPage==2, &TabButton2, CUI::CORNER_L))
2011-03-23 12:06:35 +00:00
ToolboxPage = 2;
2010-05-29 07:25:38 +00:00
ms_ColorTabbarActive = Active;
ms_ColorTabbarInactive = InActive;
g_Config.m_UiToolboxPage = ToolboxPage;
}
2010-05-29 07:25:38 +00:00
// tool box
{
RenderTools()->DrawUIRect(&ToolBox, vec4(0.0f, 0.0f, 0.0f, 0.15f), CUI::CORNER_T, 4.0f);
2010-05-29 07:25:38 +00:00
if(ToolboxPage == 0)
2014-09-18 14:13:06 +00:00
RenderServerbrowserFilters(ToolBox);
else if(ToolboxPage == 1)
RenderServerbrowserServerDetail(ToolBox);
2011-03-23 12:06:35 +00:00
else if(ToolboxPage == 2)
RenderServerbrowserFriends(ToolBox);
}
// status box
{
2015-09-05 02:52:18 +00:00
CUIRect Button, ButtonArea;
StatusBox.HSplitTop(5.0f, 0, &StatusBox);
2010-05-29 07:25:38 +00:00
// version note
2018-12-05 06:28:29 +00:00
#if defined(CONF_AUTOUPDATE)
2015-09-05 02:52:18 +00:00
CUIRect Part;
StatusBox.HSplitBottom(15.0f, &StatusBox, &Button);
char aBuf[64];
int State = Updater()->GetCurrentState();
2014-12-31 14:34:25 +00:00
bool NeedUpdate = str_comp(Client()->LatestVersion(), "0");
if(State == IUpdater::CLEAN && NeedUpdate)
{
2015-03-13 20:37:25 +00:00
str_format(aBuf, sizeof(aBuf), "DDNet %s is out!", Client()->LatestVersion());
TextRender()->TextColor(1.0f, 0.4f, 0.4f, 1.0f);
}
else if(State == IUpdater::CLEAN)
{
2015-03-14 08:54:37 +00:00
str_format(aBuf, sizeof(aBuf), Localize("Current version: %s"), GAME_VERSION);
}
else if(State >= IUpdater::GETTING_MANIFEST && State < IUpdater::NEED_RESTART)
{
char aCurrentFile[64];
Updater()->GetCurrentFile(aCurrentFile, sizeof(aCurrentFile));
str_format(aBuf, sizeof(aBuf), "Downloading %s:", aCurrentFile);
}
else if(State == IUpdater::FAIL)
2015-03-13 19:18:00 +00:00
{
2015-03-13 19:27:37 +00:00
str_format(aBuf, sizeof(aBuf), "Failed to download a file! Restart client to retry...");
2015-03-13 19:18:00 +00:00
TextRender()->TextColor(1.0f, 0.4f, 0.4f, 1.0f);
}
else if(State == IUpdater::NEED_RESTART)
{
2015-03-13 14:13:19 +00:00
str_format(aBuf, sizeof(aBuf), "DDNet Client updated!");
TextRender()->TextColor(1.0f, 0.4f, 0.4f, 1.0f);
}
UI()->DoLabelScaled(&Button, aBuf, 14.0f, -1);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
2010-05-29 07:25:38 +00:00
2014-11-24 19:20:11 +00:00
Button.VSplitLeft(TextRender()->TextWidth(0, 14.0f, aBuf, -1) + 10.0f, &Button, &Part);
if(State == IUpdater::CLEAN && NeedUpdate)
{
2015-03-13 20:37:25 +00:00
CUIRect Update;
Part.VSplitLeft(100.0f, &Update, NULL);
2014-11-24 19:20:11 +00:00
static int s_ButtonUpdate = 0;
if(DoButton_Menu(&s_ButtonUpdate, Localize("Update now"), 0, &Update))
{
Updater()->InitiateUpdate();
}
2014-11-24 19:20:11 +00:00
}
else if(State == IUpdater::NEED_RESTART)
2015-03-13 14:13:19 +00:00
{
CUIRect Restart;
Part.VSplitLeft(50.0f, &Restart, &Part);
static int s_ButtonUpdate = 0;
if(DoButton_Menu(&s_ButtonUpdate, Localize("Restart"), 0, &Restart))
{
Client()->Restart();
}
}
else if(State >= IUpdater::GETTING_MANIFEST && State < IUpdater::NEED_RESTART)
{
2014-11-24 19:20:11 +00:00
CUIRect ProgressBar, Percent;
2015-07-09 00:08:14 +00:00
Part.VSplitLeft(100.0f, &ProgressBar, &Percent);
2014-11-24 19:20:11 +00:00
ProgressBar.y += 2.0f;
ProgressBar.HMargin(1.0f, &ProgressBar);
RenderTools()->DrawUIRect(&ProgressBar, vec4(1.0f, 1.0f, 1.0f, 0.25f), CUI::CORNER_ALL, 5.0f);
ProgressBar.w = clamp((float)Updater()->GetCurrentPercent(), 10.0f, 100.0f);
2014-11-24 19:20:11 +00:00
RenderTools()->DrawUIRect(&ProgressBar, vec4(1.0f, 1.0f, 1.0f, 0.5f), CUI::CORNER_ALL, 5.0f);
}
2015-02-27 21:08:34 +00:00
#else
StatusBox.HSplitBottom(15.0f, &StatusBox, &Button);
char aBuf[64];
if(str_comp(Client()->LatestVersion(), "0") != 0)
{
2016-05-20 16:36:32 +00:00
str_format(aBuf, sizeof(aBuf), Localize("DDNet %s is out! Download it at DDNet.tw!"), Client()->LatestVersion());
2015-02-27 21:08:34 +00:00
TextRender()->TextColor(1.0f, 0.4f, 0.4f, 1.0f);
}
else
2015-06-30 16:57:39 +00:00
str_format(aBuf, sizeof(aBuf), Localize("Current version: %s"), GAME_VERSION);
2015-02-27 21:08:34 +00:00
UI()->DoLabelScaled(&Button, aBuf, 14.0f, -1);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
#endif
// button area
//StatusBox.VSplitRight(80.0f, &StatusBox, 0);
StatusBox.VSplitRight(170.0f, &StatusBox, &ButtonArea);
//ButtonArea.VSplitRight(150.0f, 0, &ButtonArea);
ButtonArea.HSplitTop(20.0f, &Button, &ButtonArea);
Button.VMargin(20.0f, &Button);
2010-05-29 07:25:38 +00:00
static int s_RefreshButton = 0;
if(ServerBrowser()->IsRefreshing())
str_format(aBuf, sizeof(aBuf), "%s (%d%%)", Localize("Refresh"), ServerBrowser()->LoadingProgression());
else
str_copy(aBuf, Localize("Refresh"), sizeof(aBuf));
if(DoButton_Menu(&s_RefreshButton, aBuf, 0, &Button) || Input()->KeyPress(KEY_F5) || (Input()->KeyPress(KEY_R) && (Input()->KeyIsPressed(KEY_LCTRL) || Input()->KeyIsPressed(KEY_RCTRL))))
{
2010-05-29 07:25:38 +00:00
if(g_Config.m_UiPage == PAGE_INTERNET)
ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET);
else if(g_Config.m_UiPage == PAGE_LAN)
ServerBrowser()->Refresh(IServerBrowser::TYPE_LAN);
else if(g_Config.m_UiPage == PAGE_FAVORITES)
ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES);
2014-09-13 14:36:25 +00:00
else if(g_Config.m_UiPage == PAGE_DDNET)
2014-09-19 22:36:22 +00:00
{
// start a new serverlist request
Client()->RequestDDNetInfo();
2014-09-13 14:36:25 +00:00
ServerBrowser()->Refresh(IServerBrowser::TYPE_DDNET);
2014-09-19 22:36:22 +00:00
}
2014-06-16 11:29:18 +00:00
m_DoubleClickIndex = -1;
}
2010-05-29 07:25:38 +00:00
ButtonArea.HSplitTop(5.0f, 0, &ButtonArea);
ButtonArea.HSplitTop(20.0f, &Button, &ButtonArea);
Button.VMargin(20.0f, &Button);
2010-05-29 07:25:38 +00:00
static int s_JoinButton = 0;
if(DoButton_Menu(&s_JoinButton, Localize("Connect"), 0, &Button) || m_EnterPressed)
2009-01-21 21:19:10 +00:00
{
2010-05-29 07:25:38 +00:00
Client()->Connect(g_Config.m_UiServerAddress);
m_EnterPressed = false;
2009-01-21 21:19:10 +00:00
}
2010-05-29 07:25:38 +00:00
// address info
StatusBox.VSplitLeft(20.0f, 0, &StatusBox);
StatusBox.HSplitTop(20.0f, &Button, &StatusBox);
UI()->DoLabelScaled(&Button, Localize("Host address"), 14.0f, -1);
StatusBox.HSplitTop(20.0f, &Button, 0);
static float Offset = 0.0f;
DoEditBox(&g_Config.m_UiServerAddress, &Button, g_Config.m_UiServerAddress, sizeof(g_Config.m_UiServerAddress), 14.0f, &Offset);
}
}
2011-06-26 15:10:13 +00:00
void CMenus::ConchainFriendlistUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
pfnCallback(pResult, pCallbackUserData);
if(pResult->NumArguments() == 2 && ((CMenus *)pUserData)->Client()->State() == IClient::STATE_OFFLINE)
{
((CMenus *)pUserData)->FriendlistOnUpdate();
((CMenus *)pUserData)->Client()->ServerBrowserUpdate();
}
}
void CMenus::ConchainServerbrowserUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData)
{
pfnCallback(pResult, pCallbackUserData);
if(pResult->NumArguments() && g_Config.m_UiPage == PAGE_FAVORITES)
((CMenus *)pUserData)->ServerBrowser()->Refresh(IServerBrowser::TYPE_FAVORITES);
}