1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-19 12:22:57 +08:00

Merge pull request #27053 from frenzibyte/unranked-pp-placeholder

Add support for displaying "unranked PP" placeholder
This commit is contained in:
Dean Herbert 2024-02-13 18:59:55 +08:00 committed by GitHub
commit f7a223f328
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 212 additions and 69 deletions

View File

@ -154,6 +154,19 @@ namespace osu.Game.Tests.Visual.Online
}); });
} }
[Test]
public void TestUnrankedPP()
{
AddStep("Load scores with unranked PP", () =>
{
var allScores = createScores();
allScores.Scores[0].Ranked = false;
allScores.UserScore = createUserBest();
allScores.UserScore.Score.Ranked = false;
scoresContainer.Scores = allScores;
});
}
private ulong onlineID = 1; private ulong onlineID = 1;
private APIScoresCollection createScores() private APIScoresCollection createScores()
@ -184,6 +197,7 @@ namespace osu.Game.Tests.Visual.Online
MaxCombo = 1234, MaxCombo = 1234,
TotalScore = 1234567890, TotalScore = 1234567890,
Accuracy = 1, Accuracy = 1,
Ranked = true,
}, },
new SoloScoreInfo new SoloScoreInfo
{ {
@ -206,6 +220,7 @@ namespace osu.Game.Tests.Visual.Online
MaxCombo = 1234, MaxCombo = 1234,
TotalScore = 1234789, TotalScore = 1234789,
Accuracy = 0.9997, Accuracy = 0.9997,
Ranked = true,
}, },
new SoloScoreInfo new SoloScoreInfo
{ {
@ -227,6 +242,7 @@ namespace osu.Game.Tests.Visual.Online
MaxCombo = 1234, MaxCombo = 1234,
TotalScore = 12345678, TotalScore = 12345678,
Accuracy = 0.9854, Accuracy = 0.9854,
Ranked = true,
}, },
new SoloScoreInfo new SoloScoreInfo
{ {
@ -247,6 +263,7 @@ namespace osu.Game.Tests.Visual.Online
MaxCombo = 1234, MaxCombo = 1234,
TotalScore = 1234567, TotalScore = 1234567,
Accuracy = 0.8765, Accuracy = 0.8765,
Ranked = true,
}, },
new SoloScoreInfo new SoloScoreInfo
{ {
@ -263,6 +280,7 @@ namespace osu.Game.Tests.Visual.Online
MaxCombo = 1234, MaxCombo = 1234,
TotalScore = 123456, TotalScore = 123456,
Accuracy = 0.6543, Accuracy = 0.6543,
Ranked = true,
}, },
} }
}; };
@ -309,6 +327,7 @@ namespace osu.Game.Tests.Visual.Online
MaxCombo = 1234, MaxCombo = 1234,
TotalScore = 123456, TotalScore = 123456,
Accuracy = 0.6543, Accuracy = 0.6543,
Ranked = true,
}, },
Position = 1337, Position = 1337,
}; };

View File

