Merge pull request #8521 from Robyt3/Client-Loading-Improvements

Refactor client loading and loading screen, fix progress bar alignment when updating
This commit is contained in:
Dennis Felsing 2024-06-25 21:57:29 +00:00 committed by GitHub
commit b0a1135de6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 97 additions and 90 deletions

View file

@ -734,17 +734,16 @@ void CMenus::RenderLoading(const char *pCaption, const char *pContent, int Incre
{
// TODO: not supported right now due to separate render thread
static std::chrono::nanoseconds s_LastLoadRender{0};
const int CurLoadRenderCount = m_LoadCurrent;
m_LoadCurrent += IncreaseCounter;
const float Percent = CurLoadRenderCount / (float)m_LoadTotal;
const int CurLoadRenderCount = m_LoadingState.m_Current;
m_LoadingState.m_Current += IncreaseCounter;
// make sure that we don't render for each little thing we load
// because that will slow down loading if we have vsync
if(time_get_nanoseconds() - s_LastLoadRender < std::chrono::nanoseconds(1s) / 60l)
const std::chrono::nanoseconds Now = time_get_nanoseconds();
if(Now - m_LoadingState.m_LastRender < std::chrono::nanoseconds(1s) / 60l)
return;
s_LastLoadRender = time_get_nanoseconds();
m_LoadingState.m_LastRender = Now;
// need up date this here to get correct
ms_GuiColor = color_cast<ColorRGBA>(ColorHSLA(g_Config.m_UiColor, true));
@ -756,27 +755,30 @@ void CMenus::RenderLoading(const char *pCaption, const char *pContent, int Incre
RenderBackground();
}
CUIRect Box = *Ui()->Screen();
Box.Margin(160.0f, &Box);
CUIRect Box;
Ui()->Screen()->Margin(160.0f, &Box);
Graphics()->BlendNormal();
Graphics()->TextureClear();
Box.Draw(ColorRGBA{0, 0, 0, 0.50f}, IGraphics::CORNER_ALL, 15.0f);
Box.Draw(ColorRGBA(0.0f, 0.0f, 0.0f, 0.5f), IGraphics::CORNER_ALL, 15.0f);
Box.Margin(20.0f, &Box);
CUIRect Part;
Box.HSplitTop(20.f, nullptr, &Box);
Box.HSplitTop(24.f, &Part, &Box);
Part.VMargin(20.f, &Part);
Ui()->DoLabel(&Part, pCaption, 24.f, TEXTALIGN_MC);
CUIRect Label;
Box.HSplitTop(24.0f, &Label, &Box);
Ui()->DoLabel(&Label, pCaption, 24.0f, TEXTALIGN_MC);
Box.HSplitTop(20.f, nullptr, &Box);
Box.HSplitTop(24.f, &Part, &Box);
Part.VMargin(20.f, &Part);
Ui()->DoLabel(&Part, pContent, 20.0f, TEXTALIGN_MC);
Box.HSplitTop(20.0f, nullptr, &Box);
Box.HSplitTop(24.0f, &Label, &Box);
Ui()->DoLabel(&Label, pContent, 20.0f, TEXTALIGN_MC);
if(RenderLoadingBar)
Graphics()->DrawRect(Box.x + 40, Box.y + Box.h - 75, (Box.w - 80) * Percent, 25, ColorRGBA(1.0f, 1.0f, 1.0f, 0.75f), IGraphics::CORNER_ALL, 5.0f);
{
CUIRect ProgressBar;
Box.HSplitBottom(30.0f, &Box, nullptr);
Box.HSplitBottom(25.0f, &Box, &ProgressBar);
ProgressBar.VMargin(20.0f, &ProgressBar);
Ui()->RenderProgressBar(ProgressBar, CurLoadRenderCount / (float)m_LoadingState.m_Total);
}
Client()->UpdateAndSwap();
}
@ -867,10 +869,10 @@ void CMenus::OnInit()
// setup load amount
const int NumMenuImages = 5;
m_LoadCurrent = 0;
m_LoadTotal = g_pData->m_NumImages + NumMenuImages + GameClient()->ComponentCount();
m_LoadingState.m_Current = 0;
m_LoadingState.m_Total = g_pData->m_NumImages + NumMenuImages + GameClient()->ComponentCount();
if(!g_Config.m_ClThreadsoundloading)
m_LoadTotal += g_pData->m_NumSounds;
m_LoadingState.m_Total += g_pData->m_NumSounds;
m_IsInit = true;
@ -1915,9 +1917,7 @@ void CMenus::RenderPopupLoading(CUIRect Screen)
Box.HSplitTop(20.0f, nullptr, &Box);
Box.HSplitTop(24.0f, &ProgressBar, &Box);
ProgressBar.VMargin(20.0f, &ProgressBar);
ProgressBar.Draw(ColorRGBA(1.0f, 1.0f, 1.0f, 0.25f), IGraphics::CORNER_ALL, 5.0f);
ProgressBar.w = maximum(10.0f, (ProgressBar.w * Client()->MapDownloadAmount()) / Client()->MapDownloadTotalsize());
ProgressBar.Draw(ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f), IGraphics::CORNER_ALL, 5.0f);
Ui()->RenderProgressBar(ProgressBar, Client()->MapDownloadAmount() / (float)Client()->MapDownloadTotalsize());
}
CUIRect Button;

