Achievements: Group leaderboards by subset and tracking state

This commit is contained in:
SternXD
2026-06-13 15:35:03 -04:00
committed by Ty
parent 972fcfa0f0
commit f5310f0ca4
+282 -138
View File
@@ -183,6 +183,8 @@ namespace Achievements
static void DrawLeaderboardEntry(const rc_client_leaderboard_entry_t& entry, bool is_self, float rank_column_width,
float name_column_width, float time_column_width, float column_spacing);
static void OpenSubset(const rc_client_subset_t* subset);
static bool DrawSubsetSidebar(float sidebar_width, bool& sidebar_has_focus, bool leaderboards_only);
static void DrawSubsetSidebarFooter(bool sidebar_has_focus);
static void OpenLeaderboard(const rc_client_leaderboard_t* lboard);
static void LeaderboardFetchNearbyCallback(
int result, const char* error_message, rc_client_leaderboard_entry_list_t* list, rc_client_t* client, void* callback_userdata);
@@ -237,6 +239,9 @@ namespace Achievements
static float s_leaderboard_list_scroll = 0.0f;
static bool s_restore_leaderboard_scroll = false;
static std::map<std::pair<u32, u32>, bool> s_achievement_buckets_collapsed;
static std::map<std::pair<u32, u8>, bool> s_leaderboard_buckets_collapsed;
static std::vector<LeaderboardTrackerIndicator> s_active_leaderboard_trackers;
static std::vector<AchievementChallengeIndicator> s_active_challenge_indicators;
static std::optional<AchievementProgressIndicator> s_active_progress_indicator;
@@ -2025,6 +2030,9 @@ void Achievements::ClearUIState()
rc_client_destroy_achievement_list(s_achievement_list);
s_achievement_list = nullptr;
}
s_achievement_buckets_collapsed.clear();
s_leaderboard_buckets_collapsed.clear();
}
template <typename T>
@@ -2412,6 +2420,9 @@ bool Achievements::PrepareAchievementsWindow()
CloseSubset();
s_subset_list = rc_client_create_subset_list(s_client);
if (!s_subset_list)
Console.Warning("Achievements: rc_client_create_subset_list() returned null");
s_achievement_buckets_collapsed.clear();
if (s_achievement_list)
rc_client_destroy_achievement_list(s_achievement_list);
@@ -2426,6 +2437,131 @@ bool Achievements::PrepareAchievementsWindow()
return true;
}
bool Achievements::DrawSubsetSidebar(float sidebar_width, bool& sidebar_has_focus, bool leaderboards_only)
{
if (!s_subset_list)
return false;
using ImGuiFullscreen::g_medium_font;
using ImGuiFullscreen::LayoutScale;
static constexpr float alpha = 0.8f;
const ImVec4 sidebar_bg(0.10f, 0.10f, 0.10f, alpha);
ImGui::PushStyleColor(ImGuiCol_ChildBg, sidebar_bg);
ImGui::PushStyleColor(ImGuiCol_NavCursor, IM_COL32(0, 0, 0, 0));
bool subset_selected = false;
if (ImGui::BeginChild("subset_sidebar", ImVec2(sidebar_width, 0.0f), 0, 0))
{
sidebar_has_focus = ImGui::IsWindowFocused();
ImGuiFullscreen::BeginMenuButtons();
const float padding = LayoutScale(10.0f);
const float spacing = LayoutScale(8.0f);
const float icon_size = LayoutScale(28.0f);
for (u32 i = 0; i < s_subset_list->num_subsets; i++)
{
const rc_client_subset_t* subset = s_subset_list->subsets[i];
if (leaderboards_only && subset->num_leaderboards == 0)
continue;
TinyString id_str;
id_str.format("sidebar_subset_{}", subset->id);
ImRect bb;
bool visible, hovered;
ImGuiFullscreen::MenuButtonFrame(id_str, true, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY,
&visible, &hovered, &bb.Min, &bb.Max, 0, 1.0f);
if (s_open_subset && s_open_subset->id == subset->id)
{
ImGui::GetWindowDrawList()->AddRectFilled(
ImVec2(bb.Min.x, bb.Min.y), ImVec2(bb.Min.x + LayoutScale(4.0f), bb.Max.y), IM_COL32(52, 152, 219, 255));
}
const ImVec2 icon_min(bb.Min.x + padding, bb.Min.y + (bb.Max.y - bb.Min.y - icon_size) * 0.5f);
const ImVec2 icon_max(icon_min.x + icon_size, icon_min.y + icon_size);
std::string badge_path = GetSubsetBadgePath(subset);
if (!badge_path.empty())
{
GSTexture* badge = ImGuiFullscreen::GetCachedTextureAsync(badge_path);
if (badge)
{
ImGui::GetWindowDrawList()->AddImage(reinterpret_cast<ImTextureID>(badge->GetNativeHandle()),
icon_min, icon_max, ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), IM_COL32(255, 255, 255, 255));
}
}
const ImRect text_bb(ImVec2(icon_max.x + spacing, bb.Min.y), ImVec2(bb.Max.x - padding, bb.Max.y));
ImGui::PushFont(g_medium_font.first, g_medium_font.second);
ImGuiFullscreen::RenderTextClippedWithShadow(
text_bb.Min, text_bb.Max, subset->title, nullptr, nullptr, ImVec2(0.0f, 0.5f), &text_bb);
ImGui::PopFont();
if (ImGui::IsItemClicked() || ImGui::IsItemActivated())
{
OpenSubset(subset);
subset_selected = true;
break;
}
}
ImGuiFullscreen::EndMenuButtons();
}
ImGui::EndChild();
ImGui::PopStyleColor(2);
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
ImGui::SameLine();
ImGui::PopStyleVar();
return subset_selected;
}
void Achievements::DrawSubsetSidebarFooter(bool sidebar_has_focus)
{
if (ImGuiFullscreen::IsGamepadInputSource())
{
const bool circleOK = ImGui::GetIO().ConfigNavSwapGamepadButtons;
const auto glyphs = ImGuiFullscreen::GetGamepadGlyphs();
if (sidebar_has_focus)
{
ImGuiFullscreen::SetFullscreenFooterText(std::array{
std::make_pair(glyphs.dpad_ud, TRANSLATE_SV("Achievements", "Navigate Subsets")),
std::make_pair(glyphs.confirm(circleOK), TRANSLATE_SV("Achievements", "Select")),
std::make_pair(glyphs.cancel(circleOK), TRANSLATE_SV("Achievements", "Back")),
});
}
else
{
ImGuiFullscreen::SetFullscreenFooterText(std::array{
std::make_pair(glyphs.dpad_ud, TRANSLATE_SV("Achievements", "Change Selection")),
std::make_pair(glyphs.cancel(circleOK), TRANSLATE_SV("Achievements", "Subsets")),
});
}
}
else
{
if (sidebar_has_focus)
{
ImGuiFullscreen::SetFullscreenFooterText(std::array{
std::make_pair(ICON_PF_ARROW_UP ICON_PF_ARROW_DOWN, TRANSLATE_SV("Achievements", "Navigate Subsets")),
std::make_pair(ICON_PF_ENTER, TRANSLATE_SV("Achievements", "Select")),
std::make_pair(ICON_PF_ESC, TRANSLATE_SV("Achievements", "Back")),
});
}
else
{
ImGuiFullscreen::SetFullscreenFooterText(std::array{
std::make_pair(ICON_PF_ARROW_UP ICON_PF_ARROW_DOWN, TRANSLATE_SV("Achievements", "Change Selection")),
std::make_pair(ICON_PF_ESC, TRANSLATE_SV("Achievements", "Subsets")),
});
}
}
}
void Achievements::DrawAchievementsWindow()
{
using ImGuiFullscreen::g_large_font;
@@ -2442,7 +2578,10 @@ void Achievements::DrawAchievementsWindow()
Achievements::IdleUpdate();
const bool has_multiple_subsets = (s_subset_list && s_subset_list->num_subsets > 1);
bool s_sidebar_has_focus = false;
static bool sidebar_has_focus = false;
static bool focus_sidebar = false;
if (!has_multiple_subsets)
sidebar_has_focus = false;
static constexpr float alpha = 0.8f;
static constexpr float heading_alpha = 0.95f;
@@ -2486,11 +2625,18 @@ void Achievements::DrawAchievementsWindow()
SmallString text;
ImVec2 text_size;
const bool wants_close = ImGuiFullscreen::WantsToCloseMenu();
if (ImGuiFullscreen::FloatingButton(ICON_FA_SQUARE_XMARK, 10.0f, 10.0f, -1.0f, -1.0f, 1.0f, 0.0f, true, g_large_font) ||
ImGuiFullscreen::WantsToCloseMenu())
(wants_close && (!has_multiple_subsets || sidebar_has_focus)))
{
sidebar_has_focus = false;
FullscreenUI::ReturnToPreviousWindow();
}
else if (has_multiple_subsets && !sidebar_has_focus && wants_close)
{
sidebar_has_focus = true;
focus_sidebar = true;
}
const ImRect title_bb(ImVec2(left, top), ImVec2(right, top + GetLineHeight(g_large_font)));
text.assign(s_open_subset ? s_open_subset->title : s_game_title);
@@ -2582,75 +2728,13 @@ void Achievements::DrawAchievementsWindow()
{
if (has_multiple_subsets)
{
const ImVec4 sidebar_bg(0.10f, 0.10f, 0.10f, alpha);
ImGui::PushStyleColor(ImGuiCol_ChildBg, sidebar_bg);
if (ImGui::BeginChild("subset_sidebar", ImVec2(sidebar_width, 0.0f), ImGuiChildFlags_NavFlattened, 0))
if (focus_sidebar)
{
ImGuiFullscreen::BeginMenuButtons();
for (u32 i = 0; i < s_subset_list->num_subsets; i++)
{
const rc_client_subset_t* subset = s_subset_list->subsets[i];
TinyString id_str;
id_str.format("sidebar_subset_{}", subset->id);
ImRect bb;
bool visible, hovered;
ImGuiFullscreen::MenuButtonFrame(id_str, true, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY,
&visible, &hovered, &bb.Min, &bb.Max, 0, 1.0f);
if (ImGui::IsItemHovered() || ImGui::IsItemFocused())
s_sidebar_has_focus = true;
const float padding = LayoutScale(10.0f);
const float spacing = LayoutScale(8.0f);
const float icon_size = LayoutScale(28.0f);
if (s_open_subset && s_open_subset->id == subset->id)
{
const float line_width = LayoutScale(4.0f);
const ImVec2 line_min(bb.Min.x, bb.Min.y);
const ImVec2 line_max(bb.Min.x + line_width, bb.Max.y);
ImGui::GetWindowDrawList()->AddRectFilled(line_min, line_max, IM_COL32(52, 152, 219, 255));
}
const ImVec2 icon_min(bb.Min.x + padding, bb.Min.y + (bb.Max.y - bb.Min.y - icon_size) * 0.5f);
const ImVec2 icon_max(icon_min.x + icon_size, icon_min.y + icon_size);
std::string badge_path = GetSubsetBadgePath(subset);
if (!badge_path.empty())
{
GSTexture* badge = ImGuiFullscreen::GetCachedTextureAsync(badge_path);
if (badge)
{
ImGui::GetWindowDrawList()->AddImage(reinterpret_cast<ImTextureID>(badge->GetNativeHandle()),
icon_min, icon_max, ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), IM_COL32(255, 255, 255, 255));
}
}
const float text_x = icon_max.x + spacing;
const ImRect text_bb(ImVec2(text_x, bb.Min.y), ImVec2(bb.Max.x - padding, bb.Max.y));
ImGui::PushFont(g_medium_font.first, g_medium_font.second);
ImGuiFullscreen::RenderTextClippedWithShadow(
text_bb.Min, text_bb.Max, subset->title, nullptr, nullptr, ImVec2(0.0f, 0.5f), &text_bb);
ImGui::PopFont();
if (ImGui::IsItemClicked() || ImGui::IsItemActivated())
OpenSubset(subset);
}
ImGuiFullscreen::EndMenuButtons();
ImGui::SetNextWindowFocus();
focus_sidebar = false;
}
ImGui::EndChild();
if (ImGui::IsItemHovered() || ImGui::IsItemFocused())
s_sidebar_has_focus = true;
ImGui::PopStyleColor();
ImGui::SameLine();
if (DrawSubsetSidebar(sidebar_width, sidebar_has_focus, false))
ImGui::SetNextWindowFocus();
}
const float content_width = has_multiple_subsets ? (display_size.x - sidebar_width) : display_size.x;
@@ -2660,12 +2744,9 @@ void Achievements::DrawAchievementsWindow()
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImGui::GetColorU32(ImGuiFullscreen::UIPrimaryColor));
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImGui::GetColorU32(ImGuiFullscreen::UISecondaryColor));
if (ImGui::BeginChild("achievements_content", ImVec2(content_width, 0.0f), ImGuiChildFlags_NavFlattened, 0))
if (ImGui::BeginChild("achievements_content", ImVec2(content_width, 0.0f), 0, 0))
{
if (ImGui::IsWindowHovered() || ImGui::IsWindowFocused())
s_sidebar_has_focus = false;
static std::map<std::pair<u32, u32>, bool> buckets_collapsed;
static const char* bucket_names[NUM_RC_CLIENT_ACHIEVEMENT_BUCKETS] = {
TRANSLATE_NOOP("Achievements", "Unknown"),
TRANSLATE_NOOP("Achievements", "Locked"),
@@ -2694,7 +2775,7 @@ void Achievements::DrawAchievementsWindow()
pxAssert(bucket.bucket_type < NUM_RC_CLIENT_ACHIEVEMENT_BUCKETS);
bool& bucket_collapsed = buckets_collapsed[std::make_pair(bucket.subset_id, bucket.bucket_type)];
bool& bucket_collapsed = s_achievement_buckets_collapsed[std::make_pair(bucket.subset_id, bucket.bucket_type)];
const char* translated_bucket_name = Host::TranslateToCString("Achievements", bucket_names[bucket.bucket_type]);
bucket_collapsed ^=
@@ -2719,54 +2800,9 @@ void Achievements::DrawAchievementsWindow()
ImGuiFullscreen::EndFullscreenWindow();
if (has_multiple_subsets)
{
if (ImGuiFullscreen::IsGamepadInputSource())
{
const bool circleOK = ImGui::GetIO().ConfigNavSwapGamepadButtons;
const auto glyphs = ImGuiFullscreen::GetGamepadGlyphs();
if (s_sidebar_has_focus)
{
ImGuiFullscreen::SetFullscreenFooterText(std::array{
std::make_pair(glyphs.dpad_ud, TRANSLATE_SV("Achievements", "Navigate Subsets")),
std::make_pair(glyphs.dpad_lr, TRANSLATE_SV("Achievements", "Back to List")),
std::make_pair(glyphs.confirm(circleOK), TRANSLATE_SV("Achievements", "Select")),
std::make_pair(glyphs.cancel(circleOK), TRANSLATE_SV("Achievements", "Back")),
});
}
else
{
ImGuiFullscreen::SetFullscreenFooterText(std::array{
std::make_pair(glyphs.dpad_lr, TRANSLATE_SV("Achievements", "Navigate Subsets")),
std::make_pair(glyphs.dpad_ud, TRANSLATE_SV("Achievements", "Change Selection")),
std::make_pair(glyphs.cancel(circleOK), TRANSLATE_SV("Achievements", "Back")),
});
}
}
else
{
if (s_sidebar_has_focus)
{
ImGuiFullscreen::SetFullscreenFooterText(std::array{
std::make_pair(ICON_PF_ARROW_UP ICON_PF_ARROW_DOWN, TRANSLATE_SV("Achievements", "Navigate Subsets")),
std::make_pair(ICON_PF_ARROW_LEFT ICON_PF_ARROW_RIGHT, TRANSLATE_SV("Achievements", "Back to List")),
std::make_pair(ICON_PF_ENTER, TRANSLATE_SV("Achievements", "Select")),
std::make_pair(ICON_PF_ESC, TRANSLATE_SV("Achievements", "Back")),
});
}
else
{
ImGuiFullscreen::SetFullscreenFooterText(std::array{
std::make_pair(ICON_PF_ARROW_LEFT ICON_PF_ARROW_RIGHT, TRANSLATE_SV("Achievements", "Navigate Subsets")),
std::make_pair(ICON_PF_ARROW_UP ICON_PF_ARROW_DOWN, TRANSLATE_SV("Achievements", "Change Selection")),
std::make_pair(ICON_PF_ESC, TRANSLATE_SV("Achievements", "Back")),
});
}
}
}
DrawSubsetSidebarFooter(sidebar_has_focus);
else
{
FullscreenUI::SetStandardSelectionFooterText(true);
}
}
void Achievements::DrawAchievement(const rc_client_achievement_t* cheevo)
@@ -2982,9 +3018,21 @@ bool Achievements::PrepareLeaderboardsWindow()
s_achievement_badge_paths = {};
CloseLeaderboard();
if (s_subset_list)
{
rc_client_destroy_subset_list(s_subset_list);
s_subset_list = nullptr;
}
CloseSubset();
s_subset_list = rc_client_create_subset_list(client);
if (!s_subset_list)
Console.Warning("Achievements: rc_client_create_subset_list() returned null");
s_leaderboard_buckets_collapsed.clear();
if (s_leaderboard_list)
rc_client_destroy_leaderboard_list(s_leaderboard_list);
s_leaderboard_list = rc_client_create_leaderboard_list(client, RC_CLIENT_LEADERBOARD_LIST_GROUPING_NONE);
s_leaderboard_list = rc_client_create_leaderboard_list(client, RC_CLIENT_LEADERBOARD_LIST_GROUPING_TRACKING);
if (!s_leaderboard_list)
{
Console.Error("Achievements: rc_client_create_leaderboard_list() returned null");
@@ -2997,6 +3045,18 @@ bool Achievements::PrepareLeaderboardsWindow()
s_restore_leaderboard_scroll = false;
s_leaderboard_list_scroll = 0.0f;
if (s_subset_list)
{
for (u32 i = 0; i < s_subset_list->num_subsets; i++)
{
if (s_subset_list->subsets[i]->num_leaderboards > 0)
{
OpenSubset(s_subset_list->subsets[i]);
break;
}
}
}
return true;
}
@@ -3020,6 +3080,14 @@ void Achievements::DrawLeaderboardsWindow()
const bool is_leaderboard_open = (s_open_leaderboard != nullptr);
bool close_leaderboard_on_exit = false;
const bool has_multiple_subsets = (s_subset_list && std::count_if(s_subset_list->subsets,
s_subset_list->subsets + s_subset_list->num_subsets,
[](const rc_client_subset_t* subset) { return subset->num_leaderboards > 0; }) > 1);
static bool sidebar_has_focus = false;
static bool focus_sidebar = false;
if (!has_multiple_subsets || is_leaderboard_open)
sidebar_has_focus = false;
ImRect bb;
const ImVec4 background(0.13f, 0.13f, 0.13f, alpha);
@@ -3082,11 +3150,18 @@ void Achievements::DrawLeaderboardsWindow()
if (!is_leaderboard_open)
{
const bool wants_close = ImGuiFullscreen::WantsToCloseMenu();
if (ImGuiFullscreen::FloatingButton(ICON_FA_SQUARE_XMARK, 10.0f, 10.0f, -1.0f, -1.0f, 1.0f, 0.0f, true, g_large_font) ||
ImGuiFullscreen::WantsToCloseMenu())
(wants_close && (!has_multiple_subsets || sidebar_has_focus)))
{
sidebar_has_focus = false;
FullscreenUI::ReturnToPreviousWindow();
}
else if (has_multiple_subsets && !sidebar_has_focus && wants_close)
{
sidebar_has_focus = true;
focus_sidebar = true;
}
}
else
{
@@ -3243,36 +3318,105 @@ void Achievements::DrawLeaderboardsWindow()
if (!is_leaderboard_open)
{
const float sidebar_width = has_multiple_subsets ? LayoutScale(200.0f) : 0.0f;
if (ImGuiFullscreen::BeginFullscreenWindow(
ImVec2(0.0f, heading_height),
ImVec2(display_size.x, display_size.y - heading_height - LayoutScale(ImGuiFullscreen::LAYOUT_FOOTER_HEIGHT)),
"leaderboards", background, 0.0f, ImVec2(ImGuiFullscreen::LAYOUT_MENU_WINDOW_X_PADDING, 0.0f), 0))
"leaderboards", background, 0.0f, ImVec2(0.0f, 0.0f), 0))
{
if (s_restore_leaderboard_scroll)
if (has_multiple_subsets)
{
ImGui::SetScrollY(s_leaderboard_list_scroll);
s_restore_leaderboard_scroll = false;
if (focus_sidebar)
{
ImGui::SetNextWindowFocus();
focus_sidebar = false;
}
if (DrawSubsetSidebar(sidebar_width, sidebar_has_focus, true))
ImGui::SetNextWindowFocus();
}
const bool had_pending_focus_request = s_restore_leaderboard_focus;
const float content_width = has_multiple_subsets ? (display_size.x - sidebar_width) : display_size.x;
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(ImGuiFullscreen::LAYOUT_MENU_WINDOW_X_PADDING, 0.0f));
ImGui::PushStyleColor(ImGuiCol_ChildBg, background);
ImGui::PushStyleColor(ImGuiCol_Header, ImGui::GetColorU32(ImGuiFullscreen::UIPrimaryDarkColor));
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImGui::GetColorU32(ImGuiFullscreen::UIPrimaryColor));
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImGui::GetColorU32(ImGuiFullscreen::UISecondaryColor));
ImGuiFullscreen::BeginMenuButtons();
for (u32 bucket_index = 0; bucket_index < s_leaderboard_list->num_buckets; bucket_index++)
if (ImGui::BeginChild("leaderboards_content", ImVec2(content_width, 0.0f), 0, 0))
{
const rc_client_leaderboard_bucket_t& bucket = s_leaderboard_list->buckets[bucket_index];
for (u32 i = 0; i < bucket.num_leaderboards; i++)
DrawLeaderboardListEntry(bucket.leaderboards[i]);
if (s_restore_leaderboard_scroll)
{
ImGui::SetScrollY(s_leaderboard_list_scroll);
s_restore_leaderboard_scroll = false;
}
const bool had_pending_focus_request = s_restore_leaderboard_focus;
ImGuiFullscreen::BeginMenuButtons();
static const char* lboard_bucket_names[NUM_RC_CLIENT_LEADERBOARD_BUCKETS] = {
TRANSLATE_NOOP("Achievements", "Unknown"),
TRANSLATE_NOOP("Achievements", "Inactive"),
TRANSLATE_NOOP("Achievements", "Active"),
TRANSLATE_NOOP("Achievements", "Unsupported"),
TRANSLATE_NOOP("Achievements", "All"),
};
const bool show_bucket_headers = (s_leaderboard_list->num_buckets > 1);
for (u32 bucket_index = 0; bucket_index < s_leaderboard_list->num_buckets; bucket_index++)
{
const rc_client_leaderboard_bucket_t& bucket = s_leaderboard_list->buckets[bucket_index];
if (s_open_subset && bucket.subset_id != 0 && bucket.subset_id != s_open_subset->id)
continue;
if (show_bucket_headers)
{
pxAssert(bucket.bucket_type < NUM_RC_CLIENT_LEADERBOARD_BUCKETS);
const char* type_name = Host::TranslateToCString("Achievements", lboard_bucket_names[bucket.bucket_type]);
TinyString bucket_label;
if (bucket.subset_id != 0 && !s_open_subset && s_subset_list)
{
auto subset_iter = std::find_if(s_subset_list->subsets, s_subset_list->subsets + s_subset_list->num_subsets,
[&](const rc_client_subset_t* s) { return s->id == bucket.subset_id; });
if (subset_iter != s_subset_list->subsets + s_subset_list->num_subsets)
bucket_label.format("{} - {}", (*subset_iter)->title, type_name);
else
bucket_label.assign(type_name);
}
else
{
bucket_label.assign(type_name);
}
bool& bucket_collapsed = s_leaderboard_buckets_collapsed[std::make_pair(bucket.subset_id, bucket.bucket_type)];
if (ImGuiFullscreen::MenuHeadingButton(
bucket_label, bucket_collapsed ? ICON_FA_CHEVRON_DOWN : ICON_FA_CHEVRON_UP))
bucket_collapsed = !bucket_collapsed;
if (bucket_collapsed)
continue;
}
for (u32 i = 0; i < bucket.num_leaderboards; i++)
DrawLeaderboardListEntry(bucket.leaderboards[i]);
}
ImGuiFullscreen::EndMenuButtons();
if (had_pending_focus_request && s_restore_leaderboard_focus)
s_restore_leaderboard_focus = false;
}
ImGui::EndChild();
ImGuiFullscreen::EndMenuButtons();
if (had_pending_focus_request && s_restore_leaderboard_focus)
s_restore_leaderboard_focus = false;
ImGui::PopStyleColor(4);
ImGui::PopStyleVar();
}
ImGuiFullscreen::EndFullscreenWindow();
FullscreenUI::SetStandardSelectionFooterText(true);
if (has_multiple_subsets)
DrawSubsetSidebarFooter(sidebar_has_focus);
else
FullscreenUI::SetStandardSelectionFooterText(true);
}
else
{