mirror of
https://github.com/stenzek/duckstation.git
synced 2025-07-08 11:10:09 +00:00
FullscreenUI: Add 'Compact Mode' for game list
This commit is contained in:
parent
0098c60ee8
commit
ca322449da
@ -8017,8 +8017,10 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
|
|||||||
if (BeginFullscreenColumnWindow(0.0f, -530.0f, "game_list_entries", GetTransparentBackgroundColor(),
|
if (BeginFullscreenColumnWindow(0.0f, -530.0f, "game_list_entries", GetTransparentBackgroundColor(),
|
||||||
ImVec2(LAYOUT_MENU_WINDOW_X_PADDING, LAYOUT_MENU_WINDOW_Y_PADDING)))
|
ImVec2(LAYOUT_MENU_WINDOW_X_PADDING, LAYOUT_MENU_WINDOW_Y_PADDING)))
|
||||||
{
|
{
|
||||||
const float row_height = 50.0f;
|
const bool compact_mode = Host::GetBaseBoolSettingValue("Main", "FullscreenUIGameListCompactMode", true);
|
||||||
const ImVec2 image_size(LayoutScale(row_height, row_height));
|
const float image_size = compact_mode ? UIStyle.LargeFontSize : LayoutScale(50.0f);
|
||||||
|
const float row_image_padding = LayoutScale(compact_mode ? 15.0f : 15.0f);
|
||||||
|
const float row_left_margin = image_size + row_image_padding;
|
||||||
|
|
||||||
ResetFocusHere();
|
ResetFocusHere();
|
||||||
|
|
||||||
@ -8030,43 +8032,38 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
|
|||||||
|
|
||||||
for (const GameList::Entry* entry : s_state.game_list_sorted_entries)
|
for (const GameList::Entry* entry : s_state.game_list_sorted_entries)
|
||||||
{
|
{
|
||||||
ImRect bb;
|
if (!compact_mode)
|
||||||
|
{
|
||||||
|
if (entry->serial.empty())
|
||||||
|
summary.format("{} | {} MB", Path::GetFileName(entry->path), to_mb(entry->file_size));
|
||||||
|
else
|
||||||
|
summary.format("{} | {} | {} MB", entry->serial, Path::GetFileName(entry->path), to_mb(entry->file_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
const ImGuiFullscreen::MenuButtonBounds mbb(entry->title, {}, summary, row_left_margin);
|
||||||
|
|
||||||
bool visible, hovered;
|
bool visible, hovered;
|
||||||
bool pressed = MenuButtonFrame(entry->path.c_str(), LayoutScale(row_height), true, &bb, &visible, &hovered);
|
bool pressed = MenuButtonFrame(entry->path, true, mbb.frame_bb, &visible, &hovered);
|
||||||
if (!visible)
|
if (!visible)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
GPUTexture* cover_texture = GetGameListCover(entry, false, true);
|
GPUTexture* cover_texture = GetGameListCover(entry, false, true);
|
||||||
|
const ImRect image_rect(CenterImage(
|
||||||
if (entry->serial.empty())
|
ImRect(ImVec2(mbb.title_bb.Min.x - row_left_margin, mbb.title_bb.Min.y),
|
||||||
{
|
ImVec2(mbb.title_bb.Min.x - row_image_padding, mbb.title_bb.Min.y + image_size)),
|
||||||
summary.format("{} | {} MB", Path::GetFileName(entry->path), to_mb(entry->file_size));
|
ImVec2(static_cast<float>(cover_texture->GetWidth()), static_cast<float>(cover_texture->GetHeight()))));
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
summary.format("{} | {} | {} MB", entry->serial, Path::GetFileName(entry->path), to_mb(entry->file_size));
|
|
||||||
}
|
|
||||||
|
|
||||||
const ImRect image_rect(
|
|
||||||
CenterImage(ImRect(bb.Min, bb.Min + image_size), ImVec2(static_cast<float>(cover_texture->GetWidth()),
|
|
||||||
static_cast<float>(cover_texture->GetHeight()))));
|
|
||||||
|
|
||||||
ImGui::GetWindowDrawList()->AddImage(cover_texture, image_rect.Min, image_rect.Max, ImVec2(0.0f, 0.0f),
|
ImGui::GetWindowDrawList()->AddImage(cover_texture, image_rect.Min, image_rect.Max, ImVec2(0.0f, 0.0f),
|
||||||
ImVec2(1.0f, 1.0f), IM_COL32(255, 255, 255, 255));
|
ImVec2(1.0f, 1.0f), IM_COL32(255, 255, 255, 255));
|
||||||
|
RenderShadowedTextClipped(UIStyle.Font, UIStyle.LargeFontSize, UIStyle.BoldFontWeight, mbb.title_bb.Min,
|
||||||
const float midpoint = bb.Min.y + UIStyle.LargeFontSize + LayoutScale(4.0f);
|
mbb.title_bb.Max, text_color, entry->title, &mbb.title_size, ImVec2(0.0f, 0.0f),
|
||||||
const float text_start_x = bb.Min.x + image_size.x + LayoutScale(15.0f);
|
mbb.title_size.x, &mbb.title_bb);
|
||||||
const ImRect title_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(bb.Max.x, midpoint));
|
|
||||||
const ImRect summary_bb(ImVec2(text_start_x, midpoint), bb.Max);
|
|
||||||
|
|
||||||
RenderShadowedTextClipped(UIStyle.Font, UIStyle.LargeFontSize, UIStyle.BoldFontWeight, title_bb.Min, title_bb.Max,
|
|
||||||
text_color, entry->title, nullptr, ImVec2(0.0f, 0.0f), 0.0f, &title_bb);
|
|
||||||
|
|
||||||
if (!summary.empty())
|
if (!summary.empty())
|
||||||
{
|
{
|
||||||
RenderShadowedTextClipped(UIStyle.Font, UIStyle.MediumFontSize, UIStyle.NormalFontWeight, summary_bb.Min,
|
RenderShadowedTextClipped(UIStyle.Font, UIStyle.MediumFontSize, UIStyle.NormalFontWeight, mbb.summary_bb.Min,
|
||||||
summary_bb.Max, subtitle_text_color, summary, nullptr, ImVec2(0.0f, 0.0f), 0.0f,
|
mbb.summary_bb.Max, subtitle_text_color, summary, &mbb.summary_size,
|
||||||
&summary_bb);
|
ImVec2(0.0f, 0.0f), mbb.summary_size.x, &mbb.summary_bb);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pressed)
|
if (pressed)
|
||||||
@ -8663,6 +8660,10 @@ void FullscreenUI::DrawGameListSettingsPage()
|
|||||||
{
|
{
|
||||||
s_state.game_list_show_trophy_icons = bsi->GetBoolValue("Main", "FullscreenUIShowTrophyIcons", true);
|
s_state.game_list_show_trophy_icons = bsi->GetBoolValue("Main", "FullscreenUIShowTrophyIcons", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DrawToggleSetting(bsi, FSUI_ICONVSTR(ICON_FA_TEXT_SLASH, "List Compact Mode"),
|
||||||
|
FSUI_VSTR("Displays only the game title in the list, instead of the title and serial/file name."),
|
||||||
|
"Main", "FullscreenUIGameListCompactMode", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuHeading(FSUI_VSTR("Search Directories"));
|
MenuHeading(FSUI_VSTR("Search Directories"));
|
||||||
@ -9495,6 +9496,7 @@ TRANSLATE_NOOP("FullscreenUI", "Disc");
|
|||||||
TRANSLATE_NOOP("FullscreenUI", "Discord Server");
|
TRANSLATE_NOOP("FullscreenUI", "Discord Server");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Display Area");
|
TRANSLATE_NOOP("FullscreenUI", "Display Area");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Displays DualShock/DualSense button icons in the footer and input binding, instead of Xbox buttons.");
|
TRANSLATE_NOOP("FullscreenUI", "Displays DualShock/DualSense button icons in the footer and input binding, instead of Xbox buttons.");
|
||||||
|
TRANSLATE_NOOP("FullscreenUI", "Displays only the game title in the list, instead of the title and serial/file name.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Displays popup messages on events such as achievement unlocks and leaderboard submissions.");
|
TRANSLATE_NOOP("FullscreenUI", "Displays popup messages on events such as achievement unlocks and leaderboard submissions.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Displays popup messages when starting, submitting, or failing a leaderboard challenge.");
|
TRANSLATE_NOOP("FullscreenUI", "Displays popup messages when starting, submitting, or failing a leaderboard challenge.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Dithering");
|
TRANSLATE_NOOP("FullscreenUI", "Dithering");
|
||||||
@ -9651,6 +9653,7 @@ TRANSLATE_NOOP("FullscreenUI", "Leaderboard Notifications");
|
|||||||
TRANSLATE_NOOP("FullscreenUI", "Leaderboards");
|
TRANSLATE_NOOP("FullscreenUI", "Leaderboards");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Light");
|
TRANSLATE_NOOP("FullscreenUI", "Light");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Line Detection");
|
TRANSLATE_NOOP("FullscreenUI", "Line Detection");
|
||||||
|
TRANSLATE_NOOP("FullscreenUI", "List Compact Mode");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "List Settings");
|
TRANSLATE_NOOP("FullscreenUI", "List Settings");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Load Database Cheats");
|
TRANSLATE_NOOP("FullscreenUI", "Load Database Cheats");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Load Devices From Save States");
|
TRANSLATE_NOOP("FullscreenUI", "Load Devices From Save States");
|
||||||
|
@ -88,36 +88,6 @@ struct BackgroundProgressDialogData
|
|||||||
s32 value;
|
s32 value;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MenuButtonBounds
|
|
||||||
{
|
|
||||||
ImVec2 title_size;
|
|
||||||
ImVec2 value_size;
|
|
||||||
ImVec2 summary_size;
|
|
||||||
|
|
||||||
ImRect frame_bb;
|
|
||||||
ImRect title_bb;
|
|
||||||
ImRect value_bb;
|
|
||||||
ImRect summary_bb;
|
|
||||||
|
|
||||||
float available_width = CalcAvailWidth();
|
|
||||||
float available_non_value_width;
|
|
||||||
|
|
||||||
MenuButtonBounds(const std::string_view& title, const std::string_view& value, const std::string_view& summary);
|
|
||||||
MenuButtonBounds(const std::string_view& title, const ImVec2& value_size, const std::string_view& summary);
|
|
||||||
MenuButtonBounds(const ImVec2& title_size, const ImVec2& value_size, const ImVec2& summary_size);
|
|
||||||
|
|
||||||
static float CalcAvailWidth();
|
|
||||||
|
|
||||||
static float GetSingleLineHeight(float y_padding = LAYOUT_MENU_BUTTON_Y_PADDING);
|
|
||||||
static float GetSummaryLineHeight(float y_padding = LAYOUT_MENU_BUTTON_Y_PADDING);
|
|
||||||
|
|
||||||
void CalcBB();
|
|
||||||
void CalcTitleSize(const std::string_view& title);
|
|
||||||
void SetValueSize(const ImVec2& value_size);
|
|
||||||
void CalcValueSize(const std::string_view& value);
|
|
||||||
void CalcSummarySize(const std::string_view& summary);
|
|
||||||
};
|
|
||||||
|
|
||||||
class MessageDialog : public PopupDialog
|
class MessageDialog : public PopupDialog
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -1545,6 +1515,27 @@ ImGuiFullscreen::MenuButtonBounds::MenuButtonBounds(const std::string_view& titl
|
|||||||
CalcBB();
|
CalcBB();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGuiFullscreen::MenuButtonBounds::MenuButtonBounds(const std::string_view& title, const std::string_view& value,
|
||||||
|
const std::string_view& summary, float left_margin)
|
||||||
|
{
|
||||||
|
// ugly, but only used for compact game list, whatever
|
||||||
|
const float orig_width = available_width;
|
||||||
|
available_width -= left_margin;
|
||||||
|
|
||||||
|
CalcValueSize(value);
|
||||||
|
CalcTitleSize(title);
|
||||||
|
CalcSummarySize(summary);
|
||||||
|
|
||||||
|
available_width = orig_width;
|
||||||
|
|
||||||
|
CalcBB();
|
||||||
|
|
||||||
|
title_bb.Min.x += left_margin;
|
||||||
|
title_bb.Max.x += left_margin;
|
||||||
|
summary_bb.Min.x += left_margin;
|
||||||
|
summary_bb.Max.x += left_margin;
|
||||||
|
}
|
||||||
|
|
||||||
ImGuiFullscreen::MenuButtonBounds::MenuButtonBounds(const std::string_view& title, const ImVec2& value_size,
|
ImGuiFullscreen::MenuButtonBounds::MenuButtonBounds(const std::string_view& title, const ImVec2& value_size,
|
||||||
const std::string_view& summary)
|
const std::string_view& summary)
|
||||||
{
|
{
|
||||||
@ -1930,30 +1921,33 @@ bool ImGuiFullscreen::MenuImageButton(std::string_view title, std::string_view s
|
|||||||
const ImVec2& uv0 /*= ImVec2(0.0f, 0.0f)*/,
|
const ImVec2& uv0 /*= ImVec2(0.0f, 0.0f)*/,
|
||||||
const ImVec2& uv1 /*= ImVec2(1.0f, 1.0f)*/)
|
const ImVec2& uv1 /*= ImVec2(1.0f, 1.0f)*/)
|
||||||
{
|
{
|
||||||
MenuButtonBounds bb(title, ImVec2(), summary);
|
const float left_margin = image_size.x + LayoutScale(15.0f);
|
||||||
|
const MenuButtonBounds mbb(title, {}, summary, left_margin);
|
||||||
|
|
||||||
bool visible, hovered;
|
bool visible, hovered;
|
||||||
bool pressed = MenuButtonFrame(title, enabled, bb.frame_bb, &visible, &hovered);
|
bool pressed = MenuButtonFrame(title, enabled, mbb.frame_bb, &visible, &hovered);
|
||||||
if (!visible)
|
if (!visible)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ImGui::GetWindowDrawList()->AddImage(user_texture_id, bb.title_bb.Min, bb.title_bb.Min + image_size, uv0, uv1,
|
const ImRect image_rect(CenterImage(
|
||||||
|
ImRect(ImVec2(mbb.title_bb.Min.x - left_margin, mbb.title_bb.Min.y),
|
||||||
|
ImVec2(mbb.title_bb.Min.x - left_margin, mbb.title_bb.Min.y + image_size.x)),
|
||||||
|
ImVec2(static_cast<float>(user_texture_id->GetWidth()), static_cast<float>(user_texture_id->GetHeight()))));
|
||||||
|
|
||||||
|
ImGui::GetWindowDrawList()->AddImage(user_texture_id, image_rect.Min, image_rect.Max, uv0, uv1,
|
||||||
enabled ? IM_COL32(255, 255, 255, 255) :
|
enabled ? IM_COL32(255, 255, 255, 255) :
|
||||||
ImGui::GetColorU32(ImGuiCol_TextDisabled));
|
ImGui::GetColorU32(ImGuiCol_TextDisabled));
|
||||||
|
|
||||||
const float text_offset = image_size.x + LayoutScale(15.0f);
|
|
||||||
bb.title_bb.Min.x += text_offset;
|
|
||||||
bb.title_bb.Max.x += text_offset;
|
|
||||||
const ImVec4& color = ImGui::GetStyle().Colors[enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled];
|
const ImVec4& color = ImGui::GetStyle().Colors[enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled];
|
||||||
RenderShadowedTextClipped(UIStyle.Font, UIStyle.LargeFontSize, UIStyle.BoldFontWeight, bb.title_bb.Min,
|
RenderShadowedTextClipped(UIStyle.Font, UIStyle.LargeFontSize, UIStyle.BoldFontWeight, mbb.title_bb.Min,
|
||||||
bb.title_bb.Max, ImGui::GetColorU32(color), title, &bb.title_size, ImVec2(0.0f, 0.0f),
|
mbb.title_bb.Max, ImGui::GetColorU32(color), title, &mbb.title_size, ImVec2(0.0f, 0.0f),
|
||||||
bb.title_size.x, &bb.title_bb);
|
mbb.title_size.x, &mbb.title_bb);
|
||||||
|
|
||||||
if (!summary.empty())
|
if (!summary.empty())
|
||||||
{
|
{
|
||||||
RenderShadowedTextClipped(UIStyle.Font, UIStyle.MediumFontSize, UIStyle.NormalFontWeight, bb.summary_bb.Min,
|
RenderShadowedTextClipped(UIStyle.Font, UIStyle.MediumFontSize, UIStyle.NormalFontWeight, mbb.summary_bb.Min,
|
||||||
bb.summary_bb.Max, ImGui::GetColorU32(DarkerColor(color)), summary, &bb.summary_size,
|
mbb.summary_bb.Max, ImGui::GetColorU32(DarkerColor(color)), summary, &mbb.summary_size,
|
||||||
ImVec2(0.0f, 0.0f), bb.summary_size.x, &bb.summary_bb);
|
ImVec2(0.0f, 0.0f), mbb.summary_size.x, &mbb.summary_bb);
|
||||||
}
|
}
|
||||||
|
|
||||||
s_state.menu_button_index++;
|
s_state.menu_button_index++;
|
||||||
|
@ -481,6 +481,39 @@ protected:
|
|||||||
State m_state = State::Inactive;
|
State m_state = State::Inactive;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Wrapper for computing menu button bounds.
|
||||||
|
struct MenuButtonBounds
|
||||||
|
{
|
||||||
|
ImVec2 title_size;
|
||||||
|
ImVec2 value_size;
|
||||||
|
ImVec2 summary_size;
|
||||||
|
|
||||||
|
ImRect frame_bb;
|
||||||
|
ImRect title_bb;
|
||||||
|
ImRect value_bb;
|
||||||
|
ImRect summary_bb;
|
||||||
|
|
||||||
|
float available_width = CalcAvailWidth();
|
||||||
|
float available_non_value_width;
|
||||||
|
|
||||||
|
MenuButtonBounds(const std::string_view& title, const std::string_view& value, const std::string_view& summary);
|
||||||
|
MenuButtonBounds(const std::string_view& title, const std::string_view& value, const std::string_view& summary,
|
||||||
|
float left_margin);
|
||||||
|
MenuButtonBounds(const std::string_view& title, const ImVec2& value_size, const std::string_view& summary);
|
||||||
|
MenuButtonBounds(const ImVec2& title_size, const ImVec2& value_size, const ImVec2& summary_size);
|
||||||
|
|
||||||
|
static float CalcAvailWidth();
|
||||||
|
|
||||||
|
static float GetSingleLineHeight(float y_padding = LAYOUT_MENU_BUTTON_Y_PADDING);
|
||||||
|
static float GetSummaryLineHeight(float y_padding = LAYOUT_MENU_BUTTON_Y_PADDING);
|
||||||
|
|
||||||
|
void CalcBB();
|
||||||
|
void CalcTitleSize(const std::string_view& title);
|
||||||
|
void SetValueSize(const ImVec2& value_size);
|
||||||
|
void CalcValueSize(const std::string_view& value);
|
||||||
|
void CalcSummarySize(const std::string_view& summary);
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace ImGuiFullscreen
|
} // namespace ImGuiFullscreen
|
||||||
|
|
||||||
// Host UI triggers from Big Picture mode.
|
// Host UI triggers from Big Picture mode.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user