diff --git a/pcsx2/Achievements.cpp b/pcsx2/Achievements.cpp index 777476c4defe7..dcc90bb3c6da7 100644 --- a/pcsx2/Achievements.cpp +++ b/pcsx2/Achievements.cpp @@ -2468,7 +2468,8 @@ void Achievements::DrawAchievementsWindow() top += GetLineHeight(g_large_font) + spacing; ImGui::PushFont(g_large_font.first, g_large_font.second); - ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &title_bb); + ImGuiFullscreen::RenderTextClippedWithShadow( + title_bb.Min, title_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &title_bb); ImGui::PopFont(); const ImRect summary_bb(ImVec2(left, top), ImVec2(right, top + GetLineHeight(g_medium_font))); @@ -2599,7 +2600,8 @@ void Achievements::DrawAchievementsWindow() 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); - ImGui::RenderTextClipped(text_bb.Min, text_bb.Max, subset->title, nullptr, nullptr, ImVec2(0.0f, 0.5f), &text_bb); + 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()) @@ -2688,21 +2690,22 @@ void Achievements::DrawAchievementsWindow() 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(ICON_PF_DPAD_UP_DOWN, TRANSLATE_SV("Achievements", "Navigate Subsets")), - std::make_pair(ICON_PF_DPAD_LEFT_RIGHT, TRANSLATE_SV("Achievements", "Back to List")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CIRCLE : ICON_PF_BUTTON_CROSS, TRANSLATE_SV("Achievements", "Select")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CROSS : ICON_PF_BUTTON_CIRCLE, TRANSLATE_SV("Achievements", "Back")), + 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(ICON_PF_DPAD_LEFT_RIGHT, TRANSLATE_SV("Achievements", "Navigate Subsets")), - std::make_pair(ICON_PF_DPAD_UP_DOWN, TRANSLATE_SV("Achievements", "Change Selection")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CROSS : ICON_PF_BUTTON_CIRCLE, TRANSLATE_SV("Achievements", "Back")), + 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")), }); } } @@ -2878,8 +2881,9 @@ void Achievements::DrawAchievement(const rc_client_achievement_t* cheevo) ImVec2(points_template_start + ((points_template_size.x - right_icon_size.x) * 0.5f), bb.Min.y), ImVec2(bb.Max.x, midpoint)); ImGui::PushFont(g_large_font.first, g_large_font.second); - 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); + ImGuiFullscreen::RenderTextClippedWithShadow(title_bb.Min, title_bb.Max, cheevo->title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb); + ImGuiFullscreen::RenderTextClippedWithShadow( + lock_bb.Min, lock_bb.Max, right_icon_text, nullptr, &right_icon_size, ImVec2(0.0f, 0.0f), &lock_bb); ImGui::PopFont(); if (badge_text && badge_icon) @@ -2905,14 +2909,16 @@ void Achievements::DrawAchievement(const rc_client_achievement_t* cheevo) { ImGui::RenderTextWrapped(summary_bb.Min, cheevo->description, cheevo->description + summary_length, summary_wrap_width); } - ImGui::RenderTextClipped(points_bb.Min, points_bb.Max, text.c_str(), text.end_ptr(), &points_size, ImVec2(0.0f, 0.0f), &points_bb); + ImGuiFullscreen::RenderTextClippedWithShadow( + points_bb.Min, points_bb.Max, text.c_str(), text.end_ptr(), &points_size, ImVec2(0.0f, 0.0f), &points_bb); if (is_unlocked) { text.format(TRANSLATE_FS("Achievements", "Unlocked: {}"), FullscreenUI::TimeToPrintableString(cheevo->unlock_time)); 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); + ImGuiFullscreen::RenderTextClippedWithShadow( + unlock_bb.Min, unlock_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &unlock_bb); } else if (is_measured) { @@ -3071,7 +3077,8 @@ void Achievements::DrawLeaderboardsWindow() top += GetLineHeight(g_large_font) + spacing; ImGui::PushFont(g_large_font.first, g_large_font.second); - ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &title_bb); + ImGuiFullscreen::RenderTextClippedWithShadow( + title_bb.Min, title_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &title_bb); ImGui::PopFont(); if (is_leaderboard_open) @@ -3082,7 +3089,7 @@ void Achievements::DrawLeaderboardsWindow() top += GetLineHeight(g_large_font) + spacing_small; ImGui::PushFont(g_large_font.first, g_large_font.second); - ImGui::RenderTextClipped( + ImGuiFullscreen::RenderTextClippedWithShadow( subtitle_bb.Min, subtitle_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &subtitle_bb); ImGui::PopFont(); @@ -3100,7 +3107,7 @@ void Achievements::DrawLeaderboardsWindow() top += GetLineHeight(g_medium_font) + spacing_small; ImGui::PushFont(g_medium_font.first, g_medium_font.second); - ImGui::RenderTextClipped( + ImGuiFullscreen::RenderTextClippedWithShadow( summary_bb.Min, summary_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &summary_bb); if (!is_leaderboard_open && !Achievements::IsHardcoreModeActive()) @@ -3108,9 +3115,9 @@ void Achievements::DrawLeaderboardsWindow() const ImRect hardcore_warning_bb(ImVec2(left, top), ImVec2(right, top + GetLineHeight(g_medium_font))); top += GetLineHeight(g_medium_font) + spacing_small; - ImGui::RenderTextClipped(hardcore_warning_bb.Min, hardcore_warning_bb.Max, - 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); + ImGuiFullscreen::RenderTextClippedWithShadow(hardcore_warning_bb.Min, hardcore_warning_bb.Max, + 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); } ImGui::PopFont(); @@ -3159,7 +3166,7 @@ void Achievements::DrawLeaderboardsWindow() const auto render_centered_heading = [&](const char* text, float width) { const ImRect rect(ImVec2(column_left, bb.Min.y), ImVec2(column_left + width, midpoint)); - ImGui::RenderTextClipped(rect.Min, rect.Max, text, nullptr, nullptr, ImVec2(0.5f, 0.0f), &rect); + ImGuiFullscreen::RenderTextClippedWithShadow(rect.Min, rect.Max, text, nullptr, nullptr, ImVec2(0.5f, 0.0f), &rect); column_left += width + column_spacing; }; @@ -3168,7 +3175,7 @@ void Achievements::DrawLeaderboardsWindow() const float name_column_total_width = icon_column_width + column_spacing + name_column_width; const ImRect user_bb(ImVec2(column_left + icon_column_width + column_spacing, bb.Min.y), ImVec2(column_left + name_column_total_width, midpoint)); - ImGui::RenderTextClipped( + ImGuiFullscreen::RenderTextClippedWithShadow( user_bb.Min, user_bb.Max, TRANSLATE("Achievements", "Name"), nullptr, nullptr, ImVec2(0.5f, 0.0f), &user_bb); column_left += name_column_total_width + column_spacing; @@ -3185,8 +3192,8 @@ void Achievements::DrawLeaderboardsWindow() const float date_column_width = std::max(bb.Max.x - column_left, 0.0f); const ImRect date_bb(ImVec2(column_left, bb.Min.y), ImVec2(column_left + date_column_width, midpoint)); - ImGui::RenderTextClipped(date_bb.Min, date_bb.Max, TRANSLATE("Achievements", "Date Submitted"), nullptr, nullptr, - ImVec2(0.5f, 0.0f), &date_bb); + ImGuiFullscreen::RenderTextClippedWithShadow( + date_bb.Min, date_bb.Max, TRANSLATE("Achievements", "Date Submitted"), nullptr, nullptr, ImVec2(0.5f, 0.0f), &date_bb); column_left += date_column_width; ImGui::PopFont(); @@ -3303,10 +3310,11 @@ void Achievements::DrawLeaderboardsWindow() if (ImGuiFullscreen::IsGamepadInputSource()) { const bool circleOK = ImGui::GetIO().ConfigNavSwapGamepadButtons; + const auto glyphs = ImGuiFullscreen::GetGamepadGlyphs(); ImGuiFullscreen::SetFullscreenFooterText(std::array{ - std::make_pair(ICON_PF_DPAD_LEFT_RIGHT, TRANSLATE_SV("Achievements", "Switch Rankings")), - std::make_pair(ICON_PF_DPAD_UP_DOWN, TRANSLATE_SV("Achievements", "Change Selection")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CROSS : ICON_PF_BUTTON_CIRCLE, TRANSLATE_SV("Achievements", "Back")), + std::make_pair(glyphs.dpad_lr, TRANSLATE_SV("Achievements", "Switch Rankings")), + std::make_pair(glyphs.dpad_ud, TRANSLATE_SV("Achievements", "Change Selection")), + std::make_pair(glyphs.cancel(circleOK), TRANSLATE_SV("Achievements", "Back")), }); } else @@ -3353,7 +3361,8 @@ void Achievements::DrawLeaderboardEntry(const rc_client_leaderboard_entry_t& ent ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 242, 0, 255)); const ImRect rank_bb(ImVec2(column_left, bb.Min.y), ImVec2(column_left + rank_column_width, midpoint)); - ImGui::RenderTextClipped(rank_bb.Min, rank_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &rank_bb); + ImGuiFullscreen::RenderTextClippedWithShadow( + rank_bb.Min, rank_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &rank_bb); column_left += rank_column_width + column_spacing; const ImRect icon_bb(ImVec2(column_left, bb.Min.y), ImVec2(column_left + icon_column_width, bb.Min.y + icon_column_width)); @@ -3383,16 +3392,18 @@ void Achievements::DrawLeaderboardEntry(const rc_client_leaderboard_entry_t& ent column_left += icon_column_width + column_spacing; const ImRect user_bb(ImVec2(column_left, bb.Min.y), ImVec2(column_left + name_column_width, midpoint)); - ImGui::RenderTextClipped(user_bb.Min, user_bb.Max, entry.user, nullptr, nullptr, ImVec2(0.0f, 0.0f), &user_bb); + ImGuiFullscreen::RenderTextClippedWithShadow(user_bb.Min, user_bb.Max, entry.user, nullptr, nullptr, ImVec2(0.0f, 0.0f), &user_bb); column_left += name_column_width + column_spacing; const ImRect score_bb(ImVec2(column_left, bb.Min.y), ImVec2(column_left + time_column_width, midpoint)); - ImGui::RenderTextClipped(score_bb.Min, score_bb.Max, entry.display, nullptr, nullptr, ImVec2(0.0f, 0.0f), &score_bb); + ImGuiFullscreen::RenderTextClippedWithShadow( + score_bb.Min, score_bb.Max, entry.display, nullptr, nullptr, ImVec2(0.0f, 0.0f), &score_bb); column_left += time_column_width + column_spacing; const ImRect time_bb(ImVec2(column_left, bb.Min.y), ImVec2(bb.Max.x, midpoint)); const auto submit_time = FullscreenUI::TimeToPrintableString(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); + ImGuiFullscreen::RenderTextClippedWithShadow( + 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(); @@ -3436,13 +3447,14 @@ void Achievements::DrawLeaderboardListEntry(const rc_client_leaderboard_t* lboar const ImRect summary_bb(ImVec2(text_start_x, midpoint), bb.Max); ImGui::PushFont(g_large_font.first, g_large_font.second); - ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, lboard->title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb); + ImGuiFullscreen::RenderTextClippedWithShadow(title_bb.Min, title_bb.Max, lboard->title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb); ImGui::PopFont(); if (lboard->description && lboard->description[0] != '\0') { ImGui::PushFont(g_medium_font.first, g_medium_font.second); - ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, lboard->description, nullptr, nullptr, ImVec2(0.0f, 0.0f), &summary_bb); + ImGuiFullscreen::RenderTextClippedWithShadow( + summary_bb.Min, summary_bb.Max, lboard->description, nullptr, nullptr, ImVec2(0.0f, 0.0f), &summary_bb); ImGui::PopFont(); } diff --git a/pcsx2/ImGui/FullscreenUI.cpp b/pcsx2/ImGui/FullscreenUI.cpp index e3c12eb6deb7a..c3b8aa14f00a2 100644 --- a/pcsx2/ImGui/FullscreenUI.cpp +++ b/pcsx2/ImGui/FullscreenUI.cpp @@ -68,12 +68,13 @@ void FullscreenUI::GetStandardSelectionFooterText(SmallStringBase& dest, bool ba if (IsGamepadInputSource()) { const bool circleOK = ImGui::GetIO().ConfigNavSwapGamepadButtons; + const auto glyphs = GetGamepadGlyphs(); ImGuiFullscreen::CreateFooterTextString( dest, std::array{ - std::make_pair(ICON_PF_DPAD_UP_DOWN, FSUI_VSTR("Change Selection")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CIRCLE : ICON_PF_BUTTON_CROSS, FSUI_VSTR("Select")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CROSS : ICON_PF_BUTTON_CIRCLE, back_instead_of_cancel ? FSUI_VSTR("Back") : FSUI_VSTR("Cancel")), + std::make_pair(glyphs.dpad_ud, FSUI_VSTR("Change Selection")), + std::make_pair(glyphs.confirm(circleOK), FSUI_VSTR("Select")), + std::make_pair(glyphs.cancel(circleOK), back_instead_of_cancel ? FSUI_VSTR("Back") : FSUI_VSTR("Cancel")), }); } else @@ -105,12 +106,13 @@ void ImGuiFullscreen::GetFileSelectorHelpText(SmallStringBase& dest) { const bool circleOK = ImGui::GetIO().ConfigNavSwapGamepadButtons; const bool swapNorthWest = ImGuiManager::IsGamepadNorthWestSwapped(); + const auto glyphs = GetGamepadGlyphs(); ImGuiFullscreen::CreateFooterTextString( dest, std::array{ - std::make_pair(ICON_PF_DPAD_UP_DOWN, FSUI_VSTR("Change Selection")), - std::make_pair(swapNorthWest ? ICON_PF_BUTTON_SQUARE : ICON_PF_BUTTON_TRIANGLE, FSUI_VSTR("Parent Directory")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CIRCLE : ICON_PF_BUTTON_CROSS, FSUI_VSTR("Select")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CROSS : ICON_PF_BUTTON_CIRCLE, FSUI_VSTR("Cancel")), + std::make_pair(glyphs.dpad_ud, FSUI_VSTR("Change Selection")), + std::make_pair(swapNorthWest ? glyphs.west : glyphs.north, FSUI_VSTR("Parent Directory")), + std::make_pair(glyphs.confirm(circleOK), FSUI_VSTR("Select")), + std::make_pair(glyphs.cancel(circleOK), FSUI_VSTR("Cancel")), }); } else @@ -131,10 +133,11 @@ void ImGuiFullscreen::GetInputDialogHelpText(SmallStringBase& dest) if (IsGamepadInputSource()) { const bool circleOK = ImGui::GetIO().ConfigNavSwapGamepadButtons; + const auto glyphs = GetGamepadGlyphs(); CreateFooterTextString(dest, std::array{ std::make_pair(ICON_PF_KEYBOARD, FSUI_VSTR("Enter Value")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CIRCLE : ICON_PF_BUTTON_CROSS, FSUI_VSTR("Select")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CROSS : ICON_PF_BUTTON_CIRCLE, FSUI_VSTR("Cancel")), + std::make_pair(glyphs.confirm(circleOK), FSUI_VSTR("Select")), + std::make_pair(glyphs.cancel(circleOK), FSUI_VSTR("Cancel")), }); } else @@ -157,6 +160,17 @@ void FullscreenUI::ApplyLayoutSettings(const SettingsInterface* bsi) // Check Nintendo Setting SmallString sdl2_nintendo_mode = GET_SETTINGS_VALUE(SmallString, "UI", "SDL2NintendoLayout", "false"); + // Check glyph preference + SmallString glyph_mode = GET_SETTINGS_VALUE(SmallString, "UI", "FullscreenUIGlyphStyle", "auto"); + + if (glyph_mode == "xbox") + InputManager::SetGamepadIconPreference(InputLayout::Xbox); + else if (glyph_mode == "playstation") + InputManager::SetGamepadIconPreference(InputLayout::Playstation); + else if (glyph_mode == "nintendo") + InputManager::SetGamepadIconPreference(InputLayout::Nintendo); + else + InputManager::SetGamepadIconPreference(InputLayout::Unknown); const InputLayout layout = ImGuiFullscreen::GetGamepadLayout(); @@ -1246,9 +1260,8 @@ void FullscreenUI::DrawLandingTemplate(ImVec2* menu_pos, ImVec2* menu_size) const ImVec2 logo_size = LayoutScale(LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY, LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); dl->AddImage(reinterpret_cast(GetCachedTexture("icons/AppIconLarge.png")->GetNativeHandle()), logo_pos, logo_pos + logo_size); - dl->AddText(heading_font.first, heading_font.second, - ImVec2(logo_pos.x + logo_size.x + LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING), logo_pos.y), - ImGui::GetColorU32(ImGuiCol_Text), "PCSX2"); + const ImVec2 branding_pos(logo_pos.x + logo_size.x + LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING), logo_pos.y); + ImGuiFullscreen::AddTextWithShadow(dl, heading_font, branding_pos, ImGui::GetColorU32(ImGuiCol_Text), "PCSX2"); } // draw time @@ -1269,6 +1282,8 @@ void FullscreenUI::DrawLandingTemplate(ImVec2* menu_pos, ImVec2* menu_size) const ImVec2 time_size = heading_font.first->CalcTextSizeA(heading_font.second, 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)); + ImGuiFullscreen::AddTextWithShadow( + dl, heading_font, time_pos, ImGui::GetColorU32(ImGuiCol_Text), heading_str.c_str(), heading_str.end_ptr()); ImGui::RenderTextClipped(time_pos, time_pos + time_size, heading_str.c_str(), heading_str.end_ptr(), &time_size); } @@ -1282,6 +1297,7 @@ void FullscreenUI::DrawLandingTemplate(ImVec2* menu_pos, ImVec2* menu_size) const ImVec2 name_size = heading_font.first->CalcTextSizeA(heading_font.second, 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); + ImGuiFullscreen::AddTextWithShadow(dl, heading_font, name_pos, ImGui::GetColorU32(ImGuiCol_Text), username, nullptr); ImGui::RenderTextClipped(name_pos, name_pos + name_size, username, nullptr, &name_size); // TODO: should we cache this? heap allocations bad... @@ -1358,13 +1374,14 @@ void FullscreenUI::DrawLandingWindow() { const bool circleOK = ImGui::GetIO().ConfigNavSwapGamepadButtons; const bool swapNorthWest = ImGuiManager::IsGamepadNorthWestSwapped(); + const auto glyphs = GetGamepadGlyphs(); SetFullscreenFooterText(std::array{ - std::make_pair(ICON_PF_SELECT_SHARE, FSUI_VSTR("About")), - std::make_pair(ICON_PF_DPAD_LEFT_RIGHT, FSUI_VSTR("Navigate")), - std::make_pair(swapNorthWest ? ICON_PF_BUTTON_SQUARE : ICON_PF_BUTTON_TRIANGLE, FSUI_VSTR("Game List")), - std::make_pair(swapNorthWest ? ICON_PF_BUTTON_TRIANGLE : ICON_PF_BUTTON_SQUARE, FSUI_VSTR("Toggle Fullscreen")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CIRCLE : ICON_PF_BUTTON_CROSS, FSUI_VSTR("Select")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CROSS : ICON_PF_BUTTON_CIRCLE, FSUI_VSTR("Exit")), + std::make_pair(glyphs.select, FSUI_VSTR("About")), + std::make_pair(glyphs.dpad_lr, FSUI_VSTR("Navigate")), + std::make_pair(swapNorthWest ? glyphs.west : glyphs.north, FSUI_VSTR("Game List")), + std::make_pair(swapNorthWest ? glyphs.north : glyphs.west, FSUI_VSTR("Toggle Fullscreen")), + std::make_pair(glyphs.confirm(circleOK), FSUI_VSTR("Select")), + std::make_pair(glyphs.cancel(circleOK), FSUI_VSTR("Exit")), }); } else @@ -1429,11 +1446,12 @@ void FullscreenUI::DrawStartGameWindow() { const bool circleOK = ImGui::GetIO().ConfigNavSwapGamepadButtons; const bool swapNorthWest = ImGuiManager::IsGamepadNorthWestSwapped(); + const auto glyphs = GetGamepadGlyphs(); SetFullscreenFooterText(std::array{ - std::make_pair(ICON_PF_DPAD_LEFT_RIGHT, FSUI_VSTR("Navigate")), - std::make_pair(swapNorthWest ? ICON_PF_BUTTON_TRIANGLE : ICON_PF_BUTTON_SQUARE, FSUI_VSTR("Load Global State")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CIRCLE : ICON_PF_BUTTON_CROSS, FSUI_VSTR("Select")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CROSS : ICON_PF_BUTTON_CIRCLE, FSUI_VSTR("Back")), + std::make_pair(glyphs.dpad_lr, FSUI_VSTR("Navigate")), + std::make_pair(swapNorthWest ? glyphs.north : glyphs.west, FSUI_VSTR("Load Global State")), + std::make_pair(glyphs.confirm(circleOK), FSUI_VSTR("Select")), + std::make_pair(glyphs.cancel(circleOK), FSUI_VSTR("Back")), }); } else @@ -1488,10 +1506,11 @@ void FullscreenUI::DrawExitWindow() if (IsGamepadInputSource()) { const bool circleOK = ImGui::GetIO().ConfigNavSwapGamepadButtons; + const auto glyphs = GetGamepadGlyphs(); SetFullscreenFooterText(std::array{ - std::make_pair(ICON_PF_DPAD_LEFT_RIGHT, FSUI_VSTR("Navigate")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CIRCLE : ICON_PF_BUTTON_CROSS, FSUI_VSTR("Select")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CROSS : ICON_PF_BUTTON_CIRCLE, FSUI_VSTR("Back")), + std::make_pair(glyphs.dpad_lr, FSUI_VSTR("Navigate")), + std::make_pair(glyphs.confirm(circleOK), FSUI_VSTR("Select")), + std::make_pair(glyphs.cancel(circleOK), FSUI_VSTR("Back")), }); } else @@ -1507,8 +1526,7 @@ void FullscreenUI::DrawExitWindow() static void DrawShadowedText( ImDrawList* dl, std::pair font, const ImVec2& pos, u32 col, const char* text, const char* text_end = nullptr, float wrap_width = 0.0f) { - dl->AddText(font.first, font.second, pos + LayoutScale(1.0f, 1.0f), IM_COL32(0, 0, 0, 100), text, text_end, wrap_width); - dl->AddText(font.first, font.second, pos, col, text, text_end, wrap_width); + ImGuiFullscreen::AddTextWithShadow(dl, font, pos, col, text, text_end, wrap_width); } void FullscreenUI::DrawPauseMenu(MainWindowType type) @@ -1812,10 +1830,11 @@ void FullscreenUI::DrawPauseMenu(MainWindowType type) if (IsGamepadInputSource()) { const bool circleOK = ImGui::GetIO().ConfigNavSwapGamepadButtons; + const auto glyphs = GetGamepadGlyphs(); SetFullscreenFooterText(std::array{ - std::make_pair(ICON_PF_DPAD_UP_DOWN, FSUI_VSTR("Change Selection")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CIRCLE : ICON_PF_BUTTON_CROSS, FSUI_VSTR("Select")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CROSS : ICON_PF_BUTTON_CIRCLE, FSUI_VSTR("Return To Game")), + std::make_pair(glyphs.dpad_ud, FSUI_VSTR("Change Selection")), + std::make_pair(glyphs.confirm(circleOK), FSUI_VSTR("Select")), + std::make_pair(glyphs.cancel(circleOK), FSUI_VSTR("Return To Game")), }); } else @@ -2179,7 +2198,7 @@ void FullscreenUI::DrawSaveStateSelector(bool is_loading) bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, 0); if (hovered) { - const ImU32 col = ImGui::GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered, 1.0f); + const ImU32 col = ImGui::GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered, 0.7f); const float t = std::min(std::abs(std::sin(ImGui::GetTime() * 0.75) * 1.1), 1.0f); ImGui::PushStyleColor(ImGuiCol_Border, ImGui::GetColorU32(ImGuiCol_Border, t)); @@ -2202,7 +2221,8 @@ 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 + g_large_font.second)); ImGui::PushFont(g_large_font.first, g_large_font.second); - ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, entry.title.c_str(), nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb); + ImGuiFullscreen::RenderTextClippedWithShadow( + title_bb.Min, title_bb.Max, entry.title.c_str(), nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb); ImGui::PopFont(); if (!entry.summary.empty()) @@ -2210,7 +2230,7 @@ void FullscreenUI::DrawSaveStateSelector(bool is_loading) const ImVec2 summary_pos(bb.Min.x, title_pos.y + g_large_font.second + summary_spacing); const ImRect summary_bb(summary_pos, ImVec2(bb.Max.x, summary_pos.y + g_medium_font.second)); ImGui::PushFont(g_medium_font.first, g_medium_font.second); - ImGui::RenderTextClipped( + ImGuiFullscreen::RenderTextClippedWithShadow( summary_bb.Min, summary_bb.Max, entry.summary.c_str(), nullptr, nullptr, ImVec2(0.0f, 0.0f), &summary_bb); ImGui::PopFont(); } @@ -2257,11 +2277,12 @@ void FullscreenUI::DrawSaveStateSelector(bool is_loading) { const bool circleOK = ImGui::GetIO().ConfigNavSwapGamepadButtons; const bool swapNorthWest = ImGuiManager::IsGamepadNorthWestSwapped(); + const auto glyphs = GetGamepadGlyphs(); SetFullscreenFooterText(std::array{ - std::make_pair(ICON_PF_DPAD, FSUI_VSTR("Select State")), - std::make_pair(swapNorthWest ? ICON_PF_BUTTON_TRIANGLE : ICON_PF_BUTTON_SQUARE, FSUI_VSTR("Options")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CIRCLE : ICON_PF_BUTTON_CROSS, FSUI_VSTR("Load/Save State")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CROSS : ICON_PF_BUTTON_CIRCLE, FSUI_VSTR("Cancel")), + std::make_pair(glyphs.dpad, FSUI_VSTR("Select State")), + std::make_pair(swapNorthWest ? glyphs.north : glyphs.west, FSUI_VSTR("Options")), + std::make_pair(glyphs.confirm(circleOK), FSUI_VSTR("Load/Save State")), + std::make_pair(glyphs.cancel(circleOK), FSUI_VSTR("Cancel")), }); } else @@ -2602,13 +2623,14 @@ void FullscreenUI::DrawGameListWindow() { const bool circleOK = ImGui::GetIO().ConfigNavSwapGamepadButtons; const bool swapNorthWest = ImGuiManager::IsGamepadNorthWestSwapped(); + const auto glyphs = GetGamepadGlyphs(); SetFullscreenFooterText(std::array{ - std::make_pair(ICON_PF_DPAD, FSUI_VSTR("Select Game")), - std::make_pair(ICON_PF_START, FSUI_VSTR("Settings")), - std::make_pair(swapNorthWest ? ICON_PF_BUTTON_SQUARE : ICON_PF_BUTTON_TRIANGLE, FSUI_VSTR("Change View")), - std::make_pair(swapNorthWest ? ICON_PF_BUTTON_TRIANGLE : ICON_PF_BUTTON_SQUARE, FSUI_VSTR("Launch Options")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CIRCLE : ICON_PF_BUTTON_CROSS, FSUI_VSTR("Start Game")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CROSS : ICON_PF_BUTTON_CIRCLE, FSUI_VSTR("Back")), + std::make_pair(glyphs.dpad, FSUI_VSTR("Select Game")), + std::make_pair(glyphs.start, FSUI_VSTR("Settings")), + std::make_pair(swapNorthWest ? glyphs.west : glyphs.north, FSUI_VSTR("Change View")), + std::make_pair(swapNorthWest ? glyphs.north : glyphs.west, FSUI_VSTR("Launch Options")), + std::make_pair(glyphs.confirm(circleOK), FSUI_VSTR("Start Game")), + std::make_pair(glyphs.cancel(circleOK), FSUI_VSTR("Back")), }); } else @@ -2910,12 +2932,12 @@ void FullscreenUI::DrawGameGrid(const ImVec2& heading_size) bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, 0); if (hovered) { - const ImU32 col = ImGui::GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered, 1.0f); + const ImU32 col = ImGui::GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered, 0.7f); const float t = std::min(std::abs(std::sin(ImGui::GetTime() * 0.75) * 1.1), 1.0f); ImGui::PushStyleColor(ImGuiCol_Border, ImGui::GetColorU32(ImGuiCol_Border, t)); - ImGuiFullscreen::DrawMenuButtonFrame(bb.Min, bb.Max, col, true, 0.0f); + ImGuiFullscreen::DrawMenuButtonFrame(bb.Min, bb.Max, col, true, LayoutScale(ImGuiFullscreen::LAYOUT_FRAME_ROUNDING)); ImGui::PopStyleColor(); } @@ -2935,8 +2957,8 @@ void FullscreenUI::DrawGameGrid(const ImVec2& heading_size) draw_title.clear(); fmt::format_to(std::back_inserter(draw_title), "{}{}", title, (title.length() == full_title.length()) ? "" : g_ellipsis); ImGui::PushFont(g_medium_font.first, g_medium_font.second); - ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, draw_title.c_str(), draw_title.c_str() + draw_title.length(), nullptr, - ImVec2(0.5f, 0.0f), &title_bb); + ImGuiFullscreen::RenderTextClippedWithShadow( + title_bb.Min, title_bb.Max, draw_title.c_str(), draw_title.c_str() + draw_title.length(), nullptr, ImVec2(0.5f, 0.0f), &title_bb); ImGui::PopFont(); } @@ -3379,7 +3401,7 @@ void FullscreenUI::DrawAboutWindow() ImGui::OpenPopup(FSUI_CSTR("About PCSX2")); ImGui::PushFont(g_large_font.first, g_large_font.second); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(ImGuiFullscreen::LAYOUT_WINDOW_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(30.0f, 30.0f)); if (ImGui::BeginPopupModal(FSUI_CSTR("About PCSX2"), &s_about_window_open, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize)) @@ -3387,10 +3409,18 @@ void FullscreenUI::DrawAboutWindow() const ImVec2 image_size = LayoutScale(500.0f, 76.0f); const ImRect image_bb(ImGui::GetCursorScreenPos(), ImGui::GetCursorScreenPos() + ImVec2(ImGui::GetCurrentWindow()->WorkRect.GetWidth(), image_size.y)); const ImRect image_rect(CenterImage(image_bb, image_size)); + const float start_y = ImGui::GetCursorPosY(); DrawListSvgTexture(ImGui::GetWindowDrawList(), s_banner_texture.get(), image_rect.Min, image_rect.Max); - const float indent = image_size.y + LayoutScale(12.0f); + ImGui::SetCursorPosY(start_y + image_size.y + LayoutScale(2.0f)); + static const std::string version_text = fmt::format(FSUI_FSTR("Version: {}"), BuildVersion::GitRev); + const float version_center_x = + ImGui::GetCursorPosX() + ((ImGui::GetCurrentWindow()->WorkRect.GetWidth() - ImGui::CalcTextSize(version_text.c_str()).x) * 0.5f); + ImGui::SetCursorPosX(version_center_x); + ImGui::TextUnformatted(version_text.c_str()); + + const float indent = LayoutScale(12.0f); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + indent); ImGui::TextWrapped("%s", FSUI_CSTR( "PCSX2 is a free and open-source PlayStation 2 (PS2) emulator. Its purpose is to emulate the PS2's hardware, using a " @@ -3428,10 +3458,6 @@ void FullscreenUI::DrawAboutWindow() EndMenuButtons(); - const float alignment = image_size.x + image_size.y; - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + alignment); - ImGui::TextWrapped(FSUI_CSTR("Version: %s"), BuildVersion::GitRev); - ImGui::EndPopup(); } @@ -3459,7 +3485,7 @@ void FullscreenUI::DrawAchievementsLoginWindow() ImGui::SetNextWindowSize(LayoutScale(400.0f, 330.0f)); ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(12.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(ImGuiFullscreen::LAYOUT_WINDOW_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(24.0f, 24.0f)); ImGui::PushStyleColor(ImGuiCol_PopupBg, ImVec4(0.13f, 0.13f, 0.13f, 0.95f)); @@ -3501,7 +3527,7 @@ void FullscreenUI::DrawAchievementsLoginWindow() ImGui::Spacing(); ImGui::Spacing(); - ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(8.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(ImGuiFullscreen::LAYOUT_FRAME_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(12.0f, 10.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, LayoutScale(1.0f)); ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.2f, 0.2f, 0.2f, 1.0f)); @@ -3548,7 +3574,7 @@ void FullscreenUI::DrawAchievementsLoginWindow() ImGui::SetCursorPosX(ImGui::GetCursorPosX() + start_x); - ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(8.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(ImGuiFullscreen::LAYOUT_FRAME_ROUNDING)); const bool can_login = !s_achievements_login_logging_in && strlen(s_achievements_login_username) > 0 && @@ -3856,44 +3882,65 @@ void FullscreenUI::DrawAchievementsSettingsPage(std::unique_lock& se if (!IsEditingGameSettings(bsi)) { MenuHeading(FSUI_CSTR("Sound Effects")); - if (MenuButton(FSUI_ICONSTR(ICON_FA_MUSIC, "Notification Sound"), bsi->GetTinyStringValue("Achievements", "InfoSoundName"))) - { - auto callback = [bsi](const std::string& path) { - if (!path.empty()) - { - bsi->SetStringValue("Achievements", "InfoSoundName", path.c_str()); - SetSettingsChanged(bsi); - } - CloseFileSelector(); - }; - OpenFileSelector(FSUI_ICONSTR(ICON_FA_FOLDER_OPEN, "Select Notification Sound"), false, std::move(callback), GetAudioFileFilters()); - } + const auto draw_sound_setting = [bsi](const char* title, const char* key, const char* default_filename, const char* selector_title) { + const std::string default_path = Path::Combine(EmuFolders::Resources, default_filename); + const std::optional custom_path = bsi->GetOptionalSmallStringValue("Achievements", key, std::nullopt); + const char* value = custom_path.has_value() ? custom_path->c_str() : default_path.c_str(); + if (!MenuButton(title, value)) + return; - if (MenuButton(FSUI_ICONSTR(ICON_FA_MUSIC, "Unlock Sound"), bsi->GetTinyStringValue("Achievements", "UnlockSoundName"))) - { - auto callback = [bsi](const std::string& path) { - if (!path.empty()) - { - bsi->SetStringValue("Achievements", "UnlockSoundName", path.c_str()); - SetSettingsChanged(bsi); - } - CloseFileSelector(); - }; - OpenFileSelector(FSUI_ICONSTR(ICON_FA_FOLDER_OPEN, "Select Unlock Sound"), false, std::move(callback), GetAudioFileFilters()); - } + ImGuiFullscreen::ChoiceDialogOptions options; + options.emplace_back(FSUI_ICONSTR(ICON_FA_FILE, "Select File"), false); + options.emplace_back(FSUI_ICONSTR(ICON_FA_VOLUME_HIGH, "Preview"), false); + options.emplace_back(FSUI_ICONSTR(ICON_FA_ROTATE_RIGHT, "Reset to Default"), false); + OpenChoiceDialog(title, false, std::move(options), + [bsi, key = std::string(key), selector_title = std::string(selector_title), default_path = std::move(default_path)]( + s32 index, const std::string&, bool) { + if (index == 0) + { + auto callback = [bsi, key = key](const std::string& path) { + if (!path.empty()) + { + bsi->SetStringValue("Achievements", key.c_str(), path.c_str()); + SetSettingsChanged(bsi); + } + CloseFileSelector(); + }; + OpenFileSelector(selector_title.c_str(), false, std::move(callback), GetAudioFileFilters()); + } + else if (index == 1) + { + const TinyString preview_path = bsi->GetTinyStringValue("Achievements", key.c_str(), default_path.c_str()); + if (!Common::PlaySoundAsync(preview_path.c_str())) + { + ShowToast(std::string(), + fmt::format(FSUI_FSTR("Failed to preview sound:\n{}"), + preview_path.empty() ? FSUI_STR("No file selected.") : preview_path.c_str())); + } + } + else if (index == 2) + { + if (bsi->ContainsValue("Achievements", key.c_str())) + { + bsi->DeleteValue("Achievements", key.c_str()); + SetSettingsChanged(bsi); + ShowToast(std::string(), FSUI_STR("Sound reset to default.")); + } + else + { + ShowToast(std::string(), FSUI_STR("Sound is already using default.")); + } + } + CloseChoiceDialog(); + }); + }; - if (MenuButton(FSUI_ICONSTR(ICON_FA_MUSIC, "Leaderboard Submit Sound"), bsi->GetTinyStringValue("Achievements", "LBSubmitSoundName"))) - { - auto callback = [bsi](const std::string& path) { - if (!path.empty()) - { - bsi->SetStringValue("Achievements", "LBSubmitSoundName", path.c_str()); - SetSettingsChanged(bsi); - } - CloseFileSelector(); - }; - OpenFileSelector(FSUI_ICONSTR(ICON_FA_FOLDER_OPEN, "Select Leaderboard Submit Sound"), false, std::move(callback), GetAudioFileFilters()); - } + draw_sound_setting(FSUI_ICONSTR(ICON_FA_MUSIC, "Notification Sound"), "InfoSoundName", "sounds/achievements/message.wav", + FSUI_ICONSTR(ICON_FA_FOLDER_OPEN, "Select Notification Sound")); + draw_sound_setting(FSUI_ICONSTR(ICON_FA_MUSIC, "Unlock Sound"), "UnlockSoundName", "sounds/achievements/unlock.wav", + FSUI_ICONSTR(ICON_FA_FOLDER_OPEN, "Select Unlock Sound")); + draw_sound_setting(FSUI_ICONSTR(ICON_FA_MUSIC, "Leaderboard Submit Sound"), "LBSubmitSoundName", + "sounds/achievements/lbsubmit.wav", FSUI_ICONSTR(ICON_FA_FOLDER_OPEN, "Select Leaderboard Submit Sound")); MenuHeading(FSUI_CSTR("Account")); if (bsi->ContainsValue("Achievements", "Token")) diff --git a/pcsx2/ImGui/FullscreenUI_Internal.h b/pcsx2/ImGui/FullscreenUI_Internal.h index e51db5ff468bc..cd87dca0a6537 100644 --- a/pcsx2/ImGui/FullscreenUI_Internal.h +++ b/pcsx2/ImGui/FullscreenUI_Internal.h @@ -70,6 +70,8 @@ using ImGuiFullscreen::GetCachedSvgTexture; using ImGuiFullscreen::GetCachedSvgTextureAsync; using ImGuiFullscreen::GetCachedTexture; using ImGuiFullscreen::GetCachedTextureAsync; +using ImGuiFullscreen::GamepadGlyphs; +using ImGuiFullscreen::GetGamepadGlyphs; using ImGuiFullscreen::GetLineHeight; using ImGuiFullscreen::GetPlaceholderTexture; using ImGuiFullscreen::GetQueuedFocusResetType; diff --git a/pcsx2/ImGui/FullscreenUI_Settings.cpp b/pcsx2/ImGui/FullscreenUI_Settings.cpp index daf661628ea5f..ebb228ac7b117 100644 --- a/pcsx2/ImGui/FullscreenUI_Settings.cpp +++ b/pcsx2/ImGui/FullscreenUI_Settings.cpp @@ -340,8 +340,9 @@ void FullscreenUI::DrawInputBindingButton( if (ImGuiFullscreen::IsGamepadInputSource()) { const bool swapNorthWest = ImGuiManager::IsGamepadNorthWestSwapped(); + const auto glyphs = GetGamepadGlyphs(); ImGuiFullscreen::QueueFooterHint(std::array{ - std::make_pair(swapNorthWest ? ICON_PF_BUTTON_TRIANGLE : ICON_PF_BUTTON_SQUARE, FSUI_VSTR("Clear Binding")), + std::make_pair(swapNorthWest ? glyphs.north : glyphs.west, FSUI_VSTR("Clear Binding")), }); } else @@ -464,7 +465,7 @@ void FullscreenUI::DrawInputBindingWindow() ImGui::OpenPopup(title); ImGui::PushFont(g_large_font.first, g_large_font.second); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(ImGuiFullscreen::LAYOUT_WINDOW_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(20.0f, 20.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, @@ -585,7 +586,7 @@ void FullscreenUI::DrawIntRangeSetting(SettingsInterface* bsi, const char* title ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); ImGui::PushFont(g_large_font.first, g_large_font.second); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(ImGuiFullscreen::LAYOUT_WINDOW_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(20.0f, 20.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, @@ -600,7 +601,7 @@ void FullscreenUI::DrawIntRangeSetting(SettingsInterface* bsi, const char* title ImGui::SetNextItemWidth(end); s32 dlg_value = static_cast(value.value_or(default_value)); - ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(8.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(ImGuiFullscreen::LAYOUT_FRAME_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, LayoutScale(1.0f)); ImGui::PushStyleVar(ImGuiStyleVar_GrabRounding, LayoutScale(8.0f)); ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.2f, 0.2f, 0.2f, 1.0f)); @@ -660,7 +661,7 @@ void FullscreenUI::DrawIntSpinBoxSetting(SettingsInterface* bsi, const char* tit ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); ImGui::PushFont(g_large_font.first, g_large_font.second); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(ImGuiFullscreen::LAYOUT_WINDOW_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(20.0f, 20.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, @@ -682,7 +683,7 @@ void FullscreenUI::DrawIntSpinBoxSetting(SettingsInterface* bsi, const char* tit const float end = ImGui::GetCurrentWindow()->WorkRect.GetWidth(); ImGui::SetNextItemWidth(end); - ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(8.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(ImGuiFullscreen::LAYOUT_FRAME_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(12.0f, 10.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, LayoutScale(1.0f)); ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.2f, 0.2f, 0.2f, 1.0f)); @@ -786,7 +787,7 @@ void FullscreenUI::DrawFloatRangeSetting(SettingsInterface* bsi, const char* tit ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); ImGui::PushFont(g_large_font.first, g_large_font.second); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(ImGuiFullscreen::LAYOUT_WINDOW_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(20.0f, 20.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, @@ -801,7 +802,7 @@ void FullscreenUI::DrawFloatRangeSetting(SettingsInterface* bsi, const char* tit ImGui::SetNextItemWidth(end); float dlg_value = value.value_or(default_value) * multiplier; - ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(8.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(ImGuiFullscreen::LAYOUT_FRAME_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, LayoutScale(1.0f)); ImGui::PushStyleVar(ImGuiStyleVar_GrabRounding, LayoutScale(8.0f)); ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.2f, 0.2f, 0.2f, 1.0f)); @@ -863,7 +864,7 @@ void FullscreenUI::DrawFloatSpinBoxSetting(SettingsInterface* bsi, const char* t ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); ImGui::PushFont(g_large_font.first, g_large_font.second); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(ImGuiFullscreen::LAYOUT_WINDOW_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(20.0f, 20.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, @@ -892,7 +893,7 @@ void FullscreenUI::DrawFloatSpinBoxSetting(SettingsInterface* bsi, const char* t ((tmp_value.value() - std::floor(tmp_value.value())) < 0.01f) ? "%.0f" : "%f", tmp_value.value()); } - ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(8.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(ImGuiFullscreen::LAYOUT_FRAME_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(12.0f, 10.0f)); ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.2f, 0.2f, 0.2f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(0.25f, 0.25f, 0.25f, 1.0f)); @@ -1009,7 +1010,7 @@ void FullscreenUI::DrawIntRectSetting(SettingsInterface* bsi, const char* title, ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); ImGui::PushFont(g_large_font.first, g_large_font.second); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(ImGuiFullscreen::LAYOUT_WINDOW_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(20.0f, 20.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, @@ -1074,7 +1075,7 @@ void FullscreenUI::DrawIntRectSetting(SettingsInterface* bsi, const char* title, ImGui::SetNextItemWidth(end); ImGui::SetCursorPosY(button_pos.y); - ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(8.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(ImGuiFullscreen::LAYOUT_FRAME_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(12.0f, 10.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, LayoutScale(1.0f)); ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.2f, 0.2f, 0.2f, 1.0f)); @@ -2014,11 +2015,12 @@ void FullscreenUI::DrawSettingsWindow() if (IsGamepadInputSource()) { const bool circleOK = ImGui::GetIO().ConfigNavSwapGamepadButtons; + const auto glyphs = GetGamepadGlyphs(); SetFullscreenFooterText(std::array{ - std::make_pair(ICON_PF_DPAD_LEFT_RIGHT, FSUI_VSTR("Change Page")), - std::make_pair(ICON_PF_DPAD_UP_DOWN, FSUI_VSTR("Navigate")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CIRCLE : ICON_PF_BUTTON_CROSS, FSUI_VSTR("Select")), - std::make_pair(circleOK ? ICON_PF_BUTTON_CROSS : ICON_PF_BUTTON_CIRCLE, FSUI_VSTR("Back")), + std::make_pair(glyphs.dpad_lr, FSUI_VSTR("Change Page")), + std::make_pair(glyphs.dpad_ud, FSUI_VSTR("Navigate")), + std::make_pair(glyphs.confirm(circleOK), FSUI_VSTR("Select")), + std::make_pair(glyphs.cancel(circleOK), FSUI_VSTR("Back")), }); } else @@ -2282,6 +2284,51 @@ void FullscreenUI::DrawInterfaceSettingsPage() DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_BOX_ARCHIVE, "Create Save State Backups"), FSUI_CSTR("Creates a backup copy of a save state if it already exists when the save is created. The backup copy has a .backup suffix"), "EmuCore", "BackupSavestate", true); + const SmallString glyph_mode = bsi->GetSmallStringValue("UI", "FullscreenUIGlyphStyle", "auto"); + static constexpr const char* glyph_names[] = { + FSUI_NSTR("Automatic"), + FSUI_NSTR("Xbox"), + FSUI_NSTR("PlayStation"), + FSUI_NSTR("Nintendo"), + }; + static constexpr const char* glyph_values[] = { + "auto", + "xbox", + "playstation", + "nintendo", + }; + size_t glyph_index = std::size(glyph_values); + for (size_t i = 0; i < std::size(glyph_values); i++) + { + if (glyph_mode == glyph_values[i]) + { + glyph_index = i; + break; + } + } + if (MenuButtonWithValue(FSUI_ICONSTR(ICON_FA_GAMEPAD, "Controller Glyph Style"), + FSUI_CSTR("Changes which gamepad button glyph set is used in Big Picture UI and input binding displays."), + (glyph_index < std::size(glyph_values)) ? FSUI_CSTR(glyph_names[glyph_index]) : FSUI_CSTR("Unknown"))) + { + ImGuiFullscreen::ChoiceDialogOptions cd_options; + cd_options.reserve(std::size(glyph_values)); + for (size_t i = 0; i < std::size(glyph_values); i++) + cd_options.emplace_back(FSUI_STR(glyph_names[i]), i == static_cast(glyph_index)); + + OpenChoiceDialog(FSUI_ICONSTR(ICON_FA_GAMEPAD, "Controller Glyph Style"), false, std::move(cd_options), [](s32 index, const std::string& title, bool checked) { + if (index >= 0 && static_cast(index) < std::size(glyph_values)) + { + auto lock = Host::GetSettingsLock(); + SettingsInterface* bsi = GetEditingSettingsInterface(false); + bsi->SetStringValue("UI", "FullscreenUIGlyphStyle", glyph_values[index]); + SetSettingsChanged(bsi); + ApplyLayoutSettings(bsi); + } + + CloseChoiceDialog(); + }); + } + // DrawStringListSetting dosn't have a callback for applying settings const SmallString swap_mode = bsi->GetSmallStringValue("UI", "SwapOKFullscreenUI", "auto"); static constexpr const char* swap_names[] = { @@ -2305,9 +2352,11 @@ void FullscreenUI::DrawInterfaceSettingsPage() } SmallStackString<256> swap_summery; - swap_summery.format(FSUI_FSTR("Uses {} as confirm when using a controller."), ICON_PF_BUTTON_CIRCLE); + const auto glyphs = GetGamepadGlyphs(); + swap_summery.format(FSUI_FSTR("Uses {} as confirm when using a controller."), + glyphs.confirm(ImGui::GetIO().ConfigNavSwapGamepadButtons)); if (MenuButtonWithValue(FSUI_ICONSTR(ICON_FA_GAMEPAD, "Swap OK/Cancel in Big Picture Mode"), swap_summery.c_str(), - (swap_index < std::size(swap_values)) ? Host::TranslateToCString(TR_CONTEXT, swap_names[swap_index]) : FSUI_CSTR("Unknown"))) + (swap_index < std::size(swap_values)) ? FSUI_CSTR(swap_names[swap_index]) : FSUI_CSTR("Unknown"))) { ImGuiFullscreen::ChoiceDialogOptions cd_options; cd_options.reserve(std::size(swap_values)); @@ -2338,9 +2387,10 @@ void FullscreenUI::DrawInterfaceSettingsPage() break; } } - swap_summery.format(FSUI_FSTR("Swaps both {}/{} (When Swap OK/Cancel is set to automatic) and {}/{} buttons"), ICON_PF_BUTTON_CROSS, ICON_PF_BUTTON_CIRCLE, ICON_PF_BUTTON_SQUARE, ICON_PF_BUTTON_TRIANGLE); + swap_summery.format(FSUI_FSTR("Swaps both {}/{} (When Swap OK/Cancel is set to automatic) and {}/{} buttons"), + glyphs.south, glyphs.east, glyphs.west, glyphs.north); if (MenuButtonWithValue(FSUI_ICONSTR(ICON_FA_GAMEPAD, "Use Legacy Nintendo Layout in Big Picture Mode"), swap_summery.c_str(), - (nintendo_index < std::size(swap_values)) ? Host::TranslateToCString(TR_CONTEXT, swap_names[nintendo_index]) : FSUI_CSTR("Unknown"))) + (nintendo_index < std::size(swap_values)) ? FSUI_CSTR(swap_names[nintendo_index]) : FSUI_CSTR("Unknown"))) { ImGuiFullscreen::ChoiceDialogOptions cd_options; cd_options.reserve(std::size(swap_values)); @@ -3071,79 +3121,79 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad FSUI_NSTR("Enabled (Check Inside Target)"), }; - DrawIntListSetting(bsi, FSUI_CSTR("CPU Sprite Render Size"), + DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_SHAPES, "CPU Sprite Render Size"), FSUI_CSTR("Uses software renderer to draw texture decompression-like sprites."), "EmuCore/GS", "UserHacks_CPUSpriteRenderBW", 0, s_cpu_sprite_render_bw_options, std::size(s_cpu_sprite_render_bw_options), true); - DrawIntListSetting(bsi, FSUI_CSTR("CPU Sprite Render Level"), FSUI_CSTR("Determines filter level for CPU sprite render."), + DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_SHAPES, "CPU Sprite Render Level"), FSUI_CSTR("Determines filter level for CPU sprite render."), "EmuCore/GS", "UserHacks_CPUSpriteRenderLevel", 0, s_cpu_sprite_render_level_options, std::size(s_cpu_sprite_render_level_options), true); - DrawIntListSetting(bsi, FSUI_CSTR("Software CLUT Render"), + DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_PALETTE, "Software CLUT Render"), FSUI_CSTR("Uses software renderer to draw texture CLUT points/sprites."), "EmuCore/GS", "UserHacks_CPUCLUTRender", 0, s_cpu_clut_render_options, std::size(s_cpu_clut_render_options), true); - DrawIntListSetting(bsi, FSUI_CSTR("GPU Target CLUT"), + DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_PALETTE, "GPU Target CLUT"), FSUI_CSTR("Try to detect when a game is drawing its own color palette and then renders it on the GPU with special handling."), "EmuCore/GS", "UserHacks_GPUTargetCLUTMode", 0, s_gpu_clut_options, std::size(s_gpu_clut_options), true, 0, manual_hw_fixes); - DrawIntSpinBoxSetting(bsi, FSUI_CSTR("Skip Draw Start"), FSUI_CSTR("Object range to skip drawing."), "EmuCore/GS", + DrawIntSpinBoxSetting(bsi, FSUI_ICONSTR(ICON_FA_FORWARD, "Skip Draw Start"), FSUI_CSTR("Object range to skip drawing."), "EmuCore/GS", "UserHacks_SkipDraw_Start", 0, 0, 5000, 1); - DrawIntSpinBoxSetting(bsi, FSUI_CSTR("Skip Draw End"), FSUI_CSTR("Object range to skip drawing."), "EmuCore/GS", + DrawIntSpinBoxSetting(bsi, FSUI_ICONSTR(ICON_FA_FORWARD_STEP, "Skip Draw End"), FSUI_CSTR("Object range to skip drawing."), "EmuCore/GS", "UserHacks_SkipDraw_End", 0, 0, 5000, 1); - DrawIntListSetting(bsi, FSUI_CSTR("Auto Flush (Hardware)"), + DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_BROOM, "Auto Flush (Hardware)"), FSUI_CSTR("Force a primitive flush when a framebuffer is also an input texture."), "EmuCore/GS", "UserHacks_AutoFlushLevel", 0, s_auto_flush_options, std::size(s_auto_flush_options), true, 0, manual_hw_fixes); - DrawToggleSetting(bsi, FSUI_CSTR("CPU Framebuffer Conversion"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_MICROCHIP, "CPU Framebuffer Conversion"), FSUI_CSTR("Convert 4-bit and 8-bit framebuffer on the CPU instead of the GPU."), "EmuCore/GS", "UserHacks_CPU_FB_Conversion", false, manual_hw_fixes); - DrawToggleSetting(bsi, FSUI_CSTR("Disable Depth Conversion"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_BAN, "Disable Depth Conversion"), FSUI_CSTR("Disable the support of depth buffers in the texture cache."), "EmuCore/GS", "UserHacks_DisableDepthSupport", false, manual_hw_fixes); - DrawToggleSetting(bsi, FSUI_CSTR("Disable Safe Features"), FSUI_CSTR("This option disables multiple safe features."), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_BAN, "Disable Safe Features"), FSUI_CSTR("This option disables multiple safe features."), "EmuCore/GS", "UserHacks_Disable_Safe_Features", false, manual_hw_fixes); - DrawToggleSetting(bsi, FSUI_CSTR("Disable Render Fixes"), FSUI_CSTR("This option disables game-specific render fixes."), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_BAN, "Disable Render Fixes"), FSUI_CSTR("This option disables game-specific render fixes."), "EmuCore/GS", "UserHacks_DisableRenderFixes", false, manual_hw_fixes); - DrawToggleSetting(bsi, FSUI_CSTR("Preload Frame Data"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_DOWNLOAD, "Preload Frame Data"), FSUI_CSTR("Uploads GS data when rendering a new frame to reproduce some effects accurately."), "EmuCore/GS", "preload_frame_with_gs_data", false, manual_hw_fixes); - DrawToggleSetting(bsi, FSUI_CSTR("Disable Partial Invalidation"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_BAN, "Disable Partial Invalidation"), FSUI_CSTR("Removes texture cache entries when there is any intersection, rather than only the intersected areas."), "EmuCore/GS", "UserHacks_DisablePartialInvalidation", false, manual_hw_fixes); - DrawIntListSetting(bsi, FSUI_CSTR("Texture Inside RT"), + DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_BOX_OPEN, "Texture Inside RT"), FSUI_CSTR("Allows the texture cache to reuse as an input texture the inner portion of a previous framebuffer."), "EmuCore/GS", "UserHacks_TextureInsideRt", 0, s_texture_inside_rt_options, std::size(s_texture_inside_rt_options), true, 0, manual_hw_fixes); - DrawToggleSetting(bsi, FSUI_CSTR("Read Targets When Closing"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_DOOR_CLOSED, "Read Targets When Closing"), FSUI_CSTR("Flushes all targets in the texture cache back to local memory when shutting down."), "EmuCore/GS", "UserHacks_ReadTCOnClose", false, manual_hw_fixes); - DrawToggleSetting(bsi, FSUI_CSTR("Estimate Texture Region"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_CROP, "Estimate Texture Region"), FSUI_CSTR("Attempts to reduce the texture size when games do not set it themselves (e.g. Snowblind games)."), "EmuCore/GS", "UserHacks_EstimateTextureRegion", false, manual_hw_fixes); - DrawToggleSetting(bsi, FSUI_CSTR("GPU Palette Conversion"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_PALETTE, "GPU Palette Conversion"), FSUI_CSTR("When enabled GPU converts colormap-textures, otherwise the CPU will. It is a trade-off between GPU and CPU."), "EmuCore/GS", "paltex", false, manual_hw_fixes); MenuHeading(FSUI_CSTR("Upscaling Fixes")); - DrawIntListSetting(bsi, FSUI_CSTR("Half Pixel Offset"), FSUI_CSTR("Adjusts vertices relative to upscaling."), "EmuCore/GS", + DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_ARROWS_UP_DOWN_LEFT_RIGHT, "Half Pixel Offset"), FSUI_CSTR("Adjusts vertices relative to upscaling."), "EmuCore/GS", "UserHacks_HalfPixelOffset", 0, s_half_pixel_offset_options, std::size(s_half_pixel_offset_options), true); - DrawIntListSetting(bsi, FSUI_CSTR("Native Scaling"), FSUI_CSTR("Attempt to do rescaling at native resolution."), "EmuCore/GS", + DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_COMPRESS, "Native Scaling"), FSUI_CSTR("Attempt to do rescaling at native resolution."), "EmuCore/GS", "UserHacks_native_scaling", 0, s_native_scaling_options, std::size(s_native_scaling_options), true); - DrawIntListSetting(bsi, FSUI_CSTR("Round Sprite"), FSUI_CSTR("Adjusts sprite coordinates."), "EmuCore/GS", + DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_CIRCLE, "Round Sprite"), FSUI_CSTR("Adjusts sprite coordinates."), "EmuCore/GS", "UserHacks_round_sprite_offset", 0, s_round_sprite_options, std::size(s_round_sprite_options), true); - DrawIntListSetting(bsi, FSUI_CSTR("Bilinear Dirty Upscale"), + DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_BRUSH, "Bilinear Dirty Upscale"), FSUI_CSTR("Can smooth out textures due to be bilinear filtered when upscaling. E.g. Brave sun glare."), "EmuCore/GS", "UserHacks_BilinearHack", static_cast(GSBilinearDirtyMode::Automatic), s_bilinear_dirty_options, std::size(s_bilinear_dirty_options), true); - DrawIntSpinBoxSetting(bsi, FSUI_CSTR("Texture Offset X"), FSUI_CSTR("Adjusts target texture offsets."), "EmuCore/GS", + DrawIntSpinBoxSetting(bsi, FSUI_ICONSTR(ICON_FA_ARROWS_LEFT_RIGHT, "Texture Offset X"), FSUI_CSTR("Adjusts target texture offsets."), "EmuCore/GS", "UserHacks_TCOffsetX", 0, -4096, 4096, 1); - DrawIntSpinBoxSetting(bsi, FSUI_CSTR("Texture Offset Y"), FSUI_CSTR("Adjusts target texture offsets."), "EmuCore/GS", + DrawIntSpinBoxSetting(bsi, FSUI_ICONSTR(ICON_FA_ARROWS_UP_DOWN, "Texture Offset Y"), FSUI_CSTR("Adjusts target texture offsets."), "EmuCore/GS", "UserHacks_TCOffsetY", 0, -4096, 4096, 1); - DrawToggleSetting(bsi, FSUI_CSTR("Align Sprite"), FSUI_CSTR("Fixes issues with upscaling (vertical lines) in some games."), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_ALIGN_CENTER, "Align Sprite"), FSUI_CSTR("Fixes issues with upscaling (vertical lines) in some games."), "EmuCore/GS", "UserHacks_align_sprite_X", false, manual_hw_fixes); - DrawToggleSetting(bsi, FSUI_CSTR("Merge Sprite"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_COMPRESS, "Merge Sprite"), FSUI_CSTR("Replaces multiple post-processing sprites with a larger single sprite."), "EmuCore/GS", "UserHacks_merge_pp_sprite", false, manual_hw_fixes); - DrawToggleSetting(bsi, FSUI_CSTR("Force Even Sprite Position"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_ALIGN_CENTER, "Force Even Sprite Position"), FSUI_CSTR("Lowers the GS precision to avoid gaps between pixels when upscaling. Fixes the text on Wild Arms games."), "EmuCore/GS", "UserHacks_ForceEvenSpritePosition", false, manual_hw_fixes); - DrawToggleSetting(bsi, FSUI_CSTR("Unscaled Palette Texture Draws"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_PALETTE, "Unscaled Palette Texture Draws"), FSUI_CSTR("Can fix some broken effects which rely on pixel perfect precision."), "EmuCore/GS", "UserHacks_NativePaletteDraw", false, manual_hw_fixes); } @@ -3206,7 +3256,7 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad "ShadeBoost_Brightness", 50, 1, 100, "%d", shadeboost_active); DrawIntRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_LIGHTBULB, "Shade Boost Contrast"), FSUI_CSTR("Adjusts contrast. 50 is normal."), "EmuCore/GS", "ShadeBoost_Contrast", 50, 1, 100, "%d", shadeboost_active); - DrawIntRangeSetting(bsi, FSUI_CSTR("Shade Boost Gamma"), FSUI_CSTR("Adjusts gamma. 50 is normal."), "EmuCore/GS", + DrawIntRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_DROPLET_SLASH, "Shade Boost Gamma"), FSUI_CSTR("Adjusts gamma. 50 is normal."), "EmuCore/GS", "ShadeBoost_Gamma", 50, 1, 100, "%d", shadeboost_active); DrawIntRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_DROPLET, "Shade Boost Saturation"), FSUI_CSTR("Adjusts saturation. 50 is normal."), "EmuCore/GS", "ShadeBoost_Saturation", 50, 1, 100, "%d", shadeboost_active); @@ -3234,11 +3284,11 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad if (show_advanced_settings) { MenuHeading(FSUI_CSTR("Advanced")); - DrawToggleSetting(bsi, FSUI_CSTR("Skip Presenting Duplicate Frames"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_FORWARD, "Skip Presenting Duplicate Frames"), FSUI_CSTR("Skips displaying frames that don't change in 25/30fps games. Can improve speed, but increase input lag/make frame pacing " "worse."), "EmuCore/GS", "SkipDuplicateFrames", false); - DrawToggleSetting(bsi, FSUI_CSTR("Disable Mailbox Presentation"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_ENVELOPE, "Disable Mailbox Presentation"), FSUI_CSTR("Forces the use of FIFO over Mailbox presentation, i.e. double buffering instead of triple buffering. " "Usually results in worse frame pacing."), "EmuCore/GS", "DisableMailboxPresentation", false); @@ -3247,33 +3297,33 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad "EmuCore/GS", "ExtendedUpscalingMultipliers", false, supports_extended_upscales); if (IsEditingGameSettings(bsi)) { - DrawIntListSetting(bsi, FSUI_CSTR("Hardware Download Mode"), FSUI_CSTR("Changes synchronization behavior for GS downloads."), + DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_MICROCHIP, "Hardware Download Mode"), FSUI_CSTR("Changes synchronization behavior for GS downloads."), "EmuCore/GS", "HWDownloadMode", static_cast(GSHardwareDownloadMode::Enabled), s_hw_download, std::size(s_hw_download), true); } - DrawIntListSetting(bsi, FSUI_CSTR("Allow Exclusive Fullscreen"), + DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_EXPAND, "Allow Exclusive Fullscreen"), FSUI_CSTR("Overrides the driver's heuristics for enabling exclusive fullscreen, or direct flip/scanout."), "EmuCore/GS", "ExclusiveFullscreenControl", -1, s_generic_options, std::size(s_generic_options), true, -1, (renderer == GSRendererType::Auto || renderer == GSRendererType::VK)); - DrawIntListSetting(bsi, FSUI_CSTR("Override Texture Barriers"), + DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_SHIELD_HALVED, "Override Texture Barriers"), FSUI_CSTR("Forces texture barrier functionality to the specified value."), "EmuCore/GS", "OverrideTextureBarriers", -1, s_generic_options, std::size(s_generic_options), true, -1); - DrawIntListSetting(bsi, FSUI_CSTR("GS Dump Compression"), FSUI_CSTR("Sets the compression algorithm for GS dumps."), "EmuCore/GS", + DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_FILE_ZIPPER, "GS Dump Compression"), FSUI_CSTR("Sets the compression algorithm for GS dumps."), "EmuCore/GS", "GSDumpCompression", static_cast(GSDumpCompressionMethod::LZMA), s_gsdump_compression, std::size(s_gsdump_compression), true); - DrawToggleSetting(bsi, FSUI_CSTR("Disable Framebuffer Fetch"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_BAN, "Disable Framebuffer Fetch"), FSUI_CSTR("Prevents the usage of framebuffer fetch when supported by host GPU."), "EmuCore/GS", "DisableFramebufferFetch", false); - DrawToggleSetting(bsi, FSUI_CSTR("Disable Shader Cache"), FSUI_CSTR("Prevents the loading and saving of shaders/pipelines to disk."), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_BAN, "Disable Shader Cache"), FSUI_CSTR("Prevents the loading and saving of shaders/pipelines to disk."), "EmuCore/GS", "DisableShaderCache", false); - DrawToggleSetting(bsi, FSUI_CSTR("Disable Vertex Shader Expand"), FSUI_CSTR("Falls back to the CPU for expanding sprites/lines."), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_BAN, "Disable Vertex Shader Expand"), FSUI_CSTR("Falls back to the CPU for expanding sprites/lines."), "EmuCore/GS", "DisableVertexShaderExpand", false); - DrawIntListSetting(bsi, FSUI_CSTR("Texture Preloading"), + DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_DOWNLOAD, "Texture Preloading"), FSUI_CSTR( "Uploads full textures to the GPU on use, rather than only the utilized regions. Can improve performance in some games."), "EmuCore/GS", "texture_preloading", static_cast(TexturePreloadingLevel::Off), s_preloading_options, std::size(s_preloading_options), true); - DrawFloatRangeSetting(bsi, FSUI_CSTR("NTSC Frame Rate"), FSUI_CSTR("Determines what frame rate NTSC games run at."), + DrawFloatRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_TV, "NTSC Frame Rate"), FSUI_CSTR("Determines what frame rate NTSC games run at."), "EmuCore/GS", "FrameRateNTSC", 59.94f, 10.0f, 300.0f, "%.2f Hz"); - DrawFloatRangeSetting(bsi, FSUI_CSTR("PAL Frame Rate"), FSUI_CSTR("Determines what frame rate PAL games run at."), + DrawFloatRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_TV, "PAL Frame Rate"), FSUI_CSTR("Determines what frame rate PAL games run at."), "EmuCore/GS", "FrameRatePAL", 50.0f, 10.0f, 300.0f, "%.2f Hz"); } @@ -3349,7 +3399,7 @@ void FullscreenUI::DrawOSDSettingsPage() if (osd_font_value.has_value() && !osd_font_value->empty()) { - if (MenuButton(FSUI_CSTR("Clear OSD Font Override"), FSUI_CSTR("Use default bundled font"))) + if (MenuButton(FSUI_ICONSTR(ICON_FA_XMARK, "Clear OSD Font Override"), FSUI_CSTR("Use default bundled font"))) { SettingsInterface* ebsi = bsi; ebsi->DeleteValue("EmuCore/GS", "OsdFontPath"); @@ -4599,7 +4649,7 @@ void FullscreenUI::DrawControllerSettingsPage() ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f)); ImGui::PushFont(g_large_font.first, g_large_font.second); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(ImGuiFullscreen::LAYOUT_WINDOW_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(20.0f, 20.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, @@ -4609,7 +4659,7 @@ void FullscreenUI::DrawControllerSettingsPage() freq_label.c_str(), nullptr, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove)) { ImGui::SetNextItemWidth(LayoutScale(450.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(8.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(ImGuiFullscreen::LAYOUT_FRAME_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, LayoutScale(1.0f)); ImGui::PushStyleVar(ImGuiStyleVar_GrabRounding, LayoutScale(8.0f)); ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.2f, 0.2f, 0.2f, 1.0f)); @@ -4950,7 +5000,7 @@ void FullscreenUI::DrawPatchesOrCheatsSettingsPage(bool cheats) { MenuHeading(FSUI_CSTR("Settings")); DrawToggleSetting( - bsi, FSUI_CSTR("Enable Cheats"), FSUI_CSTR("Enables loading cheats from pnach files."), "EmuCore", "EnableCheats", false); + bsi, FSUI_ICONSTR(ICON_FA_WAND_MAGIC_SPARKLES, "Enable Cheats"), FSUI_CSTR("Enables loading cheats from pnach files."), "EmuCore", "EnableCheats", false); if (patch_list.empty()) { @@ -5030,45 +5080,45 @@ void FullscreenUI::DrawGameFixesSettingsPage() FSUI_CSTR("Game fixes should not be modified unless you are aware of what each option does and the implications of doing so."), false, false, ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT_NO_SUMMARY); - DrawToggleSetting(bsi, FSUI_CSTR("FPU Multiply Hack"), FSUI_CSTR("For Tales of Destiny."), "EmuCore/Gamefixes", "FpuMulHack", false); - DrawToggleSetting(bsi, FSUI_CSTR("Use Software Renderer For FMVs"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_WRENCH, "FPU Multiply Hack"), FSUI_CSTR("For Tales of Destiny."), "EmuCore/Gamefixes", "FpuMulHack", false); + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_MICROCHIP, "Use Software Renderer For FMVs"), FSUI_CSTR("Needed for some games with complex FMV rendering."), "EmuCore/Gamefixes", "SoftwareRendererFMVHack", false); - DrawToggleSetting(bsi, FSUI_CSTR("Skip MPEG Hack"), FSUI_CSTR("Skips videos/FMVs in games to avoid game hanging/freezes."), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_FORWARD_FAST, "Skip MPEG Hack"), FSUI_CSTR("Skips videos/FMVs in games to avoid game hanging/freezes."), "EmuCore/Gamefixes", "SkipMPEGHack", false); DrawToggleSetting( - bsi, FSUI_CSTR("Preload TLB Hack"), FSUI_CSTR("To avoid TLB miss on Goemon."), "EmuCore/Gamefixes", "GoemonTlbHack", false); - DrawToggleSetting(bsi, FSUI_CSTR("EE Timing Hack"), + bsi, FSUI_ICONSTR(ICON_FA_MEMORY, "Preload TLB Hack"), FSUI_CSTR("To avoid TLB miss on Goemon."), "EmuCore/Gamefixes", "GoemonTlbHack", false); + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_CLOCK, "EE Timing Hack"), FSUI_CSTR("General-purpose timing hack. Known to affect following games: Digital Devil Saga, SSX."), "EmuCore/Gamefixes", "EETimingHack", false); - DrawToggleSetting(bsi, FSUI_CSTR("Instant DMA Hack"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_BOLT, "Instant DMA Hack"), FSUI_CSTR("Good for cache emulation problems. Known to affect following games: Fire Pro Wrestling Z."), "EmuCore/Gamefixes", "InstantDMAHack", false); - DrawToggleSetting(bsi, FSUI_CSTR("OPH Flag Hack"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_FLAG, "OPH Flag Hack"), FSUI_CSTR("Known to affect following games: Bleach Blade Battlers, Growlanser II and III, Wizardry."), "EmuCore/Gamefixes", "OPHFlagHack", false); DrawToggleSetting( - bsi, FSUI_CSTR("Emulate GIF FIFO"), FSUI_CSTR("Correct but slower. Known to affect the following games: FIFA Street 2."), "EmuCore/Gamefixes", "GIFFIFOHack", false); - DrawToggleSetting(bsi, FSUI_CSTR("DMA Busy Hack"), + bsi, FSUI_ICONSTR(ICON_FA_MEMORY, "Emulate GIF FIFO"), FSUI_CSTR("Correct but slower. Known to affect the following games: FIFA Street 2."), "EmuCore/Gamefixes", "GIFFIFOHack", false); + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_HOURGLASS, "DMA Busy Hack"), FSUI_CSTR("Known to affect following games: Mana Khemia 1, Metal Saga, Pilot Down Behind Enemy Lines."), "EmuCore/Gamefixes", "DMABusyHack", false); - DrawToggleSetting(bsi, FSUI_CSTR("Delay VIF1 Stalls"), FSUI_CSTR("For SOCOM 2 HUD and Spy Hunter loading hang."), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_HOURGLASS, "Delay VIF1 Stalls"), FSUI_CSTR("For SOCOM 2 HUD and Spy Hunter loading hang."), "EmuCore/Gamefixes", "VIF1StallHack", false); - DrawToggleSetting(bsi, FSUI_CSTR("Emulate VIF FIFO"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_MEMORY, "Emulate VIF FIFO"), FSUI_CSTR("Simulate VIF1 FIFO read ahead. Known to affect following games: Test Drive Unlimited, Transformers."), "EmuCore/Gamefixes", "VIFFIFOHack", false); - DrawToggleSetting(bsi, FSUI_CSTR("Full VU0 Synchronization"), FSUI_CSTR("Forces tight VU0 sync on every COP2 instruction."), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_ARROWS_ROTATE, "Full VU0 Synchronization"), FSUI_CSTR("Forces tight VU0 sync on every COP2 instruction."), "EmuCore/Gamefixes", "FullVU0SyncHack", false); - DrawToggleSetting(bsi, FSUI_CSTR("VU I Bit Hack"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_MICROCHIP, "VU I Bit Hack"), FSUI_CSTR("Avoids constant recompilation in some games. Known to affect the following games: Scarface The World is Yours, Crash Tag Team Racing."), "EmuCore/Gamefixes", "IbitHack", false); - DrawToggleSetting(bsi, FSUI_CSTR("VU Add Hack"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_PLUS, "VU Add Hack"), FSUI_CSTR("For Tri-Ace Games: Star Ocean 3, Radiata Stories, Valkyrie Profile 2."), "EmuCore/Gamefixes", "VuAddSubHack", false); - DrawToggleSetting(bsi, FSUI_CSTR("VU Overflow Hack"), FSUI_CSTR("To check for possible float overflows (Superman Returns)."), - "EmuCore/Gamefixes", "VUOverflowHack", false); - DrawToggleSetting(bsi, FSUI_CSTR("VU Sync"), FSUI_CSTR("Run behind. To avoid sync problems when reading or writing VU registers."), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_WAVE_SQUARE, "VU Overflow Hack"), FSUI_CSTR("To check for possible float overflows (Superman Returns)."), + "EmuCore/Gamefixes", "VUOverflowHack", false, false); + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_ARROWS_ROTATE, "VU Sync"), FSUI_CSTR("Run behind. To avoid sync problems when reading or writing VU registers."), "EmuCore/Gamefixes", "VUSyncHack", false); - DrawToggleSetting(bsi, FSUI_CSTR("VU XGKick Sync"), FSUI_CSTR("Use accurate timing for VU XGKicks (slower)."), "EmuCore/Gamefixes", + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_CLOCK, "VU XGKick Sync"), FSUI_CSTR("Use accurate timing for VU XGKicks (slower)."), "EmuCore/Gamefixes", "XgKickHack", false); - DrawToggleSetting(bsi, FSUI_CSTR("Force Blit Internal FPS Detection"), + DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_GAUGE, "Force Blit Internal FPS Detection"), FSUI_CSTR("Use alternative method to calculate internal FPS to avoid false readings in some games."), "EmuCore/Gamefixes", "BlitInternalFPSHack", false); diff --git a/pcsx2/ImGui/ImGuiFullscreen.cpp b/pcsx2/ImGui/ImGuiFullscreen.cpp index 4650ac50ad476..d9d4428d404ef 100644 --- a/pcsx2/ImGui/ImGuiFullscreen.cpp +++ b/pcsx2/ImGui/ImGuiFullscreen.cpp @@ -23,6 +23,7 @@ #include "common/Timer.h" #include "IconsFontAwesome.h" +#include "IconsPromptFont.h" #include "imgui_internal.h" #include "imgui_stdlib.h" @@ -55,7 +56,7 @@ namespace ImGuiFullscreen static void DrawNotifications(ImVec2& position, float spacing); static void DrawToast(); static bool MenuButtonFrame(const char* str_id, bool enabled, float height, bool* visible, bool* hovered, ImRect* bb, - ImGuiButtonFlags flags = 0, float hover_alpha = 1.0f); + ImGuiButtonFlags flags = 0, float hover_alpha = 0.7f); static void PopulateFileSelectorItems(); static void SetFileSelectorDirectory(std::string dir); @@ -735,7 +736,7 @@ void ImGuiFullscreen::EndLayout() void ImGuiFullscreen::PushResetLayout() { ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(LAYOUT_WINDOW_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(8.0f, 8.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(4.0f, 3.0f)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, LayoutScale(8.0f, 4.0f)); @@ -743,7 +744,7 @@ void ImGuiFullscreen::PushResetLayout() ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, LayoutScale(4.0f, 2.0f)); ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, LayoutScale(21.0f)); ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarSize, LayoutScale(14.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarRounding, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarRounding, LayoutScale(LAYOUT_SCROLLBAR_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, LayoutScale(10.0f)); ImGui::PushStyleVar(ImGuiStyleVar_TabRounding, LayoutScale(4.0f)); @@ -967,6 +968,45 @@ InputLayout ImGuiFullscreen::GetGamepadLayout() return s_gamepad_layout; } +static InputLayout GetEffectiveGlyphLayout() +{ + const InputLayout preferred_layout = InputManager::GetGamepadIconPreference(); + if (preferred_layout == InputLayout::Xbox || preferred_layout == InputLayout::Playstation || preferred_layout == InputLayout::Nintendo) + return preferred_layout; + + const InputLayout detected_layout = ImGuiFullscreen::GetGamepadLayout(); + switch (detected_layout) + { + case InputLayout::Playstation: + return InputLayout::Playstation; + case InputLayout::Xbox: + return InputLayout::Xbox; + case InputLayout::Nintendo: + return InputLayout::Nintendo; + case InputLayout::Unknown: + default: + return InputLayout::Playstation; + } +} + +ImGuiFullscreen::GamepadGlyphs ImGuiFullscreen::GetGamepadGlyphs() +{ + const InputLayout layout = GetEffectiveGlyphLayout(); + const bool xbox = (layout == InputLayout::Xbox); + const bool nintendo = (layout == InputLayout::Nintendo); + return { + nintendo ? ICON_PF_BUTTON_B : (xbox ? ICON_PF_BUTTON_A : ICON_PF_BUTTON_CROSS), + nintendo ? ICON_PF_BUTTON_A : (xbox ? ICON_PF_BUTTON_B : ICON_PF_BUTTON_CIRCLE), + nintendo ? ICON_PF_BUTTON_Y : (xbox ? ICON_PF_BUTTON_X : ICON_PF_BUTTON_SQUARE), + nintendo ? ICON_PF_BUTTON_X : (xbox ? ICON_PF_BUTTON_Y : ICON_PF_BUTTON_TRIANGLE), + xbox ? ICON_PF_XBOX_DPAD : ICON_PF_DPAD, + xbox ? ICON_PF_XBOX_DPAD_LEFT_RIGHT : ICON_PF_DPAD_LEFT_RIGHT, + xbox ? ICON_PF_XBOX_DPAD_UP_DOWN : ICON_PF_DPAD_UP_DOWN, + nintendo ? ICON_PF_MINUS : (xbox ? ICON_PF_SHARE_CAPTURE : ICON_PF_SELECT_SHARE), + nintendo ? ICON_PF_PLUS : (xbox ? ICON_PF_BURGER_MENU : ICON_PF_START), + }; +} + void ImGuiFullscreen::CreateFooterTextString(SmallStringBase& dest, std::span> items) { @@ -1058,11 +1098,11 @@ void ImGuiFullscreen::DrawFullscreenFooter() const ImVec2 text_size = font.first->CalcTextSizeA(font.second, max_width, 0.0f, s_last_fullscreen_footer_text.c_str(), s_last_fullscreen_footer_text.end_ptr()); - dl->AddText( - font.first, font.second, - ImVec2(io.DisplaySize.x - padding * 2.0f - text_size.x, io.DisplaySize.y - font.second - padding), + const ImVec2 prev_text_pos(io.DisplaySize.x - padding * 2.0f - text_size.x, io.DisplaySize.y - font.second - padding); + AddTextWithShadow(dl, font, prev_text_pos, ImGui::GetColorU32(ImVec4(UIPrimaryTextColor.x, UIPrimaryTextColor.y, UIPrimaryTextColor.z, prev_opacity)), - s_last_fullscreen_footer_text.c_str(), s_last_fullscreen_footer_text.end_ptr()); + s_last_fullscreen_footer_text.c_str(), s_last_fullscreen_footer_text.end_ptr(), 0.0f, nullptr, + IM_COL32(0, 0, 0, static_cast(64.0f * prev_opacity))); } } else if (s_last_fullscreen_footer_text.empty()) @@ -1074,11 +1114,11 @@ void ImGuiFullscreen::DrawFullscreenFooter() { const ImVec2 text_size = font.first->CalcTextSizeA(font.second, max_width, 0.0f, s_fullscreen_footer_text.c_str(), s_fullscreen_footer_text.end_ptr()); - dl->AddText( - font.first, font.second, - ImVec2(io.DisplaySize.x - padding * 2.0f - text_size.x, io.DisplaySize.y - font.second - padding), + const ImVec2 curr_text_pos(io.DisplaySize.x - padding * 2.0f - text_size.x, io.DisplaySize.y - font.second - padding); + AddTextWithShadow(dl, font, curr_text_pos, ImGui::GetColorU32(ImVec4(UIPrimaryTextColor.x, UIPrimaryTextColor.y, UIPrimaryTextColor.z, 1.0f - prev_opacity)), - s_fullscreen_footer_text.c_str(), s_fullscreen_footer_text.end_ptr()); + s_fullscreen_footer_text.c_str(), s_fullscreen_footer_text.end_ptr(), 0.0f, nullptr, + IM_COL32(0, 0, 0, static_cast(64.0f * (1.0f - prev_opacity)))); } } @@ -1090,12 +1130,12 @@ void ImGuiFullscreen::PrerenderMenuButtonBorder() // updating might finish the animation const ImVec2& min = s_menu_button_frame_min_animated.UpdateAndGetValue(); const ImVec2& max = s_menu_button_frame_max_animated.UpdateAndGetValue(); - const ImU32 col = ImGui::GetColorU32(ImGuiCol_ButtonHovered); + const ImU32 col = ImGui::GetColorU32(ImGuiCol_ButtonHovered, 0.7f); const float t = std::min(std::abs(std::sin(ImGui::GetTime() * 0.75) * 1.1), 1.0f); ImGui::PushStyleColor(ImGuiCol_Border, ImGui::GetColorU32(ImGuiCol_Border, t)); - ImGui::RenderFrame(min, max, col, true, 0.0f); + ImGui::RenderFrame(min, max, col, true, LayoutScale(LAYOUT_FRAME_ROUNDING)); ImGui::PopStyleColor(); @@ -1107,7 +1147,7 @@ void ImGuiFullscreen::BeginMenuButtons(u32 num_items, float y_align, float x_pad s_menu_button_index = 0; ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(x_padding, y_padding)); - ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(LAYOUT_FRAME_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, LayoutScale(1.0f)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f)); @@ -1128,6 +1168,38 @@ void ImGuiFullscreen::EndMenuButtons() ImGui::PopStyleVar(4); } +void ImGuiFullscreen::AddTextWithShadow(ImDrawList* dl, std::pair font, const ImVec2& pos, ImU32 col, const char* text, + const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect, ImU32 shadow_col, bool strip_id_suffix) +{ + const char* const rendered_text_end = strip_id_suffix ? ImGui::FindRenderedTextEnd(text, text_end) : text_end; + const ImVec2 shadow_offset = LayoutScale(1.0f, 1.0f); + dl->AddText(font.first, font.second, pos + shadow_offset, shadow_col, text, rendered_text_end, wrap_width, cpu_fine_clip_rect); + dl->AddText(font.first, font.second, pos, col, text, rendered_text_end, wrap_width, cpu_fine_clip_rect); +} + +void ImGuiFullscreen::RenderTextClippedWithShadow(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, + const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect) +{ + ImFont* font = ImGui::GetFont(); + const float font_size = ImGui::GetFontSize(); + ImDrawList* dl = ImGui::GetWindowDrawList(); + const ImVec2 text_size = text_size_if_known ? *text_size_if_known : + font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text, text_end); + + ImVec2 pos = pos_min; + if (align.x > 0.0f) + pos.x = ImMax(pos.x, pos_min.x + (pos_max.x - pos_min.x - text_size.x) * align.x); + if (align.y > 0.0f) + pos.y = ImMax(pos.y, pos_min.y + (pos_max.y - pos_min.y - text_size.y) * align.y); + + const ImVec2& clip_min = clip_rect ? clip_rect->Min : pos_min; + const ImVec2& clip_max = clip_rect ? clip_rect->Max : pos_max; + dl->PushClipRect(clip_min, clip_max, true); + AddTextWithShadow(dl, std::pair(font, font_size), pos, ImGui::GetColorU32(ImGuiCol_Text), text, text_end, 0.0f, nullptr, + IM_COL32(0, 0, 0, 64), true); + dl->PopClipRect(); +} + void ImGuiFullscreen::DrawWindowTitle(const char* title) { ImGuiWindow* window = ImGui::GetCurrentWindow(); @@ -1141,7 +1213,7 @@ void ImGuiFullscreen::DrawWindowTitle(const char* title) return; ImGui::PushFont(g_large_font.first, g_large_font.second); - ImGui::RenderTextClipped(rect.Min, rect.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &rect); + RenderTextClippedWithShadow(rect.Min, rect.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &rect); ImGui::PopFont(); const ImVec2 line_start(pos.x, pos.y + g_large_font.second + LayoutScale(LAYOUT_MENU_BUTTON_Y_PADDING)); @@ -1155,7 +1227,7 @@ void ImGuiFullscreen::GetMenuButtonFrameBounds(float height, ImVec2* pos, ImVec2 { ImGuiWindow* window = ImGui::GetCurrentWindow(); *pos = window->DC.CursorPos; - *size = ImVec2(window->WorkRect.GetWidth(), LayoutScale(height) + ImGui::GetStyle().FramePadding.y * 2.0f); + *size = ImVec2(ImGui::GetContentRegionAvail().x, LayoutScale(height) + ImGui::GetStyle().FramePadding.y * 2.0f); } void ImGuiFullscreen::DrawMenuButtonFrame(const ImVec2& p_min, const ImVec2& p_max, ImU32 fill_col, @@ -1249,7 +1321,7 @@ bool ImGuiFullscreen::MenuButtonFrame( const float t = std::min(std::abs(std::sin(ImGui::GetTime() * 0.75) * 1.1), 1.0f); ImGui::PushStyleColor(ImGuiCol_Border, ImGui::GetColorU32(ImGuiCol_Border, t)); - DrawMenuButtonFrame(bb->Min, bb->Max, col, true, 0.0f); + DrawMenuButtonFrame(bb->Min, bb->Max, col, true, LayoutScale(LAYOUT_FRAME_ROUNDING)); ImGui::PopStyleColor(); } @@ -1268,7 +1340,7 @@ bool ImGuiFullscreen::MenuButtonFrame( } bool ImGuiFullscreen::MenuButtonFrame(const char* str_id, bool enabled, float height, bool* visible, bool* hovered, ImVec2* min, - ImVec2* max, ImGuiButtonFlags flags /*= 0*/, float hover_alpha /*= 0*/) + ImVec2* max, ImGuiButtonFlags flags /*= 0*/, float hover_alpha /*= 0.7f*/) { ImRect bb; const bool result = MenuButtonFrame(str_id, enabled, height, visible, hovered, &bb, flags, hover_alpha); @@ -1296,7 +1368,7 @@ void ImGuiFullscreen::MenuHeading(const char* title, bool draw_line /*= true*/) ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled)); ImGui::PushFont(g_large_font.first, g_large_font.second); - ImGui::RenderTextClipped(bb.Min, bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &bb); + RenderTextClippedWithShadow(bb.Min, bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &bb); ImGui::PopFont(); ImGui::PopStyleColor(); @@ -1323,13 +1395,13 @@ bool ImGuiFullscreen::MenuHeadingButton( if (!enabled) ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled)); ImGui::PushFont(g_large_font.first, g_large_font.second); - ImGui::RenderTextClipped(bb.Min, bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &bb); + RenderTextClippedWithShadow(bb.Min, bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &bb); if (value) { const ImVec2 value_size(g_large_font.first->CalcTextSizeA(g_large_font.second, std::numeric_limits::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); + RenderTextClippedWithShadow(value_bb.Min, value_bb.Max, value, nullptr, nullptr, ImVec2(0.0f, 0.0f), &value_bb); } ImGui::PopFont(); @@ -1361,7 +1433,8 @@ bool ImGuiFullscreen::ActiveButtonWithRightText(const char* title, const char* r const ImVec2 border_size_v = ImVec2(border_size, border_size); ImVec2 pos, size; GetMenuButtonFrameBounds(height, &pos, &size); - ImGui::RenderFrame(pos + border_size_v, pos + size - border_size_v, ImGui::GetColorU32(UIPrimaryColor), false); + ImGui::RenderFrame(pos + border_size_v, pos + size - border_size_v, ImGui::GetColorU32(UIPrimaryColor), false, + LayoutScale(LAYOUT_FRAME_ROUNDING)); } ImRect bb; @@ -1376,14 +1449,14 @@ bool ImGuiFullscreen::ActiveButtonWithRightText(const char* title, const char* r ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled)); ImGui::PushFont(font.first, font.second); - ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb); + RenderTextClippedWithShadow(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb); if (right_title && *right_title) { const ImVec2 right_text_size = font.first->CalcTextSizeA(font.second, 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), + RenderTextClippedWithShadow(right_text_start, title_bb.Max, right_title, nullptr, &right_text_size, ImVec2(0.0f, 0.0f), &title_bb); } @@ -1398,9 +1471,24 @@ bool ImGuiFullscreen::ActiveButtonWithRightText(const char* title, const char* r bool ImGuiFullscreen::MenuButton(const char* title, const char* summary, bool enabled, float height, std::pair font, std::pair summary_font) { + float dynamic_height = height; + float avail_summary_width = 0.0f; + const float frame_width = ImGui::GetContentRegionAvail().x; + if (summary && summary[0]) + { + avail_summary_width = frame_width - ImGui::GetStyle().FramePadding.x * 2.0f; + if (avail_summary_width > 0.0f) + { + const float wrapped_summary_height = + summary_font.first->CalcTextSizeA(summary_font.second, FLT_MAX, avail_summary_width, summary).y; + const float content_height_px = GetLineHeight(font) + LayoutScale(4.0f) + wrapped_summary_height; + dynamic_height = std::max(height, LayoutUnscale(content_height_px)); + } + } + ImRect bb; bool visible, hovered; - bool pressed = MenuButtonFrame(title, enabled, height, &visible, &hovered, &bb); + bool pressed = MenuButtonFrame(title, enabled, dynamic_height, &visible, &hovered, &bb); if (!visible) return false; @@ -1412,13 +1500,21 @@ bool ImGuiFullscreen::MenuButton(const char* title, const char* summary, bool en ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled)); ImGui::PushFont(font.first, font.second); - ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb); + RenderTextClippedWithShadow(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb); ImGui::PopFont(); if (summary) { ImGui::PushFont(summary_font.first, summary_font.second); - ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, summary, nullptr, nullptr, ImVec2(0.0f, 0.0f), &summary_bb); + ImGui::PushStyleColor(ImGuiCol_Text, MulAlpha(ImGui::GetStyleColorVec4(ImGuiCol_Text), 0.60f)); + if (avail_summary_width > 0.0f) + { + ImDrawList* dl = ImGui::GetWindowDrawList(); + const ImVec4 summary_clip(summary_bb.Min.x, summary_bb.Min.y, summary_bb.Max.x, summary_bb.Max.y); + AddTextWithShadow(dl, summary_font, summary_bb.Min, ImGui::GetColorU32(ImGuiCol_Text), + summary, nullptr, avail_summary_width, &summary_clip); + } + ImGui::PopStyleColor(); ImGui::PopFont(); } @@ -1445,7 +1541,7 @@ bool ImGuiFullscreen::MenuButtonWithoutSummary(const char* title, bool enabled, ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled)); ImGui::PushFont(font.first, font.second); - ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, title, nullptr, nullptr, text_align, &title_bb); + RenderTextClippedWithShadow(title_bb.Min, title_bb.Max, title, nullptr, nullptr, text_align, &title_bb); ImGui::PopFont(); if (!enabled) @@ -1476,13 +1572,15 @@ bool ImGuiFullscreen::MenuImageButton(const char* title, const char* summary, Im ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled)); ImGui::PushFont(title_font.first, title_font.second); - ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb); + RenderTextClippedWithShadow(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb); ImGui::PopFont(); if (summary) { ImGui::PushFont(summary_font.first, summary_font.second); - ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, summary, nullptr, nullptr, ImVec2(0.0f, 0.0f), &summary_bb); + ImGui::PushStyleColor(ImGuiCol_Text, MulAlpha(ImGui::GetStyleColorVec4(ImGuiCol_Text), 0.60f)); + RenderTextClippedWithShadow(summary_bb.Min, summary_bb.Max, summary, nullptr, nullptr, ImVec2(0.0f, 0.0f), &summary_bb); + ImGui::PopStyleColor(); ImGui::PopFont(); } @@ -1554,9 +1652,9 @@ bool ImGuiFullscreen::FloatingButton(const char* text, float x, float y, float w if (hovered) { const float t = std::min(std::abs(std::sin(ImGui::GetTime() * 0.75) * 1.1), 1.0f); - const ImU32 col = ImGui::GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered, 1.0f); + const ImU32 col = ImGui::GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered, 0.7f); ImGui::PushStyleColor(ImGuiCol_Border, ImGui::GetColorU32(ImGuiCol_Border, t)); - DrawMenuButtonFrame(bb.Min, bb.Max, col, true, 0.0f); + DrawMenuButtonFrame(bb.Min, bb.Max, col, true, LayoutScale(LAYOUT_FRAME_ROUNDING)); ImGui::PopStyleColor(); } } @@ -1574,7 +1672,7 @@ bool ImGuiFullscreen::FloatingButton(const char* text, float x, float y, float w ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled)); ImGui::PushFont(font.first, font.second); - ImGui::RenderTextClipped(bb.Min, bb.Max, text, nullptr, nullptr, ImVec2(0.0f, 0.0f), &bb); + RenderTextClippedWithShadow(bb.Min, bb.Max, text, nullptr, nullptr, ImVec2(0.0f, 0.0f), &bb); ImGui::PopFont(); if (!enabled) @@ -1586,39 +1684,63 @@ bool ImGuiFullscreen::FloatingButton(const char* text, float x, float y, float w bool ImGuiFullscreen::ToggleButton( const char* title, const char* summary, bool* v, bool enabled, float height, std::pair font, std::pair summary_font) { + const float toggle_width = LayoutScale(50.0f); + const float toggle_height = LayoutScale(25.0f); + const float toggle_gap = LayoutScale(8.0f); + + float dynamic_height = height; + float avail_summary_width = 0.0f; + const float frame_width = ImGui::GetContentRegionAvail().x; + if (summary && summary[0]) + { + avail_summary_width = frame_width - ImGui::GetStyle().FramePadding.x * 2.0f - toggle_width - toggle_gap; + if (avail_summary_width > 0.0f) + { + const float wrapped_summary_height = + summary_font.first->CalcTextSizeA(summary_font.second, FLT_MAX, avail_summary_width, summary).y; + const float content_height_px = GetLineHeight(font) + LayoutScale(4.0f) + wrapped_summary_height; + dynamic_height = std::max(height, LayoutUnscale(content_height_px)); + } + } + ImRect bb; bool visible, hovered; - bool pressed = MenuButtonFrame(title, enabled, height, &visible, &hovered, &bb, ImGuiButtonFlags_PressedOnClick); + bool pressed = MenuButtonFrame(title, enabled, dynamic_height, &visible, &hovered, &bb, ImGuiButtonFlags_PressedOnClick); if (!visible) return false; const float midpoint = bb.Min.y + GetLineHeight(font) + 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); + const ImRect summary_bb(ImVec2(bb.Min.x, midpoint), ImVec2(bb.Max.x - toggle_width - toggle_gap, bb.Max.y)); if (!enabled) ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled)); ImGui::PushFont(font.first, font.second); - ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb); + RenderTextClippedWithShadow(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb); ImGui::PopFont(); if (summary) { ImGui::PushFont(summary_font.first, summary_font.second); - ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, summary, nullptr, nullptr, ImVec2(0.0f, 0.0f), &summary_bb); + ImGui::PushStyleColor(ImGuiCol_Text, MulAlpha(ImGui::GetStyleColorVec4(ImGuiCol_Text), 0.60f)); + if (avail_summary_width > 0.0f) + { + ImDrawList* dl = ImGui::GetWindowDrawList(); + const ImVec4 summary_clip(summary_bb.Min.x, summary_bb.Min.y, summary_bb.Max.x, summary_bb.Max.y); + AddTextWithShadow(dl, summary_font, summary_bb.Min, ImGui::GetColorU32(ImGuiCol_Text), + summary, nullptr, avail_summary_width, &summary_clip); + } + ImGui::PopStyleColor(); ImGui::PopFont(); } 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); - const float toggle_y = (LayoutScale(height) - toggle_height) * 0.5f; const float toggle_radius = toggle_height * 0.5f; - const ImVec2 toggle_pos(bb.Max.x - toggle_width - toggle_x, bb.Min.y + toggle_y); + const float toggle_y = (bb.Max.y - bb.Min.y - toggle_height) * 0.5f; + const ImVec2 toggle_pos(bb.Max.x - toggle_width, bb.Min.y + toggle_y); if (pressed) *v = !*v; @@ -1657,39 +1779,63 @@ bool ImGuiFullscreen::ToggleButton( bool ImGuiFullscreen::ThreeWayToggleButton( const char* title, const char* summary, std::optional* v, bool enabled, float height, std::pair font, std::pair summary_font) { + const float toggle_width = LayoutScale(50.0f); + const float toggle_height = LayoutScale(25.0f); + const float toggle_gap = LayoutScale(8.0f); + + float dynamic_height = height; + float avail_summary_width = 0.0f; + const float frame_width = ImGui::GetContentRegionAvail().x; + if (summary && summary[0]) + { + avail_summary_width = frame_width - ImGui::GetStyle().FramePadding.x * 2.0f - toggle_width - toggle_gap; + if (avail_summary_width > 0.0f) + { + const float wrapped_summary_height = + summary_font.first->CalcTextSizeA(summary_font.second, FLT_MAX, avail_summary_width, summary).y; + const float content_height_px = GetLineHeight(font) + LayoutScale(4.0f) + wrapped_summary_height; + dynamic_height = std::max(height, LayoutUnscale(content_height_px)); + } + } + ImRect bb; bool visible, hovered; - bool pressed = MenuButtonFrame(title, enabled, height, &visible, &hovered, &bb, ImGuiButtonFlags_PressedOnClick); + bool pressed = MenuButtonFrame(title, enabled, dynamic_height, &visible, &hovered, &bb, ImGuiButtonFlags_PressedOnClick); if (!visible) return false; const float midpoint = bb.Min.y + GetLineHeight(font) + 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); + const ImRect summary_bb(ImVec2(bb.Min.x, midpoint), ImVec2(bb.Max.x - toggle_width - toggle_gap, bb.Max.y)); if (!enabled) ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled)); ImGui::PushFont(font.first, font.second); - ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb); + RenderTextClippedWithShadow(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb); ImGui::PopFont(); if (summary) { ImGui::PushFont(summary_font.first, summary_font.second); - ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, summary, nullptr, nullptr, ImVec2(0.0f, 0.0f), &summary_bb); + ImGui::PushStyleColor(ImGuiCol_Text, MulAlpha(ImGui::GetStyleColorVec4(ImGuiCol_Text), 0.60f)); + if (avail_summary_width > 0.0f) + { + ImDrawList* dl = ImGui::GetWindowDrawList(); + const ImVec4 summary_clip(summary_bb.Min.x, summary_bb.Min.y, summary_bb.Max.x, summary_bb.Max.y); + AddTextWithShadow(dl, summary_font, summary_bb.Min, ImGui::GetColorU32(ImGuiCol_Text), + summary, nullptr, avail_summary_width, &summary_clip); + } + ImGui::PopStyleColor(); ImGui::PopFont(); } 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); - const float toggle_y = (LayoutScale(LAYOUT_MENU_BUTTON_HEIGHT) - toggle_height) * 0.5f; const float toggle_radius = toggle_height * 0.5f; - const ImVec2 toggle_pos(bb.Max.x - toggle_width - toggle_x, bb.Min.y + toggle_y); + const float toggle_y = (bb.Max.y - bb.Min.y - toggle_height) * 0.5f; + const ImVec2 toggle_pos(bb.Max.x - toggle_width, bb.Min.y + toggle_y); if (pressed) { @@ -1734,14 +1880,28 @@ bool ImGuiFullscreen::ThreeWayToggleButton( bool ImGuiFullscreen::MenuButtonWithValue( const char* title, const char* summary, const char* value, bool enabled, float height, std::pair font, std::pair summary_font) { + const ImVec2 value_size(ImGui::CalcTextSize(value)); + float dynamic_height = height; + float avail_summary_width = 0.0f; + const float frame_width = ImGui::GetContentRegionAvail().x; + if (summary && summary[0]) + { + avail_summary_width = frame_width - ImGui::GetStyle().FramePadding.x * 2.0f - value_size.x; + if (avail_summary_width > 0.0f) + { + const float wrapped_summary_height = + summary_font.first->CalcTextSizeA(summary_font.second, FLT_MAX, avail_summary_width, summary).y; + const float content_height_px = GetLineHeight(font) + LayoutScale(4.0f) + wrapped_summary_height; + dynamic_height = std::max(height, LayoutUnscale(content_height_px)); + } + } + ImRect bb; bool visible, hovered; - bool pressed = MenuButtonFrame(title, enabled, height, &visible, &hovered, &bb); + bool pressed = MenuButtonFrame(title, enabled, dynamic_height, &visible, &hovered, &bb); if (!visible) return false; - const ImVec2 value_size(ImGui::CalcTextSize(value)); - const float midpoint = bb.Min.y + GetLineHeight(font) + LayoutScale(4.0f); const float text_end = bb.Max.x - value_size.x; const ImRect title_bb(bb.Min, ImVec2(text_end, midpoint)); @@ -1751,14 +1911,22 @@ bool ImGuiFullscreen::MenuButtonWithValue( ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetColorU32(ImGuiCol_TextDisabled)); ImGui::PushFont(font.first, font.second); - 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); + RenderTextClippedWithShadow(title_bb.Min, title_bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb); + RenderTextClippedWithShadow(bb.Min, bb.Max, value, nullptr, nullptr, ImVec2(1.0f, 0.5f), &bb); ImGui::PopFont(); if (summary) { ImGui::PushFont(summary_font.first, summary_font.second); - ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, summary, nullptr, nullptr, ImVec2(0.0f, 0.0f), &summary_bb); + ImGui::PushStyleColor(ImGuiCol_Text, MulAlpha(ImGui::GetStyleColorVec4(ImGuiCol_Text), 0.60f)); + if (avail_summary_width > 0.0f) + { + ImDrawList* dl = ImGui::GetWindowDrawList(); + const ImVec4 summary_clip(summary_bb.Min.x, summary_bb.Min.y, summary_bb.Max.x, summary_bb.Max.y); + AddTextWithShadow(dl, summary_font, summary_bb.Min, ImGui::GetColorU32(ImGuiCol_Text), + summary, nullptr, avail_summary_width, &summary_clip); + } + ImGui::PopStyleColor(); ImGui::PopFont(); } @@ -1814,7 +1982,7 @@ void ImGuiFullscreen::BeginNavBar(float x_padding /*= LAYOUT_MENU_BUTTON_X_PADDI s_menu_button_index = 0; ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(x_padding, y_padding)); - ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(LAYOUT_FRAME_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, LayoutScale(1.0f)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, LayoutScale(1.0f, 0.0f)); PushPrimaryColor(); @@ -1850,7 +2018,7 @@ void ImGuiFullscreen::NavTitle(const char* title, float height /*= LAYOUT_MENU_B bb.Max.y -= style.FramePadding.y; ImGui::PushFont(font.first, font.second); - ImGui::RenderTextClipped(bb.Min, bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &bb); + RenderTextClippedWithShadow(bb.Min, bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &bb); ImGui::PopFont(); } @@ -1906,8 +2074,8 @@ bool ImGuiFullscreen::NavButton(const char* title, bool is_active, bool enabled pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus); if (hovered) { - const ImU32 col = ImGui::GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered, 1.0f); - DrawMenuButtonFrame(bb.Min, bb.Max, col, true, 0.0f); + const ImU32 col = ImGui::GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered, 0.7f); + DrawMenuButtonFrame(bb.Min, bb.Max, col, true, LayoutScale(LAYOUT_FRAME_ROUNDING)); } } else @@ -1924,7 +2092,7 @@ bool ImGuiFullscreen::NavButton(const char* title, bool is_active, bool enabled ImGuiCol_Text, ImGui::GetColorU32(enabled ? (is_active ? ImGuiCol_Text : ImGuiCol_TextDisabled) : ImGuiCol_ButtonHovered)); ImGui::PushFont(font.first, font.second); - ImGui::RenderTextClipped(bb.Min, bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &bb); + RenderTextClippedWithShadow(bb.Min, bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &bb); ImGui::PopFont(); ImGui::PopStyleColor(); @@ -1974,8 +2142,8 @@ bool ImGuiFullscreen::NavTab(const char* title, bool is_active, bool enabled /* pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus); if (hovered) { - const ImU32 col = ImGui::GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered, 1.0f); - DrawMenuButtonFrame(bb.Min, bb.Max, col, true, 0.0f); + const ImU32 col = ImGui::GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered, 0.7f); + DrawMenuButtonFrame(bb.Min, bb.Max, col, true, LayoutScale(LAYOUT_FRAME_ROUNDING)); } } else @@ -1988,7 +2156,7 @@ bool ImGuiFullscreen::NavTab(const char* title, bool is_active, bool enabled /* if (!hovered) { const ImU32 col = ImGui::GetColorU32(is_active ? background : ImVec4(background.x, background.y, background.z, 0.5f)); - ImGui::RenderFrame(bb.Min, bb.Max, col, false, 0.0f); + ImGui::RenderFrame(bb.Min, bb.Max, col, false, LayoutScale(LAYOUT_FRAME_ROUNDING)); } #if 0 @@ -2011,7 +2179,7 @@ bool ImGuiFullscreen::NavTab(const char* title, bool is_active, bool enabled /* ImGui::GetColorU32(enabled ? (is_active ? ImGuiCol_Text : ImGuiCol_TextDisabled) : ImGuiCol_ButtonHovered)); ImGui::PushFont(font.first, font.second); - ImGui::RenderTextClipped(bb.Min, bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &bb); + RenderTextClippedWithShadow(bb.Min, bb.Max, title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &bb); ImGui::PopFont(); ImGui::PopStyleColor(); @@ -2030,7 +2198,7 @@ bool ImGuiFullscreen::BeginHorizontalMenu(const char* name, const ImVec2& positi const float menu_height = LayoutScale(LAYOUT_HORIZONTAL_MENU_HEIGHT); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(item_padding, item_padding)); - ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(LAYOUT_FRAME_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, LayoutScale(1.0f)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(item_spacing, 0.0f)); @@ -2069,12 +2237,12 @@ bool ImGuiFullscreen::HorizontalMenuItem(GSTexture* icon, const ImVec2& icon_uv0 const bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held, 0); if (hovered) { - const ImU32 col = ImGui::GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered, 1.0f); + const ImU32 col = ImGui::GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered, 0.7f); const float t = static_cast(std::min(std::abs(std::sin(ImGui::GetTime() * 0.75) * 1.1), 1.0)); ImGui::PushStyleColor(ImGuiCol_Border, ImGui::GetColorU32(ImGuiCol_Border, t)); - DrawMenuButtonFrame(bb.Min, bb.Max, col, true, 0.0f); + DrawMenuButtonFrame(bb.Min, bb.Max, col, true, LayoutScale(LAYOUT_FRAME_ROUNDING)); ImGui::PopStyleColor(); } @@ -2095,15 +2263,14 @@ bool ImGuiFullscreen::HorizontalMenuItem(GSTexture* icon, const ImVec2& icon_uv0 const ImVec2 title_pos = ImVec2(bb.Min.x + (avail_width - title_size.x) * 0.5f, icon_pos.y + icon_size + LayoutScale(10.0f)); - dl->AddText(title_font.first, title_font.second, title_pos, ImGui::GetColorU32(ImGuiCol_Text), title, nullptr, 0.0f); + AddTextWithShadow(dl, title_font, title_pos, ImGui::GetColorU32(ImGuiCol_Text), title, nullptr, 0.0f); const std::pair desc_font = g_medium_font; const ImVec2 desc_size = desc_font.first->CalcTextSizeA(desc_font.second, avail_width, avail_width, description); const ImVec2 desc_pos = ImVec2(bb.Min.x + (avail_width - desc_size.x) * 0.5f, title_pos.y + title_size.y + 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); - dl->AddText(desc_font.first, desc_font.second, desc_pos, ImGui::GetColorU32(ImGuiCol_Text), description, nullptr, - avail_width, &desc_bb); + AddTextWithShadow(dl, desc_font, desc_pos, ImGui::GetColorU32(ImGuiCol_Text), description, nullptr, avail_width, &desc_bb); ImGui::SameLine(); @@ -2262,7 +2429,7 @@ void ImGuiFullscreen::DrawFileSelector() FileSelectorItem* selected = nullptr; ImGui::PushFont(g_large_font.first, g_large_font.second); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(LAYOUT_WINDOW_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING, LAYOUT_MENU_BUTTON_Y_PADDING)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); ImGui::PushStyleColor(ImGuiCol_Text, UIPrimaryTextColor); @@ -2389,7 +2556,7 @@ void ImGuiFullscreen::DrawChoiceDialog() ImGui::PushFont(g_large_font.first, g_large_font.second); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(20.0f, 20.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(LAYOUT_WINDOW_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING, LAYOUT_MENU_BUTTON_Y_PADDING)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); ImGui::PushStyleColor(ImGuiCol_Text, UIPrimaryTextColor); @@ -2518,7 +2685,7 @@ void ImGuiFullscreen::DrawInputDialog() ImGui::PushFont(g_large_font.first, g_large_font.second); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(20.0f, 20.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(LAYOUT_WINDOW_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING, LAYOUT_MENU_BUTTON_Y_PADDING)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); ImGui::PushStyleColor(ImGuiCol_Text, UIPrimaryTextColor); @@ -2578,7 +2745,7 @@ void ImGuiFullscreen::DrawInputDialog() if (s_focus_reset_queued != FocusResetType::None) ImGui::SetKeyboardFocusHere(); - ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(8.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, LayoutScale(LAYOUT_FRAME_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(12.0f, 10.0f)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, LayoutScale(1.0f)); ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.2f, 0.2f, 0.2f, 1.0f)); @@ -2723,7 +2890,7 @@ void ImGuiFullscreen::DrawMessageDialog() ImGui::PushFont(g_large_font.first, g_large_font.second); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(20.0f, 20.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(LAYOUT_WINDOW_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING, LAYOUT_MENU_BUTTON_Y_PADDING)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); ImGui::PushStyleColor(ImGuiCol_Text, UIPrimaryTextColor); @@ -2889,7 +3056,7 @@ void ImGuiFullscreen::DrawProgressDialogs(ImVec2& position, float spacing) ImGui::PushFont(g_large_font.first, g_large_font.second); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, LayoutScale(20.0f, 20.0f)); - ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(10.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, LayoutScale(LAYOUT_WINDOW_ROUNDING)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING, LAYOUT_MENU_BUTTON_Y_PADDING)); ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); ImGui::PushStyleColor(ImGuiCol_Text, UIPrimaryTextColor); @@ -3098,14 +3265,15 @@ void ImGuiFullscreen::DrawNotifications(ImVec2& position, float spacing) const ImVec2 title_min(badge_max.x + horizontal_spacing, box_min.y + vertical_padding); const ImVec2 title_max(title_min.x + title_size.x, title_min.y + title_size.y); const u32 title_col = (toast_title_color & ~IM_COL32_A_MASK) | (opacity << IM_COL32_A_SHIFT); - dl->AddText(title_font.first, title_font.second, title_min, title_col, notif.title.c_str(), - notif.title.c_str() + notif.title.size(), max_text_width); + const u32 text_shadow_col = IM_COL32(0, 0, 0, (64u * opacity) / 255u); + AddTextWithShadow(dl, title_font, title_min, title_col, notif.title.c_str(), notif.title.c_str() + notif.title.size(), max_text_width, + nullptr, text_shadow_col); const ImVec2 text_min(badge_max.x + horizontal_spacing, title_max.y + vertical_spacing); const ImVec2 text_max(text_min.x + text_size.x, text_min.y + text_size.y); const u32 text_col = (toast_text_color & ~IM_COL32_A_MASK) | (opacity << IM_COL32_A_SHIFT); - dl->AddText(text_font.first, text_font.second, text_min, text_col, notif.text.c_str(), - notif.text.c_str() + notif.text.size(), max_text_width); + AddTextWithShadow(dl, text_font, text_min, text_col, notif.text.c_str(), notif.text.c_str() + notif.text.size(), max_text_width, + nullptr, text_shadow_col); position.y += s_notification_vertical_direction * (box_height + shadow_size + spacing); index++; @@ -3165,19 +3333,22 @@ void ImGuiFullscreen::DrawToast() ImDrawList* dl = ImGui::GetForegroundDrawList(); dl->AddRectFilled(box_pos, box_pos + box_size, ImGui::GetColorU32(ModAlpha(UIPrimaryColor, alpha)), padding); + const u32 shadow_col = IM_COL32(0, 0, 0, static_cast(64.0f * alpha)); if (!s_toast_title.empty()) { const float offset = (comb_size.x - title_size.x) * 0.5f; - dl->AddText(title_font.first, title_font.second, box_pos + ImVec2(offset + padding, padding), + const ImVec2 title_pos = box_pos + ImVec2(offset + padding, padding); + AddTextWithShadow(dl, title_font, title_pos, ImGui::GetColorU32(ModAlpha(UIPrimaryTextColor, alpha)), s_toast_title.c_str(), s_toast_title.c_str() + s_toast_title.length(), - max_width); + max_width, nullptr, shadow_col); } if (!s_toast_message.empty()) { const float offset = (comb_size.x - message_size.x) * 0.5f; - dl->AddText(message_font.first, message_font.second, box_pos + ImVec2(offset + padding, padding + spacing + title_size.y), + const ImVec2 message_pos = box_pos + ImVec2(offset + padding, padding + spacing + title_size.y); + AddTextWithShadow(dl, message_font, message_pos, ImGui::GetColorU32(ModAlpha(UIPrimaryTextColor, alpha)), s_toast_message.c_str(), - s_toast_message.c_str() + s_toast_message.length(), max_width); + s_toast_message.c_str() + s_toast_message.length(), max_width, nullptr, shadow_col); } } diff --git a/pcsx2/ImGui/ImGuiFullscreen.h b/pcsx2/ImGui/ImGuiFullscreen.h index ef28beb270ac5..ae76c87c5603e 100644 --- a/pcsx2/ImGui/ImGuiFullscreen.h +++ b/pcsx2/ImGui/ImGuiFullscreen.h @@ -41,6 +41,9 @@ namespace ImGuiFullscreen 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_WINDOW_ROUNDING = 8.0f; + static constexpr float LAYOUT_FRAME_ROUNDING = 6.0f; + static constexpr float LAYOUT_SCROLLBAR_ROUNDING = 5.0f; extern std::pair g_standard_font; extern std::pair g_medium_font; @@ -165,6 +168,22 @@ namespace ImGuiFullscreen bool IsGamepadInputSource(); void ReportGamepadLayout(InputLayout layout); InputLayout GetGamepadLayout(); + struct GamepadGlyphs + { + const char* south; + const char* east; + const char* west; + const char* north; + const char* dpad; + const char* dpad_lr; + const char* dpad_ud; + const char* select; + const char* start; + + const char* confirm(bool circleOK) const { return circleOK ? east : south; } + const char* cancel(bool circleOK) const { return circleOK ? south : east; } + }; + GamepadGlyphs GetGamepadGlyphs(); void CreateFooterTextString(SmallStringBase& dest, std::span> items); void SetFullscreenFooterText(std::string_view text); void SetFullscreenFooterText(std::span> items); @@ -173,12 +192,17 @@ namespace ImGuiFullscreen void DrawFullscreenFooter(); void PrerenderMenuButtonBorder(); + void AddTextWithShadow(ImDrawList* dl, std::pair font, const ImVec2& pos, ImU32 col, const char* text, + const char* text_end = nullptr, float wrap_width = 0.0f, const ImVec4* cpu_fine_clip_rect = nullptr, + ImU32 shadow_col = IM_COL32(0, 0, 0, 64), bool strip_id_suffix = false); + void RenderTextClippedWithShadow(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end = nullptr, + const ImVec2* text_size_if_known = nullptr, const ImVec2& align = ImVec2(0.0f, 0.0f), const ImRect* clip_rect = nullptr); void BeginMenuButtons(u32 num_items = 0, float y_align = 0.0f, float x_padding = LAYOUT_MENU_BUTTON_X_PADDING, float y_padding = LAYOUT_MENU_BUTTON_Y_PADDING, float item_height = LAYOUT_MENU_BUTTON_HEIGHT); void EndMenuButtons(); void GetMenuButtonFrameBounds(float height, ImVec2* pos, ImVec2* size); bool MenuButtonFrame(const char* str_id, bool enabled, float height, bool* visible, bool* hovered, ImVec2* min, ImVec2* max, - ImGuiButtonFlags flags = 0, float hover_alpha = 1.0f); + ImGuiButtonFlags flags = 0, float hover_alpha = 0.7f); void DrawMenuButtonFrame(const ImVec2& p_min, const ImVec2& p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); void ResetMenuButtonFrame(); void MenuHeading(const char* title, bool draw_line = true); diff --git a/pcsx2/ImGui/ImGuiManager.cpp b/pcsx2/ImGui/ImGuiManager.cpp index 117abd7295382..b5650ca3babf0 100644 --- a/pcsx2/ImGui/ImGuiManager.cpp +++ b/pcsx2/ImGui/ImGuiManager.cpp @@ -370,11 +370,19 @@ void ImGuiManager::SetStyle() colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); - colors[ImGuiCol_NavCursor] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_NavCursor] = ImVec4(0.26f, 0.59f, 0.98f, 0.70f); colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f); colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); + style.WindowRounding = 6.0f; + style.ChildRounding = 6.0f; + style.PopupRounding = 6.0f; + style.FrameRounding = 5.0f; + style.GrabRounding = 5.0f; + style.TabRounding = 5.0f; + style.ScrollbarRounding = 5.0f; + style.ScaleAllSizes(s_global_scale); } @@ -545,7 +553,7 @@ ImFont* ImGuiManager::AddTextFont() { // Exclude FA and PF ranges // clang-format off - static constexpr ImWchar range_exclude_icons[] = { 0x2198,0x2199,0x219e,0x21a7,0x21b0,0x21b3,0x21ba,0x21c3,0x21ce,0x21d4,0x21dc,0x21e8,0x21f3,0x21f3,0x21f7,0x21fb,0x2206,0x2208,0x221a,0x221a,0x227a,0x227d,0x22bf,0x22c8,0x2349,0x2349,0x235a,0x2367,0x237a,0x237f,0x23b2,0x23b5,0x23cc,0x23cc,0x23f4,0x23f7,0x2427,0x2452,0x2460,0x246b,0x248f,0x248f,0x24f5,0x24ff,0x2605,0x2605,0x2699,0x2699,0x278a,0x278e,0x27f6,0x27f6,0xff21,0xff3a,0x0,0x0 }; + static constexpr ImWchar range_exclude_icons[] = { 0x2198,0x21a7,0x21b0,0x21b3,0x21ba,0x21c3,0x21ce,0x21d4,0x21dc,0x21e8,0x21f3,0x21f3,0x21f7,0x2202,0x2206,0x2208,0x221a,0x221a,0x227a,0x227f,0x2284,0x2284,0x22bf,0x22c8,0x2349,0x2349,0x235a,0x2367,0x237a,0x237f,0x23b2,0x23b5,0x23cc,0x23cc,0x23f4,0x23f7,0x2427,0x2452,0x2460,0x246b,0x248f,0x248f,0x24f5,0x24ff,0x2605,0x2605,0x2699,0x2699,0x278a,0x278e,0x27f6,0x27f6,0xff21,0xff3a,0x0,0x0 }; // clang-format on std::vector exclude; diff --git a/pcsx2/Input/InputManager.cpp b/pcsx2/Input/InputManager.cpp index 10d05a761a595..0c5d3129a0943 100644 --- a/pcsx2/Input/InputManager.cpp +++ b/pcsx2/Input/InputManager.cpp @@ -139,6 +139,9 @@ static InputInterceptHook::Callback m_event_intercept_callback; // Input sources. Keyboard/mouse don't exist here. static std::array, static_cast(InputSourceType::Count)> s_input_sources; +// Layout preference for gamepad controller glyphs. +static std::atomic s_gamepad_icon_preference = InputLayout::Unknown; + // ------------------------------------------------------------------------ // Hotkeys // ------------------------------------------------------------------------ @@ -444,6 +447,16 @@ bool InputManager::PrettifyInputBinding(SmallStringBase& binding, bool use_icons return changed; } +void InputManager::SetGamepadIconPreference(InputLayout layout) +{ + s_gamepad_icon_preference.store(layout, std::memory_order_relaxed); +} + +InputLayout InputManager::GetGamepadIconPreference() +{ + return s_gamepad_icon_preference.load(std::memory_order_relaxed); +} + void InputManager::PrettifyInputBindingPart(const std::string_view binding, SmallString& ret, bool& changed, bool use_icons) { std::string_view source, sub_binding; diff --git a/pcsx2/Input/InputManager.h b/pcsx2/Input/InputManager.h index c51f87d6ebd76..625264552df77 100644 --- a/pcsx2/Input/InputManager.h +++ b/pcsx2/Input/InputManager.h @@ -222,6 +222,10 @@ namespace InputManager /// Represents a binding with icon fonts, if available. bool PrettifyInputBinding(SmallStringBase& binding, bool use_icons = true); + /// Sets the preferred button icon style for UI and binding displays, overriding per-device detection. + void SetGamepadIconPreference(InputLayout layout); + InputLayout GetGamepadIconPreference(); + /// Splits a chord into individual bindings. std::vector SplitChord(const std::string_view binding); diff --git a/pcsx2/Input/SDLInputSource.cpp b/pcsx2/Input/SDLInputSource.cpp index 8e0410aa40ec5..a46dfe475edab 100644 --- a/pcsx2/Input/SDLInputSource.cpp +++ b/pcsx2/Input/SDLInputSource.cpp @@ -94,6 +94,10 @@ static constexpr const char* s_sdl_trigger_ps_icons[] = { ICON_PF_LEFT_TRIGGER_L2, // SDL_GAMEPAD_AXIS_LEFT_TRIGGER ICON_PF_RIGHT_TRIGGER_R2, // SDL_GAMEPAD_AXIS_RIGHT_TRIGGER }; +static constexpr const char* s_sdl_trigger_nintendo_icons[] = { + ICON_PF_LEFT_TRIGGER_ZL, // SDL_GAMEPAD_AXIS_LEFT_TRIGGER + ICON_PF_RIGHT_TRIGGER_ZR, // SDL_GAMEPAD_AXIS_RIGHT_TRIGGER +}; static const char* const* s_sdl_trigger_icons_list[] = { s_sdl_trigger_icons, // SDL_GAMEPAD_TYPE_UNKNOWN @@ -103,7 +107,7 @@ static const char* const* s_sdl_trigger_icons_list[] = { s_sdl_trigger_ps_icons, // SDL_GAMEPAD_TYPE_PS3 s_sdl_trigger_ps_icons, // SDL_GAMEPAD_TYPE_PS4 s_sdl_trigger_ps_icons, // SDL_GAMEPAD_TYPE_PS5 - // Switch + s_sdl_trigger_nintendo_icons, // SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO }; static constexpr const char* s_sdl_ps3_pressure_icons[] = { @@ -379,6 +383,23 @@ static constexpr const char* s_sdl_button_ps5_icons[] = { ICON_PF_DUALSENSE_TOUCHPAD, // SDL_GAMEPAD_BUTTON_TOUCHPAD }; +static constexpr const char* s_sdl_button_nintendo_icons[] = { + ICON_PF_BUTTON_B, // SDL_GAMEPAD_BUTTON_SOUTH + ICON_PF_BUTTON_A, // SDL_GAMEPAD_BUTTON_EAST + ICON_PF_BUTTON_Y, // SDL_GAMEPAD_BUTTON_WEST + ICON_PF_BUTTON_X, // SDL_GAMEPAD_BUTTON_NORTH + ICON_PF_MINUS, // SDL_GAMEPAD_BUTTON_BACK + ICON_PF_HOME_MENU, // SDL_GAMEPAD_BUTTON_GUIDE + ICON_PF_PLUS, // SDL_GAMEPAD_BUTTON_START + ICON_PF_LEFT_ANALOG_CLICK, // SDL_GAMEPAD_BUTTON_LEFT_STICK + ICON_PF_RIGHT_ANALOG_CLICK, // SDL_GAMEPAD_BUTTON_RIGHT_STICK + ICON_PF_LEFT_SHOULDER_L, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER + ICON_PF_RIGHT_SHOULDER_R, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER + ICON_PF_JOYCON_DPAD_UP, // SDL_GAMEPAD_BUTTON_DPAD_UP + ICON_PF_JOYCON_DPAD_DOWN, // SDL_GAMEPAD_BUTTON_DPAD_DOWN + ICON_PF_JOYCON_DPAD_LEFT, // SDL_GAMEPAD_BUTTON_DPAD_LEFT + ICON_PF_JOYCON_DPAD_RIGHT, // SDL_GAMEPAD_BUTTON_DPAD_RIGHT +}; static constexpr const char* const* s_sdl_button_icons_list[] = { s_sdl_button_icons, // SDL_GAMEPAD_TYPE_UNKNOWN s_sdl_button_icons, // SDL_GAMEPAD_TYPE_STANDARD @@ -387,7 +408,7 @@ static constexpr const char* const* s_sdl_button_icons_list[] = { s_sdl_button_ps3_icons, // SDL_GAMEPAD_TYPE_PS3 s_sdl_button_ps4_icons, // SDL_GAMEPAD_TYPE_PS4 s_sdl_button_ps5_icons, // SDL_GAMEPAD_TYPE_PS5 - // Switch + s_sdl_button_nintendo_icons, // SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO }; static constexpr size_t s_sdl_button_iconsize_list[] = { std::size(s_sdl_button_icons), // SDL_GAMEPAD_TYPE_UNKNOWN @@ -397,7 +418,7 @@ static constexpr size_t s_sdl_button_iconsize_list[] = { std::size(s_sdl_button_ps3_icons), // SDL_GAMEPAD_TYPE_PS3 std::size(s_sdl_button_ps4_icons), // SDL_GAMEPAD_TYPE_PS4 std::size(s_sdl_button_ps5_icons), // SDL_GAMEPAD_TYPE_PS5 - // Switch + std::size(s_sdl_button_nintendo_icons), // SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO }; static constexpr const GenericInputBinding s_sdl_generic_binding_button_mapping[] = { @@ -1083,6 +1104,14 @@ TinyString SDLInputSource::ConvertKeyToIcon(InputBindingKey key) if (it != m_controllers.end()) type = SDL_GetRealGamepadType(it->gamepad); + const InputLayout glyph_preference = InputManager::GetGamepadIconPreference(); + if (glyph_preference == InputLayout::Xbox) + type = SDL_GAMEPAD_TYPE_XBOXONE; + else if (glyph_preference == InputLayout::Playstation) + type = SDL_GAMEPAD_TYPE_PS5; + else if (glyph_preference == InputLayout::Nintendo) + type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO; + if (key.source_subtype == InputSubclass::ControllerAxis) { if (key.modifier != InputModifier::FullAxis)