@ -40,7 +40,8 @@ namespace osu.Game.Tests.Visual.Online
new APIMod { Acronym = new OsuModHardRock().Acronym }, new APIMod { Acronym = new OsuModHardRock().Acronym },
new APIMod { Acronym = new OsuModDoubleTime().Acronym }, new APIMod { Acronym = new OsuModDoubleTime().Acronym },
}, },
Accuracy = 0.9813 Accuracy = 0.9813,
Ranked = true,
}; };
var secondScore = new SoloScoreInfo var secondScore = new SoloScoreInfo
@ -62,7 +63,8 @@ namespace osu.Game.Tests.Visual.Online
new APIMod { Acronym = new OsuModHardRock().Acronym }, new APIMod { Acronym = new OsuModHardRock().Acronym },
new APIMod { Acronym = new OsuModDoubleTime().Acronym }, new APIMod { Acronym = new OsuModDoubleTime().Acronym },
}, },
Accuracy = 0.998546 Accuracy = 0.998546,
Ranked = true,
}; };
var thirdScore = new SoloScoreInfo var thirdScore = new SoloScoreInfo
@ -79,7 +81,8 @@ namespace osu.Game.Tests.Visual.Online
DifficultyName = "Insane" DifficultyName = "Insane"
}, },
EndedAt = DateTimeOffset.Now, EndedAt = DateTimeOffset.Now,
Accuracy = 0.9726 Accuracy = 0.9726,
Ranked = true,
}; };
var noPPScore = new SoloScoreInfo var noPPScore = new SoloScoreInfo
@ -95,7 +98,26 @@ namespace osu.Game.Tests.Visual.Online
DifficultyName = "[4K] Cataclysmic Hypernova" DifficultyName = "[4K] Cataclysmic Hypernova"
}, },
EndedAt = DateTimeOffset.Now, EndedAt = DateTimeOffset.Now,
Accuracy = 0.55879 Accuracy = 0.55879,
Ranked = true,
};
var lovedScore = new SoloScoreInfo
{
Rank = ScoreRank.B,
Beatmap = new APIBeatmap
{
BeatmapSet = new APIBeatmapSet
{
Title = "C18H27NO3(extend)",
Artist = "Team Grimoire",
},
DifficultyName = "[4K] Cataclysmic Hypernova",
Status = BeatmapOnlineStatus.Loved,
},
EndedAt = DateTimeOffset.Now,
Accuracy = 0.55879,
Ranked = true,
}; };
var unprocessedPPScore = new SoloScoreInfo var unprocessedPPScore = new SoloScoreInfo
@ -112,7 +134,26 @@ namespace osu.Game.Tests.Visual.Online
Status = BeatmapOnlineStatus.Ranked, Status = BeatmapOnlineStatus.Ranked,
}, },
EndedAt = DateTimeOffset.Now, EndedAt = DateTimeOffset.Now,
Accuracy = 0.55879 Accuracy = 0.55879,
Ranked = true,
};
var unrankedPPScore = new SoloScoreInfo
{
Rank = ScoreRank.B,
Beatmap = new APIBeatmap
{
BeatmapSet = new APIBeatmapSet
{
Title = "C18H27NO3(extend)",
Artist = "Team Grimoire",
},
DifficultyName = "[4K] Cataclysmic Hypernova",
Status = BeatmapOnlineStatus.Ranked,
},
EndedAt = DateTimeOffset.Now,
Accuracy = 0.55879,
Ranked = false,
}; };
Add(new FillFlowContainer Add(new FillFlowContainer
@ -128,7 +169,9 @@ namespace osu.Game.Tests.Visual.Online
new ColourProvidedContainer(OverlayColourScheme.Green, new DrawableProfileScore(firstScore)), new ColourProvidedContainer(OverlayColourScheme.Green, new DrawableProfileScore(firstScore)),
new ColourProvidedContainer(OverlayColourScheme.Green, new DrawableProfileScore(secondScore)), new ColourProvidedContainer(OverlayColourScheme.Green, new DrawableProfileScore(secondScore)),
new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileScore(noPPScore)), new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileScore(noPPScore)),
new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileScore(lovedScore)),
new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileScore(unprocessedPPScore)), new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileScore(unprocessedPPScore)),
new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileScore(unrankedPPScore)),
new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileWeightedScore(firstScore, 0.97)), new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileWeightedScore(firstScore, 0.97)),
new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileWeightedScore(secondScore, 0.85)), new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileWeightedScore(secondScore, 0.85)),
new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileWeightedScore(thirdScore, 0.66)), new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileWeightedScore(thirdScore, 0.66)),

View File

@ -0,0 +1,17 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
namespace osu.Game.Graphics.Sprites
{
/// <summary>
/// A <see cref="SpriteIcon"/> with a publicly settable tooltip text.
/// </summary>
public partial class SpriteIconWithTooltip : SpriteIcon, IHasTooltip
{
public LocalisableString TooltipText { get; set; }
}
}

View File

@ -0,0 +1,16 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics.Cursor;
using osu.Framework.Localisation;
namespace osu.Game.Graphics.Sprites
{
/// <summary>
/// An <see cref="OsuSpriteText"/> with a publicly settable tooltip text.
/// </summary>
internal partial class SpriteTextWithTooltip : OsuSpriteText, IHasTooltip
{
public LocalisableString TooltipText { get; set; }
}
}

View File