View file

@ -186,8 +186,14 @@ protected:
const CMenuImage *FindMenuImage(const char *pName);
// loading
int m_LoadCurrent;
int m_LoadTotal;
class CLoadingState
{
public:
std::chrono::nanoseconds m_LastRender{0};
int m_Current;
int m_Total;
};
CLoadingState m_LoadingState;
//
char m_aMessageTopic[512];

View file

@ -199,16 +199,42 @@ void CMenus::RenderStartMenu(CUIRect MainView)
// render version
CUIRect VersionUpdate, CurVersion;
MainView.HSplitBottom(20.0f, 0, &VersionUpdate);
VersionUpdate.VSplitRight(50.0f, &CurVersion, 0);
MainView.HSplitBottom(20.0f, nullptr, &VersionUpdate);
VersionUpdate.VSplitRight(50.0f, &CurVersion, nullptr);
VersionUpdate.VMargin(VMargin, &VersionUpdate);
Ui()->DoLabel(&CurVersion, GAME_RELEASE_VERSION, 14.0f, TEXTALIGN_MR);
#if defined(CONF_AUTOUPDATE)
char aBuf[64];
CUIRect Part;
IUpdater::EUpdaterState State = Updater()->GetCurrentState();
bool NeedUpdate = str_comp(Client()->LatestVersion(), "0");
CUIRect UpdateButton;
VersionUpdate.VSplitRight(100.0f, &VersionUpdate, &UpdateButton);
VersionUpdate.VSplitRight(10.0f, &VersionUpdate, nullptr);
char aBuf[128];
const IUpdater::EUpdaterState State = Updater()->GetCurrentState();
const bool NeedUpdate = str_comp(Client()->LatestVersion(), "0");
if(State == IUpdater::CLEAN && NeedUpdate)
{
static CButtonContainer s_VersionUpdate;
if(DoButton_Menu(&s_VersionUpdate, Localize("Update now"), 0, &UpdateButton, 0, IGraphics::CORNER_ALL, 5.0f, 0.0f, ColorRGBA(0.0f, 0.0f, 0.0f, 0.25f)))
{
Updater()->InitiateUpdate();
}
}
else if(State == IUpdater::NEED_RESTART)
{
static CButtonContainer s_VersionUpdate;
if(DoButton_Menu(&s_VersionUpdate, Localize("Restart"), 0, &UpdateButton, 0, IGraphics::CORNER_ALL, 5.0f, 0.0f, ColorRGBA(0.0f, 0.0f, 0.0f, 0.25f)))
{
Client()->Restart();
}
}
else if(State >= IUpdater::GETTING_MANIFEST && State < IUpdater::NEED_RESTART)
{
Ui()->RenderProgressBar(UpdateButton, Updater()->GetCurrentPercent() / 100.0f);
}
if(State == IUpdater::CLEAN && NeedUpdate)
{
str_format(aBuf, sizeof(aBuf), Localize("DDNet %s is out!"), Client()->LatestVersion());
@ -235,55 +261,17 @@ void CMenus::RenderStartMenu(CUIRect MainView)
TextRender()->TextColor(1.0f, 0.4f, 0.4f, 1.0f);
}
Ui()->DoLabel(&VersionUpdate, aBuf, 14.0f, TEXTALIGN_ML);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
VersionUpdate.VSplitLeft(TextRender()->TextWidth(14.0f, aBuf, -1, -1.0f) + 10.0f, 0, &Part);
if(State == IUpdater::CLEAN && NeedUpdate)
{
CUIRect Update;
Part.VSplitLeft(100.0f, &Update, NULL);
static CButtonContainer s_VersionUpdate;
if(DoButton_Menu(&s_VersionUpdate, Localize("Update now"), 0, &Update, 0, IGraphics::CORNER_ALL, 5.0f, 0.0f, ColorRGBA(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 CButtonContainer s_VersionUpdate;
if(DoButton_Menu(&s_VersionUpdate, Localize("Restart"), 0, &Restart, 0, IGraphics::CORNER_ALL, 5.0f, 0.0f, ColorRGBA(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);
ProgressBar.Draw(ColorRGBA(1.0f, 1.0f, 1.0f, 0.25f), IGraphics::CORNER_ALL, 5.0f);
ProgressBar.w = clamp((float)Updater()->GetCurrentPercent(), 10.0f, 100.0f);
ProgressBar.Draw(ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f), IGraphics::CORNER_ALL, 5.0f);
}
TextRender()->TextColor(TextRender()->DefaultTextColor());
#elif defined(CONF_INFORM_UPDATE)
if(str_comp(Client()->LatestVersion(), "0") != 0)
{
char aBuf[64];
str_format(aBuf, sizeof(aBuf), Localize("DDNet %s is out!"), Client()->LatestVersion());
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
TextRender()->TextColor(TextRender()->DefaultTextColor());
Ui()->DoLabel(&VersionUpdate, aBuf, 14.0f, TEXTALIGN_MC);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
}
#endif
Ui()->DoLabel(&CurVersion, GAME_RELEASE_VERSION, 14.0f, TEXTALIGN_MR);
if(NewPage != -1)
{
m_ShowStart = false;

View file

@ -23,6 +23,7 @@
#include <game/generated/client_data7.h>
#include <game/generated/protocol.h>
#include <base/log.h>
#include <base/math.h>
#include <base/system.h>
#include <base/vmath.h>
@ -203,6 +204,8 @@ void CGameClient::OnConsoleInit()
void CGameClient::OnInit()
{
const int64_t OnInitStart = time_get();
Client()->SetLoadingCallback([this](IClient::ELoadingCallbackDetail Detail) {
const char *pTitle;
if(Detail == IClient::LOADING_CALLBACK_DETAIL_DEMO || DemoPlayer()->IsPlaying())
@ -236,8 +239,6 @@ void CGameClient::OnInit()
m_UI.Init(Kernel());
m_RenderTools.Init(Graphics(), TextRender());
int64_t Start = time_get();
if(GIT_SHORTREV_HASH)
{
str_format(m_aDDNetVersionStr, sizeof(m_aDDNetVersionStr), "%s %s (%s)", GAME_NAME, GAME_RELEASE_VERSION, GIT_SHORTREV_HASH);
@ -265,20 +266,23 @@ void CGameClient::OnInit()
Client()->UpdateAndSwap();
const char *pLoadingDDNetCaption = Localize("Loading DDNet Client");
const char *pLoadingMessageComponents = Localize("Initializing components");
const char *pLoadingMessageComponentsSpecial = Localize("Why are you slowmo replaying to read this?");
char aLoadingMessage[256];
// init all components
int SkippedComps = 0;
int CompCounter = 0;
for(int i = m_vpAll.size() - 1; i >= 0; --i)
int SkippedComps = 1;
int CompCounter = 1;
const int NumComponents = ComponentCount();
for(int i = NumComponents - 1; i >= 0; --i)
{
m_vpAll[i]->OnInit();
// try to render a frame after each component, also flushes GPU uploads
if(m_Menus.IsInit())
{
char aBuff[256];
str_format(aBuff, std::size(aBuff), "%s [%d/%d]", CompCounter == 40 ? Localize("Why are you slowmo replaying to read this?") : Localize("Initializing components"), (CompCounter + 1), (int)ComponentCount());
m_Menus.RenderLoading(pLoadingDDNetCaption, aBuff, 1 + SkippedComps);
SkippedComps = 0;
str_format(aLoadingMessage, std::size(aLoadingMessage), "%s [%d/%d]", CompCounter == NumComponents ? pLoadingMessageComponentsSpecial : pLoadingMessageComponents, CompCounter, NumComponents);
m_Menus.RenderLoading(pLoadingDDNetCaption, aLoadingMessage, SkippedComps);
SkippedComps = 1;
}
else
{
@ -293,6 +297,7 @@ void CGameClient::OnInit()
m_HudSkinLoaded = false;
// setup load amount, load textures
const char *pLoadingMessageAssets = Localize("Initializing assets");
for(int i = 0; i < g_pData->m_NumImages; i++)
{
if(i == IMAGE_GAME)
@ -309,7 +314,7 @@ void CGameClient::OnInit()
g_pData->m_aImages[i].m_Id = IGraphics::CTextureHandle();
else
g_pData->m_aImages[i].m_Id = Graphics()->LoadTexture(g_pData->m_aImages[i].m_pFilename, IStorage::TYPE_ALL);
m_Menus.RenderLoading(pLoadingDDNetCaption, Localize("Initializing assets"), 1);
m_Menus.RenderLoading(pLoadingDDNetCaption, pLoadingMessageAssets, 1);
}
m_GameWorld.m_pCollision = Collision();
@ -341,11 +346,6 @@ void CGameClient::OnInit()
}
}
int64_t End = time_get();
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "initialisation finished after %.2fms", ((End - Start) * 1000) / (float)time_freq());
Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "gameclient", aBuf);
m_MapImages.SetTextureScale(g_Config.m_ClTextEntitiesSize);
// Aggressively try to grab window again since some Windows users report
@ -364,6 +364,8 @@ void CGameClient::OnInit()
int Size = m_vpAll[i]->Sizeof();
pChecksum->m_aComponentsChecksum[i] = Size;
}
log_trace("gameclient", "initialization finished after %.2fms", (time_get() - OnInitStart) * 1000.0f / (float)time_freq());
}
void CGameClient::OnUpdate()

View file

@ -1333,6 +1333,14 @@ bool CUi::DoScrollbarOption(const void *pId, int *pOption, const CUIRect *pRect,
return false;
}
void CUi::RenderProgressBar(CUIRect ProgressBar, float Progress)
{
const float Rounding = minimum(5.0f, ProgressBar.h / 2.0f);
ProgressBar.Draw(ColorRGBA(1.0f, 1.0f, 1.0f, 0.25f), IGraphics::CORNER_ALL, Rounding);
ProgressBar.w = maximum(ProgressBar.w * Progress, 2 * Rounding);
ProgressBar.Draw(ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f), IGraphics::CORNER_ALL, Rounding);
}
void CUi::RenderProgressSpinner(vec2 Center, float OuterRadius, const SProgressSpinnerProperties &Props) const
{
Graphics()->TextureClear();

View file

@ -599,6 +599,9 @@ public:
float DoScrollbarH(const void *pId, const CUIRect *pRect, float Current, const ColorRGBA *pColorInner = nullptr);
bool DoScrollbarOption(const void *pId, int *pOption, const CUIRect *pRect, const char *pStr, int Min, int Max, const IScrollbarScale *pScale = &ms_LinearScrollbarScale, unsigned Flags = 0u, const char *pSuffix = "");
// progress bar
void RenderProgressBar(CUIRect ProgressBar, float Progress);
// progress spinner
void RenderProgressSpinner(vec2 Center, float OuterRadius, const SProgressSpinnerProperties &Props = {}) const;