diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index 0eb85a905..9fe01f0b0 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -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(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; diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 67cf1a408..7bd0e7303 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -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]; diff --git a/src/game/client/components/menus_start.cpp b/src/game/client/components/menus_start.cpp index 46875a33d..ec505159b 100644 --- a/src/game/client/components/menus_start.cpp +++ b/src/game/client/components/menus_start.cpp @@ -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; diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index ee21b1e2a..6e6f2aab8 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -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() diff --git a/src/game/client/ui.cpp b/src/game/client/ui.cpp index a08545c43..e29646fa3 100644 --- a/src/game/client/ui.cpp +++ b/src/game/client/ui.cpp @@ -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(); diff --git a/src/game/client/ui.h b/src/game/client/ui.h index f9a802e83..7ee062aea 100644 --- a/src/game/client/ui.h +++ b/src/game/client/ui.h @@ -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;