@ -115,6 +115,9 @@ namespace osu.Game.Online.API.Requests.Responses
[JsonProperty("has_replay")] [JsonProperty("has_replay")]
public bool HasReplay { get; set; } public bool HasReplay { get; set; }
[JsonProperty("ranked")]
public bool Ranked { get; set; }
// These properties are calculated or not relevant to any external usage. // These properties are calculated or not relevant to any external usage.
public bool ShouldSerializeID() => false; public bool ShouldSerializeID() => false;
public bool ShouldSerializeUser() => false; public bool ShouldSerializeUser() => false;
@ -213,6 +216,7 @@ namespace osu.Game.Online.API.Requests.Responses
HasOnlineReplay = HasReplay, HasOnlineReplay = HasReplay,
Mods = mods, Mods = mods,
PP = PP, PP = PP,
Ranked = Ranked,
}; };
if (beatmap is BeatmapInfo realmBeatmap) if (beatmap is BeatmapInfo realmBeatmap)

View File

@ -23,9 +23,9 @@ using osuTK.Graphics;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Sprites;
using osu.Game.Resources.Localisation.Web; using osu.Game.Resources.Localisation.Web;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Scoring.Drawables;
namespace osu.Game.Overlays.BeatmapSet.Scores namespace osu.Game.Overlays.BeatmapSet.Scores
{ {
@ -180,10 +180,26 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
if (showPerformancePoints) if (showPerformancePoints)
{ {
if (score.PP != null) if (!score.Ranked)
content.Add(new StatisticText(score.PP, format: @"N0")); {
content.Add(new SpriteTextWithTooltip
{
Text = "-",
Font = OsuFont.GetFont(size: text_size),
TooltipText = ScoresStrings.StatusNoPp
});
}
else if (score.PP == null)
{
content.Add(new SpriteIconWithTooltip
{
Icon = FontAwesome.Solid.Sync,
Size = new Vector2(text_size),
TooltipText = ScoresStrings.StatusProcessing,
});
}
else else
content.Add(new UnprocessedPerformancePointsPlaceholder { Size = new Vector2(text_size) }); content.Add(new StatisticText(score.PP, format: @"N0"));
} }
content.Add(new ScoreboardTime(score.Date, text_size) content.Add(new ScoreboardTime(score.Date, text_size)

View File

@ -22,7 +22,6 @@ using osu.Game.Resources.Localisation.Web;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Scoring.Drawables;
using osuTK; using osuTK;
namespace osu.Game.Overlays.BeatmapSet.Scores namespace osu.Game.Overlays.BeatmapSet.Scores
@ -125,10 +124,26 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
ppColumn.Alpha = value.BeatmapInfo!.Status.GrantsPerformancePoints() ? 1 : 0; ppColumn.Alpha = value.BeatmapInfo!.Status.GrantsPerformancePoints() ? 1 : 0;
if (value.PP is double pp) if (!value.Ranked)
ppColumn.Text = pp.ToLocalisableString(@"N0"); {
ppColumn.Drawable = new SpriteTextWithTooltip
{
Text = "-",
Font = smallFont,
TooltipText = ScoresStrings.StatusNoPp
};
}
else if (value.PP is not double pp)
{
ppColumn.Drawable = new SpriteIconWithTooltip
{
Icon = FontAwesome.Solid.Sync,
Size = new Vector2(smallFont.Size),
TooltipText = ScoresStrings.StatusProcessing,
};
}
else else
ppColumn.Drawable = new UnprocessedPerformancePointsPlaceholder { Size = new Vector2(smallFont.Size) }; ppColumn.Text = pp.ToLocalisableString(@"N0");
statisticsColumns.ChildrenEnumerable = value.GetStatisticsForDisplay().Select(createStatisticsColumn); statisticsColumns.ChildrenEnumerable = value.GetStatisticsForDisplay().Select(createStatisticsColumn);
modsColumn.Mods = value.Mods; modsColumn.Mods = value.Mods;

View File

@ -8,16 +8,17 @@ using osu.Framework.Extensions.ObjectExtensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation; using osu.Framework.Localisation;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Leaderboards; using osu.Game.Online.Leaderboards;
using osu.Game.Resources.Localisation.Web;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Scoring.Drawables;
using osu.Game.Utils; using osu.Game.Utils;
using osuTK; using osuTK;
@ -213,42 +214,75 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
private Drawable createDrawablePerformance() private Drawable createDrawablePerformance()
{ {
if (!Score.PP.HasValue) var font = OsuFont.GetFont(weight: FontWeight.Bold);
{
if (Score.Beatmap?.Status.GrantsPerformancePoints() == true)
return new UnprocessedPerformancePointsPlaceholder { Size = new Vector2(16), Colour = colourProvider.Highlight1 };
return new OsuSpriteText if (Score.PP.HasValue)
{
return new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Direction = FillDirection.Horizontal,
Children = new[]
{
new OsuSpriteText
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Font = font,
Text = $"{Score.PP:0}",
Colour = colourProvider.Highlight1
},
new OsuSpriteText
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Font = font.With(size: 12),
Text = "pp",
Colour = colourProvider.Light3
}
}
};
}
if (Score.Beatmap?.Status.GrantsPerformancePoints() != true)
{
if (Score.Beatmap?.Status == BeatmapOnlineStatus.Loved)
{
return new SpriteIconWithTooltip
{
Icon = FontAwesome.Solid.Heart,
Size = new Vector2(font.Size),
TooltipText = UsersStrings.ShowExtraTopRanksNotRanked,
Colour = colourProvider.Highlight1
};
}
return new SpriteTextWithTooltip
{ {
Font = OsuFont.GetFont(weight: FontWeight.Bold),
Text = "-", Text = "-",
Font = OsuFont.GetFont(weight: FontWeight.Bold),
TooltipText = UsersStrings.ShowExtraTopRanksNotRanked,
Colour = colourProvider.Highlight1 Colour = colourProvider.Highlight1
}; };
} }
return new FillFlowContainer if (!Score.Ranked)
{ {
AutoSizeAxes = Axes.Both, return new SpriteTextWithTooltip
Direction = FillDirection.Horizontal,
Children = new[]
{ {
new OsuSpriteText Text = "-",
{ Font = OsuFont.GetFont(weight: FontWeight.Bold),
Anchor = Anchor.BottomLeft, TooltipText = ScoresStrings.StatusNoPp,
Origin = Anchor.BottomLeft, Colour = colourProvider.Highlight1
Font = OsuFont.GetFont(weight: FontWeight.Bold), };
Text = $"{Score.PP:0}", }
Colour = colourProvider.Highlight1
}, return new SpriteIconWithTooltip
new OsuSpriteText {
{ Icon = FontAwesome.Solid.Sync,
Anchor = Anchor.BottomLeft, Size = new Vector2(font.Size),
Origin = Anchor.BottomLeft, TooltipText = ScoresStrings.StatusProcessing,
Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), Colour = colourProvider.Highlight1
Text = "pp",
Colour = colourProvider.Light3
}
}
}; };
} }

