diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs index 94b693363a..6cb171974a 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs @@ -84,20 +84,26 @@ namespace osu.Game.Tests.Visual.Beatmaps explicitMap.Title = someDifficulties.TitleUnicode = "explicit beatmap"; explicitMap.HasExplicitContent = true; + var spotlightMap = CreateAPIBeatmapSet(Ruleset.Value); + spotlightMap.Title = someDifficulties.TitleUnicode = "spotlight beatmap"; + spotlightMap.FeaturedInSpotlight = true; + var featuredMap = CreateAPIBeatmapSet(Ruleset.Value); featuredMap.Title = someDifficulties.TitleUnicode = "featured artist beatmap"; featuredMap.TrackId = 1; - var explicitFeaturedMap = CreateAPIBeatmapSet(Ruleset.Value); - explicitFeaturedMap.Title = someDifficulties.TitleUnicode = "explicit featured artist"; - explicitFeaturedMap.HasExplicitContent = true; - explicitFeaturedMap.TrackId = 2; + var allBadgesMap = CreateAPIBeatmapSet(Ruleset.Value); + allBadgesMap.Title = someDifficulties.TitleUnicode = "all-badges beatmap"; + allBadgesMap.HasExplicitContent = true; + allBadgesMap.FeaturedInSpotlight = true; + allBadgesMap.TrackId = 2; var longName = CreateAPIBeatmapSet(Ruleset.Value); longName.Title = longName.TitleUnicode = "this track has an incredibly and implausibly long title"; longName.Artist = longName.ArtistUnicode = "and this artist! who would have thunk it. it's really such a long name."; longName.Source = "wow. even the source field has an impossibly long string in it. this really takes the cake, doesn't it?"; longName.HasExplicitContent = true; + longName.FeaturedInSpotlight = true; longName.TrackId = 444; testCases = new[] @@ -108,8 +114,9 @@ namespace osu.Game.Tests.Visual.Beatmaps someDifficulties, manyDifficulties, explicitMap, + spotlightMap, featuredMap, - explicitFeaturedMap, + allBadgesMap, longName }; diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs index f87cca80b0..859727e632 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapSetOverlay.cs @@ -165,6 +165,17 @@ namespace osu.Game.Tests.Visual.Online }); } + [Test] + public void TestSpotlightBeatmap() + { + AddStep("show spotlight map", () => + { + var beatmapSet = getBeatmapSet(); + beatmapSet.FeaturedInSpotlight = true; + overlay.ShowBeatmapSet(beatmapSet); + }); + } + [Test] public void TestFeaturedBeatmap() { @@ -176,6 +187,19 @@ namespace osu.Game.Tests.Visual.Online }); } + [Test] + public void TestAllBadgesBeatmap() + { + AddStep("show map with all badges", () => + { + var beatmapSet = getBeatmapSet(); + beatmapSet.HasExplicitContent = true; + beatmapSet.FeaturedInSpotlight = true; + beatmapSet.TrackId = 1; + overlay.ShowBeatmapSet(beatmapSet); + }); + } + [Test] public void TestHide() { diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs index 535f222228..58c1ebee0f 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs @@ -54,7 +54,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards Height = height; FillFlowContainer leftIconArea = null!; - GridContainer titleContainer = null!; + FillFlowContainer titleBadgeArea = null!; GridContainer artistContainer = null!; Child = content.With(c => @@ -93,7 +93,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards Direction = FillDirection.Vertical, Children = new Drawable[] { - titleContainer = new GridContainer + new GridContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -108,7 +108,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards }, Content = new[] { - new[] + new Drawable[] { new OsuSpriteText { @@ -117,7 +117,13 @@ namespace osu.Game.Beatmaps.Drawables.Cards RelativeSizeAxes = Axes.X, Truncate = true }, - Empty() + titleBadgeArea = new FillFlowContainer + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + } } } }, @@ -244,19 +250,29 @@ namespace osu.Game.Beatmaps.Drawables.Cards if (BeatmapSet.HasStoryboard) leftIconArea.Add(new IconPill(FontAwesome.Solid.Image) { IconSize = new Vector2(20) }); - if (BeatmapSet.HasExplicitContent) + if (BeatmapSet.FeaturedInSpotlight) { - titleContainer.Content[0][1] = new ExplicitContentBeatmapPill + titleBadgeArea.Add(new SpotlightBeatmapBadge { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, Margin = new MarginPadding { Left = 5 } - }; + }); + } + + if (BeatmapSet.HasExplicitContent) + { + titleBadgeArea.Add(new ExplicitContentBeatmapBadge + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Margin = new MarginPadding { Left = 5 } + }); } if (BeatmapSet.TrackId != null) { - artistContainer.Content[0][1] = new FeaturedArtistBeatmapPill + artistContainer.Content[0][1] = new FeaturedArtistBeatmapBadge { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardNormal.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardNormal.cs index 08befd5340..3d7e81de21 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardNormal.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardNormal.cs @@ -55,7 +55,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards Height = height; FillFlowContainer leftIconArea = null!; - GridContainer titleContainer = null!; + FillFlowContainer titleBadgeArea = null!; GridContainer artistContainer = null!; Child = content.With(c => @@ -94,14 +94,14 @@ namespace osu.Game.Beatmaps.Drawables.Cards Direction = FillDirection.Vertical, Children = new Drawable[] { - titleContainer = new GridContainer + new GridContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, ColumnDimensions = new[] { new Dimension(), - new Dimension(GridSizeMode.AutoSize) + new Dimension(GridSizeMode.AutoSize), }, RowDimensions = new[] { @@ -109,7 +109,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards }, Content = new[] { - new[] + new Drawable[] { new OsuSpriteText { @@ -118,7 +118,13 @@ namespace osu.Game.Beatmaps.Drawables.Cards RelativeSizeAxes = Axes.X, Truncate = true }, - Empty() + titleBadgeArea = new FillFlowContainer + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + } } } }, @@ -225,19 +231,29 @@ namespace osu.Game.Beatmaps.Drawables.Cards if (BeatmapSet.HasStoryboard) leftIconArea.Add(new IconPill(FontAwesome.Solid.Image) { IconSize = new Vector2(20) }); - if (BeatmapSet.HasExplicitContent) + if (BeatmapSet.FeaturedInSpotlight) { - titleContainer.Content[0][1] = new ExplicitContentBeatmapPill + titleBadgeArea.Add(new SpotlightBeatmapBadge { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, Margin = new MarginPadding { Left = 5 } - }; + }); + } + + if (BeatmapSet.HasExplicitContent) + { + titleBadgeArea.Add(new ExplicitContentBeatmapBadge + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Margin = new MarginPadding { Left = 5 } + }); } if (BeatmapSet.TrackId != null) { - artistContainer.Content[0][1] = new FeaturedArtistBeatmapPill + artistContainer.Content[0][1] = new FeaturedArtistBeatmapBadge { Anchor = Anchor.BottomRight, Origin = Anchor.BottomRight, diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs index d99c13b977..79c65fa79e 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs @@ -42,6 +42,9 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"nsfw")] public bool HasExplicitContent { get; set; } + [JsonProperty(@"spotlight")] + public bool FeaturedInSpotlight { get; set; } + [JsonProperty(@"video")] public bool HasVideo { get; set; } diff --git a/osu.Game/Overlays/BeatmapSet/ExplicitContentBeatmapPill.cs b/osu.Game/Overlays/BeatmapSet/BeatmapBadge.cs similarity index 57% rename from osu.Game/Overlays/BeatmapSet/ExplicitContentBeatmapPill.cs rename to osu.Game/Overlays/BeatmapSet/BeatmapBadge.cs index 21d1d1172c..a75fc8e888 100644 --- a/osu.Game/Overlays/BeatmapSet/ExplicitContentBeatmapPill.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapBadge.cs @@ -6,42 +6,62 @@ using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; -using osu.Game.Resources.Localisation.Web; + +#nullable enable namespace osu.Game.Overlays.BeatmapSet { - public class ExplicitContentBeatmapPill : CompositeDrawable + public abstract class BeatmapBadge : CompositeDrawable { - public ExplicitContentBeatmapPill() + /// + /// The text displayed on the badge's label. + /// + public LocalisableString BadgeText { - AutoSizeAxes = Axes.Both; + set => badgeLabel.Text = value.ToUpper(); } - [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, OverlayColourProvider colourProvider) + /// + /// The colour of the badge's label. + /// + public Colour4 BadgeColour { + set => badgeLabel.Colour = value; + } + + private readonly Box background; + private readonly OsuSpriteText badgeLabel; + + protected BeatmapBadge() + { + AutoSizeAxes = Axes.Both; + InternalChild = new CircularContainer { Masking = true, AutoSizeAxes = Axes.Both, Children = new Drawable[] { - new Box + background = new Box { RelativeSizeAxes = Axes.Both, - Colour = colourProvider?.Background5 ?? colours.Gray2, }, - new OsuSpriteText + badgeLabel = new OsuSpriteText { - Margin = new MarginPadding { Horizontal = 10f, Vertical = 2f }, - Text = BeatmapsetsStrings.NsfwBadgeLabel.ToUpper(), Font = OsuFont.GetFont(size: 10, weight: FontWeight.SemiBold), - Colour = colours.Orange2 + Margin = new MarginPadding { Horizontal = 10, Vertical = 2 }, } } }; } + + [BackgroundDependencyLoader(true)] + private void load(OsuColour colours, OverlayColourProvider? colourProvider) + { + background.Colour = colourProvider?.Background5 ?? colours.Gray2; + } } } diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs index 8f4089c707..56efb725cd 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapSetHeaderContent.cs @@ -39,8 +39,11 @@ namespace osu.Game.Overlays.BeatmapSet private readonly Box coverGradient; private readonly OsuSpriteText title, artist; private readonly AuthorInfo author; - private readonly ExplicitContentBeatmapPill explicitContentPill; - private readonly FeaturedArtistBeatmapPill featuredArtistPill; + + private readonly ExplicitContentBeatmapBadge explicitContent; + private readonly SpotlightBeatmapBadge spotlight; + private readonly FeaturedArtistBeatmapBadge featuredArtist; + private readonly FillFlowContainer downloadButtonsContainer; private readonly BeatmapAvailability beatmapAvailability; private readonly BeatmapSetOnlineStatusPill onlineStatusPill; @@ -126,7 +129,14 @@ namespace osu.Game.Overlays.BeatmapSet Origin = Anchor.BottomLeft, Margin = new MarginPadding { Left = 5, Bottom = 4 }, // To better lineup with the font }, - explicitContentPill = new ExplicitContentBeatmapPill + explicitContent = new ExplicitContentBeatmapBadge + { + Alpha = 0f, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Margin = new MarginPadding { Left = 10, Bottom = 4 }, + }, + spotlight = new SpotlightBeatmapBadge { Alpha = 0f, Anchor = Anchor.BottomLeft, @@ -146,7 +156,7 @@ namespace osu.Game.Overlays.BeatmapSet { Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium, italics: true), }, - featuredArtistPill = new FeaturedArtistBeatmapPill + featuredArtist = new FeaturedArtistBeatmapBadge { Alpha = 0f, Anchor = Anchor.BottomLeft, @@ -257,8 +267,9 @@ namespace osu.Game.Overlays.BeatmapSet title.Text = new RomanisableString(setInfo.NewValue.TitleUnicode, setInfo.NewValue.Title); artist.Text = new RomanisableString(setInfo.NewValue.ArtistUnicode, setInfo.NewValue.Artist); - explicitContentPill.Alpha = setInfo.NewValue.HasExplicitContent ? 1 : 0; - featuredArtistPill.Alpha = setInfo.NewValue.TrackId != null ? 1 : 0; + explicitContent.Alpha = setInfo.NewValue.HasExplicitContent ? 1 : 0; + spotlight.Alpha = setInfo.NewValue.FeaturedInSpotlight ? 1 : 0; + featuredArtist.Alpha = setInfo.NewValue.TrackId != null ? 1 : 0; onlineStatusPill.FadeIn(500, Easing.OutQuint); onlineStatusPill.Status = setInfo.NewValue.Status; diff --git a/osu.Game/Overlays/BeatmapSet/ExplicitContentBeatmapBadge.cs b/osu.Game/Overlays/BeatmapSet/ExplicitContentBeatmapBadge.cs new file mode 100644 index 0000000000..2a20d22b61 --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/ExplicitContentBeatmapBadge.cs @@ -0,0 +1,21 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Game.Graphics; +using osu.Game.Resources.Localisation.Web; + +#nullable enable + +namespace osu.Game.Overlays.BeatmapSet +{ + public class ExplicitContentBeatmapBadge : BeatmapBadge + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + BadgeText = BeatmapsetsStrings.NsfwBadgeLabel; + BadgeColour = colours.Orange2; + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/FeaturedArtistBeatmapBadge.cs b/osu.Game/Overlays/BeatmapSet/FeaturedArtistBeatmapBadge.cs new file mode 100644 index 0000000000..4f336d85fc --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/FeaturedArtistBeatmapBadge.cs @@ -0,0 +1,22 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Game.Graphics; +using osu.Game.Resources.Localisation.Web; + +#nullable enable + +namespace osu.Game.Overlays.BeatmapSet +{ + public class FeaturedArtistBeatmapBadge : BeatmapBadge + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + BadgeText = BeatmapsetsStrings.FeaturedArtistBadgeLabel; + BadgeColour = colours.Blue1; + // todo: add linking support to allow redirecting featured artist badge to corresponding track. + } + } +} diff --git a/osu.Game/Overlays/BeatmapSet/FeaturedArtistBeatmapPill.cs b/osu.Game/Overlays/BeatmapSet/FeaturedArtistBeatmapPill.cs deleted file mode 100644 index 1be987cde2..0000000000 --- a/osu.Game/Overlays/BeatmapSet/FeaturedArtistBeatmapPill.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Allocation; -using osu.Framework.Extensions.LocalisationExtensions; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Shapes; -using osu.Game.Graphics; -using osu.Game.Graphics.Sprites; -using osu.Game.Resources.Localisation.Web; - -namespace osu.Game.Overlays.BeatmapSet -{ - public class FeaturedArtistBeatmapPill : CompositeDrawable - { - public FeaturedArtistBeatmapPill() - { - AutoSizeAxes = Axes.Both; - } - - [BackgroundDependencyLoader(true)] - private void load(OsuColour colours, OverlayColourProvider colourProvider) - { - InternalChild = new CircularContainer - { - Masking = true, - AutoSizeAxes = Axes.Both, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colourProvider?.Background5 ?? colours.Gray2, - }, - new OsuSpriteText - { - Margin = new MarginPadding { Horizontal = 10f, Vertical = 2f }, - Text = BeatmapsetsStrings.FeaturedArtistBadgeLabel.ToUpper(), - Font = OsuFont.GetFont(size: 10, weight: FontWeight.SemiBold), - Colour = colours.Blue1 - } - } - }; - } - } -} diff --git a/osu.Game/Overlays/BeatmapSet/SpotlightBeatmapBadge.cs b/osu.Game/Overlays/BeatmapSet/SpotlightBeatmapBadge.cs new file mode 100644 index 0000000000..3204f79b21 --- /dev/null +++ b/osu.Game/Overlays/BeatmapSet/SpotlightBeatmapBadge.cs @@ -0,0 +1,22 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Game.Graphics; +using osu.Game.Resources.Localisation.Web; + +#nullable enable + +namespace osu.Game.Overlays.BeatmapSet +{ + public class SpotlightBeatmapBadge : BeatmapBadge + { + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + BadgeText = BeatmapsetsStrings.SpotlightBadgeLabel; + BadgeColour = colours.Pink1; + // todo: add linking support to allow redirecting spotlight badge to https://osu.ppy.sh/wiki/en/Beatmap_Spotlights. + } + } +} diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index 2618e15d31..39853a5c45 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -78,7 +78,7 @@ namespace osu.Game.Screens.OnlinePlay private Container difficultyIconContainer; private LinkFlowContainer beatmapText; private LinkFlowContainer authorText; - private ExplicitContentBeatmapPill explicitContentPill; + private ExplicitContentBeatmapBadge explicitContent; private ModDisplay modDisplay; private FillFlowContainer buttonsFlow; private UpdateableAvatar ownerAvatar; @@ -293,7 +293,7 @@ namespace osu.Game.Screens.OnlinePlay } bool hasExplicitContent = (beatmap?.BeatmapSet as IBeatmapSetOnlineInfo)?.HasExplicitContent == true; - explicitContentPill.Alpha = hasExplicitContent ? 1 : 0; + explicitContent.Alpha = hasExplicitContent ? 1 : 0; modDisplay.Current.Value = requiredMods.ToArray(); @@ -380,7 +380,7 @@ namespace osu.Game.Screens.OnlinePlay Children = new Drawable[] { authorText = new LinkFlowContainer(fontParameters) { AutoSizeAxes = Axes.Both }, - explicitContentPill = new ExplicitContentBeatmapPill + explicitContent = new ExplicitContentBeatmapBadge { Alpha = 0f, Anchor = Anchor.CentreLeft,