From 7560d3de0435408c62d7e8ad9fbedfcb1e211747 Mon Sep 17 00:00:00 2001
From: MBmasher
Date: Mon, 22 Nov 2021 10:52:04 +1100
Subject: [PATCH 01/61] Remove decay factor in Flashlight skill
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs
index 466f0556ab..68434fd3d0 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs
@@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
{
}
- private double skillMultiplier => 0.15;
+ private double skillMultiplier => 0.07;
private double strainDecayBase => 0.15;
protected override double DecayWeight => 1.0;
protected override int HistoryLength => 10; // Look back for 10 notes is added for the sake of flashlight calculations.
@@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
// We also want to nerf stacks so that only the first object of the stack is accounted for.
double stackNerf = Math.Min(1.0, (osuPrevious.JumpDistance / scalingFactor) / 25.0);
- result += Math.Pow(0.8, i) * stackNerf * scalingFactor * jumpDistance / cumulativeStrainTime;
+ result += stackNerf * scalingFactor * jumpDistance / cumulativeStrainTime;
}
}
From 43546992586fcefc8f072deb091004edcf418175 Mon Sep 17 00:00:00 2001
From: MBmasher
Date: Tue, 30 Nov 2021 12:51:23 +1100
Subject: [PATCH 02/61] Fix cumulative strain time calculation in Flashlight
skill
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs
index 466f0556ab..9c539d5e4b 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs
@@ -45,11 +45,17 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
var osuPrevious = (OsuDifficultyHitObject)Previous[i];
var osuPreviousHitObject = (OsuHitObject)(osuPrevious.BaseObject);
+ OsuDifficultyHitObject osuLastPrevious;
+ if (i == 0)
+ osuLastPrevious = osuCurrent;
+ else
+ osuLastPrevious = (OsuDifficultyHitObject)Previous[i - 1];
+
if (!(osuPrevious.BaseObject is Spinner))
{
double jumpDistance = (osuHitObject.StackedPosition - osuPreviousHitObject.EndPosition).Length;
- cumulativeStrainTime += osuPrevious.StrainTime;
+ cumulativeStrainTime += osuLastPrevious.StrainTime;
// We want to nerf objects that can be easily seen within the Flashlight circle radius.
if (i == 0)
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 03/61] 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 04/61] 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 05/61] 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 06/61] 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 07/61] 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 08/61] 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 09/61] 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 10/61] 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 11/61] 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 12/61] 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 13/61] 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 14/61] 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);
}
}
}
From 04cfae9bdeb525855a34527a217e8b2cba34b115 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Sat, 18 Dec 2021 16:26:15 +0900
Subject: [PATCH 15/61] Fix "Random Skin" text not showing up correctly
---
osu.Game/Database/RealmLiveUnmanaged.cs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/osu.Game/Database/RealmLiveUnmanaged.cs b/osu.Game/Database/RealmLiveUnmanaged.cs
index 5a69898206..ea50ccc1ff 100644
--- a/osu.Game/Database/RealmLiveUnmanaged.cs
+++ b/osu.Game/Database/RealmLiveUnmanaged.cs
@@ -26,6 +26,8 @@ namespace osu.Game.Database
public bool Equals(ILive? other) => ID == other?.ID;
+ public override string ToString() => Value.ToString();
+
public Guid ID => Value.ID;
public void PerformRead(Action perform) => perform(Value);
From c11217755987abbe9ca0c63ad832f6839463647e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bart=C5=82omiej=20Dach?=
Date: Sun, 19 Dec 2021 12:48:09 +0100
Subject: [PATCH 16/61] Bring profile header test in line with modern
conventions
- Removed online code that didn't work anyway after the introduction of
the development web instance.
- Removed some weird test steps.
- Fixed online/offline test steps not working at all due to identical
user ID.
---
.../Online/TestSceneUserProfileHeader.cs | 73 +++++--------------
1 file changed, 20 insertions(+), 53 deletions(-)
diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs
index 76997bded7..c319d2f7de 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs
@@ -2,85 +2,52 @@
// See the LICENCE file in the repository root for full licence text.
using System;
+using NUnit.Framework;
using osu.Framework.Allocation;
-using osu.Game.Online.API;
-using osu.Game.Online.API.Requests;
+using osu.Framework.Testing;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.Profile;
-using osu.Game.Users;
namespace osu.Game.Tests.Visual.Online
{
public class TestSceneUserProfileHeader : OsuTestScene
{
- protected override bool UseOnlineAPI => true;
-
[Cached]
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green);
- [Resolved]
- private IAPIProvider api { get; set; }
+ private ProfileHeader header;
- private readonly ProfileHeader header;
-
- public TestSceneUserProfileHeader()
+ [SetUpSteps]
+ public void SetUpSteps()
{
- header = new ProfileHeader();
- Add(header);
+ AddStep("create header", () => Child = header = new ProfileHeader());
+ }
- AddStep("Show test dummy", () => header.User.Value = TestSceneUserProfileOverlay.TEST_USER);
+ [Test]
+ public void TestBasic()
+ {
+ AddStep("Show example user", () => header.User.Value = TestSceneUserProfileOverlay.TEST_USER);
+ }
- AddStep("Show null dummy", () => header.User.Value = new APIUser
- {
- Username = "Null"
- });
-
- AddStep("Show online dummy", () => header.User.Value = new APIUser
+ [Test]
+ public void TestOnlineState()
+ {
+ AddStep("Show online user", () => header.User.Value = new APIUser
{
+ Id = 1001,
Username = "IAmOnline",
LastVisit = DateTimeOffset.Now,
IsOnline = true,
});
- AddStep("Show offline dummy", () => header.User.Value = new APIUser
+ AddStep("Show offline user", () => header.User.Value = new APIUser
{
+ Id = 1002,
Username = "IAmOffline",
- LastVisit = DateTimeOffset.Now,
+ LastVisit = DateTimeOffset.Now.AddDays(-10),
IsOnline = false,
});
-
- addOnlineStep("Show ppy", new APIUser
- {
- Username = @"peppy",
- Id = 2,
- IsSupporter = true,
- Country = new Country { FullName = @"Australia", FlagName = @"AU" },
- CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg"
- });
-
- addOnlineStep("Show flyte", new APIUser
- {
- Username = @"flyte",
- Id = 3103765,
- Country = new Country { FullName = @"Japan", FlagName = @"JP" },
- CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg"
- });
- }
-
- private void addOnlineStep(string name, APIUser fallback)
- {
- AddStep(name, () =>
- {
- if (api.IsLoggedIn)
- {
- var request = new GetUserRequest(fallback.Id);
- request.Success += user => header.User.Value = user;
- api.Queue(request);
- }
- else
- header.User.Value = fallback;
- });
}
}
}
From 097402677d131f96aca3031c13876a5d927bcfb4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bart=C5=82omiej=20Dach?=
Date: Sun, 19 Dec 2021 12:55:24 +0100
Subject: [PATCH 17/61] Add test for ranked/unranked user display
---
.../Online/TestSceneUserProfileHeader.cs | 39 +++++++++++++++++++
.../Online/TestSceneUserProfileOverlay.cs | 1 +
osu.Game/Users/UserStatistics.cs | 3 ++
3 files changed, 43 insertions(+)
diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs
index c319d2f7de..dda9543159 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileHeader.cs
@@ -2,12 +2,14 @@
// See the LICENCE file in the repository root for full licence text.
using System;
+using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Testing;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Overlays.Profile;
+using osu.Game.Users;
namespace osu.Game.Tests.Visual.Online
{
@@ -49,5 +51,42 @@ namespace osu.Game.Tests.Visual.Online
IsOnline = false,
});
}
+
+ [Test]
+ public void TestRankedState()
+ {
+ AddStep("Show ranked user", () => header.User.Value = new APIUser
+ {
+ Id = 2001,
+ Username = "RankedUser",
+ Statistics = new UserStatistics
+ {
+ IsRanked = true,
+ GlobalRank = 15000,
+ CountryRank = 1500,
+ RankHistory = new APIRankHistory
+ {
+ Mode = @"osu",
+ Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray()
+ },
+ }
+ });
+
+ AddStep("Show unranked user", () => header.User.Value = new APIUser
+ {
+ Id = 2002,
+ Username = "UnrankedUser",
+ Statistics = new UserStatistics
+ {
+ IsRanked = false,
+ // web will sometimes return non-empty rank history even for unranked users.
+ RankHistory = new APIRankHistory
+ {
+ Mode = @"osu",
+ Data = Enumerable.Range(2345, 85).ToArray()
+ },
+ }
+ });
+ }
}
}
diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs
index 1c92bb1e38..78e2ceb45b 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneUserProfileOverlay.cs
@@ -29,6 +29,7 @@ namespace osu.Game.Tests.Visual.Online
ProfileOrder = new[] { "me" },
Statistics = new UserStatistics
{
+ IsRanked = true,
GlobalRank = 2148,
CountryRank = 1,
PP = 4567.89m,
diff --git a/osu.Game/Users/UserStatistics.cs b/osu.Game/Users/UserStatistics.cs
index c690447256..f8d26fe421 100644
--- a/osu.Game/Users/UserStatistics.cs
+++ b/osu.Game/Users/UserStatistics.cs
@@ -27,6 +27,9 @@ namespace osu.Game.Users
public int Progress;
}
+ [JsonProperty(@"is_ranked")]
+ public bool IsRanked;
+
[JsonProperty(@"global_rank")]
public int? GlobalRank;
From a6ccbafc77ead8416a8ea6f10407bd30db186046 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bart=C5=82omiej=20Dach?=
Date: Sun, 19 Dec 2021 13:19:00 +0100
Subject: [PATCH 18/61] Fix rank graph showing for unranked users
---
osu.Game/Overlays/Profile/Header/Components/RankGraph.cs | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs
index d6e515d8a1..d195babcbf 100644
--- a/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs
+++ b/osu.Game/Overlays/Profile/Header/Components/RankGraph.cs
@@ -42,7 +42,9 @@ namespace osu.Game.Overlays.Profile.Header.Components
private void updateStatistics(UserStatistics statistics)
{
- int[] userRanks = statistics?.RankHistory?.Data;
+ // checking both IsRanked and RankHistory is required.
+ // see https://github.com/ppy/osu-web/blob/154ceafba0f35a1dd935df53ec98ae2ea5615f9f/resources/assets/lib/profile-page/rank-chart.tsx#L46
+ int[] userRanks = statistics?.IsRanked == true ? statistics.RankHistory?.Data : null;
Data = userRanks?.Select((x, index) => new KeyValuePair(index, x)).Where(x => x.Value != 0).ToArray();
}
From 1203ae5984ca1c399f5c876a2cee6b4900466e5f Mon Sep 17 00:00:00 2001
From: Dan Balasescu
Date: Mon, 20 Dec 2021 11:49:39 +0900
Subject: [PATCH 19/61] Require installing .NET 5 in README
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 24b70b2de6..f18c5e76f9 100644
--- a/README.md
+++ b/README.md
@@ -48,7 +48,7 @@ You can see some examples of custom rulesets by visiting the [custom ruleset dir
Please make sure you have the following prerequisites:
-- A desktop platform with the [.NET 5.0 SDK](https://dotnet.microsoft.com/download) or higher installed.
+- A desktop platform with the [.NET 5.0 SDK](https://dotnet.microsoft.com/download) installed.
- When developing with mobile, [Xamarin](https://docs.microsoft.com/en-us/xamarin/) is required, which is shipped together with Visual Studio or [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/).
- When working with the codebase, we recommend using an IDE with intelligent code completion and syntax highlighting, such as [Visual Studio 2019+](https://visualstudio.microsoft.com/vs/), [JetBrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio Code](https://code.visualstudio.com/).
- When running on Linux, please have a system-wide FFmpeg installation available to support video decoding.
From 11f3ec0cb5821311ae5b5f8df1231925c3bd7efe Mon Sep 17 00:00:00 2001
From: Dan Balasescu
Date: Mon, 20 Dec 2021 12:44:22 +0900
Subject: [PATCH 20/61] Wait for previous screen to be hidden in test
---
.../Visual/Background/TestSceneBackgroundScreenDefault.cs | 1 +
1 file changed, 1 insertion(+)
diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs
index 3211405670..844fe7705a 100644
--- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs
+++ b/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenDefault.cs
@@ -85,6 +85,7 @@ namespace osu.Game.Tests.Visual.Background
// of note, this needs to be a type that doesn't match BackgroundScreenDefault else it is silently not pushed by the background stack.
AddStep("push new background to stack", () => stack.Push(nestedScreen = new BackgroundScreenBeatmap(Beatmap.Value)));
AddUntilStep("wait for screen to load", () => nestedScreen.IsLoaded && nestedScreen.IsCurrentScreen());
+ AddUntilStep("previous background hidden", () => !screen.IsAlive);
AddAssert("top level background hasn't changed yet", () => screen.CheckLastLoadChange() == null);
From 9316abc2786dded8078cccb977d21a7058c5faa4 Mon Sep 17 00:00:00 2001
From: Dan Balasescu
Date: Mon, 20 Dec 2021 13:10:13 +0900
Subject: [PATCH 21/61] Better fix for intermittent multiplayer tests
---
.../Visual/Multiplayer/QueueModeTestScene.cs | 3 +--
.../Multiplayer/TestSceneMultiplayer.cs | 10 ++++----
.../Visual/Multiplayer/TestSceneTeamVersus.cs | 2 +-
.../Multiplayer/MultiplayerTestScene.cs | 2 +-
.../Multiplayer/TestMultiplayerClient.cs | 12 +++++++---
.../Multiplayer/TestMultiplayerRoomManager.cs | 24 ++-----------------
6 files changed, 19 insertions(+), 34 deletions(-)
diff --git a/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs b/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs
index 357db16e2c..83292c36bf 100644
--- a/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs
@@ -41,7 +41,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
private TestMultiplayerScreenStack multiplayerScreenStack;
protected TestMultiplayerClient Client => multiplayerScreenStack.Client;
- protected TestMultiplayerRoomManager RoomManager => multiplayerScreenStack.RoomManager;
[Cached(typeof(UserLookupCache))]
private UserLookupCache lookupCache = new TestUserLookupCache();
@@ -93,7 +92,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
InputManager.Click(MouseButton.Left);
});
- AddUntilStep("wait for join", () => RoomManager.RoomJoined);
+ AddUntilStep("wait for join", () => Client.RoomJoined);
}
[Test]
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
index 710855a605..99411254a7 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
@@ -216,7 +216,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("Press select", () => InputManager.Key(Key.Enter));
AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true);
- AddUntilStep("wait for join", () => roomManager.RoomJoined);
+ AddUntilStep("wait for join", () => client.RoomJoined);
}
[Test]
@@ -295,7 +295,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("join room", () => InputManager.Key(Key.Enter));
AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true);
- AddUntilStep("wait for join", () => roomManager.RoomJoined);
+ AddUntilStep("wait for join", () => client.RoomJoined);
AddAssert("Check participant count correct", () => client.APIRoom?.ParticipantCount.Value == 1);
AddAssert("Check participant list contains user", () => client.APIRoom?.RecentParticipants.Count(u => u.Id == API.LocalUser.Value.Id) == 1);
@@ -353,7 +353,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("press join room button", () => passwordEntryPopover.ChildrenOfType().First().TriggerClick());
AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true);
- AddUntilStep("wait for join", () => roomManager.RoomJoined);
+ AddUntilStep("wait for join", () => client.RoomJoined);
}
[Test]
@@ -646,7 +646,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("join room", () => InputManager.Key(Key.Enter));
AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true);
- AddUntilStep("wait for join", () => roomManager.RoomJoined);
+ AddUntilStep("wait for join", () => client.RoomJoined);
AddAssert("local room has correct settings", () =>
{
@@ -838,7 +838,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
InputManager.Click(MouseButton.Left);
});
- AddUntilStep("wait for join", () => roomManager.RoomJoined);
+ AddUntilStep("wait for join", () => client.RoomJoined);
}
}
}
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs
index ccce26ad31..4ecbc30d76 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs
@@ -187,7 +187,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
InputManager.Click(MouseButton.Left);
});
- AddUntilStep("wait for join", () => multiplayerScreenStack.RoomManager.RoomJoined);
+ AddUntilStep("wait for join", () => client.RoomJoined);
}
}
}
diff --git a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs
index 5656704abf..7607122ef0 100644
--- a/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs
+++ b/osu.Game/Tests/Visual/Multiplayer/MultiplayerTestScene.cs
@@ -24,7 +24,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
protected new MultiplayerTestSceneDependencies OnlinePlayDependencies => (MultiplayerTestSceneDependencies)base.OnlinePlayDependencies;
- public bool RoomJoined => RoomManager.RoomJoined;
+ public bool RoomJoined => Client.RoomJoined;
private readonly bool joinRoom;
diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
index 4e0cfe405e..5b08b6b835 100644
--- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
+++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs
@@ -31,9 +31,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
private readonly Bindable isConnected = new Bindable(true);
public new Room? APIRoom => base.APIRoom;
-
public Action? RoomSetupAction;
+ public bool RoomJoined { get; private set; }
+
[Resolved]
private IAPIProvider api { get; set; } = null!;
@@ -49,7 +50,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
private MultiplayerPlaylistItem? currentItem => Room?.Playlist[currentIndex];
private int currentIndex;
-
private long lastPlaylistItemId;
public TestMultiplayerClient(TestMultiplayerRoomManager roomManager)
@@ -217,9 +217,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
// emulate the server sending this after the join room. scheduler required to make sure the join room event is fired first (in Join).
changeMatchType(Room.Settings.MatchType).Wait();
+
+ RoomJoined = true;
}
- protected override Task LeaveRoomInternal() => Task.CompletedTask;
+ protected override Task LeaveRoomInternal()
+ {
+ RoomJoined = false;
+ return Task.CompletedTask;
+ }
public override Task TransferHost(int userId) => ((IMultiplayerClient)this).HostChanged(userId);
diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs
index a1f010f082..296db3152d 100644
--- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs
+++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerRoomManager.cs
@@ -17,8 +17,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
///
public class TestMultiplayerRoomManager : MultiplayerRoomManager
{
- public bool RoomJoined { get; private set; }
-
private readonly TestRoomRequestsHandler requestsHandler;
public TestMultiplayerRoomManager(TestRoomRequestsHandler requestsHandler)
@@ -29,28 +27,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
public IReadOnlyList ServerSideRooms => requestsHandler.ServerSideRooms;
public override void CreateRoom(Room room, Action onSuccess = null, Action onError = null)
- {
- base.CreateRoom(room, r =>
- {
- onSuccess?.Invoke(r);
- RoomJoined = true;
- }, onError);
- }
+ => base.CreateRoom(room, r => onSuccess?.Invoke(r), onError);
public override void JoinRoom(Room room, string password = null, Action onSuccess = null, Action onError = null)
- {
- base.JoinRoom(room, password, r =>
- {
- onSuccess?.Invoke(r);
- RoomJoined = true;
- }, onError);
- }
-
- public override void PartRoom()
- {
- base.PartRoom();
- RoomJoined = false;
- }
+ => base.JoinRoom(room, password, r => onSuccess?.Invoke(r), onError);
///
/// Adds a room to a local "server-side" list that's returned when a is fired.
From d79602a9127ffcff60597dcbb8291da70566ffe2 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Mon, 20 Dec 2021 16:58:16 +0900
Subject: [PATCH 22/61] Add wait step to `TestScenePlaylistResultScreen`
explicitly for screen load
---
.../Visual/Playlists/TestScenePlaylistsResultsScreen.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs
index 25ca1299ef..e9210496ca 100644
--- a/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs
+++ b/osu.Game.Tests/Visual/Playlists/TestScenePlaylistsResultsScreen.cs
@@ -168,12 +168,13 @@ namespace osu.Game.Tests.Visual.Playlists
}));
});
+ AddUntilStep("wait for screen to load", () => resultsScreen.IsLoaded);
waitForDisplay();
}
private void waitForDisplay()
{
- AddUntilStep("wait for load to complete", () =>
+ AddUntilStep("wait for scores loaded", () =>
requestComplete
&& resultsScreen.ScorePanelList.GetScorePanels().Count() == totalCount
&& resultsScreen.ScorePanelList.AllPanelsVisible);
From af78a3e99d9126d6bd47219b4fe6a1b6625376d4 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Mon, 20 Dec 2021 17:09:08 +0900
Subject: [PATCH 23/61] Fix weird loop logic
---
osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
index be390742ea..01692ebc80 100644
--- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
+++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
@@ -883,7 +883,7 @@ namespace osu.Game.Tests.Visual.SongSelect
{
var usableRulesets = rulesets.AvailableRulesets.Where(r => r.OnlineID != 2).ToArray();
- for (int i = 0; i < 100; i += 10)
+ for (int i = 0; i < 10; i++)
manager.Import(TestResources.CreateTestBeatmapSetInfo(rulesets: usableRulesets)).Wait();
});
}
From 5c8e317a6e7b647b40e1f92a9d0d6eb17dbafda5 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Mon, 20 Dec 2021 17:11:15 +0900
Subject: [PATCH 24/61] Chooser earlier items in song select tests to avoid
potentially not having enough
---
.../Visual/SongSelect/TestScenePlaySongSelect.cs | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
index 01692ebc80..dcc34d2eaa 100644
--- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
+++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
@@ -488,8 +488,9 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep("select beatmap externally", () =>
{
target = manager.GetAllUsableBeatmapSets()
- .Where(b => b.Beatmaps.Any(bi => bi.RulesetID == targetRuleset))
- .ElementAt(5).Beatmaps.First(bi => bi.RulesetID == targetRuleset);
+ .First(b => b.Beatmaps.Any(bi => bi.RulesetID == targetRuleset))
+ .Beatmaps
+ .First(bi => bi.RulesetID == targetRuleset);
Beatmap.Value = manager.GetWorkingBeatmap(target);
});
@@ -534,8 +535,10 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep("select beatmap externally", () =>
{
- target = manager.GetAllUsableBeatmapSets().Where(b => b.Beatmaps.Any(bi => bi.RulesetID == 1))
- .ElementAt(5).Beatmaps.First();
+ target = manager
+ .GetAllUsableBeatmapSets()
+ .First(b => b.Beatmaps.Any(bi => bi.RulesetID == 1))
+ .Beatmaps.First();
Beatmap.Value = manager.GetWorkingBeatmap(target);
});
From 6caa950c44aba65eb9aef5aa2895d79e6ee0ddda Mon Sep 17 00:00:00 2001
From: MBmasher
Date: Mon, 20 Dec 2021 19:16:41 +1100
Subject: [PATCH 25/61] Rename `osuPrevious` to `osuLoop`
---
.../Difficulty/Skills/Flashlight.cs | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs
index 9c539d5e4b..cb1ccf949e 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs
@@ -42,27 +42,27 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
for (int i = 0; i < Previous.Count; i++)
{
- var osuPrevious = (OsuDifficultyHitObject)Previous[i];
- var osuPreviousHitObject = (OsuHitObject)(osuPrevious.BaseObject);
+ var osuLoop = (OsuDifficultyHitObject)Previous[i];
+ var osuLoopHitObject = (OsuHitObject)(osuLoop.BaseObject);
- OsuDifficultyHitObject osuLastPrevious;
+ OsuDifficultyHitObject osuLoopNext;
if (i == 0)
- osuLastPrevious = osuCurrent;
+ osuLoopNext = osuCurrent;
else
- osuLastPrevious = (OsuDifficultyHitObject)Previous[i - 1];
+ osuLoopNext = (OsuDifficultyHitObject)Previous[i - 1];
- if (!(osuPrevious.BaseObject is Spinner))
+ if (!(osuLoop.BaseObject is Spinner))
{
- double jumpDistance = (osuHitObject.StackedPosition - osuPreviousHitObject.EndPosition).Length;
+ double jumpDistance = (osuHitObject.StackedPosition - osuLoopHitObject.EndPosition).Length;
- cumulativeStrainTime += osuLastPrevious.StrainTime;
+ cumulativeStrainTime += osuLoopNext.StrainTime;
// We want to nerf objects that can be easily seen within the Flashlight circle radius.
if (i == 0)
smallDistNerf = Math.Min(1.0, jumpDistance / 75.0);
// We also want to nerf stacks so that only the first object of the stack is accounted for.
- double stackNerf = Math.Min(1.0, (osuPrevious.JumpDistance / scalingFactor) / 25.0);
+ double stackNerf = Math.Min(1.0, (osuLoop.JumpDistance / scalingFactor) / 25.0);
result += Math.Pow(0.8, i) * stackNerf * scalingFactor * jumpDistance / cumulativeStrainTime;
}
From 090c3e84e7004e544f7c57374865c87ceac41109 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Mon, 20 Dec 2021 17:38:14 +0900
Subject: [PATCH 26/61] Avoid blocking windows key usage when the osu! window
is not active
As discussed in https://github.com/ppy/osu/discussions/16147.
---
osu.Desktop/Windows/GameplayWinKeyBlocker.cs | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/osu.Desktop/Windows/GameplayWinKeyBlocker.cs b/osu.Desktop/Windows/GameplayWinKeyBlocker.cs
index dbfd170ea1..4acaf61cea 100644
--- a/osu.Desktop/Windows/GameplayWinKeyBlocker.cs
+++ b/osu.Desktop/Windows/GameplayWinKeyBlocker.cs
@@ -14,6 +14,7 @@ namespace osu.Desktop.Windows
{
private Bindable disableWinKey;
private IBindable localUserPlaying;
+ private IBindable isActive;
[Resolved]
private GameHost host { get; set; }
@@ -24,13 +25,16 @@ namespace osu.Desktop.Windows
localUserPlaying = localUserInfo.IsPlaying.GetBoundCopy();
localUserPlaying.BindValueChanged(_ => updateBlocking());
+ isActive = host.IsActive.GetBoundCopy();
+ isActive.BindValueChanged(_ => updateBlocking());
+
disableWinKey = config.GetBindable(OsuSetting.GameplayDisableWinKey);
disableWinKey.BindValueChanged(_ => updateBlocking(), true);
}
private void updateBlocking()
{
- bool shouldDisable = disableWinKey.Value && localUserPlaying.Value;
+ bool shouldDisable = isActive.Value && disableWinKey.Value && localUserPlaying.Value;
if (shouldDisable)
host.InputThread.Scheduler.Add(WindowsKey.Disable);
From 87051d5d61c71c8045c668686fe5b3020cb548a6 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Mon, 20 Dec 2021 17:46:20 +0900
Subject: [PATCH 27/61] Add better defined steps to `TestLoseHostWhileReady`
ready button test
Not 100% sure this will solve the issue but it's worth a try. The button
state checks are using `Until` everywhere else so this brings the test
in line with the standards.
As seen
https://github.com/ppy/osu/runs/4579641456?check_suite_focus=true.
---
.../Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs
index 84b63a5733..81220e2527 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerReadyButton.cs
@@ -163,10 +163,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
});
addClickButtonStep();
+ AddUntilStep("user is ready", () => Client.Room?.Users[0].State == MultiplayerUserState.Ready);
+
AddStep("transfer host", () => Client.TransferHost(Client.Room?.Users[1].UserID ?? 0));
addClickButtonStep();
- AddAssert("match not started", () => Client.Room?.Users[0].State == MultiplayerUserState.Idle);
+ AddUntilStep("user is idle (match not started)", () => Client.Room?.Users[0].State == MultiplayerUserState.Idle);
+ AddAssert("ready button enabled", () => button.ChildrenOfType().Single().Enabled.Value);
}
[TestCase(true)]
From 1533aefce5015d03083501d5bb6547bb77e7b5c4 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Mon, 20 Dec 2021 18:22:19 +0900
Subject: [PATCH 28/61] Update framework
---
osu.Android.props | 2 +-
osu.Game/osu.Game.csproj | 2 +-
osu.iOS.props | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/osu.Android.props b/osu.Android.props
index 209b8cd63e..1532d4ce23 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -52,7 +52,7 @@
-
+
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 97bdf00f69..6e6002bc8e 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -36,7 +36,7 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index d4b7339900..de359245d1 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -60,7 +60,7 @@
-
+
@@ -83,7 +83,7 @@
-
+
From 6907a9a3ccb5ef46863b5eb4bd6231f678fc606c Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Mon, 20 Dec 2021 18:24:14 +0900
Subject: [PATCH 29/61] Name some screen stacks for better logging context
---
osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs | 6 +++++-
.../Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs | 5 ++++-
osu.Game/Tests/Visual/ScreenTestScene.cs | 6 +++++-
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs b/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs
index 370f3bd0ae..88502b7074 100644
--- a/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs
+++ b/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs
@@ -49,7 +49,11 @@ namespace osu.Game.Tests.Visual
InternalChildren = new Drawable[]
{
Client = new TestMultiplayerClient(RoomManager),
- screenStack = new OsuScreenStack { RelativeSizeAxes = Axes.Both }
+ screenStack = new OsuScreenStack
+ {
+ Name = nameof(TestMultiplayerScreenStack),
+ RelativeSizeAxes = Axes.Both
+ }
};
screenStack.Push(multiplayerScreen);
diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs
index c3190cd845..48f153ecbe 100644
--- a/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs
+++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Spectate/PlayerArea.cs
@@ -87,7 +87,10 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
gameplayContent.Child = new PlayerIsolationContainer(beatmapManager.GetWorkingBeatmap(Score.ScoreInfo.BeatmapInfo), Score.ScoreInfo.Ruleset, Score.ScoreInfo.Mods)
{
RelativeSizeAxes = Axes.Both,
- Child = stack = new OsuScreenStack()
+ Child = stack = new OsuScreenStack
+ {
+ Name = nameof(PlayerArea),
+ }
};
stack.Push(new MultiSpectatorPlayerLoader(Score, () => new MultiSpectatorPlayer(Score, GameplayClock)));
diff --git a/osu.Game/Tests/Visual/ScreenTestScene.cs b/osu.Game/Tests/Visual/ScreenTestScene.cs
index aa46b516bf..c44a848275 100644
--- a/osu.Game/Tests/Visual/ScreenTestScene.cs
+++ b/osu.Game/Tests/Visual/ScreenTestScene.cs
@@ -29,7 +29,11 @@ namespace osu.Game.Tests.Visual
{
base.Content.AddRange(new Drawable[]
{
- Stack = new OsuScreenStack { RelativeSizeAxes = Axes.Both },
+ Stack = new OsuScreenStack
+ {
+ Name = nameof(ScreenTestScene),
+ RelativeSizeAxes = Axes.Both
+ },
content = new Container { RelativeSizeAxes = Axes.Both },
DialogOverlay = new DialogOverlay()
});
From ec0a6735eb519272f85413c0017e9dcf95ed11e5 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Mon, 20 Dec 2021 18:24:59 +0900
Subject: [PATCH 30/61] Rename `TestMultiplayerScreenStack` to
`TestMultiplayerComponents`
---
.../Visual/Multiplayer/QueueModeTestScene.cs | 20 +++----
.../Multiplayer/TestSceneMultiplayer.cs | 52 +++++++++----------
.../Visual/Multiplayer/TestSceneTeamVersus.cs | 18 +++----
.../Navigation/TestSceneScreenNavigation.cs | 8 +--
...nStack.cs => TestMultiplayerComponents.cs} | 6 +--
5 files changed, 52 insertions(+), 52 deletions(-)
rename osu.Game.Tests/Visual/{TestMultiplayerScreenStack.cs => TestMultiplayerComponents.cs} (95%)
diff --git a/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs b/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs
index 83292c36bf..5acb44ac45 100644
--- a/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs
@@ -31,16 +31,16 @@ namespace osu.Game.Tests.Visual.Multiplayer
protected BeatmapInfo InitialBeatmap { get; private set; }
protected BeatmapInfo OtherBeatmap { get; private set; }
- protected IScreen CurrentScreen => multiplayerScreenStack.CurrentScreen;
- protected IScreen CurrentSubScreen => multiplayerScreenStack.MultiplayerScreen.CurrentSubScreen;
+ protected IScreen CurrentScreen => multiplayerComponents.CurrentScreen;
+ protected IScreen CurrentSubScreen => multiplayerComponents.MultiplayerScreen.CurrentSubScreen;
private BeatmapManager beatmaps;
private RulesetStore rulesets;
private BeatmapSetInfo importedSet;
- private TestMultiplayerScreenStack multiplayerScreenStack;
+ private TestMultiplayerComponents multiplayerComponents;
- protected TestMultiplayerClient Client => multiplayerScreenStack.Client;
+ protected TestMultiplayerClient Client => multiplayerComponents.Client;
[Cached(typeof(UserLookupCache))]
private UserLookupCache lookupCache = new TestUserLookupCache();
@@ -64,12 +64,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
OtherBeatmap = importedSet.Beatmaps.Last(b => b.RulesetID == 0);
});
- AddStep("load multiplayer", () => LoadScreen(multiplayerScreenStack = new TestMultiplayerScreenStack()));
- AddUntilStep("wait for multiplayer to load", () => multiplayerScreenStack.IsLoaded);
+ AddStep("load multiplayer", () => LoadScreen(multiplayerComponents = new TestMultiplayerComponents()));
+ AddUntilStep("wait for multiplayer to load", () => multiplayerComponents.IsLoaded);
AddUntilStep("wait for lounge to load", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true);
- AddUntilStep("wait for lounge", () => multiplayerScreenStack.ChildrenOfType().SingleOrDefault()?.IsLoaded == true);
- AddStep("open room", () => multiplayerScreenStack.ChildrenOfType().Single().Open(new Room
+ AddUntilStep("wait for lounge", () => multiplayerComponents.ChildrenOfType().SingleOrDefault()?.IsLoaded == true);
+ AddStep("open room", () => multiplayerComponents.ChildrenOfType().Single().Open(new Room
{
Name = { Value = "Test Room" },
QueueMode = { Value = Mode },
@@ -109,8 +109,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddUntilStep("wait for ready", () => Client.LocalUser?.State == MultiplayerUserState.Ready);
clickReadyButton();
- AddUntilStep("wait for player", () => multiplayerScreenStack.CurrentScreen is Player player && player.IsLoaded);
- AddStep("exit player", () => multiplayerScreenStack.MultiplayerScreen.MakeCurrent());
+ AddUntilStep("wait for player", () => multiplayerComponents.CurrentScreen is Player player && player.IsLoaded);
+ AddStep("exit player", () => multiplayerComponents.MultiplayerScreen.MakeCurrent());
}
private void clickReadyButton()
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
index 99411254a7..bd0e5c4eb9 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayer.cs
@@ -46,10 +46,10 @@ namespace osu.Game.Tests.Visual.Multiplayer
private RulesetStore rulesets;
private BeatmapSetInfo importedSet;
- private TestMultiplayerScreenStack multiplayerScreenStack;
+ private TestMultiplayerComponents multiplayerComponents;
- private TestMultiplayerClient client => multiplayerScreenStack.Client;
- private TestMultiplayerRoomManager roomManager => multiplayerScreenStack.RoomManager;
+ private TestMultiplayerClient client => multiplayerComponents.Client;
+ private TestMultiplayerRoomManager roomManager => multiplayerComponents.RoomManager;
[Cached(typeof(UserLookupCache))]
private UserLookupCache lookupCache = new TestUserLookupCache();
@@ -71,8 +71,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First();
});
- AddStep("load multiplayer", () => LoadScreen(multiplayerScreenStack = new TestMultiplayerScreenStack()));
- AddUntilStep("wait for multiplayer to load", () => multiplayerScreenStack.IsLoaded);
+ AddStep("load multiplayer", () => LoadScreen(multiplayerComponents = new TestMultiplayerComponents()));
+ AddUntilStep("wait for multiplayer to load", () => multiplayerComponents.IsLoaded);
AddUntilStep("wait for lounge to load", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true);
}
@@ -419,7 +419,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("Enter song select", () =>
{
- var currentSubScreen = ((Screens.OnlinePlay.Multiplayer.Multiplayer)multiplayerScreenStack.CurrentScreen).CurrentSubScreen;
+ var currentSubScreen = ((Screens.OnlinePlay.Multiplayer.Multiplayer)multiplayerComponents.CurrentScreen).CurrentSubScreen;
((MultiplayerMatchSubScreen)currentSubScreen).OpenSongSelection(client.Room?.Settings.PlaylistItemId);
});
@@ -433,7 +433,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("start match externally", () => client.StartMatch());
- AddUntilStep("play started", () => multiplayerScreenStack.CurrentScreen is Player);
+ AddUntilStep("play started", () => multiplayerComponents.CurrentScreen is Player);
AddAssert("Beatmap matches current item", () => Beatmap.Value.BeatmapInfo.OnlineID == client.Room?.Playlist.First().BeatmapID);
}
@@ -473,7 +473,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("start match externally", () => client.StartMatch());
- AddAssert("play not started", () => multiplayerScreenStack.IsCurrentScreen());
+ AddAssert("play not started", () => multiplayerComponents.IsCurrentScreen());
}
[Test]
@@ -517,7 +517,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First();
});
- AddUntilStep("play started", () => multiplayerScreenStack.CurrentScreen is SpectatorScreen);
+ AddUntilStep("play started", () => multiplayerComponents.CurrentScreen is SpectatorScreen);
}
[Test]
@@ -559,16 +559,16 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("open mod overlay", () => this.ChildrenOfType().Single().TriggerClick());
- AddStep("invoke on back button", () => multiplayerScreenStack.OnBackButton());
+ AddStep("invoke on back button", () => multiplayerComponents.OnBackButton());
AddAssert("mod overlay is hidden", () => this.ChildrenOfType().Single().State.Value == Visibility.Hidden);
AddAssert("dialog overlay is hidden", () => DialogOverlay.State.Value == Visibility.Hidden);
- testLeave("back button", () => multiplayerScreenStack.OnBackButton());
+ testLeave("back button", () => multiplayerComponents.OnBackButton());
// mimics home button and OS window close
- testLeave("forced exit", () => multiplayerScreenStack.Exit());
+ testLeave("forced exit", () => multiplayerComponents.Exit());
void testLeave(string actionName, Action action)
{
@@ -605,7 +605,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddUntilStep($"wait for time > {i}", () => this.ChildrenOfType().SingleOrDefault()?.GameplayClock.CurrentTime > time);
}
- AddUntilStep("wait for results", () => multiplayerScreenStack.CurrentScreen is ResultsScreen);
+ AddUntilStep("wait for results", () => multiplayerComponents.CurrentScreen is ResultsScreen);
}
[Test]
@@ -680,15 +680,15 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("set other user ready", () => client.ChangeUserState(1234, MultiplayerUserState.Ready));
pressReadyButton(1234);
- AddUntilStep("wait for gameplay", () => (multiplayerScreenStack.CurrentScreen as MultiSpectatorScreen)?.IsLoaded == true);
+ AddUntilStep("wait for gameplay", () => (multiplayerComponents.CurrentScreen as MultiSpectatorScreen)?.IsLoaded == true);
AddStep("press back button and exit", () =>
{
- multiplayerScreenStack.OnBackButton();
- multiplayerScreenStack.Exit();
+ multiplayerComponents.OnBackButton();
+ multiplayerComponents.Exit();
});
- AddUntilStep("wait for return to match subscreen", () => multiplayerScreenStack.MultiplayerScreen.IsCurrentScreen());
+ AddUntilStep("wait for return to match subscreen", () => multiplayerComponents.MultiplayerScreen.IsCurrentScreen());
AddUntilStep("user state is idle", () => client.LocalUser?.State == MultiplayerUserState.Idle);
}
@@ -716,17 +716,17 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("set other user ready", () => client.ChangeUserState(1234, MultiplayerUserState.Ready));
pressReadyButton(1234);
- AddUntilStep("wait for gameplay", () => (multiplayerScreenStack.CurrentScreen as MultiSpectatorScreen)?.IsLoaded == true);
+ AddUntilStep("wait for gameplay", () => (multiplayerComponents.CurrentScreen as MultiSpectatorScreen)?.IsLoaded == true);
AddStep("set other user loaded", () => client.ChangeUserState(1234, MultiplayerUserState.Loaded));
AddStep("set other user finished play", () => client.ChangeUserState(1234, MultiplayerUserState.FinishedPlay));
AddStep("press back button and exit", () =>
{
- multiplayerScreenStack.OnBackButton();
- multiplayerScreenStack.Exit();
+ multiplayerComponents.OnBackButton();
+ multiplayerComponents.Exit();
});
- AddUntilStep("wait for return to match subscreen", () => multiplayerScreenStack.MultiplayerScreen.IsCurrentScreen());
+ AddUntilStep("wait for return to match subscreen", () => multiplayerComponents.MultiplayerScreen.IsCurrentScreen());
AddWaitStep("wait for possible state change", 5);
AddUntilStep("user state is spectating", () => client.LocalUser?.State == MultiplayerUserState.Spectating);
}
@@ -758,7 +758,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddUntilStep("item arrived in playlist", () => client.Room?.Playlist.Count == 2);
- AddStep("exit gameplay as initial user", () => multiplayerScreenStack.MultiplayerScreen.MakeCurrent());
+ AddStep("exit gameplay as initial user", () => multiplayerComponents.MultiplayerScreen.MakeCurrent());
AddUntilStep("queue contains item", () => this.ChildrenOfType().Single().Items.Single().ID == 2);
}
@@ -792,7 +792,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("delete item as other user", () => client.RemoveUserPlaylistItem(1234, 2));
AddUntilStep("item removed from playlist", () => client.Room?.Playlist.Count == 1);
- AddStep("exit gameplay as initial user", () => multiplayerScreenStack.MultiplayerScreen.MakeCurrent());
+ AddStep("exit gameplay as initial user", () => multiplayerComponents.MultiplayerScreen.MakeCurrent());
AddUntilStep("queue is empty", () => this.ChildrenOfType().Single().Items.Count == 0);
}
@@ -800,7 +800,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
pressReadyButton();
pressReadyButton();
- AddUntilStep("wait for player", () => multiplayerScreenStack.CurrentScreen is Player);
+ AddUntilStep("wait for player", () => multiplayerComponents.CurrentScreen is Player);
}
private ReadyButton readyButton => this.ChildrenOfType().Single();
@@ -826,8 +826,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
private void createRoom(Func room)
{
- AddUntilStep("wait for lounge", () => multiplayerScreenStack.ChildrenOfType().SingleOrDefault()?.IsLoaded == true);
- AddStep("open room", () => multiplayerScreenStack.ChildrenOfType().Single().Open(room()));
+ AddUntilStep("wait for lounge", () => multiplayerComponents.ChildrenOfType().SingleOrDefault()?.IsLoaded == true);
+ AddStep("open room", () => multiplayerComponents.ChildrenOfType().Single().Open(room()));
AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true);
AddWaitStep("wait for transition", 2);
diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs
index 4ecbc30d76..81c59b90f5 100644
--- a/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs
@@ -31,9 +31,9 @@ namespace osu.Game.Tests.Visual.Multiplayer
private RulesetStore rulesets;
private BeatmapSetInfo importedSet;
- private TestMultiplayerScreenStack multiplayerScreenStack;
+ private TestMultiplayerComponents multiplayerComponents;
- private TestMultiplayerClient client => multiplayerScreenStack.Client;
+ private TestMultiplayerClient client => multiplayerComponents.Client;
[Cached(typeof(UserLookupCache))]
private UserLookupCache lookupCache = new TestUserLookupCache();
@@ -55,8 +55,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First();
});
- AddStep("load multiplayer", () => LoadScreen(multiplayerScreenStack = new TestMultiplayerScreenStack()));
- AddUntilStep("wait for multiplayer to load", () => multiplayerScreenStack.IsLoaded);
+ AddStep("load multiplayer", () => LoadScreen(multiplayerComponents = new TestMultiplayerComponents()));
+ AddUntilStep("wait for multiplayer to load", () => multiplayerComponents.IsLoaded);
AddUntilStep("wait for lounge to load", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true);
}
@@ -103,7 +103,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("press own button", () =>
{
- InputManager.MoveMouseTo(multiplayerScreenStack.ChildrenOfType().First());
+ InputManager.MoveMouseTo(multiplayerComponents.ChildrenOfType().First());
InputManager.Click(MouseButton.Left);
});
AddAssert("user on team 1", () => (client.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 1);
@@ -113,7 +113,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddStep("press other user's button", () =>
{
- InputManager.MoveMouseTo(multiplayerScreenStack.ChildrenOfType().ElementAt(1));
+ InputManager.MoveMouseTo(multiplayerComponents.ChildrenOfType().ElementAt(1));
InputManager.Click(MouseButton.Left);
});
AddAssert("user still on team 0", () => (client.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0);
@@ -164,18 +164,18 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddUntilStep("room type is head to head", () => client.Room?.Settings.MatchType == MatchType.HeadToHead);
- AddUntilStep("team displays are not displaying teams", () => multiplayerScreenStack.ChildrenOfType().All(d => d.DisplayedTeam == null));
+ AddUntilStep("team displays are not displaying teams", () => multiplayerComponents.ChildrenOfType().All(d => d.DisplayedTeam == null));
AddStep("change to team vs", () => client.ChangeSettings(matchType: MatchType.TeamVersus));
AddUntilStep("room type is team vs", () => client.Room?.Settings.MatchType == MatchType.TeamVersus);
- AddUntilStep("team displays are displaying teams", () => multiplayerScreenStack.ChildrenOfType().All(d => d.DisplayedTeam != null));
+ AddUntilStep("team displays are displaying teams", () => multiplayerComponents.ChildrenOfType().All(d => d.DisplayedTeam != null));
}
private void createRoom(Func room)
{
- AddStep("open room", () => multiplayerScreenStack.ChildrenOfType().Single().Open(room()));
+ AddStep("open room", () => multiplayerComponents.ChildrenOfType().Single().Open(room()));
AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true);
AddWaitStep("wait for transition", 2);
diff --git a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs
index 664c186cf8..48ab643992 100644
--- a/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs
+++ b/osu.Game.Tests/Visual/Navigation/TestSceneScreenNavigation.cs
@@ -336,12 +336,12 @@ namespace osu.Game.Tests.Visual.Navigation
[Test]
public void TestPushMatchSubScreenAndPressBackButtonImmediately()
{
- TestMultiplayerScreenStack multiplayerScreenStack = null;
+ TestMultiplayerComponents multiplayerComponents = null;
- PushAndConfirm(() => multiplayerScreenStack = new TestMultiplayerScreenStack());
+ PushAndConfirm(() => multiplayerComponents = new TestMultiplayerComponents());
- AddUntilStep("wait for lounge", () => multiplayerScreenStack.ChildrenOfType().SingleOrDefault()?.IsLoaded == true);
- AddStep("open room", () => multiplayerScreenStack.ChildrenOfType().Single().Open());
+ AddUntilStep("wait for lounge", () => multiplayerComponents.ChildrenOfType().SingleOrDefault()?.IsLoaded == true);
+ AddStep("open room", () => multiplayerComponents.ChildrenOfType().Single().Open());
AddStep("press back button", () => Game.ChildrenOfType().First().Action());
AddWaitStep("wait two frames", 2);
}
diff --git a/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs b/osu.Game.Tests/Visual/TestMultiplayerComponents.cs
similarity index 95%
rename from osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs
rename to osu.Game.Tests/Visual/TestMultiplayerComponents.cs
index 88502b7074..cd7a936778 100644
--- a/osu.Game.Tests/Visual/TestMultiplayerScreenStack.cs
+++ b/osu.Game.Tests/Visual/TestMultiplayerComponents.cs
@@ -26,7 +26,7 @@ namespace osu.Game.Tests.Visual
///
///
///
- public class TestMultiplayerScreenStack : OsuScreen
+ public class TestMultiplayerComponents : OsuScreen
{
public Screens.OnlinePlay.Multiplayer.Multiplayer MultiplayerScreen => multiplayerScreen;
@@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual
private readonly OsuScreenStack screenStack;
private readonly TestMultiplayer multiplayerScreen;
- public TestMultiplayerScreenStack()
+ public TestMultiplayerComponents()
{
multiplayerScreen = new TestMultiplayer();
@@ -51,7 +51,7 @@ namespace osu.Game.Tests.Visual
Client = new TestMultiplayerClient(RoomManager),
screenStack = new OsuScreenStack
{
- Name = nameof(TestMultiplayerScreenStack),
+ Name = nameof(TestMultiplayerComponents),
RelativeSizeAxes = Axes.Both
}
};
From f492cf84d9d83d8ea9a39e5c1c511471d5bd7f29 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bart=C5=82omiej=20Dach?=
Date: Mon, 20 Dec 2021 11:24:40 +0100
Subject: [PATCH 31/61] Ensure presence of at least 1 difficulty for each
ruleset
---
.../SongSelect/TestScenePlaySongSelect.cs | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
index dcc34d2eaa..912d3f838c 100644
--- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
+++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs
@@ -466,7 +466,9 @@ namespace osu.Game.Tests.Visual.SongSelect
public void TestExternalBeatmapChangeWhileFiltered(bool differentRuleset)
{
createSongSelect();
- addManyTestMaps();
+ // ensure there is at least 1 difficulty for each of the rulesets
+ // (catch is excluded inside of addManyTestMaps).
+ addManyTestMaps(3);
changeRuleset(0);
@@ -519,7 +521,9 @@ namespace osu.Game.Tests.Visual.SongSelect
public void TestExternalBeatmapChangeWhileFilteredThenRefilter()
{
createSongSelect();
- addManyTestMaps();
+ // ensure there is at least 1 difficulty for each of the rulesets
+ // (catch is excluded inside of addManyTestMaps).
+ addManyTestMaps(3);
changeRuleset(0);
@@ -880,14 +884,21 @@ namespace osu.Game.Tests.Visual.SongSelect
AddUntilStep("wait for carousel loaded", () => songSelect.Carousel.IsAlive);
}
- private void addManyTestMaps()
+ ///
+ /// Imports test beatmap sets to show in the carousel.
+ ///
+ ///
+ /// The exact count of difficulties to create for each beatmap set.
+ /// A value causes the count of difficulties to be selected randomly.
+ ///
+ private void addManyTestMaps(int? difficultyCountPerSet = null)
{
AddStep("import test maps", () =>
{
var usableRulesets = rulesets.AvailableRulesets.Where(r => r.OnlineID != 2).ToArray();
for (int i = 0; i < 10; i++)
- manager.Import(TestResources.CreateTestBeatmapSetInfo(rulesets: usableRulesets)).Wait();
+ manager.Import(TestResources.CreateTestBeatmapSetInfo(difficultyCountPerSet, usableRulesets)).Wait();
});
}
From a59583ee0901c3086059cd38b44ffcb86c7729b5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bart=C5=82omiej=20Dach?=
Date: Mon, 20 Dec 2021 13:18:02 +0100
Subject: [PATCH 32/61] Add extension method for returning next playlist item
---
.../OnlinePlay/PlaylistExtensionsTest.cs | 72 +++++++++++++++++++
osu.Game/Online/Rooms/PlaylistExtensions.cs | 10 +++
2 files changed, 82 insertions(+)
create mode 100644 osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs
diff --git a/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs b/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs
new file mode 100644
index 0000000000..d2ee47bc23
--- /dev/null
+++ b/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs
@@ -0,0 +1,72 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using NUnit.Framework;
+using osu.Game.Online.Rooms;
+
+namespace osu.Game.Tests.OnlinePlay
+{
+ [TestFixture]
+ public class PlaylistExtensionsTest
+ {
+ [Test]
+ public void TestPlaylistItemsInOrder()
+ {
+ var items = new[]
+ {
+ new PlaylistItem { ID = 1, BeatmapID = 1001, PlaylistOrder = 1 },
+ new PlaylistItem { ID = 2, BeatmapID = 1002, PlaylistOrder = 2 },
+ new PlaylistItem { ID = 3, BeatmapID = 1003, PlaylistOrder = 3 },
+ };
+
+ var nextItem = items.GetNextItem();
+
+ Assert.That(nextItem, Is.EqualTo(items[0]));
+ }
+
+ [Test]
+ public void TestPlaylistItemsOutOfOrder()
+ {
+ var items = new[]
+ {
+ new PlaylistItem { ID = 2, BeatmapID = 1002, PlaylistOrder = 2 },
+ new PlaylistItem { ID = 1, BeatmapID = 1001, PlaylistOrder = 1 },
+ new PlaylistItem { ID = 3, BeatmapID = 1003, PlaylistOrder = 3 },
+ };
+
+ var nextItem = items.GetNextItem();
+
+ Assert.That(nextItem, Is.EqualTo(items[1]));
+ }
+
+ [Test]
+ public void TestExpiredPlaylistItemsSkipped()
+ {
+ var items = new[]
+ {
+ new PlaylistItem { ID = 2, BeatmapID = 1002, PlaylistOrder = 2, Expired = true },
+ new PlaylistItem { ID = 1, BeatmapID = 1001, PlaylistOrder = 1, Expired = true },
+ new PlaylistItem { ID = 3, BeatmapID = 1003, PlaylistOrder = 3 },
+ };
+
+ var nextItem = items.GetNextItem();
+
+ Assert.That(nextItem, Is.EqualTo(items[2]));
+ }
+
+ [Test]
+ public void TestAllItemsExpired()
+ {
+ var items = new[]
+ {
+ new PlaylistItem { ID = 2, BeatmapID = 1002, PlaylistOrder = 2, Expired = true },
+ new PlaylistItem { ID = 1, BeatmapID = 1001, PlaylistOrder = 1, Expired = true },
+ new PlaylistItem { ID = 3, BeatmapID = 1003, PlaylistOrder = 3, Expired = true },
+ };
+
+ var nextItem = items.GetNextItem();
+
+ Assert.That(nextItem, Is.Null);
+ }
+ }
+}
diff --git a/osu.Game/Online/Rooms/PlaylistExtensions.cs b/osu.Game/Online/Rooms/PlaylistExtensions.cs
index 992011da3c..e900dc53ef 100644
--- a/osu.Game/Online/Rooms/PlaylistExtensions.cs
+++ b/osu.Game/Online/Rooms/PlaylistExtensions.cs
@@ -1,6 +1,9 @@
// 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 System.Linq;
using Humanizer;
using Humanizer.Localisation;
@@ -10,6 +13,13 @@ namespace osu.Game.Online.Rooms
{
public static class PlaylistExtensions
{
+ ///
+ /// Returns the next to be played from the supplied ,
+ /// or if all items are expired.
+ ///
+ public static PlaylistItem? GetNextItem(this IEnumerable playlist) =>
+ playlist.OrderBy(item => item.PlaylistOrder).FirstOrDefault(item => !item.Expired);
+
public static string GetTotalDuration(this BindableList playlist) =>
playlist.Select(p => p.Beatmap.Value.Length).Sum().Milliseconds().Humanize(minUnit: TimeUnit.Second, maxUnit: TimeUnit.Hour, precision: 2);
}
From a5a9922f81529f46d2efe46e11af0c6822512bf7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bart=C5=82omiej=20Dach?=
Date: Mon, 20 Dec 2021 13:19:00 +0100
Subject: [PATCH 33/61] Fix lounge screen content not matching current room
playlist item
---
osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs | 8 ++++----
osu.Game/Online/Rooms/PlaylistExtensions.cs | 4 ++--
.../OnlinePlay/Components/OnlinePlayBackgroundSprite.cs | 4 ++--
.../Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs | 3 +--
osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs | 5 ++---
5 files changed, 11 insertions(+), 13 deletions(-)
diff --git a/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs b/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs
index d2ee47bc23..001513be1f 100644
--- a/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs
+++ b/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs
@@ -19,7 +19,7 @@ namespace osu.Game.Tests.OnlinePlay
new PlaylistItem { ID = 3, BeatmapID = 1003, PlaylistOrder = 3 },
};
- var nextItem = items.GetNextItem();
+ var nextItem = items.GetCurrentItem();
Assert.That(nextItem, Is.EqualTo(items[0]));
}
@@ -34,7 +34,7 @@ namespace osu.Game.Tests.OnlinePlay
new PlaylistItem { ID = 3, BeatmapID = 1003, PlaylistOrder = 3 },
};
- var nextItem = items.GetNextItem();
+ var nextItem = items.GetCurrentItem();
Assert.That(nextItem, Is.EqualTo(items[1]));
}
@@ -49,7 +49,7 @@ namespace osu.Game.Tests.OnlinePlay
new PlaylistItem { ID = 3, BeatmapID = 1003, PlaylistOrder = 3 },
};
- var nextItem = items.GetNextItem();
+ var nextItem = items.GetCurrentItem();
Assert.That(nextItem, Is.EqualTo(items[2]));
}
@@ -64,7 +64,7 @@ namespace osu.Game.Tests.OnlinePlay
new PlaylistItem { ID = 3, BeatmapID = 1003, PlaylistOrder = 3, Expired = true },
};
- var nextItem = items.GetNextItem();
+ var nextItem = items.GetCurrentItem();
Assert.That(nextItem, Is.Null);
}
diff --git a/osu.Game/Online/Rooms/PlaylistExtensions.cs b/osu.Game/Online/Rooms/PlaylistExtensions.cs
index e900dc53ef..46cb218910 100644
--- a/osu.Game/Online/Rooms/PlaylistExtensions.cs
+++ b/osu.Game/Online/Rooms/PlaylistExtensions.cs
@@ -14,10 +14,10 @@ namespace osu.Game.Online.Rooms
public static class PlaylistExtensions
{
///
- /// Returns the next to be played from the supplied ,
+ /// Returns the first non-expired in playlist order from the supplied ,
/// or if all items are expired.
///
- public static PlaylistItem? GetNextItem(this IEnumerable playlist) =>
+ public static PlaylistItem? GetCurrentItem(this IEnumerable playlist) =>
playlist.OrderBy(item => item.PlaylistOrder).FirstOrDefault(item => !item.Expired);
public static string GetTotalDuration(this BindableList playlist) =>
diff --git a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs
index e2ba0b03b0..d144e1e3a9 100644
--- a/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs
+++ b/osu.Game/Screens/OnlinePlay/Components/OnlinePlayBackgroundSprite.cs
@@ -1,10 +1,10 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Beatmaps.Drawables;
+using osu.Game.Online.Rooms;
namespace osu.Game.Screens.OnlinePlay.Components
{
@@ -30,7 +30,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
private void updateBeatmap()
{
- sprite.Beatmap.Value = Playlist.FirstOrDefault()?.Beatmap.Value;
+ sprite.Beatmap.Value = Playlist.GetCurrentItem()?.Beatmap.Value;
}
protected virtual UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new UpdateableBeatmapBackgroundSprite(BeatmapSetCoverType) { RelativeSizeAxes = Axes.Both };
diff --git a/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs b/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs
index 6c00ca2e81..926c35c5da 100644
--- a/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs
+++ b/osu.Game/Screens/OnlinePlay/Lounge/LoungeBackgroundScreen.cs
@@ -3,7 +3,6 @@
#nullable enable
-using System.Linq;
using osu.Framework.Bindables;
using osu.Framework.Screens;
using osu.Game.Online.Rooms;
@@ -20,7 +19,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge
public LoungeBackgroundScreen()
{
SelectedRoom.BindValueChanged(onSelectedRoomChanged);
- playlist.BindCollectionChanged((_, __) => PlaylistItem = playlist.FirstOrDefault());
+ playlist.BindCollectionChanged((_, __) => PlaylistItem = playlist.GetCurrentItem());
}
private void onSelectedRoomChanged(ValueChangedEvent room)
diff --git a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs
index 6b111d76a5..c833621fbc 100644
--- a/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs
+++ b/osu.Game/Screens/OnlinePlay/OnlinePlayComposite.cs
@@ -2,7 +2,6 @@
// See the LICENCE file in the repository root for full licence text.
using System;
-using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics.Containers;
@@ -73,7 +72,7 @@ namespace osu.Game.Screens.OnlinePlay
private IBindable subScreenSelectedItem { get; set; }
///
- /// The currently selected item in the , or the last item from
+ /// The currently selected item in the , or the current item from
/// if this is not within a .
///
protected readonly Bindable SelectedItem = new Bindable();
@@ -88,7 +87,7 @@ namespace osu.Game.Screens.OnlinePlay
protected virtual void UpdateSelectedItem()
=> SelectedItem.Value = RoomID.Value == null || subScreenSelectedItem == null
- ? Playlist.LastOrDefault()
+ ? Playlist.GetCurrentItem()
: subScreenSelectedItem.Value;
}
}
From 0975f570ba2bdf82dd4aee1bd36412b94cb0b31e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bart=C5=82omiej=20Dach?=
Date: Mon, 20 Dec 2021 13:42:49 +0100
Subject: [PATCH 34/61] Return last playlist item if all expired
---
.../OnlinePlay/PlaylistExtensionsTest.cs | 29 ++++++++++++++-----
osu.Game/Online/Rooms/PlaylistExtensions.cs | 14 +++++++--
2 files changed, 32 insertions(+), 11 deletions(-)
diff --git a/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs b/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs
index 001513be1f..5913cb0f29 100644
--- a/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs
+++ b/osu.Game.Tests/OnlinePlay/PlaylistExtensionsTest.cs
@@ -1,6 +1,7 @@
// 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 NUnit.Framework;
using osu.Game.Online.Rooms;
@@ -9,6 +10,17 @@ namespace osu.Game.Tests.OnlinePlay
[TestFixture]
public class PlaylistExtensionsTest
{
+ [Test]
+ public void TestEmpty()
+ {
+ // mostly an extreme edge case, i.e. during room creation.
+ var items = Array.Empty();
+
+ var currentItem = items.GetCurrentItem();
+
+ Assert.That(currentItem, Is.Null);
+ }
+
[Test]
public void TestPlaylistItemsInOrder()
{
@@ -19,9 +31,9 @@ namespace osu.Game.Tests.OnlinePlay
new PlaylistItem { ID = 3, BeatmapID = 1003, PlaylistOrder = 3 },
};
- var nextItem = items.GetCurrentItem();
+ var currentItem = items.GetCurrentItem();
- Assert.That(nextItem, Is.EqualTo(items[0]));
+ Assert.That(currentItem, Is.EqualTo(items[0]));
}
[Test]
@@ -34,9 +46,9 @@ namespace osu.Game.Tests.OnlinePlay
new PlaylistItem { ID = 3, BeatmapID = 1003, PlaylistOrder = 3 },
};
- var nextItem = items.GetCurrentItem();
+ var currentItem = items.GetCurrentItem();
- Assert.That(nextItem, Is.EqualTo(items[1]));
+ Assert.That(currentItem, Is.EqualTo(items[1]));
}
[Test]
@@ -49,9 +61,9 @@ namespace osu.Game.Tests.OnlinePlay
new PlaylistItem { ID = 3, BeatmapID = 1003, PlaylistOrder = 3 },
};
- var nextItem = items.GetCurrentItem();
+ var currentItem = items.GetCurrentItem();
- Assert.That(nextItem, Is.EqualTo(items[2]));
+ Assert.That(currentItem, Is.EqualTo(items[2]));
}
[Test]
@@ -64,9 +76,10 @@ namespace osu.Game.Tests.OnlinePlay
new PlaylistItem { ID = 3, BeatmapID = 1003, PlaylistOrder = 3, Expired = true },
};
- var nextItem = items.GetCurrentItem();
+ var currentItem = items.GetCurrentItem();
- Assert.That(nextItem, Is.Null);
+ // if all items are expired, the last-played item is expected to be returned.
+ Assert.That(currentItem, Is.EqualTo(items[2]));
}
}
}
diff --git a/osu.Game/Online/Rooms/PlaylistExtensions.cs b/osu.Game/Online/Rooms/PlaylistExtensions.cs
index 46cb218910..355ae6188d 100644
--- a/osu.Game/Online/Rooms/PlaylistExtensions.cs
+++ b/osu.Game/Online/Rooms/PlaylistExtensions.cs
@@ -15,10 +15,18 @@ namespace osu.Game.Online.Rooms
{
///
/// Returns the first non-expired in playlist order from the supplied ,
- /// or if all items are expired.
+ /// or the last-played if all items are expired,
+ /// or if was empty.
///
- public static PlaylistItem? GetCurrentItem(this IEnumerable playlist) =>
- playlist.OrderBy(item => item.PlaylistOrder).FirstOrDefault(item => !item.Expired);
+ public static PlaylistItem? GetCurrentItem(this ICollection playlist)
+ {
+ if (playlist.Count == 0)
+ return null;
+
+ return playlist.All(item => item.Expired)
+ ? playlist.OrderByDescending(item => item.PlaylistOrder).First()
+ : playlist.OrderBy(item => item.PlaylistOrder).First(item => !item.Expired);
+ }
public static string GetTotalDuration(this BindableList playlist) =>
playlist.Select(p => p.Beatmap.Value.Length).Sum().Milliseconds().Humanize(minUnit: TimeUnit.Second, maxUnit: TimeUnit.Hour, precision: 2);
From 9344897542ff6b6463d8377d61f63b3ec0c8b5b3 Mon Sep 17 00:00:00 2001
From: dekrain
Date: Mon, 20 Dec 2021 16:51:51 +0100
Subject: [PATCH 35/61] Split session statics reset method to prevent unloading
seasonal backgrounds while idle
---
osu.Game/Configuration/SessionStatics.cs | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/osu.Game/Configuration/SessionStatics.cs b/osu.Game/Configuration/SessionStatics.cs
index ac94c39bd2..99f1e5a8b2 100644
--- a/osu.Game/Configuration/SessionStatics.cs
+++ b/osu.Game/Configuration/SessionStatics.cs
@@ -13,9 +13,7 @@ namespace osu.Game.Configuration
///
public class SessionStatics : InMemoryConfigManager
{
- protected override void InitialiseDefaults() => ResetValues();
-
- public void ResetValues()
+ protected override void InitialiseDefaults()
{
ensureDefault(SetDefault(Static.LoginOverlayDisplayed, false));
ensureDefault(SetDefault(Static.MutedAudioNotificationShownOnce, false));
@@ -24,6 +22,18 @@ namespace osu.Game.Configuration
ensureDefault(SetDefault(Static.SeasonalBackgrounds, null));
}
+ ///
+ /// Used to revert statics to their defaults after being idle for appropiate amount of time.
+ /// Does not affect loaded seasonal backgrounds.
+ ///
+ public void ResetValues()
+ {
+ ensureDefault(GetBindable(Static.LoginOverlayDisplayed));
+ ensureDefault(GetBindable(Static.MutedAudioNotificationShownOnce));
+ ensureDefault(GetBindable(Static.LowBatteryNotificationShownOnce));
+ ensureDefault(GetBindable(Static.LastHoverSoundPlaybackTime));
+ }
+
private void ensureDefault(Bindable bindable) => bindable.SetDefault();
}
From e21dbf10ff7734be7b0493d488f311e1a1657f1b Mon Sep 17 00:00:00 2001
From: Dan Balasescu
Date: Tue, 21 Dec 2021 12:25:32 +0900
Subject: [PATCH 36/61] Refactor further to remove indexing confusion
---
.../Difficulty/Skills/Flashlight.cs | 23 ++++++++++---------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs
index 21a2fc2252..ad7464244e 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs
@@ -40,32 +40,33 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
double result = 0.0;
+ OsuDifficultyHitObject lastObj = null;
+
+ // This is iterating backwards in time from the current object.
for (int i = 0; i < Previous.Count; i++)
{
- var osuLoop = (OsuDifficultyHitObject)Previous[i];
- var osuLoopHitObject = (OsuHitObject)(osuLoop.BaseObject);
+ var currentObj = (OsuDifficultyHitObject)Previous[i];
+ var currentHitObject = (OsuHitObject)(currentObj.BaseObject);
- OsuDifficultyHitObject osuLoopNext;
- if (i == 0)
- osuLoopNext = osuCurrent;
- else
- osuLoopNext = (OsuDifficultyHitObject)Previous[i - 1];
+ lastObj ??= currentObj;
- if (!(osuLoop.BaseObject is Spinner))
+ if (!(currentObj.BaseObject is Spinner))
{
- double jumpDistance = (osuHitObject.StackedPosition - osuLoopHitObject.EndPosition).Length;
+ double jumpDistance = (osuHitObject.StackedPosition - currentHitObject.EndPosition).Length;
- cumulativeStrainTime += osuLoopNext.StrainTime;
+ cumulativeStrainTime += lastObj.StrainTime;
// We want to nerf objects that can be easily seen within the Flashlight circle radius.
if (i == 0)
smallDistNerf = Math.Min(1.0, jumpDistance / 75.0);
// We also want to nerf stacks so that only the first object of the stack is accounted for.
- double stackNerf = Math.Min(1.0, (osuLoop.LazyJumpDistance / scalingFactor) / 25.0);
+ double stackNerf = Math.Min(1.0, (currentObj.LazyJumpDistance / scalingFactor) / 25.0);
result += Math.Pow(0.8, i) * stackNerf * scalingFactor * jumpDistance / cumulativeStrainTime;
}
+
+ lastObj = currentObj;
}
return Math.Pow(smallDistNerf * result, 2.0);
From 28d6ff5d9c8bac9390e7576829623798934fc61a Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Tue, 21 Dec 2021 12:36:01 +0900
Subject: [PATCH 37/61] Fix potential wrong thread mutation in
`ColourHitErrorMeter`
---
.../Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs
index 5012be7249..00e6059541 100644
--- a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs
+++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs
@@ -53,13 +53,13 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
LayoutEasing = Easing.OutQuint;
}
- public void Push(Color4 colour)
+ public void Push(Color4 colour) => Schedule(() =>
{
Add(new HitErrorCircle(colour, drawable_judgement_size));
if (Children.Count > max_available_judgements)
Children.FirstOrDefault(c => !c.IsRemoved)?.Remove();
- }
+ });
}
internal class HitErrorCircle : Container
From c21b2d166223d2305a0f3d7ce8d9fc77c3bc4a66 Mon Sep 17 00:00:00 2001
From: Dan Balasescu
Date: Tue, 21 Dec 2021 12:39:07 +0900
Subject: [PATCH 38/61] Fix incorrect variable
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs
index ad7464244e..bdf7032521 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs
@@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
var currentObj = (OsuDifficultyHitObject)Previous[i];
var currentHitObject = (OsuHitObject)(currentObj.BaseObject);
- lastObj ??= currentObj;
+ lastObj ??= osuCurrent;
if (!(currentObj.BaseObject is Spinner))
{
From f366cdc73eabbaff9224e3c7010e3f641a079158 Mon Sep 17 00:00:00 2001
From: Dan Balasescu
Date: Tue, 21 Dec 2021 12:39:34 +0900
Subject: [PATCH 39/61] Extract initial set out of loop
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs
index bdf7032521..ff0780be85 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Flashlight.cs
@@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
double result = 0.0;
- OsuDifficultyHitObject lastObj = null;
+ OsuDifficultyHitObject lastObj = osuCurrent;
// This is iterating backwards in time from the current object.
for (int i = 0; i < Previous.Count; i++)
@@ -48,8 +48,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
var currentObj = (OsuDifficultyHitObject)Previous[i];
var currentHitObject = (OsuHitObject)(currentObj.BaseObject);
- lastObj ??= osuCurrent;
-
if (!(currentObj.BaseObject is Spinner))
{
double jumpDistance = (osuHitObject.StackedPosition - currentHitObject.EndPosition).Length;
From 52db7b36fc44a66d64a5b68d5a266ece48a2cebc Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Tue, 21 Dec 2021 12:55:21 +0900
Subject: [PATCH 40/61] Move `Schedule` call to base implementation of error
meter for extra safety
---
.../Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs | 4 ++--
osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs | 7 ++++++-
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs
index 00e6059541..5012be7249 100644
--- a/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs
+++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/ColourHitErrorMeter.cs
@@ -53,13 +53,13 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
LayoutEasing = Easing.OutQuint;
}
- public void Push(Color4 colour) => Schedule(() =>
+ public void Push(Color4 colour)
{
Add(new HitErrorCircle(colour, drawable_judgement_size));
if (Children.Count > max_available_judgements)
Children.FirstOrDefault(c => !c.IsRemoved)?.Remove();
- });
+ }
}
internal class HitErrorCircle : Container
diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs
index c7b06a3a2c..16c23f07f5 100644
--- a/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs
+++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs
@@ -40,9 +40,14 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
if (gameplayClockContainer != null)
gameplayClockContainer.OnSeek += Clear;
- processor.NewJudgement += OnNewJudgement;
+ // Scheduled as meter implementations are likely going to change/add drawables when reacting to this.
+ processor.NewJudgement += j => Schedule(() => OnNewJudgement(j));
}
+ ///
+ /// Fired when a new judgement arrives.
+ ///
+ /// The new judgement.
protected abstract void OnNewJudgement(JudgementResult judgement);
protected Color4 GetColourForHitResult(HitResult result)
From edcbd4de6d27cd9788523064207e4111d2d99f80 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Tue, 21 Dec 2021 13:05:26 +0900
Subject: [PATCH 41/61] Fix incorrect event unbind logic
---
osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs
index 16c23f07f5..1f08cb8aa7 100644
--- a/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs
+++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/HitErrorMeter.cs
@@ -40,10 +40,12 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
if (gameplayClockContainer != null)
gameplayClockContainer.OnSeek += Clear;
- // Scheduled as meter implementations are likely going to change/add drawables when reacting to this.
- processor.NewJudgement += j => Schedule(() => OnNewJudgement(j));
+ processor.NewJudgement += processorNewJudgement;
}
+ // Scheduled as meter implementations are likely going to change/add drawables when reacting to this.
+ private void processorNewJudgement(JudgementResult j) => Schedule(() => OnNewJudgement(j));
+
///
/// Fired when a new judgement arrives.
///
@@ -89,7 +91,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
base.Dispose(isDisposing);
if (processor != null)
- processor.NewJudgement -= OnNewJudgement;
+ processor.NewJudgement -= processorNewJudgement;
if (gameplayClockContainer != null)
gameplayClockContainer.OnSeek -= Clear;
From 9aff646ff49ac0194b194621b9c90e1af9ab2cc9 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Tue, 21 Dec 2021 13:20:12 +0900
Subject: [PATCH 42/61] Centralise all multiplayer button clicking test logic
This adds the "wait for enabled" check in a way that can be easily
reused, as it keeps getting missed in test implementations.
This particular commit hopefully fixes
https://github.com/ppy/osu/runs/4583845033?check_suite_focus=true.
---
.../Visual/Multiplayer/QueueModeTestScene.cs | 23 ++-----------
.../Multiplayer/TestSceneMultiplayer.cs | 18 ++--------
.../TestSceneMultiplayerMatchSubScreen.cs | 33 ++++---------------
.../TestSceneMultiplayerReadyButton.cs | 28 +++++-----------
.../TestSceneMultiplayerSpectateButton.cs | 17 +++-------
.../Visual/OsuManualInputManagerTestScene.cs | 23 +++++++++++++
6 files changed, 48 insertions(+), 94 deletions(-)
diff --git a/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs b/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs
index 5acb44ac45..88c54eb2bb 100644
--- a/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs
+++ b/osu.Game.Tests/Visual/Multiplayer/QueueModeTestScene.cs
@@ -5,7 +5,6 @@ using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Audio;
-using osu.Framework.Graphics.UserInterface;
using osu.Framework.Platform;
using osu.Framework.Screens;
using osu.Framework.Testing;
@@ -20,7 +19,6 @@ using osu.Game.Screens.OnlinePlay.Multiplayer;
using osu.Game.Screens.OnlinePlay.Multiplayer.Match;
using osu.Game.Screens.Play;
using osu.Game.Tests.Resources;
-using osuTK.Input;
namespace osu.Game.Tests.Visual.Multiplayer
{
@@ -86,11 +84,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
AddUntilStep("wait for room open", () => this.ChildrenOfType().FirstOrDefault()?.IsLoaded == true);
AddWaitStep("wait for transition", 2);
- AddStep("create room", () =>
- {
- InputManager.MoveMouseTo(this.ChildrenOfType().Single());
- InputManager.Click(MouseButton.Left);
- });
+ ClickButtonWhenEnabled();
AddUntilStep("wait for join", () => Client.RoomJoined);
}
@@ -104,24 +98,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
protected void RunGameplay()
{
AddUntilStep("wait for idle", () => Client.LocalUser?.State == MultiplayerUserState.Idle);
- clickReadyButton();
+ ClickButtonWhenEnabled();
AddUntilStep("wait for ready", () => Client.LocalUser?.State == MultiplayerUserState.Ready);
- clickReadyButton();
+ ClickButtonWhenEnabled();
AddUntilStep("wait for player", () => multiplayerComponents.CurrentScreen is Player player && player.IsLoaded);
AddStep("exit player", () => multiplayerComponents.MultiplayerScreen.MakeCurrent());
}
-
- private void clickReadyButton()
- {
- AddUntilStep("wait for ready button to be enabled", () => this.ChildrenOfType().Single().ChildrenOfType