From d82564aab66aee6d9c97138d1805f9a1a878396b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 17 Oct 2021 17:00:54 +0200 Subject: [PATCH 1/6] Add test scene for beatmap cards --- .../Visual/Beatmaps/TestSceneBeatmapCard.cs | 162 ++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs new file mode 100644 index 0000000000..d267ad929d --- /dev/null +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs @@ -0,0 +1,162 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays; +using osu.Game.Users; +using osuTK; + +namespace osu.Game.Tests.Visual.Beatmaps +{ + public class TestSceneBeatmapCard : OsuTestScene + { + private IBeatmapSetInfo[] testCases; + + #region Test case generation + + [BackgroundDependencyLoader] + private void load() + { + var normal = CreateAPIBeatmapSet(Ruleset.Value); + normal.HasVideo = true; + normal.HasStoryboard = true; + + var undownloadable = getUndownloadableBeatmapSet(); + var manyDifficulties = getManyDifficultiesBeatmapSet(); + + var explicitMap = CreateAPIBeatmapSet(Ruleset.Value); + explicitMap.HasExplicitContent = true; + + var featuredMap = CreateAPIBeatmapSet(Ruleset.Value); + featuredMap.TrackId = 1; + + var explicitFeaturedMap = CreateAPIBeatmapSet(Ruleset.Value); + explicitFeaturedMap.HasExplicitContent = true; + explicitFeaturedMap.TrackId = 2; + + testCases = new IBeatmapSetInfo[] + { + normal, + undownloadable, + manyDifficulties, + explicitMap, + featuredMap, + explicitFeaturedMap + }; + } + + private APIBeatmapSet getUndownloadableBeatmapSet() => new APIBeatmapSet + { + OnlineID = 123, + Title = "undownloadable beatmap", + Artist = "test", + Source = "more tests", + Author = new User + { + Username = "BanchoBot", + Id = 3, + }, + Availability = new BeatmapSetOnlineAvailability + { + DownloadDisabled = true, + }, + Preview = @"https://b.ppy.sh/preview/12345.mp3", + PlayCount = 123, + FavouriteCount = 456, + BPM = 111, + HasVideo = true, + HasStoryboard = true, + Covers = new BeatmapSetOnlineCovers(), + Beatmaps = new List + { + new APIBeatmap + { + RulesetID = Ruleset.Value.OnlineID, + DifficultyName = "Test", + StarRating = 6.42, + } + } + }; + + private static APIBeatmapSet getManyDifficultiesBeatmapSet() + { + var beatmaps = new List(); + + for (int i = 0; i < 100; i++) + { + beatmaps.Add(new APIBeatmap + { + RulesetID = i % 4, + StarRating = 2 + i % 4 * 2, + }); + } + + return new APIBeatmapSet + { + OnlineID = 1, + Title = "many difficulties beatmap", + Artist = "test", + Author = new User + { + Username = "BanchoBot", + Id = 3, + }, + HasVideo = true, + HasStoryboard = true, + Covers = new BeatmapSetOnlineCovers(), + Beatmaps = beatmaps, + }; + } + + #endregion + + private Drawable createContent(OverlayColourScheme colourScheme, Func creationFunc) + { + var colourProvider = new OverlayColourProvider(colourScheme); + + return new DependencyProvidingContainer + { + RelativeSizeAxes = Axes.Both, + CachedDependencies = new (Type, object)[] + { + (typeof(OverlayColourProvider), colourProvider) + }, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colourProvider.Background5 + }, + new BasicScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Full, + Padding = new MarginPadding(10), + Spacing = new Vector2(10), + ChildrenEnumerable = testCases.Select(creationFunc) + } + } + } + }; + } + + private void createTestCase(Func creationFunc) + { + foreach (var scheme in Enum.GetValues(typeof(OverlayColourScheme)).Cast()) + AddStep($"set {scheme} scheme", () => Child = createContent(scheme, creationFunc)); + } + } +} From 5962f16b1ca71d99f264a8755f4484bc117fd14d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 17 Oct 2021 18:24:17 +0200 Subject: [PATCH 2/6] Implement basic card appearance --- .../Visual/Beatmaps/TestSceneBeatmapCard.cs | 35 ++- .../Beatmaps/Drawables/Cards/BeatmapCard.cs | 248 ++++++++++++++++++ 2 files changed, 275 insertions(+), 8 deletions(-) create mode 100644 osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs index d267ad929d..d1b21547dc 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs @@ -4,11 +4,13 @@ using System; using System.Collections.Generic; using System.Linq; +using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables.Cards; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Users; @@ -18,7 +20,7 @@ namespace osu.Game.Tests.Visual.Beatmaps { public class TestSceneBeatmapCard : OsuTestScene { - private IBeatmapSetInfo[] testCases; + private APIBeatmapSet[] testCases; #region Test case generation @@ -30,7 +32,13 @@ namespace osu.Game.Tests.Visual.Beatmaps normal.HasStoryboard = true; var undownloadable = getUndownloadableBeatmapSet(); - var manyDifficulties = getManyDifficultiesBeatmapSet(); + + var someDifficulties = getManyDifficultiesBeatmapSet(11); + someDifficulties.Title = someDifficulties.TitleUnicode = "some difficulties"; + someDifficulties.Status = BeatmapSetOnlineStatus.Qualified; + + var manyDifficulties = getManyDifficultiesBeatmapSet(100); + manyDifficulties.Status = BeatmapSetOnlineStatus.Pending; var explicitMap = CreateAPIBeatmapSet(Ruleset.Value); explicitMap.HasExplicitContent = true; @@ -42,14 +50,22 @@ namespace osu.Game.Tests.Visual.Beatmaps explicitFeaturedMap.HasExplicitContent = true; explicitFeaturedMap.TrackId = 2; - testCases = new IBeatmapSetInfo[] + 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.HasExplicitContent = true; + longName.TrackId = 444; + + testCases = new[] { normal, undownloadable, + someDifficulties, manyDifficulties, explicitMap, featuredMap, - explicitFeaturedMap + explicitFeaturedMap, + longName }; } @@ -86,11 +102,11 @@ namespace osu.Game.Tests.Visual.Beatmaps } }; - private static APIBeatmapSet getManyDifficultiesBeatmapSet() + private static APIBeatmapSet getManyDifficultiesBeatmapSet(int count) { var beatmaps = new List(); - for (int i = 0; i < 100; i++) + for (int i = 0; i < count; i++) { beatmaps.Add(new APIBeatmap { @@ -118,7 +134,7 @@ namespace osu.Game.Tests.Visual.Beatmaps #endregion - private Drawable createContent(OverlayColourScheme colourScheme, Func creationFunc) + private Drawable createContent(OverlayColourScheme colourScheme, Func creationFunc) { var colourProvider = new OverlayColourProvider(colourScheme); @@ -153,10 +169,13 @@ namespace osu.Game.Tests.Visual.Beatmaps }; } - private void createTestCase(Func creationFunc) + private void createTestCase(Func creationFunc) { foreach (var scheme in Enum.GetValues(typeof(OverlayColourScheme)).Cast()) AddStep($"set {scheme} scheme", () => Child = createContent(scheme, creationFunc)); } + + [Test] + public void TestNormal() => createTestCase(beatmapSetInfo => new BeatmapCard(beatmapSetInfo)); } } diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs new file mode 100644 index 0000000000..38098899b0 --- /dev/null +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs @@ -0,0 +1,248 @@ +// 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.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays; +using osu.Game.Overlays.BeatmapSet; +using osuTK; +using osu.Game.Overlays.BeatmapListing.Panels; +using osu.Game.Resources.Localisation.Web; + +namespace osu.Game.Beatmaps.Drawables.Cards +{ + public class BeatmapCard : OsuClickableContainer + { + private const float width = 408; + private const float height = 100; + private const float corner_radius = 10; + + private readonly APIBeatmapSet beatmapSet; + private FillFlowContainer iconArea; + private GridContainer titleContainer; + private GridContainer artistContainer; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } + + public BeatmapCard(APIBeatmapSet beatmapSet) + : base(HoverSampleSet.Submit) + { + this.beatmapSet = beatmapSet; + } + + [BackgroundDependencyLoader] + private void load() + { + Width = width; + Height = height; + CornerRadius = corner_radius; + Masking = true; + + InternalChildren = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colourProvider.Background3 + }, + new Container + { + Name = @"Left (icon) area", + Size = new Vector2(height), + Children = new Drawable[] + { + new UpdateableOnlineBeatmapSetCover(BeatmapSetCoverType.List) + { + RelativeSizeAxes = Axes.Both, + OnlineInfo = beatmapSet + }, + iconArea = new FillFlowContainer + { + Margin = new MarginPadding(5), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(1) + } + } + }, + new Container + { + Name = @"Main content", + X = height - corner_radius, + Width = width - height, + Height = height, + CornerRadius = corner_radius, + Masking = true, + Children = new Drawable[] + { + new UpdateableOnlineBeatmapSetCover + { + RelativeSizeAxes = Axes.Both, + OnlineInfo = beatmapSet, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(colourProvider.Background2, colourProvider.Background2.Opacity(0.8f)), + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding + { + Horizontal = 10, + Vertical = 4 + }, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + titleContainer = new GridContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.AutoSize) + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize) + }, + Content = new[] + { + new[] + { + new OsuSpriteText + { + Text = new RomanisableString(beatmapSet.TitleUnicode, beatmapSet.Title), + Font = OsuFont.Default.With(size: 22.5f, weight: FontWeight.SemiBold), + RelativeSizeAxes = Axes.X, + Truncate = true + }, + Empty() + } + } + }, + artistContainer = new GridContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.AutoSize) + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize) + }, + Content = new[] + { + new[] + { + new OsuSpriteText + { + Text = createArtistText(), + Font = OsuFont.Default.With(size: 17.5f, weight: FontWeight.SemiBold), + RelativeSizeAxes = Axes.X, + Truncate = true + }, + Empty() + }, + } + }, + new LinkFlowContainer(s => + { + s.Shadow = false; + s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold); + }).With(d => + { + d.AutoSizeAxes = Axes.Both; + d.Margin = new MarginPadding { Top = 2 }; + d.AddText("mapped by ", t => t.Colour = colourProvider.Content2); + d.AddUserLink(beatmapSet.Author); + }), + } + }, + new FillFlowContainer + { + Name = @"Bottom content", + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Padding = new MarginPadding + { + Horizontal = 10, + Vertical = 4 + }, + Spacing = new Vector2(4, 0), + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Children = new Drawable[] + { + new BeatmapSetOnlineStatusPill + { + AutoSizeAxes = Axes.Both, + Status = beatmapSet.Status, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft + }, + new DifficultySpectrumDisplay(beatmapSet) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + DotSize = new Vector2(6, 12) + } + } + } + } + } + }; + + if (beatmapSet.HasVideo) + iconArea.Add(new IconPill(FontAwesome.Solid.Film)); + + if (beatmapSet.HasStoryboard) + iconArea.Add(new IconPill(FontAwesome.Solid.Image)); + + if (beatmapSet.HasExplicitContent) + { + titleContainer.Content[0][1] = new ExplicitContentBeatmapPill + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Margin = new MarginPadding { Left = 5 } + }; + } + + if (beatmapSet.TrackId != null) + { + artistContainer.Content[0][1] = new FeaturedArtistBeatmapPill + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Margin = new MarginPadding { Left = 5 } + }; + } + } + + private LocalisableString createArtistText() + { + var romanisableArtist = new RomanisableString(beatmapSet.ArtistUnicode, beatmapSet.Artist); + return BeatmapsetsStrings.ShowDetailsByArtist(romanisableArtist); + } + } +} From a59f2d7b835804cb0d66aeacd0a9e8a5031bdcf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 17 Oct 2021 18:59:31 +0200 Subject: [PATCH 3/6] Implement basic hover card state --- .../Beatmaps/Drawables/Cards/BeatmapCard.cs | 52 +++++++++++++++++-- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs index 38098899b0..516ffa5628 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -19,6 +20,7 @@ using osu.Game.Overlays.BeatmapSet; using osuTK; using osu.Game.Overlays.BeatmapListing.Panels; using osu.Game.Resources.Localisation.Web; +using osuTK.Graphics; namespace osu.Game.Beatmaps.Drawables.Cards { @@ -28,8 +30,16 @@ namespace osu.Game.Beatmaps.Drawables.Cards private const float height = 100; private const float corner_radius = 10; + private const float transition_duration = 400; + private readonly APIBeatmapSet beatmapSet; + + private UpdateableOnlineBeatmapSetCover leftCover; private FillFlowContainer iconArea; + + private Container mainContent; + private Box foregroundGradient; + private GridContainer titleContainer; private GridContainer artistContainer; @@ -63,7 +73,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards Size = new Vector2(height), Children = new Drawable[] { - new UpdateableOnlineBeatmapSetCover(BeatmapSetCoverType.List) + leftCover = new UpdateableOnlineBeatmapSetCover(BeatmapSetCoverType.List) { RelativeSizeAxes = Axes.Both, OnlineInfo = beatmapSet @@ -77,11 +87,10 @@ namespace osu.Game.Beatmaps.Drawables.Cards } } }, - new Container + mainContent = new Container { Name = @"Main content", X = height - corner_radius, - Width = width - height, Height = height, CornerRadius = corner_radius, Masking = true, @@ -92,10 +101,9 @@ namespace osu.Game.Beatmaps.Drawables.Cards RelativeSizeAxes = Axes.Both, OnlineInfo = beatmapSet, }, - new Box + foregroundGradient = new Box { RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(colourProvider.Background2, colourProvider.Background2.Opacity(0.8f)), }, new FillFlowContainer { @@ -239,10 +247,44 @@ namespace osu.Game.Beatmaps.Drawables.Cards } } + protected override void LoadComplete() + { + base.LoadComplete(); + updateState(); + FinishTransforms(true); + } + private LocalisableString createArtistText() { var romanisableArtist = new RomanisableString(beatmapSet.ArtistUnicode, beatmapSet.Artist); return BeatmapsetsStrings.ShowDetailsByArtist(romanisableArtist); } + + protected override bool OnHover(HoverEvent e) + { + updateState(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + updateState(); + base.OnHoverLost(e); + } + + private void updateState() + { + float targetWidth = width - height; + if (IsHovered) + targetWidth -= 20; + + mainContent.ResizeWidthTo(targetWidth, transition_duration, Easing.OutQuint); + + var foregroundColour = IsHovered ? colourProvider.Background4 : colourProvider.Background2; + var foregroundGradientColour = ColourInfo.GradientHorizontal(foregroundColour, foregroundColour.Opacity(0.8f)); + foregroundGradient.FadeColour(foregroundGradientColour, transition_duration, Easing.OutQuint); + + leftCover.FadeColour(IsHovered ? OsuColour.Gray(0.2f) : Color4.White, transition_duration, Easing.OutQuint); + } } } From f671ee28c542b7fbddc558dcf69590b79a85bc09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 22 Oct 2021 22:03:37 +0200 Subject: [PATCH 4/6] Use buffered container to eliminate gaps near foreground border --- .../Beatmaps/Drawables/Cards/BeatmapCard.cs | 25 ++-- .../Cards/BeatmapCardContentBackground.cs | 125 ++++++++++++++++++ 2 files changed, 133 insertions(+), 17 deletions(-) create mode 100644 osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs index 516ffa5628..b1fe381410 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs @@ -2,9 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; @@ -26,19 +24,19 @@ namespace osu.Game.Beatmaps.Drawables.Cards { public class BeatmapCard : OsuClickableContainer { + public const float TRANSITION_DURATION = 400; + private const float width = 408; private const float height = 100; private const float corner_radius = 10; - private const float transition_duration = 400; - private readonly APIBeatmapSet beatmapSet; private UpdateableOnlineBeatmapSetCover leftCover; private FillFlowContainer iconArea; private Container mainContent; - private Box foregroundGradient; + private BeatmapCardContentBackground mainContentBackground; private GridContainer titleContainer; private GridContainer artistContainer; @@ -96,14 +94,10 @@ namespace osu.Game.Beatmaps.Drawables.Cards Masking = true, Children = new Drawable[] { - new UpdateableOnlineBeatmapSetCover - { - RelativeSizeAxes = Axes.Both, - OnlineInfo = beatmapSet, - }, - foregroundGradient = new Box + mainContentBackground = new BeatmapCardContentBackground { RelativeSizeAxes = Axes.Both, + BeatmapSet = beatmapSet, }, new FillFlowContainer { @@ -278,13 +272,10 @@ namespace osu.Game.Beatmaps.Drawables.Cards if (IsHovered) targetWidth -= 20; - mainContent.ResizeWidthTo(targetWidth, transition_duration, Easing.OutQuint); + mainContent.ResizeWidthTo(targetWidth, TRANSITION_DURATION, Easing.OutQuint); + mainContentBackground.Dimmed.Value = IsHovered; - var foregroundColour = IsHovered ? colourProvider.Background4 : colourProvider.Background2; - var foregroundGradientColour = ColourInfo.GradientHorizontal(foregroundColour, foregroundColour.Opacity(0.8f)); - foregroundGradient.FadeColour(foregroundGradientColour, transition_duration, Easing.OutQuint); - - leftCover.FadeColour(IsHovered ? OsuColour.Gray(0.2f) : Color4.White, transition_duration, Easing.OutQuint); + leftCover.FadeColour(IsHovered ? OsuColour.Gray(0.2f) : Color4.White, TRANSITION_DURATION, Easing.OutQuint); } } } diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs new file mode 100644 index 0000000000..88c9d771ac --- /dev/null +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs @@ -0,0 +1,125 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable enable + +using System; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Overlays; + +namespace osu.Game.Beatmaps.Drawables.Cards +{ + public class BeatmapCardContentBackground : ModelBackedDrawable + { + public IBeatmapSetOnlineInfo BeatmapSet + { + get => Model; + set => Model = value; + } + + public new bool Masking + { + get => base.Masking; + set => base.Masking = value; + } + + public BindableBool Dimmed { get; private set; } = new BindableBool(); + + protected override double LoadDelay => 500; + + protected override double TransformDuration => 400; + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + InternalChild = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colourProvider.Background2 + }; + } + + protected override DelayedLoadWrapper CreateDelayedLoadWrapper(Func createContentFunc, double timeBeforeLoad) + => new DelayedLoadUnloadWrapper(createContentFunc, timeBeforeLoad); + + protected override Drawable? CreateDrawable(IBeatmapSetOnlineInfo? model) + { + if (model == null) + return null; + + return new BufferedBackground(model) + { + RelativeSizeAxes = Axes.Both, + Dimmed = { BindTarget = Dimmed } + }; + } + + private class BufferedBackground : BufferedContainer + { + public BindableBool Dimmed { get; } = new BindableBool(); + + private readonly IBeatmapSetOnlineInfo onlineInfo; + + private readonly Box background; + private OnlineBeatmapSetCover? cover; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + + public BufferedBackground(IBeatmapSetOnlineInfo onlineInfo) + { + this.onlineInfo = onlineInfo; + + RelativeSizeAxes = Axes.Both; + InternalChild = background = new Box + { + RelativeSizeAxes = Axes.Both, + }; + } + + [BackgroundDependencyLoader] + private void load() + { + background.Colour = colourProvider.Background2; + + LoadComponentAsync(new OnlineBeatmapSetCover(onlineInfo) + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + FillMode = FillMode.Fill + }, loaded => + { + cover = loaded; + cover.Colour = Colour4.Transparent; + AddInternal(cover); + FinishTransforms(true); + updateState(); + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Dimmed.BindValueChanged(_ => updateState(), true); + FinishTransforms(true); + } + + private void updateState() + { + if (cover == null) + return; + + background.FadeColour(Dimmed.Value ? colourProvider.Background4 : colourProvider.Background2, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + + var gradient = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0), Colour4.White.Opacity(0.2f)); + cover.FadeColour(gradient, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + } + } + } +} From 75e89f17add1e7fe3a4dccf7a1a25775c58d8329 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 3 Nov 2021 00:07:03 +0100 Subject: [PATCH 5/6] Rewrite `BeatmapCardContentBackground` --- .../Beatmaps/Drawables/Cards/BeatmapCard.cs | 3 +- .../Cards/BeatmapCardContentBackground.cs | 130 +++++------------- 2 files changed, 39 insertions(+), 94 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs index b1fe381410..20c5359320 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs @@ -94,10 +94,9 @@ namespace osu.Game.Beatmaps.Drawables.Cards Masking = true, Children = new Drawable[] { - mainContentBackground = new BeatmapCardContentBackground + mainContentBackground = new BeatmapCardContentBackground(beatmapSet) { RelativeSizeAxes = Axes.Both, - BeatmapSet = beatmapSet, }, new FillFlowContainer { diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs index 88c9d771ac..392f5d1bfa 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs @@ -3,7 +3,6 @@ #nullable enable -using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -14,112 +13,59 @@ using osu.Game.Overlays; namespace osu.Game.Beatmaps.Drawables.Cards { - public class BeatmapCardContentBackground : ModelBackedDrawable + public class BeatmapCardContentBackground : CompositeDrawable { - public IBeatmapSetOnlineInfo BeatmapSet + public BindableBool Dimmed { get; } = new BindableBool(); + + private readonly Box background; + private readonly DelayedLoadUnloadWrapper cover; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + + public BeatmapCardContentBackground(IBeatmapSetOnlineInfo onlineInfo) { - get => Model; - set => Model = value; + InternalChildren = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + cover = new DelayedLoadUnloadWrapper(() => createCover(onlineInfo), 500, 500) + { + RelativeSizeAxes = Axes.Both, + Colour = Colour4.Transparent + } + }; } - public new bool Masking + private static Drawable createCover(IBeatmapSetOnlineInfo onlineInfo) => new OnlineBeatmapSetCover(onlineInfo) { - get => base.Masking; - set => base.Masking = value; - } - - public BindableBool Dimmed { get; private set; } = new BindableBool(); - - protected override double LoadDelay => 500; - - protected override double TransformDuration => 400; + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + FillMode = FillMode.Fill + }; [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) { - InternalChild = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colourProvider.Background2 - }; + background.Colour = colourProvider.Background2; } - protected override DelayedLoadWrapper CreateDelayedLoadWrapper(Func createContentFunc, double timeBeforeLoad) - => new DelayedLoadUnloadWrapper(createContentFunc, timeBeforeLoad); - - protected override Drawable? CreateDrawable(IBeatmapSetOnlineInfo? model) + protected override void LoadComplete() { - if (model == null) - return null; - - return new BufferedBackground(model) - { - RelativeSizeAxes = Axes.Both, - Dimmed = { BindTarget = Dimmed } - }; + base.LoadComplete(); + Dimmed.BindValueChanged(_ => updateState(), true); + FinishTransforms(true); } - private class BufferedBackground : BufferedContainer + private void updateState() => Schedule(() => { - public BindableBool Dimmed { get; } = new BindableBool(); + background.FadeColour(Dimmed.Value ? colourProvider.Background4 : colourProvider.Background2, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); - private readonly IBeatmapSetOnlineInfo onlineInfo; - - private readonly Box background; - private OnlineBeatmapSetCover? cover; - - [Resolved] - private OverlayColourProvider colourProvider { get; set; } = null!; - - public BufferedBackground(IBeatmapSetOnlineInfo onlineInfo) - { - this.onlineInfo = onlineInfo; - - RelativeSizeAxes = Axes.Both; - InternalChild = background = new Box - { - RelativeSizeAxes = Axes.Both, - }; - } - - [BackgroundDependencyLoader] - private void load() - { - background.Colour = colourProvider.Background2; - - LoadComponentAsync(new OnlineBeatmapSetCover(onlineInfo) - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - FillMode = FillMode.Fill - }, loaded => - { - cover = loaded; - cover.Colour = Colour4.Transparent; - AddInternal(cover); - FinishTransforms(true); - updateState(); - }); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - Dimmed.BindValueChanged(_ => updateState(), true); - FinishTransforms(true); - } - - private void updateState() - { - if (cover == null) - return; - - background.FadeColour(Dimmed.Value ? colourProvider.Background4 : colourProvider.Background2, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); - - var gradient = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0), Colour4.White.Opacity(0.2f)); - cover.FadeColour(gradient, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); - } - } + var gradient = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0), Colour4.White.Opacity(0.2f)); + cover.FadeColour(gradient, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + }); } } From 1813681fac0c0ae3407eb3cbfd2d7e04e95533b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 3 Nov 2021 00:10:50 +0100 Subject: [PATCH 6/6] Move private method below protected --- osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs index 20c5359320..8136ebbd70 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs @@ -247,12 +247,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards FinishTransforms(true); } - private LocalisableString createArtistText() - { - var romanisableArtist = new RomanisableString(beatmapSet.ArtistUnicode, beatmapSet.Artist); - return BeatmapsetsStrings.ShowDetailsByArtist(romanisableArtist); - } - protected override bool OnHover(HoverEvent e) { updateState(); @@ -265,6 +259,12 @@ namespace osu.Game.Beatmaps.Drawables.Cards base.OnHoverLost(e); } + private LocalisableString createArtistText() + { + var romanisableArtist = new RomanisableString(beatmapSet.ArtistUnicode, beatmapSet.Artist); + return BeatmapsetsStrings.ShowDetailsByArtist(romanisableArtist); + } + private void updateState() { float targetWidth = width - height;