Adapt 0.7 start menu

- Working Local Server button (needs fixing for Windows)
- Highlight buttons if server is running, new news is out and editor has
  unsaved changes
This commit is contained in:
def 2020-09-03 14:08:26 +02:00
parent d1aa014357
commit 2cdc7d0faf
26 changed files with 762 additions and 155 deletions

View file

@ -1144,6 +1144,11 @@ set(EXPECTED_DATA
maps/license.txt
maps7/Gold\ Mine.map
maps7/readme.txt
menuimages/demos.png
menuimages/editor.png
menuimages/local_server.png
menuimages/play_game.png
menuimages/settings.png
particles.png
shader/pipeline.frag
shader/pipeline.vert
@ -1693,6 +1698,7 @@ if(CLIENT)
components/menus_demo.cpp
components/menus_ingame.cpp
components/menus_settings.cpp
components/menus_start.cpp
components/motd.cpp
components/motd.h
components/nameplates.cpp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 87 KiB

BIN
data/menuimages/demos.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
data/menuimages/editor.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View file

@ -18,7 +18,9 @@
#if defined(CONF_FAMILY_UNIX)
#include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
/* unix net includes */
#include <sys/socket.h>
@ -2286,6 +2288,16 @@ void str_utf8_truncate(char *dst, int dst_size, const char *src, int truncation_
str_copy(dst, src, size+1);
}
void str_truncate(char *dst, int dst_size, const char *src, int truncation_len)
{
int size = dst_size;
if(truncation_len < size)
{
size = truncation_len + 1;
}
str_copy(dst, src, size);
}
int str_length(const char *str)
{
return (int)strlen(str);
@ -3202,10 +3214,11 @@ int pid(void)
#endif
}
void shell_execute(const char *file)
int shell_execute(const char *file)
{
#if defined(CONF_FAMILY_WINDOWS)
ShellExecute(NULL, NULL, file, NULL, NULL, SW_SHOWDEFAULT);
// TODO: Get PID
#elif defined(CONF_FAMILY_UNIX)
char *argv[2];
pid_t pid;
@ -3214,6 +3227,18 @@ void shell_execute(const char *file)
pid = fork();
if(!pid)
execv(file, argv);
return pid;
#endif
}
int kill_process(int pid)
{
#if defined(CONF_FAMILY_WINDOWS)
// TODO: Implement
#elif defined(CONF_FAMILY_UNIX)
int status;
kill(pid, SIGTERM);
return waitpid(pid, &status, 0);
#endif
}

View file

@ -1012,6 +1012,24 @@ void str_copy(char *dst, const char *src, int dst_size);
*/
void str_utf8_truncate(char *dst, int dst_size, const char *src, int truncation_len);
/*
Function: str_truncate
Truncates a string to a given length.
Parameters:
dst - Pointer to a buffer that shall receive the string.
dst_size - Size of the buffer dst.
src - String to be truncated.
truncation_len - Maximum length of the returned string (not
counting the zero termination).
Remarks:
- The strings are treated as zero-terminated strings.
- Garantees that dst string will contain zero-termination.
*/
void str_truncate(char *dst, int dst_size, const char *src, int truncation_len);
/*
Function: str_length
Returns the length of a zero terminated string.
@ -1964,13 +1982,36 @@ const char *str_next_token(const char *str, const char *delim, char *buffer, int
*/
int str_in_list(const char *list, const char *delim, const char *needle);
/*
Function: pid
Returns the pid of the current process.
Returns:
pid of the current process
*/
int pid(void);
/*
Function: shell_execute
Executes a given file.
Returns:
pid of the new process
*/
void shell_execute(const char *file);
int shell_execute(const char *file);
/*
Function: kill_process
Sends kill signal to a process.
Parameters:
pid - pid of the process
Returns:
0 - Success
1 - Error
*/
int kill_process(int pid);
/*
Function: os_is_winxp_or_lower
@ -1987,7 +2028,6 @@ int os_is_winxp_or_lower(void);
Generates a null-terminated password of length `2 *
random_length`.
Parameters:
buffer - Pointer to the start of the output buffer.
length - Length of the buffer.

View file

@ -67,7 +67,6 @@
#include "friends.h"
#include "serverbrowser.h"
#include "updater.h"
#include "client.h"
#if defined(CONF_VIDEORECORDER)
@ -2441,9 +2440,9 @@ void CClient::LoadDDNetInfo()
{
const char *pNewsString = json_string_get(pNews);
// Only switch to news page if something new was added to the news
// Only mark news button if something new was added to the news
if(m_aNews[0] && str_find(m_aNews, pNewsString) == nullptr)
g_Config.m_UiPage = CMenus::PAGE_NEWS;
g_Config.m_UiUnreadNews = true;
str_copy(m_aNews, pNewsString, sizeof(m_aNews));
}

View file

@ -7,6 +7,7 @@
#include <base/hash.h>
#include <engine/client/http.h>
#include <engine/client/updater.h>
#define CONNECTLINK "ddnet:"

View file

@ -714,6 +714,17 @@ void CGraphics_Threaded::SetColor(ColorRGBA rgb)
SetColor(rgb.r, rgb.g, rgb.b, rgb.a);
}
void CGraphics_Threaded::SetColor4(vec4 TopLeft, vec4 TopRight, vec4 BottomLeft, vec4 BottomRight)
{
dbg_assert(m_Drawing != 0, "called Graphics()->SetColor without begin");
CColorVertex Array[4] = {
CColorVertex(0, TopLeft.r, TopLeft.g, TopLeft.b, TopLeft.a),
CColorVertex(1, TopRight.r, TopRight.g, TopRight.b, TopRight.a),
CColorVertex(2, BottomRight.r, BottomRight.g, BottomRight.b, BottomRight.a),
CColorVertex(3, BottomLeft.r, BottomLeft.g, BottomLeft.b, BottomLeft.a)};
SetColorVertex(Array, 4);
}
void CGraphics_Threaded::ChangeColorOfCurrentQuadVertices(float r, float g, float b, float a)
{
clampf(r, 0.f, 1.f);

View file

@ -768,6 +768,7 @@ public:
virtual void SetColorVertex(const CColorVertex *pArray, int Num);
virtual void SetColor(float r, float g, float b, float a);
virtual void SetColor(ColorRGBA rgb);
virtual void SetColor4(vec4 TopLeft, vec4 TopRight, vec4 BottomLeft, vec4 BottomRight);
// go through all vertices and change their color (only works for quads)
virtual void ChangeColorOfCurrentQuadVertices(float r, float g, float b, float a);

View file

@ -299,6 +299,7 @@ public:
virtual void SetColorVertex(const CColorVertex *pArray, int Num) = 0;
virtual void SetColor(float r, float g, float b, float a) = 0;
virtual void SetColor(ColorRGBA rgb) = 0;
virtual void SetColor4(vec4 TopLeft, vec4 TopRight, vec4 BottomLeft, vec4 BottomRight) = 0;
virtual void ChangeColorOfCurrentQuadVertices(float r, float g, float b, float a) = 0;
virtual void ChangeColorOfQuadVertices(int QuadOffset, unsigned char r, unsigned char g, unsigned char b, unsigned char a) = 0;

View file

@ -213,6 +213,7 @@ void CBinds::SetDefaults()
UnbindAll();
Bind(KEY_F1, "toggle_local_console");
Bind(KEY_F2, "toggle_remote_console");
Bind(KEY_F7, "toggle_server_console");
Bind(KEY_TAB, "+scoreboard");
Bind(KEY_EQUALS, "+statboard");
Bind(KEY_F10, "screenshot");

View file

@ -355,7 +355,7 @@ void CGameConsole::CInstance::PrintLine(const char *pLine, bool Highlighted)
}
CGameConsole::CGameConsole()
: m_LocalConsole(CONSOLETYPE_LOCAL), m_RemoteConsole(CONSOLETYPE_REMOTE)
: m_LocalConsole(CONSOLETYPE_LOCAL), m_RemoteConsole(CONSOLETYPE_REMOTE), m_ServerConsole(CONSOLETYPE_SERVER)
{
m_ConsoleType = CONSOLETYPE_LOCAL;
m_ConsoleState = CONSOLE_CLOSED;
@ -373,6 +373,8 @@ CGameConsole::CInstance *CGameConsole::CurrentConsole()
{
if(m_ConsoleType == CONSOLETYPE_REMOTE)
return &m_RemoteConsole;
if(m_ConsoleType == CONSOLETYPE_SERVER)
return &m_ServerConsole;
return &m_LocalConsole;
}
@ -503,6 +505,8 @@ void CGameConsole::OnRender()
Graphics()->SetColor(0.2f, 0.2f, 0.2f,0.9f);
if(m_ConsoleType == CONSOLETYPE_REMOTE)
Graphics()->SetColor(0.4f, 0.2f, 0.2f,0.9f);
else if(m_ConsoleType == CONSOLETYPE_SERVER)
Graphics()->SetColor(0.2f, 0.2f, 0.4f,0.9f);
Graphics()->QuadsSetSubset(0,-ConsoleHeight*0.075f,Screen.w*0.075f*0.5f,0);
QuadItem = IGraphics::CQuadItem(0, 0, Screen.w, ConsoleHeight);
Graphics()->QuadsDrawTL(&QuadItem, 1);
@ -782,7 +786,7 @@ void CGameConsole::Toggle(int Type)
void CGameConsole::Dump(int Type)
{
CInstance *pConsole = Type == CONSOLETYPE_REMOTE ? &m_RemoteConsole : &m_LocalConsole;
CInstance *pConsole = Type == CONSOLETYPE_REMOTE ? &m_RemoteConsole : Type == CONSOLETYPE_SERVER ? &m_ServerConsole : &m_LocalConsole;
char aFilename[128];
char aDate[20];
@ -810,6 +814,11 @@ void CGameConsole::ConToggleRemoteConsole(IConsole::IResult *pResult, void *pUse
((CGameConsole *)pUserData)->Toggle(CONSOLETYPE_REMOTE);
}
void CGameConsole::ConToggleServerConsole(IConsole::IResult *pResult, void *pUserData)
{
((CGameConsole *)pUserData)->Toggle(CONSOLETYPE_SERVER);
}
void CGameConsole::ConClearLocalConsole(IConsole::IResult *pResult, void *pUserData)
{
((CGameConsole *)pUserData)->m_LocalConsole.ClearBacklog();
@ -820,6 +829,11 @@ void CGameConsole::ConClearRemoteConsole(IConsole::IResult *pResult, void *pUser
((CGameConsole *)pUserData)->m_RemoteConsole.ClearBacklog();
}
void CGameConsole::ConClearServerConsole(IConsole::IResult *pResult, void *pUserData)
{
((CGameConsole *)pUserData)->m_ServerConsole.ClearBacklog();
}
void CGameConsole::ConDumpLocalConsole(IConsole::IResult *pResult, void *pUserData)
{
((CGameConsole *)pUserData)->Dump(CONSOLETYPE_LOCAL);
@ -830,6 +844,11 @@ void CGameConsole::ConDumpRemoteConsole(IConsole::IResult *pResult, void *pUserD
((CGameConsole *)pUserData)->Dump(CONSOLETYPE_REMOTE);
}
void CGameConsole::ConDumpServerConsole(IConsole::IResult *pResult, void *pUserData)
{
((CGameConsole *)pUserData)->Dump(CONSOLETYPE_SERVER);
}
void CGameConsole::ClientConsolePrintCallback(const char *pStr, void *pUserData, bool Highlighted)
{
((CGameConsole *)pUserData)->m_LocalConsole.PrintLine(pStr, Highlighted);
@ -874,6 +893,8 @@ void CGameConsole::PrintLine(int Type, const char *pLine)
m_LocalConsole.PrintLine(pLine);
else if(Type == CONSOLETYPE_REMOTE)
m_RemoteConsole.PrintLine(pLine);
else if(Type == CONSOLETYPE_SERVER)
m_ServerConsole.PrintLine(pLine);
}
void CGameConsole::OnConsoleInit()
@ -881,6 +902,7 @@ void CGameConsole::OnConsoleInit()
// init console instances
m_LocalConsole.Init(this);
m_RemoteConsole.Init(this);
m_ServerConsole.Init(this);
m_pConsole = Kernel()->RequestInterface<IConsole>();
@ -889,10 +911,13 @@ void CGameConsole::OnConsoleInit()
Console()->Register("toggle_local_console", "", CFGFLAG_CLIENT, ConToggleLocalConsole, this, "Toggle local console");
Console()->Register("toggle_remote_console", "", CFGFLAG_CLIENT, ConToggleRemoteConsole, this, "Toggle remote console");
Console()->Register("toggle_server_console", "", CFGFLAG_CLIENT, ConToggleServerConsole, this, "Toggle server console");
Console()->Register("clear_local_console", "", CFGFLAG_CLIENT, ConClearLocalConsole, this, "Clear local console");
Console()->Register("clear_remote_console", "", CFGFLAG_CLIENT, ConClearRemoteConsole, this, "Clear remote console");
Console()->Register("clear_sever_console", "", CFGFLAG_CLIENT, ConClearServerConsole, this, "Clear server console");
Console()->Register("dump_local_console", "", CFGFLAG_CLIENT, ConDumpLocalConsole, this, "Dump local console");
Console()->Register("dump_remote_console", "", CFGFLAG_CLIENT, ConDumpRemoteConsole, this, "Dump remote console");
Console()->Register("dump_server_console", "", CFGFLAG_CLIENT, ConDumpServerConsole, this, "Dump server console");
Console()->Register("console_page_up", "", CFGFLAG_CLIENT, ConConsolePageUp, this, "Previous page in console");
Console()->Register("console_page_down", "", CFGFLAG_CLIENT, ConConsolePageDown, this, "Next page in console");

View file

@ -71,6 +71,7 @@ class CGameConsole : public CComponent
CInstance m_LocalConsole;
CInstance m_RemoteConsole;
CInstance m_ServerConsole;
CInstance *CurrentConsole();
float TimeNow();
@ -88,10 +89,13 @@ class CGameConsole : public CComponent
static void ClientConsolePrintCallback(const char *pStr, void *pUserData, bool Highlighted);
static void ConToggleLocalConsole(IConsole::IResult *pResult, void *pUserData);
static void ConToggleRemoteConsole(IConsole::IResult *pResult, void *pUserData);
static void ConToggleServerConsole(IConsole::IResult *pResult, void *pUserData);
static void ConClearLocalConsole(IConsole::IResult *pResult, void *pUserData);
static void ConClearRemoteConsole(IConsole::IResult *pResult, void *pUserData);
static void ConClearServerConsole(IConsole::IResult *pResult, void *pUserData);
static void ConDumpLocalConsole(IConsole::IResult *pResult, void *pUserData);
static void ConDumpRemoteConsole(IConsole::IResult *pResult, void *pUserData);
static void ConDumpServerConsole(IConsole::IResult *pResult, void *pUserData);
static void ConConsolePageUp(IConsole::IResult *pResult, void *pUserData);
static void ConConsolePageDown(IConsole::IResult *pResult, void *pUserData);
static void ConchainConsoleOutputLevelUpdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
@ -101,6 +105,7 @@ public:
{
CONSOLETYPE_LOCAL=0,
CONSOLETYPE_REMOTE,
CONSOLETYPE_SERVER,
};
CGameConsole();

View file

@ -25,6 +25,7 @@
#include <game/generated/client_data.h>
#include <game/client/components/binds.h>
#include <game/client/components/console.h>
#include <game/client/components/sounds.h>
#include <game/client/gameclient.h>
#include <game/client/lineinput.h>
@ -56,6 +57,7 @@ CMenus::CMenus()
{
m_Popup = POPUP_NONE;
m_ActivePage = PAGE_INTERNET;
m_MenuPage = 0;
m_GamePage = PAGE_GAME;
m_NeedRestartGraphics = false;
@ -63,6 +65,7 @@ CMenus::CMenus()
m_NeedSendinfo = false;
m_NeedSendDummyinfo = false;
m_MenuActive = true;
m_ShowStart = true;
m_UseMouseButtons = true;
m_MouseSlow = false;
@ -81,6 +84,9 @@ CMenus::CMenus()
m_DemoPlayerState = DEMOPLAYER_NONE;
m_Dummy = false;
m_ServerProcess.Pid = -1;
m_ServerProcess.Initialized = false;
}
float CMenus::ButtonColorMul(const void *pID)
@ -142,15 +148,40 @@ int CMenus::DoButton_Toggle(const void *pID, int Checked, const CUIRect *pRect,
return Active ? UI()->DoButtonLogic(pID, "", Checked, pRect) : 0;
}
int CMenus::DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
int CMenus::DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect, const char *pImageName, int Corners, float r, float FontFactor, vec4 ColorHot, vec4 Color)
{
RenderTools()->DrawUIRect(pRect, ColorRGBA(1,1,1,0.5f * ButtonColorMul(pID)), CUI::CORNER_ALL, 5.0f);
CUIRect Temp;
pRect->HMargin(pRect->h>=20.0f?2.0f:1.0f, &Temp);
UI()->DoLabel(&Temp, pText, Temp.h*ms_FontmodHeight, 0);
CUIRect Text = *pRect;
Color.a *= ButtonColorMul(pID);
RenderTools()->DrawUIRect(pRect, Color, Corners, r);
if(pImageName)
{
CUIRect Image;
pRect->VSplitRight(pRect->h*4.0f, &Text, &Image); // always correct ratio for image
// render image
const CMenuImage *pImage = FindMenuImage(pImageName);
if(pImage)
{
Graphics()->TextureSet(UI()->HotItem() == pID ? pImage->m_OrgTexture : pImage->m_GreyTexture);
Graphics()->WrapClamp();
Graphics()->QuadsBegin();
Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
IGraphics::CQuadItem QuadItem(Image.x, Image.y, Image.w, Image.h);
Graphics()->QuadsDrawTL(&QuadItem, 1);
Graphics()->QuadsEnd();
Graphics()->WrapNormal();
}
}
Text.HMargin(pRect->h>=20.0f?2.0f:1.0f, &Text);
Text.HMargin((Text.h*FontFactor)/2.0f, &Text);
UI()->DoLabel(&Text, pText, Text.h*ms_FontmodHeight, 0);
return UI()->DoButtonLogic(pID, pText, Checked, pRect);
}
void CMenus::DoButton_KeySelect(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
{
RenderTools()->DrawUIRect(pRect, ColorRGBA(1,1,1,0.5f * ButtonColorMul(pID)), CUI::CORNER_ALL, 5.0f);
@ -688,7 +719,7 @@ int CMenus::RenderMenubar(CUIRect r)
CUIRect Box = r;
CUIRect Button;
m_ActivePage = g_Config.m_UiPage;
m_ActivePage = m_MenuPage;
int NewPage = -1;
if(Client()->State() != IClient::STATE_OFFLINE)
@ -861,7 +892,7 @@ int CMenus::RenderMenubar(CUIRect r)
if(NewPage != -1)
{
if(Client()->State() == IClient::STATE_OFFLINE)
g_Config.m_UiPage = NewPage;
SetMenuPage(NewPage);
else
m_GamePage = NewPage;
}
@ -925,6 +956,8 @@ void CMenus::RenderLoading()
void CMenus::RenderNews(CUIRect MainView)
{
g_Config.m_UiUnreadNews = false;
RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_B, 10.0f);
MainView.HSplitTop(15.0f, 0, &MainView);
@ -955,6 +988,8 @@ void CMenus::OnInit()
{
if(g_Config.m_ClShowWelcome)
m_Popup = POPUP_LANGUAGE;
if(g_Config.m_ClSkipStartMenu)
m_ShowStart = false;
Console()->Chain("add_favorite", ConchainServerbrowserUpdate, this);
Console()->Chain("remove_favorite", ConchainServerbrowserUpdate, this);
@ -963,6 +998,10 @@ void CMenus::OnInit()
m_TextureBlob = Graphics()->LoadTexture("blob.png", IStorage::TYPE_ALL, CImageInfo::FORMAT_AUTO, 0);
// load menu images
m_lMenuImages.clear();
Storage()->ListDirectory(IStorage::TYPE_ALL, "menuimages", MenuImageScan, this);
// setup load amount
m_LoadCurrent = 0;
m_LoadTotal = g_pData->m_NumImages;
@ -1014,6 +1053,7 @@ int CMenus::Render()
static int s_Frame = 0;
if(s_Frame == 0)
{
m_MenuPage = g_Config.m_UiPage;
s_Frame++;
}
else if(s_Frame == 1)
@ -1062,53 +1102,63 @@ int CMenus::Render()
if(m_Popup == POPUP_NONE)
{
Screen.HSplitTop(24.0f, &TabBar, &MainView);
// render news
if(g_Config.m_UiPage < PAGE_NEWS || g_Config.m_UiPage > PAGE_SETTINGS || (Client()->State() == IClient::STATE_OFFLINE && g_Config.m_UiPage >= PAGE_GAME && g_Config.m_UiPage <= PAGE_CALLVOTE))
if(m_ShowStart && Client()->State() == IClient::STATE_OFFLINE)
RenderStartMenu(Screen);
else
{
ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET);
g_Config.m_UiPage = PAGE_INTERNET;
m_DoubleClickIndex = -1;
}
Screen.HSplitTop(24.0f, &TabBar, &MainView);
// render current page
if(Client()->State() != IClient::STATE_OFFLINE)
{
if(m_GamePage == PAGE_GAME)
RenderGame(MainView);
else if(m_GamePage == PAGE_PLAYERS)
RenderPlayers(MainView);
else if(m_GamePage == PAGE_SERVER_INFO)
RenderServerInfo(MainView);
else if(m_GamePage == PAGE_NETWORK)
RenderInGameNetwork(MainView);
else if(m_GamePage == PAGE_GHOST)
RenderGhost(MainView);
else if(m_GamePage == PAGE_CALLVOTE)
RenderServerControl(MainView);
else if(m_GamePage == PAGE_SETTINGS)
if(Client()->State() == IClient::STATE_OFFLINE && m_EscapePressed)
{
m_ShowStart = true;
}
// render news
if(m_MenuPage < PAGE_NEWS || m_MenuPage > PAGE_SETTINGS || (Client()->State() == IClient::STATE_OFFLINE && m_MenuPage >= PAGE_GAME && m_MenuPage <= PAGE_CALLVOTE))
{
ServerBrowser()->Refresh(IServerBrowser::TYPE_INTERNET);
SetMenuPage(PAGE_INTERNET);
m_DoubleClickIndex = -1;
}
// render current page
if(Client()->State() != IClient::STATE_OFFLINE)
{
if(m_GamePage == PAGE_GAME)
RenderGame(MainView);
else if(m_GamePage == PAGE_PLAYERS)
RenderPlayers(MainView);
else if(m_GamePage == PAGE_SERVER_INFO)
RenderServerInfo(MainView);
else if(m_GamePage == PAGE_NETWORK)
RenderInGameNetwork(MainView);
else if(m_GamePage == PAGE_GHOST)
RenderGhost(MainView);
else if(m_GamePage == PAGE_CALLVOTE)
RenderServerControl(MainView);
else if(m_GamePage == PAGE_SETTINGS)
RenderSettings(MainView);
}
else if(m_MenuPage == PAGE_NEWS)
RenderNews(MainView);
else if(m_MenuPage == PAGE_INTERNET)
RenderServerbrowser(MainView);
else if(m_MenuPage == PAGE_LAN)
RenderServerbrowser(MainView);
else if(m_MenuPage == PAGE_DEMOS)
RenderDemoList(MainView);
else if(m_MenuPage == PAGE_FAVORITES)
RenderServerbrowser(MainView);
else if(m_MenuPage == PAGE_DDNET)
RenderServerbrowser(MainView);
else if(m_MenuPage == PAGE_KOG)
RenderServerbrowser(MainView);
else if(m_MenuPage == PAGE_SETTINGS)
RenderSettings(MainView);
}
else if(g_Config.m_UiPage == PAGE_NEWS)
RenderNews(MainView);
else if(g_Config.m_UiPage == PAGE_INTERNET)
RenderServerbrowser(MainView);
else if(g_Config.m_UiPage == PAGE_LAN)
RenderServerbrowser(MainView);
else if(g_Config.m_UiPage == PAGE_DEMOS)
RenderDemoList(MainView);
else if(g_Config.m_UiPage == PAGE_FAVORITES)
RenderServerbrowser(MainView);
else if(g_Config.m_UiPage == PAGE_DDNET)
RenderServerbrowser(MainView);
else if(g_Config.m_UiPage == PAGE_KOG)
RenderServerbrowser(MainView);
else if(g_Config.m_UiPage == PAGE_SETTINGS)
RenderSettings(MainView);
// do tab bar
RenderMenubar(TabBar);
// do tab bar
RenderMenubar(TabBar);
}
}
else
{
@ -2017,6 +2067,26 @@ extern "C" void font_debug_render();
void CMenus::OnRender()
{
if(m_ServerProcess.Pid != -1)
{
// TODO: Maybe call this less often, or probably even cleaner, use econ
if(!m_ServerProcess.Initialized)
{
IOHANDLE File = io_open("autoexec_server.log", IOFLAG_READ);
if(File)
{
m_ServerProcess.LineReader.Init(File);
m_ServerProcess.Initialized = true;
}
}
if(m_ServerProcess.Initialized)
{
const char *pLine = m_ServerProcess.LineReader.Get();
if(pLine)
GameClient()->m_pGameConsole->PrintLine(CGameConsole::CONSOLETYPE_SERVER, pLine);
}
}
if(Client()->State() != IClient::STATE_ONLINE && Client()->State() != IClient::STATE_DEMOPLAYBACK)
SetActive(true);
@ -2158,6 +2228,13 @@ void CMenus::RenderBackground()
Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);}
}
bool CMenus::CheckHotKey(int Key) const
{
return m_Popup == POPUP_NONE &&
!Input()->KeyIsPressed(KEY_LSHIFT) && !Input()->KeyIsPressed(KEY_RSHIFT) && !Input()->KeyIsPressed(KEY_LCTRL) && !Input()->KeyIsPressed(KEY_RCTRL) && !Input()->KeyIsPressed(KEY_LALT) && // no modifier
Input()->KeyIsPressed(Key) && m_pClient->m_pGameConsole->IsClosed();
}
int CMenus::DoButton_CheckBox_DontCare(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
{
switch(Checked)
@ -2222,3 +2299,103 @@ void CMenus::RenderUpdating(const char *pCaption, int current, int total)
Graphics()->Swap();
}
int CMenus::MenuImageScan(const char *pName, int IsDir, int DirType, void *pUser)
{
CMenus *pSelf = (CMenus *)pUser;
if(IsDir || !str_endswith(pName, ".png"))
return 0;
char aBuf[MAX_PATH_LENGTH];
str_format(aBuf, sizeof(aBuf), "menuimages/%s", pName);
CImageInfo Info;
if(!pSelf->Graphics()->LoadPNG(&Info, aBuf, DirType))
{
str_format(aBuf, sizeof(aBuf), "failed to load menu image from %s", pName);
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "game", aBuf);
return 0;
}
CMenuImage MenuImage;
MenuImage.m_OrgTexture = pSelf->Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, Info.m_Format, 0);
unsigned char *d = (unsigned char *)Info.m_pData;
//int Pitch = Info.m_Width*4;
// create colorless version
int Step = Info.m_Format == CImageInfo::FORMAT_RGBA ? 4 : 3;
// make the texture gray scale
for(int i = 0; i < Info.m_Width*Info.m_Height; i++)
{
int v = (d[i*Step]+d[i*Step+1]+d[i*Step+2])/3;
d[i*Step] = v;
d[i*Step+1] = v;
d[i*Step+2] = v;
}
/* same grey like sinks
int Freq[256] = {0};
int OrgWeight = 0;
int NewWeight = 192;
// find most common frequence
for(int y = 0; y < Info.m_Height; y++)
for(int x = 0; x < Info.m_Width; x++)
{
if(d[y*Pitch+x*4+3] > 128)
Freq[d[y*Pitch+x*4]]++;
}
for(int i = 1; i < 256; i++)
{
if(Freq[OrgWeight] < Freq[i])
OrgWeight = i;
}
// reorder
int InvOrgWeight = 255-OrgWeight;
int InvNewWeight = 255-NewWeight;
for(int y = 0; y < Info.m_Height; y++)
for(int x = 0; x < Info.m_Width; x++)
{
int v = d[y*Pitch+x*4];
if(v <= OrgWeight)
v = (int)(((v/(float)OrgWeight) * NewWeight));
else
v = (int)(((v-OrgWeight)/(float)InvOrgWeight)*InvNewWeight + NewWeight);
d[y*Pitch+x*4] = v;
d[y*Pitch+x*4+1] = v;
d[y*Pitch+x*4+2] = v;
}
*/
MenuImage.m_GreyTexture = pSelf->Graphics()->LoadTextureRaw(Info.m_Width, Info.m_Height, Info.m_Format, Info.m_pData, Info.m_Format, 0);
free(Info.m_pData);
// set menu image data
str_truncate(MenuImage.m_aName, sizeof(MenuImage.m_aName), pName, str_length(pName) - 4);
str_format(aBuf, sizeof(aBuf), "load menu image %s", MenuImage.m_aName);
pSelf->Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "game", aBuf);
pSelf->m_lMenuImages.add(MenuImage);
pSelf->RenderLoading();
return 0;
}
const CMenus::CMenuImage *CMenus::FindMenuImage(const char *pName)
{
for(int i = 0; i < m_lMenuImages.size(); i++)
{
if(str_comp(m_lMenuImages[i].m_aName, pName) == 0)
return &m_lMenuImages[i];
}
return 0;
}
void CMenus::SetMenuPage(int NewPage)
{
m_MenuPage = NewPage;
if(NewPage >= PAGE_INTERNET && NewPage <= PAGE_KOG)
g_Config.m_UiPage = NewPage;
}

