From 9275e1ad776d7f94e8d6bf723a95b9eb545f6512 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sun, 12 Apr 2026 12:15:04 +1000 Subject: [PATCH] Achievements: Add RA SVG icon variant Can't be used for everything. --- data/resources/images/ra-icon.svg | 44 +++++++++++++++++++ src/core/achievements.cpp | 9 ++-- src/core/achievements.h | 1 + src/core/fullscreenui_achievements.cpp | 4 +- src/core/fullscreenui_settings.cpp | 18 ++++---- src/duckstation-qt/achievementlogindialog.cpp | 2 +- 6 files changed, 63 insertions(+), 15 deletions(-) create mode 100644 data/resources/images/ra-icon.svg diff --git a/data/resources/images/ra-icon.svg b/data/resources/images/ra-icon.svg new file mode 100644 index 000000000..7abbbd7fd --- /dev/null +++ b/data/resources/images/ra-icon.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + diff --git a/src/core/achievements.cpp b/src/core/achievements.cpp index 957c3dea8..94c609f0d 100644 --- a/src/core/achievements.cpp +++ b/src/core/achievements.cpp @@ -74,6 +74,7 @@ static constexpr const char* UNLOCK_SOUND_NAME = "sounds/achievements/unlock.wav static constexpr const char* LBSUBMIT_SOUND_NAME = "sounds/achievements/lbsubmit.wav"; static constexpr const char* CACHE_SUBDIRECTORY_NAME = "achievement_images"; constexpr const char* const RA_LOGO_ICON_NAME = "images/ra-icon.webp"; +constexpr const char* const RA_LOGO_SVG_ICON_NAME = "images/ra-icon.svg"; static constexpr float LOGIN_NOTIFICATION_TIME = 5.0f; static constexpr float ACHIEVEMENT_SUMMARY_NOTIFICATION_TIME = 5.0f; @@ -1537,14 +1538,14 @@ void Achievements::DisplayAchievementSummary() if (rc_client_get_spectator_mode_enabled(s_state.client)) { Host::AddIconOSDMessage( - OSDMessageType::Warning, "SpectatorOrEncoreMode", RA_LOGO_ICON_NAME, + OSDMessageType::Warning, "SpectatorOrEncoreMode", RA_LOGO_SVG_ICON_NAME, TRANSLATE_STR("Achievements", "Spectator mode enabled."), TRANSLATE_STR("Achievements", "All achievements are locked, and unlocks will not be recorded in your account.")); } else if (rc_client_get_encore_mode_enabled(s_state.client)) { Host::AddIconOSDMessage( - OSDMessageType::Warning, "SpectatorOrEncoreMode", RA_LOGO_ICON_NAME, + OSDMessageType::Warning, "SpectatorOrEncoreMode", RA_LOGO_SVG_ICON_NAME, TRANSLATE_STR("Achievements", "Encore mode enabled."), TRANSLATE_STR("Achievements", "All achievements are locked, but unlocks will still be recorded in your account.")); @@ -1951,7 +1952,7 @@ void Achievements::HandleServerReconnectedEvent(const rc_client_event_t* event) { WARNING_LOG("Server reconnected."); - Host::AddIconOSDMessage(OSDMessageType::Warning, "AchievementsDisconnected", RA_LOGO_ICON_NAME, + Host::AddIconOSDMessage(OSDMessageType::Warning, "AchievementsDisconnected", RA_LOGO_SVG_ICON_NAME, TRANSLATE_STR("Achievements", "Achievements Reconnected"), TRANSLATE_STR("Achievements", "All pending unlock requests have completed.")); } @@ -1985,7 +1986,7 @@ void Achievements::OnHardcoreModeChanged(bool enabled, bool display_message, boo if (System::IsValid() && display_message) { - Host::AddIconOSDMessage(OSDMessageType::Info, "AchievementsHardcoreModeChanged", RA_LOGO_ICON_NAME, + Host::AddIconOSDMessage(OSDMessageType::Info, "AchievementsHardcoreModeChanged", RA_LOGO_SVG_ICON_NAME, enabled ? TRANSLATE_STR("Achievements", "Hardcore mode enabled.") : TRANSLATE_STR("Achievements", "Hardcore mode disabled."), enabled ? TRANSLATE_STR("Achievements", "Restrictions are now active.") : diff --git a/src/core/achievements.h b/src/core/achievements.h index e010226d8..6cf53d353 100644 --- a/src/core/achievements.h +++ b/src/core/achievements.h @@ -200,6 +200,7 @@ u32 GetPendingUnlockCount(); /// The name of the RetroAchievements icon, which can be used in notifications. extern const char* const RA_LOGO_ICON_NAME; +extern const char* const RA_LOGO_SVG_ICON_NAME; } // namespace Achievements diff --git a/src/core/fullscreenui_achievements.cpp b/src/core/fullscreenui_achievements.cpp index 6af15283e..da0b3d089 100644 --- a/src/core/fullscreenui_achievements.cpp +++ b/src/core/fullscreenui_achievements.cpp @@ -1499,7 +1499,7 @@ void FullscreenUI::OpenAchievementsWindow() if (const auto lock = Achievements::GetLock(); !Achievements::IsActive() || !Achievements::HasAchievements()) { - Host::AddIconOSDMessage(OSDMessageType::Info, "AchievementsUnavailable", Achievements::RA_LOGO_ICON_NAME, + Host::AddIconOSDMessage(OSDMessageType::Info, "AchievementsUnavailable", Achievements::RA_LOGO_SVG_ICON_NAME, TRANSLATE_STR("Achievements", "Achievements are not available."), Achievements::IsActive() ? TRANSLATE_STR("Achievements", "This game has no achievements.") : @@ -2405,7 +2405,7 @@ void FullscreenUI::OpenLeaderboardsWindow() if (const auto lock = Achievements::GetLock(); !Achievements::IsActive() || !Achievements::HasLeaderboards()) { - Host::AddIconOSDMessage(OSDMessageType::Info, "LeaderboardsUnavailable", Achievements::RA_LOGO_ICON_NAME, + Host::AddIconOSDMessage(OSDMessageType::Info, "LeaderboardsUnavailable", Achievements::RA_LOGO_SVG_ICON_NAME, TRANSLATE_STR("Achievements", "Leaderboards are not available."), Achievements::IsActive() ? TRANSLATE_STR("Achievements", "This game has no leaderboards.") : diff --git a/src/core/fullscreenui_settings.cpp b/src/core/fullscreenui_settings.cpp index 8ddf51d1c..3f8c73543 100644 --- a/src/core/fullscreenui_settings.cpp +++ b/src/core/fullscreenui_settings.cpp @@ -5195,21 +5195,23 @@ void FullscreenUI::DrawAchievementsLoginWindow() return; } - const std::string_view ra_title = "RetroAchivements"; + static constexpr std::string_view ra_title = "RetroAchivements"; const ImVec2 ra_title_size = UIStyle.Font->CalcTextSizeA(UIStyle.LargeFontSize, UIStyle.BoldFontWeight, FLT_MAX, 0.0f, IMSTR_START_END(ra_title)); const float ra_title_spacing = LayoutScale(10.0f); - GPUTexture* ra_logo = GetCachedTexture("images/ra-icon.webp"); - const ImVec2 ra_logo_size = ImVec2(UIStyle.LargeFontSize * 1.85f, UIStyle.LargeFontSize); - const ImVec2 ra_logo_imgsize = CenterImage(ra_logo_size, ra_logo).GetSize(); + const ImVec2 ra_logo_size = ImVec2(UIStyle.LargeFontSize * 2.0f, UIStyle.LargeFontSize); + const ImRect ra_logo_rect = CenterImage(ra_logo_size, ImVec2(454.0f, 245.0f)); + GPUTexture* const ra_logo = + GetCachedTexture(Achievements::RA_LOGO_SVG_ICON_NAME, static_cast(ra_logo_rect.GetWidth()), + static_cast(ra_logo_rect.GetHeight())); const ImRect work_rect = ImGui::GetCurrentWindow()->WorkRect; const float indent = (work_rect.GetWidth() - (ra_logo_size.x + ra_title_spacing + ra_title_size.x)) * 0.5f; ImDrawList* const dl = ImGui::GetWindowDrawList(); const ImVec2 ra_logo_pos = work_rect.Min + ImVec2(indent, 0.0f); - dl->AddImage(ra_logo, ra_logo_pos, ra_logo_pos + ra_logo_imgsize); - dl->AddText(UIStyle.Font, UIStyle.LargeFontSize, UIStyle.BoldFontWeight, - ra_logo_pos + ImVec2(ra_logo_size.x + ra_title_spacing, 0.0f), ImGui::GetColorU32(ImGuiCol_Text), - IMSTR_START_END(ra_title)); + dl->AddImage(ra_logo, ra_logo_pos + ra_logo_rect.Min, ra_logo_pos + ra_logo_rect.Max); + const ImVec2 title_pos = ra_logo_pos + ImVec2(ra_logo_size.x + ra_title_spacing, 0.0f); + RenderShadowedTextClipped(dl, UIStyle.Font, UIStyle.LargeFontSize, UIStyle.BoldFontWeight, title_pos, + title_pos + ra_title_size, ImGui::GetColorU32(ImGuiCol_Text), ra_title, &ra_title_size); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ra_logo_size.y + LayoutScale(15.0f)); diff --git a/src/duckstation-qt/achievementlogindialog.cpp b/src/duckstation-qt/achievementlogindialog.cpp index 6509ba1f8..ac2420615 100644 --- a/src/duckstation-qt/achievementlogindialog.cpp +++ b/src/duckstation-qt/achievementlogindialog.cpp @@ -15,7 +15,7 @@ AchievementLoginDialog::AchievementLoginDialog(QWidget* parent, Achievements::Lo : QDialog(parent), m_reason(reason) { m_ui.setupUi(this); - m_ui.iconLabel->setPixmap(QPixmap(QtHost::GetResourceQPath("images/ra-icon.webp", true))); + m_ui.iconLabel->setPixmap(QPixmap(QtHost::GetResourceQPath(Achievements::RA_LOGO_SVG_ICON_NAME, true))); QFont title_font(m_ui.titleLabel->font()); title_font.setBold(true); title_font.setPixelSize(20);