diff --git a/source/main/gui/GUIUtils.cpp b/source/main/gui/GUIUtils.cpp index e4814b38be..cf66f271c0 100644 --- a/source/main/gui/GUIUtils.cpp +++ b/source/main/gui/GUIUtils.cpp @@ -125,54 +125,47 @@ void RoR::ImTextFeeder::NextLine() // Internal helper inline void ColorToInts(ImVec4 v, int&r, int&g, int&b) { r=(int)(v.x*255); g=(int)(v.y*255); b=(int)(v.z*255); } -void RoR::DrawImGuiSpinner(float& counter, const ImVec2 size, const float spacing, const float step_sec) +// A nice spinner https://github.com/ocornut/imgui/issues/1901#issuecomment-444929973 +void RoR::LoadingIndicatorCircle(const char* label, const float indicator_radius, const ImVec4& main_color, const ImVec4& backdrop_color, const int circle_count, const float speed) { - // Hardcoded to 4 segments, counter is reset after full round (4 steps) - // -------------------------------------------------------------------- - - const ImU32 COLORS[] = { ImColor(255,255,255,255), ImColor(210,210,210,255), ImColor(120,120,120,255), ImColor(60,60,60,255) }; - - // Update counter, determine coloring - counter += ImGui::GetIO().DeltaTime; - int color_start = 0; // Index to GUI_SPINNER_COLORS array for the top middle segment (segment 0) - while (counter > (step_sec*4.f)) + ImGuiWindow* window = ImGui::GetCurrentWindow(); + if (window->SkipItems) { - counter -= (step_sec*4.f); + return; } - if (counter > (step_sec*3.f)) - { - color_start = 3; - } - else if (counter > (step_sec*2.f)) + ImGuiContext& g = *GImGui; + const ImGuiID id = window->GetID(label); + + const ImVec2 pos = window->DC.CursorPos; + const float circle_radius = indicator_radius / 10.0f; + const ImRect bb(pos, ImVec2(pos.x + indicator_radius * 2.0f, pos.y + indicator_radius * 2.0f)); + ImGui::ItemSize(bb, ImGui::GetStyle().FramePadding.y); + if (!ImGui::ItemAdd(bb, id)) { - color_start = 2; + return; } - else if (counter > (step_sec)) + + const float t = g.Time; + const auto degree_offset = 2.0f * IM_PI / circle_count; + + for (int i = 0; i < circle_count; ++i) { - color_start = 1; - } + const auto x = indicator_radius * std::sin(degree_offset * i); + const auto y = indicator_radius * std::cos(degree_offset * i); + const auto growth = std::max(0.0f, std::sin(t * speed - i * degree_offset)); + ImVec4 color; + color.x = main_color.x * growth + backdrop_color.x * (1.0f - growth); + color.y = main_color.y * growth + backdrop_color.y * (1.0f - growth); + color.z = main_color.z * growth + backdrop_color.z * (1.0f - growth); + color.w = 1.0f; - // Draw segments - ImDrawList* draw_list = ImGui::GetWindowDrawList(); - const ImVec2 pos = ImGui::GetCursorScreenPos(); - const float left = pos.x; - const float top = pos.y; - const float right = pos.x + size.x; - const float bottom = pos.y + size.y; - const float mid_x = pos.x + (size.x / 2.f); - const float mid_y = pos.y + (size.y / 2.f); - - // NOTE: Enter vertices in clockwise order, otherwise anti-aliasing doesn't work and polygon is rasterized larger! -- Observed under OpenGL2 / OGRE 1.9 - - // Top triangle, vertices: mid, left, right - draw_list->AddTriangleFilled(ImVec2(mid_x, mid_y-spacing), ImVec2(left + spacing, top), ImVec2(right - spacing, top), COLORS[color_start]); - // Right triangle, vertices: mid, top, bottom - draw_list->AddTriangleFilled(ImVec2(mid_x+spacing, mid_y), ImVec2(right, top + spacing), ImVec2(right, bottom - spacing), COLORS[(color_start+3)%4]); - // Bottom triangle, vertices: mid, right, left - draw_list->AddTriangleFilled(ImVec2(mid_x, mid_y+spacing), ImVec2(right - spacing, bottom), ImVec2(left + spacing, bottom), COLORS[(color_start+2)%4]); - // Left triangle, vertices: mid, bottom, top - draw_list->AddTriangleFilled(ImVec2(mid_x-spacing, mid_y), ImVec2(left, bottom - spacing), ImVec2(left, top + spacing), COLORS[(color_start+1)%4]); + window->DrawList->AddCircleFilled(ImVec2(pos.x + indicator_radius + x, + pos.y + indicator_radius - y), + circle_radius + growth * circle_radius, + ImGui::GetColorU32(color)); + + } } //source: https://github.com/ocornut/imgui/issues/1982#issuecomment-408834301 @@ -367,46 +360,3 @@ ImDrawList* RoR::GetImDummyFullscreenWindow() return drawlist; } - -// A nice spinner https://github.com/ocornut/imgui/issues/1901#issuecomment-444929973 -void RoR::LoadingIndicatorCircle(const char* label, const float indicator_radius, const ImVec4& main_color, const ImVec4& backdrop_color, const int circle_count, const float speed) -{ - ImGuiWindow* window = ImGui::GetCurrentWindow(); - if (window->SkipItems) - { - return; - } - - ImGuiContext& g = *GImGui; - const ImGuiID id = window->GetID(label); - - const ImVec2 pos = window->DC.CursorPos; - const float circle_radius = indicator_radius / 10.0f; - const ImRect bb(pos, ImVec2(pos.x + indicator_radius * 2.0f, pos.y + indicator_radius * 2.0f)); - ImGui::ItemSize(bb, ImGui::GetStyle().FramePadding.y); - if (!ImGui::ItemAdd(bb, id)) - { - return; - } - - const float t = g.Time; - const auto degree_offset = 2.0f * IM_PI / circle_count; - - for (int i = 0; i < circle_count; ++i) - { - const auto x = indicator_radius * std::sin(degree_offset * i); - const auto y = indicator_radius * std::cos(degree_offset * i); - const auto growth = std::max(0.0f, std::sin(t * speed - i * degree_offset)); - ImVec4 color; - color.x = main_color.x * growth + backdrop_color.x * (1.0f - growth); - color.y = main_color.y * growth + backdrop_color.y * (1.0f - growth); - color.z = main_color.z * growth + backdrop_color.z * (1.0f - growth); - color.w = 1.0f; - - window->DrawList->AddCircleFilled(ImVec2(pos.x + indicator_radius + x, - pos.y + indicator_radius - y), - circle_radius + growth * circle_radius, - ImGui::GetColorU32(color)); - - } -} diff --git a/source/main/gui/GUIUtils.h b/source/main/gui/GUIUtils.h index f86bcbc7aa..e95e858e16 100644 --- a/source/main/gui/GUIUtils.h +++ b/source/main/gui/GUIUtils.h @@ -43,9 +43,7 @@ struct ImTextFeeder /// Helper for drawing multiline wrapped & colored text. }; /// Draws animated loading spinner -void DrawImGuiSpinner( - float& counter, const ImVec2 size = ImVec2(16.f, 16.f), - const float spacing = 2.f, const float step_sec = 0.15f); +void LoadingIndicatorCircle(const char* label, const float indicator_radius, const ImVec4& main_color, const ImVec4& backdrop_color, const int circle_count, const float speed); /// Add rotated textured quad to ImDrawList, source: https://github.com/ocornut/imgui/issues/1982#issuecomment-408834301 void DrawImageRotated(ImTextureID tex_id, ImVec2 center, ImVec2 size, float angle); @@ -76,6 +74,4 @@ Ogre::TexturePtr FetchIcon(const char* name); ImDrawList* GetImDummyFullscreenWindow(); -void LoadingIndicatorCircle(const char* label, const float indicator_radius, const ImVec4& main_color, const ImVec4& backdrop_color, const int circle_count, const float speed); - } // namespace RoR diff --git a/source/main/gui/panels/GUI_LoadingWindow.cpp b/source/main/gui/panels/GUI_LoadingWindow.cpp index 8b7ce92019..45827d7380 100644 --- a/source/main/gui/panels/GUI_LoadingWindow.cpp +++ b/source/main/gui/panels/GUI_LoadingWindow.cpp @@ -78,6 +78,8 @@ void LoadingWindow::SetProgressNetConnect(const std::string& net_status) void LoadingWindow::Draw() { + GUIManager::GuiTheme const& theme = App::GetGuiManager()->GetTheme(); + // Height calc float text_h = ImGui::CalcTextSize("A").y; float statusbar_h = text_h + (ImGui::GetStyle().FramePadding.y * 2); @@ -98,7 +100,8 @@ void LoadingWindow::Draw() if (m_percent == PERC_SHOW_SPINNER) { - DrawImGuiSpinner(m_spinner_counter, ImVec2(ImGui::GetTextLineHeight(), ImGui::GetTextLineHeight())); + float spinner_size = 8.f; + LoadingIndicatorCircle("spinner", spinner_size, theme.value_blue_text_color, theme.value_blue_text_color, 10, 10); } else if (m_percent == PERC_HIDE_PROGRESSBAR) { diff --git a/source/main/gui/panels/GUI_MultiplayerSelector.cpp b/source/main/gui/panels/GUI_MultiplayerSelector.cpp index 88d03c82f4..b37c57ac92 100644 --- a/source/main/gui/panels/GUI_MultiplayerSelector.cpp +++ b/source/main/gui/panels/GUI_MultiplayerSelector.cpp @@ -230,6 +230,8 @@ void MultiplayerSelector::DrawDirectTab() void MultiplayerSelector::DrawServerlistTab() { + GUIManager::GuiTheme const& theme = App::GetGuiManager()->GetTheme(); + const char* draw_label_text = nullptr; ImVec4 draw_label_color; @@ -252,6 +254,14 @@ void MultiplayerSelector::DrawServerlistTab() draw_label_color = m_serverlist_msg_color; } + if (m_show_spinner) + { + float spinner_size = 25.f; + ImGui::SetCursorPosX((ImGui::GetWindowSize().x / 2.f) - spinner_size); + ImGui::SetCursorPosY((ImGui::GetWindowSize().y / 2.f) - spinner_size); + LoadingIndicatorCircle("spinner", spinner_size, theme.value_blue_text_color, theme.value_blue_text_color, 10, 10); + } + // DRAW SERVERLIST TABLE if (m_draw_table) { @@ -355,11 +365,11 @@ void MultiplayerSelector::DrawServerlistTab() void MultiplayerSelector::StartAsyncRefresh() { #if defined(USE_CURL) + m_show_spinner = true; m_draw_table = false; m_serverlist_data.clear(); m_selected_item = -1; - m_serverlist_msg = _LC("MultiplayerSelector", "... refreshing ..."); - m_serverlist_msg_color = App::GetGuiManager()->GetTheme().in_progress_text_color; + m_serverlist_msg = ""; std::packaged_task task(FetchServerlist); std::thread(std::move(task), App::mp_api_url->getStr()).detach(); // launch on a thread #endif // defined(USE_CURL) @@ -381,6 +391,7 @@ void MultiplayerSelector::SetVisible(bool visible) void MultiplayerSelector::DisplayRefreshFailed(std::string const& msg) { + m_show_spinner = false; m_serverlist_msg = msg; m_serverlist_msg_color = App::GetGuiManager()->GetTheme().error_text_color; m_draw_table = false; @@ -388,6 +399,7 @@ void MultiplayerSelector::DisplayRefreshFailed(std::string const& msg) void MultiplayerSelector::UpdateServerlist(MpServerInfoVec* data) { + m_show_spinner = false; m_serverlist_data = *data; m_draw_table = true; if (m_serverlist_data.empty()) diff --git a/source/main/gui/panels/GUI_MultiplayerSelector.h b/source/main/gui/panels/GUI_MultiplayerSelector.h index 53cb371d25..03a0c983e7 100644 --- a/source/main/gui/panels/GUI_MultiplayerSelector.h +++ b/source/main/gui/panels/GUI_MultiplayerSelector.h @@ -84,6 +84,7 @@ class MultiplayerSelector Str<1000> m_password_buf; Str<1000> m_server_host_buf; Ogre::TexturePtr m_lock_icon; + bool m_show_spinner = false; }; } // namespace GUI