View file

@ -9,11 +9,18 @@
#include <engine/demo.h>
#include <engine/friends.h>
#include <engine/shared/config.h>
#include <engine/shared/linereader.h>
#include <game/voting.h>
#include <game/client/component.h>
#include <game/client/ui.h>
struct CServerProcess
{
pid_t Pid;
bool Initialized;
CLineReader LineReader;
};
// compnent to fetch keypresses, override all other input
class CMenusKeyBinder : public CComponent
@ -39,11 +46,10 @@ class CMenus : public CComponent
float ButtonColorMul(const void *pID);
int DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
int DoButton_Sprite(const void *pID, int ImageID, int SpriteID, int Checked, const CUIRect *pRect, int Corners);
int DoButton_Toggle(const void *pID, int Checked, const CUIRect *pRect, bool Active);
int DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
int DoButton_Menu(const void *pID, const char *pText, int Checked, const CUIRect *pRect, const char *pImageName=0, 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 DoButton_MenuTab(const void *pID, const char *pText, int Checked, const CUIRect *pRect, int Corners);
int DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect);
@ -95,9 +101,11 @@ class CMenus : public CComponent
//static void demolist_listdir_callback(const char *name, int is_dir, void *user);
//static void demolist_list_callback(const CUIRect *rect, int index, void *user);
int m_MenuPage;
int m_GamePage;
int m_Popup;
int m_ActivePage;
bool m_ShowStart;
bool m_MenuActive;
bool m_UseMouseButtons;
vec2 m_MousePos;
@ -105,6 +113,19 @@ class CMenus : public CComponent
int64 m_LastInput;
// images
struct CMenuImage
{
char m_aName[64];
IGraphics::CTextureHandle m_OrgTexture;
IGraphics::CTextureHandle m_GreyTexture;
};
array<CMenuImage> m_lMenuImages;
static int MenuImageScan(const char *pName, int IsDir, int DirType, void *pUser);
const CMenuImage *FindMenuImage(const char* pName);
// loading
int m_LoadCurrent;
int m_LoadTotal;
@ -277,6 +298,9 @@ class CMenus : public CComponent
void RenderDemoPlayer(CUIRect MainView);
void RenderDemoList(CUIRect MainView);
// found in menus_start.cpp
void RenderStartMenu(CUIRect MainView);
// found in menus_ingame.cpp
void RenderGame(CUIRect MainView);
void RenderPlayers(CUIRect MainView);
@ -311,6 +335,9 @@ class CMenus : public CComponent
void SetActive(bool Active);
IGraphics::CTextureHandle m_TextureBlob;
bool CheckHotKey(int Key) const;
public:
void RenderBackground();
@ -437,6 +464,7 @@ public:
private:
static int GhostlistFetchCallback(const char *pName, int IsDir, int StorageType, void *pUser);
void SetMenuPage(int NewPage);
// found in menus_ingame.cpp
void RenderInGameNetwork(CUIRect MainView);
@ -446,5 +474,7 @@ private:
void RenderSettingsDDNet(CUIRect MainView);
void RenderSettingsHUD(CUIRect MainView);
ColorHSLA RenderHSLScrollbars(CUIRect *pRect, unsigned int *pColor, bool Alpha = false);
CServerProcess m_ServerProcess;
};
#endif

