1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 11:42:56 +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 APIScoresCollection createScores()
@ -184,6 +197,7 @@ namespace osu.Game.Tests.Visual.Online
MaxCombo = 1234,
TotalScore = 1234567890,
Accuracy = 1,
Ranked = true,
},
new SoloScoreInfo
{
@ -206,6 +220,7 @@ namespace osu.Game.Tests.Visual.Online
MaxCombo = 1234,
TotalScore = 1234789,
Accuracy = 0.9997,
Ranked = true,
},
new SoloScoreInfo
{
@ -227,6 +242,7 @@ namespace osu.Game.Tests.Visual.Online
MaxCombo = 1234,
TotalScore = 12345678,
Accuracy = 0.9854,
Ranked = true,
},
new SoloScoreInfo
{
@ -247,6 +263,7 @@ namespace osu.Game.Tests.Visual.Online
MaxCombo = 1234,
TotalScore = 1234567,
Accuracy = 0.8765,
Ranked = true,
},
new SoloScoreInfo
{
@ -263,6 +280,7 @@ namespace osu.Game.Tests.Visual.Online
MaxCombo = 1234,
TotalScore = 123456,
Accuracy = 0.6543,
Ranked = true,
},
}
};
@ -309,6 +327,7 @@ namespace osu.Game.Tests.Visual.Online
MaxCombo = 1234,
TotalScore = 123456,
Accuracy = 0.6543,
Ranked = true,
},
Position = 1337,
};

View File

@ -40,7 +40,8 @@ namespace osu.Game.Tests.Visual.Online
new APIMod { Acronym = new OsuModHardRock().Acronym },
new APIMod { Acronym = new OsuModDoubleTime().Acronym },
},
Accuracy = 0.9813
Accuracy = 0.9813,
Ranked = true,
};
var secondScore = new SoloScoreInfo
@ -62,7 +63,8 @@ namespace osu.Game.Tests.Visual.Online
new APIMod { Acronym = new OsuModHardRock().Acronym },
new APIMod { Acronym = new OsuModDoubleTime().Acronym },
},
Accuracy = 0.998546
Accuracy = 0.998546,
Ranked = true,
};
var thirdScore = new SoloScoreInfo
@ -79,7 +81,8 @@ namespace osu.Game.Tests.Visual.Online
DifficultyName = "Insane"
},
EndedAt = DateTimeOffset.Now,
Accuracy = 0.9726
Accuracy = 0.9726,
Ranked = true,
};
var noPPScore = new SoloScoreInfo
@ -95,7 +98,26 @@ namespace osu.Game.Tests.Visual.Online
DifficultyName = "[4K] Cataclysmic Hypernova"
},
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
@ -112,7 +134,26 @@ namespace osu.Game.Tests.Visual.Online
Status = BeatmapOnlineStatus.Ranked,
},
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
@ -128,7 +169,9 @@ namespace osu.Game.Tests.Visual.Online
new ColourProvidedContainer(OverlayColourScheme.Green, new DrawableProfileScore(firstScore)),
new ColourProvidedContainer(OverlayColourScheme.Green, new DrawableProfileScore(secondScore)),
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(unrankedPPScore)),
new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileWeightedScore(firstScore, 0.97)),
new ColourProvidedContainer(OverlayColourScheme.Pink, new DrawableProfileWeightedScore(secondScore, 0.85)),
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")]
public bool HasReplay { get; set; }
[JsonProperty("ranked")]
public bool Ranked { get; set; }
// These properties are calculated or not relevant to any external usage.
public bool ShouldSerializeID() => false;
public bool ShouldSerializeUser() => false;
@ -213,6 +216,7 @@ namespace osu.Game.Online.API.Requests.Responses
HasOnlineReplay = HasReplay,
Mods = mods,
PP = PP,
Ranked = Ranked,
};
if (beatmap is BeatmapInfo realmBeatmap)

View File

@ -23,9 +23,9 @@ using osuTK.Graphics;
using osu.Framework.Localisation;
using osu.Framework.Extensions.LocalisationExtensions;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Sprites;
using osu.Game.Resources.Localisation.Web;
using osu.Game.Rulesets.Mods;
using osu.Game.Scoring.Drawables;
namespace osu.Game.Overlays.BeatmapSet.Scores
{
@ -180,10 +180,26 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
if (showPerformancePoints)
{
if (score.PP != null)
content.Add(new StatisticText(score.PP, format: @"N0"));
if (!score.Ranked)
{
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
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)

View File

@ -22,7 +22,6 @@ using osu.Game.Resources.Localisation.Web;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
using osu.Game.Scoring.Drawables;
using osuTK;
namespace osu.Game.Overlays.BeatmapSet.Scores
@ -125,10 +124,26 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
ppColumn.Alpha = value.BeatmapInfo!.Status.GrantsPerformancePoints() ? 1 : 0;
if (value.PP is double pp)
ppColumn.Text = pp.ToLocalisableString(@"N0");
if (!value.Ranked)
{
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
ppColumn.Drawable = new UnprocessedPerformancePointsPlaceholder { Size = new Vector2(smallFont.Size) };
ppColumn.Text = pp.ToLocalisableString(@"N0");
statisticsColumns.ChildrenEnumerable = value.GetStatisticsForDisplay().Select(createStatisticsColumn);
modsColumn.Mods = value.Mods;

View File

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

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; }
/// <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>
/// The online ID of this score.
/// </summary>

View File

@ -37,7 +37,7 @@
</PackageReference>
<PackageReference Include="Realm" Version="11.5.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" />
<!-- Held back due to 0.34.0 failing AOT compilation on ZstdSharp.dll dependency. -->
<PackageReference Include="SharpCompress" Version="0.36.0" />