From a32492cdd5614f9d88c4d3e04b5222a10002b0ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 27 Nov 2021 15:27:41 +0100 Subject: [PATCH 01/12] Duplicate `BeatmapCard{-> Extra}` as blueprint for extra card size --- .../Visual/Beatmaps/TestSceneBeatmapCard.cs | 14 + .../Drawables/Cards/BeatmapCardExtra.cs | 430 ++++++++++++++++++ 2 files changed, 444 insertions(+) create mode 100644 osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs index f835d21603..04aea4ac9c 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs @@ -262,5 +262,19 @@ namespace osu.Game.Tests.Visual.Beatmaps }); AddToggleStep("disable/enable expansion", disabled => this.ChildrenOfType().ForEach(card => card.Expanded.Disabled = disabled)); } + + [Test] + public void TestExtra() + { + createTestCase(beatmapSetInfo => new BeatmapCardExtra(beatmapSetInfo)); + + AddToggleStep("toggle expanded state", expanded => + { + var card = this.ChildrenOfType().Last(); + if (!card.Expanded.Disabled) + card.Expanded.Value = expanded; + }); + AddToggleStep("disable/enable expansion", disabled => this.ChildrenOfType().ForEach(card => card.Expanded.Disabled = disabled)); + } } } diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs new file mode 100644 index 0000000000..f244e912a1 --- /dev/null +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs @@ -0,0 +1,430 @@ +// 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.Collections.Generic; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +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.Beatmaps.Drawables.Cards.Buttons; +using osu.Game.Beatmaps.Drawables.Cards.Statistics; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays; +using osu.Game.Overlays.BeatmapSet; +using osuTK; +using osu.Game.Resources.Localisation.Web; +using DownloadButton = osu.Game.Beatmaps.Drawables.Cards.Buttons.DownloadButton; + +namespace osu.Game.Beatmaps.Drawables.Cards +{ + public class BeatmapCardExtra : OsuClickableContainer + { + private const float width = 408; + private const float height = 100; + private const float icon_area_width = 30; + + public Bindable Expanded { get; } = new BindableBool(); + + private readonly APIBeatmapSet beatmapSet; + private readonly Bindable favouriteState; + + private readonly BeatmapDownloadTracker downloadTracker; + + private BeatmapCardContent content = null!; + + private BeatmapCardThumbnail thumbnail = null!; + + private Container rightAreaBackground = null!; + private Container rightAreaButtons = null!; + + private Container mainContent = null!; + private BeatmapCardContentBackground mainContentBackground = null!; + private FillFlowContainer statisticsContainer = null!; + + private FillFlowContainer idleBottomContent = null!; + private BeatmapCardDownloadProgressBar downloadProgressBar = null!; + + [Resolved] + private OsuColour colours { get; set; } = null!; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + + public BeatmapCardExtra(APIBeatmapSet beatmapSet) + : base(HoverSampleSet.Submit) + { + this.beatmapSet = beatmapSet; + favouriteState = new Bindable(new BeatmapSetFavouriteState(beatmapSet.HasFavourited, beatmapSet.FavouriteCount)); + downloadTracker = new BeatmapDownloadTracker(beatmapSet); + } + + [BackgroundDependencyLoader(true)] + private void load(BeatmapSetOverlay? beatmapSetOverlay) + { + Width = width; + Height = height; + + FillFlowContainer leftIconArea; + GridContainer titleContainer; + GridContainer artistContainer; + + InternalChild = content = new BeatmapCardContent(height) + { + MainContent = new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + downloadTracker, + rightAreaBackground = new Container + { + RelativeSizeAxes = Axes.Y, + Width = icon_area_width + 2 * BeatmapCard.CORNER_RADIUS, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + // workaround for masking artifacts at the top & bottom of card, + // which become especially visible on downloaded beatmaps (when the icon area has a lime background). + Padding = new MarginPadding { Vertical = 1 }, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Colour4.White + }, + }, + thumbnail = new BeatmapCardThumbnail(beatmapSet) + { + Name = @"Left (icon) area", + Size = new Vector2(height), + Padding = new MarginPadding { Right = BeatmapCard.CORNER_RADIUS }, + Child = leftIconArea = new FillFlowContainer + { + Margin = new MarginPadding(5), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(1) + } + }, + new Container + { + Name = @"Right (button) area", + Width = 30, + RelativeSizeAxes = Axes.Y, + Origin = Anchor.TopRight, + Anchor = Anchor.TopRight, + Padding = new MarginPadding { Vertical = 17.5f }, + Child = rightAreaButtons = new Container + { + RelativeSizeAxes = Axes.Both, + Children = new BeatmapCardIconButton[] + { + new FavouriteButton(beatmapSet) + { + Current = favouriteState, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre + }, + new DownloadButton(beatmapSet) + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + State = { BindTarget = downloadTracker.State } + }, + new GoToBeatmapButton(beatmapSet) + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + State = { BindTarget = downloadTracker.State } + } + } + } + }, + mainContent = new Container + { + Name = @"Main content", + X = height - BeatmapCard.CORNER_RADIUS, + Height = height, + CornerRadius = BeatmapCard.CORNER_RADIUS, + Masking = true, + Children = new Drawable[] + { + mainContentBackground = new BeatmapCardContentBackground(beatmapSet) + { + RelativeSizeAxes = Axes.Both, + }, + 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 Container + { + Name = @"Bottom content", + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Padding = new MarginPadding + { + Horizontal = 10, + Vertical = 4 + }, + Children = new Drawable[] + { + idleBottomContent = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 3), + AlwaysPresent = true, + Children = new Drawable[] + { + statisticsContainer = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Alpha = 0, + AlwaysPresent = true, + ChildrenEnumerable = createStatistics() + }, + new BeatmapCardExtraInfoRow(beatmapSet) + { + Hovered = _ => + { + content.ScheduleShow(); + return false; + }, + Unhovered = _ => + { + // This hide should only trigger if the expanded content has not shown yet. + // ie. if the user has not shown intent to want to see it (quickly moved over the info row area). + if (!Expanded.Value) + content.ScheduleHide(); + } + } + } + }, + downloadProgressBar = new BeatmapCardDownloadProgressBar + { + RelativeSizeAxes = Axes.X, + Height = 6, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + State = { BindTarget = downloadTracker.State }, + Progress = { BindTarget = downloadTracker.Progress } + } + } + } + } + } + } + }, + ExpandedContent = new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Horizontal = 10, Vertical = 13 }, + Child = new BeatmapCardDifficultyList(beatmapSet) + }, + Expanded = { BindTarget = Expanded } + }; + + if (beatmapSet.HasVideo) + leftIconArea.Add(new IconPill(FontAwesome.Solid.Film) { IconSize = new Vector2(20) }); + + if (beatmapSet.HasStoryboard) + leftIconArea.Add(new IconPill(FontAwesome.Solid.Image) { IconSize = new Vector2(20) }); + + 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 } + }; + } + + Action = () => beatmapSetOverlay?.FetchAndShowBeatmapSet(beatmapSet.OnlineID); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + downloadTracker.State.BindValueChanged(_ => updateState()); + Expanded.BindValueChanged(_ => updateState(), true); + FinishTransforms(true); + } + + protected override bool OnHover(HoverEvent e) + { + updateState(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + content.ScheduleHide(); + + updateState(); + base.OnHoverLost(e); + } + + private LocalisableString createArtistText() + { + var romanisableArtist = new RomanisableString(beatmapSet.ArtistUnicode, beatmapSet.Artist); + return BeatmapsetsStrings.ShowDetailsByArtist(romanisableArtist); + } + + private IEnumerable createStatistics() + { + if (beatmapSet.HypeStatus != null) + yield return new HypesStatistic(beatmapSet.HypeStatus); + + // web does not show nominations unless hypes are also present. + // see: https://github.com/ppy/osu-web/blob/8ed7d071fd1d3eaa7e43cf0e4ff55ca2fef9c07c/resources/assets/lib/beatmapset-panel.tsx#L443 + if (beatmapSet.HypeStatus != null && beatmapSet.NominationStatus != null) + yield return new NominationsStatistic(beatmapSet.NominationStatus); + + yield return new FavouritesStatistic(beatmapSet) { Current = favouriteState }; + yield return new PlayCountStatistic(beatmapSet); + + var dateStatistic = BeatmapCardDateStatistic.CreateFor(beatmapSet); + if (dateStatistic != null) + yield return dateStatistic; + } + + private void updateState() + { + bool showDetails = IsHovered || Expanded.Value; + + float targetWidth = width - height; + if (showDetails) + targetWidth = targetWidth - icon_area_width + BeatmapCard.CORNER_RADIUS; + + thumbnail.Dimmed.Value = showDetails; + + // Scale value is intentionally chosen to fit in the spacing of listing displays, as to not overlap horizontally with adjacent cards. + // This avoids depth issues where a hovered (scaled) card to the right of another card would be beneath the card to the left. + content.ScaleTo(Expanded.Value ? 1.03f : 1, 500, Easing.OutQuint); + + mainContent.ResizeWidthTo(targetWidth, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + mainContentBackground.Dimmed.Value = showDetails; + + statisticsContainer.FadeTo(showDetails ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + + rightAreaBackground.FadeColour(downloadTracker.State.Value == DownloadState.LocallyAvailable ? colours.Lime0 : colourProvider.Background3, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + rightAreaButtons.FadeTo(showDetails ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + + foreach (var button in rightAreaButtons) + { + button.IdleColour = downloadTracker.State.Value != DownloadState.LocallyAvailable ? colourProvider.Light1 : colourProvider.Background3; + button.HoverColour = downloadTracker.State.Value != DownloadState.LocallyAvailable ? colourProvider.Content1 : colourProvider.Foreground1; + } + + bool showProgress = downloadTracker.State.Value == DownloadState.Downloading || downloadTracker.State.Value == DownloadState.Importing; + + idleBottomContent.FadeTo(showProgress ? 0 : 1, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + downloadProgressBar.FadeTo(showProgress ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + } + } +} From 61e04f75cc7ad4c5966e605525679e7b28f23ebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 27 Nov 2021 15:41:09 +0100 Subject: [PATCH 02/12] Resize extra card to design size --- osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs index f244e912a1..7e79bded5d 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs @@ -30,8 +30,8 @@ namespace osu.Game.Beatmaps.Drawables.Cards { public class BeatmapCardExtra : OsuClickableContainer { - private const float width = 408; - private const float height = 100; + private const float width = 475; + private const float height = 140; private const float icon_area_width = 30; public Bindable Expanded { get; } = new BindableBool(); From 419fee1380ad94e068b417e7ea3fc1a5244c078e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 27 Nov 2021 15:46:01 +0100 Subject: [PATCH 03/12] Move mapper link to bottom content --- .../Drawables/Cards/BeatmapCardExtra.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs index 7e79bded5d..f42c96be7c 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs @@ -229,17 +229,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards }, } }, - 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 Container @@ -265,6 +254,17 @@ namespace osu.Game.Beatmaps.Drawables.Cards AlwaysPresent = true, Children = new Drawable[] { + 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); + }), statisticsContainer = new FillFlowContainer { RelativeSizeAxes = Axes.X, From 3ecfaa532cb270e36e96344b7f88488105e6b15c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 27 Nov 2021 15:47:52 +0100 Subject: [PATCH 04/12] Add source field to extra beatmap card --- osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs | 1 + osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs index 04aea4ac9c..2a308dd0d4 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs @@ -97,6 +97,7 @@ namespace osu.Game.Tests.Visual.Beatmaps 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.TrackId = 444; diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs index f42c96be7c..1926614c8f 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs @@ -229,6 +229,15 @@ namespace osu.Game.Beatmaps.Drawables.Cards }, } }, + new OsuSpriteText + { + RelativeSizeAxes = Axes.X, + Truncate = true, + Text = beatmapSet.Source, + Shadow = false, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold), + Colour = colourProvider.Content2 + }, } }, new Container From 2d739c95ea133a9b0068a283a7296700a6377f54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 27 Nov 2021 16:01:35 +0100 Subject: [PATCH 05/12] Lay out extra card statistics in grid as per design --- .../Drawables/Cards/BeatmapCardExtra.cs | 54 +++++++++++++------ 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs index 1926614c8f..663bb26919 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs @@ -3,7 +3,6 @@ #nullable enable -using System.Collections.Generic; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -50,7 +49,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards private Container mainContent = null!; private BeatmapCardContentBackground mainContentBackground = null!; - private FillFlowContainer statisticsContainer = null!; + private GridContainer statisticsContainer = null!; private FillFlowContainer idleBottomContent = null!; private BeatmapCardDownloadProgressBar downloadProgressBar = null!; @@ -274,15 +273,26 @@ namespace osu.Game.Beatmaps.Drawables.Cards d.AddText("mapped by ", t => t.Colour = colourProvider.Content2); d.AddUserLink(beatmapSet.Author); }), - statisticsContainer = new FillFlowContainer + statisticsContainer = new GridContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Alpha = 0, - AlwaysPresent = true, - ChildrenEnumerable = createStatistics() + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize) + }, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + new Dimension() + }, + Content = new[] + { + new Drawable[3], + new Drawable[3] + } }, new BeatmapCardExtraInfoRow(beatmapSet) { @@ -352,6 +362,8 @@ namespace osu.Game.Beatmaps.Drawables.Cards }; } + createStatistics(); + Action = () => beatmapSetOverlay?.FetchAndShowBeatmapSet(beatmapSet.OnlineID); } @@ -384,22 +396,32 @@ namespace osu.Game.Beatmaps.Drawables.Cards return BeatmapsetsStrings.ShowDetailsByArtist(romanisableArtist); } - private IEnumerable createStatistics() + private void createStatistics() { + BeatmapCardStatistic withMargin(BeatmapCardStatistic original) + { + original.Margin = new MarginPadding { Right = 10 }; + return original; + } + + statisticsContainer.Content[0][0] = withMargin(new FavouritesStatistic(beatmapSet) + { + Current = favouriteState, + }); + + statisticsContainer.Content[1][0] = withMargin(new PlayCountStatistic(beatmapSet)); + if (beatmapSet.HypeStatus != null) - yield return new HypesStatistic(beatmapSet.HypeStatus); + statisticsContainer.Content[0][1] = withMargin(new HypesStatistic(beatmapSet.HypeStatus)); // web does not show nominations unless hypes are also present. // see: https://github.com/ppy/osu-web/blob/8ed7d071fd1d3eaa7e43cf0e4ff55ca2fef9c07c/resources/assets/lib/beatmapset-panel.tsx#L443 if (beatmapSet.HypeStatus != null && beatmapSet.NominationStatus != null) - yield return new NominationsStatistic(beatmapSet.NominationStatus); - - yield return new FavouritesStatistic(beatmapSet) { Current = favouriteState }; - yield return new PlayCountStatistic(beatmapSet); + statisticsContainer.Content[1][1] = withMargin(new NominationsStatistic(beatmapSet.NominationStatus)); var dateStatistic = BeatmapCardDateStatistic.CreateFor(beatmapSet); if (dateStatistic != null) - yield return dateStatistic; + statisticsContainer.Content[0][2] = withMargin(dateStatistic); } private void updateState() @@ -419,8 +441,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards mainContent.ResizeWidthTo(targetWidth, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); mainContentBackground.Dimmed.Value = showDetails; - statisticsContainer.FadeTo(showDetails ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); - rightAreaBackground.FadeColour(downloadTracker.State.Value == DownloadState.LocallyAvailable ? colours.Lime0 : colourProvider.Background3, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); rightAreaButtons.FadeTo(showDetails ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); From 083ee92deea8f018032fcaa9d111f2192dd76a43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 27 Nov 2021 16:09:00 +0100 Subject: [PATCH 06/12] Adjust button vertical padding --- osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs index 663bb26919..f47e1a7eab 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs @@ -121,7 +121,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards RelativeSizeAxes = Axes.Y, Origin = Anchor.TopRight, Anchor = Anchor.TopRight, - Padding = new MarginPadding { Vertical = 17.5f }, + Padding = new MarginPadding { Vertical = 35 }, Child = rightAreaButtons = new Container { RelativeSizeAxes = Axes.Both, From 883fcf26044bef614e4d6d08d9e4719acb537ea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 17 Dec 2021 11:44:36 +0100 Subject: [PATCH 07/12] Fix tests --- .../Visual/Beatmaps/TestSceneBeatmapCard.cs | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs index 55dbf89334..2b98c61e9b 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs @@ -255,6 +255,12 @@ namespace osu.Game.Tests.Visual.Beatmaps createTestCase(beatmapSetInfo => new BeatmapCard(beatmapSetInfo)); } + [Test] + public void TestExtra() + { + createTestCase(beatmapSetInfo => new BeatmapCardExtra(beatmapSetInfo)); + } + [Test] public void TestHoverState() { @@ -280,19 +286,5 @@ namespace osu.Game.Tests.Visual.Beatmaps BeatmapCard firstCard() => this.ChildrenOfType().First(); } - - [Test] - public void TestExtra() - { - createTestCase(beatmapSetInfo => new BeatmapCardExtra(beatmapSetInfo)); - - AddToggleStep("toggle expanded state", expanded => - { - var card = this.ChildrenOfType().Last(); - if (!card.Expanded.Disabled) - card.Expanded.Value = expanded; - }); - AddToggleStep("disable/enable expansion", disabled => this.ChildrenOfType().ForEach(card => card.Expanded.Disabled = disabled)); - } } } From 3fa45479b0cc3c5d0dbd9e024f22cf5b954d29a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 17 Dec 2021 11:13:07 +0100 Subject: [PATCH 08/12] Share hype/nomination statistic show logic --- osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs | 12 ++++++------ .../Beatmaps/Drawables/Cards/BeatmapCardExtra.cs | 12 ++++++------ .../Drawables/Cards/Statistics/HypesStatistic.cs | 7 ++++++- .../Cards/Statistics/NominationsStatistic.cs | 9 ++++++++- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs index 1e24501426..14c29f8e99 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs @@ -380,13 +380,13 @@ namespace osu.Game.Beatmaps.Drawables.Cards private IEnumerable createStatistics() { - if (beatmapSet.HypeStatus != null) - yield return new HypesStatistic(beatmapSet.HypeStatus); + var hypesStatistic = HypesStatistic.CreateFor(beatmapSet); + if (hypesStatistic != null) + yield return hypesStatistic; - // web does not show nominations unless hypes are also present. - // see: https://github.com/ppy/osu-web/blob/8ed7d071fd1d3eaa7e43cf0e4ff55ca2fef9c07c/resources/assets/lib/beatmapset-panel.tsx#L443 - if (beatmapSet.HypeStatus != null && beatmapSet.NominationStatus != null) - yield return new NominationsStatistic(beatmapSet.NominationStatus); + var nominationsStatistic = NominationsStatistic.CreateFor(beatmapSet); + if (nominationsStatistic != null) + yield return nominationsStatistic; yield return new FavouritesStatistic(beatmapSet) { Current = favouriteState }; yield return new PlayCountStatistic(beatmapSet); diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs index 8d3c606d76..2ccc732119 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs @@ -409,13 +409,13 @@ namespace osu.Game.Beatmaps.Drawables.Cards statisticsContainer.Content[1][0] = withMargin(new PlayCountStatistic(beatmapSet)); - if (beatmapSet.HypeStatus != null) - statisticsContainer.Content[0][1] = withMargin(new HypesStatistic(beatmapSet.HypeStatus)); + var hypesStatistic = HypesStatistic.CreateFor(beatmapSet); + if (hypesStatistic != null) + statisticsContainer.Content[0][1] = withMargin(hypesStatistic); - // web does not show nominations unless hypes are also present. - // see: https://github.com/ppy/osu-web/blob/8ed7d071fd1d3eaa7e43cf0e4ff55ca2fef9c07c/resources/assets/lib/beatmapset-panel.tsx#L443 - if (beatmapSet.HypeStatus != null && beatmapSet.NominationStatus != null) - statisticsContainer.Content[1][1] = withMargin(new NominationsStatistic(beatmapSet.NominationStatus)); + var nominationsStatistic = NominationsStatistic.CreateFor(beatmapSet); + if (nominationsStatistic != null) + statisticsContainer.Content[1][1] = withMargin(nominationsStatistic); var dateStatistic = BeatmapCardDateStatistic.CreateFor(beatmapSet); if (dateStatistic != null) diff --git a/osu.Game/Beatmaps/Drawables/Cards/Statistics/HypesStatistic.cs b/osu.Game/Beatmaps/Drawables/Cards/Statistics/HypesStatistic.cs index 3fe31c7a41..521d1a5f21 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Statistics/HypesStatistic.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Statistics/HypesStatistic.cs @@ -1,6 +1,8 @@ // 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 osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics.Sprites; using osu.Game.Resources.Localisation.Web; @@ -12,11 +14,14 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Statistics /// public class HypesStatistic : BeatmapCardStatistic { - public HypesStatistic(BeatmapSetHypeStatus hypeStatus) + private HypesStatistic(BeatmapSetHypeStatus hypeStatus) { Icon = FontAwesome.Solid.Bullhorn; Text = hypeStatus.Current.ToLocalisableString(); TooltipText = BeatmapsStrings.HypeRequiredText(hypeStatus.Current.ToLocalisableString(), hypeStatus.Required.ToLocalisableString()); } + + public static HypesStatistic? CreateFor(IBeatmapSetOnlineInfo beatmapSetOnlineInfo) + => beatmapSetOnlineInfo.HypeStatus == null ? null : new HypesStatistic(beatmapSetOnlineInfo.HypeStatus); } } diff --git a/osu.Game/Beatmaps/Drawables/Cards/Statistics/NominationsStatistic.cs b/osu.Game/Beatmaps/Drawables/Cards/Statistics/NominationsStatistic.cs index f09269a615..23bd6ef0a9 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Statistics/NominationsStatistic.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Statistics/NominationsStatistic.cs @@ -1,6 +1,8 @@ // 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 osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics.Sprites; using osu.Game.Resources.Localisation.Web; @@ -12,11 +14,16 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Statistics /// public class NominationsStatistic : BeatmapCardStatistic { - public NominationsStatistic(BeatmapSetNominationStatus nominationStatus) + private NominationsStatistic(BeatmapSetNominationStatus nominationStatus) { Icon = FontAwesome.Solid.ThumbsUp; Text = nominationStatus.Current.ToLocalisableString(); TooltipText = BeatmapsStrings.NominationsRequiredText(nominationStatus.Current.ToLocalisableString(), nominationStatus.Required.ToLocalisableString()); } + + public static NominationsStatistic? CreateFor(IBeatmapSetOnlineInfo beatmapSetOnlineInfo) + // web does not show nominations unless hypes are also present. + // see: https://github.com/ppy/osu-web/blob/8ed7d071fd1d3eaa7e43cf0e4ff55ca2fef9c07c/resources/assets/lib/beatmapset-panel.tsx#L443 + => beatmapSetOnlineInfo.HypeStatus == null || beatmapSetOnlineInfo.NominationStatus == null ? null : new NominationsStatistic(beatmapSetOnlineInfo.NominationStatus); } } From 7aab12d4b061d6621e5c3b5e5bc36be8a75e8c06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 17 Dec 2021 11:27:38 +0100 Subject: [PATCH 09/12] Share extra row dropdown show/cancel show logic --- .../Beatmaps/Drawables/Cards/BeatmapCard.cs | 38 +++++++------------ .../Drawables/Cards/BeatmapCardExtra.cs | 38 +++++++------------ .../Cards/BeatmapCardExtraInfoRow.cs | 25 +++++++++++- 3 files changed, 49 insertions(+), 52 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs index 14c29f8e99..4892abc846 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs @@ -44,7 +44,8 @@ namespace osu.Game.Beatmaps.Drawables.Cards private readonly BeatmapDownloadTracker downloadTracker; - private BeatmapCardContent content = null!; + [Cached] + private readonly BeatmapCardContent content; private BeatmapCardThumbnail thumbnail = null!; @@ -72,6 +73,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards this.beatmapSet = beatmapSet; favouriteState = new Bindable(new BeatmapSetFavouriteState(beatmapSet.HasFavourited, beatmapSet.FavouriteCount)); downloadTracker = new BeatmapDownloadTracker(beatmapSet); + content = new BeatmapCardContent(height); } [BackgroundDependencyLoader(true)] @@ -80,13 +82,13 @@ namespace osu.Game.Beatmaps.Drawables.Cards Width = width; Height = height; - FillFlowContainer leftIconArea; - GridContainer titleContainer; - GridContainer artistContainer; + FillFlowContainer leftIconArea = null!; + GridContainer titleContainer = null!; + GridContainer artistContainer = null!; - InternalChild = content = new BeatmapCardContent(height) + InternalChild = content.With(c => { - MainContent = new Container + c.MainContent = new Container { RelativeSizeAxes = Axes.Both, Children = new Drawable[] @@ -281,20 +283,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards ChildrenEnumerable = createStatistics() }, new BeatmapCardExtraInfoRow(beatmapSet) - { - Hovered = _ => - { - content.ExpandAfterDelay(); - return false; - }, - Unhovered = _ => - { - // Handles the case where a user has not shown explicit intent to view expanded info. - // ie. quickly moved over the info row area but didn't remain within it. - if (!Expanded.Value) - content.CancelExpand(); - } - } } }, downloadProgressBar = new BeatmapCardDownloadProgressBar @@ -311,16 +299,16 @@ namespace osu.Game.Beatmaps.Drawables.Cards } } } - }, - ExpandedContent = new Container + }; + c.ExpandedContent = new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Padding = new MarginPadding { Horizontal = 10, Vertical = 13 }, Child = new BeatmapCardDifficultyList(beatmapSet) - }, - Expanded = { BindTarget = Expanded } - }; + }; + c.Expanded.BindTarget = Expanded; + }); if (beatmapSet.HasVideo) leftIconArea.Add(new IconPill(FontAwesome.Solid.Film) { IconSize = new Vector2(20) }); diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs index 2ccc732119..328294a323 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs @@ -40,7 +40,8 @@ namespace osu.Game.Beatmaps.Drawables.Cards private readonly BeatmapDownloadTracker downloadTracker; - private BeatmapCardContent content = null!; + [Cached] + private readonly BeatmapCardContent content; private BeatmapCardThumbnail thumbnail = null!; @@ -66,6 +67,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards this.beatmapSet = beatmapSet; favouriteState = new Bindable(new BeatmapSetFavouriteState(beatmapSet.HasFavourited, beatmapSet.FavouriteCount)); downloadTracker = new BeatmapDownloadTracker(beatmapSet); + content = new BeatmapCardContent(height); } [BackgroundDependencyLoader(true)] @@ -74,13 +76,13 @@ namespace osu.Game.Beatmaps.Drawables.Cards Width = width; Height = height; - FillFlowContainer leftIconArea; - GridContainer titleContainer; - GridContainer artistContainer; + FillFlowContainer leftIconArea = null!; + GridContainer titleContainer = null!; + GridContainer artistContainer = null!; - InternalChild = content = new BeatmapCardContent(height) + InternalChild = content.With(c => { - MainContent = new Container + c.MainContent = new Container { RelativeSizeAxes = Axes.Both, Children = new Drawable[] @@ -295,20 +297,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards } }, new BeatmapCardExtraInfoRow(beatmapSet) - { - Hovered = _ => - { - content.ExpandAfterDelay(); - return false; - }, - Unhovered = _ => - { - // This hide should only trigger if the expanded content has not shown yet. - // ie. if the user has not shown intent to want to see it (quickly moved over the info row area). - if (!Expanded.Value) - content.CancelExpand(); - } - } } }, downloadProgressBar = new BeatmapCardDownloadProgressBar @@ -325,16 +313,16 @@ namespace osu.Game.Beatmaps.Drawables.Cards } } } - }, - ExpandedContent = new Container + }; + c.ExpandedContent = new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Padding = new MarginPadding { Horizontal = 10, Vertical = 13 }, Child = new BeatmapCardDifficultyList(beatmapSet) - }, - Expanded = { BindTarget = Expanded } - }; + }; + c.Expanded.BindTarget = Expanded; + }); if (beatmapSet.HasVideo) leftIconArea.Add(new IconPill(FontAwesome.Solid.Film) { IconSize = new Vector2(20) }); diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtraInfoRow.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtraInfoRow.cs index 0a9d98e621..2d411ad344 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtraInfoRow.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtraInfoRow.cs @@ -1,21 +1,28 @@ // 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 osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; using osu.Game.Online.API.Requests.Responses; using osuTK; namespace osu.Game.Beatmaps.Drawables.Cards { - public class BeatmapCardExtraInfoRow : HoverHandlingContainer + public class BeatmapCardExtraInfoRow : CompositeDrawable { + [Resolved(CanBeNull = true)] + private BeatmapCardContent? content { get; set; } + public BeatmapCardExtraInfoRow(APIBeatmapSet beatmapSet) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - Child = new FillFlowContainer + InternalChild = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, @@ -39,5 +46,19 @@ namespace osu.Game.Beatmaps.Drawables.Cards } }; } + + protected override bool OnHover(HoverEvent e) + { + content?.ExpandAfterDelay(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + if (content?.Expanded.Value == false) + content.CancelExpand(); + + base.OnHoverLost(e); + } } } From f052b47d873cbe41277295a6ac75525a72fe996e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 17 Dec 2021 12:58:05 +0100 Subject: [PATCH 10/12] Extract collapsible button container for card usage --- .../Beatmaps/Drawables/Cards/BeatmapCard.cs | 104 +--------- .../Drawables/Cards/BeatmapCardExtra.cs | 104 +--------- .../Cards/CollapsibleButtonContainer.cs | 184 ++++++++++++++++++ 3 files changed, 200 insertions(+), 192 deletions(-) create mode 100644 osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs index 4892abc846..13c4cfe207 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs @@ -8,11 +8,9 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; 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.Beatmaps.Drawables.Cards.Buttons; using osu.Game.Beatmaps.Drawables.Cards.Statistics; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -24,7 +22,6 @@ using osu.Game.Overlays; using osu.Game.Overlays.BeatmapSet; using osuTK; using osu.Game.Resources.Localisation.Web; -using DownloadButton = osu.Game.Beatmaps.Drawables.Cards.Buttons.DownloadButton; namespace osu.Game.Beatmaps.Drawables.Cards { @@ -37,7 +34,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards private const float width = 408; private const float height = 100; - private const float icon_area_width = 30; private readonly APIBeatmapSet beatmapSet; private readonly Bindable favouriteState; @@ -48,20 +44,13 @@ namespace osu.Game.Beatmaps.Drawables.Cards private readonly BeatmapCardContent content; private BeatmapCardThumbnail thumbnail = null!; + private CollapsibleButtonContainer buttonContainer = null!; - private Container rightAreaBackground = null!; - private Container rightAreaButtons = null!; - - private Container mainContent = null!; - private BeatmapCardContentBackground mainContentBackground = null!; private FillFlowContainer statisticsContainer = null!; private FillFlowContainer idleBottomContent = null!; private BeatmapCardDownloadProgressBar downloadProgressBar = null!; - [Resolved] - private OsuColour colours { get; set; } = null!; - [Resolved] private OverlayColourProvider colourProvider { get; set; } = null!; @@ -94,21 +83,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards Children = new Drawable[] { downloadTracker, - rightAreaBackground = new Container - { - RelativeSizeAxes = Axes.Y, - Width = icon_area_width + 2 * CORNER_RADIUS, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - // workaround for masking artifacts at the top & bottom of card, - // which become especially visible on downloaded beatmaps (when the icon area has a lime background). - Padding = new MarginPadding { Vertical = 1 }, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Colour4.White - }, - }, thumbnail = new BeatmapCardThumbnail(beatmapSet) { Name = @"Left (icon) area", @@ -122,61 +96,19 @@ namespace osu.Game.Beatmaps.Drawables.Cards Spacing = new Vector2(1) } }, - new Container + buttonContainer = new CollapsibleButtonContainer(beatmapSet) { - Name = @"Right (button) area", - Width = 30, - RelativeSizeAxes = Axes.Y, - Origin = Anchor.TopRight, - Anchor = Anchor.TopRight, - Padding = new MarginPadding { Vertical = 17.5f }, - Child = rightAreaButtons = new Container - { - RelativeSizeAxes = Axes.Both, - Children = new BeatmapCardIconButton[] - { - new FavouriteButton(beatmapSet) - { - Current = favouriteState, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre - }, - new DownloadButton(beatmapSet) - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - State = { BindTarget = downloadTracker.State } - }, - new GoToBeatmapButton(beatmapSet) - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - State = { BindTarget = downloadTracker.State } - } - } - } - }, - mainContent = new Container - { - Name = @"Main content", X = height - CORNER_RADIUS, - Height = height, - CornerRadius = CORNER_RADIUS, - Masking = true, + Width = width - height + CORNER_RADIUS, + FavouriteState = { BindTarget = favouriteState }, + ButtonsCollapsedWidth = CORNER_RADIUS, + ButtonsExpandedWidth = 30, + ButtonsPadding = new MarginPadding { Vertical = 17.5f }, Children = new Drawable[] { - mainContentBackground = new BeatmapCardContentBackground(beatmapSet) - { - RelativeSizeAxes = Axes.Both, - }, new FillFlowContainer { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding - { - Horizontal = 10, - Vertical = 4 - }, Direction = FillDirection.Vertical, Children = new Drawable[] { @@ -256,11 +188,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards AutoSizeAxes = Axes.Y, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Padding = new MarginPadding - { - Horizontal = 10, - Vertical = 4 - }, Children = new Drawable[] { idleBottomContent = new FillFlowContainer @@ -388,30 +315,15 @@ namespace osu.Game.Beatmaps.Drawables.Cards { bool showDetails = IsHovered || Expanded.Value; - float targetWidth = width - height; - if (showDetails) - targetWidth = targetWidth - icon_area_width + CORNER_RADIUS; - + buttonContainer.ShowDetails.Value = showDetails; thumbnail.Dimmed.Value = showDetails; // Scale value is intentionally chosen to fit in the spacing of listing displays, as to not overlap horizontally with adjacent cards. // This avoids depth issues where a hovered (scaled) card to the right of another card would be beneath the card to the left. content.ScaleTo(Expanded.Value ? 1.03f : 1, 500, Easing.OutQuint); - mainContent.ResizeWidthTo(targetWidth, TRANSITION_DURATION, Easing.OutQuint); - mainContentBackground.Dimmed.Value = showDetails; - statisticsContainer.FadeTo(showDetails ? 1 : 0, TRANSITION_DURATION, Easing.OutQuint); - rightAreaBackground.FadeColour(downloadTracker.State.Value == DownloadState.LocallyAvailable ? colours.Lime0 : colourProvider.Background3, TRANSITION_DURATION, Easing.OutQuint); - rightAreaButtons.FadeTo(showDetails ? 1 : 0, TRANSITION_DURATION, Easing.OutQuint); - - foreach (var button in rightAreaButtons) - { - button.IdleColour = downloadTracker.State.Value != DownloadState.LocallyAvailable ? colourProvider.Light1 : colourProvider.Background3; - button.HoverColour = downloadTracker.State.Value != DownloadState.LocallyAvailable ? colourProvider.Content1 : colourProvider.Foreground1; - } - bool showProgress = downloadTracker.State.Value == DownloadState.Downloading || downloadTracker.State.Value == DownloadState.Importing; idleBottomContent.FadeTo(showProgress ? 0 : 1, TRANSITION_DURATION, Easing.OutQuint); diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs index 328294a323..fb498d643a 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs @@ -7,11 +7,9 @@ using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; 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.Beatmaps.Drawables.Cards.Buttons; using osu.Game.Beatmaps.Drawables.Cards.Statistics; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -23,7 +21,6 @@ using osu.Game.Overlays; using osu.Game.Overlays.BeatmapSet; using osuTK; using osu.Game.Resources.Localisation.Web; -using DownloadButton = osu.Game.Beatmaps.Drawables.Cards.Buttons.DownloadButton; namespace osu.Game.Beatmaps.Drawables.Cards { @@ -31,7 +28,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards { private const float width = 475; private const float height = 140; - private const float icon_area_width = 30; public Bindable Expanded { get; } = new BindableBool(); @@ -44,20 +40,13 @@ namespace osu.Game.Beatmaps.Drawables.Cards private readonly BeatmapCardContent content; private BeatmapCardThumbnail thumbnail = null!; + private CollapsibleButtonContainer buttonContainer = null!; - private Container rightAreaBackground = null!; - private Container rightAreaButtons = null!; - - private Container mainContent = null!; - private BeatmapCardContentBackground mainContentBackground = null!; private GridContainer statisticsContainer = null!; private FillFlowContainer idleBottomContent = null!; private BeatmapCardDownloadProgressBar downloadProgressBar = null!; - [Resolved] - private OsuColour colours { get; set; } = null!; - [Resolved] private OverlayColourProvider colourProvider { get; set; } = null!; @@ -88,21 +77,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards Children = new Drawable[] { downloadTracker, - rightAreaBackground = new Container - { - RelativeSizeAxes = Axes.Y, - Width = icon_area_width + 2 * BeatmapCard.CORNER_RADIUS, - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - // workaround for masking artifacts at the top & bottom of card, - // which become especially visible on downloaded beatmaps (when the icon area has a lime background). - Padding = new MarginPadding { Vertical = 1 }, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = Colour4.White - }, - }, thumbnail = new BeatmapCardThumbnail(beatmapSet) { Name = @"Left (icon) area", @@ -116,61 +90,19 @@ namespace osu.Game.Beatmaps.Drawables.Cards Spacing = new Vector2(1) } }, - new Container + buttonContainer = new CollapsibleButtonContainer(beatmapSet) { - Name = @"Right (button) area", - Width = 30, - RelativeSizeAxes = Axes.Y, - Origin = Anchor.TopRight, - Anchor = Anchor.TopRight, - Padding = new MarginPadding { Vertical = 35 }, - Child = rightAreaButtons = new Container - { - RelativeSizeAxes = Axes.Both, - Children = new BeatmapCardIconButton[] - { - new FavouriteButton(beatmapSet) - { - Current = favouriteState, - Anchor = Anchor.TopCentre, - Origin = Anchor.TopCentre - }, - new DownloadButton(beatmapSet) - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - State = { BindTarget = downloadTracker.State } - }, - new GoToBeatmapButton(beatmapSet) - { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - State = { BindTarget = downloadTracker.State } - } - } - } - }, - mainContent = new Container - { - Name = @"Main content", X = height - BeatmapCard.CORNER_RADIUS, - Height = height, - CornerRadius = BeatmapCard.CORNER_RADIUS, - Masking = true, + Width = width - height + BeatmapCard.CORNER_RADIUS, + FavouriteState = { BindTarget = favouriteState }, + ButtonsCollapsedWidth = BeatmapCard.CORNER_RADIUS, + ButtonsExpandedWidth = 30, + ButtonsPadding = new MarginPadding { Vertical = 35 }, Children = new Drawable[] { - mainContentBackground = new BeatmapCardContentBackground(beatmapSet) - { - RelativeSizeAxes = Axes.Both, - }, new FillFlowContainer { RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding - { - Horizontal = 10, - Vertical = 4 - }, Direction = FillDirection.Vertical, Children = new Drawable[] { @@ -248,11 +180,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards AutoSizeAxes = Axes.Y, Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Padding = new MarginPadding - { - Horizontal = 10, - Vertical = 4 - }, Children = new Drawable[] { idleBottomContent = new FillFlowContainer @@ -414,28 +341,13 @@ namespace osu.Game.Beatmaps.Drawables.Cards { bool showDetails = IsHovered || Expanded.Value; - float targetWidth = width - height; - if (showDetails) - targetWidth = targetWidth - icon_area_width + BeatmapCard.CORNER_RADIUS; - + buttonContainer.ShowDetails.Value = showDetails; thumbnail.Dimmed.Value = showDetails; // Scale value is intentionally chosen to fit in the spacing of listing displays, as to not overlap horizontally with adjacent cards. // This avoids depth issues where a hovered (scaled) card to the right of another card would be beneath the card to the left. content.ScaleTo(Expanded.Value ? 1.03f : 1, 500, Easing.OutQuint); - mainContent.ResizeWidthTo(targetWidth, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); - mainContentBackground.Dimmed.Value = showDetails; - - rightAreaBackground.FadeColour(downloadTracker.State.Value == DownloadState.LocallyAvailable ? colours.Lime0 : colourProvider.Background3, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); - rightAreaButtons.FadeTo(showDetails ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); - - foreach (var button in rightAreaButtons) - { - button.IdleColour = downloadTracker.State.Value != DownloadState.LocallyAvailable ? colourProvider.Light1 : colourProvider.Background3; - button.HoverColour = downloadTracker.State.Value != DownloadState.LocallyAvailable ? colourProvider.Content1 : colourProvider.Foreground1; - } - bool showProgress = downloadTracker.State.Value == DownloadState.Downloading || downloadTracker.State.Value == DownloadState.Importing; idleBottomContent.FadeTo(showProgress ? 0 : 1, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); diff --git a/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs b/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs new file mode 100644 index 0000000000..3a2cb80a8d --- /dev/null +++ b/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs @@ -0,0 +1,184 @@ +// 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 osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps.Drawables.Cards.Buttons; +using osu.Game.Graphics; +using osu.Game.Online; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays; + +namespace osu.Game.Beatmaps.Drawables.Cards +{ + public class CollapsibleButtonContainer : Container + { + public Bindable ShowDetails = new Bindable(); + public Bindable FavouriteState = new Bindable(); + + private readonly BeatmapDownloadTracker downloadTracker; + + private float buttonsExpandedWidth; + + public float ButtonsExpandedWidth + { + get => buttonsExpandedWidth; + set + { + buttonsExpandedWidth = value; + buttonArea.Width = value; + if (IsLoaded) + updateState(); + } + } + + private float buttonsCollapsedWidth; + + public float ButtonsCollapsedWidth + { + get => buttonsCollapsedWidth; + set + { + buttonsCollapsedWidth = value; + if (IsLoaded) + updateState(); + } + } + + public MarginPadding ButtonsPadding + { + get => buttons.Padding; + set => buttons.Padding = value; + } + + protected override Container Content => mainContent; + + private readonly Container background; + + private readonly Container buttonArea; + private readonly Container buttons; + + private readonly Container mainArea; + private readonly Container mainContent; + + [Resolved] + private OsuColour colours { get; set; } = null!; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + + public CollapsibleButtonContainer(APIBeatmapSet beatmapSet) + { + downloadTracker = new BeatmapDownloadTracker(beatmapSet); + + RelativeSizeAxes = Axes.Y; + Masking = true; + CornerRadius = BeatmapCard.CORNER_RADIUS; + + InternalChildren = new Drawable[] + { + downloadTracker, + background = new Container + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, + // workaround for masking artifacts at the top & bottom of card, + // which become especially visible on downloaded beatmaps (when the icon area has a lime background). + Padding = new MarginPadding { Vertical = 1 }, + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Colour4.White + }, + }, + buttonArea = new Container + { + Name = @"Right (button) area", + RelativeSizeAxes = Axes.Y, + Origin = Anchor.TopRight, + Anchor = Anchor.TopRight, + Child = buttons = new Container + { + RelativeSizeAxes = Axes.Both, + Children = new BeatmapCardIconButton[] + { + new FavouriteButton(beatmapSet) + { + Current = FavouriteState, + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre + }, + new DownloadButton(beatmapSet) + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + State = { BindTarget = downloadTracker.State } + }, + new GoToBeatmapButton(beatmapSet) + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + State = { BindTarget = downloadTracker.State } + } + } + } + }, + mainArea = new Container + { + Name = @"Main content", + RelativeSizeAxes = Axes.Y, + CornerRadius = BeatmapCard.CORNER_RADIUS, + Masking = true, + Children = new Drawable[] + { + new BeatmapCardContentBackground(beatmapSet) + { + RelativeSizeAxes = Axes.Both, + Dimmed = { BindTarget = ShowDetails } + }, + mainContent = new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding + { + Horizontal = 10, + Vertical = 4 + }, + } + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + downloadTracker.State.BindValueChanged(_ => updateState()); + ShowDetails.BindValueChanged(_ => updateState(), true); + FinishTransforms(true); + } + + private void updateState() + { + float targetWidth = Width - (ShowDetails.Value ? ButtonsExpandedWidth : ButtonsCollapsedWidth); + + mainArea.ResizeWidthTo(targetWidth, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + + background.FadeColour(downloadTracker.State.Value == DownloadState.LocallyAvailable ? colours.Lime0 : colourProvider.Background3, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + buttons.FadeTo(ShowDetails.Value ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + + foreach (var button in buttons) + { + button.IdleColour = downloadTracker.State.Value != DownloadState.LocallyAvailable ? colourProvider.Light1 : colourProvider.Background3; + button.HoverColour = downloadTracker.State.Value != DownloadState.LocallyAvailable ? colourProvider.Content1 : colourProvider.Foreground1; + } + } + } +} From d6f60399342512250fb0c92b90d0c8e13d853eb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 17 Dec 2021 13:27:11 +0100 Subject: [PATCH 11/12] Extract base class for beatmap cards --- .../Beatmaps/Drawables/Cards/BeatmapCard.cs | 101 +++++----------- .../Drawables/Cards/BeatmapCardBase.cs | 80 +++++++++++++ .../Drawables/Cards/BeatmapCardContent.cs | 14 +-- .../Cards/BeatmapCardContentBackground.cs | 4 +- .../Cards/BeatmapCardDownloadProgressBar.cs | 4 +- .../Drawables/Cards/BeatmapCardExtra.cs | 108 ++++++------------ .../Drawables/Cards/BeatmapCardThumbnail.cs | 4 +- .../Cards/Buttons/BeatmapCardIconButton.cs | 2 +- .../Drawables/Cards/Buttons/DownloadButton.cs | 4 +- .../Cards/Buttons/GoToBeatmapButton.cs | 2 +- .../Drawables/Cards/Buttons/PlayButton.cs | 2 +- .../Cards/CollapsibleButtonContainer.cs | 10 +- 12 files changed, 168 insertions(+), 167 deletions(-) create mode 100644 osu.Game/Beatmaps/Drawables/Cards/BeatmapCardBase.cs diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs index 13c4cfe207..b0df2e40d3 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs @@ -5,18 +5,14 @@ using System.Collections.Generic; using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Beatmaps.Drawables.Cards.Statistics; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using osu.Game.Online; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Overlays.BeatmapSet; @@ -25,21 +21,14 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Beatmaps.Drawables.Cards { - public class BeatmapCard : OsuClickableContainer + public class BeatmapCard : BeatmapCardBase { - public const float TRANSITION_DURATION = 400; - public const float CORNER_RADIUS = 10; - - public IBindable Expanded { get; } + protected override Drawable IdleContent => idleBottomContent; + protected override Drawable DownloadInProgressContent => downloadProgressBar; private const float width = 408; private const float height = 100; - private readonly APIBeatmapSet beatmapSet; - private readonly Bindable favouriteState; - - private readonly BeatmapDownloadTracker downloadTracker; - [Cached] private readonly BeatmapCardContent content; @@ -55,18 +44,13 @@ namespace osu.Game.Beatmaps.Drawables.Cards private OverlayColourProvider colourProvider { get; set; } = null!; public BeatmapCard(APIBeatmapSet beatmapSet, bool allowExpansion = true) - : base(HoverSampleSet.Submit) + : base(beatmapSet, allowExpansion) { - Expanded = new BindableBool { Disabled = !allowExpansion }; - - this.beatmapSet = beatmapSet; - favouriteState = new Bindable(new BeatmapSetFavouriteState(beatmapSet.HasFavourited, beatmapSet.FavouriteCount)); - downloadTracker = new BeatmapDownloadTracker(beatmapSet); content = new BeatmapCardContent(height); } - [BackgroundDependencyLoader(true)] - private void load(BeatmapSetOverlay? beatmapSetOverlay) + [BackgroundDependencyLoader] + private void load() { Width = width; Height = height; @@ -75,15 +59,14 @@ namespace osu.Game.Beatmaps.Drawables.Cards GridContainer titleContainer = null!; GridContainer artistContainer = null!; - InternalChild = content.With(c => + Child = content.With(c => { c.MainContent = new Container { RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - downloadTracker, - thumbnail = new BeatmapCardThumbnail(beatmapSet) + thumbnail = new BeatmapCardThumbnail(BeatmapSet) { Name = @"Left (icon) area", Size = new Vector2(height), @@ -96,11 +79,11 @@ namespace osu.Game.Beatmaps.Drawables.Cards Spacing = new Vector2(1) } }, - buttonContainer = new CollapsibleButtonContainer(beatmapSet) + buttonContainer = new CollapsibleButtonContainer(BeatmapSet) { X = height - CORNER_RADIUS, Width = width - height + CORNER_RADIUS, - FavouriteState = { BindTarget = favouriteState }, + FavouriteState = { BindTarget = FavouriteState }, ButtonsCollapsedWidth = CORNER_RADIUS, ButtonsExpandedWidth = 30, ButtonsPadding = new MarginPadding { Vertical = 17.5f }, @@ -131,7 +114,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards { new OsuSpriteText { - Text = new RomanisableString(beatmapSet.TitleUnicode, beatmapSet.Title), + Text = new RomanisableString(BeatmapSet.TitleUnicode, BeatmapSet.Title), Font = OsuFont.Default.With(size: 22.5f, weight: FontWeight.SemiBold), RelativeSizeAxes = Axes.X, Truncate = true @@ -177,7 +160,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards d.AutoSizeAxes = Axes.Both; d.Margin = new MarginPadding { Top = 2 }; d.AddText("mapped by ", t => t.Colour = colourProvider.Content2); - d.AddUserLink(beatmapSet.Author); + d.AddUserLink(BeatmapSet.Author); }), } }, @@ -209,7 +192,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards AlwaysPresent = true, ChildrenEnumerable = createStatistics() }, - new BeatmapCardExtraInfoRow(beatmapSet) + new BeatmapCardExtraInfoRow(BeatmapSet) } }, downloadProgressBar = new BeatmapCardDownloadProgressBar @@ -218,8 +201,8 @@ namespace osu.Game.Beatmaps.Drawables.Cards Height = 6, Anchor = Anchor.Centre, Origin = Anchor.Centre, - State = { BindTarget = downloadTracker.State }, - Progress = { BindTarget = downloadTracker.Progress } + State = { BindTarget = DownloadTracker.State }, + Progress = { BindTarget = DownloadTracker.Progress } } } } @@ -232,18 +215,18 @@ namespace osu.Game.Beatmaps.Drawables.Cards RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Padding = new MarginPadding { Horizontal = 10, Vertical = 13 }, - Child = new BeatmapCardDifficultyList(beatmapSet) + Child = new BeatmapCardDifficultyList(BeatmapSet) }; c.Expanded.BindTarget = Expanded; }); - if (beatmapSet.HasVideo) + if (BeatmapSet.HasVideo) leftIconArea.Add(new IconPill(FontAwesome.Solid.Film) { IconSize = new Vector2(20) }); - if (beatmapSet.HasStoryboard) + if (BeatmapSet.HasStoryboard) leftIconArea.Add(new IconPill(FontAwesome.Solid.Image) { IconSize = new Vector2(20) }); - if (beatmapSet.HasExplicitContent) + if (BeatmapSet.HasExplicitContent) { titleContainer.Content[0][1] = new ExplicitContentBeatmapPill { @@ -253,7 +236,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards }; } - if (beatmapSet.TrackId != null) + if (BeatmapSet.TrackId != null) { artistContainer.Content[0][1] = new FeaturedArtistBeatmapPill { @@ -262,57 +245,36 @@ namespace osu.Game.Beatmaps.Drawables.Cards Margin = new MarginPadding { Left = 5 } }; } - - Action = () => beatmapSetOverlay?.FetchAndShowBeatmapSet(beatmapSet.OnlineID); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - downloadTracker.State.BindValueChanged(_ => updateState()); - Expanded.BindValueChanged(_ => updateState(), true); - FinishTransforms(true); - } - - protected override bool OnHover(HoverEvent e) - { - updateState(); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - updateState(); - base.OnHoverLost(e); } private LocalisableString createArtistText() { - var romanisableArtist = new RomanisableString(beatmapSet.ArtistUnicode, beatmapSet.Artist); + var romanisableArtist = new RomanisableString(BeatmapSet.ArtistUnicode, BeatmapSet.Artist); return BeatmapsetsStrings.ShowDetailsByArtist(romanisableArtist); } private IEnumerable createStatistics() { - var hypesStatistic = HypesStatistic.CreateFor(beatmapSet); + var hypesStatistic = HypesStatistic.CreateFor(BeatmapSet); if (hypesStatistic != null) yield return hypesStatistic; - var nominationsStatistic = NominationsStatistic.CreateFor(beatmapSet); + var nominationsStatistic = NominationsStatistic.CreateFor(BeatmapSet); if (nominationsStatistic != null) yield return nominationsStatistic; - yield return new FavouritesStatistic(beatmapSet) { Current = favouriteState }; - yield return new PlayCountStatistic(beatmapSet); + yield return new FavouritesStatistic(BeatmapSet) { Current = FavouriteState }; + yield return new PlayCountStatistic(BeatmapSet); - var dateStatistic = BeatmapCardDateStatistic.CreateFor(beatmapSet); + var dateStatistic = BeatmapCardDateStatistic.CreateFor(BeatmapSet); if (dateStatistic != null) yield return dateStatistic; } - private void updateState() + protected override void UpdateState() { + base.UpdateState(); + bool showDetails = IsHovered || Expanded.Value; buttonContainer.ShowDetails.Value = showDetails; @@ -323,11 +285,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards content.ScaleTo(Expanded.Value ? 1.03f : 1, 500, Easing.OutQuint); statisticsContainer.FadeTo(showDetails ? 1 : 0, TRANSITION_DURATION, Easing.OutQuint); - - bool showProgress = downloadTracker.State.Value == DownloadState.Downloading || downloadTracker.State.Value == DownloadState.Importing; - - idleBottomContent.FadeTo(showProgress ? 0 : 1, TRANSITION_DURATION, Easing.OutQuint); - downloadProgressBar.FadeTo(showProgress ? 1 : 0, TRANSITION_DURATION, Easing.OutQuint); } } } diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardBase.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardBase.cs new file mode 100644 index 0000000000..77df0809bc --- /dev/null +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardBase.cs @@ -0,0 +1,80 @@ +// 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 osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Input.Events; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays; + +namespace osu.Game.Beatmaps.Drawables.Cards +{ + public abstract class BeatmapCardBase : OsuClickableContainer + { + public const float TRANSITION_DURATION = 400; + public const float CORNER_RADIUS = 10; + + public IBindable Expanded { get; } + + protected readonly APIBeatmapSet BeatmapSet; + protected readonly Bindable FavouriteState; + + protected abstract Drawable IdleContent { get; } + protected abstract Drawable DownloadInProgressContent { get; } + + protected readonly BeatmapDownloadTracker DownloadTracker; + + protected BeatmapCardBase(APIBeatmapSet beatmapSet, bool allowExpansion = true) + : base(HoverSampleSet.Submit) + { + Expanded = new BindableBool { Disabled = !allowExpansion }; + + BeatmapSet = beatmapSet; + FavouriteState = new Bindable(new BeatmapSetFavouriteState(beatmapSet.HasFavourited, beatmapSet.FavouriteCount)); + DownloadTracker = new BeatmapDownloadTracker(beatmapSet); + } + + [BackgroundDependencyLoader(true)] + private void load(BeatmapSetOverlay? beatmapSetOverlay) + { + Action = () => beatmapSetOverlay?.FetchAndShowBeatmapSet(BeatmapSet.OnlineID); + + AddInternal(DownloadTracker); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + DownloadTracker.State.BindValueChanged(_ => UpdateState()); + Expanded.BindValueChanged(_ => UpdateState(), true); + FinishTransforms(true); + } + + protected override bool OnHover(HoverEvent e) + { + UpdateState(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + UpdateState(); + base.OnHoverLost(e); + } + + protected virtual void UpdateState() + { + bool showProgress = DownloadTracker.State.Value == DownloadState.Downloading || DownloadTracker.State.Value == DownloadState.Importing; + + IdleContent.FadeTo(showProgress ? 0 : 1, TRANSITION_DURATION, Easing.OutQuint); + DownloadInProgressContent.FadeTo(showProgress ? 1 : 0, TRANSITION_DURATION, Easing.OutQuint); + } + } +} diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContent.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContent.cs index 286e03e700..e16421503c 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContent.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContent.cs @@ -54,7 +54,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - CornerRadius = BeatmapCard.CORNER_RADIUS, + CornerRadius = BeatmapCardBase.CORNER_RADIUS, Masking = true, Unhovered = _ => updateFromHoverChange(), Children = new Drawable[] @@ -67,7 +67,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards { RelativeSizeAxes = Axes.X, Height = height, - CornerRadius = BeatmapCard.CORNER_RADIUS, + CornerRadius = BeatmapCardBase.CORNER_RADIUS, Masking = true, }, dropdownContent = new HoverHandlingContainer @@ -91,7 +91,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards borderContainer = new Container { RelativeSizeAxes = Axes.Both, - CornerRadius = BeatmapCard.CORNER_RADIUS, + CornerRadius = BeatmapCardBase.CORNER_RADIUS, Masking = true, BorderThickness = 3, Child = new Box @@ -139,9 +139,9 @@ namespace osu.Game.Beatmaps.Drawables.Cards private void updateState() { - background.FadeTo(Expanded.Value ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); - dropdownContent.FadeTo(Expanded.Value ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); - borderContainer.FadeTo(Expanded.Value ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + background.FadeTo(Expanded.Value ? 1 : 0, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); + dropdownContent.FadeTo(Expanded.Value ? 1 : 0, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); + borderContainer.FadeTo(Expanded.Value ? 1 : 0, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); content.TweenEdgeEffectTo(new EdgeEffectParameters { @@ -150,7 +150,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards Radius = 10, Colour = Colour4.Black.Opacity(Expanded.Value ? 0.3f : 0f), Hollow = true, - }, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + }, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); } private class ExpandedContentScrollContainer : OsuScrollContainer diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs index 392f5d1bfa..6388e1698c 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs @@ -62,10 +62,10 @@ namespace osu.Game.Beatmaps.Drawables.Cards private void updateState() => Schedule(() => { - background.FadeColour(Dimmed.Value ? colourProvider.Background4 : colourProvider.Background2, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + background.FadeColour(Dimmed.Value ? colourProvider.Background4 : colourProvider.Background2, BeatmapCardBase.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); + cover.FadeColour(gradient, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); }); } } diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDownloadProgressBar.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDownloadProgressBar.cs index ffb4e0c540..b80c5221ab 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDownloadProgressBar.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardDownloadProgressBar.cs @@ -82,14 +82,14 @@ namespace osu.Game.Beatmaps.Drawables.Cards break; case DownloadState.Importing: - foregroundFill.FadeColour(colours.Yellow, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + foregroundFill.FadeColour(colours.Yellow, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); break; } } private void progressChanged() { - foreground.ResizeWidthTo((float)progress.Value, progress.Value > 0 ? BeatmapCard.TRANSITION_DURATION : 0, Easing.OutQuint); + foreground.ResizeWidthTo((float)progress.Value, progress.Value > 0 ? BeatmapCardBase.TRANSITION_DURATION : 0, Easing.OutQuint); } } } diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs index fb498d643a..39acbb352d 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs @@ -4,18 +4,14 @@ #nullable enable using osu.Framework.Allocation; -using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; -using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Beatmaps.Drawables.Cards.Statistics; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; -using osu.Game.Graphics.UserInterface; -using osu.Game.Online; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Overlays.BeatmapSet; @@ -24,18 +20,14 @@ using osu.Game.Resources.Localisation.Web; namespace osu.Game.Beatmaps.Drawables.Cards { - public class BeatmapCardExtra : OsuClickableContainer + public class BeatmapCardExtra : BeatmapCardBase { + protected override Drawable IdleContent => idleBottomContent; + protected override Drawable DownloadInProgressContent => downloadProgressBar; + private const float width = 475; private const float height = 140; - public Bindable Expanded { get; } = new BindableBool(); - - private readonly APIBeatmapSet beatmapSet; - private readonly Bindable favouriteState; - - private readonly BeatmapDownloadTracker downloadTracker; - [Cached] private readonly BeatmapCardContent content; @@ -50,12 +42,9 @@ namespace osu.Game.Beatmaps.Drawables.Cards [Resolved] private OverlayColourProvider colourProvider { get; set; } = null!; - public BeatmapCardExtra(APIBeatmapSet beatmapSet) - : base(HoverSampleSet.Submit) + public BeatmapCardExtra(APIBeatmapSet beatmapSet, bool allowExpansion = true) + : base(beatmapSet, allowExpansion) { - this.beatmapSet = beatmapSet; - favouriteState = new Bindable(new BeatmapSetFavouriteState(beatmapSet.HasFavourited, beatmapSet.FavouriteCount)); - downloadTracker = new BeatmapDownloadTracker(beatmapSet); content = new BeatmapCardContent(height); } @@ -69,19 +58,18 @@ namespace osu.Game.Beatmaps.Drawables.Cards GridContainer titleContainer = null!; GridContainer artistContainer = null!; - InternalChild = content.With(c => + Child = content.With(c => { c.MainContent = new Container { RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - downloadTracker, - thumbnail = new BeatmapCardThumbnail(beatmapSet) + thumbnail = new BeatmapCardThumbnail(BeatmapSet) { Name = @"Left (icon) area", Size = new Vector2(height), - Padding = new MarginPadding { Right = BeatmapCard.CORNER_RADIUS }, + Padding = new MarginPadding { Right = CORNER_RADIUS }, Child = leftIconArea = new FillFlowContainer { Margin = new MarginPadding(5), @@ -90,12 +78,12 @@ namespace osu.Game.Beatmaps.Drawables.Cards Spacing = new Vector2(1) } }, - buttonContainer = new CollapsibleButtonContainer(beatmapSet) + buttonContainer = new CollapsibleButtonContainer(BeatmapSet) { - X = height - BeatmapCard.CORNER_RADIUS, - Width = width - height + BeatmapCard.CORNER_RADIUS, - FavouriteState = { BindTarget = favouriteState }, - ButtonsCollapsedWidth = BeatmapCard.CORNER_RADIUS, + X = height - CORNER_RADIUS, + Width = width - height + CORNER_RADIUS, + FavouriteState = { BindTarget = FavouriteState }, + ButtonsCollapsedWidth = CORNER_RADIUS, ButtonsExpandedWidth = 30, ButtonsPadding = new MarginPadding { Vertical = 35 }, Children = new Drawable[] @@ -125,7 +113,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards { new OsuSpriteText { - Text = new RomanisableString(beatmapSet.TitleUnicode, beatmapSet.Title), + Text = new RomanisableString(BeatmapSet.TitleUnicode, BeatmapSet.Title), Font = OsuFont.Default.With(size: 22.5f, weight: FontWeight.SemiBold), RelativeSizeAxes = Axes.X, Truncate = true @@ -166,7 +154,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards { RelativeSizeAxes = Axes.X, Truncate = true, - Text = beatmapSet.Source, + Text = BeatmapSet.Source, Shadow = false, Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold), Colour = colourProvider.Content2 @@ -200,7 +188,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards d.AutoSizeAxes = Axes.Both; d.Margin = new MarginPadding { Top = 2 }; d.AddText("mapped by ", t => t.Colour = colourProvider.Content2); - d.AddUserLink(beatmapSet.Author); + d.AddUserLink(BeatmapSet.Author); }), statisticsContainer = new GridContainer { @@ -223,7 +211,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards new Drawable[3] } }, - new BeatmapCardExtraInfoRow(beatmapSet) + new BeatmapCardExtraInfoRow(BeatmapSet) } }, downloadProgressBar = new BeatmapCardDownloadProgressBar @@ -232,8 +220,8 @@ namespace osu.Game.Beatmaps.Drawables.Cards Height = 6, Anchor = Anchor.Centre, Origin = Anchor.Centre, - State = { BindTarget = downloadTracker.State }, - Progress = { BindTarget = downloadTracker.Progress } + State = { BindTarget = DownloadTracker.State }, + Progress = { BindTarget = DownloadTracker.Progress } } } } @@ -246,18 +234,18 @@ namespace osu.Game.Beatmaps.Drawables.Cards RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Padding = new MarginPadding { Horizontal = 10, Vertical = 13 }, - Child = new BeatmapCardDifficultyList(beatmapSet) + Child = new BeatmapCardDifficultyList(BeatmapSet) }; c.Expanded.BindTarget = Expanded; }); - if (beatmapSet.HasVideo) + if (BeatmapSet.HasVideo) leftIconArea.Add(new IconPill(FontAwesome.Solid.Film) { IconSize = new Vector2(20) }); - if (beatmapSet.HasStoryboard) + if (BeatmapSet.HasStoryboard) leftIconArea.Add(new IconPill(FontAwesome.Solid.Image) { IconSize = new Vector2(20) }); - if (beatmapSet.HasExplicitContent) + if (BeatmapSet.HasExplicitContent) { titleContainer.Content[0][1] = new ExplicitContentBeatmapPill { @@ -267,7 +255,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards }; } - if (beatmapSet.TrackId != null) + if (BeatmapSet.TrackId != null) { artistContainer.Content[0][1] = new FeaturedArtistBeatmapPill { @@ -279,33 +267,12 @@ namespace osu.Game.Beatmaps.Drawables.Cards createStatistics(); - Action = () => beatmapSetOverlay?.FetchAndShowBeatmapSet(beatmapSet.OnlineID); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - - downloadTracker.State.BindValueChanged(_ => updateState()); - Expanded.BindValueChanged(_ => updateState(), true); - FinishTransforms(true); - } - - protected override bool OnHover(HoverEvent e) - { - updateState(); - return base.OnHover(e); - } - - protected override void OnHoverLost(HoverLostEvent e) - { - updateState(); - base.OnHoverLost(e); + Action = () => beatmapSetOverlay?.FetchAndShowBeatmapSet(BeatmapSet.OnlineID); } private LocalisableString createArtistText() { - var romanisableArtist = new RomanisableString(beatmapSet.ArtistUnicode, beatmapSet.Artist); + var romanisableArtist = new RomanisableString(BeatmapSet.ArtistUnicode, BeatmapSet.Artist); return BeatmapsetsStrings.ShowDetailsByArtist(romanisableArtist); } @@ -317,28 +284,30 @@ namespace osu.Game.Beatmaps.Drawables.Cards return original; } - statisticsContainer.Content[0][0] = withMargin(new FavouritesStatistic(beatmapSet) + statisticsContainer.Content[0][0] = withMargin(new FavouritesStatistic(BeatmapSet) { - Current = favouriteState, + Current = FavouriteState, }); - statisticsContainer.Content[1][0] = withMargin(new PlayCountStatistic(beatmapSet)); + statisticsContainer.Content[1][0] = withMargin(new PlayCountStatistic(BeatmapSet)); - var hypesStatistic = HypesStatistic.CreateFor(beatmapSet); + var hypesStatistic = HypesStatistic.CreateFor(BeatmapSet); if (hypesStatistic != null) statisticsContainer.Content[0][1] = withMargin(hypesStatistic); - var nominationsStatistic = NominationsStatistic.CreateFor(beatmapSet); + var nominationsStatistic = NominationsStatistic.CreateFor(BeatmapSet); if (nominationsStatistic != null) statisticsContainer.Content[1][1] = withMargin(nominationsStatistic); - var dateStatistic = BeatmapCardDateStatistic.CreateFor(beatmapSet); + var dateStatistic = BeatmapCardDateStatistic.CreateFor(BeatmapSet); if (dateStatistic != null) statisticsContainer.Content[0][2] = withMargin(dateStatistic); } - private void updateState() + protected override void UpdateState() { + base.UpdateState(); + bool showDetails = IsHovered || Expanded.Value; buttonContainer.ShowDetails.Value = showDetails; @@ -347,11 +316,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards // Scale value is intentionally chosen to fit in the spacing of listing displays, as to not overlap horizontally with adjacent cards. // This avoids depth issues where a hovered (scaled) card to the right of another card would be beneath the card to the left. content.ScaleTo(Expanded.Value ? 1.03f : 1, 500, Easing.OutQuint); - - bool showProgress = downloadTracker.State.Value == DownloadState.Downloading || downloadTracker.State.Value == DownloadState.Importing; - - idleBottomContent.FadeTo(showProgress ? 0 : 1, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); - downloadProgressBar.FadeTo(showProgress ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); } } } diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs index f11a5916e1..e6b305552a 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardThumbnail.cs @@ -88,8 +88,8 @@ namespace osu.Game.Beatmaps.Drawables.Cards { bool shouldDim = Dimmed.Value || playButton.Playing.Value; - playButton.FadeTo(shouldDim ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); - cover.FadeColour(shouldDim ? OsuColour.Gray(0.2f) : Color4.White, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + playButton.FadeTo(shouldDim ? 1 : 0, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); + cover.FadeColour(shouldDim ? OsuColour.Gray(0.2f) : Color4.White, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); } } } diff --git a/osu.Game/Beatmaps/Drawables/Cards/Buttons/BeatmapCardIconButton.cs b/osu.Game/Beatmaps/Drawables/Cards/Buttons/BeatmapCardIconButton.cs index e362e3abeb..02c9ea640a 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Buttons/BeatmapCardIconButton.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Buttons/BeatmapCardIconButton.cs @@ -115,7 +115,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons bool isHovered = IsHovered && Enabled.Value; content.ScaleTo(isHovered ? 1.2f : 1, 500, Easing.OutQuint); - content.FadeColour(isHovered ? HoverColour : IdleColour, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + content.FadeColour(isHovered ? HoverColour : IdleColour, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); } } } diff --git a/osu.Game/Beatmaps/Drawables/Cards/Buttons/DownloadButton.cs b/osu.Game/Beatmaps/Drawables/Cards/Buttons/DownloadButton.cs index c94e335e8f..d7ba4af21e 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Buttons/DownloadButton.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Buttons/DownloadButton.cs @@ -69,7 +69,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons case DownloadState.LocallyAvailable: Action = null; TooltipText = string.Empty; - this.FadeOut(BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + this.FadeOut(BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); break; case DownloadState.NotDownloaded: @@ -81,7 +81,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons } Action = () => beatmaps.Download(beatmapSet, preferNoVideo.Value); - this.FadeIn(BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + this.FadeIn(BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); spinner.Hide(); Icon.Show(); diff --git a/osu.Game/Beatmaps/Drawables/Cards/Buttons/GoToBeatmapButton.cs b/osu.Game/Beatmaps/Drawables/Cards/Buttons/GoToBeatmapButton.cs index 9a6a3c01b7..b039eb6f10 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Buttons/GoToBeatmapButton.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Buttons/GoToBeatmapButton.cs @@ -43,7 +43,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons private void updateState() { - this.FadeTo(state.Value == DownloadState.LocallyAvailable ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + this.FadeTo(state.Value == DownloadState.LocallyAvailable ? 1 : 0, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); } } } diff --git a/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs b/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs index f7bab26666..6d66d5001a 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/Buttons/PlayButton.cs @@ -141,7 +141,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards.Buttons private void toggleLoading(bool loading) { Enabled.Value = !loading; - icon.FadeTo(loading ? 0 : 1, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + icon.FadeTo(loading ? 0 : 1, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); loadingSpinner.State.Value = loading ? Visibility.Visible : Visibility.Hidden; } } diff --git a/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs b/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs index 3a2cb80a8d..e1a630182f 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/CollapsibleButtonContainer.cs @@ -78,7 +78,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards RelativeSizeAxes = Axes.Y; Masking = true; - CornerRadius = BeatmapCard.CORNER_RADIUS; + CornerRadius = BeatmapCardBase.CORNER_RADIUS; InternalChildren = new Drawable[] { @@ -133,7 +133,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards { Name = @"Main content", RelativeSizeAxes = Axes.Y, - CornerRadius = BeatmapCard.CORNER_RADIUS, + CornerRadius = BeatmapCardBase.CORNER_RADIUS, Masking = true, Children = new Drawable[] { @@ -169,10 +169,10 @@ namespace osu.Game.Beatmaps.Drawables.Cards { float targetWidth = Width - (ShowDetails.Value ? ButtonsExpandedWidth : ButtonsCollapsedWidth); - mainArea.ResizeWidthTo(targetWidth, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + mainArea.ResizeWidthTo(targetWidth, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); - background.FadeColour(downloadTracker.State.Value == DownloadState.LocallyAvailable ? colours.Lime0 : colourProvider.Background3, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); - buttons.FadeTo(ShowDetails.Value ? 1 : 0, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + background.FadeColour(downloadTracker.State.Value == DownloadState.LocallyAvailable ? colours.Lime0 : colourProvider.Background3, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); + buttons.FadeTo(ShowDetails.Value ? 1 : 0, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); foreach (var button in buttons) { From 33e930f47786c5edad0d003fdee13aaf10f079cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 17 Dec 2021 13:29:20 +0100 Subject: [PATCH 12/12] Move scale-on-expand logic to `BeatmapCardContent` --- osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs | 4 ---- osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContent.cs | 4 ++++ osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs | 4 ---- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs index b0df2e40d3..a3b4c4c86c 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs @@ -280,10 +280,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards buttonContainer.ShowDetails.Value = showDetails; thumbnail.Dimmed.Value = showDetails; - // Scale value is intentionally chosen to fit in the spacing of listing displays, as to not overlap horizontally with adjacent cards. - // This avoids depth issues where a hovered (scaled) card to the right of another card would be beneath the card to the left. - content.ScaleTo(Expanded.Value ? 1.03f : 1, 500, Easing.OutQuint); - statisticsContainer.FadeTo(showDetails ? 1 : 0, TRANSITION_DURATION, Easing.OutQuint); } } diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContent.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContent.cs index e16421503c..9c43c16100 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContent.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContent.cs @@ -139,6 +139,10 @@ namespace osu.Game.Beatmaps.Drawables.Cards private void updateState() { + // Scale value is intentionally chosen to fit in the spacing of listing displays, as to not overlap horizontally with adjacent cards. + // This avoids depth issues where a hovered (scaled) card to the right of another card would be beneath the card to the left. + this.ScaleTo(Expanded.Value ? 1.03f : 1, 500, Easing.OutQuint); + background.FadeTo(Expanded.Value ? 1 : 0, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); dropdownContent.FadeTo(Expanded.Value ? 1 : 0, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); borderContainer.FadeTo(Expanded.Value ? 1 : 0, BeatmapCardBase.TRANSITION_DURATION, Easing.OutQuint); diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs index 39acbb352d..308cba9f0f 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardExtra.cs @@ -312,10 +312,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards buttonContainer.ShowDetails.Value = showDetails; thumbnail.Dimmed.Value = showDetails; - - // Scale value is intentionally chosen to fit in the spacing of listing displays, as to not overlap horizontally with adjacent cards. - // This avoids depth issues where a hovered (scaled) card to the right of another card would be beneath the card to the left. - content.ScaleTo(Expanded.Value ? 1.03f : 1, 500, Easing.OutQuint); } } }