View file

@ -1306,97 +1306,13 @@ void CMenus::RenderServerbrowser(CUIRect MainView)
{
CUIRect Button, ButtonArea;
StatusBox.HSplitTop(5.0f, 0, &StatusBox);
// version note
#if defined(CONF_AUTOUPDATE)
CUIRect Part;
StatusBox.HSplitBottom(15.0f, &StatusBox, &Button);
char aBuf[64];
int State = Updater()->GetCurrentState();
bool NeedUpdate = str_comp(Client()->LatestVersion(), "0");
if(State == IUpdater::CLEAN && NeedUpdate)
{
str_format(aBuf, sizeof(aBuf), Localize("DDNet %s is out!"), Client()->LatestVersion());
TextRender()->TextColor(1.0f, 0.4f, 0.4f, 1.0f);
}
else if(State == IUpdater::CLEAN)
{
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), Localize("Downloading %s:"), aCurrentFile);
}
else if(State == IUpdater::FAIL)
{
str_format(aBuf, sizeof(aBuf), Localize("Update failed! Check log..."));
TextRender()->TextColor(1.0f, 0.4f, 0.4f, 1.0f);
}
else if(State == IUpdater::NEED_RESTART)
{
str_format(aBuf, sizeof(aBuf), Localize("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);
Button.VSplitLeft(TextRender()->TextWidth(0, 14.0f, aBuf, -1, -1.0f) + 10.0f, &Button, &Part);
if(State == IUpdater::CLEAN && NeedUpdate)
{
CUIRect Update;
Part.VSplitLeft(100.0f, &Update, NULL);
static int s_ButtonUpdate = 0;
if(DoButton_Menu(&s_ButtonUpdate, Localize("Update now"), 0, &Update))
{
Updater()->InitiateUpdate();
}
}
else if(State == IUpdater::NEED_RESTART)
{
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)
{
CUIRect ProgressBar, Percent;
Part.VSplitLeft(100.0f, &ProgressBar, &Percent);
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);
RenderTools()->DrawUIRect(&ProgressBar, vec4(1.0f, 1.0f, 1.0f, 0.5f), CUI::CORNER_ALL, 5.0f);
}
#else
StatusBox.HSplitBottom(15.0f, &StatusBox, &Button);
char aBuf[64];
if(str_comp(Client()->LatestVersion(), "0") != 0)
{
str_format(aBuf, sizeof(aBuf), Localize("DDNet %s is out!"), Client()->LatestVersion());
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
}
else
str_format(aBuf, sizeof(aBuf), Localize("Current version: %s"), GAME_VERSION);
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);
static int s_RefreshButton = 0;
char aBuf[64];
if(ServerBrowser()->IsRefreshing())
str_format(aBuf, sizeof(aBuf), "%s (%d%%)", Localize("Refresh"), ServerBrowser()->LoadingProgression());
else
@ -1438,6 +1354,7 @@ void CMenus::RenderServerbrowser(CUIRect MainView)
// address info
StatusBox.VSplitLeft(20.0f, 0, &StatusBox);
StatusBox.HSplitTop(5.0f, 0, &StatusBox);
StatusBox.HSplitTop(20.0f, &Button, &StatusBox);
UI()->DoLabelScaled(&Button, Localize("Host address"), 14.0f, -1);
StatusBox.HSplitTop(20.0f, &Button, 0);

View file

@ -165,8 +165,15 @@ void CMenus::RenderSettingsGeneral(CUIRect MainView)
Left.VSplitRight(5.0f, &Left, 0);
Right.VMargin(5.0f, &Right);
// skip main menu
Left.HSplitTop(5.0f, 0, &Left);
Left.HSplitTop(20.0f, &Button, &Left);
if(DoButton_CheckBox(&g_Config.m_ClSkipStartMenu, Localize("Skip the main menu"), g_Config.m_ClSkipStartMenu, &Button))
g_Config.m_ClSkipStartMenu^= 1;
// auto demo settings
{
Left.HSplitTop(5.0f, 0, &Left);
Left.HSplitTop(20.0f, &Button, &Left);
if(DoButton_CheckBox(&g_Config.m_ClAutoDemoRecord, Localize("Automatically record demos"), g_Config.m_ClAutoDemoRecord, &Button))
g_Config.m_ClAutoDemoRecord ^= 1;

View file

@ -0,0 +1,205 @@
/* (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 <engine/graphics.h>
#include <engine/keys.h>
#include <engine/textrender.h>
#include <engine/client/updater.h>
#include <engine/shared/config.h>
#include <game/editor/editor.h>
#include <game/version.h>
#include <game/client/components/console.h>
#include <game/client/render.h>
#include <game/client/ui.h>
#include "menus.h"
void CMenus::RenderStartMenu(CUIRect MainView)
{
// render logo
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_BANNER].m_Id);
Graphics()->QuadsBegin();
Graphics()->SetColor(1,1,1,1);
IGraphics::CQuadItem QuadItem(MainView.w/2-170, 60, 360, 103);
Graphics()->QuadsDrawTL(&QuadItem, 1);
Graphics()->QuadsEnd();
const float Rounding = 10.0f;
const float VMargin = MainView.w/2-190.0f;
CUIRect Menu;
MainView.VMargin(VMargin, &Menu);
Menu.HSplitBottom(20.0f, &Menu, 0);
CUIRect Button;
int NewPage = -1;
Menu.HSplitBottom(40.0f, &Menu, &Button);
static int s_QuitButton;
if(DoButton_Menu(&s_QuitButton, Localize("Quit"), 0, &Button, 0, CUI::CORNER_ALL, Rounding, 0.5f, vec4(0.0f, 0.0f, 0.0f, 0.5f), vec4(0.0f, 0.0f, 0.0f, 0.25f)) || m_EscapePressed || CheckHotKey(KEY_Q))
m_Popup = POPUP_QUIT;
Menu.HSplitBottom(40.0f, &Menu, 0);
Menu.HSplitBottom(40.0f, &Menu, &Button);
static int s_SettingsButton;
if(DoButton_Menu(&s_SettingsButton, Localize("Settings"), 0, &Button, g_Config.m_ClShowStartMenuImages ? "settings" : 0, CUI::CORNER_ALL, Rounding, 0.5f, vec4(0.0f, 0.0f, 0.0f, 0.5f), vec4(0.0f, 0.0f, 0.0f, 0.25f)) || CheckHotKey(KEY_S))
NewPage = PAGE_SETTINGS;
Menu.HSplitBottom(5.0f, &Menu, 0); // little space
Menu.HSplitBottom(40.0f, &Menu, &Button);
static int s_LocalServerButton = 0;
if(DoButton_Menu(&s_LocalServerButton, m_ServerProcess.Pid == -1 ? Localize("Run server") : Localize("Stop server"), 0, &Button, g_Config.m_ClShowStartMenuImages ? "local_server" : 0, CUI::CORNER_ALL, Rounding, 0.5f, vec4(0.0f, 0.0f, 0.0f, 0.5f), m_ServerProcess.Pid == -1 ? vec4(0.0f, 0.0f, 0.0f, 0.25f) : vec4(0.0f, 1.0f, 0.0f, 0.25f)) || CheckHotKey(KEY_R))
{
if(m_ServerProcess.Pid == -1)
{
m_ServerProcess.Pid = shell_execute(PLAT_SERVER_EXEC);
}
else
{
kill_process(m_ServerProcess.Pid);
m_ServerProcess.Pid = -1;
}
}
Menu.HSplitBottom(5.0f, &Menu, 0); // little space
Menu.HSplitBottom(40.0f, &Menu, &Button);
static int s_LearnButton;
if(DoButton_Menu(&s_LearnButton, Localize("Learn"), 0, &Button, g_Config.m_ClShowStartMenuImages ? "learn" : 0, CUI::CORNER_ALL, Rounding, 0.5f, vec4(0.0f, 0.0f, 0.0f, 0.5f), vec4(0.0f, 0.0f, 0.0f, 0.25f)) || CheckHotKey(KEY_L))
{
if(!open_link("https://wiki.ddnet.tw/"))
{
dbg_msg("menus", "couldn't open link");
}
m_DoubleClickIndex = -1;
}
Menu.HSplitBottom(5.0f, &Menu, 0); // little space
Menu.HSplitBottom(40.0f, &Menu, &Button);
static int s_NewsButton;
if(DoButton_Menu(&s_NewsButton, Localize("News"), 0, &Button, g_Config.m_ClShowStartMenuImages ? "news" : 0, CUI::CORNER_ALL, Rounding, 0.5f, vec4(0.0f, 0.0f, 0.0f, 0.5f), g_Config.m_UiUnreadNews ? vec4(0.0f, 1.0f, 0.0f, 0.25f) : vec4(0.0f, 0.0f, 0.0f, 0.25f)) || CheckHotKey(KEY_N))
NewPage = PAGE_NEWS;
static bool EditorHotkeyWasPressed = true;
static float EditorHotKeyChecktime = 0;
Menu.HSplitBottom(5.0f, &Menu, 0); // little space
Menu.HSplitBottom(40.0f, &Menu, &Button);
static int s_MapEditorButton;
if(DoButton_Menu(&s_MapEditorButton, Localize("Editor"), 0, &Button, g_Config.m_ClShowStartMenuImages ? "editor" : 0, CUI::CORNER_ALL, Rounding, 0.5f, vec4(0.0f, 0.0f, 0.0f, 0.5f), m_pClient->Editor()->HasUnsavedData() ? vec4(0.0f, 1.0f, 0.0f, 0.25f) : vec4(0.0f, 0.0f, 0.0f, 0.25f)) || (!EditorHotkeyWasPressed && Client()->LocalTime() - EditorHotKeyChecktime < 0.1f && CheckHotKey(KEY_E)))
{
g_Config.m_ClEditor = 1;
Input()->MouseModeRelative();
EditorHotkeyWasPressed = true;
}
if(!Input()->KeyIsPressed(KEY_E))
{
EditorHotkeyWasPressed = false;
EditorHotKeyChecktime = Client()->LocalTime();
}
Menu.HSplitBottom(5.0f, &Menu, 0); // little space
Menu.HSplitBottom(40.0f, &Menu, &Button);
static int s_DemoButton;
if(DoButton_Menu(&s_DemoButton, Localize("Demos"), 0, &Button, g_Config.m_ClShowStartMenuImages ? "demos" : 0, CUI::CORNER_ALL, Rounding, 0.5f, vec4(0.0f, 0.0f, 0.0f, 0.5f), vec4(0.0f, 0.0f, 0.0f, 0.25f)) || CheckHotKey(KEY_D))
{
NewPage = PAGE_DEMOS;
}
Menu.HSplitBottom(5.0f, &Menu, 0); // little space
Menu.HSplitBottom(40.0f, &Menu, &Button);
static int s_PlayButton;
if(DoButton_Menu(&s_PlayButton, Localize("Play"), 0, &Button, g_Config.m_ClShowStartMenuImages ? "play_game" : 0, CUI::CORNER_ALL, Rounding, 0.5f, vec4(0.0f, 0.0f, 0.0f, 0.5f), vec4(0.0f, 0.0f, 0.0f, 0.25f)) || m_EnterPressed || CheckHotKey(KEY_P))
NewPage = g_Config.m_UiPage;
// render version
CUIRect Version;
MainView.HSplitBottom(30.0f, 0, &Version);
MainView.HSplitBottom(20.0f, 0, &Version);
Version.VSplitLeft(VMargin, 0, &Version);
Version.VSplitRight(50.0f, &Version, 0);
char aBuf[64];
#if defined(CONF_AUTOUPDATE)
CUIRect Part;
int State = Updater()->GetCurrentState();
bool NeedUpdate = str_comp(Client()->LatestVersion(), "0");
if(State == IUpdater::CLEAN && NeedUpdate)
{
str_format(aBuf, sizeof(aBuf), Localize("DDNet %s is out!"), Client()->LatestVersion());
TextRender()->TextColor(1.0f, 0.4f, 0.4f, 1.0f);
}
else if(State == IUpdater::CLEAN)
{
aBuf[0] = '\0';
}
else if(State >= IUpdater::GETTING_MANIFEST && State < IUpdater::NEED_RESTART)
{
char aCurrentFile[64];
Updater()->GetCurrentFile(aCurrentFile, sizeof(aCurrentFile));
str_format(aBuf, sizeof(aBuf), Localize("Downloading %s:"), aCurrentFile);
}
else if(State == IUpdater::FAIL)
{
str_format(aBuf, sizeof(aBuf), Localize("Update failed! Check log..."));
TextRender()->TextColor(1.0f, 0.4f, 0.4f, 1.0f);
}
else if(State == IUpdater::NEED_RESTART)
{
str_format(aBuf, sizeof(aBuf), Localize("DDNet Client updated!"));
TextRender()->TextColor(1.0f, 0.4f, 0.4f, 1.0f);
}
UI()->DoLabel(&Version, aBuf, 14.0f, -1);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
Version.VSplitLeft(TextRender()->TextWidth(0, 14.0f, aBuf, -1, -1.0f) + 10.0f, 0, &Part);
if(State == IUpdater::CLEAN && NeedUpdate)
{
CUIRect Update;
Part.VSplitLeft(100.0f, &Update, NULL);
static int s_VersionUpdate = 0;
if(DoButton_Menu(&s_VersionUpdate, Localize("Update now"), 0, &Update, 0, CUI::CORNER_ALL, 5.0f, 0.0f, vec4(0.0f, 0.0f, 0.0f, 0.5f), vec4(0.0f, 0.0f, 0.0f, 0.25f)))
{
Updater()->InitiateUpdate();
}
}
else if(State == IUpdater::NEED_RESTART)
{
CUIRect Restart;
Part.VSplitLeft(50.0f, &Restart, &Part);
static int s_VersionUpdate = 0;
if(DoButton_Menu(&s_VersionUpdate, Localize("Restart"), 0, &Restart, 0, CUI::CORNER_ALL, 5.0f, 0.0f, vec4(0.0f, 0.0f, 0.0f, 0.5f), vec4(0.0f, 0.0f, 0.0f, 0.25f)))
{
Client()->Restart();
}
}
else if(State >= IUpdater::GETTING_MANIFEST && State < IUpdater::NEED_RESTART)
{
CUIRect ProgressBar, Percent;
Part.VSplitLeft(100.0f, &ProgressBar, &Percent);
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);
RenderTools()->DrawUIRect(&ProgressBar, vec4(1.0f, 1.0f, 1.0f, 0.5f), CUI::CORNER_ALL, 5.0f);
}
#else
if(str_comp(Client()->LatestVersion(), "0") != 0)
{
str_format(aBuf, sizeof(aBuf), Localize("DDNet %s is out!"), Client()->LatestVersion());
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
UI()->DoLabel(&Version, aBuf, 14.0f, -1);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
}
#endif
UI()->DoLabel(&Version, GAME_RELEASE_VERSION, 14.0f, 1);
if(NewPage != -1)
{
m_MenuPage = NewPage;
m_ShowStart = false;
}
}

View file

@ -212,6 +212,153 @@ void CRenderTools::DrawRoundRectExt(float x, float y, float w, float h, float r,
Graphics()->QuadsDrawTL(ArrayQ, NumItems);
}
void CRenderTools::DrawRoundRectExt4(float x, float y, float w, float h, vec4 ColorTopLeft, vec4 ColorTopRight, vec4 ColorBottomLeft, vec4 ColorBottomRight, float r, int Corners)
{
int Num = 8;
for(int i = 0; i < Num; i+=2)
{
float a1 = i/(float)Num * pi/2;
float a2 = (i+1)/(float)Num * pi/2;
float a3 = (i+2)/(float)Num * pi/2;
float Ca1 = cosf(a1);
float Ca2 = cosf(a2);
float Ca3 = cosf(a3);
float Sa1 = sinf(a1);
float Sa2 = sinf(a2);
float Sa3 = sinf(a3);
if(Corners&1) // TL
{
Graphics()->SetColor(ColorTopLeft.r, ColorTopLeft.g, ColorTopLeft.b, ColorTopLeft.a);
IGraphics::CFreeformItem ItemF = IGraphics::CFreeformItem(
x+r, y+r,
x+(1-Ca1)*r, y+(1-Sa1)*r,
x+(1-Ca3)*r, y+(1-Sa3)*r,
x+(1-Ca2)*r, y+(1-Sa2)*r);
Graphics()->QuadsDrawFreeform(&ItemF, 1);
}
if(Corners&2) // TR
{
Graphics()->SetColor(ColorTopRight.r, ColorTopRight.g, ColorTopRight.b, ColorTopRight.a);
IGraphics::CFreeformItem ItemF = IGraphics::CFreeformItem(
x+w-r, y+r,
x+w-r+Ca1*r, y+(1-Sa1)*r,
x+w-r+Ca3*r, y+(1-Sa3)*r,
x+w-r+Ca2*r, y+(1-Sa2)*r);
Graphics()->QuadsDrawFreeform(&ItemF, 1);
}
if(Corners&4) // BL
{
Graphics()->SetColor(ColorBottomLeft.r, ColorBottomLeft.g, ColorBottomLeft.b, ColorBottomLeft.a);
IGraphics::CFreeformItem ItemF = IGraphics::CFreeformItem(
x+r, y+h-r,
x+(1-Ca1)*r, y+h-r+Sa1*r,
x+(1-Ca3)*r, y+h-r+Sa3*r,
x+(1-Ca2)*r, y+h-r+Sa2*r);
Graphics()->QuadsDrawFreeform(&ItemF, 1);
}
if(Corners&8) // BR
{
Graphics()->SetColor(ColorBottomRight.r, ColorBottomRight.g, ColorBottomRight.b, ColorBottomRight.a);
IGraphics::CFreeformItem ItemF = IGraphics::CFreeformItem(
x+w-r, y+h-r,
x+w-r+Ca1*r, y+h-r+Sa1*r,
x+w-r+Ca3*r, y+h-r+Sa3*r,
x+w-r+Ca2*r, y+h-r+Sa2*r);
Graphics()->QuadsDrawFreeform(&ItemF, 1);
}
if(Corners&16) // ITL
{
Graphics()->SetColor(ColorTopLeft.r, ColorTopLeft.g, ColorTopLeft.b, ColorTopLeft.a);
IGraphics::CFreeformItem ItemF = IGraphics::CFreeformItem(
x, y,
x+(1-Ca1)*r, y-r+Sa1*r,
x+(1-Ca3)*r, y-r+Sa3*r,
x+(1-Ca2)*r, y-r+Sa2*r);
Graphics()->QuadsDrawFreeform(&ItemF, 1);
}
if(Corners&32) // ITR
{
Graphics()->SetColor(ColorTopRight.r, ColorTopRight.g, ColorTopRight.b, ColorTopRight.a);
IGraphics::CFreeformItem ItemF = IGraphics::CFreeformItem(
x+w, y,
x+w-r+Ca1*r, y-r+Sa1*r,
x+w-r+Ca3*r, y-r+Sa3*r,
x+w-r+Ca2*r, y-r+Sa2*r);
Graphics()->QuadsDrawFreeform(&ItemF, 1);
}
if(Corners&64) // IBL
{
Graphics()->SetColor(ColorBottomLeft.r, ColorBottomLeft.g, ColorBottomLeft.b, ColorBottomLeft.a);
IGraphics::CFreeformItem ItemF = IGraphics::CFreeformItem(
x, y+h,
x+(1-Ca1)*r, y+h+(1-Sa1)*r,
x+(1-Ca3)*r, y+h+(1-Sa3)*r,
x+(1-Ca2)*r, y+h+(1-Sa2)*r);
Graphics()->QuadsDrawFreeform(&ItemF, 1);
}
if(Corners&128) // IBR
{
Graphics()->SetColor(ColorBottomRight.r, ColorBottomRight.g, ColorBottomRight.b, ColorBottomRight.a);
IGraphics::CFreeformItem ItemF = IGraphics::CFreeformItem(
x+w, y+h,
x+w-r+Ca1*r, y+h+(1-Sa1)*r,
x+w-r+Ca3*r, y+h+(1-Sa3)*r,
x+w-r+Ca2*r, y+h+(1-Sa2)*r);
Graphics()->QuadsDrawFreeform(&ItemF, 1);
}
}
Graphics()->SetColor4(ColorTopLeft, ColorTopRight, ColorBottomLeft, ColorBottomRight);
IGraphics::CQuadItem ItemQ = IGraphics::CQuadItem(x+r, y+r, w-r*2, h-r*2); // center
Graphics()->QuadsDrawTL(&ItemQ, 1);
Graphics()->SetColor4(ColorTopLeft, ColorTopRight, ColorTopLeft, ColorTopRight);
ItemQ = IGraphics::CQuadItem(x+r, y, w-r*2, r); // top
Graphics()->QuadsDrawTL(&ItemQ, 1);
Graphics()->SetColor4(ColorBottomLeft, ColorBottomRight, ColorBottomLeft, ColorBottomRight);
ItemQ = IGraphics::CQuadItem(x+r, y+h-r, w-r*2, r); // bottom
Graphics()->QuadsDrawTL(&ItemQ, 1);
Graphics()->SetColor4(ColorTopLeft, ColorTopLeft, ColorBottomLeft, ColorBottomLeft);
ItemQ = IGraphics::CQuadItem(x, y+r, r, h-r*2); // left
Graphics()->QuadsDrawTL(&ItemQ, 1);
Graphics()->SetColor4(ColorTopRight, ColorTopRight, ColorBottomRight, ColorBottomRight);
ItemQ = IGraphics::CQuadItem(x+w-r, y+r, r, h-r*2); // right
Graphics()->QuadsDrawTL(&ItemQ, 1);
if(!(Corners&1))
{
Graphics()->SetColor(ColorTopLeft.r, ColorTopLeft.g, ColorTopLeft.b, ColorTopLeft.a);
IGraphics::CQuadItem ItemQ = IGraphics::CQuadItem(x, y, r, r); // TL
Graphics()->QuadsDrawTL(&ItemQ, 1);
}
if(!(Corners&2))
{
Graphics()->SetColor(ColorTopRight.r, ColorTopRight.g, ColorTopRight.b, ColorTopRight.a);
IGraphics::CQuadItem ItemQ = IGraphics::CQuadItem(x+w, y, -r, r); // TR
Graphics()->QuadsDrawTL(&ItemQ, 1);
}
if(!(Corners&4))
{
Graphics()->SetColor(ColorBottomLeft.r, ColorBottomLeft.g, ColorBottomLeft.b, ColorBottomLeft.a);
IGraphics::CQuadItem ItemQ = IGraphics::CQuadItem(x, y+h, r, -r); // BL
Graphics()->QuadsDrawTL(&ItemQ, 1);
}
if(!(Corners&8))
{
Graphics()->SetColor(ColorBottomRight.r, ColorBottomRight.g, ColorBottomRight.b, ColorBottomRight.a);
IGraphics::CQuadItem ItemQ = IGraphics::CQuadItem(x+w, y+h, -r, -r); // BR
Graphics()->QuadsDrawTL(&ItemQ, 1);
}
}
int CRenderTools::CreateRoundRectQuadContainer(float x, float y, float w, float h, float r, int Corners)
{
int ContainerIndex = Graphics()->CreateQuadContainer();
@ -295,6 +442,16 @@ void CRenderTools::DrawUIRect(const CUIRect *r, ColorRGBA Color, int Corners, fl
Graphics()->QuadsEnd();
}
void CRenderTools::DrawUIRect4(const CUIRect *r, vec4 ColorTopLeft, vec4 ColorTopRight, vec4 ColorBottomLeft, vec4 ColorBottomRight, int Corners, float Rounding)
{
Graphics()->TextureClear();
Graphics()->QuadsBegin();
DrawRoundRectExt4(r->x,r->y,r->w,r->h,ColorTopLeft,ColorTopRight,ColorBottomLeft,ColorBottomRight,Rounding, Corners);
Graphics()->QuadsEnd();
}
void CRenderTools::DrawCircle(float x, float y, float r, int Segments)
{
IGraphics::CFreeformItem Array[32];

View file

@ -66,10 +66,12 @@ public:
// rects
void DrawRoundRect(float x, float y, float w, float h, float r);
void DrawRoundRectExt(float x, float y, float w, float h, float r, int Corners);
void DrawRoundRectExt4(float x, float y, float w, float h, vec4 ColorTopLeft, vec4 ColorTopRight, vec4 ColorBottomLeft, vec4 ColorBottomRight, float r, int Corners);
int CreateRoundRectQuadContainer(float x, float y, float w, float h, float r, int Corners);
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);
void DrawCircle(float x, float y, float r, int Segments);

View file

@ -5775,16 +5775,8 @@ void CEditor::RenderMenubar(CUIRect MenuBar)
UI()->DoLabel(&Info, aBuf, 10.0f, 1, -1);
static int s_CloseButton = 0;
if(DoButton_Editor(&s_CloseButton, "×", 0, &Close, 0, "Exits from the editor"))
{
if(HasUnsavedData())
{
m_PopupEventType = POPEVENT_EXIT;
m_PopupEventActivated = true;
}
else
g_Config.m_ClEditor = 0;
}
if(DoButton_Editor(&s_CloseButton, "×", 0, &Close, 0, "Exits from the editor") || (m_Dialog == DIALOG_NONE && !m_PopupEventActivated && Input()->KeyPress(KEY_ESCAPE)))
g_Config.m_ClEditor = 0;
}
void CEditor::Render()

View file

@ -112,6 +112,7 @@ MACRO_CONFIG_INT(UiColorizeGametype, ui_colorize_gametype, 1, 0, 1, CFGFLAG_CLIE
MACRO_CONFIG_STR(UiDemoSelected, ui_demo_selected, 256, "", CFGFLAG_CLIENT|CFGFLAG_SAVE, "Selected demo file")
MACRO_CONFIG_INT(UiCloseWindowAfterChangingSetting, ui_close_window_after_changing_setting, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Close window after changing setting")
MACRO_CONFIG_INT(UiUnreadNews, ui_unread_news, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Whether there is unread news")
MACRO_CONFIG_INT(GfxNoclip, gfx_noclip, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Disable clipping")
@ -135,6 +136,10 @@ MACRO_CONFIG_INT(ClDummyJump, cl_dummy_jump, 0, 0, 1, CFGFLAG_CLIENT, "Whether d
MACRO_CONFIG_INT(ClDummyFire, cl_dummy_fire, 0, 0, 1, CFGFLAG_CLIENT, "Whether dummy is firing")
MACRO_CONFIG_INT(ClDummyHook, cl_dummy_hook, 0, 0, 1, CFGFLAG_CLIENT, "Whether dummy is hooking")
// start menu
MACRO_CONFIG_INT(ClShowStartMenuImages, cl_show_start_menu_images, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show start menu images")
MACRO_CONFIG_INT(ClSkipStartMenu, cl_skip_start_menu, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Skip the start menu")
// server
MACRO_CONFIG_INT(SvWarmup, sv_warmup, 0, 0, 0, CFGFLAG_SERVER, "Number of seconds to do warmup before round starts")
MACRO_CONFIG_STR(SvMotd, sv_motd, 900, "", CFGFLAG_SERVER, "Message of the day to display for the clients")