FullscreenUI: Add drop shadows to most text

Improves readability with custom backgrounds.
This commit is contained in:
Stenzek 2025-03-01 16:00:03 +10:00
parent 9bfc3e90cc
commit 34fdbafe85
No known key found for this signature in database
4 changed files with 277 additions and 306 deletions

View File

@ -2584,6 +2584,7 @@ bool Achievements::PrepareAchievementsWindow()
void Achievements::DrawAchievementsWindow()
{
using ImGuiFullscreen::LayoutScale;
using ImGuiFullscreen::RenderShadowedTextClipped;
using ImGuiFullscreen::UIStyle;
auto lock = Achievements::GetLock();
@ -2602,6 +2603,7 @@ void Achievements::DrawAchievementsWindow()
const ImVec4 background = ImGuiFullscreen::ModAlpha(UIStyle.BackgroundColor, alpha);
const ImVec4 heading_background = ImGuiFullscreen::ModAlpha(UIStyle.BackgroundColor, heading_alpha);
const ImVec2 display_size = ImGui::GetIO().DisplaySize;
const u32 text_color = ImGui::GetColorU32(ImGuiCol_Text);
const float heading_height = LayoutScale(heading_height_unscaled);
bool close_window = false;
@ -2651,10 +2653,8 @@ void Achievements::DrawAchievementsWindow()
top += UIStyle.LargeFont->FontSize + spacing;
ImGui::PushFont(UIStyle.LargeFont);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f),
&title_bb);
ImGui::PopFont();
RenderShadowedTextClipped(UIStyle.LargeFont, title_bb.Min, title_bb.Max, text_color, text.c_str(), text.end_ptr(),
nullptr, ImVec2(0.0f, 0.0f), 0.0f, &title_bb);
const ImRect summary_bb(ImVec2(left, top), ImVec2(right, top + UIStyle.MediumFont->FontSize));
if (s_state.game_summary.num_core_achievements > 0)
@ -2679,10 +2679,8 @@ void Achievements::DrawAchievementsWindow()
top += UIStyle.MediumFont->FontSize + spacing;
ImGui::PushFont(UIStyle.MediumFont);
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, text.c_str(), text.end_ptr(), nullptr,
ImVec2(0.0f, 0.0f), &summary_bb);
ImGui::PopFont();
RenderShadowedTextClipped(UIStyle.MediumFont, summary_bb.Min, summary_bb.Max, text_color, text.c_str(),
text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), 0.0f, &summary_bb);
if (s_state.game_summary.num_core_achievements > 0)
{
@ -2778,6 +2776,7 @@ void Achievements::DrawAchievement(const rc_client_achievement_t* cheevo)
{
using ImGuiFullscreen::LayoutScale;
using ImGuiFullscreen::LayoutUnscale;
using ImGuiFullscreen::RenderShadowedTextClipped;
using ImGuiFullscreen::UIStyle;
static constexpr float alpha = 0.8f;
@ -2785,6 +2784,7 @@ void Achievements::DrawAchievement(const rc_client_achievement_t* cheevo)
static constexpr float progress_spacing_unscaled = 5.0f;
const float spacing = ImGuiFullscreen::LayoutScale(4.0f);
const u32 text_color = ImGui::GetColorU32(ImGuiCol_Text);
const bool is_unlocked = (cheevo->state == RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED);
const std::string_view measured_progress(cheevo->measured_progress);
@ -2876,26 +2876,24 @@ void Achievements::DrawAchievement(const rc_client_achievement_t* cheevo)
const float text_start_x = bb.Min.x + image_size.x + LayoutScale(15.0f);
const ImRect title_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(points_start, midpoint));
const ImRect summary_bb(ImVec2(text_start_x, midpoint),
ImVec2(points_start, midpoint + UIStyle.MediumFont->FontSize + extra_summary_height));
const ImRect summary_bb(ImVec2(text_start_x, midpoint), ImVec2(points_start, midpoint + summary_text_size.y));
const ImRect points_bb(ImVec2(points_start, midpoint), bb.Max);
const ImRect lock_bb(ImVec2(points_template_start + ((points_template_size.x - right_icon_size.x) * 0.5f), bb.Min.y),
ImVec2(bb.Max.x, midpoint));
ImGui::PushFont(UIStyle.LargeFont);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, cheevo->title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb);
ImGui::RenderTextClipped(lock_bb.Min, lock_bb.Max, right_icon_text, nullptr, &right_icon_size, ImVec2(0.0f, 0.0f),
&lock_bb);
ImGui::PopFont();
RenderShadowedTextClipped(UIStyle.LargeFont, title_bb.Min, title_bb.Max, text_color, cheevo->title, nullptr, nullptr,
ImVec2(0.0f, 0.0f), 0.0f, &title_bb);
RenderShadowedTextClipped(UIStyle.LargeFont, lock_bb.Min, lock_bb.Max, text_color, right_icon_text, nullptr,
&right_icon_size, ImVec2(0.0f, 0.0f), 0.0f, &lock_bb);
ImGui::PushFont(UIStyle.MediumFont);
if (cheevo->description && summary_length > 0)
{
ImGui::RenderTextWrapped(summary_bb.Min, cheevo->description, cheevo->description + summary_length,
summary_wrap_width);
RenderShadowedTextClipped(UIStyle.MediumFont, summary_bb.Min, summary_bb.Max, text_color, cheevo->description,
cheevo->description + summary_length, &summary_text_size, ImVec2(0.0f, 0.0f),
summary_wrap_width, &summary_bb);
}
ImGui::RenderTextClipped(points_bb.Min, points_bb.Max, text.c_str(), text.end_ptr(), &points_size, ImVec2(0.0f, 0.0f),
&points_bb);
RenderShadowedTextClipped(UIStyle.MediumFont, points_bb.Min, points_bb.Max, text_color, text.c_str(), text.end_ptr(),
&points_size, ImVec2(0.0f, 0.0f), 0.0f, &points_bb);
if (is_unlocked)
{
@ -2904,8 +2902,8 @@ void Achievements::DrawAchievement(const rc_client_achievement_t* cheevo)
text.format(TRANSLATE_FS("Achievements", "Unlocked: {}"), date);
const ImRect unlock_bb(summary_bb.Min.x, summary_bb.Max.y + spacing, summary_bb.Max.x, bb.Max.y);
ImGui::RenderTextClipped(unlock_bb.Min, unlock_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f),
&unlock_bb);
RenderShadowedTextClipped(UIStyle.MediumFont, unlock_bb.Min, unlock_bb.Max, text_color, text.c_str(),
text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), 0.0f, &unlock_bb);
}
else if (is_measured)
{
@ -2934,8 +2932,6 @@ void Achievements::DrawAchievement(const rc_client_achievement_t* cheevo)
INFO_LOG("Opening achievement details: {}", url);
Host::OpenURL(url);
}
ImGui::PopFont();
}
bool Achievements::PrepareLeaderboardsWindow()
@ -2960,6 +2956,7 @@ bool Achievements::PrepareLeaderboardsWindow()
void Achievements::DrawLeaderboardsWindow()
{
using ImGuiFullscreen::LayoutScale;
using ImGuiFullscreen::RenderShadowedTextClipped;
using ImGuiFullscreen::UIStyle;
static constexpr float alpha = 0.8f;
@ -2982,6 +2979,7 @@ void Achievements::DrawLeaderboardsWindow()
const ImVec4 background = ImGuiFullscreen::ModAlpha(ImGuiFullscreen::UIStyle.BackgroundColor, alpha);
const ImVec4 heading_background = ImGuiFullscreen::ModAlpha(ImGuiFullscreen::UIStyle.BackgroundColor, heading_alpha);
const ImVec2 display_size = ImGui::GetIO().DisplaySize;
const u32 text_color = ImGui::GetColorU32(ImGuiCol_Text);
const float padding = LayoutScale(10.0f);
const float spacing = LayoutScale(10.0f);
const float spacing_small = spacing / 2.0f;
@ -3062,10 +3060,8 @@ void Achievements::DrawLeaderboardsWindow()
top += UIStyle.LargeFont->FontSize + spacing;
ImGui::PushFont(UIStyle.LargeFont);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f),
&title_bb);
ImGui::PopFont();
RenderShadowedTextClipped(UIStyle.LargeFont, title_bb.Min, title_bb.Max, text_color, text.c_str(), text.end_ptr(),
nullptr, ImVec2(0.0f, 0.0f), 0.0f, &title_bb);
if (is_leaderboard_open)
{
@ -3074,10 +3070,8 @@ void Achievements::DrawLeaderboardsWindow()
top += UIStyle.LargeFont->FontSize + spacing_small;
ImGui::PushFont(UIStyle.LargeFont);
ImGui::RenderTextClipped(subtitle_bb.Min, subtitle_bb.Max, text.c_str(), text.end_ptr(), nullptr,
ImVec2(0.0f, 0.0f), &subtitle_bb);
ImGui::PopFont();
RenderShadowedTextClipped(UIStyle.LargeFont, subtitle_bb.Min, subtitle_bb.Max, text_color, text.c_str(),
text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), 0.0f, &subtitle_bb);
text.assign(s_state.open_leaderboard->description);
}
@ -3092,24 +3086,21 @@ void Achievements::DrawLeaderboardsWindow()
const ImRect summary_bb(ImVec2(left, top), ImVec2(right, top + UIStyle.MediumFont->FontSize));
top += UIStyle.MediumFont->FontSize + spacing_small;
ImGui::PushFont(UIStyle.MediumFont);
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, text.c_str(), text.end_ptr(), nullptr,
ImVec2(0.0f, 0.0f), &summary_bb);
RenderShadowedTextClipped(UIStyle.MediumFont, summary_bb.Min, summary_bb.Max, text_color, text.c_str(),
text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), 0.0f, &summary_bb);
if (!is_leaderboard_open && !Achievements::IsHardcoreModeActive())
{
const ImRect hardcore_warning_bb(ImVec2(left, top), ImVec2(right, top + UIStyle.MediumFont->FontSize));
top += UIStyle.MediumFont->FontSize + spacing_small;
ImGui::RenderTextClipped(
hardcore_warning_bb.Min, hardcore_warning_bb.Max,
RenderShadowedTextClipped(
UIStyle.MediumFont, hardcore_warning_bb.Min, hardcore_warning_bb.Max, text_color,
TRANSLATE("Achievements",
"Submitting scores is disabled because hardcore mode is off. Leaderboards are read-only."),
nullptr, nullptr, ImVec2(0.0f, 0.0f), &hardcore_warning_bb);
nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f, &hardcore_warning_bb);
}
ImGui::PopFont();
if (is_leaderboard_open)
{
const float tab_width = (ImGui::GetWindowWidth() / ImGuiFullscreen::UIStyle.LayoutScale) * 0.5f;
@ -3149,19 +3140,23 @@ void Achievements::DrawLeaderboardsWindow()
&visible, &hovered, &bb.Min, &bb.Max, 0, alpha);
UNREFERENCED_VARIABLE(pressed);
// add padding from the window below, don't want the menu items butted up against the edge
bb.Min.x += LayoutScale(ImGuiFullscreen::LAYOUT_MENU_WINDOW_X_PADDING);
bb.Max.x -= LayoutScale(ImGuiFullscreen::LAYOUT_MENU_WINDOW_X_PADDING);
const float midpoint = bb.Min.y + UIStyle.LargeFont->FontSize + LayoutScale(4.0f);
float text_start_x = bb.Min.x + LayoutScale(15.0f) + padding;
ImGui::PushFont(UIStyle.LargeFont);
const ImRect rank_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(bb.Max.x, midpoint));
ImGui::RenderTextClipped(rank_bb.Min, rank_bb.Max, TRANSLATE("Achievements", "Rank"), nullptr, nullptr,
ImVec2(0.0f, 0.0f), &rank_bb);
RenderShadowedTextClipped(UIStyle.LargeFont, rank_bb.Min, rank_bb.Max, text_color,
TRANSLATE("Achievements", "Rank"), nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f,
&rank_bb);
text_start_x += rank_column_width + column_spacing;
const ImRect user_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(bb.Max.x, midpoint));
ImGui::RenderTextClipped(user_bb.Min, user_bb.Max, TRANSLATE("Achievements", "Name"), nullptr, nullptr,
ImVec2(0.0f, 0.0f), &user_bb);
RenderShadowedTextClipped(UIStyle.LargeFont, user_bb.Min, user_bb.Max, text_color,
TRANSLATE("Achievements", "Name"), nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f,
&user_bb);
text_start_x += name_column_width + column_spacing;
static const char* value_headings[NUM_RC_CLIENT_LEADERBOARD_FORMATS] = {
@ -3171,19 +3166,18 @@ void Achievements::DrawLeaderboardsWindow()
};
const ImRect score_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(bb.Max.x, midpoint));
ImGui::RenderTextClipped(
score_bb.Min, score_bb.Max,
RenderShadowedTextClipped(
UIStyle.LargeFont, score_bb.Min, score_bb.Max, text_color,
Host::TranslateToCString(
"Achievements",
value_headings[std::min<u8>(s_state.open_leaderboard->format, NUM_RC_CLIENT_LEADERBOARD_FORMATS - 1)]),
nullptr, nullptr, ImVec2(0.0f, 0.0f), &score_bb);
nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f, &score_bb);
text_start_x += time_column_width + column_spacing;
const ImRect date_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(bb.Max.x, midpoint));
ImGui::RenderTextClipped(date_bb.Min, date_bb.Max, TRANSLATE("Achievements", "Date Submitted"), nullptr,
nullptr, ImVec2(0.0f, 0.0f), &date_bb);
ImGui::PopFont();
RenderShadowedTextClipped(UIStyle.LargeFont, date_bb.Min, date_bb.Max, text_color,
TRANSLATE("Achievements", "Date Submitted"), nullptr, nullptr, ImVec2(0.0f, 0.0f),
0.0f, &date_bb);
const float line_thickness = LayoutScale(1.0f);
const float line_padding = LayoutScale(5.0f);
@ -3260,15 +3254,11 @@ void Achievements::DrawLeaderboardsWindow()
}
else
{
ImGui::PushFont(UIStyle.LargeFont);
const ImVec2 pos_min(0.0f, heading_height);
const ImVec2 pos_max(display_size.x, display_size.y);
ImGui::RenderTextClipped(pos_min, pos_max,
TRANSLATE("Achievements", "Downloading leaderboard data, please wait..."), nullptr,
nullptr, ImVec2(0.5f, 0.5f));
ImGui::PopFont();
RenderShadowedTextClipped(UIStyle.LargeFont, pos_min, pos_max, text_color,
TRANSLATE("Achievements", "Downloading leaderboard data, please wait..."), nullptr,
nullptr, ImVec2(0.5f, 0.5f), 0.0f);
}
}
else
@ -3292,10 +3282,9 @@ void Achievements::DrawLeaderboardsWindow()
const float midpoint = bb.Min.y + UIStyle.LargeFont->FontSize + LayoutScale(4.0f);
const ImRect title_bb(bb.Min, ImVec2(bb.Max.x, midpoint));
ImGui::PushFont(UIStyle.LargeFont);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, TRANSLATE("Achievements", "Loading..."), nullptr,
nullptr, ImVec2(0, 0), &title_bb);
ImGui::PopFont();
RenderShadowedTextClipped(UIStyle.LargeFont, title_bb.Min, title_bb.Max, text_color,
TRANSLATE("Achievements", "Loading..."), nullptr, nullptr, ImVec2(0, 0), 0.0f,
&title_bb);
if (!s_state.leaderboard_fetch_handle)
FetchNextLeaderboardEntries();
@ -3329,6 +3318,7 @@ void Achievements::DrawLeaderboardEntry(const rc_client_leaderboard_entry_t& ent
float column_spacing)
{
using ImGuiFullscreen::LayoutScale;
using ImGuiFullscreen::RenderShadowedTextClipped;
using ImGuiFullscreen::UIStyle;
static constexpr float alpha = 0.8f;
@ -3347,14 +3337,11 @@ void Achievements::DrawLeaderboardEntry(const rc_client_leaderboard_entry_t& ent
text.format("{}", entry.rank);
ImGui::PushFont(UIStyle.LargeFont);
if (is_self)
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 242, 0, 255));
const u32 text_color = is_self ? IM_COL32(255, 242, 0, 255) : ImGui::GetColorU32(ImGuiCol_Text);
const ImRect rank_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(bb.Max.x, midpoint));
ImGui::RenderTextClipped(rank_bb.Min, rank_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f),
&rank_bb);
RenderShadowedTextClipped(UIStyle.LargeFont, rank_bb.Min, rank_bb.Max, text_color, text.c_str(), text.end_ptr(),
nullptr, ImVec2(0.0f, 0.0f), 0.0f, &rank_bb);
text_start_x += rank_column_width + column_spacing;
const float icon_size = bb.Max.y - bb.Min.y;
@ -3383,23 +3370,20 @@ void Achievements::DrawLeaderboardEntry(const rc_client_leaderboard_entry_t& ent
}
const ImRect user_bb(ImVec2(text_start_x + column_spacing + icon_size, bb.Min.y), ImVec2(bb.Max.x, midpoint));
ImGui::RenderTextClipped(user_bb.Min, user_bb.Max, entry.user, nullptr, nullptr, ImVec2(0.0f, 0.0f), &user_bb);
RenderShadowedTextClipped(UIStyle.LargeFont, user_bb.Min, user_bb.Max, text_color, entry.user, nullptr, nullptr,
ImVec2(0.0f, 0.0f), 0.0f, &user_bb);
text_start_x += name_column_width + column_spacing;
const ImRect score_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(bb.Max.x, midpoint));
ImGui::RenderTextClipped(score_bb.Min, score_bb.Max, entry.display, nullptr, nullptr, ImVec2(0.0f, 0.0f), &score_bb);
RenderShadowedTextClipped(UIStyle.LargeFont, score_bb.Min, score_bb.Max, text_color, entry.display, nullptr, nullptr,
ImVec2(0.0f, 0.0f), 0.0f, &score_bb);
text_start_x += time_column_width + column_spacing;
const ImRect time_bb(ImVec2(text_start_x, bb.Min.y), ImVec2(bb.Max.x, midpoint));
SmallString submit_time;
FullscreenUI::TimeToPrintableString(&submit_time, entry.submitted);
ImGui::RenderTextClipped(time_bb.Min, time_bb.Max, submit_time.c_str(), submit_time.end_ptr(), nullptr,
ImVec2(0.0f, 0.0f), &time_bb);
if (is_self)
ImGui::PopStyleColor();
ImGui::PopFont();
RenderShadowedTextClipped(UIStyle.LargeFont, time_bb.Min, time_bb.Max, text_color, submit_time.c_str(),
submit_time.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), 0.0f, &time_bb);
if (pressed)
{
@ -3411,6 +3395,7 @@ void Achievements::DrawLeaderboardEntry(const rc_client_leaderboard_entry_t& ent
void Achievements::DrawLeaderboardListEntry(const rc_client_leaderboard_t* lboard)
{
using ImGuiFullscreen::LayoutScale;
using ImGuiFullscreen::RenderShadowedTextClipped;
using ImGuiFullscreen::UIStyle;
static constexpr float alpha = 0.8f;
@ -3427,19 +3412,17 @@ void Achievements::DrawLeaderboardListEntry(const rc_client_leaderboard_t* lboar
const float midpoint = bb.Min.y + UIStyle.LargeFont->FontSize + LayoutScale(4.0f);
const float text_start_x = bb.Min.x + LayoutScale(15.0f);
const u32 text_color = ImGui::GetColorU32(ImGuiCol_Text);
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);
ImGui::PushFont(UIStyle.LargeFont);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, lboard->title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb);
ImGui::PopFont();
RenderShadowedTextClipped(UIStyle.LargeFont, title_bb.Min, title_bb.Max, text_color, lboard->title, nullptr, nullptr,
ImVec2(0.0f, 0.0f), 0.0f, &title_bb);
if (lboard->description && lboard->description[0] != '\0')
{
ImGui::PushFont(UIStyle.MediumFont);
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, lboard->description, nullptr, nullptr, ImVec2(0.0f, 0.0f),
&summary_bb);
ImGui::PopFont();
RenderShadowedTextClipped(UIStyle.MediumFont, summary_bb.Min, summary_bb.Max, text_color, lboard->description,
nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f, &summary_bb);
}
if (pressed)

View File

@ -143,6 +143,7 @@ using ImGuiFullscreen::PopPrimaryColor;
using ImGuiFullscreen::PushPrimaryColor;
using ImGuiFullscreen::QueueResetFocus;
using ImGuiFullscreen::RangeButton;
using ImGuiFullscreen::RenderShadowedTextClipped;
using ImGuiFullscreen::ResetFocusHere;
using ImGuiFullscreen::RightAlignNavButtons;
using ImGuiFullscreen::SetFullscreenFooterText;
@ -1765,17 +1766,19 @@ void FullscreenUI::DrawLandingTemplate(ImVec2* menu_pos, ImVec2* menu_size)
ImDrawList* const dl = ImGui::GetWindowDrawList();
SmallString heading_str;
ImGui::PushFont(heading_font);
ImGui::PushStyleColor(ImGuiCol_Text, UIStyle.PrimaryTextColor);
const u32 text_color = ImGui::GetColorU32(UIStyle.PrimaryTextColor);
// draw branding
{
const ImVec2 logo_pos = LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING, LAYOUT_MENU_BUTTON_Y_PADDING);
const ImVec2 logo_size = LayoutScale(LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY);
dl->AddImage(s_state.app_icon_texture.get(), logo_pos, logo_pos + logo_size);
dl->AddText(heading_font, heading_font->FontSize,
ImVec2(logo_pos.x + logo_size.x + LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING), logo_pos.y),
ImGui::GetColorU32(ImGuiCol_Text), "DuckStation");
const char* heading_text = "DuckStation";
const ImVec2 text_size = heading_font->CalcTextSizeA(heading_font->FontSize, FLT_MAX, 0.0f, heading_text);
const ImVec2 text_pos = ImVec2(logo_pos.x + logo_size.x + LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING), logo_pos.y);
ImGuiFullscreen::RenderShadowedTextClipped(heading_font, text_pos, text_pos + text_size, text_color, heading_text,
nullptr, &text_size);
}
// draw time
@ -1786,7 +1789,8 @@ void FullscreenUI::DrawLandingTemplate(ImVec2* menu_pos, ImVec2* menu_size)
const ImVec2 time_size = heading_font->CalcTextSizeA(heading_font->FontSize, FLT_MAX, 0.0f, "00:00");
time_pos = ImVec2(heading_size.x - LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING) - time_size.x,
LayoutScale(LAYOUT_MENU_BUTTON_Y_PADDING));
ImGui::RenderTextClipped(time_pos, time_pos + time_size, heading_str.c_str(), heading_str.end_ptr(), &time_size);
ImGuiFullscreen::RenderShadowedTextClipped(heading_font, time_pos, time_pos + time_size, text_color,
heading_str.c_str(), heading_str.end_ptr(), &time_size);
}
// draw achievements info
@ -1799,7 +1803,8 @@ void FullscreenUI::DrawLandingTemplate(ImVec2* menu_pos, ImVec2* menu_size)
const ImVec2 name_size = heading_font->CalcTextSizeA(heading_font->FontSize, FLT_MAX, 0.0f, username);
const ImVec2 name_pos =
ImVec2(time_pos.x - name_size.x - LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING), time_pos.y);
ImGui::RenderTextClipped(name_pos, name_pos + name_size, username, nullptr, &name_size);
ImGuiFullscreen::RenderShadowedTextClipped(heading_font, name_pos, name_pos + name_size, text_color, username,
nullptr, &name_size);
if (s_state.achievements_user_badge_path.empty()) [[unlikely]]
s_state.achievements_user_badge_path = Achievements::GetLoggedInUserBadgePath();
@ -1815,9 +1820,6 @@ void FullscreenUI::DrawLandingTemplate(ImVec2* menu_pos, ImVec2* menu_size)
}
}
}
ImGui::PopStyleColor();
ImGui::PopFont();
}
EndFullscreenWindow();
}
@ -7026,19 +7028,16 @@ void FullscreenUI::DrawSaveStateSelector(bool is_loading)
const ImVec2 title_pos(bb.Min.x, bb.Min.y + image_height + title_spacing);
const ImRect title_bb(title_pos, ImVec2(bb.Max.x, title_pos.y + UIStyle.LargeFont->FontSize));
ImGui::PushFont(UIStyle.LargeFont);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, entry.title.c_str(), nullptr, nullptr, ImVec2(0.0f, 0.0f),
&title_bb);
ImGui::PopFont();
RenderShadowedTextClipped(UIStyle.LargeFont, title_bb.Min, title_bb.Max, ImGui::GetColorU32(ImGuiCol_Text),
entry.title.c_str(), nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f, &title_bb);
if (!entry.summary.empty())
{
const ImVec2 summary_pos(bb.Min.x, title_pos.y + UIStyle.LargeFont->FontSize + summary_spacing);
const ImRect summary_bb(summary_pos, ImVec2(bb.Max.x, summary_pos.y + UIStyle.MediumFont->FontSize));
ImGui::PushFont(UIStyle.MediumFont);
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, entry.summary.c_str(), nullptr, nullptr,
ImVec2(0.0f, 0.0f), &summary_bb);
ImGui::PopFont();
RenderShadowedTextClipped(UIStyle.MediumFont, summary_bb.Min, summary_bb.Max,
ImGui::GetColorU32(ImGuiCol_Text), entry.summary.c_str(), nullptr, nullptr,
ImVec2(0.0f, 0.0f), 0.0f, &summary_bb);
}
if (pressed)
@ -7489,6 +7488,8 @@ void FullscreenUI::DrawGameListWindow()
void FullscreenUI::DrawGameList(const ImVec2& heading_size)
{
static constexpr auto to_mb = [](s64 size) { return static_cast<u32>((size + 1048575) / 1048576); };
if (!BeginFullscreenColumns(nullptr, heading_size.y, true, true))
{
EndFullscreenColumns();
@ -7515,6 +7516,7 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
BeginMenuButtons();
SmallString summary;
const u32 text_color = ImGui::GetColorU32(ImGuiCol_Text);
for (const GameList::Entry* entry : s_state.game_list_sorted_entries)
{
@ -7528,11 +7530,13 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
GPUTexture* cover_texture = GetGameListCover(entry, true);
if (entry->serial.empty())
summary.format("{} - ", Settings::GetDiscRegionDisplayName(entry->region));
{
summary.format("{} | {} MB", Path::GetFileName(entry->path), to_mb(entry->file_size));
}
else
summary.format("{} - {} - ", entry->serial, Settings::GetDiscRegionDisplayName(entry->region));
summary.append(Path::GetFileName(entry->path));
{
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()),
@ -7546,17 +7550,14 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
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);
ImGui::PushFont(UIStyle.LargeFont);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, entry->title.c_str(),
entry->title.c_str() + entry->title.size(), nullptr, ImVec2(0.0f, 0.0f), &title_bb);
ImGui::PopFont();
RenderShadowedTextClipped(UIStyle.LargeFont, title_bb.Min, title_bb.Max, text_color, entry->title.c_str(),
entry->title.c_str() + entry->title.size(), nullptr, ImVec2(0.0f, 0.0f), 0.0f,
&title_bb);
if (!summary.empty())
{
ImGui::PushFont(UIStyle.MediumFont);
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, summary.c_str(), summary.end_ptr(), nullptr,
ImVec2(0.0f, 0.0f), &summary_bb);
ImGui::PopFont();
RenderShadowedTextClipped(UIStyle.MediumFont, summary_bb.Min, summary_bb.Max, text_color, summary.c_str(),
summary.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), 0.0f, &summary_bb);
}
if (pressed)
@ -7604,6 +7605,7 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
static constexpr float field_margin_y = 4.0f;
static constexpr float start_x = 50.0f;
float text_y = info_top_margin + cover_size + info_top_margin;
float text_width;
PushPrimaryColor();
@ -7700,7 +7702,6 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
// size
if (selected_entry->file_size >= 0)
{
const auto to_mb = [](s64 size) { return static_cast<u32>((size + 1048575) / 1048576); };
ImGui::Text(FSUI_CSTR("File Size: %u MB (%u MB on disk)"), to_mb(selected_entry->file_size),
to_mb(selected_entry->uncompressed_size));
}
@ -7766,6 +7767,7 @@ void FullscreenUI::DrawGameGrid(const ImVec2& heading_size)
const u32 grid_count_x = static_cast<u32>(std::floor(ImGui::GetWindowWidth() / item_width_with_spacing));
const float start_x =
(static_cast<float>(ImGui::GetWindowWidth()) - (item_width_with_spacing * static_cast<float>(grid_count_x))) * 0.5f;
const u32 text_color = ImGui::GetColorU32(ImGuiCol_Text);
SmallString draw_title;
@ -7822,10 +7824,8 @@ void FullscreenUI::DrawGameGrid(const ImVec2& heading_size)
const std::string_view title(
std::string_view(entry->title).substr(0, (entry->title.length() > 31) ? 31 : std::string_view::npos));
draw_title.format("{}{}", title, (title.length() == entry->title.length()) ? "" : "...");
ImGui::PushFont(UIStyle.MediumFont);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, draw_title.c_str(), draw_title.end_ptr(), nullptr,
ImVec2(0.5f, 0.0f), &title_bb);
ImGui::PopFont();
RenderShadowedTextClipped(UIStyle.MediumFont, title_bb.Min, title_bb.Max, text_color, draw_title.c_str(),
draw_title.end_ptr(), nullptr, ImVec2(0.5f, 0.0f), 0.0f, &title_bb);
if (pressed)
{

View File

@ -1004,8 +1004,12 @@ void ImGuiFullscreen::DrawFullscreenFooter()
return;
}
static constexpr float TRANSITION_TIME = 0.15f;
const float padding = LayoutScale(LAYOUT_FOOTER_PADDING);
const float height = LayoutScale(LAYOUT_FOOTER_HEIGHT);
const ImVec2 shadow_offset = LayoutScale(LAYOUT_SHADOW_OFFSET, LAYOUT_SHADOW_OFFSET);
const u32 text_color = ImGui::GetColorU32(UIStyle.PrimaryTextColor);
ImDrawList* dl = ImGui::GetForegroundDrawList();
dl->AddRectFilled(ImVec2(0.0f, io.DisplaySize.y - height), io.DisplaySize,
@ -1019,23 +1023,24 @@ void ImGuiFullscreen::DrawFullscreenFooter()
s_state.fullscreen_footer_text != s_state.last_fullscreen_footer_text)
{
if (s_state.fullscreen_text_change_time == 0.0f)
s_state.fullscreen_text_change_time = 0.15f;
s_state.fullscreen_text_change_time = TRANSITION_TIME;
else
s_state.fullscreen_text_change_time = std::max(s_state.fullscreen_text_change_time - io.DeltaTime, 0.0f);
if (s_state.fullscreen_text_change_time == 0.0f)
s_state.last_fullscreen_footer_text = s_state.fullscreen_footer_text;
prev_opacity = s_state.fullscreen_text_change_time * (1.0f / 0.15f);
prev_opacity = s_state.fullscreen_text_change_time * (1.0f / TRANSITION_TIME);
if (prev_opacity > 0.0f)
{
const ImVec2 text_size =
font->CalcTextSizeA(font->FontSize, max_width, 0.0f, s_state.last_fullscreen_footer_text.c_str(),
s_state.last_fullscreen_footer_text.end_ptr());
dl->AddText(font, font->FontSize,
ImVec2(io.DisplaySize.x - padding * 2.0f - text_size.x, io.DisplaySize.y - font->FontSize - padding),
ImGui::GetColorU32(ImVec4(UIStyle.PrimaryTextColor.x, UIStyle.PrimaryTextColor.y,
UIStyle.PrimaryTextColor.z, prev_opacity)),
const ImVec2 text_pos =
ImVec2(io.DisplaySize.x - padding * 2.0f - text_size.x, io.DisplaySize.y - font->FontSize - padding);
dl->AddText(font, font->FontSize, text_pos + shadow_offset, MulAlpha(UIStyle.ShadowColor, prev_opacity),
s_state.last_fullscreen_footer_text.c_str(), s_state.last_fullscreen_footer_text.end_ptr());
dl->AddText(font, font->FontSize, text_pos, ModAlpha(text_color, prev_opacity),
s_state.last_fullscreen_footer_text.c_str(), s_state.last_fullscreen_footer_text.end_ptr());
}
}
@ -1049,11 +1054,13 @@ void ImGuiFullscreen::DrawFullscreenFooter()
const ImVec2 text_size =
font->CalcTextSizeA(font->FontSize, max_width, 0.0f, s_state.fullscreen_footer_text.c_str(),
s_state.fullscreen_footer_text.end_ptr());
dl->AddText(font, font->FontSize,
ImVec2(io.DisplaySize.x - padding * 2.0f - text_size.x, io.DisplaySize.y - font->FontSize - padding),
ImGui::GetColorU32(ImVec4(UIStyle.PrimaryTextColor.x, UIStyle.PrimaryTextColor.y,
UIStyle.PrimaryTextColor.z, 1.0f - prev_opacity)),
const ImVec2 text_pos =
ImVec2(io.DisplaySize.x - padding * 2.0f - text_size.x, io.DisplaySize.y - font->FontSize - padding);
const float opacity = 1.0f - prev_opacity;
dl->AddText(font, font->FontSize, text_pos + shadow_offset, MulAlpha(UIStyle.ShadowColor, opacity),
s_state.fullscreen_footer_text.c_str(), s_state.fullscreen_footer_text.end_ptr());
dl->AddText(font, font->FontSize, text_pos, ModAlpha(text_color, opacity), s_state.fullscreen_footer_text.c_str(),
s_state.fullscreen_footer_text.end_ptr());
}
// for next frame
@ -1290,6 +1297,54 @@ void ImGuiFullscreen::ResetMenuButtonFrame()
s_state.has_hovered_menu_item = false;
}
void ImGuiFullscreen::RenderShadowedTextClipped(ImFont* font, const ImVec2& pos_min, const ImVec2& pos_max, u32 color,
const char* text, const char* text_end,
const ImVec2* text_size_if_known /* = nullptr */,
const ImVec2& align /* = ImVec2(0, 0)*/, float wrap_width /* = 0.0f*/,
const ImRect* clip_rect /* = nullptr */)
{
const char* text_display_end = ImGui::FindRenderedTextEnd(text, text_end);
const int text_len = (int)(text_display_end - text);
if (text_len == 0)
return;
// Perform CPU side clipping for single clipped element to avoid using scissor state
ImVec2 pos = pos_min;
const ImVec2 text_size = text_size_if_known ?
*text_size_if_known :
font->CalcTextSizeA(font->FontSize, FLT_MAX, 0.0f, text, text_display_end, nullptr);
const ImVec2* clip_min = clip_rect ? &clip_rect->Min : &pos_min;
const ImVec2* clip_max = clip_rect ? &clip_rect->Max : &pos_max;
bool need_clipping = (pos.x + text_size.x >= clip_max->x) || (pos.y + text_size.y >= clip_max->y);
if (clip_rect) // If we had no explicit clipping rectangle then pos==clip_min
need_clipping |= (pos.x < clip_min->x) || (pos.y < clip_min->y);
// Align whole block. We should defer that to the better rendering function when we'll have support for individual
// line alignment.
if (align.x > 0.0f)
pos.x = ImMax(pos.x, pos.x + (pos_max.x - pos.x - text_size.x) * align.x);
if (align.y > 0.0f)
pos.y = ImMax(pos.y, pos.y + (pos_max.y - pos.y - text_size.y) * align.y);
ImDrawList* const dl = ImGui::GetWindowDrawList();
// Render
if (need_clipping)
{
ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y);
dl->AddText(font, font->FontSize, pos + LayoutScale(LAYOUT_SHADOW_OFFSET, LAYOUT_SHADOW_OFFSET),
UIStyle.ShadowColor, text, text_display_end, wrap_width, &fine_clip_rect);
dl->AddText(font, font->FontSize, pos, color, text, text_display_end, wrap_width, &fine_clip_rect);
}
else
{
dl->AddText(font, font->FontSize, pos + LayoutScale(LAYOUT_SHADOW_OFFSET, LAYOUT_SHADOW_OFFSET),
UIStyle.ShadowColor, text, text_display_end, wrap_width, nullptr);
dl->AddText(font, font->FontSize, pos, color, text, text_display_end, wrap_width, nullptr);
}
}
void ImGuiFullscreen::MenuHeading(const char* title, bool draw_line /*= true*/)
{
const float line_thickness = draw_line ? LayoutScale(1.0f) : 0.0f;
@ -1301,16 +1356,16 @@ void ImGuiFullscreen::MenuHeading(const char* title, bool draw_line /*= true*/)
if (!visible)
return;
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled));
ImGui::PushFont(UIStyle.LargeFont);
ImGui::RenderTextClipped(bb.Min, bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &bb);
ImGui::PopFont();
ImGui::PopStyleColor();
RenderShadowedTextClipped(UIStyle.LargeFont, bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_TextDisabled), title,
nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f, &bb);
if (draw_line)
{
const ImVec2 line_start(bb.Min.x, bb.Min.y + UIStyle.LargeFont->FontSize + line_padding);
const ImVec2 line_end(bb.Max.x, line_start.y);
const ImVec2 shadow_offset = LayoutScale(LAYOUT_SHADOW_OFFSET, LAYOUT_SHADOW_OFFSET);
ImGui::GetWindowDrawList()->AddLine(line_start + shadow_offset, line_end + shadow_offset, UIStyle.ShadowColor,
line_thickness);
ImGui::GetWindowDrawList()->AddLine(line_start, line_end, ImGui::GetColorU32(ImGuiCol_TextDisabled),
line_thickness);
}
@ -1328,27 +1383,26 @@ bool ImGuiFullscreen::MenuHeadingButton(const char* title, const char* value /*=
if (!visible)
return false;
if (!enabled)
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled));
ImGui::PushFont(UIStyle.LargeFont);
ImGui::RenderTextClipped(bb.Min, bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &bb);
const u32 color = enabled ? ImGui::GetColorU32(ImGuiCol_Text) : ImGui::GetColorU32(ImGuiCol_TextDisabled);
RenderShadowedTextClipped(UIStyle.LargeFont, bb.Min, bb.Max, color, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f,
&bb);
if (value)
{
const ImVec2 value_size(
UIStyle.LargeFont->CalcTextSizeA(UIStyle.LargeFont->FontSize, std::numeric_limits<float>::max(), 0.0f, value));
const ImRect value_bb(ImVec2(bb.Max.x - value_size.x, bb.Min.y), ImVec2(bb.Max.x, bb.Max.y));
ImGui::RenderTextClipped(value_bb.Min, value_bb.Max, value, nullptr, nullptr, ImVec2(0.0f, 0.0f), &value_bb);
RenderShadowedTextClipped(UIStyle.LargeFont, value_bb.Min, value_bb.Max, color, value, nullptr, &value_size,
ImVec2(0.0f, 0.0f), 0.0f, &value_bb);
}
ImGui::PopFont();
if (!enabled)
ImGui::PopStyleColor();
if (draw_line)
{
const ImVec2 line_start(bb.Min.x, bb.Min.y + UIStyle.LargeFont->FontSize + line_padding);
const ImVec2 line_end(bb.Max.x, line_start.y);
const ImVec2 shadow_offset = LayoutScale(LAYOUT_SHADOW_OFFSET, LAYOUT_SHADOW_OFFSET);
ImGui::GetWindowDrawList()->AddLine(line_start + shadow_offset, line_end + shadow_offset, UIStyle.ShadowColor,
line_thickness);
ImGui::GetWindowDrawList()->AddLine(line_start, line_end, ImGui::GetColorU32(ImGuiCol_TextDisabled),
line_thickness);
}
@ -1391,26 +1445,18 @@ bool ImGuiFullscreen::ActiveButtonWithRightText(const char* title, const char* r
return false;
const ImRect title_bb(bb.GetTL(), bb.GetBR());
const u32 text_color = ImGui::GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled);
if (!enabled)
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled));
ImGui::PushFont(font);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb);
RenderShadowedTextClipped(font, title_bb.Min, title_bb.Max, text_color, title, nullptr, nullptr, ImVec2(0.0f, 0.0f),
0.0f, &title_bb);
if (right_title && *right_title)
{
const ImVec2 right_text_size = font->CalcTextSizeA(font->FontSize, title_bb.GetWidth(), 0.0f, right_title);
const ImVec2 right_text_start = ImVec2(title_bb.Max.x - right_text_size.x, title_bb.Min.y);
ImGui::RenderTextClipped(right_text_start, title_bb.Max, right_title, nullptr, &right_text_size, ImVec2(0.0f, 0.0f),
&title_bb);
RenderShadowedTextClipped(font, right_text_start, title_bb.Max, text_color, right_title, nullptr, &right_text_size,
ImVec2(0.0f, 0.0f), 0.0f, &title_bb);
}
ImGui::PopFont();
if (!enabled)
ImGui::PopStyleColor();
s_state.menu_button_index++;
return pressed;
}
@ -1427,25 +1473,16 @@ bool ImGuiFullscreen::MenuButton(const char* title, const char* summary, bool en
const float midpoint = bb.Min.y + font->FontSize + LayoutScale(4.0f);
const ImRect title_bb(bb.Min, ImVec2(bb.Max.x, midpoint));
const ImRect summary_bb(ImVec2(bb.Min.x, midpoint), bb.Max);
if (!enabled)
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled));
ImGui::PushFont(font);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb);
ImGui::PopFont();
const u32 color = enabled ? ImGui::GetColorU32(ImGuiCol_Text) : ImGui::GetColorU32(ImGuiCol_TextDisabled);
RenderShadowedTextClipped(font, title_bb.Min, title_bb.Max, color, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f,
&title_bb);
if (summary)
{
ImGui::PushFont(summary_font);
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, summary, nullptr, nullptr, ImVec2(0.0f, 0.0f),
&summary_bb);
ImGui::PopFont();
RenderShadowedTextClipped(summary_font, summary_bb.Min, summary_bb.Max, color, summary, nullptr, nullptr,
ImVec2(0.0f, 0.0f), 0.0f, &summary_bb);
}
if (!enabled)
ImGui::PopStyleColor();
s_state.menu_button_index++;
return pressed;
}
@ -1462,16 +1499,9 @@ bool ImGuiFullscreen::MenuButtonWithoutSummary(const char* title, bool enabled,
const float midpoint = bb.Min.y + font->FontSize + LayoutScale(4.0f);
const ImRect title_bb(bb.Min, ImVec2(bb.Max.x, midpoint));
const ImRect summary_bb(ImVec2(bb.Min.x, midpoint), bb.Max);
if (!enabled)
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled));
ImGui::PushFont(font);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, title, nullptr, nullptr, text_align, &title_bb);
ImGui::PopFont();
if (!enabled)
ImGui::PopStyleColor();
const u32 color = enabled ? ImGui::GetColorU32(ImGuiCol_Text) : ImGui::GetColorU32(ImGuiCol_TextDisabled);
RenderShadowedTextClipped(font, title_bb.Min, title_bb.Max, color, title, nullptr, nullptr, text_align, 0.0f,
&title_bb);
s_state.menu_button_index++;
return pressed;
@ -1495,25 +1525,16 @@ bool ImGuiFullscreen::MenuImageButton(const char* title, const char* summary, Im
const float text_start_x = bb.Min.x + image_size.x + LayoutScale(15.0f);
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);
if (!enabled)
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled));
ImGui::PushFont(title_font);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb);
ImGui::PopFont();
const u32 color = enabled ? ImGui::GetColorU32(ImGuiCol_Text) : ImGui::GetColorU32(ImGuiCol_TextDisabled);
RenderShadowedTextClipped(title_font, title_bb.Min, title_bb.Max, color, title, nullptr, nullptr, ImVec2(0.0f, 0.0f),
0.0f, &title_bb);
if (summary)
{
ImGui::PushFont(summary_font);
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, summary, nullptr, nullptr, ImVec2(0.0f, 0.0f),
&summary_bb);
ImGui::PopFont();
RenderShadowedTextClipped(summary_font, summary_bb.Min, summary_bb.Max, color, summary, nullptr, nullptr,
ImVec2(0.0f, 0.0f), 0.0f, &summary_bb);
}
if (!enabled)
ImGui::PopStyleColor();
s_state.menu_button_index++;
return pressed;
}
@ -1594,16 +1615,8 @@ bool ImGuiFullscreen::FloatingButton(const char* text, float x, float y, float w
bb.Min += padding;
bb.Max -= padding;
if (!enabled)
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled));
ImGui::PushFont(font);
ImGui::RenderTextClipped(bb.Min, bb.Max, text, nullptr, nullptr, ImVec2(0.0f, 0.0f), &bb);
ImGui::PopFont();
if (!enabled)
ImGui::PopStyleColor();
const u32 color = enabled ? ImGui::GetColorU32(ImGuiCol_Text) : ImGui::GetColorU32(ImGuiCol_TextDisabled);
RenderShadowedTextClipped(font, bb.Min, bb.Max, color, text, nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f, &bb);
return pressed;
}
@ -1620,24 +1633,17 @@ bool ImGuiFullscreen::ToggleButton(const char* title, const char* summary, bool*
const ImRect title_bb(bb.Min, ImVec2(bb.Max.x, midpoint));
const ImRect summary_bb(ImVec2(bb.Min.x, midpoint), bb.Max);
if (!enabled)
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled));
const u32 color = enabled ? ImGui::GetColorU32(ImGuiCol_Text) : ImGui::GetColorU32(ImGuiCol_TextDisabled);
ImGui::PushFont(font);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb);
ImGui::PopFont();
RenderShadowedTextClipped(font, title_bb.Min, title_bb.Max, color, title, nullptr, nullptr, ImVec2(0.0, 0.0f), 0.0f,
&title_bb);
if (summary)
{
ImGui::PushFont(summary_font);
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, summary, nullptr, nullptr, ImVec2(0.0f, 0.0f),
&summary_bb);
ImGui::PopFont();
RenderShadowedTextClipped(summary_font, summary_bb.Min, summary_bb.Max, color, summary, nullptr, nullptr,
ImVec2(0.0, 0.0f), 0.0f, &summary_bb);
}
if (!enabled)
ImGui::PopStyleColor();
const float toggle_width = LayoutScale(50.0f);
const float toggle_height = LayoutScale(25.0f);
const float toggle_x = LayoutScale(8.0f);
@ -1694,24 +1700,17 @@ bool ImGuiFullscreen::ThreeWayToggleButton(const char* title, const char* summar
const ImRect title_bb(bb.Min, ImVec2(bb.Max.x, midpoint));
const ImRect summary_bb(ImVec2(bb.Min.x, midpoint), bb.Max);
if (!enabled)
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled));
const u32 color = enabled ? ImGui::GetColorU32(ImGuiCol_Text) : ImGui::GetColorU32(ImGuiCol_TextDisabled);
ImGui::PushFont(font);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb);
ImGui::PopFont();
RenderShadowedTextClipped(font, title_bb.Min, title_bb.Max, color, title, nullptr, nullptr, ImVec2(0.0, 0.0f), 0.0f,
&title_bb);
if (summary)
{
ImGui::PushFont(summary_font);
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, summary, nullptr, nullptr, ImVec2(0.0f, 0.0f),
&summary_bb);
ImGui::PopFont();
RenderShadowedTextClipped(summary_font, summary_bb.Min, summary_bb.Max, color, summary, nullptr, nullptr,
ImVec2(0.0, 0.0f), 0.0f, &summary_bb);
}
if (!enabled)
ImGui::PopStyleColor();
const float toggle_width = LayoutScale(50.0f);
const float toggle_height = LayoutScale(25.0f);
const float toggle_x = LayoutScale(8.0f);
@ -1773,32 +1772,25 @@ bool ImGuiFullscreen::RangeButton(const char* title, const char* summary, s32* v
return false;
const SmallString value_text = SmallString::from_sprintf(format, *value);
const ImVec2 value_size(ImGui::CalcTextSize(value_text.c_str()));
const ImVec2 value_size =
font->CalcTextSizeA(font->FontSize, FLT_MAX, 0.0f, value_text.c_str(), value_text.end_ptr());
const float midpoint = bb.Min.y + font->FontSize + LayoutScale(4.0f);
const float text_end = bb.Max.x - value_size.x;
const ImRect title_bb(bb.Min, ImVec2(text_end, midpoint));
const ImRect summary_bb(ImVec2(bb.Min.x, midpoint), ImVec2(text_end, bb.Max.y));
if (!enabled)
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled));
ImGui::PushFont(font);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb);
ImGui::RenderTextClipped(bb.Min, bb.Max, value_text.c_str(), nullptr, nullptr, ImVec2(1.0f, 0.5f), &bb);
ImGui::PopFont();
const u32 color = enabled ? ImGui::GetColorU32(ImGuiCol_Text) : ImGui::GetColorU32(ImGuiCol_TextDisabled);
RenderShadowedTextClipped(font, title_bb.Min, title_bb.Max, color, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f,
&title_bb);
RenderShadowedTextClipped(font, bb.Min, bb.Max, color, value_text.c_str(), value_text.end_ptr(), &value_size,
ImVec2(1.0f, 0.5f), 0.0f, &bb);
if (summary)
{
ImGui::PushFont(summary_font);
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, summary, nullptr, nullptr, ImVec2(0.0f, 0.0f),
&summary_bb);
ImGui::PopFont();
RenderShadowedTextClipped(summary_font, summary_bb.Min, summary_bb.Max, color, summary, nullptr, nullptr,
ImVec2(0.0f, 0.0f), 0.0f, &summary_bb);
}
if (!enabled)
ImGui::PopStyleColor();
if (pressed)
ImGui::OpenPopup(title);
@ -1839,32 +1831,25 @@ bool ImGuiFullscreen::RangeButton(const char* title, const char* summary, float*
return false;
const SmallString value_text = SmallString::from_sprintf(format, *value);
const ImVec2 value_size(ImGui::CalcTextSize(value_text.c_str()));
const ImVec2 value_size =
font->CalcTextSizeA(font->FontSize, FLT_MAX, 0.0f, value_text.c_str(), value_text.end_ptr());
const float midpoint = bb.Min.y + font->FontSize + LayoutScale(4.0f);
const float text_end = bb.Max.x - value_size.x;
const ImRect title_bb(bb.Min, ImVec2(text_end, midpoint));
const ImRect summary_bb(ImVec2(bb.Min.x, midpoint), ImVec2(text_end, bb.Max.y));
if (!enabled)
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled));
ImGui::PushFont(font);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb);
ImGui::RenderTextClipped(bb.Min, bb.Max, value_text.c_str(), nullptr, nullptr, ImVec2(1.0f, 0.5f), &bb);
ImGui::PopFont();
const u32 color = enabled ? ImGui::GetColorU32(ImGuiCol_Text) : ImGui::GetColorU32(ImGuiCol_TextDisabled);
RenderShadowedTextClipped(font, title_bb.Min, title_bb.Max, color, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f,
&title_bb);
RenderShadowedTextClipped(font, bb.Min, bb.Max, color, value_text.c_str(), value_text.end_ptr(), &value_size,
ImVec2(1.0f, 0.5f), 0.0f, &bb);
if (summary)
{
ImGui::PushFont(summary_font);
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, summary, nullptr, nullptr, ImVec2(0.0f, 0.0f),
&summary_bb);
ImGui::PopFont();
RenderShadowedTextClipped(summary_font, summary_bb.Min, summary_bb.Max, color, summary, nullptr, nullptr,
ImVec2(0.0f, 0.0f), 0.0f, &summary_bb);
}
if (!enabled)
ImGui::PopStyleColor();
if (pressed)
ImGui::OpenPopup(title);
@ -1907,26 +1892,17 @@ bool ImGuiFullscreen::MenuButtonWithValue(const char* title, const char* summary
const float text_end = bb.Max.x - value_size.x;
const ImRect title_bb(bb.Min, ImVec2(text_end, midpoint));
const ImRect summary_bb(ImVec2(bb.Min.x, midpoint), ImVec2(text_end, bb.Max.y));
if (!enabled)
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled));
ImGui::PushFont(font);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb);
ImGui::RenderTextClipped(bb.Min, bb.Max, value, nullptr, nullptr, ImVec2(1.0f, 0.5f), &bb);
ImGui::PopFont();
const u32 color = enabled ? ImGui::GetColorU32(ImGuiCol_Text) : ImGui::GetColorU32(ImGuiCol_TextDisabled);
RenderShadowedTextClipped(font, title_bb.Min, title_bb.Max, color, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f,
&title_bb);
RenderShadowedTextClipped(font, bb.Min, bb.Max, color, value, nullptr, nullptr, ImVec2(1.0f, 0.5f), 0.0f, &bb);
if (summary)
{
ImGui::PushFont(summary_font);
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, summary, nullptr, nullptr, ImVec2(0.0f, 0.0f),
&summary_bb);
ImGui::PopFont();
RenderShadowedTextClipped(summary_font, summary_bb.Min, summary_bb.Max, color, summary, nullptr, nullptr,
ImVec2(0.0f, 0.0f), 0.0f, &summary_bb);
}
if (!enabled)
ImGui::PopStyleColor();
return pressed;
}
@ -2023,9 +1999,8 @@ void ImGuiFullscreen::NavTitle(const char* title, float height /*= LAYOUT_MENU_B
bb.Min.y += style.FramePadding.y;
bb.Max.y -= style.FramePadding.y;
ImGui::PushFont(font);
ImGui::RenderTextClipped(bb.Min, bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &bb);
ImGui::PopFont();
RenderShadowedTextClipped(font, bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_Text), title, nullptr, &text_size,
ImVec2(0.0f, 0.0f), 0.0f, &bb);
}
void ImGuiFullscreen::RightAlignNavButtons(u32 num_items /*= 0*/,
@ -2098,15 +2073,10 @@ bool ImGuiFullscreen::NavButton(const char* title, bool is_active, bool enabled
bb.Min += style.FramePadding;
bb.Max -= style.FramePadding;
ImGui::PushStyleColor(
ImGuiCol_Text,
ImGui::GetColorU32(enabled ? (is_active ? ImGuiCol_Text : ImGuiCol_TextDisabled) : ImGuiCol_ButtonHovered));
ImGui::PushFont(font);
ImGui::RenderTextClipped(bb.Min, bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &bb);
ImGui::PopFont();
ImGui::PopStyleColor();
RenderShadowedTextClipped(
font, bb.Min, bb.Max,
ImGui::GetColorU32(enabled ? (is_active ? ImGuiCol_Text : ImGuiCol_TextDisabled) : ImGuiCol_ButtonHovered), title,
nullptr, &text_size, ImVec2(0.0f, 0.0f), 0.0f, &bb);
return pressed;
}
@ -2177,15 +2147,10 @@ bool ImGuiFullscreen::NavTab(const char* title, bool is_active, bool enabled /*
bb.Min += pad;
bb.Max -= pad;
ImGui::PushStyleColor(
ImGuiCol_Text,
ImGui::GetColorU32(enabled ? (is_active ? ImGuiCol_Text : ImGuiCol_TextDisabled) : ImGuiCol_ButtonHovered));
ImGui::PushFont(font);
ImGui::RenderTextClipped(bb.Min, bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &bb);
ImGui::PopFont();
ImGui::PopStyleColor();
RenderShadowedTextClipped(
font, bb.Min, bb.Max,
ImGui::GetColorU32(enabled ? (is_active ? ImGuiCol_Text : ImGuiCol_TextDisabled) : ImGuiCol_ButtonHovered), title,
nullptr, nullptr, ImVec2(0.0f, 0.0f), 0.0f, &bb);
return pressed;
}
@ -2209,7 +2174,7 @@ bool ImGuiFullscreen::BeginHorizontalMenu(const char* name, const ImVec2& positi
if (!BeginFullscreenWindow(position, size, name, bg_color, 0.0f, ImVec2()))
return false;
ImGui::SetCursorPos(ImVec2((size.x - menu_width) * 0.5f, (size.y - menu_height) * 0.5f));
ImGui::SetCursorPos(ImFloor(ImVec2((size.x - menu_width) * 0.5f, (size.y - menu_height) * 0.5f)));
PrerenderMenuButtonBorder();
return true;
@ -2267,19 +2232,19 @@ bool ImGuiFullscreen::HorizontalMenuItem(GPUTexture* icon, const char* title, co
title_font->CalcTextSizeA(title_font->FontSize, std::numeric_limits<float>::max(), avail_width, title);
const ImVec2 title_pos =
ImVec2(bb.Min.x + (avail_width - title_size.x) * 0.5f, icon_pos.y + icon_size + LayoutScale(10.0f));
const ImVec4 title_bb = ImVec4(title_pos.x, title_pos.y, title_pos.x + title_size.x, title_pos.y + title_size.y);
const ImRect title_bb = ImRect(title_pos, title_pos + title_size);
dl->AddText(title_font, title_font->FontSize, title_pos, ImGui::GetColorU32(ImGuiCol_Text), title, nullptr, 0.0f,
&title_bb);
RenderShadowedTextClipped(title_font, title_bb.Min, title_bb.Max, ImGui::GetColorU32(ImGuiCol_Text), title, nullptr,
&title_size, ImVec2(0.0f, 0.0f), avail_width, &title_bb);
ImFont* desc_font = UIStyle.MediumFont;
const ImVec2 desc_size =
desc_font->CalcTextSizeA(desc_font->FontSize, std::numeric_limits<float>::max(), avail_width, description);
const ImVec2 desc_pos = ImVec2(bb.Min.x + (avail_width - desc_size.x) * 0.5f, title_bb.w + LayoutScale(10.0f));
const ImVec4 desc_bb = ImVec4(desc_pos.x, desc_pos.y, desc_pos.x + desc_size.x, desc_pos.y + desc_size.y);
const ImVec2 desc_pos = ImVec2(bb.Min.x + (avail_width - desc_size.x) * 0.5f, title_bb.Max.y + LayoutScale(10.0f));
const ImRect desc_bb = ImRect(desc_pos, desc_pos + desc_size);
dl->AddText(desc_font, desc_font->FontSize, desc_pos, ImGui::GetColorU32(ImGuiCol_Text), description, nullptr,
avail_width, &desc_bb);
RenderShadowedTextClipped(desc_font, desc_bb.Min, desc_bb.Max, ImGui::GetColorU32(ImGuiCol_Text), description,
nullptr, nullptr, ImVec2(0.0f, 0.0f), avail_width, &desc_bb);
ImGui::SameLine();
@ -3467,6 +3432,7 @@ void ImGuiFullscreen::SetTheme(std::string_view theme)
UIStyle.SecondaryTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
UIStyle.ToastBackgroundColor = HEX_TO_IMVEC4(0x282828, 0xff);
UIStyle.ToastTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
UIStyle.ShadowColor = IM_COL32(0, 0, 0, 100);
}
else if (theme == "CobaltSky")
{
@ -3489,6 +3455,7 @@ void ImGuiFullscreen::SetTheme(std::string_view theme)
UIStyle.SecondaryTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
UIStyle.ToastBackgroundColor = HEX_TO_IMVEC4(0x282828, 0xff);
UIStyle.ToastTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
UIStyle.ShadowColor = IM_COL32(0, 0, 0, 100);
}
else if (theme == "GreyMatter")
{
@ -3511,6 +3478,7 @@ void ImGuiFullscreen::SetTheme(std::string_view theme)
UIStyle.SecondaryTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
UIStyle.ToastBackgroundColor = HEX_TO_IMVEC4(0x282828, 0xff);
UIStyle.ToastTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
UIStyle.ShadowColor = IM_COL32(0, 0, 0, 100);
}
else if (theme == "PinkyPals")
{
@ -3533,6 +3501,7 @@ void ImGuiFullscreen::SetTheme(std::string_view theme)
UIStyle.SecondaryTextColor = HEX_TO_IMVEC4(0x000000, 0xff);
UIStyle.ToastBackgroundColor = HEX_TO_IMVEC4(0x282828, 0xff);
UIStyle.ToastTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
UIStyle.ShadowColor = IM_COL32(100, 100, 100, 50);
}
else if (theme == "Light")
{
@ -3556,6 +3525,7 @@ void ImGuiFullscreen::SetTheme(std::string_view theme)
UIStyle.SecondaryTextColor = HEX_TO_IMVEC4(0x000000, 0xff);
UIStyle.ToastBackgroundColor = HEX_TO_IMVEC4(0xf1f1f1, 0xff);
UIStyle.ToastTextColor = HEX_TO_IMVEC4(0x000000, 0xff);
UIStyle.ShadowColor = IM_COL32(100, 100, 100, 50);
}
else
{
@ -3579,5 +3549,6 @@ void ImGuiFullscreen::SetTheme(std::string_view theme)
UIStyle.SecondaryTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
UIStyle.ToastBackgroundColor = HEX_TO_IMVEC4(0x282828, 0xff);
UIStyle.ToastTextColor = HEX_TO_IMVEC4(0xffffff, 0xff);
UIStyle.ShadowColor = IM_COL32(0, 0, 0, 100);
}
}

View File

@ -42,6 +42,7 @@ static constexpr float LAYOUT_FOOTER_HEIGHT = LAYOUT_MEDIUM_FONT_SIZE + LAYOUT_F
static constexpr float LAYOUT_HORIZONTAL_MENU_HEIGHT = 320.0f;
static constexpr float LAYOUT_HORIZONTAL_MENU_PADDING = 30.0f;
static constexpr float LAYOUT_HORIZONTAL_MENU_ITEM_WIDTH = 250.0f;
static constexpr float LAYOUT_SHADOW_OFFSET = 1.0f;
struct ALIGN_TO_CACHE_LINE UIStyles
{
@ -68,6 +69,8 @@ struct ALIGN_TO_CACHE_LINE UIStyles
ImFont* MediumFont;
ImFont* LargeFont;
u32 ShadowColor;
float LayoutScale;
float RcpLayoutScale;
float LayoutPaddingLeft;
@ -108,12 +111,22 @@ ALWAYS_INLINE static ImVec4 ModAlpha(const ImVec4& v, float a)
{
return ImVec4(v.x, v.y, v.z, a);
}
ALWAYS_INLINE static u32 ModAlpha(u32 col32, float a)
{
return (col32 & ~IM_COL32_A_MASK) | (static_cast<u32>(a * 255.0f) << IM_COL32_A_SHIFT);
}
ALWAYS_INLINE static ImVec4 MulAlpha(const ImVec4& v, float a)
{
return ImVec4(v.x, v.y, v.z, v.w * a);
}
ALWAYS_INLINE static u32 MulAlpha(u32 col32, float a)
{
return (col32 & ~IM_COL32_A_MASK) |
(static_cast<u32>(static_cast<float>((col32 & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT) * a) << IM_COL32_A_SHIFT);
}
ALWAYS_INLINE static std::string_view RemoveHash(std::string_view s)
{
const std::string_view::size_type pos = s.find('#');
@ -217,6 +230,10 @@ bool MenuButtonFrame(const char* str_id, bool enabled, float height, bool* visib
void DrawMenuButtonFrame(const ImVec2& p_min, const ImVec2& p_max, ImU32 fill_col, bool border = true,
float rounding = 0.0f);
void ResetMenuButtonFrame();
void RenderShadowedTextClipped(ImFont* font, const ImVec2& pos_min, const ImVec2& pos_max, u32 color, const char* text,
const char* text_end, const ImVec2* text_size_if_known = nullptr,
const ImVec2& align = ImVec2(0, 0), float wrap_width = 0.0f,
const ImRect* clip_rect = nullptr);
void MenuHeading(const char* title, bool draw_line = true);
bool MenuHeadingButton(const char* title, const char* value = nullptr, bool enabled = true, bool draw_line = true);
bool ActiveButton(const char* title, bool is_active, bool enabled = true,