Achievements: Add point count to unlock popup

pull/3594/head
Stenzek 3 weeks ago
parent b237604ac7
commit 5818a05be3
No known key found for this signature in database

@ -1263,16 +1263,16 @@ void Achievements::DisplayAchievementSummary()
FullscreenUI::AddNotification("AchievementsSummary", FullscreenUI::AddNotification("AchievementsSummary",
IsHardcoreModeActive() ? ACHIEVEMENT_SUMMARY_NOTIFICATION_TIME_HC : IsHardcoreModeActive() ? ACHIEVEMENT_SUMMARY_NOTIFICATION_TIME_HC :
ACHIEVEMENT_SUMMARY_NOTIFICATION_TIME, ACHIEVEMENT_SUMMARY_NOTIFICATION_TIME,
s_state.game_title, std::string(summary), s_state.game_icon); s_state.game_icon, s_state.game_title, std::string(summary), {});
if (s_state.game_summary.num_unsupported_achievements > 0) if (s_state.game_summary.num_unsupported_achievements > 0)
{ {
FullscreenUI::AddNotification( FullscreenUI::AddNotification(
"UnsupportedAchievements", ACHIEVEMENT_SUMMARY_UNSUPPORTED_TIME, "UnsupportedAchievements", ACHIEVEMENT_SUMMARY_UNSUPPORTED_TIME, "images/warning.svg",
TRANSLATE_STR("Achievements", "Unsupported Achievements"), TRANSLATE_STR("Achievements", "Unsupported Achievements"),
TRANSLATE_PLURAL_STR("Achievements", "%n achievements are not supported by DuckStation.", "Achievement popup", TRANSLATE_PLURAL_STR("Achievements", "%n achievements are not supported by DuckStation.", "Achievement popup",
s_state.game_summary.num_unsupported_achievements), s_state.game_summary.num_unsupported_achievements),
"images/warning.svg"); {});
} }
} }
@ -1312,9 +1312,12 @@ void Achievements::HandleUnlockEvent(const rc_client_event_t* event)
else else
title = cheevo->title; title = cheevo->title;
std::string note = fmt::format(ICON_EMOJI_TROPHY " {}", cheevo->points);
FullscreenUI::AddNotification(fmt::format("achievement_unlock_{}", cheevo->id), FullscreenUI::AddNotification(fmt::format("achievement_unlock_{}", cheevo->id),
static_cast<float>(g_settings.achievements_notification_duration), std::move(title), static_cast<float>(g_settings.achievements_notification_duration),
cheevo->description, GetAchievementBadgePath(cheevo, false)); GetAchievementBadgePath(cheevo, false), std::move(title),
std::string(cheevo->description), std::move(note));
} }
if (g_settings.achievements_sound_effects) if (g_settings.achievements_sound_effects)
@ -1333,9 +1336,10 @@ void Achievements::HandleGameCompleteEvent(const rc_client_event_t* event)
TRANSLATE_PLURAL_STR("Achievements", "%n achievements", "Mastery popup", TRANSLATE_PLURAL_STR("Achievements", "%n achievements", "Mastery popup",
s_state.game_summary.num_unlocked_achievements), s_state.game_summary.num_unlocked_achievements),
TRANSLATE_PLURAL_STR("Achievements", "%n points", "Achievement points", s_state.game_summary.points_unlocked)); TRANSLATE_PLURAL_STR("Achievements", "%n points", "Achievement points", s_state.game_summary.points_unlocked));
std::string note = fmt::format(ICON_EMOJI_TROPHY " {}", s_state.game_summary.points_unlocked);
FullscreenUI::AddNotification("achievement_mastery", GAME_COMPLETE_NOTIFICATION_TIME, s_state.game_title, FullscreenUI::AddNotification("achievement_mastery", GAME_COMPLETE_NOTIFICATION_TIME, s_state.game_icon,
std::move(message), s_state.game_icon); s_state.game_title, std::move(message), std::move(note));
} }
} }
@ -1364,8 +1368,8 @@ void Achievements::HandleSubsetCompleteEvent(const rc_client_event_t* event)
s_state.game_summary.num_unlocked_achievements), s_state.game_summary.num_unlocked_achievements),
TRANSLATE_PLURAL_STR("Achievements", "%n points", "Achievement points", s_state.game_summary.points_unlocked)); TRANSLATE_PLURAL_STR("Achievements", "%n points", "Achievement points", s_state.game_summary.points_unlocked));
FullscreenUI::AddNotification("achievement_mastery", GAME_COMPLETE_NOTIFICATION_TIME, event->subset->title, FullscreenUI::AddNotification("achievement_mastery", GAME_COMPLETE_NOTIFICATION_TIME, std::move(badge_path),
std::move(message), std::move(badge_path)); std::string(event->subset->title), std::move(message), {});
} }
} }
@ -1375,9 +1379,9 @@ void Achievements::HandleLeaderboardStartedEvent(const rc_client_event_t* event)
if (g_settings.achievements_leaderboard_notifications) if (g_settings.achievements_leaderboard_notifications)
{ {
FullscreenUI::AddNotification(fmt::format("leaderboard_{}", event->leaderboard->id), FullscreenUI::AddNotification(
LEADERBOARD_STARTED_NOTIFICATION_TIME, event->leaderboard->title, fmt::format("leaderboard_{}", event->leaderboard->id), LEADERBOARD_STARTED_NOTIFICATION_TIME, s_state.game_icon,
TRANSLATE_STR("Achievements", "Leaderboard attempt started."), s_state.game_icon); std::string(event->leaderboard->title), TRANSLATE_STR("Achievements", "Leaderboard attempt started."), {});
} }
} }
@ -1387,9 +1391,9 @@ void Achievements::HandleLeaderboardFailedEvent(const rc_client_event_t* event)
if (g_settings.achievements_leaderboard_notifications) if (g_settings.achievements_leaderboard_notifications)
{ {
FullscreenUI::AddNotification(fmt::format("leaderboard_{}", event->leaderboard->id), FullscreenUI::AddNotification(
LEADERBOARD_FAILED_NOTIFICATION_TIME, event->leaderboard->title, fmt::format("leaderboard_{}", event->leaderboard->id), LEADERBOARD_FAILED_NOTIFICATION_TIME, s_state.game_icon,
TRANSLATE_STR("Achievements", "Leaderboard attempt failed."), s_state.game_icon); std::string(event->leaderboard->title), TRANSLATE_STR("Achievements", "Leaderboard attempt failed."), {});
} }
} }
@ -1413,8 +1417,8 @@ void Achievements::HandleLeaderboardSubmittedEvent(const rc_client_event_t* even
g_settings.achievements_spectator_mode ? std::string_view() : TRANSLATE_SV("Achievements", " (Submitting)")); g_settings.achievements_spectator_mode ? std::string_view() : TRANSLATE_SV("Achievements", " (Submitting)"));
FullscreenUI::AddNotification(fmt::format("leaderboard_{}", event->leaderboard->id), FullscreenUI::AddNotification(fmt::format("leaderboard_{}", event->leaderboard->id),
static_cast<float>(g_settings.achievements_leaderboard_duration), static_cast<float>(g_settings.achievements_leaderboard_duration), s_state.game_icon,
event->leaderboard->title, std::move(message), s_state.game_icon); std::string(event->leaderboard->title), std::move(message), {});
} }
if (g_settings.achievements_sound_effects) if (g_settings.achievements_sound_effects)
@ -1444,8 +1448,8 @@ void Achievements::HandleLeaderboardScoreboardEvent(const rc_client_event_t* eve
event->leaderboard_scoreboard->new_rank, event->leaderboard_scoreboard->num_entries); event->leaderboard_scoreboard->new_rank, event->leaderboard_scoreboard->num_entries);
FullscreenUI::AddNotification(fmt::format("leaderboard_{}", event->leaderboard->id), FullscreenUI::AddNotification(fmt::format("leaderboard_{}", event->leaderboard->id),
static_cast<float>(g_settings.achievements_leaderboard_duration), std::move(title), static_cast<float>(g_settings.achievements_leaderboard_duration), s_state.game_icon,
std::move(message), s_state.game_icon); std::move(title), std::move(message), {});
} }
} }
@ -1518,11 +1522,11 @@ void Achievements::HandleAchievementChallengeIndicatorShowEvent(const rc_client_
// we still track these even if the option is disabled, so that they can be displayed in the pause menu // we still track these even if the option is disabled, so that they can be displayed in the pause menu
if (g_settings.achievements_challenge_indicator_mode == AchievementChallengeIndicatorMode::Notification) if (g_settings.achievements_challenge_indicator_mode == AchievementChallengeIndicatorMode::Notification)
{ {
FullscreenUI::AddNotification( FullscreenUI::AddNotification(fmt::format("AchievementChallenge{}", event->achievement->id),
fmt::format("AchievementChallenge{}", event->achievement->id), CHALLENGE_STARTED_NOTIFICATION_TIME, CHALLENGE_STARTED_NOTIFICATION_TIME, std::move(badge_path),
fmt::format(TRANSLATE_FS("Achievements", "Challenge Started: {}"), fmt::format(TRANSLATE_FS("Achievements", "Challenge Started: {}"),
event->achievement->title ? event->achievement->title : ""), event->achievement->title ? event->achievement->title : ""),
event->achievement->description ? event->achievement->description : "", std::move(badge_path)); event->achievement->description, {});
} }
s_state.active_challenge_indicators.push_back( s_state.active_challenge_indicators.push_back(
@ -1549,10 +1553,10 @@ void Achievements::HandleAchievementChallengeIndicatorHideEvent(const rc_client_
{ {
FullscreenUI::AddNotification(fmt::format("AchievementChallenge{}", event->achievement->id), FullscreenUI::AddNotification(fmt::format("AchievementChallenge{}", event->achievement->id),
CHALLENGE_FAILED_NOTIFICATION_TIME, CHALLENGE_FAILED_NOTIFICATION_TIME,
GetAchievementBadgePath(event->achievement, false),
fmt::format(TRANSLATE_FS("Achievements", "Challenge Failed: {}"), fmt::format(TRANSLATE_FS("Achievements", "Challenge Failed: {}"),
event->achievement->title ? event->achievement->title : ""), event->achievement->title ? event->achievement->title : ""),
event->achievement->description ? event->achievement->description : "", event->achievement->description, {});
GetAchievementBadgePath(event->achievement, false));
} }
if (g_settings.achievements_challenge_indicator_mode == AchievementChallengeIndicatorMode::Notification || if (g_settings.achievements_challenge_indicator_mode == AchievementChallengeIndicatorMode::Notification ||
g_settings.achievements_challenge_indicator_mode == AchievementChallengeIndicatorMode::Disabled) g_settings.achievements_challenge_indicator_mode == AchievementChallengeIndicatorMode::Disabled)
@ -1946,12 +1950,12 @@ void Achievements::ClientLoginWithTokenCallback(int result, const char* error_me
if (System::IsValid()) if (System::IsValid())
{ {
FullscreenUI::AddNotification( FullscreenUI::AddNotification(
"AchievementsLoginFailed", Host::OSD_ERROR_DURATION, "AchievementsLoginFailed", Host::OSD_ERROR_DURATION, "images/warning.svg",
TRANSLATE_STR("Achievements", "RetroAchievements Login Failed"), TRANSLATE_STR("Achievements", "RetroAchievements Login Failed"),
fmt::format( fmt::format(
TRANSLATE_FS("Achievements", "Achievement unlocks will not be submitted for this session.\nError: {}"), TRANSLATE_FS("Achievements", "Achievement unlocks will not be submitted for this session.\nError: {}"),
error_message), error_message),
"images/warning.svg"); {});
} }
return; return;
@ -1990,8 +1994,8 @@ void Achievements::FinishLogin()
std::string summary = fmt::format(TRANSLATE_FS("Achievements", "Score: {} ({} softcore)\nUnread messages: {}"), std::string summary = fmt::format(TRANSLATE_FS("Achievements", "Score: {} ({} softcore)\nUnread messages: {}"),
user->score, user->score_softcore, user->num_unread_messages); user->score, user->score_softcore, user->num_unread_messages);
FullscreenUI::AddNotification("achievements_login", LOGIN_NOTIFICATION_TIME, user->display_name, std::move(summary), FullscreenUI::AddNotification("achievements_login", LOGIN_NOTIFICATION_TIME, s_state.user_badge_path,
s_state.user_badge_path); user->display_name, std::move(summary), {});
} }
} }

@ -139,6 +139,7 @@ struct Notification
std::string key; std::string key;
std::string title; std::string title;
std::string text; std::string text;
std::string note;
std::string badge_path; std::string badge_path;
Timer::Value start_time; Timer::Value start_time;
Timer::Value move_time; Timer::Value move_time;
@ -4695,8 +4696,8 @@ void FullscreenUI::UpdateNotificationsRunIdle()
[]() { GPUThread::SetRunIdleReason(GPUThread::RunIdleReason::NotificationsActive, AreAnyNotificationsActive()); }); []() { GPUThread::SetRunIdleReason(GPUThread::RunIdleReason::NotificationsActive, AreAnyNotificationsActive()); });
} }
void FullscreenUI::AddNotification(std::string key, float duration, std::string title, std::string text, void FullscreenUI::AddNotification(std::string key, float duration, std::string image_path, std::string title,
std::string image_path) std::string text, std::string note)
{ {
const std::unique_lock lock(s_state.shared_state_mutex); const std::unique_lock lock(s_state.shared_state_mutex);
if (!s_state.has_initialized) if (!s_state.has_initialized)
@ -4714,6 +4715,7 @@ void FullscreenUI::AddNotification(std::string key, float duration, std::string
it->duration = duration; it->duration = duration;
it->title = std::move(title); it->title = std::move(title);
it->text = std::move(text); it->text = std::move(text);
it->note = std::move(note);
it->badge_path = std::move(image_path); it->badge_path = std::move(image_path);
// Don't fade it in again // Don't fade it in again
@ -4730,6 +4732,7 @@ void FullscreenUI::AddNotification(std::string key, float duration, std::string
notif.duration = duration; notif.duration = duration;
notif.title = std::move(title); notif.title = std::move(title);
notif.text = std::move(text); notif.text = std::move(text);
notif.note = std::move(note);
notif.badge_path = std::move(image_path); notif.badge_path = std::move(image_path);
notif.start_time = current_time; notif.start_time = current_time;
notif.move_time = current_time; notif.move_time = current_time;
@ -4761,12 +4764,13 @@ void FullscreenUI::DrawNotifications(ImVec2& position, float spacing)
const float shadow_size = FullscreenUI::LayoutScale(2.0f); const float shadow_size = FullscreenUI::LayoutScale(2.0f);
const float rounding = FullscreenUI::LayoutScale(20.0f); const float rounding = FullscreenUI::LayoutScale(20.0f);
ImFont* const title_font = UIStyle.Font; ImFont*& font = UIStyle.Font;
const float title_font_size = UIStyle.LargeFontSize; const float& title_font_size = UIStyle.LargeFontSize;
const float title_font_weight = UIStyle.BoldFontWeight; const float& title_font_weight = UIStyle.BoldFontWeight;
ImFont* const text_font = UIStyle.Font; const float& text_font_size = UIStyle.MediumFontSize;
const float text_font_size = UIStyle.MediumFontSize; const float& text_font_weight = UIStyle.NormalFontWeight;
const float text_font_weight = UIStyle.NormalFontWeight; const float& note_font_size = UIStyle.MediumFontSize;
const float& note_font_weight = UIStyle.BoldFontWeight;
for (u32 index = 0; index < static_cast<u32>(s_state.notifications.size());) for (u32 index = 0; index < static_cast<u32>(s_state.notifications.size());)
{ {
@ -4778,9 +4782,13 @@ void FullscreenUI::DrawNotifications(ImVec2& position, float spacing)
continue; continue;
} }
const ImVec2 title_size = title_font->CalcTextSizeA(title_font_size, title_font_weight, max_text_width, // place note to the right of the title
max_text_width, IMSTR_START_END(notif.title)); const ImVec2 note_size = notif.note.empty() ? ImVec2() :
const ImVec2 text_size = text_font->CalcTextSizeA(text_font_size, text_font_weight, max_text_width, max_text_width, font->CalcTextSizeA(note_font_size, note_font_weight, FLT_MAX, 0.0f,
IMSTR_START_END(notif.note));
const ImVec2 title_size = font->CalcTextSizeA(title_font_size, title_font_weight, max_text_width - note_size.x,
max_text_width - note_size.x, IMSTR_START_END(notif.title));
const ImVec2 text_size = font->CalcTextSizeA(text_font_size, text_font_weight, max_text_width, max_text_width,
IMSTR_START_END(notif.text)); IMSTR_START_END(notif.text));
float box_width = std::max((horizontal_padding * 2.0f) + badge_size + horizontal_spacing + float box_width = std::max((horizontal_padding * 2.0f) + badge_size + horizontal_spacing +
@ -4860,14 +4868,22 @@ void FullscreenUI::DrawNotifications(ImVec2& position, float spacing)
const ImVec2 title_pos = ImVec2(badge_max.x + horizontal_spacing, box_min.y + vertical_padding); const ImVec2 title_pos = ImVec2(badge_max.x + horizontal_spacing, box_min.y + vertical_padding);
const ImRect title_bb = ImRect(title_pos, title_pos + title_size); const ImRect title_bb = ImRect(title_pos, title_pos + title_size);
RenderShadowedTextClipped(dl, title_font, title_font_size, title_font_weight, title_bb.Min, title_bb.Max, title_col, RenderShadowedTextClipped(dl, font, title_font_size, title_font_weight, title_bb.Min, title_bb.Max, title_col,
notif.title, &title_size, ImVec2(0.0f, 0.0f), max_text_width, &title_bb); notif.title, &title_size, ImVec2(0.0f, 0.0f), max_text_width - note_size.x, &title_bb);
const ImVec2 text_pos = ImVec2(badge_max.x + horizontal_spacing, title_bb.Max.y + vertical_spacing); const ImVec2 text_pos = ImVec2(badge_max.x + horizontal_spacing, title_bb.Max.y + vertical_spacing);
const ImRect text_bb = ImRect(text_pos, text_pos + text_size); const ImRect text_bb = ImRect(text_pos, text_pos + text_size);
RenderShadowedTextClipped(dl, text_font, text_font_size, text_font_weight, text_bb.Min, text_bb.Max, text_col, RenderShadowedTextClipped(dl, font, text_font_size, text_font_weight, text_bb.Min, text_bb.Max, text_col,
notif.text, &text_size, ImVec2(0.0f, 0.0f), max_text_width, &text_bb); notif.text, &text_size, ImVec2(0.0f, 0.0f), max_text_width, &text_bb);
if (!notif.note.empty())
{
const ImVec2 note_pos = ImVec2(box_max.x - horizontal_padding - note_size.x, box_min.y + vertical_padding);
const ImRect note_bb = ImRect(note_pos, note_pos + note_size);
RenderShadowedTextClipped(dl, font, note_font_size, note_font_weight, note_bb.Min, note_bb.Max, title_col,
notif.note, &note_size, ImVec2(0.0f, 0.0f), max_text_width, &note_bb);
}
if (clip_box) if (clip_box)
dl->PopClipRect(); dl->PopClipRect();

@ -491,7 +491,8 @@ bool IsLoadingScreenOpen();
void CloseLoadingScreen(); void CloseLoadingScreen();
/// Notification and toast support. /// Notification and toast support.
void AddNotification(std::string key, float duration, std::string title, std::string text, std::string image_path); void AddNotification(std::string key, float duration, std::string image_path, std::string title, std::string text,
std::string note);
void ShowToast(std::string title, std::string message, float duration = 10.0f); void ShowToast(std::string title, std::string message, float duration = 10.0f);
// Wrapper for an animated popup dialog. // Wrapper for an animated popup dialog.

Loading…
Cancel
Save