View File

@ -1,27 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
#nullable disable
using osu.Framework.Graphics;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Localisation;
using osu.Game.Resources.Localisation.Web;
namespace osu.Game.Scoring.Drawables
{
/// <summary>
/// A placeholder used in PP columns for scores with unprocessed PP value.
/// </summary>
public partial class UnprocessedPerformancePointsPlaceholder : SpriteIcon, IHasTooltip
{
public LocalisableString TooltipText => ScoresStrings.StatusProcessing;
public UnprocessedPerformancePointsPlaceholder()
{
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Icon = FontAwesome.Solid.ExclamationTriangle;
}
}
}

View File

@ -107,6 +107,12 @@ namespace osu.Game.Scoring
public double? PP { get; set; } public double? PP { get; set; }
/// <summary>
/// Whether the performance points in this score is awarded to the player. This is used for online display purposes (see <see cref="SoloScoreInfo.Ranked"/>).
/// </summary>
[Ignored]
public bool Ranked { get; set; }
/// <summary> /// <summary>
/// The online ID of this score. /// The online ID of this score.
/// </summary> /// </summary>

View File

@ -37,7 +37,7 @@
</PackageReference> </PackageReference>
<PackageReference Include="Realm" Version="11.5.0" /> <PackageReference Include="Realm" Version="11.5.0" />
<PackageReference Include="ppy.osu.Framework" Version="2024.205.0" /> <PackageReference Include="ppy.osu.Framework" Version="2024.205.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2024.129.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2024.207.0" />
<PackageReference Include="Sentry" Version="3.41.3" /> <PackageReference Include="Sentry" Version="3.41.3" />
<!-- Held back due to 0.34.0 failing AOT compilation on ZstdSharp.dll dependency. --> <!-- Held back due to 0.34.0 failing AOT compilation on ZstdSharp.dll dependency. -->
<PackageReference Include="SharpCompress" Version="0.36.0" /> <PackageReference Include="SharpCompress" Version="0.36.0" />