From d82564aab66aee6d9c97138d1805f9a1a878396b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 17 Oct 2021 17:00:54 +0200 Subject: [PATCH 01/30] Add test scene for beatmap cards --- .../Visual/Beatmaps/TestSceneBeatmapCard.cs | 162 ++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs new file mode 100644 index 0000000000..d267ad929d --- /dev/null +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs @@ -0,0 +1,162 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Beatmaps; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays; +using osu.Game.Users; +using osuTK; + +namespace osu.Game.Tests.Visual.Beatmaps +{ + public class TestSceneBeatmapCard : OsuTestScene + { + private IBeatmapSetInfo[] testCases; + + #region Test case generation + + [BackgroundDependencyLoader] + private void load() + { + var normal = CreateAPIBeatmapSet(Ruleset.Value); + normal.HasVideo = true; + normal.HasStoryboard = true; + + var undownloadable = getUndownloadableBeatmapSet(); + var manyDifficulties = getManyDifficultiesBeatmapSet(); + + var explicitMap = CreateAPIBeatmapSet(Ruleset.Value); + explicitMap.HasExplicitContent = true; + + var featuredMap = CreateAPIBeatmapSet(Ruleset.Value); + featuredMap.TrackId = 1; + + var explicitFeaturedMap = CreateAPIBeatmapSet(Ruleset.Value); + explicitFeaturedMap.HasExplicitContent = true; + explicitFeaturedMap.TrackId = 2; + + testCases = new IBeatmapSetInfo[] + { + normal, + undownloadable, + manyDifficulties, + explicitMap, + featuredMap, + explicitFeaturedMap + }; + } + + private APIBeatmapSet getUndownloadableBeatmapSet() => new APIBeatmapSet + { + OnlineID = 123, + Title = "undownloadable beatmap", + Artist = "test", + Source = "more tests", + Author = new User + { + Username = "BanchoBot", + Id = 3, + }, + Availability = new BeatmapSetOnlineAvailability + { + DownloadDisabled = true, + }, + Preview = @"https://b.ppy.sh/preview/12345.mp3", + PlayCount = 123, + FavouriteCount = 456, + BPM = 111, + HasVideo = true, + HasStoryboard = true, + Covers = new BeatmapSetOnlineCovers(), + Beatmaps = new List + { + new APIBeatmap + { + RulesetID = Ruleset.Value.OnlineID, + DifficultyName = "Test", + StarRating = 6.42, + } + } + }; + + private static APIBeatmapSet getManyDifficultiesBeatmapSet() + { + var beatmaps = new List(); + + for (int i = 0; i < 100; i++) + { + beatmaps.Add(new APIBeatmap + { + RulesetID = i % 4, + StarRating = 2 + i % 4 * 2, + }); + } + + return new APIBeatmapSet + { + OnlineID = 1, + Title = "many difficulties beatmap", + Artist = "test", + Author = new User + { + Username = "BanchoBot", + Id = 3, + }, + HasVideo = true, + HasStoryboard = true, + Covers = new BeatmapSetOnlineCovers(), + Beatmaps = beatmaps, + }; + } + + #endregion + + private Drawable createContent(OverlayColourScheme colourScheme, Func creationFunc) + { + var colourProvider = new OverlayColourProvider(colourScheme); + + return new DependencyProvidingContainer + { + RelativeSizeAxes = Axes.Both, + CachedDependencies = new (Type, object)[] + { + (typeof(OverlayColourProvider), colourProvider) + }, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colourProvider.Background5 + }, + new BasicScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Full, + Padding = new MarginPadding(10), + Spacing = new Vector2(10), + ChildrenEnumerable = testCases.Select(creationFunc) + } + } + } + }; + } + + private void createTestCase(Func creationFunc) + { + foreach (var scheme in Enum.GetValues(typeof(OverlayColourScheme)).Cast()) + AddStep($"set {scheme} scheme", () => Child = createContent(scheme, creationFunc)); + } + } +} From 5962f16b1ca71d99f264a8755f4484bc117fd14d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 17 Oct 2021 18:24:17 +0200 Subject: [PATCH 02/30] Implement basic card appearance --- .../Visual/Beatmaps/TestSceneBeatmapCard.cs | 35 ++- .../Beatmaps/Drawables/Cards/BeatmapCard.cs | 248 ++++++++++++++++++ 2 files changed, 275 insertions(+), 8 deletions(-) create mode 100644 osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs diff --git a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs index d267ad929d..d1b21547dc 100644 --- a/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs +++ b/osu.Game.Tests/Visual/Beatmaps/TestSceneBeatmapCard.cs @@ -4,11 +4,13 @@ using System; using System.Collections.Generic; using System.Linq; +using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables.Cards; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays; using osu.Game.Users; @@ -18,7 +20,7 @@ namespace osu.Game.Tests.Visual.Beatmaps { public class TestSceneBeatmapCard : OsuTestScene { - private IBeatmapSetInfo[] testCases; + private APIBeatmapSet[] testCases; #region Test case generation @@ -30,7 +32,13 @@ namespace osu.Game.Tests.Visual.Beatmaps normal.HasStoryboard = true; var undownloadable = getUndownloadableBeatmapSet(); - var manyDifficulties = getManyDifficultiesBeatmapSet(); + + var someDifficulties = getManyDifficultiesBeatmapSet(11); + someDifficulties.Title = someDifficulties.TitleUnicode = "some difficulties"; + someDifficulties.Status = BeatmapSetOnlineStatus.Qualified; + + var manyDifficulties = getManyDifficultiesBeatmapSet(100); + manyDifficulties.Status = BeatmapSetOnlineStatus.Pending; var explicitMap = CreateAPIBeatmapSet(Ruleset.Value); explicitMap.HasExplicitContent = true; @@ -42,14 +50,22 @@ namespace osu.Game.Tests.Visual.Beatmaps explicitFeaturedMap.HasExplicitContent = true; explicitFeaturedMap.TrackId = 2; - testCases = new IBeatmapSetInfo[] + var longName = CreateAPIBeatmapSet(Ruleset.Value); + longName.Title = longName.TitleUnicode = "this track has an incredibly and implausibly long title"; + longName.Artist = longName.ArtistUnicode = "and this artist! who would have thunk it. it's really such a long name."; + longName.HasExplicitContent = true; + longName.TrackId = 444; + + testCases = new[] { normal, undownloadable, + someDifficulties, manyDifficulties, explicitMap, featuredMap, - explicitFeaturedMap + explicitFeaturedMap, + longName }; } @@ -86,11 +102,11 @@ namespace osu.Game.Tests.Visual.Beatmaps } }; - private static APIBeatmapSet getManyDifficultiesBeatmapSet() + private static APIBeatmapSet getManyDifficultiesBeatmapSet(int count) { var beatmaps = new List(); - for (int i = 0; i < 100; i++) + for (int i = 0; i < count; i++) { beatmaps.Add(new APIBeatmap { @@ -118,7 +134,7 @@ namespace osu.Game.Tests.Visual.Beatmaps #endregion - private Drawable createContent(OverlayColourScheme colourScheme, Func creationFunc) + private Drawable createContent(OverlayColourScheme colourScheme, Func creationFunc) { var colourProvider = new OverlayColourProvider(colourScheme); @@ -153,10 +169,13 @@ namespace osu.Game.Tests.Visual.Beatmaps }; } - private void createTestCase(Func creationFunc) + private void createTestCase(Func creationFunc) { foreach (var scheme in Enum.GetValues(typeof(OverlayColourScheme)).Cast()) AddStep($"set {scheme} scheme", () => Child = createContent(scheme, creationFunc)); } + + [Test] + public void TestNormal() => createTestCase(beatmapSetInfo => new BeatmapCard(beatmapSetInfo)); } } diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs new file mode 100644 index 0000000000..38098899b0 --- /dev/null +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs @@ -0,0 +1,248 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; +using osu.Game.Graphics; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays; +using osu.Game.Overlays.BeatmapSet; +using osuTK; +using osu.Game.Overlays.BeatmapListing.Panels; +using osu.Game.Resources.Localisation.Web; + +namespace osu.Game.Beatmaps.Drawables.Cards +{ + public class BeatmapCard : OsuClickableContainer + { + private const float width = 408; + private const float height = 100; + private const float corner_radius = 10; + + private readonly APIBeatmapSet beatmapSet; + private FillFlowContainer iconArea; + private GridContainer titleContainer; + private GridContainer artistContainer; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } + + public BeatmapCard(APIBeatmapSet beatmapSet) + : base(HoverSampleSet.Submit) + { + this.beatmapSet = beatmapSet; + } + + [BackgroundDependencyLoader] + private void load() + { + Width = width; + Height = height; + CornerRadius = corner_radius; + Masking = true; + + InternalChildren = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colourProvider.Background3 + }, + new Container + { + Name = @"Left (icon) area", + Size = new Vector2(height), + Children = new Drawable[] + { + new UpdateableOnlineBeatmapSetCover(BeatmapSetCoverType.List) + { + RelativeSizeAxes = Axes.Both, + OnlineInfo = beatmapSet + }, + iconArea = new FillFlowContainer + { + Margin = new MarginPadding(5), + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(1) + } + } + }, + new Container + { + Name = @"Main content", + X = height - corner_radius, + Width = width - height, + Height = height, + CornerRadius = corner_radius, + Masking = true, + Children = new Drawable[] + { + new UpdateableOnlineBeatmapSetCover + { + RelativeSizeAxes = Axes.Both, + OnlineInfo = beatmapSet, + }, + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientHorizontal(colourProvider.Background2, colourProvider.Background2.Opacity(0.8f)), + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding + { + Horizontal = 10, + Vertical = 4 + }, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + titleContainer = new GridContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.AutoSize) + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize) + }, + Content = new[] + { + new[] + { + new OsuSpriteText + { + Text = new RomanisableString(beatmapSet.TitleUnicode, beatmapSet.Title), + Font = OsuFont.Default.With(size: 22.5f, weight: FontWeight.SemiBold), + RelativeSizeAxes = Axes.X, + Truncate = true + }, + Empty() + } + } + }, + artistContainer = new GridContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.AutoSize) + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize) + }, + Content = new[] + { + new[] + { + new OsuSpriteText + { + Text = createArtistText(), + Font = OsuFont.Default.With(size: 17.5f, weight: FontWeight.SemiBold), + RelativeSizeAxes = Axes.X, + Truncate = true + }, + Empty() + }, + } + }, + new LinkFlowContainer(s => + { + s.Shadow = false; + s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold); + }).With(d => + { + d.AutoSizeAxes = Axes.Both; + d.Margin = new MarginPadding { Top = 2 }; + d.AddText("mapped by ", t => t.Colour = colourProvider.Content2); + d.AddUserLink(beatmapSet.Author); + }), + } + }, + new FillFlowContainer + { + Name = @"Bottom content", + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Horizontal, + Padding = new MarginPadding + { + Horizontal = 10, + Vertical = 4 + }, + Spacing = new Vector2(4, 0), + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Children = new Drawable[] + { + new BeatmapSetOnlineStatusPill + { + AutoSizeAxes = Axes.Both, + Status = beatmapSet.Status, + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft + }, + new DifficultySpectrumDisplay(beatmapSet) + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + DotSize = new Vector2(6, 12) + } + } + } + } + } + }; + + if (beatmapSet.HasVideo) + iconArea.Add(new IconPill(FontAwesome.Solid.Film)); + + if (beatmapSet.HasStoryboard) + iconArea.Add(new IconPill(FontAwesome.Solid.Image)); + + if (beatmapSet.HasExplicitContent) + { + titleContainer.Content[0][1] = new ExplicitContentBeatmapPill + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Margin = new MarginPadding { Left = 5 } + }; + } + + if (beatmapSet.TrackId != null) + { + artistContainer.Content[0][1] = new FeaturedArtistBeatmapPill + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + Margin = new MarginPadding { Left = 5 } + }; + } + } + + private LocalisableString createArtistText() + { + var romanisableArtist = new RomanisableString(beatmapSet.ArtistUnicode, beatmapSet.Artist); + return BeatmapsetsStrings.ShowDetailsByArtist(romanisableArtist); + } + } +} From a59f2d7b835804cb0d66aeacd0a9e8a5031bdcf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 17 Oct 2021 18:59:31 +0200 Subject: [PATCH 03/30] Implement basic hover card state --- .../Beatmaps/Drawables/Cards/BeatmapCard.cs | 52 +++++++++++++++++-- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs index 38098899b0..516ffa5628 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -19,6 +20,7 @@ using osu.Game.Overlays.BeatmapSet; using osuTK; using osu.Game.Overlays.BeatmapListing.Panels; using osu.Game.Resources.Localisation.Web; +using osuTK.Graphics; namespace osu.Game.Beatmaps.Drawables.Cards { @@ -28,8 +30,16 @@ namespace osu.Game.Beatmaps.Drawables.Cards private const float height = 100; private const float corner_radius = 10; + private const float transition_duration = 400; + private readonly APIBeatmapSet beatmapSet; + + private UpdateableOnlineBeatmapSetCover leftCover; private FillFlowContainer iconArea; + + private Container mainContent; + private Box foregroundGradient; + private GridContainer titleContainer; private GridContainer artistContainer; @@ -63,7 +73,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards Size = new Vector2(height), Children = new Drawable[] { - new UpdateableOnlineBeatmapSetCover(BeatmapSetCoverType.List) + leftCover = new UpdateableOnlineBeatmapSetCover(BeatmapSetCoverType.List) { RelativeSizeAxes = Axes.Both, OnlineInfo = beatmapSet @@ -77,11 +87,10 @@ namespace osu.Game.Beatmaps.Drawables.Cards } } }, - new Container + mainContent = new Container { Name = @"Main content", X = height - corner_radius, - Width = width - height, Height = height, CornerRadius = corner_radius, Masking = true, @@ -92,10 +101,9 @@ namespace osu.Game.Beatmaps.Drawables.Cards RelativeSizeAxes = Axes.Both, OnlineInfo = beatmapSet, }, - new Box + foregroundGradient = new Box { RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientHorizontal(colourProvider.Background2, colourProvider.Background2.Opacity(0.8f)), }, new FillFlowContainer { @@ -239,10 +247,44 @@ namespace osu.Game.Beatmaps.Drawables.Cards } } + protected override void LoadComplete() + { + base.LoadComplete(); + updateState(); + FinishTransforms(true); + } + private LocalisableString createArtistText() { var romanisableArtist = new RomanisableString(beatmapSet.ArtistUnicode, beatmapSet.Artist); return BeatmapsetsStrings.ShowDetailsByArtist(romanisableArtist); } + + protected override bool OnHover(HoverEvent e) + { + updateState(); + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + updateState(); + base.OnHoverLost(e); + } + + private void updateState() + { + float targetWidth = width - height; + if (IsHovered) + targetWidth -= 20; + + mainContent.ResizeWidthTo(targetWidth, transition_duration, Easing.OutQuint); + + var foregroundColour = IsHovered ? colourProvider.Background4 : colourProvider.Background2; + var foregroundGradientColour = ColourInfo.GradientHorizontal(foregroundColour, foregroundColour.Opacity(0.8f)); + foregroundGradient.FadeColour(foregroundGradientColour, transition_duration, Easing.OutQuint); + + leftCover.FadeColour(IsHovered ? OsuColour.Gray(0.2f) : Color4.White, transition_duration, Easing.OutQuint); + } } } From f671ee28c542b7fbddc558dcf69590b79a85bc09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Fri, 22 Oct 2021 22:03:37 +0200 Subject: [PATCH 04/30] Use buffered container to eliminate gaps near foreground border --- .../Beatmaps/Drawables/Cards/BeatmapCard.cs | 25 ++-- .../Cards/BeatmapCardContentBackground.cs | 125 ++++++++++++++++++ 2 files changed, 133 insertions(+), 17 deletions(-) create mode 100644 osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs index 516ffa5628..b1fe381410 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs @@ -2,9 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; @@ -26,19 +24,19 @@ namespace osu.Game.Beatmaps.Drawables.Cards { public class BeatmapCard : OsuClickableContainer { + public const float TRANSITION_DURATION = 400; + private const float width = 408; private const float height = 100; private const float corner_radius = 10; - private const float transition_duration = 400; - private readonly APIBeatmapSet beatmapSet; private UpdateableOnlineBeatmapSetCover leftCover; private FillFlowContainer iconArea; private Container mainContent; - private Box foregroundGradient; + private BeatmapCardContentBackground mainContentBackground; private GridContainer titleContainer; private GridContainer artistContainer; @@ -96,14 +94,10 @@ namespace osu.Game.Beatmaps.Drawables.Cards Masking = true, Children = new Drawable[] { - new UpdateableOnlineBeatmapSetCover - { - RelativeSizeAxes = Axes.Both, - OnlineInfo = beatmapSet, - }, - foregroundGradient = new Box + mainContentBackground = new BeatmapCardContentBackground { RelativeSizeAxes = Axes.Both, + BeatmapSet = beatmapSet, }, new FillFlowContainer { @@ -278,13 +272,10 @@ namespace osu.Game.Beatmaps.Drawables.Cards if (IsHovered) targetWidth -= 20; - mainContent.ResizeWidthTo(targetWidth, transition_duration, Easing.OutQuint); + mainContent.ResizeWidthTo(targetWidth, TRANSITION_DURATION, Easing.OutQuint); + mainContentBackground.Dimmed.Value = IsHovered; - var foregroundColour = IsHovered ? colourProvider.Background4 : colourProvider.Background2; - var foregroundGradientColour = ColourInfo.GradientHorizontal(foregroundColour, foregroundColour.Opacity(0.8f)); - foregroundGradient.FadeColour(foregroundGradientColour, transition_duration, Easing.OutQuint); - - leftCover.FadeColour(IsHovered ? OsuColour.Gray(0.2f) : Color4.White, transition_duration, Easing.OutQuint); + leftCover.FadeColour(IsHovered ? OsuColour.Gray(0.2f) : Color4.White, TRANSITION_DURATION, Easing.OutQuint); } } } diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs new file mode 100644 index 0000000000..88c9d771ac --- /dev/null +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs @@ -0,0 +1,125 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable enable + +using System; +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Colour; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Overlays; + +namespace osu.Game.Beatmaps.Drawables.Cards +{ + public class BeatmapCardContentBackground : ModelBackedDrawable + { + public IBeatmapSetOnlineInfo BeatmapSet + { + get => Model; + set => Model = value; + } + + public new bool Masking + { + get => base.Masking; + set => base.Masking = value; + } + + public BindableBool Dimmed { get; private set; } = new BindableBool(); + + protected override double LoadDelay => 500; + + protected override double TransformDuration => 400; + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + InternalChild = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = colourProvider.Background2 + }; + } + + protected override DelayedLoadWrapper CreateDelayedLoadWrapper(Func createContentFunc, double timeBeforeLoad) + => new DelayedLoadUnloadWrapper(createContentFunc, timeBeforeLoad); + + protected override Drawable? CreateDrawable(IBeatmapSetOnlineInfo? model) + { + if (model == null) + return null; + + return new BufferedBackground(model) + { + RelativeSizeAxes = Axes.Both, + Dimmed = { BindTarget = Dimmed } + }; + } + + private class BufferedBackground : BufferedContainer + { + public BindableBool Dimmed { get; } = new BindableBool(); + + private readonly IBeatmapSetOnlineInfo onlineInfo; + + private readonly Box background; + private OnlineBeatmapSetCover? cover; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + + public BufferedBackground(IBeatmapSetOnlineInfo onlineInfo) + { + this.onlineInfo = onlineInfo; + + RelativeSizeAxes = Axes.Both; + InternalChild = background = new Box + { + RelativeSizeAxes = Axes.Both, + }; + } + + [BackgroundDependencyLoader] + private void load() + { + background.Colour = colourProvider.Background2; + + LoadComponentAsync(new OnlineBeatmapSetCover(onlineInfo) + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + FillMode = FillMode.Fill + }, loaded => + { + cover = loaded; + cover.Colour = Colour4.Transparent; + AddInternal(cover); + FinishTransforms(true); + updateState(); + }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Dimmed.BindValueChanged(_ => updateState(), true); + FinishTransforms(true); + } + + private void updateState() + { + if (cover == null) + return; + + background.FadeColour(Dimmed.Value ? colourProvider.Background4 : colourProvider.Background2, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + + var gradient = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0), Colour4.White.Opacity(0.2f)); + cover.FadeColour(gradient, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + } + } + } +} From eaeee80a262abb31d9ef3664dec0b42ad2712ed0 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 2 Nov 2021 16:53:50 +0900 Subject: [PATCH 05/30] Fix PP counter showing incorrect values with rate adjustment mods --- osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs index ef289c2a20..09ca326cce 100644 --- a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs +++ b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs @@ -48,6 +48,9 @@ namespace osu.Game.Screens.Play.HUD [CanBeNull] private GameplayState gameplayState { get; set; } + [Resolved(CanBeNull = true)] + private GameplayClock gameplayClock { get; set; } + [CanBeNull] private List timedAttributes; @@ -133,10 +136,12 @@ namespace osu.Game.Screens.Play.HUD [CanBeNull] private DifficultyAttributes getAttributeAtTime(JudgementResult judgement) { - if (timedAttributes == null || timedAttributes.Count == 0) + if (timedAttributes == null || timedAttributes.Count == 0 || gameplayClock == null) return null; - int attribIndex = timedAttributes.BinarySearch(new TimedDifficultyAttributes(judgement.HitObject.GetEndTime(), null)); + double judgementTime = judgement.HitObject.GetEndTime() / gameplayClock.TrueGameplayRate; + + int attribIndex = timedAttributes.BinarySearch(new TimedDifficultyAttributes(judgementTime, null)); if (attribIndex < 0) attribIndex = ~attribIndex - 1; From 0cdd2898feb831da98511e7f1189dcd6d3309a5b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 2 Nov 2021 17:17:14 +0900 Subject: [PATCH 06/30] Expose non-adjusted time from CalculateTimed() --- osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs | 2 +- .../Rulesets/Difficulty/TimedDifficultyAttributes.cs | 7 +++++++ osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs | 9 ++------- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index eab81186d5..d410fb6edf 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Difficulty foreach (var skill in skills) skill.ProcessInternal(hitObject); - attribs.Add(new TimedDifficultyAttributes(hitObject.EndTime, CreateDifficultyAttributes(progressiveBeatmap, playableMods, skills, clockRate))); + attribs.Add(new TimedDifficultyAttributes(hitObject.EndTime * clockRate, CreateDifficultyAttributes(progressiveBeatmap, playableMods, skills, clockRate))); } return attribs; diff --git a/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs b/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs index 973b2dacb2..28319ec6d7 100644 --- a/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs +++ b/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs @@ -11,7 +11,14 @@ namespace osu.Game.Rulesets.Difficulty /// public class TimedDifficultyAttributes : IComparable { + /// + /// The non-clock adjusted time value at which the attributes take effect. + /// public readonly double Time; + + /// + /// The attributes. + /// public readonly DifficultyAttributes Attributes; public TimedDifficultyAttributes(double time, DifficultyAttributes attributes) diff --git a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs index 09ca326cce..ef289c2a20 100644 --- a/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs +++ b/osu.Game/Screens/Play/HUD/PerformancePointsCounter.cs @@ -48,9 +48,6 @@ namespace osu.Game.Screens.Play.HUD [CanBeNull] private GameplayState gameplayState { get; set; } - [Resolved(CanBeNull = true)] - private GameplayClock gameplayClock { get; set; } - [CanBeNull] private List timedAttributes; @@ -136,12 +133,10 @@ namespace osu.Game.Screens.Play.HUD [CanBeNull] private DifficultyAttributes getAttributeAtTime(JudgementResult judgement) { - if (timedAttributes == null || timedAttributes.Count == 0 || gameplayClock == null) + if (timedAttributes == null || timedAttributes.Count == 0) return null; - double judgementTime = judgement.HitObject.GetEndTime() / gameplayClock.TrueGameplayRate; - - int attribIndex = timedAttributes.BinarySearch(new TimedDifficultyAttributes(judgementTime, null)); + int attribIndex = timedAttributes.BinarySearch(new TimedDifficultyAttributes(judgement.HitObject.GetEndTime(), null)); if (attribIndex < 0) attribIndex = ~attribIndex - 1; From efba7a9c4d70093a00ccb4f163c02c805b1248df Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 2 Nov 2021 17:18:02 +0900 Subject: [PATCH 07/30] Missed hyphen --- osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs b/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs index 28319ec6d7..e61fa72de9 100644 --- a/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs +++ b/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Difficulty public class TimedDifficultyAttributes : IComparable { /// - /// The non-clock adjusted time value at which the attributes take effect. + /// The non-clock-adjusted time value at which the attributes take effect. /// public readonly double Time; From 168a7a588b62b3f087e1d6e9785b7e8eeb2f9959 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 2 Nov 2021 17:19:14 +0900 Subject: [PATCH 08/30] Add xmldoc to ctor also --- osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs b/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs index e61fa72de9..2509971389 100644 --- a/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs +++ b/osu.Game/Rulesets/Difficulty/TimedDifficultyAttributes.cs @@ -21,6 +21,11 @@ namespace osu.Game.Rulesets.Difficulty /// public readonly DifficultyAttributes Attributes; + /// + /// Creates new . + /// + /// The non-clock-adjusted time value at which the attributes take effect. + /// The attributes. public TimedDifficultyAttributes(double time, DifficultyAttributes attributes) { Time = time; From 81aaef719fc58911d3ec94fc9c5c6bd2a77480b8 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Tue, 2 Nov 2021 17:55:00 +0900 Subject: [PATCH 09/30] Add xmldoc to CalculateTimed() --- osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs index d410fb6edf..5b4284dc2f 100644 --- a/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs +++ b/osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs @@ -58,6 +58,11 @@ namespace osu.Game.Rulesets.Difficulty return CreateDifficultyAttributes(Beatmap, playableMods, skills, clockRate); } + /// + /// Calculates the difficulty of the beatmap and returns a set of representing the difficulty at every relevant time value in the beatmap. + /// + /// The mods that should be applied to the beatmap. + /// The set of . public List CalculateTimed(params Mod[] mods) { preProcess(mods); From c85a4dca281bc0ed97ef275ae2ae8c08dab5a819 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Nov 2021 02:47:33 +0900 Subject: [PATCH 10/30] Fix crash when attempting to view global leaderboards --- osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs index 2e41723f34..5395fe0429 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs @@ -37,6 +37,7 @@ namespace osu.Game.Online.API.Requests.Responses public DateTimeOffset Date { get; set; } [JsonProperty(@"beatmap")] + [CanBeNull] public APIBeatmap Beatmap { get; set; } [JsonProperty("accuracy")] @@ -46,6 +47,7 @@ namespace osu.Game.Online.API.Requests.Responses public double? PP { get; set; } [JsonProperty(@"beatmapset")] + [CanBeNull] public APIBeatmapSet BeatmapSet { set @@ -96,7 +98,7 @@ namespace osu.Game.Online.API.Requests.Responses { TotalScore = TotalScore, MaxCombo = MaxCombo, - BeatmapInfo = Beatmap.ToBeatmapInfo(rulesets), + BeatmapInfo = Beatmap?.ToBeatmapInfo(rulesets), User = User, Accuracy = Accuracy, OnlineScoreID = OnlineID, From 08b0ffad504c9836931626987a5adcbde04945cb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Nov 2021 03:12:13 +0900 Subject: [PATCH 11/30] Fix incorrect check for local beatmap in `BeatmapDifficultyCache` This was correct in the WIP branch I have, but pulled out alone (where usages of `ToBeatmapInfo` still exist) it was not enough. --- osu.Game/Beatmaps/BeatmapDifficultyCache.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs index 9a0cdb387d..035f438b89 100644 --- a/osu.Game/Beatmaps/BeatmapDifficultyCache.cs +++ b/osu.Game/Beatmaps/BeatmapDifficultyCache.cs @@ -131,7 +131,7 @@ namespace osu.Game.Beatmaps var localRulesetInfo = rulesetInfo as RulesetInfo; // Difficulty can only be computed if the beatmap and ruleset are locally available. - if (localBeatmapInfo == null || localRulesetInfo == null) + if (localBeatmapInfo == null || localBeatmapInfo.ID == 0 || localRulesetInfo == null) { // If not, fall back to the existing star difficulty (e.g. from an online source). return Task.FromResult(new StarDifficulty(beatmapInfo.StarRating, (beatmapInfo as IBeatmapOnlineInfo)?.MaxCombo ?? 0)); From 6efd3d3115d953a5dbdb8a107a0db01e185eb9e4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Nov 2021 03:07:27 +0900 Subject: [PATCH 12/30] Don't perform background difficulty calculation for multiplayer panels There are cases these are shown in a long list. They shouldn't be running calculations. --- osu.Game/Beatmaps/Drawables/DifficultyIcon.cs | 5 +++-- osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs index 64412675bb..6e573cc2a0 100644 --- a/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs +++ b/osu.Game/Beatmaps/Drawables/DifficultyIcon.cs @@ -60,8 +60,9 @@ namespace osu.Game.Beatmaps.Drawables /// The ruleset to show the difficulty with. /// The mods to show the difficulty with. /// Whether to display a tooltip when hovered. - public DifficultyIcon([NotNull] IBeatmapInfo beatmapInfo, [CanBeNull] IRulesetInfo ruleset, [CanBeNull] IReadOnlyList mods, bool shouldShowTooltip = true) - : this(beatmapInfo, shouldShowTooltip) + /// Whether to perform difficulty lookup (including calculation if necessary). + public DifficultyIcon([NotNull] IBeatmapInfo beatmapInfo, [CanBeNull] IRulesetInfo ruleset, [CanBeNull] IReadOnlyList mods, bool shouldShowTooltip = true, bool performBackgroundDifficultyLookup = true) + : this(beatmapInfo, shouldShowTooltip, performBackgroundDifficultyLookup) { this.ruleset = ruleset ?? beatmapInfo.Ruleset; this.mods = mods ?? Array.Empty(); diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index 69ab7225ac..6f947bd398 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -105,7 +105,7 @@ namespace osu.Game.Screens.OnlinePlay private void refresh() { - difficultyIconContainer.Child = new DifficultyIcon(beatmap.Value, ruleset.Value, requiredMods) { Size = new Vector2(32) }; + difficultyIconContainer.Child = new DifficultyIcon(beatmap.Value, ruleset.Value, requiredMods, performBackgroundDifficultyLookup: false) { Size = new Vector2(32) }; beatmapText.Clear(); beatmapText.AddLink(Item.Beatmap.Value.GetDisplayTitleRomanisable(), LinkAction.OpenBeatmap, Item.Beatmap.Value.OnlineBeatmapID.ToString(), null, text => From c028275d6cd8541c92cd09933fc303039ab3d86a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 2 Nov 2021 19:16:44 +0100 Subject: [PATCH 13/30] Fix multiplayer score submission not working --- osu.Game/Online/Rooms/SubmitRoomScoreRequest.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Online/Rooms/SubmitRoomScoreRequest.cs b/osu.Game/Online/Rooms/SubmitRoomScoreRequest.cs index 9e432fa99e..d5da6c401c 100644 --- a/osu.Game/Online/Rooms/SubmitRoomScoreRequest.cs +++ b/osu.Game/Online/Rooms/SubmitRoomScoreRequest.cs @@ -5,6 +5,7 @@ using System.Net.Http; using Newtonsoft.Json; using osu.Framework.IO.Network; using osu.Game.Online.API; +using osu.Game.Online.Solo; using osu.Game.Scoring; namespace osu.Game.Online.Rooms @@ -14,14 +15,14 @@ namespace osu.Game.Online.Rooms private readonly long scoreId; private readonly long roomId; private readonly long playlistItemId; - private readonly ScoreInfo scoreInfo; + private readonly SubmittableScore score; public SubmitRoomScoreRequest(long scoreId, long roomId, long playlistItemId, ScoreInfo scoreInfo) { this.scoreId = scoreId; this.roomId = roomId; this.playlistItemId = playlistItemId; - this.scoreInfo = scoreInfo; + score = new SubmittableScore(scoreInfo); } protected override WebRequest CreateWebRequest() @@ -31,7 +32,7 @@ namespace osu.Game.Online.Rooms req.ContentType = "application/json"; req.Method = HttpMethod.Put; - req.AddRaw(JsonConvert.SerializeObject(scoreInfo, new JsonSerializerSettings + req.AddRaw(JsonConvert.SerializeObject(score, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore })); From 392559ae3effe1ad5dc96105fad3698eb1bca562 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Nov 2021 03:22:39 +0900 Subject: [PATCH 14/30] Fix beatmap download notifications not showing beatmap name correctly --- osu.Game/Beatmaps/BeatmapManager.cs | 17 +++++++++++++++++ .../Panels/BeatmapPanelDownloadButton.cs | 2 +- .../BeatmapSet/Buttons/HeaderDownloadButton.cs | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 0509a9db47..0caee8f9cd 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -249,6 +249,23 @@ namespace osu.Game.Beatmaps public IBindable>> DownloadFailed => beatmapModelDownloader.DownloadFailed; + // Temporary method until this class supports IBeatmapSetInfo or otherwise. + public bool Download(IBeatmapSetInfo model, bool minimiseDownloadSize = false) + { + return beatmapModelDownloader.Download(new BeatmapSetInfo + { + OnlineBeatmapSetID = model.OnlineID, + Metadata = new BeatmapMetadata + { + Title = model.Metadata?.Title, + Artist = model.Metadata?.Artist, + TitleUnicode = model.Metadata?.TitleUnicode, + ArtistUnicode = model.Metadata?.ArtistUnicode, + Author = new User { Username = model.Metadata?.Author }, + } + }, minimiseDownloadSize); + } + public bool Download(BeatmapSetInfo model, bool minimiseDownloadSize = false) { return beatmapModelDownloader.Download(model, minimiseDownloadSize); diff --git a/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs b/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs index d7c2837f4d..5ed49cf384 100644 --- a/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs +++ b/osu.Game/Overlays/BeatmapListing/Panels/BeatmapPanelDownloadButton.cs @@ -86,7 +86,7 @@ namespace osu.Game.Overlays.BeatmapListing.Panels break; default: - beatmaps.Download(new BeatmapSetInfo { OnlineBeatmapSetID = beatmapSet.OnlineID }, noVideoSetting.Value); + beatmaps.Download(beatmapSet, noVideoSetting.Value); break; } }; diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs index 6862864c55..bd7723d3c0 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs @@ -108,7 +108,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons return; } - beatmaps.Download(new BeatmapSetInfo { OnlineBeatmapSetID = beatmapSet.OnlineID }, noVideo); + beatmaps.Download(beatmapSet, noVideo); }; localUser.BindTo(api.LocalUser); From 8d0b32981f941173e8a3ca7f512a36f5c11e9efd Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Nov 2021 03:30:15 +0900 Subject: [PATCH 15/30] Fix unauthenticated API requests no longer working --- osu.Game/Online/API/APIRequest.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index d60c9cfe65..eea448fee3 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -107,7 +107,8 @@ namespace osu.Game.Online.API WebRequest = CreateWebRequest(); WebRequest.Failed += Fail; WebRequest.AllowRetryOnTimeout = false; - WebRequest.AddHeader("Authorization", $"Bearer {API.AccessToken}"); + if (API.IsLoggedIn) + WebRequest.AddHeader("Authorization", $"Bearer {API.AccessToken}"); if (isFailing) return; From 51e92e1b2d71d9d02c9edc8974c842c9894f1507 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Nov 2021 04:09:31 +0900 Subject: [PATCH 16/30] Check for null/empty instead --- osu.Game/Online/API/APIRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index eea448fee3..69d72226ba 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -107,7 +107,7 @@ namespace osu.Game.Online.API WebRequest = CreateWebRequest(); WebRequest.Failed += Fail; WebRequest.AllowRetryOnTimeout = false; - if (API.IsLoggedIn) + if (!string.IsNullOrEmpty(API.AccessToken)) WebRequest.AddHeader("Authorization", $"Bearer {API.AccessToken}"); if (isFailing) return; From 85037dfb700518a67a6236cc3ddf9d6a1df11f75 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Nov 2021 04:32:21 +0900 Subject: [PATCH 17/30] Fix multiplayer potentially getting incorrect beatmap availability state after changing beatmaps --- .../Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs index 6cd735af23..a642e283f9 100644 --- a/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs +++ b/osu.Game/Online/Rooms/OnlinePlayBeatmapAvailabilityTracker.cs @@ -53,7 +53,10 @@ namespace osu.Game.Online.Rooms downloadTracker?.RemoveAndDisposeImmediately(); downloadTracker = new BeatmapDownloadTracker(item.NewValue.Beatmap.Value.BeatmapSet); - downloadTracker.State.BindValueChanged(_ => updateAvailability()); + + AddInternal(downloadTracker); + + downloadTracker.State.BindValueChanged(_ => updateAvailability(), true); downloadTracker.Progress.BindValueChanged(_ => { if (downloadTracker.State.Value != DownloadState.Downloading) @@ -63,9 +66,7 @@ namespace osu.Game.Online.Rooms // we don't want to flood the network with this, so rate limit how often we send progress updates. if (progressUpdate?.Completed != false) progressUpdate = Scheduler.AddDelayed(updateAvailability, progressUpdate == null ? 0 : 500); - }); - - AddInternal(downloadTracker); + }, true); }, true); } From 47914c49bacb3ea879e1045693757e7196916ac0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Nov 2021 04:54:36 +0900 Subject: [PATCH 18/30] Fix missed null consideration --- .../Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs index ca5534dbc2..fb464e1b41 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/DrawableProfileScore.cs @@ -91,7 +91,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks { new OsuSpriteText { - Text = $"{Score.Beatmap.DifficultyName}", + Text = $"{Score.Beatmap?.DifficultyName}", Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular), Colour = colours.Yellow }, From 98367fc48295c136b77b7cdb0c8518c840ac228f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 1 Nov 2021 15:39:22 +0100 Subject: [PATCH 19/30] Update usages of `GetLocalised{-> Bindable}String` --- osu.Game/Overlays/Music/PlaylistItem.cs | 4 ++-- osu.Game/Screens/Select/BeatmapInfoWedge.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index eea2a9dc7e..04f1f14b20 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -46,8 +46,8 @@ namespace osu.Game.Overlays.Music artistColour = colours.Gray9; HandleColour = colours.Gray5; - title = localisation.GetLocalisedString(new RomanisableString(Model.Metadata.TitleUnicode, Model.Metadata.Title)); - artist = localisation.GetLocalisedString(new RomanisableString(Model.Metadata.ArtistUnicode, Model.Metadata.Artist)); + title = localisation.GetLocalisedBindableString(new RomanisableString(Model.Metadata.TitleUnicode, Model.Metadata.Title)); + artist = localisation.GetLocalisedBindableString(new RomanisableString(Model.Metadata.ArtistUnicode, Model.Metadata.Artist)); } protected override void LoadComplete() diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs index 2de72beaad..89eed14e6d 100644 --- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs +++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs @@ -188,8 +188,8 @@ namespace osu.Game.Screens.Select RelativeSizeAxes = Axes.Both; - titleBinding = localisation.GetLocalisedString(new RomanisableString(metadata.TitleUnicode, metadata.Title)); - artistBinding = localisation.GetLocalisedString(new RomanisableString(metadata.ArtistUnicode, metadata.Artist)); + titleBinding = localisation.GetLocalisedBindableString(new RomanisableString(metadata.TitleUnicode, metadata.Title)); + artistBinding = localisation.GetLocalisedBindableString(new RomanisableString(metadata.ArtistUnicode, metadata.Artist)); const float top_height = 0.7f; From b95c95527e94ccd8929bd6d28a0b367d4b10ebcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 30 Oct 2021 18:31:43 +0200 Subject: [PATCH 20/30] Accept `LocalisableString`s in `LinkFlowContainer` --- .../Graphics/Containers/LinkFlowContainer.cs | 17 +++--------- .../OnlinePlay/Components/BeatmapTitle.cs | 27 ++++++------------- 2 files changed, 11 insertions(+), 33 deletions(-) diff --git a/osu.Game/Graphics/Containers/LinkFlowContainer.cs b/osu.Game/Graphics/Containers/LinkFlowContainer.cs index 0b43c16ebe..7d1210d0e3 100644 --- a/osu.Game/Graphics/Containers/LinkFlowContainer.cs +++ b/osu.Game/Graphics/Containers/LinkFlowContainer.cs @@ -7,12 +7,10 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using System.Collections.Generic; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Localisation; using osu.Framework.Platform; -using osu.Game.Graphics.Sprites; using osu.Game.Users; namespace osu.Game.Graphics.Containers @@ -58,23 +56,14 @@ namespace osu.Game.Graphics.Containers AddText(text.Substring(previousLinkEnd)); } - public void AddLink(string text, string url, Action creationParameters = null) => + public void AddLink(LocalisableString text, string url, Action creationParameters = null) => createLink(CreateChunkFor(text, true, CreateSpriteText, creationParameters), new LinkDetails(LinkAction.External, url), url); - public void AddLink(string text, Action action, string tooltipText = null, Action creationParameters = null) + public void AddLink(LocalisableString text, Action action, string tooltipText = null, Action creationParameters = null) => createLink(CreateChunkFor(text, true, CreateSpriteText, creationParameters), new LinkDetails(LinkAction.Custom, string.Empty), tooltipText, action); - public void AddLink(string text, LinkAction action, string argument, string tooltipText = null, Action creationParameters = null) - => createLink(CreateChunkFor(text, true, CreateSpriteText, creationParameters), new LinkDetails(action, argument), tooltipText); - public void AddLink(LocalisableString text, LinkAction action, string argument, string tooltipText = null, Action creationParameters = null) - { - var spriteText = new OsuSpriteText { Text = text }; - - AddText(spriteText, creationParameters); - RemoveInternal(spriteText); // TODO: temporary, will go away when TextParts support localisation properly. - createLink(new TextPartManual(spriteText.Yield()), new LinkDetails(action, argument), tooltipText); - } + => createLink(CreateChunkFor(text, true, CreateSpriteText, creationParameters), new LinkDetails(action, argument), tooltipText); public void AddLink(IEnumerable text, LinkAction action, string linkArgument, string tooltipText = null) { diff --git a/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs b/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs index 2901758332..e948c1adae 100644 --- a/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs +++ b/osu.Game/Screens/OnlinePlay/Components/BeatmapTitle.cs @@ -7,7 +7,6 @@ using osu.Framework.Graphics; using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; using osu.Game.Online.Chat; namespace osu.Game.Screens.OnlinePlay.Components @@ -69,24 +68,14 @@ namespace osu.Game.Screens.OnlinePlay.Components } else { - textFlow.AddLink(new[] - { - new OsuSpriteText - { - Text = new RomanisableString(beatmap.Value.Metadata.ArtistUnicode, beatmap.Value.Metadata.Artist), - Font = OsuFont.GetFont(size: TextSize), - }, - new OsuSpriteText - { - Text = " - ", - Font = OsuFont.GetFont(size: TextSize), - }, - new OsuSpriteText - { - Text = new RomanisableString(beatmap.Value.Metadata.TitleUnicode, beatmap.Value.Metadata.Title), - Font = OsuFont.GetFont(size: TextSize), - } - }, LinkAction.OpenBeatmap, beatmap.Value.OnlineID.ToString(), "Open beatmap"); + var metadataInfo = beatmap.Value.Metadata; + + string artistUnicode = string.IsNullOrEmpty(metadataInfo.ArtistUnicode) ? metadataInfo.Artist : metadataInfo.ArtistUnicode; + string titleUnicode = string.IsNullOrEmpty(metadataInfo.TitleUnicode) ? metadataInfo.Title : metadataInfo.TitleUnicode; + + var title = new RomanisableString($"{artistUnicode} - {titleUnicode}".Trim(), $"{metadataInfo.Artist} - {metadataInfo.Title}".Trim()); + + textFlow.AddLink(title, LinkAction.OpenBeatmap, beatmap.Value.OnlineID.ToString(), "Open beatmap"); } } } From ad98ab0a2644ae6da0a7062a6dd21995ca4c2a1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 30 Oct 2021 18:31:55 +0200 Subject: [PATCH 21/30] Fix drawable room playlist item assuming single sprite text --- osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs index 6f947bd398..675b5e4c04 100644 --- a/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/OnlinePlay/DrawableRoomPlaylistItem.cs @@ -111,7 +111,6 @@ namespace osu.Game.Screens.OnlinePlay beatmapText.AddLink(Item.Beatmap.Value.GetDisplayTitleRomanisable(), LinkAction.OpenBeatmap, Item.Beatmap.Value.OnlineBeatmapID.ToString(), null, text => { text.Truncate = true; - text.RelativeSizeAxes = Axes.X; }); authorText.Clear(); From 11de9247047cf8f9ac3ee75280150bdd61627871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 30 Oct 2021 18:50:13 +0200 Subject: [PATCH 22/30] Use `LocalisableString`s where possible to leverage localisable text flow --- osu.Game/Graphics/UserInterface/OsuCheckbox.cs | 3 ++- osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs | 7 ++++--- osu.Game/Online/Placeholders/ClickablePlaceholder.cs | 3 ++- osu.Game/Online/Placeholders/MessagePlaceholder.cs | 5 +++-- osu.Game/Overlays/Dialog/PopupDialog.cs | 9 +++++---- osu.Game/Overlays/Notifications/ProgressNotification.cs | 3 ++- osu.Game/Overlays/Notifications/SimpleNotification.cs | 5 +++-- osu.Game/Screens/Edit/Timing/SliderWithTextBoxInput.cs | 3 ++- 8 files changed, 23 insertions(+), 15 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs index e8f80dec57..da511d8212 100644 --- a/osu.Game/Graphics/UserInterface/OsuCheckbox.cs +++ b/osu.Game/Graphics/UserInterface/OsuCheckbox.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Game.Graphics.Containers; namespace osu.Game.Graphics.UserInterface @@ -19,7 +20,7 @@ namespace osu.Game.Graphics.UserInterface /// protected virtual bool PlaySoundsOnUserChange => true; - public string LabelText + public LocalisableString LabelText { set { diff --git a/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs b/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs index d5f76733cf..95884f1515 100644 --- a/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs +++ b/osu.Game/Graphics/UserInterfaceV2/LabelledDrawable.cs @@ -8,6 +8,7 @@ using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Localisation; using osu.Game.Graphics.Containers; using osu.Game.Overlays; using osuTK; @@ -156,18 +157,18 @@ namespace osu.Game.Graphics.UserInterfaceV2 descriptionText.Colour = osuColour.Yellow; } - public string Label + public LocalisableString Label { set => labelText.Text = value; } - public string Description + public LocalisableString Description { set { descriptionText.Text = value; - if (!string.IsNullOrEmpty(value)) + if (value == default) descriptionText.Show(); else descriptionText.Hide(); diff --git a/osu.Game/Online/Placeholders/ClickablePlaceholder.cs b/osu.Game/Online/Placeholders/ClickablePlaceholder.cs index 936ad79c64..054a4a3c39 100644 --- a/osu.Game/Online/Placeholders/ClickablePlaceholder.cs +++ b/osu.Game/Online/Placeholders/ClickablePlaceholder.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; @@ -12,7 +13,7 @@ namespace osu.Game.Online.Placeholders { public Action Action; - public ClickablePlaceholder(string actionMessage, IconUsage icon) + public ClickablePlaceholder(LocalisableString actionMessage, IconUsage icon) { OsuTextFlowContainer textFlow; diff --git a/osu.Game/Online/Placeholders/MessagePlaceholder.cs b/osu.Game/Online/Placeholders/MessagePlaceholder.cs index 7342765ca4..1676ba6cf2 100644 --- a/osu.Game/Online/Placeholders/MessagePlaceholder.cs +++ b/osu.Game/Online/Placeholders/MessagePlaceholder.cs @@ -3,14 +3,15 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; namespace osu.Game.Online.Placeholders { public class MessagePlaceholder : Placeholder { - private readonly string message; + private readonly LocalisableString message; - public MessagePlaceholder(string message) + public MessagePlaceholder(LocalisableString message) { AddIcon(FontAwesome.Solid.ExclamationCircle, cp => { diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs index 78ef2ec795..0f953f92bb 100644 --- a/osu.Game/Overlays/Dialog/PopupDialog.cs +++ b/osu.Game/Overlays/Dialog/PopupDialog.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Input.Events; +using osu.Framework.Localisation; using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; using osuTK; @@ -42,9 +43,9 @@ namespace osu.Game.Overlays.Dialog set => icon.Icon = value; } - private string headerText; + private LocalisableString headerText; - public string HeaderText + public LocalisableString HeaderText { get => headerText; set @@ -57,9 +58,9 @@ namespace osu.Game.Overlays.Dialog } } - private string bodyText; + private LocalisableString bodyText; - public string BodyText + public LocalisableString BodyText { get => bodyText; set diff --git a/osu.Game/Overlays/Notifications/ProgressNotification.cs b/osu.Game/Overlays/Notifications/ProgressNotification.cs index b27e15dd2c..c44b88ad29 100644 --- a/osu.Game/Overlays/Notifications/ProgressNotification.cs +++ b/osu.Game/Overlays/Notifications/ProgressNotification.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; @@ -22,7 +23,7 @@ namespace osu.Game.Overlays.Notifications { private const float loading_spinner_size = 22; - public string Text + public LocalisableString Text { set => Schedule(() => textDrawable.Text = value); } diff --git a/osu.Game/Overlays/Notifications/SimpleNotification.cs b/osu.Game/Overlays/Notifications/SimpleNotification.cs index 3a3136b1ea..17ec12a4ca 100644 --- a/osu.Game/Overlays/Notifications/SimpleNotification.cs +++ b/osu.Game/Overlays/Notifications/SimpleNotification.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; +using osu.Framework.Localisation; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osuTK; @@ -15,9 +16,9 @@ namespace osu.Game.Overlays.Notifications { public class SimpleNotification : Notification { - private string text = string.Empty; + private LocalisableString text; - public string Text + public LocalisableString Text { get => text; set diff --git a/osu.Game/Screens/Edit/Timing/SliderWithTextBoxInput.cs b/osu.Game/Screens/Edit/Timing/SliderWithTextBoxInput.cs index 10a5771520..6c004a7c8b 100644 --- a/osu.Game/Screens/Edit/Timing/SliderWithTextBoxInput.cs +++ b/osu.Game/Screens/Edit/Timing/SliderWithTextBoxInput.cs @@ -6,6 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Localisation; using osu.Game.Graphics.UserInterfaceV2; using osu.Game.Overlays.Settings; @@ -16,7 +17,7 @@ namespace osu.Game.Screens.Edit.Timing { private readonly SettingsSlider slider; - public SliderWithTextBoxInput(string labelText) + public SliderWithTextBoxInput(LocalisableString labelText) { LabelledTextBox textbox; From ed00cd9fc5b321694e4cf5854448647cd6728b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 30 Oct 2021 18:50:34 +0200 Subject: [PATCH 23/30] Remove simple localisable `.ToString()` calls --- osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs | 2 +- .../Settings/Sections/Maintenance/DirectorySelectScreen.cs | 2 +- osu.Game/Overlays/Settings/SettingsCheckbox.cs | 3 +-- osu.Game/Overlays/Settings/SettingsItem.cs | 4 ++-- .../Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs | 3 ++- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs index 5cc598ae70..e84eee15be 100644 --- a/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs +++ b/osu.Game/Overlays/Changelog/ChangelogSupporterPromo.cs @@ -101,7 +101,7 @@ namespace osu.Game.Overlays.Changelog t.Colour = colour.PinkLighter; }) { - Text = ChangelogStrings.SupportText2.ToString(), + Text = ChangelogStrings.SupportText2, Margin = new MarginPadding { Top = 10 }, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs index e509cac2f1..0814e3c824 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/DirectorySelectScreen.cs @@ -83,7 +83,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance cp.Font = OsuFont.Default.With(size: 24); }) { - Text = HeaderText.ToString(), + Text = HeaderText, TextAnchor = Anchor.TopCentre, Margin = new MarginPadding(10), RelativeSizeAxes = Axes.X, diff --git a/osu.Game/Overlays/Settings/SettingsCheckbox.cs b/osu.Game/Overlays/Settings/SettingsCheckbox.cs index 8b7ac80a5b..8a8fed4d30 100644 --- a/osu.Game/Overlays/Settings/SettingsCheckbox.cs +++ b/osu.Game/Overlays/Settings/SettingsCheckbox.cs @@ -16,8 +16,7 @@ namespace osu.Game.Overlays.Settings public override LocalisableString LabelText { get => labelText; - // checkbox doesn't properly support localisation yet. - set => ((OsuCheckbox)Control).LabelText = (labelText = value).ToString(); + set => ((OsuCheckbox)Control).LabelText = labelText = value; } } } diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index b593dea576..e709be1343 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -68,7 +68,7 @@ namespace osu.Game.Overlays.Settings { set { - bool hasValue = !string.IsNullOrWhiteSpace(value.ToString()); + bool hasValue = value != default; if (warningText == null) { @@ -80,7 +80,7 @@ namespace osu.Game.Overlays.Settings } warningText.Alpha = hasValue ? 1 : 0; - warningText.Text = value.ToString(); // TODO: Remove ToString() call after TextFlowContainer supports localisation (see https://github.com/ppy/osu-framework/issues/4636). + warningText.Text = value ?? default; } } diff --git a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs index 2fe3c7b668..ef2c2df4a6 100644 --- a/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs +++ b/osu.Game/Screens/OnlinePlay/Lounge/Components/PlaylistCountPill.cs @@ -4,6 +4,7 @@ using System.Collections.Specialized; using Humanizer; using osu.Framework.Allocation; +using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Game.Graphics; using osu.Game.Graphics.Containers; @@ -46,7 +47,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components private void updateCount(object sender, NotifyCollectionChangedEventArgs e) { count.Clear(); - count.AddText(Playlist.Count.ToString(), s => s.Font = s.Font.With(weight: FontWeight.Bold)); + count.AddText(Playlist.Count.ToLocalisableString(), s => s.Font = s.Font.With(weight: FontWeight.Bold)); count.AddText(" "); count.AddText("Beatmap".ToQuantity(Playlist.Count, ShowQuantityAs.None)); } From d218e7d935f057fc306d5be2d6e4aa9a19bbc122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 30 Oct 2021 19:22:00 +0200 Subject: [PATCH 24/30] Remove manual romanisation handling in `PlaylistItem` --- osu.Game/Overlays/Music/PlaylistItem.cs | 33 +++++++++++-------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 04f1f14b20..ce4e9e9698 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -25,9 +25,6 @@ namespace osu.Game.Overlays.Music private TextFlowContainer text; private ITextPart titlePart; - private ILocalisedBindableString title; - private ILocalisedBindableString artist; - private Color4 selectedColour; private Color4 artistColour; @@ -45,17 +42,12 @@ namespace osu.Game.Overlays.Music selectedColour = colours.Yellow; artistColour = colours.Gray9; HandleColour = colours.Gray5; - - title = localisation.GetLocalisedBindableString(new RomanisableString(Model.Metadata.TitleUnicode, Model.Metadata.Title)); - artist = localisation.GetLocalisedBindableString(new RomanisableString(Model.Metadata.ArtistUnicode, Model.Metadata.Artist)); } protected override void LoadComplete() { base.LoadComplete(); - artist.BindValueChanged(_ => recreateText(), true); - SelectedSet.BindValueChanged(set => { if (set.OldValue?.Equals(Model) != true && set.NewValue?.Equals(Model) != true) @@ -71,26 +63,31 @@ namespace osu.Game.Overlays.Music s.FadeColour(SelectedSet.Value?.Equals(Model) == true ? selectedColour : Color4.White, instant ? 0 : FADE_DURATION); } - protected override Drawable CreateContent() => text = new OsuTextFlowContainer + protected override Drawable CreateContent() { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }; + text = new OsuTextFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }; - private void recreateText() - { - text.Clear(); + var title = new RomanisableString(Model.Metadata.TitleUnicode, Model.Metadata.Title); + var artist = new RomanisableString(Model.Metadata.ArtistUnicode, Model.Metadata.Artist); - // space after the title to put a space between the title and artist - titlePart = text.AddText(title.Value + @" ", sprite => sprite.Font = OsuFont.GetFont(weight: FontWeight.Regular)); + titlePart = text.AddText(title, sprite => sprite.Font = OsuFont.GetFont(weight: FontWeight.Regular)); updateSelectionState(true); + titlePart.DrawablePartsRecreated += _ => updateSelectionState(true); - text.AddText(artist.Value, sprite => + text.AddText(@" "); // to separate the title from the artist. + + text.AddText(artist, sprite => { sprite.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold); sprite.Colour = artistColour; sprite.Padding = new MarginPadding { Top = 1 }; }); + + return text; } protected override bool OnClick(ClickEvent e) From e4e8390a8ac2138b571418f711792ab282804d01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 1 Nov 2021 15:44:51 +0100 Subject: [PATCH 25/30] Update `ScreenEntry` colour usage to update correctly on language change --- osu.Game/Overlays/AccountCreation/ScreenEntry.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index 8ee3b1cb2e..2ba8fc3ae2 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -5,7 +5,6 @@ using System; using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Utils; @@ -135,7 +134,16 @@ namespace osu.Game.Overlays.AccountCreation characterCheckText = passwordDescription.AddText("8 characters long"); passwordDescription.AddText(". Choose something long but also something you will remember, like a line from your favourite song."); - passwordTextBox.Current.ValueChanged += password => { characterCheckText.Drawables.ForEach(s => s.Colour = password.NewValue.Length == 0 ? Color4.White : Interpolation.ValueAt(password.NewValue.Length, Color4.OrangeRed, Color4.YellowGreen, 0, 8, Easing.In)); }; + passwordTextBox.Current.BindValueChanged(_ => updateCharacterCheckTextColour(), true); + characterCheckText.DrawablePartsRecreated += _ => updateCharacterCheckTextColour(); + } + + private void updateCharacterCheckTextColour() + { + string password = passwordTextBox.Text; + + foreach (var d in characterCheckText.Drawables) + d.Colour = password.Length == 0 ? Color4.White : Interpolation.ValueAt(password.Length, Color4.OrangeRed, Color4.YellowGreen, 0, 8, Easing.In); } public override void OnEntering(IScreen last) From 195a141625d38018debc744089dcdc4578cfc808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 2 Nov 2021 22:51:25 +0100 Subject: [PATCH 26/30] Fix score tracker not tracking non-online scores correctly --- osu.Game/Online/ScoreDownloadTracker.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/osu.Game/Online/ScoreDownloadTracker.cs b/osu.Game/Online/ScoreDownloadTracker.cs index 675dbf608c..e679071ac1 100644 --- a/osu.Game/Online/ScoreDownloadTracker.cs +++ b/osu.Game/Online/ScoreDownloadTracker.cs @@ -35,7 +35,11 @@ namespace osu.Game.Online return; // Used to interact with manager classes that don't support interface types. Will eventually be replaced. - var scoreInfo = new ScoreInfo { OnlineScoreID = TrackedItem.OnlineScoreID }; + var scoreInfo = new ScoreInfo + { + ID = TrackedItem.ID, + OnlineScoreID = TrackedItem.OnlineScoreID + }; if (Manager.IsAvailableLocally(scoreInfo)) UpdateState(DownloadState.LocallyAvailable); From 494d582830fac10f7bc036cbf87c8b5789471061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 2 Nov 2021 23:19:45 +0100 Subject: [PATCH 27/30] Fix `PlaylistItem` attempting to read from `OsuColour` dependency too early --- osu.Game/Overlays/Music/PlaylistItem.cs | 28 ++++++++++++------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index ce4e9e9698..04c12b8cd7 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -25,8 +25,8 @@ namespace osu.Game.Overlays.Music private TextFlowContainer text; private ITextPart titlePart; - private Color4 selectedColour; - private Color4 artistColour; + [Resolved] + private OsuColour colours { get; set; } public PlaylistItem(BeatmapSetInfo item) : base(item) @@ -37,10 +37,8 @@ namespace osu.Game.Overlays.Music } [BackgroundDependencyLoader] - private void load(OsuColour colours, LocalisationManager localisation) + private void load() { - selectedColour = colours.Yellow; - artistColour = colours.Gray9; HandleColour = colours.Gray5; } @@ -60,16 +58,18 @@ namespace osu.Game.Overlays.Music private void updateSelectionState(bool instant) { foreach (Drawable s in titlePart.Drawables) - s.FadeColour(SelectedSet.Value?.Equals(Model) == true ? selectedColour : Color4.White, instant ? 0 : FADE_DURATION); + s.FadeColour(SelectedSet.Value?.Equals(Model) == true ? colours.Yellow : Color4.White, instant ? 0 : FADE_DURATION); } - protected override Drawable CreateContent() + protected override Drawable CreateContent() => text = new OsuTextFlowContainer { - text = new OsuTextFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - }; + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + }; + + protected override void LoadAsyncComplete() + { + base.LoadAsyncComplete(); var title = new RomanisableString(Model.Metadata.TitleUnicode, Model.Metadata.Title); var artist = new RomanisableString(Model.Metadata.ArtistUnicode, Model.Metadata.Artist); @@ -83,11 +83,9 @@ namespace osu.Game.Overlays.Music text.AddText(artist, sprite => { sprite.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold); - sprite.Colour = artistColour; + sprite.Colour = colours.Gray9; sprite.Padding = new MarginPadding { Top = 1 }; }); - - return text; } protected override bool OnClick(ClickEvent e) From 75e89f17add1e7fe3a4dccf7a1a25775c58d8329 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 3 Nov 2021 00:07:03 +0100 Subject: [PATCH 28/30] Rewrite `BeatmapCardContentBackground` --- .../Beatmaps/Drawables/Cards/BeatmapCard.cs | 3 +- .../Cards/BeatmapCardContentBackground.cs | 130 +++++------------- 2 files changed, 39 insertions(+), 94 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs index b1fe381410..20c5359320 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs @@ -94,10 +94,9 @@ namespace osu.Game.Beatmaps.Drawables.Cards Masking = true, Children = new Drawable[] { - mainContentBackground = new BeatmapCardContentBackground + mainContentBackground = new BeatmapCardContentBackground(beatmapSet) { RelativeSizeAxes = Axes.Both, - BeatmapSet = beatmapSet, }, new FillFlowContainer { diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs index 88c9d771ac..392f5d1bfa 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCardContentBackground.cs @@ -3,7 +3,6 @@ #nullable enable -using System; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Graphics; @@ -14,112 +13,59 @@ using osu.Game.Overlays; namespace osu.Game.Beatmaps.Drawables.Cards { - public class BeatmapCardContentBackground : ModelBackedDrawable + public class BeatmapCardContentBackground : CompositeDrawable { - public IBeatmapSetOnlineInfo BeatmapSet + public BindableBool Dimmed { get; } = new BindableBool(); + + private readonly Box background; + private readonly DelayedLoadUnloadWrapper cover; + + [Resolved] + private OverlayColourProvider colourProvider { get; set; } = null!; + + public BeatmapCardContentBackground(IBeatmapSetOnlineInfo onlineInfo) { - get => Model; - set => Model = value; + InternalChildren = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + cover = new DelayedLoadUnloadWrapper(() => createCover(onlineInfo), 500, 500) + { + RelativeSizeAxes = Axes.Both, + Colour = Colour4.Transparent + } + }; } - public new bool Masking + private static Drawable createCover(IBeatmapSetOnlineInfo onlineInfo) => new OnlineBeatmapSetCover(onlineInfo) { - get => base.Masking; - set => base.Masking = value; - } - - public BindableBool Dimmed { get; private set; } = new BindableBool(); - - protected override double LoadDelay => 500; - - protected override double TransformDuration => 400; + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + FillMode = FillMode.Fill + }; [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) { - InternalChild = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = colourProvider.Background2 - }; + background.Colour = colourProvider.Background2; } - protected override DelayedLoadWrapper CreateDelayedLoadWrapper(Func createContentFunc, double timeBeforeLoad) - => new DelayedLoadUnloadWrapper(createContentFunc, timeBeforeLoad); - - protected override Drawable? CreateDrawable(IBeatmapSetOnlineInfo? model) + protected override void LoadComplete() { - if (model == null) - return null; - - return new BufferedBackground(model) - { - RelativeSizeAxes = Axes.Both, - Dimmed = { BindTarget = Dimmed } - }; + base.LoadComplete(); + Dimmed.BindValueChanged(_ => updateState(), true); + FinishTransforms(true); } - private class BufferedBackground : BufferedContainer + private void updateState() => Schedule(() => { - public BindableBool Dimmed { get; } = new BindableBool(); + background.FadeColour(Dimmed.Value ? colourProvider.Background4 : colourProvider.Background2, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); - private readonly IBeatmapSetOnlineInfo onlineInfo; - - private readonly Box background; - private OnlineBeatmapSetCover? cover; - - [Resolved] - private OverlayColourProvider colourProvider { get; set; } = null!; - - public BufferedBackground(IBeatmapSetOnlineInfo onlineInfo) - { - this.onlineInfo = onlineInfo; - - RelativeSizeAxes = Axes.Both; - InternalChild = background = new Box - { - RelativeSizeAxes = Axes.Both, - }; - } - - [BackgroundDependencyLoader] - private void load() - { - background.Colour = colourProvider.Background2; - - LoadComponentAsync(new OnlineBeatmapSetCover(onlineInfo) - { - RelativeSizeAxes = Axes.Both, - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - FillMode = FillMode.Fill - }, loaded => - { - cover = loaded; - cover.Colour = Colour4.Transparent; - AddInternal(cover); - FinishTransforms(true); - updateState(); - }); - } - - protected override void LoadComplete() - { - base.LoadComplete(); - Dimmed.BindValueChanged(_ => updateState(), true); - FinishTransforms(true); - } - - private void updateState() - { - if (cover == null) - return; - - background.FadeColour(Dimmed.Value ? colourProvider.Background4 : colourProvider.Background2, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); - - var gradient = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0), Colour4.White.Opacity(0.2f)); - cover.FadeColour(gradient, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); - } - } + var gradient = ColourInfo.GradientHorizontal(Colour4.White.Opacity(0), Colour4.White.Opacity(0.2f)); + cover.FadeColour(gradient, BeatmapCard.TRANSITION_DURATION, Easing.OutQuint); + }); } } From 1813681fac0c0ae3407eb3cbfd2d7e04e95533b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Wed, 3 Nov 2021 00:10:50 +0100 Subject: [PATCH 29/30] Move private method below protected --- osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs index 20c5359320..8136ebbd70 100644 --- a/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs +++ b/osu.Game/Beatmaps/Drawables/Cards/BeatmapCard.cs @@ -247,12 +247,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards FinishTransforms(true); } - private LocalisableString createArtistText() - { - var romanisableArtist = new RomanisableString(beatmapSet.ArtistUnicode, beatmapSet.Artist); - return BeatmapsetsStrings.ShowDetailsByArtist(romanisableArtist); - } - protected override bool OnHover(HoverEvent e) { updateState(); @@ -265,6 +259,12 @@ namespace osu.Game.Beatmaps.Drawables.Cards base.OnHoverLost(e); } + private LocalisableString createArtistText() + { + var romanisableArtist = new RomanisableString(beatmapSet.ArtistUnicode, beatmapSet.Artist); + return BeatmapsetsStrings.ShowDetailsByArtist(romanisableArtist); + } + private void updateState() { float targetWidth = width - height; From 8d40d55d933eb45ea5a30582d38e23a6ccb3d17d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 3 Nov 2021 17:09:49 +0900 Subject: [PATCH 30/30] 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 dec994bcb2..4887e3a95f 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 c1c3336b5c..972d64a997 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 0baf067a63..f6e4f61fde 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -70,7 +70,7 @@ - + @@ -93,7 +93,7 @@ - +