From b45f1ef99a6489984534cf86ac219469b6d0265f Mon Sep 17 00:00:00 2001 From: Maximilian Junges Date: Sun, 9 Feb 2020 22:27:37 +0100 Subject: [PATCH 01/72] make timestamps hoverable --- osu.Game/Overlays/BeatmapSet/AuthorInfo.cs | 26 +++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index 096e91b65b..485ca100c6 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.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 osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -50,7 +51,7 @@ namespace osu.Game.Overlays.BeatmapSet fields.Children = new Drawable[] { new Field("mapped by", BeatmapSet.Metadata.Author.Username, OsuFont.GetFont(weight: FontWeight.Regular, italics: true)), - new Field("submitted on", online.Submitted.ToString(@"MMMM d, yyyy"), OsuFont.GetFont(weight: FontWeight.Bold)) + new Field("submitted", online.Submitted, OsuFont.GetFont(weight: FontWeight.Bold)) { Margin = new MarginPadding { Top = 5 }, }, @@ -58,11 +59,11 @@ namespace osu.Game.Overlays.BeatmapSet if (online.Ranked.HasValue) { - fields.Add(new Field("ranked on", online.Ranked.Value.ToString(@"MMMM d, yyyy"), OsuFont.GetFont(weight: FontWeight.Bold))); + fields.Add(new Field("ranked", online.Ranked.Value, OsuFont.GetFont(weight: FontWeight.Bold))); } else if (online.LastUpdated.HasValue) { - fields.Add(new Field("last updated on", online.LastUpdated.Value.ToString(@"MMMM d, yyyy"), OsuFont.GetFont(weight: FontWeight.Bold))); + fields.Add(new Field("last updated", online.LastUpdated.Value, OsuFont.GetFont(weight: FontWeight.Bold))); } } @@ -126,6 +127,25 @@ namespace osu.Game.Overlays.BeatmapSet }, }; } + + public Field(string first, DateTimeOffset second, FontUsage secondFont) + { + AutoSizeAxes = Axes.Both; + Direction = FillDirection.Horizontal; + + Children = new[] + { + new OsuSpriteText + { + Text = $"{first} ", + Font = OsuFont.GetFont(size: 13) + }, + new DrawableDate(second) + { + Font = secondFont.With(size: 13) + } + }; + } } } } From 867c7338093934caf6164ba27029b3e65d006614 Mon Sep 17 00:00:00 2001 From: Maximilian Junges Date: Sun, 9 Feb 2020 23:19:32 +0100 Subject: [PATCH 02/72] make score date hoverable --- .../BeatmapSet/Scores/TopScoreUserSection.cs | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index 72a7efd777..ba1db8ef03 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.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 osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -12,7 +13,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Online.Leaderboards; using osu.Game.Scoring; using osu.Game.Users.Drawables; -using osu.Game.Utils; using osuTK; using osuTK.Graphics; @@ -24,7 +24,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly UpdateableRank rank; private readonly UpdateableAvatar avatar; private readonly LinkFlowContainer usernameText; - private readonly SpriteText date; + private readonly DrawableDate achievedOn; private readonly UpdateableFlag flag; public TopScoreUserSection() @@ -92,11 +92,24 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, }, - date = new OsuSpriteText + new FillFlowContainer() { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: 10, weight: FontWeight.Bold) + Children = new[] + { + new OsuSpriteText + { + Text = "achieved ", + Font = OsuFont.GetFont(size: 10, weight: FontWeight.Bold) + }, + achievedOn = new DrawableDate(DateTimeOffset.MinValue) + { + Font = OsuFont.GetFont(size: 10, weight: FontWeight.Bold) + }, + } }, flag = new UpdateableFlag { @@ -125,7 +138,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { avatar.User = value.User; flag.Country = value.User.Country; - date.Text = $@"achieved {HumanizerUtils.Humanize(value.Date)}"; + achievedOn.Date = value.Date; usernameText.Clear(); usernameText.AddUserLink(value.User); @@ -134,4 +147,4 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } } -} +} \ No newline at end of file From 3e06324f61770bd6bcee4135c0573d5fc1720b0a Mon Sep 17 00:00:00 2001 From: Maximilian Junges Date: Sun, 9 Feb 2020 23:39:34 +0100 Subject: [PATCH 03/72] fix formatting issue --- osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index ba1db8ef03..6c33629c0e 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -92,7 +92,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.CentreLeft, AutoSizeAxes = Axes.Both, }, - new FillFlowContainer() + new FillFlowContainer { AutoSizeAxes = Axes.Both, Direction = FillDirection.Horizontal, From ed8cb1d6bf42b35b97370810216404532acb114a Mon Sep 17 00:00:00 2001 From: Maximilian Junges Date: Sun, 9 Feb 2020 23:46:06 +0100 Subject: [PATCH 04/72] add missing eof newline --- osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index 6c33629c0e..94a6334401 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -147,4 +147,4 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } } } -} \ No newline at end of file +} From 627833844839dec52e21f1ad7bc00cd796933a9c Mon Sep 17 00:00:00 2001 From: Maximilian Junges Date: Tue, 11 Feb 2020 14:21:12 +0100 Subject: [PATCH 05/72] implement custom tooltip for DrawableDate --- osu.Game/Graphics/DrawableDate.cs | 75 ++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/DrawableDate.cs b/osu.Game/Graphics/DrawableDate.cs index 0224c77ee8..dcbea96071 100644 --- a/osu.Game/Graphics/DrawableDate.cs +++ b/osu.Game/Graphics/DrawableDate.cs @@ -4,13 +4,16 @@ using System; using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; +using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Sprites; using osu.Game.Utils; +using osuTK; namespace osu.Game.Graphics { - public class DrawableDate : OsuSpriteText, IHasTooltip + public class DrawableDate : OsuSpriteText, IHasCustomTooltip { private DateTimeOffset date; @@ -75,6 +78,74 @@ namespace osu.Game.Graphics private void updateTime() => Text = Format(); - public virtual string TooltipText => string.Format($"{Date:MMMM d, yyyy h:mm tt \"UTC\"z}"); + public ITooltip GetCustomTooltip() => new DateTooltip(); + + public object TooltipContent => Date; + + private class DateTooltip : VisibilityContainer, ITooltip + { + private readonly OsuSpriteText dateText, timeText; + private readonly Box background; + + public DateTooltip() + { + AutoSizeAxes = Axes.Both; + Masking = true; + CornerRadius = 5; + + Children = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both + }, + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Padding = new MarginPadding(10), + Children = new Drawable[] + { + dateText = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + }, + timeText = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Regular), + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + } + } + }, + }; + } + + [BackgroundDependencyLoader] + private void load(OsuColour colours) + { + // Temporary colour since it's currently impossible to change it without bugs (see https://github.com/ppy/osu-framework/issues/3231) + // If above is fixed, this should use OverlayColourProvider + background.Colour = colours.Gray1; + timeText.Colour = colours.GreyCyanLighter; + } + + protected override void PopIn() => this.FadeIn(200, Easing.OutQuint); + protected override void PopOut() => this.FadeOut(200, Easing.OutQuint); + + public bool SetContent(object content) + { + if (!(content is DateTimeOffset date)) + return false; + + dateText.Text = string.Format($"{date:d MMMM yyyy}") + " "; + timeText.Text = string.Format($"{date:hh:mm:ss \"UTC\"z}"); + return true; + } + + public void Move(Vector2 pos) => Position = pos; + } } } From 2901ec9f261d8d9963f964ef114f5c3b06063267 Mon Sep 17 00:00:00 2001 From: voidedWarranties Date: Tue, 11 Feb 2020 20:05:26 -0800 Subject: [PATCH 06/72] Select specific difficulties using their icons --- osu.Game/Screens/Select/BeatmapCarousel.cs | 7 ++++- .../Select/Carousel/CarouselBeatmapSet.cs | 5 +++- .../Carousel/DrawableCarouselBeatmapSet.cs | 28 +++++++++++++++++-- osu.Game/Screens/Select/SongSelect.cs | 1 + 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 592e26adc2..1777527ced 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -53,6 +53,11 @@ namespace osu.Game.Screens.Select /// public Action SelectionChanged; + /// + /// Raised when user finalises beatmap selection using + /// + public Action SelectionFinalised; + public override bool HandleNonPositionalInput => AllowSelection; public override bool HandlePositionalInput => AllowSelection; @@ -577,7 +582,7 @@ namespace osu.Game.Screens.Select b.Metadata = beatmapSet.Metadata; } - var set = new CarouselBeatmapSet(beatmapSet); + var set = new CarouselBeatmapSet(beatmapSet, this); foreach (var c in set.Beatmaps) { diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 301d0d4dae..66ee4d2aee 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -15,8 +15,9 @@ namespace osu.Game.Screens.Select.Carousel public IEnumerable Beatmaps => InternalChildren.OfType(); public BeatmapSetInfo BeatmapSet; + public BeatmapCarousel Carousel; - public CarouselBeatmapSet(BeatmapSetInfo beatmapSet) + public CarouselBeatmapSet(BeatmapSetInfo beatmapSet, BeatmapCarousel carousel) { BeatmapSet = beatmapSet ?? throw new ArgumentNullException(nameof(beatmapSet)); @@ -24,6 +25,8 @@ namespace osu.Game.Screens.Select.Carousel .Where(b => !b.Hidden) .Select(b => new CarouselBeatmap(b)) .ForEach(AddChild); + + Carousel = carousel; } protected override DrawableCarouselItem CreateDrawableRepresentation() => new DrawableCarouselBeatmapSet(this); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 699e01bca7..536fca9e6f 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.UserInterface; +using osu.Framework.Input.Events; using osu.Framework.Localisation; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; @@ -33,10 +34,13 @@ namespace osu.Game.Screens.Select.Carousel private DialogOverlay dialogOverlay; private readonly BeatmapSetInfo beatmapSet; + private BeatmapCarousel carousel; + public DrawableCarouselBeatmapSet(CarouselBeatmapSet set) : base(set) { beatmapSet = set.BeatmapSet; + carousel = set.Carousel; } [BackgroundDependencyLoader(true)] @@ -117,7 +121,7 @@ namespace osu.Game.Screens.Select.Carousel return beatmaps.Count > maximum_difficulty_icons ? (IEnumerable)beatmaps.GroupBy(b => b.Beatmap.Ruleset).Select(group => new FilterableGroupedDifficultyIcon(group.ToList(), group.Key)) - : beatmaps.Select(b => new FilterableDifficultyIcon(b)); + : beatmaps.Select(b => new FilterableDifficultyIcon(b, carousel)); } public MenuItem[] ContextMenuItems @@ -210,12 +214,32 @@ namespace osu.Game.Screens.Select.Carousel { private readonly BindableBool filtered = new BindableBool(); - public FilterableDifficultyIcon(CarouselBeatmap item) + private BeatmapCarousel carousel; + private BeatmapInfo info; + + public FilterableDifficultyIcon(CarouselBeatmap item, BeatmapCarousel carousel) : base(item.Beatmap) { filtered.BindTo(item.Filtered); filtered.ValueChanged += isFiltered => Schedule(() => this.FadeTo(isFiltered.NewValue ? 0.1f : 1, 100)); filtered.TriggerChange(); + + this.carousel = carousel; + info = item.Beatmap; + } + + protected override bool OnClick(ClickEvent e) + { + if(e.AltPressed || carousel.SelectedBeatmap == info) + { + Schedule(() => carousel.SelectionFinalised?.Invoke(info)); + } + else + { + carousel.SelectBeatmap(info); + } + + return true; } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 5037081b5e..bfa693cf3d 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -155,6 +155,7 @@ namespace osu.Game.Screens.Select Origin = Anchor.CentreRight, RelativeSizeAxes = Axes.Both, SelectionChanged = updateSelectedBeatmap, + SelectionFinalised = beatmapInfo => { FinaliseSelection(beatmapInfo); }, BeatmapSetsChanged = carouselBeatmapsLoaded, }, } From b126c002924788acd7dd62cc410821db081da0fa Mon Sep 17 00:00:00 2001 From: voidedWarranties Date: Wed, 12 Feb 2020 19:05:08 -0800 Subject: [PATCH 07/72] Use dependency loader to get SongSelect instance --- osu.Game/Screens/Select/BeatmapCarousel.cs | 7 +---- .../Select/Carousel/CarouselBeatmapSet.cs | 5 +--- .../Carousel/DrawableCarouselBeatmapSet.cs | 27 ++++++++++--------- osu.Game/Screens/Select/SongSelect.cs | 3 +-- 4 files changed, 18 insertions(+), 24 deletions(-) diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 1777527ced..592e26adc2 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -53,11 +53,6 @@ namespace osu.Game.Screens.Select /// public Action SelectionChanged; - /// - /// Raised when user finalises beatmap selection using - /// - public Action SelectionFinalised; - public override bool HandleNonPositionalInput => AllowSelection; public override bool HandlePositionalInput => AllowSelection; @@ -582,7 +577,7 @@ namespace osu.Game.Screens.Select b.Metadata = beatmapSet.Metadata; } - var set = new CarouselBeatmapSet(beatmapSet, this); + var set = new CarouselBeatmapSet(beatmapSet); foreach (var c in set.Beatmaps) { diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs index 66ee4d2aee..301d0d4dae 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmapSet.cs @@ -15,9 +15,8 @@ namespace osu.Game.Screens.Select.Carousel public IEnumerable Beatmaps => InternalChildren.OfType(); public BeatmapSetInfo BeatmapSet; - public BeatmapCarousel Carousel; - public CarouselBeatmapSet(BeatmapSetInfo beatmapSet, BeatmapCarousel carousel) + public CarouselBeatmapSet(BeatmapSetInfo beatmapSet) { BeatmapSet = beatmapSet ?? throw new ArgumentNullException(nameof(beatmapSet)); @@ -25,8 +24,6 @@ namespace osu.Game.Screens.Select.Carousel .Where(b => !b.Hidden) .Select(b => new CarouselBeatmap(b)) .ForEach(AddChild); - - Carousel = carousel; } protected override DrawableCarouselItem CreateDrawableRepresentation() => new DrawableCarouselBeatmapSet(this); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 536fca9e6f..fd13bdc3eb 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -34,18 +34,20 @@ namespace osu.Game.Screens.Select.Carousel private DialogOverlay dialogOverlay; private readonly BeatmapSetInfo beatmapSet; - private BeatmapCarousel carousel; + private SongSelect songSelect; public DrawableCarouselBeatmapSet(CarouselBeatmapSet set) : base(set) { beatmapSet = set.BeatmapSet; - carousel = set.Carousel; } [BackgroundDependencyLoader(true)] - private void load(BeatmapManager manager, BeatmapSetOverlay beatmapOverlay, DialogOverlay overlay) + private void load(SongSelect songSelect, BeatmapManager manager, BeatmapSetOverlay beatmapOverlay, DialogOverlay overlay) { + if(songSelect != null) + this.songSelect = songSelect; + restoreHiddenRequested = s => s.Beatmaps.ForEach(manager.Restore); dialogOverlay = overlay; if (beatmapOverlay != null) @@ -121,7 +123,7 @@ namespace osu.Game.Screens.Select.Carousel return beatmaps.Count > maximum_difficulty_icons ? (IEnumerable)beatmaps.GroupBy(b => b.Beatmap.Ruleset).Select(group => new FilterableGroupedDifficultyIcon(group.ToList(), group.Key)) - : beatmaps.Select(b => new FilterableDifficultyIcon(b, carousel)); + : beatmaps.Select(b => new FilterableDifficultyIcon(b, songSelect, songSelect.Carousel)); } public MenuItem[] ContextMenuItems @@ -214,32 +216,33 @@ namespace osu.Game.Screens.Select.Carousel { private readonly BindableBool filtered = new BindableBool(); + private SongSelect songSelect; private BeatmapCarousel carousel; private BeatmapInfo info; - public FilterableDifficultyIcon(CarouselBeatmap item, BeatmapCarousel carousel) + public FilterableDifficultyIcon(CarouselBeatmap item, SongSelect songSelect, BeatmapCarousel carousel) : base(item.Beatmap) { filtered.BindTo(item.Filtered); filtered.ValueChanged += isFiltered => Schedule(() => this.FadeTo(isFiltered.NewValue ? 0.1f : 1, 100)); filtered.TriggerChange(); + this.songSelect = songSelect; this.carousel = carousel; info = item.Beatmap; } protected override bool OnClick(ClickEvent e) { - if(e.AltPressed || carousel.SelectedBeatmap == info) + if(!filtered.Value) { - Schedule(() => carousel.SelectionFinalised?.Invoke(info)); - } - else - { - carousel.SelectBeatmap(info); + carousel?.SelectBeatmap(info); + + if (e.AltPressed) + songSelect?.FinaliseSelection(); } - return true; + return base.OnClick(e); } } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index bfa693cf3d..463a17989a 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -80,7 +80,7 @@ namespace osu.Game.Screens.Select protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value); - protected BeatmapCarousel Carousel { get; private set; } + public BeatmapCarousel Carousel { get; private set; } private BeatmapInfoWedge beatmapInfoWedge; private DialogOverlay dialogOverlay; @@ -155,7 +155,6 @@ namespace osu.Game.Screens.Select Origin = Anchor.CentreRight, RelativeSizeAxes = Axes.Both, SelectionChanged = updateSelectedBeatmap, - SelectionFinalised = beatmapInfo => { FinaliseSelection(beatmapInfo); }, BeatmapSetsChanged = carouselBeatmapsLoaded, }, } From f8b69fe63285186a2e6b661e875353696e86ce1f Mon Sep 17 00:00:00 2001 From: voidedWarranties Date: Wed, 12 Feb 2020 20:11:39 -0800 Subject: [PATCH 08/72] Remove unnecessary carousel variable, fix code formatting --- .../Carousel/DrawableCarouselBeatmapSet.cs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index fd13bdc3eb..80dae575ff 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -45,7 +45,7 @@ namespace osu.Game.Screens.Select.Carousel [BackgroundDependencyLoader(true)] private void load(SongSelect songSelect, BeatmapManager manager, BeatmapSetOverlay beatmapOverlay, DialogOverlay overlay) { - if(songSelect != null) + if (songSelect != null) this.songSelect = songSelect; restoreHiddenRequested = s => s.Beatmaps.ForEach(manager.Restore); @@ -123,7 +123,7 @@ namespace osu.Game.Screens.Select.Carousel return beatmaps.Count > maximum_difficulty_icons ? (IEnumerable)beatmaps.GroupBy(b => b.Beatmap.Ruleset).Select(group => new FilterableGroupedDifficultyIcon(group.ToList(), group.Key)) - : beatmaps.Select(b => new FilterableDifficultyIcon(b, songSelect, songSelect.Carousel)); + : beatmaps.Select(b => new FilterableDifficultyIcon(b, songSelect)); } public MenuItem[] ContextMenuItems @@ -216,11 +216,10 @@ namespace osu.Game.Screens.Select.Carousel { private readonly BindableBool filtered = new BindableBool(); - private SongSelect songSelect; - private BeatmapCarousel carousel; - private BeatmapInfo info; + private readonly SongSelect songSelect; + private readonly BeatmapInfo info; - public FilterableDifficultyIcon(CarouselBeatmap item, SongSelect songSelect, BeatmapCarousel carousel) + public FilterableDifficultyIcon(CarouselBeatmap item, SongSelect songSelect) : base(item.Beatmap) { filtered.BindTo(item.Filtered); @@ -228,15 +227,14 @@ namespace osu.Game.Screens.Select.Carousel filtered.TriggerChange(); this.songSelect = songSelect; - this.carousel = carousel; info = item.Beatmap; } protected override bool OnClick(ClickEvent e) { - if(!filtered.Value) + if (!filtered.Value) { - carousel?.SelectBeatmap(info); + songSelect?.Carousel.SelectBeatmap(info); if (e.AltPressed) songSelect?.FinaliseSelection(); From ad0de2796427ee9025d01afe82fe062d9a0a2b8e Mon Sep 17 00:00:00 2001 From: voidedWarranties Date: Wed, 12 Feb 2020 22:11:26 -0800 Subject: [PATCH 09/72] Safer dependency injection and accessibility levels --- osu.Game/OsuGame.cs | 47 +++++++++++-------- .../Carousel/DrawableCarouselBeatmapSet.cs | 26 +++++----- osu.Game/Screens/Select/SongSelect.cs | 2 +- 3 files changed, 43 insertions(+), 32 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index ff3dee55af..3d6b93c87d 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -311,22 +311,12 @@ namespace osu.Game public void ShowBeatmap(int beatmapId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId)); /// - /// Present a beatmap at song select immediately. + /// Present a specific beatmap difficulty at song select immediately. /// The user should have already requested this interactively. /// /// The beatmap to select. - public void PresentBeatmap(BeatmapSetInfo beatmap) + public void PresentBeatmap(BeatmapInfo beatmap) { - var databasedSet = beatmap.OnlineBeatmapSetID != null - ? BeatmapManager.QueryBeatmapSet(s => s.OnlineBeatmapSetID == beatmap.OnlineBeatmapSetID) - : BeatmapManager.QueryBeatmapSet(s => s.Hash == beatmap.Hash); - - if (databasedSet == null) - { - Logger.Log("The requested beatmap could not be loaded.", LoggingTarget.Information); - return; - } - PerformFromScreen(screen => { // we might already be at song select, so a check is required before performing the load to solo. @@ -334,19 +324,36 @@ namespace osu.Game menuScreen.LoadToSolo(); // we might even already be at the song - if (Beatmap.Value.BeatmapSetInfo.Hash == databasedSet.Hash) - { + if (Beatmap.Value.BeatmapInfo.Hash == beatmap.Hash) return; - } - // Use first beatmap available for current ruleset, else switch ruleset. - var first = databasedSet.Beatmaps.Find(b => b.Ruleset.Equals(Ruleset.Value)) ?? databasedSet.Beatmaps.First(); - - Ruleset.Value = first.Ruleset; - Beatmap.Value = BeatmapManager.GetWorkingBeatmap(first); + Ruleset.Value = beatmap.Ruleset; + Beatmap.Value = BeatmapManager.GetWorkingBeatmap(beatmap); }, validScreens: new[] { typeof(PlaySongSelect) }); } + /// + /// + /// Instead of selecting a specific difficulty, this will select the first difficulty of the current ruleset in a beatmapset, + /// or the first difficulty of the set if there is none. + /// + /// The beatmapset to select. + public void PresentBeatmap(BeatmapSetInfo beatmapSet) + { + var databasedSet = beatmapSet.OnlineBeatmapSetID != null + ? BeatmapManager.QueryBeatmapSet(s => s.OnlineBeatmapSetID == beatmapSet.OnlineBeatmapSetID) + : BeatmapManager.QueryBeatmapSet(s => s.Hash == beatmapSet.Hash); + + if (databasedSet == null) + { + Logger.Log("The requested beatmap could not be loaded.", LoggingTarget.Information); + return; + } + + var first = databasedSet.Beatmaps.Find(b => b.Ruleset.Equals(Ruleset.Value)) ?? databasedSet.Beatmaps.First(); + PresentBeatmap(first); + } + /// /// Present a score's replay immediately. /// The user should have already requested this interactively. diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 80dae575ff..9e4f31b15b 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -34,8 +34,6 @@ namespace osu.Game.Screens.Select.Carousel private DialogOverlay dialogOverlay; private readonly BeatmapSetInfo beatmapSet; - private SongSelect songSelect; - public DrawableCarouselBeatmapSet(CarouselBeatmapSet set) : base(set) { @@ -43,11 +41,8 @@ namespace osu.Game.Screens.Select.Carousel } [BackgroundDependencyLoader(true)] - private void load(SongSelect songSelect, BeatmapManager manager, BeatmapSetOverlay beatmapOverlay, DialogOverlay overlay) + private void load(BeatmapManager manager, BeatmapSetOverlay beatmapOverlay, DialogOverlay overlay) { - if (songSelect != null) - this.songSelect = songSelect; - restoreHiddenRequested = s => s.Beatmaps.ForEach(manager.Restore); dialogOverlay = overlay; if (beatmapOverlay != null) @@ -123,7 +118,7 @@ namespace osu.Game.Screens.Select.Carousel return beatmaps.Count > maximum_difficulty_icons ? (IEnumerable)beatmaps.GroupBy(b => b.Beatmap.Ruleset).Select(group => new FilterableGroupedDifficultyIcon(group.ToList(), group.Key)) - : beatmaps.Select(b => new FilterableDifficultyIcon(b, songSelect)); + : beatmaps.Select(b => new FilterableDifficultyIcon(b)); } public MenuItem[] ContextMenuItems @@ -216,17 +211,17 @@ namespace osu.Game.Screens.Select.Carousel { private readonly BindableBool filtered = new BindableBool(); - private readonly SongSelect songSelect; + private OsuGame game; + private SongSelect songSelect; private readonly BeatmapInfo info; - public FilterableDifficultyIcon(CarouselBeatmap item, SongSelect songSelect) + public FilterableDifficultyIcon(CarouselBeatmap item) : base(item.Beatmap) { filtered.BindTo(item.Filtered); filtered.ValueChanged += isFiltered => Schedule(() => this.FadeTo(isFiltered.NewValue ? 0.1f : 1, 100)); filtered.TriggerChange(); - this.songSelect = songSelect; info = item.Beatmap; } @@ -234,7 +229,7 @@ namespace osu.Game.Screens.Select.Carousel { if (!filtered.Value) { - songSelect?.Carousel.SelectBeatmap(info); + game.PresentBeatmap(info); if (e.AltPressed) songSelect?.FinaliseSelection(); @@ -242,6 +237,15 @@ namespace osu.Game.Screens.Select.Carousel return base.OnClick(e); } + + [BackgroundDependencyLoader] + private void load(OsuGame game, SongSelect songSelect) + { + this.game = game; + + if (songSelect != null) + this.songSelect = songSelect; + } } public class FilterableGroupedDifficultyIcon : GroupedDifficultyIcon diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 463a17989a..5037081b5e 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -80,7 +80,7 @@ namespace osu.Game.Screens.Select protected override BackgroundScreen CreateBackground() => new BackgroundScreenBeatmap(Beatmap.Value); - public BeatmapCarousel Carousel { get; private set; } + protected BeatmapCarousel Carousel { get; private set; } private BeatmapInfoWedge beatmapInfoWedge; private DialogOverlay dialogOverlay; From b2fbeab7732437b8671c512fe69eabeb6deefb47 Mon Sep 17 00:00:00 2001 From: Maximilian Junges Date: Thu, 13 Feb 2020 14:07:14 +0100 Subject: [PATCH 10/72] simplify string formatting and fix color --- osu.Game/Graphics/DrawableDate.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game/Graphics/DrawableDate.cs b/osu.Game/Graphics/DrawableDate.cs index dcbea96071..8c520f4e10 100644 --- a/osu.Game/Graphics/DrawableDate.cs +++ b/osu.Game/Graphics/DrawableDate.cs @@ -126,10 +126,8 @@ namespace osu.Game.Graphics [BackgroundDependencyLoader] private void load(OsuColour colours) { - // Temporary colour since it's currently impossible to change it without bugs (see https://github.com/ppy/osu-framework/issues/3231) - // If above is fixed, this should use OverlayColourProvider - background.Colour = colours.Gray1; - timeText.Colour = colours.GreyCyanLighter; + background.Colour = colours.GreySeafoamDarker; + timeText.Colour = colours.BlueLighter; } protected override void PopIn() => this.FadeIn(200, Easing.OutQuint); @@ -140,8 +138,8 @@ namespace osu.Game.Graphics if (!(content is DateTimeOffset date)) return false; - dateText.Text = string.Format($"{date:d MMMM yyyy}") + " "; - timeText.Text = string.Format($"{date:hh:mm:ss \"UTC\"z}"); + dateText.Text = $"{date:d MMMM yyyy} "; + timeText.Text = $"{date:hh:mm:ss \"UTC\"z}"; return true; } From c871f07d2ef9f55d1c91f9ac6138fd2d162e7ed3 Mon Sep 17 00:00:00 2001 From: voidedWarranties Date: Thu, 13 Feb 2020 17:14:46 -0800 Subject: [PATCH 11/72] Use CarouselBeatmap action to select beatmap --- osu.Game/OsuGame.cs | 55 ++++++++----------- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 + .../Select/Carousel/CarouselBeatmap.cs | 5 ++ .../Carousel/DrawableCarouselBeatmapSet.cs | 23 +------- 4 files changed, 34 insertions(+), 51 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 3d6b93c87d..79616ef97c 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -311,38 +311,15 @@ namespace osu.Game public void ShowBeatmap(int beatmapId) => waitForReady(() => beatmapSetOverlay, _ => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId)); /// - /// Present a specific beatmap difficulty at song select immediately. + /// Present a beatmap at song select immediately. /// The user should have already requested this interactively. /// /// The beatmap to select. - public void PresentBeatmap(BeatmapInfo beatmap) + public void PresentBeatmap(BeatmapSetInfo beatmap) { - PerformFromScreen(screen => - { - // we might already be at song select, so a check is required before performing the load to solo. - if (screen is MainMenu) - menuScreen.LoadToSolo(); - - // we might even already be at the song - if (Beatmap.Value.BeatmapInfo.Hash == beatmap.Hash) - return; - - Ruleset.Value = beatmap.Ruleset; - Beatmap.Value = BeatmapManager.GetWorkingBeatmap(beatmap); - }, validScreens: new[] { typeof(PlaySongSelect) }); - } - - /// - /// - /// Instead of selecting a specific difficulty, this will select the first difficulty of the current ruleset in a beatmapset, - /// or the first difficulty of the set if there is none. - /// - /// The beatmapset to select. - public void PresentBeatmap(BeatmapSetInfo beatmapSet) - { - var databasedSet = beatmapSet.OnlineBeatmapSetID != null - ? BeatmapManager.QueryBeatmapSet(s => s.OnlineBeatmapSetID == beatmapSet.OnlineBeatmapSetID) - : BeatmapManager.QueryBeatmapSet(s => s.Hash == beatmapSet.Hash); + var databasedSet = beatmap.OnlineBeatmapSetID != null + ? BeatmapManager.QueryBeatmapSet(s => s.OnlineBeatmapSetID == beatmap.OnlineBeatmapSetID) + : BeatmapManager.QueryBeatmapSet(s => s.Hash == beatmap.Hash); if (databasedSet == null) { @@ -350,8 +327,24 @@ namespace osu.Game return; } - var first = databasedSet.Beatmaps.Find(b => b.Ruleset.Equals(Ruleset.Value)) ?? databasedSet.Beatmaps.First(); - PresentBeatmap(first); + PerformFromScreen(screen => + { + // we might already be at song select, so a check is required before performing the load to solo. + if (screen is MainMenu) + menuScreen.LoadToSolo(); + + // we might even already be at the song + if (Beatmap.Value.BeatmapSetInfo.Hash == databasedSet.Hash) + { + return; + } + + // Use first beatmap available for current ruleset, else switch ruleset. + var first = databasedSet.Beatmaps.Find(b => b.Ruleset.Equals(Ruleset.Value)) ?? databasedSet.Beatmaps.First(); + + Ruleset.Value = first.Ruleset; + Beatmap.Value = BeatmapManager.GetWorkingBeatmap(first); + }, validScreens: new[] { typeof(PlaySongSelect) }); } /// @@ -453,7 +446,7 @@ namespace osu.Game /// /// The action to perform once we are in the correct state. /// An optional collection of valid screen types. If any of these screens are already current we can perform the action immediately, else the first valid parent will be made current before performing the action. is used if not specified. - protected void PerformFromScreen(Action action, IEnumerable validScreens = null) + public void PerformFromScreen(Action action, IEnumerable validScreens = null) { performFromMainMenuTask?.Cancel(); diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 592e26adc2..f6e0e6bf70 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -592,6 +592,8 @@ namespace osu.Game.Screens.Select scrollPositionCache.Invalidate(); } }; + + c.Select = () => SelectBeatmap(c.Beatmap); } return set; diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 2ffb73f226..116053b4f2 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -13,6 +13,11 @@ namespace osu.Game.Screens.Select.Carousel { public readonly BeatmapInfo Beatmap; + /// + /// Select this beatmap on the carousel. + /// + public Action Select; + public CarouselBeatmap(BeatmapInfo beatmap) { Beatmap = beatmap; diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 9e4f31b15b..5ef0e8a018 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -211,9 +211,7 @@ namespace osu.Game.Screens.Select.Carousel { private readonly BindableBool filtered = new BindableBool(); - private OsuGame game; - private SongSelect songSelect; - private readonly BeatmapInfo info; + private readonly Action select; public FilterableDifficultyIcon(CarouselBeatmap item) : base(item.Beatmap) @@ -222,30 +220,15 @@ namespace osu.Game.Screens.Select.Carousel filtered.ValueChanged += isFiltered => Schedule(() => this.FadeTo(isFiltered.NewValue ? 0.1f : 1, 100)); filtered.TriggerChange(); - info = item.Beatmap; + select = item.Select; } protected override bool OnClick(ClickEvent e) { - if (!filtered.Value) - { - game.PresentBeatmap(info); - - if (e.AltPressed) - songSelect?.FinaliseSelection(); - } + select?.Invoke(); return base.OnClick(e); } - - [BackgroundDependencyLoader] - private void load(OsuGame game, SongSelect songSelect) - { - this.game = game; - - if (songSelect != null) - this.songSelect = songSelect; - } } public class FilterableGroupedDifficultyIcon : GroupedDifficultyIcon From 368e6f9579492d6321c89850cf4fe114a0337c83 Mon Sep 17 00:00:00 2001 From: voidedWarranties Date: Thu, 13 Feb 2020 17:47:16 -0800 Subject: [PATCH 12/72] Use CarouselBeatmap.State to select --- osu.Game/OsuGame.cs | 2 +- osu.Game/Screens/Select/BeatmapCarousel.cs | 2 -- osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs | 5 ----- .../Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs | 8 ++++---- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs index 79616ef97c..ff3dee55af 100644 --- a/osu.Game/OsuGame.cs +++ b/osu.Game/OsuGame.cs @@ -446,7 +446,7 @@ namespace osu.Game /// /// The action to perform once we are in the correct state. /// An optional collection of valid screen types. If any of these screens are already current we can perform the action immediately, else the first valid parent will be made current before performing the action. is used if not specified. - public void PerformFromScreen(Action action, IEnumerable validScreens = null) + protected void PerformFromScreen(Action action, IEnumerable validScreens = null) { performFromMainMenuTask?.Cancel(); diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index f6e0e6bf70..592e26adc2 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -592,8 +592,6 @@ namespace osu.Game.Screens.Select scrollPositionCache.Invalidate(); } }; - - c.Select = () => SelectBeatmap(c.Beatmap); } return set; diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index 116053b4f2..2ffb73f226 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -13,11 +13,6 @@ namespace osu.Game.Screens.Select.Carousel { public readonly BeatmapInfo Beatmap; - /// - /// Select this beatmap on the carousel. - /// - public Action Select; - public CarouselBeatmap(BeatmapInfo beatmap) { Beatmap = beatmap; diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 5ef0e8a018..572580f7c1 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -211,7 +211,7 @@ namespace osu.Game.Screens.Select.Carousel { private readonly BindableBool filtered = new BindableBool(); - private readonly Action select; + private readonly CarouselBeatmap item; public FilterableDifficultyIcon(CarouselBeatmap item) : base(item.Beatmap) @@ -220,14 +220,14 @@ namespace osu.Game.Screens.Select.Carousel filtered.ValueChanged += isFiltered => Schedule(() => this.FadeTo(isFiltered.NewValue ? 0.1f : 1, 100)); filtered.TriggerChange(); - select = item.Select; + this.item = item; } protected override bool OnClick(ClickEvent e) { - select?.Invoke(); + item.State.Value = CarouselItemState.Selected; - return base.OnClick(e); + return true; } } From 8e1ecddb1dbd05a81b71ef14f513bdd733fd2807 Mon Sep 17 00:00:00 2001 From: voidedWarranties Date: Fri, 14 Feb 2020 17:23:24 -0800 Subject: [PATCH 13/72] Add testing --- .../SongSelect/TestScenePlaySongSelect.cs | 40 +++++++++++++++++++ .../Carousel/DrawableCarouselBeatmapSet.cs | 7 ++-- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 80192b9ebc..2b6d7cce58 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -463,6 +463,46 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("Selected beatmap has not changed", () => songSelect.Carousel.SelectedBeatmap.ID == previousID); } + [Test] + public void TestDifficultyIconSelecting() + { + int? previousID = null; + addRulesetImportStep(0); + createSongSelect(); + + AddStep("Store current ID", () => previousID = songSelect.Carousel.SelectedBeatmap.ID); + AddStep("Click on a difficulty", () => + { + InputManager.MoveMouseTo(songSelect.Carousel.ChildrenOfType() + .First(icon => icon.Item.Beatmap != songSelect.Carousel.SelectedBeatmap)); + + InputManager.PressButton(MouseButton.Left); + InputManager.ReleaseButton(MouseButton.Left); + }); + AddAssert("Selected beatmap changed", () => songSelect.Carousel.SelectedBeatmap.ID != previousID); + + AddStep("Filter some difficulties", () => songSelect.Carousel.Filter(new FilterCriteria + { + BPM = new FilterCriteria.OptionalRange + { + Min = songSelect.Carousel.SelectedBeatmapSet.MaxBPM, + IsLowerInclusive = true + } + })); + AddUntilStep("Wait for filter", () => songSelect.Carousel.ChildrenOfType().Any(icon => icon.Item.Filtered.Value)); + + AddStep("Store current ID", () => previousID = songSelect.Carousel.SelectedBeatmap.ID); + AddStep("Click on a filtered difficulty", () => + { + InputManager.MoveMouseTo(songSelect.Carousel.ChildrenOfType() + .First(icon => icon.Item.Filtered.Value)); + + InputManager.PressButton(MouseButton.Left); + InputManager.ReleaseButton(MouseButton.Left); + }); + AddAssert("Selected beatmap has not changed", () => songSelect.Carousel.SelectedBeatmap.ID == previousID); + } + private void addRulesetImportStep(int id) => AddStep($"import test map for ruleset {id}", () => importForRuleset(id)); private void importForRuleset(int id) => manager.Import(createTestBeatmapSet(getImportId(), rulesets.AvailableRulesets.Where(r => r.ID == id).ToArray())).Wait(); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 572580f7c1..4b98c4eeb2 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -211,7 +211,7 @@ namespace osu.Game.Screens.Select.Carousel { private readonly BindableBool filtered = new BindableBool(); - private readonly CarouselBeatmap item; + public readonly CarouselBeatmap Item; public FilterableDifficultyIcon(CarouselBeatmap item) : base(item.Beatmap) @@ -220,12 +220,13 @@ namespace osu.Game.Screens.Select.Carousel filtered.ValueChanged += isFiltered => Schedule(() => this.FadeTo(isFiltered.NewValue ? 0.1f : 1, 100)); filtered.TriggerChange(); - this.item = item; + Item = item; } protected override bool OnClick(ClickEvent e) { - item.State.Value = CarouselItemState.Selected; + if (!filtered.Value) + Item.State.Value = CarouselItemState.Selected; return true; } From 8c81f1e684ce4e4b32531f8fb4807b6cc087f002 Mon Sep 17 00:00:00 2001 From: voidedWarranties Date: Sat, 15 Feb 2020 17:51:55 -0800 Subject: [PATCH 14/72] Move CarouselBeatmap access to private, test using indices --- .../SongSelect/TestScenePlaySongSelect.cs | 44 +++++++++++++++---- .../Carousel/DrawableCarouselBeatmapSet.cs | 6 +-- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs index 2b6d7cce58..369ae346dc 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestScenePlaySongSelect.cs @@ -466,36 +466,53 @@ namespace osu.Game.Tests.Visual.SongSelect [Test] public void TestDifficultyIconSelecting() { - int? previousID = null; addRulesetImportStep(0); createSongSelect(); - AddStep("Store current ID", () => previousID = songSelect.Carousel.SelectedBeatmap.ID); + DrawableCarouselBeatmapSet set = null; + AddStep("Find the DrawableCarouselBeatmapSet", () => + { + set = songSelect.Carousel.ChildrenOfType().First(); + }); + + DrawableCarouselBeatmapSet.FilterableDifficultyIcon difficultyIcon = null; + AddStep("Find an icon", () => + { + difficultyIcon = set.ChildrenOfType() + .First(icon => getDifficultyIconIndex(set, icon) != getCurrentBeatmapIndex()); + }); AddStep("Click on a difficulty", () => { - InputManager.MoveMouseTo(songSelect.Carousel.ChildrenOfType() - .First(icon => icon.Item.Beatmap != songSelect.Carousel.SelectedBeatmap)); + InputManager.MoveMouseTo(difficultyIcon); InputManager.PressButton(MouseButton.Left); InputManager.ReleaseButton(MouseButton.Left); }); - AddAssert("Selected beatmap changed", () => songSelect.Carousel.SelectedBeatmap.ID != previousID); + AddAssert("Selected beatmap correct", () => getCurrentBeatmapIndex() == getDifficultyIconIndex(set, difficultyIcon)); + double? maxBPM = null; AddStep("Filter some difficulties", () => songSelect.Carousel.Filter(new FilterCriteria { BPM = new FilterCriteria.OptionalRange { - Min = songSelect.Carousel.SelectedBeatmapSet.MaxBPM, + Min = maxBPM = songSelect.Carousel.SelectedBeatmapSet.MaxBPM, IsLowerInclusive = true } })); - AddUntilStep("Wait for filter", () => songSelect.Carousel.ChildrenOfType().Any(icon => icon.Item.Filtered.Value)); + DrawableCarouselBeatmapSet.FilterableDifficultyIcon filteredIcon = null; + AddStep("Get filtered icon", () => + { + var filteredBeatmap = songSelect.Carousel.SelectedBeatmapSet.Beatmaps.Find(b => b.BPM < maxBPM); + int filteredBeatmapIndex = getBeatmapIndex(filteredBeatmap.BeatmapSet, filteredBeatmap); + filteredIcon = set.ChildrenOfType().ElementAt(filteredBeatmapIndex); + }); + + int? previousID = null; AddStep("Store current ID", () => previousID = songSelect.Carousel.SelectedBeatmap.ID); AddStep("Click on a filtered difficulty", () => { - InputManager.MoveMouseTo(songSelect.Carousel.ChildrenOfType() - .First(icon => icon.Item.Filtered.Value)); + InputManager.MoveMouseTo(filteredIcon); InputManager.PressButton(MouseButton.Left); InputManager.ReleaseButton(MouseButton.Left); @@ -503,6 +520,15 @@ namespace osu.Game.Tests.Visual.SongSelect AddAssert("Selected beatmap has not changed", () => songSelect.Carousel.SelectedBeatmap.ID == previousID); } + private int getBeatmapIndex(BeatmapSetInfo set, BeatmapInfo info) => set.Beatmaps.FindIndex(b => b == info); + + private int getCurrentBeatmapIndex() => getBeatmapIndex(songSelect.Carousel.SelectedBeatmapSet, songSelect.Carousel.SelectedBeatmap); + + private int getDifficultyIconIndex(DrawableCarouselBeatmapSet set, DrawableCarouselBeatmapSet.FilterableDifficultyIcon icon) + { + return set.ChildrenOfType().ToList().FindIndex(i => i == icon); + } + private void addRulesetImportStep(int id) => AddStep($"import test map for ruleset {id}", () => importForRuleset(id)); private void importForRuleset(int id) => manager.Import(createTestBeatmapSet(getImportId(), rulesets.AvailableRulesets.Where(r => r.ID == id).ToArray())).Wait(); diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs index 4b98c4eeb2..3d958dc67f 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmapSet.cs @@ -211,7 +211,7 @@ namespace osu.Game.Screens.Select.Carousel { private readonly BindableBool filtered = new BindableBool(); - public readonly CarouselBeatmap Item; + private readonly CarouselBeatmap item; public FilterableDifficultyIcon(CarouselBeatmap item) : base(item.Beatmap) @@ -220,13 +220,13 @@ namespace osu.Game.Screens.Select.Carousel filtered.ValueChanged += isFiltered => Schedule(() => this.FadeTo(isFiltered.NewValue ? 0.1f : 1, 100)); filtered.TriggerChange(); - Item = item; + this.item = item; } protected override bool OnClick(ClickEvent e) { if (!filtered.Value) - Item.State.Value = CarouselItemState.Selected; + item.State.Value = CarouselItemState.Selected; return true; } From dd5e713c0c109a387307925aba91764c8f389282 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Sun, 16 Feb 2020 21:42:05 +0100 Subject: [PATCH 15/72] Adjust colours --- osu.Game/Beatmaps/Drawables/UpdateableBeatmapSetCover.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapSetCover.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapSetCover.cs index 16eecb7198..182ab055b3 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapSetCover.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapSetCover.cs @@ -50,7 +50,7 @@ namespace osu.Game.Beatmaps.Drawables Child = new Box { RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(OsuColour.Gray(0.2f), OsuColour.Gray(0.1f)), + Colour = OsuColour.Gray(0.2f), }; } From 8fcd5e93dd56db9116fd90cac4e8b2aa662e3375 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Sun, 16 Feb 2020 21:43:11 +0100 Subject: [PATCH 16/72] Adjust table layout to match osu-web --- .../Overlays/BeatmapSet/Scores/ScoreTable.cs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 43a45bd2fc..99b3870bc1 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// 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.Graphics; @@ -77,17 +77,20 @@ namespace osu.Game.Overlays.BeatmapSet.Scores new TableColumn("rank", Anchor.CentreRight, new Dimension(GridSizeMode.AutoSize)), new TableColumn("", Anchor.Centre, new Dimension(GridSizeMode.Absolute, 70)), // grade new TableColumn("score", Anchor.CentreLeft, new Dimension(GridSizeMode.AutoSize)), - new TableColumn("accuracy", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 60, maxSize: 70)), - new TableColumn("player", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 150)), - new TableColumn("max combo", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 70, maxSize: 110)) + new TableColumn("accuracy", Anchor.CentreLeft, new Dimension(GridSizeMode.Absolute, minSize: 60, maxSize: 70)), + new TableColumn("", Anchor.CentreLeft, new Dimension(GridSizeMode.Absolute, 25)), // flag + new TableColumn("player", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 125)), + new TableColumn("max combo", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 70, maxSize: 120)) }; - foreach (var statistic in score.SortedStatistics) - columns.Add(new TableColumn(statistic.Key.GetDescription(), Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70))); + foreach (var statistic in score.SortedStatistics.Take(score.SortedStatistics.Count() - 1)) + columns.Add(new TableColumn(statistic.Key.GetDescription(), Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 35, maxSize: 60))); + + columns.Add(new TableColumn(score.SortedStatistics.LastOrDefault().Key.GetDescription(), Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 45, maxSize: 95))); columns.AddRange(new[] { - new TableColumn("pp", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 40, maxSize: 70)), + new TableColumn("pp", Anchor.CentreLeft, new Dimension(GridSizeMode.Absolute, 30)), new TableColumn("mods", Anchor.CentreLeft, new Dimension(GridSizeMode.AutoSize)), }); From 4d180a685a1070e3dc4ada778a3bf675208030e6 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Sun, 16 Feb 2020 21:43:33 +0100 Subject: [PATCH 17/72] Adjust font sizes and spacing in BeatmapSetOverlay --- osu.Game/Overlays/BeatmapSet/AuthorInfo.cs | 8 ++-- osu.Game/Overlays/BeatmapSet/BasicStats.cs | 11 +++--- osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 38 +++++++++++-------- .../Buttons/HeaderDownloadButton.cs | 13 ++++--- osu.Game/Overlays/BeatmapSet/Details.cs | 2 +- osu.Game/Overlays/BeatmapSet/Header.cs | 7 +++- osu.Game/Overlays/BeatmapSet/Info.cs | 10 +++-- .../BeatmapSet/LeaderboardScopeSelector.cs | 1 - .../BeatmapSet/Scores/DrawableTopScore.cs | 4 +- .../Scores/NotSupporterPlaceholder.cs | 6 +-- .../Overlays/BeatmapSet/Scores/ScoreTable.cs | 38 ++++++------------- .../Scores/ScoreTableRowBackground.cs | 4 +- .../BeatmapSet/Scores/ScoresContainer.cs | 6 +-- .../Scores/TopScoreStatisticsSection.cs | 22 ++++++----- .../BeatmapSet/Scores/TopScoreUserSection.cs | 2 +- osu.Game/Overlays/BeatmapSet/SuccessRate.cs | 6 +-- .../Screens/Select/Details/AdvancedStats.cs | 8 ++-- .../Screens/Select/Details/UserRatings.cs | 13 ++++--- 18 files changed, 102 insertions(+), 97 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs index 096e91b65b..a6ff0ebeb8 100644 --- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs +++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs @@ -76,7 +76,7 @@ namespace osu.Game.Overlays.BeatmapSet new Container { AutoSizeAxes = Axes.Both, - CornerRadius = 3, + CornerRadius = 4, Masking = true, Child = avatar = new UpdateableAvatar { @@ -87,7 +87,7 @@ namespace osu.Game.Overlays.BeatmapSet { Colour = Color4.Black.Opacity(0.25f), Type = EdgeEffectType.Shadow, - Radius = 3, + Radius = 4, Offset = new Vector2(0f, 1f), }, }, @@ -117,12 +117,12 @@ namespace osu.Game.Overlays.BeatmapSet new OsuSpriteText { Text = $"{first} ", - Font = OsuFont.GetFont(size: 13) + Font = OsuFont.GetFont(size: 11) }, new OsuSpriteText { Text = second, - Font = secondFont.With(size: 13) + Font = secondFont.With(size: 11) }, }; } diff --git a/osu.Game/Overlays/BeatmapSet/BasicStats.cs b/osu.Game/Overlays/BeatmapSet/BasicStats.cs index 7092b860a0..ba0a62ec2f 100644 --- a/osu.Game/Overlays/BeatmapSet/BasicStats.cs +++ b/osu.Game/Overlays/BeatmapSet/BasicStats.cs @@ -105,7 +105,7 @@ namespace osu.Game.Overlays.BeatmapSet { TooltipText = name; RelativeSizeAxes = Axes.X; - AutoSizeAxes = Axes.Y; + Height = 24f; Children = new Drawable[] { @@ -113,7 +113,8 @@ namespace osu.Game.Overlays.BeatmapSet { Anchor = Anchor.Centre, Origin = Anchor.Centre, - AutoSizeAxes = Axes.Both, + AutoSizeAxes = Axes.X, + RelativeSizeAxes = Axes.Y, Children = new Drawable[] { new SpriteIcon @@ -121,7 +122,7 @@ namespace osu.Game.Overlays.BeatmapSet Anchor = Anchor.CentreLeft, Origin = Anchor.Centre, Icon = FontAwesome.Solid.Square, - Size = new Vector2(13), + Size = new Vector2(12), Rotation = 45, Colour = OsuColour.FromHex(@"441288"), }, @@ -130,7 +131,7 @@ namespace osu.Game.Overlays.BeatmapSet Anchor = Anchor.CentreLeft, Origin = Anchor.Centre, Icon = icon, - Size = new Vector2(13), + Size = new Vector2(12), Colour = OsuColour.FromHex(@"f7dd55"), Scale = new Vector2(0.8f), }, @@ -139,7 +140,7 @@ namespace osu.Game.Overlays.BeatmapSet Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Margin = new MarginPadding { Left = 10 }, - Font = OsuFont.GetFont(size: 13, weight: FontWeight.Bold), + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), }, }, }, diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index bf2a92cd4f..265e2d32f9 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -34,7 +34,6 @@ namespace osu.Game.Overlays.BeatmapSet public readonly DifficultiesContainer Difficulties; public readonly Bindable Beatmap = new Bindable(); - private BeatmapSetInfo beatmapSet; public BeatmapSetInfo BeatmapSet @@ -67,7 +66,7 @@ namespace osu.Game.Overlays.BeatmapSet { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Left = -(tile_icon_padding + tile_spacing / 2) }, + Margin = new MarginPadding { Left = -(tile_icon_padding + tile_spacing / 2), Bottom = 10 }, OnLostHover = () => { showBeatmap(Beatmap.Value); @@ -77,7 +76,6 @@ namespace osu.Game.Overlays.BeatmapSet new FillFlowContainer { AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Top = 10 }, Spacing = new Vector2(5f), Children = new[] { @@ -85,13 +83,13 @@ namespace osu.Game.Overlays.BeatmapSet { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Font = OsuFont.GetFont(size: 20, weight: FontWeight.Bold) + Font = OsuFont.GetFont(size: 17, weight: FontWeight.Bold) }, starRating = new OsuSpriteText { Anchor = Anchor.BottomLeft, Origin = Anchor.BottomLeft, - Font = OsuFont.GetFont(size: 13, weight: FontWeight.Bold), + Font = OsuFont.GetFont(size: 11, weight: FontWeight.Bold), Text = "Star Difficulty", Alpha = 0, Margin = new MarginPadding { Bottom = 1 }, @@ -192,9 +190,11 @@ namespace osu.Game.Overlays.BeatmapSet public class DifficultySelectorButton : OsuClickableContainer, IStateful { private const float transition_duration = 100; - private const float size = 52; + private const float size = 54; + private const float background_size = size - 2; - private readonly Container bg; + private readonly Container background; + private readonly Box backgroundBox; private readonly DifficultyIcon icon; public readonly BeatmapInfo Beatmap; @@ -230,16 +230,16 @@ namespace osu.Game.Overlays.BeatmapSet Children = new Drawable[] { - bg = new Container + background = new Container { - RelativeSizeAxes = Axes.Both, + Size = new Vector2(background_size), Masking = true, CornerRadius = 4, - Child = new Box + Child = backgroundBox = new Box { RelativeSizeAxes = Axes.Both, - Colour = Color4.Black.Opacity(0.5f), - }, + Alpha = 0.5f + } }, icon = new DifficultyIcon(beatmap, shouldShowTooltip: false) { @@ -273,15 +273,21 @@ namespace osu.Game.Overlays.BeatmapSet private void fadeIn() { - bg.FadeIn(transition_duration); + background.FadeIn(transition_duration); icon.FadeIn(transition_duration); } private void fadeOut() { - bg.FadeOut(); + background.FadeOut(); icon.FadeTo(0.7f, transition_duration); } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + backgroundBox.Colour = colourProvider.Background6; + } } private class Statistic : FillFlowContainer @@ -314,13 +320,13 @@ namespace osu.Game.Overlays.BeatmapSet Origin = Anchor.CentreLeft, Icon = icon, Shadow = true, - Size = new Vector2(13), + Size = new Vector2(12), }, text = new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold, italics: true) + Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold, italics: true), }, }; } diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs index 53003b0488..e64256b850 100644 --- a/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs +++ b/osu.Game/Overlays/BeatmapSet/Buttons/HeaderDownloadButton.cs @@ -22,6 +22,8 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons { public class HeaderDownloadButton : BeatmapDownloadTrackingComposite, IHasTooltip { + private const int text_size = 12; + private readonly bool noVideo; public string TooltipText => button.Enabled.Value ? "download this beatmap" : "login to download"; @@ -80,8 +82,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons Anchor = Anchor.CentreRight, Origin = Anchor.CentreRight, Icon = FontAwesome.Solid.Download, - Size = new Vector2(16), - Margin = new MarginPadding { Right = 5 }, + Size = new Vector2(18), }, } }, @@ -120,7 +121,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons new OsuSpriteText { Text = "Downloading...", - Font = OsuFont.GetFont(size: 13, weight: FontWeight.Bold) + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) }, }; break; @@ -131,7 +132,7 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons new OsuSpriteText { Text = "Importing...", - Font = OsuFont.GetFont(size: 13, weight: FontWeight.Bold) + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) }, }; break; @@ -146,12 +147,12 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons new OsuSpriteText { Text = "Download", - Font = OsuFont.GetFont(size: 13, weight: FontWeight.Bold) + Font = OsuFont.GetFont(size: text_size, weight: FontWeight.Bold) }, new OsuSpriteText { Text = getVideoSuffixText(), - Font = OsuFont.GetFont(size: 11, weight: FontWeight.Bold) + Font = OsuFont.GetFont(size: text_size - 2, weight: FontWeight.Bold) }, }; this.FadeIn(200); diff --git a/osu.Game/Overlays/BeatmapSet/Details.cs b/osu.Game/Overlays/BeatmapSet/Details.cs index 488e181fa2..680487ffbb 100644 --- a/osu.Game/Overlays/BeatmapSet/Details.cs +++ b/osu.Game/Overlays/BeatmapSet/Details.cs @@ -74,7 +74,7 @@ namespace osu.Game.Overlays.BeatmapSet { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Vertical = 10 }, + Padding = new MarginPadding { Vertical = 10 } }, }, new DetailBox diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs index 29f09a1ad8..c1e9ce2008 100644 --- a/osu.Game/Overlays/BeatmapSet/Header.cs +++ b/osu.Game/Overlays/BeatmapSet/Header.cs @@ -144,12 +144,15 @@ namespace osu.Game.Overlays.BeatmapSet }, } }, - artist = new OsuSpriteText { Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium, italics: true) }, + artist = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium, italics: true), + Margin = new MarginPadding { Bottom = 20 } + }, new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Margin = new MarginPadding { Top = 20 }, Child = author = new AuthorInfo(), }, beatmapAvailability = new BeatmapAvailability(), diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs index 85e871baca..0f2d6a9e35 100644 --- a/osu.Game/Overlays/BeatmapSet/Info.cs +++ b/osu.Game/Overlays/BeatmapSet/Info.cs @@ -20,8 +20,9 @@ namespace osu.Game.Overlays.BeatmapSet public class Info : Container { private const float transition_duration = 250; - private const float metadata_width = 225; + private const float metadata_width = 175; private const float spacing = 20; + private const float base_height = 220; private readonly Box successRateBackground; private readonly Box background; @@ -41,7 +42,7 @@ namespace osu.Game.Overlays.BeatmapSet OsuSpriteText unrankedPlaceholder; RelativeSizeAxes = Axes.X; - Height = 220; + Height = base_height; Masking = true; EdgeEffect = new EdgeEffectParameters { @@ -135,6 +136,7 @@ namespace osu.Game.Overlays.BeatmapSet var setHasLeaderboard = b.NewValue?.OnlineInfo?.Status > 0; successRate.Alpha = setHasLeaderboard ? 1 : 0; unrankedPlaceholder.Alpha = setHasLeaderboard ? 0 : 1; + Height = setHasLeaderboard ? 270 : base_height; }; } @@ -176,8 +178,8 @@ namespace osu.Game.Overlays.BeatmapSet new OsuSpriteText { Text = title, - Font = OsuFont.GetFont(size: 14, weight: FontWeight.Black), - Margin = new MarginPadding { Top = 20 }, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), + Margin = new MarginPadding { Top = 15 }, }, textFlow = new OsuTextFlowContainer { diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs index 20a3b09db4..48062ef3f0 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs @@ -37,7 +37,6 @@ namespace osu.Game.Overlays.BeatmapSet public ScopeSelectorTabItem(BeatmapLeaderboardScope value) : base(value) { - Text.Font = OsuFont.GetFont(size: 16); } protected override bool OnHover(HoverEvent e) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index bb85b4a37b..382155117e 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores AutoSizeAxes = Axes.Y; Masking = true; - CornerRadius = 5; + CornerRadius = 4; EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, @@ -46,7 +46,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Vertical = 10, Left = 10, - Right = 25, + Right = 30, }, Children = new Drawable[] { diff --git a/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs b/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs index ba08a78a61..b2c87a1477 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/NotSupporterPlaceholder.cs @@ -21,7 +21,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { AutoSizeAxes = Axes.Both, Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 10), + Spacing = new Vector2(0, 20), Children = new Drawable[] { new OsuSpriteText @@ -29,9 +29,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = @"You need to be an osu!supporter to access the friend and country rankings!", - Font = OsuFont.GetFont(weight: FontWeight.Bold), + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold), }, - text = new LinkFlowContainer(t => t.Font = t.Font.With(size: 12)) + text = new LinkFlowContainer(t => t.Font = t.Font.With(size: 11)) { Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 99b3870bc1..9c886dfa75 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -1,4 +1,4 @@ -// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// 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.Graphics; @@ -22,7 +22,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public class ScoreTable : TableContainer { private const float horizontal_inset = 20; - private const float row_height = 25; + private const float row_height = 22; private const int text_size = 12; private readonly FillFlowContainer backgroundFlow; @@ -63,7 +63,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores return; for (int i = 0; i < value.Count; i++) - backgroundFlow.Add(new ScoreTableRowBackground(i, value[i])); + backgroundFlow.Add(new ScoreTableRowBackground(i, value[i], row_height)); Columns = createHeaders(value[0]); Content = value.Select((s, i) => createContent(i, s)).ToArray().ToRectangular(); @@ -99,6 +99,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private Drawable[] createContent(int index, ScoreInfo score) { + var username = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: text_size)) { AutoSizeAxes = Axes.Both }; + username.AddUserLink(score.User); + var content = new List { new OsuSpriteText @@ -108,7 +111,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }, new UpdateableRank(score.Rank) { - Size = new Vector2(30, 20) + Size = new Vector2(28, 14) }, new OsuSpriteText { @@ -123,35 +126,18 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Font = OsuFont.GetFont(size: text_size), Colour = score.Accuracy == 1 ? highAccuracyColour : Color4.White }, - }; - - var username = new LinkFlowContainer(t => t.Font = OsuFont.GetFont(size: text_size)) { AutoSizeAxes = Axes.Both }; - username.AddUserLink(score.User); - - content.AddRange(new Drawable[] - { - new FillFlowContainer + new UpdateableFlag(score.User.Country) { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Margin = new MarginPadding { Right = horizontal_inset }, - Spacing = new Vector2(5, 0), - Children = new Drawable[] - { - new UpdateableFlag(score.User.Country) - { - Size = new Vector2(20, 13), - ShowPlaceholderOnNull = false, - }, - username - } + Size = new Vector2(19, 13), + ShowPlaceholderOnNull = false, }, + username, new OsuSpriteText { Text = $@"{score.MaxCombo:N0}x", Font = OsuFont.GetFont(size: text_size) } - }); + }; foreach (var kvp in score.SortedStatistics) { diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs index 83271efe09..d84e1eff8c 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTableRowBackground.cs @@ -22,13 +22,13 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private readonly int index; private readonly ScoreInfo score; - public ScoreTableRowBackground(int index, ScoreInfo score) + public ScoreTableRowBackground(int index, ScoreInfo score, float height) { this.index = index; this.score = score; RelativeSizeAxes = Axes.X; - Height = 25; + Height = height; CornerRadius = 5; Masking = true; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 8560232209..3cb77c6450 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -90,9 +90,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.TopCentre, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Width = 0.95f, Direction = FillDirection.Vertical, - Margin = new MarginPadding { Vertical = spacing }, + Padding = new MarginPadding { Horizontal = 50 }, + Margin = new MarginPadding { Vertical = 20 }, Children = new Drawable[] { new FillFlowContainer @@ -121,7 +121,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, - Margin = new MarginPadding { Vertical = spacing }, + Margin = new MarginPadding { Top = spacing }, Children = new Drawable[] { noScoresPlaceholder = new NoScoresPlaceholder diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs index a7066c4827..a15dc57d23 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs @@ -27,7 +27,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores private const float bottom_columns_min_width = 45; private readonly FontUsage smallFont = OsuFont.GetFont(size: 16); - private readonly FontUsage largeFont = OsuFont.GetFont(size: 22); + private readonly FontUsage largeFont = OsuFont.GetFont(size: 22, weight: FontWeight.Light); private readonly TextColumn totalScoreColumn; private readonly TextColumn accuracyColumn; @@ -47,7 +47,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Direction = FillDirection.Vertical, - Spacing = new Vector2(10, 8), Children = new Drawable[] { new FillFlowContainer @@ -117,6 +116,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public InfoColumn(string title, Drawable content, float? minWidth = null) { AutoSizeAxes = Axes.Both; + Margin = new MarginPadding { Vertical = 5 }; InternalChild = new GridContainer { @@ -128,7 +128,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.Absolute, 4), + new Dimension(GridSizeMode.Absolute, 2), new Dimension(GridSizeMode.AutoSize) }, Content = new[] @@ -138,21 +138,24 @@ namespace osu.Game.Overlays.BeatmapSet.Scores text = new OsuSpriteText { Font = OsuFont.GetFont(size: 10, weight: FontWeight.Bold), - Text = title.ToUpper() + Text = title.ToUpper(), + // 2px padding bottom + 1px vertical to compensate for the additional spacing because of 1.25 line-height in osu-web + Padding = new MarginPadding { Top = 1, Bottom = 3 } } }, new Drawable[] { separator = new Box { - Anchor = Anchor.CentreLeft, + Anchor = Anchor.TopLeft, RelativeSizeAxes = Axes.X, - Height = 2 - } + Height = 2, + }, }, new[] { - content + // osu-web has 4px margin here but also uses 0.9 line-height, reducing margin to 2px seems like a good alternative to that + content.With(c => c.Margin = new MarginPadding { Top = 2 }) } } }; @@ -194,9 +197,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores public ModsInfoColumn() : this(new FillFlowContainer { - AutoSizeAxes = Axes.Both, + AutoSizeAxes = Axes.X, Direction = FillDirection.Horizontal, Spacing = new Vector2(1), + Height = 18f }) { } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index 8a368aa535..4e253018c3 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -67,7 +67,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores Origin = Anchor.Centre, Size = new Vector2(70), Masking = true, - CornerRadius = 5, + CornerRadius = 4, EdgeEffect = new EdgeEffectParameters { Type = EdgeEffectType.Shadow, diff --git a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs index 15216b6e69..3bb36545cd 100644 --- a/osu.Game/Overlays/BeatmapSet/SuccessRate.cs +++ b/osu.Game/Overlays/BeatmapSet/SuccessRate.cs @@ -65,7 +65,7 @@ namespace osu.Game.Overlays.BeatmapSet Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "Success Rate", - Font = OsuFont.GetFont(size: 13) + Font = OsuFont.GetFont(size: 12) }, successRate = new Bar { @@ -82,7 +82,7 @@ namespace osu.Game.Overlays.BeatmapSet { Anchor = Anchor.TopRight, Origin = Anchor.TopCentre, - Font = OsuFont.GetFont(size: 13), + Font = OsuFont.GetFont(size: 12), }, }, new OsuSpriteText @@ -90,7 +90,7 @@ namespace osu.Game.Overlays.BeatmapSet Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "Points of Failure", - Font = OsuFont.GetFont(size: 13), + Font = OsuFont.GetFont(size: 12), Margin = new MarginPadding { Vertical = 20 }, }, }, diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index 7ab91677a9..44fac32360 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -51,7 +51,6 @@ namespace osu.Game.Screens.Select.Details { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Spacing = new Vector2(4f), Children = new[] { FirstValue = new StatisticRow(), //circle size/key amount @@ -199,6 +198,7 @@ namespace osu.Game.Screens.Select.Details this.forceDecimalPlaces = forceDecimalPlaces; RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; + Padding = new MarginPadding { Vertical = 2.5f }; Children = new Drawable[] { @@ -206,9 +206,11 @@ namespace osu.Game.Screens.Select.Details { Width = name_width, AutoSizeAxes = Axes.Y, + // osu-web uses 1.25 line-height, which at 12px font size makes the element 14px tall - this compentates that difference + Padding = new MarginPadding { Vertical = 1 }, Child = name = new OsuSpriteText { - Font = OsuFont.GetFont(size: 13) + Font = OsuFont.GetFont(size: 12) }, }, bar = new Bar @@ -239,7 +241,7 @@ namespace osu.Game.Screens.Select.Details { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Font = OsuFont.GetFont(size: 13) + Font = OsuFont.GetFont(size: 12) }, }, }; diff --git a/osu.Game/Screens/Select/Details/UserRatings.cs b/osu.Game/Screens/Select/Details/UserRatings.cs index c1e01e3572..cf5e3ba1b3 100644 --- a/osu.Game/Screens/Select/Details/UserRatings.cs +++ b/osu.Game/Screens/Select/Details/UserRatings.cs @@ -71,31 +71,32 @@ namespace osu.Game.Screens.Select.Details Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "User Rating", - Font = OsuFont.GetFont(size: 13) + Font = OsuFont.GetFont(size: 12), + Margin = new MarginPadding { Bottom = 5 }, }, ratingsBar = new Bar { RelativeSizeAxes = Axes.X, Height = 5, - Margin = new MarginPadding { Top = 5 }, }, new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, + Margin = new MarginPadding { Bottom = 10 }, Children = new[] { negativeRatings = new OsuSpriteText { Text = "0", - Font = OsuFont.GetFont(size: 13) + Font = OsuFont.GetFont(size: 12) }, positiveRatings = new OsuSpriteText { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, Text = @"0", - Font = OsuFont.GetFont(size: 13) + Font = OsuFont.GetFont(size: 12) }, }, }, @@ -104,8 +105,8 @@ namespace osu.Game.Screens.Select.Details Anchor = Anchor.TopCentre, Origin = Anchor.TopCentre, Text = "Rating Spread", - Font = OsuFont.GetFont(size: 13), - Margin = new MarginPadding { Top = 10, Bottom = 5 }, + Font = OsuFont.GetFont(size: 12), + Margin = new MarginPadding { Bottom = 5 }, }, }, }, From 64a9b9c6fbea86aaf1cf2ead68fa8797dc1f9aa1 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Sun, 16 Feb 2020 21:52:08 +0100 Subject: [PATCH 18/72] Remove redundant using directives --- osu.Game/Beatmaps/Drawables/UpdateableBeatmapSetCover.cs | 1 - osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs | 2 -- osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs | 1 - osu.Game/Screens/Select/Details/AdvancedStats.cs | 1 - 4 files changed, 5 deletions(-) diff --git a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapSetCover.cs b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapSetCover.cs index 182ab055b3..c60bd0286e 100644 --- a/osu.Game/Beatmaps/Drawables/UpdateableBeatmapSetCover.cs +++ b/osu.Game/Beatmaps/Drawables/UpdateableBeatmapSetCover.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; diff --git a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs index 265e2d32f9..66886b0882 100644 --- a/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs +++ b/osu.Game/Overlays/BeatmapSet/BeatmapPicker.cs @@ -6,7 +6,6 @@ using System.Linq; using osu.Framework; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; @@ -19,7 +18,6 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets; using osuTK; -using osuTK.Graphics; namespace osu.Game.Overlays.BeatmapSet { diff --git a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs index 48062ef3f0..607355b7bf 100644 --- a/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs +++ b/osu.Game/Overlays/BeatmapSet/LeaderboardScopeSelector.cs @@ -3,7 +3,6 @@ using osu.Game.Screens.Select.Leaderboards; using osu.Game.Graphics.UserInterface; -using osu.Game.Graphics; using osu.Framework.Allocation; using osuTK.Graphics; using osu.Framework.Graphics.UserInterface; diff --git a/osu.Game/Screens/Select/Details/AdvancedStats.cs b/osu.Game/Screens/Select/Details/AdvancedStats.cs index 44fac32360..af0d36ea9a 100644 --- a/osu.Game/Screens/Select/Details/AdvancedStats.cs +++ b/osu.Game/Screens/Select/Details/AdvancedStats.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osuTK; using osuTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; From 5ca93758dc40e50094897877749391ec9dea0d5b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Mon, 17 Feb 2020 16:59:35 +0900 Subject: [PATCH 19/72] Fix music playlist being enumerated asynchronously --- osu.Game/Overlays/Music/PlaylistOverlay.cs | 8 ++++-- osu.Game/Overlays/MusicController.cs | 30 +++++++++++++++++----- osu.Game/Overlays/NowPlayingOverlay.cs | 11 +++++--- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs index 8f753fd3aa..b878aba489 100644 --- a/osu.Game/Overlays/Music/PlaylistOverlay.cs +++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs @@ -75,8 +75,6 @@ namespace osu.Game.Overlays.Music }, }; - list.Items.BindTo(beatmapSets); - filter.Search.OnCommit = (sender, newText) => { BeatmapInfo toSelect = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault(); @@ -87,7 +85,13 @@ namespace osu.Game.Overlays.Music beatmap.Value.Track.Restart(); } }; + } + protected override void LoadComplete() + { + base.LoadComplete(); + + list.Items.BindTo(beatmapSets); beatmap.BindValueChanged(working => list.SelectedSet.Value = working.NewValue.BeatmapSetInfo, true); } diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs index 7c7daf6eb9..d788929739 100644 --- a/osu.Game/Overlays/MusicController.cs +++ b/osu.Game/Overlays/MusicController.cs @@ -25,7 +25,16 @@ namespace osu.Game.Overlays [Resolved] private BeatmapManager beatmaps { get; set; } - public IBindableList BeatmapSets => beatmapSets; + public IBindableList BeatmapSets + { + get + { + if (LoadState < LoadState.Ready) + throw new InvalidOperationException($"{nameof(BeatmapSets)} should not be accessed before the music controller is loaded."); + + return beatmapSets; + } + } /// /// Point in time after which the current track will be restarted on triggering a "previous track" action. @@ -54,16 +63,18 @@ namespace osu.Game.Overlays [BackgroundDependencyLoader] private void load() { - beatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets().OrderBy(_ => RNG.Next())); beatmaps.ItemAdded += handleBeatmapAdded; beatmaps.ItemRemoved += handleBeatmapRemoved; + + beatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets().OrderBy(_ => RNG.Next())); } protected override void LoadComplete() { + base.LoadComplete(); + beatmap.BindValueChanged(beatmapChanged, true); mods.BindValueChanged(_ => ResetTrackAdjustments(), true); - base.LoadComplete(); } /// @@ -82,11 +93,16 @@ namespace osu.Game.Overlays /// public bool IsPlaying => current?.Track.IsRunning ?? false; - private void handleBeatmapAdded(BeatmapSetInfo set) => - Schedule(() => beatmapSets.Add(set)); + private void handleBeatmapAdded(BeatmapSetInfo set) => Schedule(() => + { + if (!beatmapSets.Contains(set)) + beatmapSets.Add(set); + }); - private void handleBeatmapRemoved(BeatmapSetInfo set) => - Schedule(() => beatmapSets.RemoveAll(s => s.ID == set.ID)); + private void handleBeatmapRemoved(BeatmapSetInfo set) => Schedule(() => + { + beatmapSets.RemoveAll(s => s.ID == set.ID); + }); private ScheduledDelegate seekDelegate; diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs index dfcf99d30c..118cb037cb 100644 --- a/osu.Game/Overlays/NowPlayingOverlay.cs +++ b/osu.Game/Overlays/NowPlayingOverlay.cs @@ -58,6 +58,9 @@ namespace osu.Game.Overlays [Resolved] private Bindable beatmap { get; set; } + [Resolved] + private OsuColour colours { get; set; } + public NowPlayingOverlay() { Width = 400; @@ -65,7 +68,7 @@ namespace osu.Game.Overlays } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load() { Children = new Drawable[] { @@ -182,15 +185,15 @@ namespace osu.Game.Overlays } } }; - - playlist.BeatmapSets.BindTo(musicController.BeatmapSets); - playlist.State.ValueChanged += s => playlistButton.FadeColour(s.NewValue == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint); } protected override void LoadComplete() { base.LoadComplete(); + playlist.BeatmapSets.BindTo(musicController.BeatmapSets); + playlist.State.BindValueChanged(s => playlistButton.FadeColour(s.NewValue == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint), true); + beatmap.BindDisabledChanged(beatmapDisabledChanged, true); musicController.TrackChanged += trackChanged; From e3d37b808d6dad9f2a6916a3632d56970e11e320 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Feb 2020 17:33:09 +0900 Subject: [PATCH 20/72] Move overlined displays to a higher namespace --- .../Visual/Multiplayer/TestSceneOverlinedParticipants.cs | 2 +- .../Visual/Multiplayer/TestSceneOverlinedPlaylist.cs | 2 +- .../Screens/Multi/{Match => }/Components/OverlinedDisplay.cs | 2 +- .../Multi/{Match => }/Components/OverlinedParticipants.cs | 3 +-- .../Screens/Multi/{Match => }/Components/OverlinedPlaylist.cs | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) rename osu.Game/Screens/Multi/{Match => }/Components/OverlinedDisplay.cs (98%) rename osu.Game/Screens/Multi/{Match => }/Components/OverlinedParticipants.cs (90%) rename osu.Game/Screens/Multi/{Match => }/Components/OverlinedPlaylist.cs (95%) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedParticipants.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedParticipants.cs index e07ebc1454..575602d787 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedParticipants.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedParticipants.cs @@ -3,7 +3,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Game.Screens.Multi.Match.Components; +using osu.Game.Screens.Multi.Components; using osuTK; namespace osu.Game.Tests.Visual.Multiplayer diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs index cf4897be50..4e38f6d2c2 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs @@ -5,7 +5,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets.Osu; -using osu.Game.Screens.Multi.Match.Components; +using osu.Game.Screens.Multi.Components; using osu.Game.Tests.Beatmaps; using osuTK; diff --git a/osu.Game/Screens/Multi/Match/Components/OverlinedDisplay.cs b/osu.Game/Screens/Multi/Components/OverlinedDisplay.cs similarity index 98% rename from osu.Game/Screens/Multi/Match/Components/OverlinedDisplay.cs rename to osu.Game/Screens/Multi/Components/OverlinedDisplay.cs index 854877bd1c..844337aed4 100644 --- a/osu.Game/Screens/Multi/Match/Components/OverlinedDisplay.cs +++ b/osu.Game/Screens/Multi/Components/OverlinedDisplay.cs @@ -9,7 +9,7 @@ using osu.Game.Graphics; using osu.Game.Graphics.Sprites; using osuTK; -namespace osu.Game.Screens.Multi.Match.Components +namespace osu.Game.Screens.Multi.Components { public abstract class OverlinedDisplay : MultiplayerComposite { diff --git a/osu.Game/Screens/Multi/Match/Components/OverlinedParticipants.cs b/osu.Game/Screens/Multi/Components/OverlinedParticipants.cs similarity index 90% rename from osu.Game/Screens/Multi/Match/Components/OverlinedParticipants.cs rename to osu.Game/Screens/Multi/Components/OverlinedParticipants.cs index 7a4290a9a1..fbf2bb91c5 100644 --- a/osu.Game/Screens/Multi/Match/Components/OverlinedParticipants.cs +++ b/osu.Game/Screens/Multi/Components/OverlinedParticipants.cs @@ -3,9 +3,8 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; -using osu.Game.Screens.Multi.Components; -namespace osu.Game.Screens.Multi.Match.Components +namespace osu.Game.Screens.Multi.Components { public class OverlinedParticipants : OverlinedDisplay { diff --git a/osu.Game/Screens/Multi/Match/Components/OverlinedPlaylist.cs b/osu.Game/Screens/Multi/Components/OverlinedPlaylist.cs similarity index 95% rename from osu.Game/Screens/Multi/Match/Components/OverlinedPlaylist.cs rename to osu.Game/Screens/Multi/Components/OverlinedPlaylist.cs index eea85d9d64..4fe79b40a0 100644 --- a/osu.Game/Screens/Multi/Match/Components/OverlinedPlaylist.cs +++ b/osu.Game/Screens/Multi/Components/OverlinedPlaylist.cs @@ -6,7 +6,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Game.Online.Multiplayer; -namespace osu.Game.Screens.Multi.Match.Components +namespace osu.Game.Screens.Multi.Components { public class OverlinedPlaylist : OverlinedDisplay { From 380d200b46e417db260bb5ca3613dfb107c9615b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Feb 2020 17:34:47 +0900 Subject: [PATCH 21/72] Allow different sizing modes for OverlinedDisplay --- .../Multi/Components/OverlinedDisplay.cs | 59 ++++++++++++++----- .../Screens/Multi/Match/MatchSubScreen.cs | 3 +- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/osu.Game/Screens/Multi/Components/OverlinedDisplay.cs b/osu.Game/Screens/Multi/Components/OverlinedDisplay.cs index 844337aed4..600fa99a9a 100644 --- a/osu.Game/Screens/Multi/Components/OverlinedDisplay.cs +++ b/osu.Game/Screens/Multi/Components/OverlinedDisplay.cs @@ -15,6 +15,26 @@ namespace osu.Game.Screens.Multi.Components { protected readonly Container Content; + public override Axes RelativeSizeAxes + { + get => base.RelativeSizeAxes; + set + { + base.RelativeSizeAxes = value; + updateDimensions(); + } + } + + public override Axes AutoSizeAxes + { + get => base.AutoSizeAxes; + protected set + { + base.AutoSizeAxes = value; + updateDimensions(); + } + } + protected string Details { set => details.Text = value; @@ -22,14 +42,12 @@ namespace osu.Game.Screens.Multi.Components private readonly Circle line; private readonly OsuSpriteText details; + private readonly GridContainer grid; protected OverlinedDisplay(string title) { - RelativeSizeAxes = Axes.Both; - - InternalChild = new GridContainer + InternalChild = grid = new GridContainer { - RelativeSizeAxes = Axes.Both, Content = new[] { new Drawable[] @@ -62,19 +80,12 @@ namespace osu.Game.Screens.Multi.Components }, new Drawable[] { - Content = new Container - { - Margin = new MarginPadding { Top = 5 }, - RelativeSizeAxes = Axes.Both - } + Content = new Container { Margin = new MarginPadding { Top = 5 } } } - }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.AutoSize), } }; + + updateDimensions(); } [BackgroundDependencyLoader] @@ -83,5 +94,25 @@ namespace osu.Game.Screens.Multi.Components line.Colour = colours.Yellow; details.Colour = colours.Yellow; } + + private void updateDimensions() + { + grid.RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension(GridSizeMode.AutoSize), + new Dimension(AutoSizeAxes.HasFlag(Axes.Y) ? GridSizeMode.AutoSize : GridSizeMode.Distributed), + }; + + grid.AutoSizeAxes = Axes.None; + grid.RelativeSizeAxes = Axes.None; + grid.AutoSizeAxes = AutoSizeAxes; + grid.RelativeSizeAxes = ~AutoSizeAxes; + + Content.AutoSizeAxes = Axes.None; + Content.RelativeSizeAxes = Axes.None; + Content.AutoSizeAxes = grid.AutoSizeAxes; + Content.RelativeSizeAxes = grid.RelativeSizeAxes; + } } } diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index a8630b79b1..caa88a06e0 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -114,7 +114,7 @@ namespace osu.Game.Screens.Multi.Match { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Right = 5 }, - Child = new OverlinedParticipants() + Child = new OverlinedParticipants { RelativeSizeAxes = Axes.Both } }, new Container { @@ -122,6 +122,7 @@ namespace osu.Game.Screens.Multi.Match Padding = new MarginPadding { Horizontal = 5 }, Child = new OverlinedPlaylist(true) // Temporarily always allow selection { + RelativeSizeAxes = Axes.Both, SelectedItem = { BindTarget = SelectedItem } } }, From ec73e8f0c717e6baf11367a6b7ba4291652a958a Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Feb 2020 17:37:01 +0900 Subject: [PATCH 22/72] Allow different sizing modes for OverlinedParticipants --- .../TestSceneOverlinedParticipants.cs | 42 ++++++++++++++++--- .../Graphics/Containers/OsuScrollContainer.cs | 7 ++-- .../Multi/Components/OverlinedParticipants.cs | 32 +++++++++++++- .../Multi/Components/ParticipantsList.cs | 41 ++++++++++++------ .../Multi/Lounge/Components/RoomInspector.cs | 11 ++++- .../Screens/Multi/Match/MatchSubScreen.cs | 2 +- 6 files changed, 110 insertions(+), 25 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedParticipants.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedParticipants.cs index 575602d787..1fc258a225 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedParticipants.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedParticipants.cs @@ -1,8 +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; +using System.Collections.Generic; +using NUnit.Framework; using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Game.Screens.Multi.Components; using osuTK; @@ -10,18 +12,46 @@ namespace osu.Game.Tests.Visual.Multiplayer { public class TestSceneOverlinedParticipants : MultiplayerTestScene { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(OverlinedParticipants), + typeof(OverlinedDisplay), + typeof(ParticipantsList) + }; + protected override bool UseOnlineAPI => true; public TestSceneOverlinedParticipants() { Room.RoomID.Value = 7; + } - Add(new Container + [Test] + public void TestHorizontalLayout() + { + AddStep("create component", () => { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(500), - Child = new OverlinedParticipants() + Child = new OverlinedParticipants(Direction.Horizontal) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 500, + AutoSizeAxes = Axes.Y, + }; + }); + } + + [Test] + public void TestVerticalLayout() + { + AddStep("create component", () => + { + Child = new OverlinedParticipants(Direction.Vertical) + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(500) + }; }); } } diff --git a/osu.Game/Graphics/Containers/OsuScrollContainer.cs b/osu.Game/Graphics/Containers/OsuScrollContainer.cs index 6d531887ed..1824fcd878 100644 --- a/osu.Game/Graphics/Containers/OsuScrollContainer.cs +++ b/osu.Game/Graphics/Containers/OsuScrollContainer.cs @@ -14,6 +14,9 @@ namespace osu.Game.Graphics.Containers { public class OsuScrollContainer : ScrollContainer { + public const float SCROLL_BAR_HEIGHT = 10; + public const float SCROLL_BAR_PADDING = 3; + /// /// Allows controlling the scroll bar from any position in the container using the right mouse button. /// Uses the value of to smoothly scroll to the dragged location. @@ -96,8 +99,6 @@ namespace osu.Game.Graphics.Containers protected class OsuScrollbar : ScrollbarContainer { - private const float dim_size = 10; - private Color4 hoverColour; private Color4 defaultColour; private Color4 highlightColour; @@ -135,7 +136,7 @@ namespace osu.Game.Graphics.Containers public override void ResizeTo(float val, int duration = 0, Easing easing = Easing.None) { - Vector2 size = new Vector2(dim_size) + Vector2 size = new Vector2(SCROLL_BAR_HEIGHT) { [(int)ScrollDirection] = val }; diff --git a/osu.Game/Screens/Multi/Components/OverlinedParticipants.cs b/osu.Game/Screens/Multi/Components/OverlinedParticipants.cs index fbf2bb91c5..a709c6a57a 100644 --- a/osu.Game/Screens/Multi/Components/OverlinedParticipants.cs +++ b/osu.Game/Screens/Multi/Components/OverlinedParticipants.cs @@ -3,15 +3,43 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; +using osu.Game.Graphics.Containers; namespace osu.Game.Screens.Multi.Components { public class OverlinedParticipants : OverlinedDisplay { - public OverlinedParticipants() + public new Axes AutoSizeAxes + { + get => base.AutoSizeAxes; + set => base.AutoSizeAxes = value; + } + + public OverlinedParticipants(Direction direction) : base("Participants") { - Content.Add(new ParticipantsList { RelativeSizeAxes = Axes.Both }); + OsuScrollContainer scroll; + ParticipantsList list; + + Content.Add(scroll = new OsuScrollContainer(direction) + { + Child = list = new ParticipantsList() + }); + + switch (direction) + { + case Direction.Horizontal: + scroll.RelativeSizeAxes = Axes.X; + scroll.Height = ParticipantsList.TILE_SIZE + OsuScrollContainer.SCROLL_BAR_HEIGHT + OsuScrollContainer.SCROLL_BAR_PADDING * 2; + list.AutoSizeAxes = Axes.Both; + break; + + case Direction.Vertical: + scroll.RelativeSizeAxes = Axes.Both; + list.RelativeSizeAxes = Axes.X; + list.AutoSizeAxes = Axes.Y; + break; + } } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Multi/Components/ParticipantsList.cs b/osu.Game/Screens/Multi/Components/ParticipantsList.cs index 2ef36b2795..81d530ce68 100644 --- a/osu.Game/Screens/Multi/Components/ParticipantsList.cs +++ b/osu.Game/Screens/Multi/Components/ParticipantsList.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; using osu.Game.Online.API; using osu.Game.Online.API.Requests; using osu.Game.Users; @@ -19,21 +18,39 @@ namespace osu.Game.Screens.Multi.Components { public class ParticipantsList : MultiplayerComposite { + public const float TILE_SIZE = 70; + + public override Axes RelativeSizeAxes + { + get => base.RelativeSizeAxes; + set + { + base.RelativeSizeAxes = value; + fill.RelativeSizeAxes = value; + } + } + + public new Axes AutoSizeAxes + { + get => base.AutoSizeAxes; + set + { + base.AutoSizeAxes = value; + fill.AutoSizeAxes = value; + } + } + + public FillDirection Direction + { + get => fill.Direction; + set => fill.Direction = value; + } + private readonly FillFlowContainer fill; public ParticipantsList() { - InternalChild = new OsuScrollContainer - { - RelativeSizeAxes = Axes.Both, - Child = fill = new FillFlowContainer - { - Spacing = new Vector2(10), - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Full, - } - }; + InternalChild = fill = new FillFlowContainer { Spacing = new Vector2(10) }; } [BackgroundDependencyLoader] diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index cb6bbf6731..b86495784a 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Beatmaps; using osu.Game.Graphics; +using osu.Game.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi.Components; @@ -157,7 +158,15 @@ namespace osu.Game.Screens.Multi.Lounge.Components { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Horizontal = 10 }, - Child = new ParticipantsList { RelativeSizeAxes = Axes.Both } + Child = new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both, + Child = new ParticipantsList + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y + } + } } } } diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index caa88a06e0..422aeb3298 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -114,7 +114,7 @@ namespace osu.Game.Screens.Multi.Match { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Right = 5 }, - Child = new OverlinedParticipants { RelativeSizeAxes = Axes.Both } + Child = new OverlinedParticipants(Direction.Vertical) { RelativeSizeAxes = Axes.Both } }, new Container { From ac416ae743b825705baf45608b40b0bfb34225e9 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Feb 2020 17:47:59 +0900 Subject: [PATCH 23/72] Implement new room inspector redesign --- .../Multiplayer/TestSceneLoungeRoomInfo.cs | 59 +++++ .../Multi/Lounge/Components/RoomInfo.cs | 89 ++++++++ .../Multi/Lounge/Components/RoomInspector.cs | 203 +++--------------- 3 files changed, 176 insertions(+), 175 deletions(-) create mode 100644 osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs create mode 100644 osu.Game/Screens/Multi/Lounge/Components/RoomInfo.cs diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs new file mode 100644 index 0000000000..1e1bc9725c --- /dev/null +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneLoungeRoomInfo.cs @@ -0,0 +1,59 @@ +// 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 NUnit.Framework; +using osu.Framework.Graphics; +using osu.Game.Online.Multiplayer; +using osu.Game.Online.Multiplayer.RoomStatuses; +using osu.Game.Screens.Multi.Lounge.Components; +using osu.Game.Users; + +namespace osu.Game.Tests.Visual.Multiplayer +{ + public class TestSceneLoungeRoomInfo : MultiplayerTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(RoomInfo) + }; + + [SetUp] + public void Setup() => Schedule(() => + { + Room.CopyFrom(new Room()); + + Child = new RoomInfo + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 500 + }; + }); + + public override void SetUpSteps() + { + // Todo: Temp + } + + [Test] + public void TestNonSelectedRoom() + { + AddStep("set null room", () => Room.RoomID.Value = null); + } + + [Test] + public void TestOpenRoom() + { + AddStep("set open room", () => + { + Room.RoomID.Value = 0; + Room.Name.Value = "Room 0"; + Room.Host.Value = new User { Username = "peppy", Id = 2 }; + Room.EndDate.Value = DateTimeOffset.Now.AddMonths(1); + Room.Status.Value = new RoomStatusOpen(); + }); + } + } +} diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInfo.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInfo.cs new file mode 100644 index 0000000000..02f2667802 --- /dev/null +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInfo.cs @@ -0,0 +1,89 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Sprites; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Screens.Multi.Components; +using osuTK; + +namespace osu.Game.Screens.Multi.Lounge.Components +{ + public class RoomInfo : MultiplayerComposite + { + private readonly List statusElements = new List(); + private readonly SpriteText roomName; + + public RoomInfo() + { + AutoSizeAxes = Axes.Y; + + RoomStatusInfo statusInfo; + ModeTypeInfo typeInfo; + ParticipantInfo participantInfo; + + InternalChild = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 4), + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new FillFlowContainer + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Vertical, + Children = new Drawable[] + { + roomName = new OsuSpriteText { Font = OsuFont.GetFont(size: 30) }, + statusInfo = new RoomStatusInfo(), + } + }, + typeInfo = new ModeTypeInfo + { + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight + } + } + }, + participantInfo = new ParticipantInfo(), + } + }; + + statusElements.AddRange(new Drawable[] { statusInfo, typeInfo, participantInfo }); + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + if (RoomID.Value == null) + statusElements.ForEach(e => e.FadeOut()); + + RoomID.BindValueChanged(id => + { + if (id.NewValue == null) + statusElements.ForEach(e => e.FadeOut(100)); + else + statusElements.ForEach(e => e.FadeIn(100)); + }, true); + + RoomName.BindValueChanged(name => + { + roomName.Text = name.NewValue ?? "No room selected"; + }, true); + } + } +} diff --git a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs index b86495784a..891853dee5 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/RoomInspector.cs @@ -2,19 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; -using osu.Framework.Bindables; -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.Game.Beatmaps; using osu.Game.Graphics; -using osu.Game.Graphics.Containers; -using osu.Game.Graphics.Sprites; -using osu.Game.Online.Multiplayer; using osu.Game.Screens.Multi.Components; -using osuTK; using osuTK.Graphics; namespace osu.Game.Screens.Multi.Lounge.Components @@ -25,16 +18,9 @@ namespace osu.Game.Screens.Multi.Lounge.Components private readonly MarginPadding contentPadding = new MarginPadding { Horizontal = 20, Vertical = 10 }; - private ParticipantCountDisplay participantCount; - private OsuSpriteText name; - private BeatmapTypeInfo beatmapTypeInfo; - private ParticipantInfo participantInfo; - [Resolved] private BeatmapManager beatmaps { get; set; } - private readonly Bindable status = new Bindable(new RoomStatusNoneSelected()); - [BackgroundDependencyLoader] private void load(OsuColour colours) { @@ -43,185 +29,52 @@ namespace osu.Game.Screens.Multi.Lounge.Components new Box { RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex(@"343138"), + Colour = Color4.Black, + Alpha = 0.25f }, - new GridContainer + new Container { RelativeSizeAxes = Axes.Both, - RowDimensions = new[] + Padding = new MarginPadding { Horizontal = 30 }, + Child = new GridContainer { - new Dimension(GridSizeMode.AutoSize), - new Dimension(GridSizeMode.Distributed), - }, - Content = new[] - { - new Drawable[] + RelativeSizeAxes = Axes.Both, + Content = new[] { - new FillFlowContainer + new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] + new FillFlowContainer { - new Container + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - Height = 200, - Masking = true, - Children = new Drawable[] + new RoomInfo { - new MultiplayerBackgroundSprite { RelativeSizeAxes = Axes.Both }, - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(Color4.Black.Opacity(0.5f), Color4.Black.Opacity(0)), - }, - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding(20), - Children = new Drawable[] - { - participantCount = new ParticipantCountDisplay - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - }, - name = new OsuSpriteText - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Font = OsuFont.GetFont(size: 30), - Current = RoomName - }, - }, - }, + RelativeSizeAxes = Axes.X, + Margin = new MarginPadding { Vertical = 60 }, }, - }, - new StatusColouredContainer(transition_duration) - { - RelativeSizeAxes = Axes.X, - Height = 5, - Child = new Box { RelativeSizeAxes = Axes.Both } - }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] + new OverlinedParticipants(Direction.Horizontal) { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex(@"28242d"), - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - LayoutDuration = transition_duration, - Padding = contentPadding, - Spacing = new Vector2(0f, 5f), - Children = new Drawable[] - { - new StatusColouredContainer(transition_duration) - { - AutoSizeAxes = Axes.Both, - Child = new StatusText - { - Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14), - } - }, - beatmapTypeInfo = new BeatmapTypeInfo(), - }, - }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y }, - }, - new Container - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = contentPadding, - Children = new Drawable[] - { - participantInfo = new ParticipantInfo(), - }, - }, - }, - }, - }, - new Drawable[] - { - new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = 10 }, - Child = new OsuScrollContainer - { - RelativeSizeAxes = Axes.Both, - Child = new ParticipantsList - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y } } - } + }, + new Drawable[] + { + new OverlinedPlaylist(false) { RelativeSizeAxes = Axes.Both }, + }, + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), } } } }; - - Status.BindValueChanged(_ => updateStatus(), true); - RoomID.BindValueChanged(_ => updateStatus(), true); - } - - protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) - { - var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); - dependencies.CacheAs(status, new CacheInfo(nameof(Room.Status), typeof(Room))); - return dependencies; - } - - private void updateStatus() - { - if (RoomID.Value == null) - { - status.Value = new RoomStatusNoneSelected(); - - participantCount.FadeOut(transition_duration); - beatmapTypeInfo.FadeOut(transition_duration); - name.FadeOut(transition_duration); - participantInfo.FadeOut(transition_duration); - } - else - { - status.Value = Status.Value; - - participantCount.FadeIn(transition_duration); - beatmapTypeInfo.FadeIn(transition_duration); - name.FadeIn(transition_duration); - participantInfo.FadeIn(transition_duration); - } - } - - private class RoomStatusNoneSelected : RoomStatus - { - public override string Message => @"No Room Selected"; - public override Color4 GetAppropriateColour(OsuColour colours) => colours.Gray8; - } - - private class StatusText : OsuSpriteText - { - [Resolved(typeof(Room), nameof(Room.Status))] - private Bindable status { get; set; } - - [BackgroundDependencyLoader] - private void load() - { - status.BindValueChanged(s => Text = s.NewValue.Message, true); - } } } } From e96668904406abd2d81c9a0c988835ffaf264152 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Feb 2020 19:42:25 +0900 Subject: [PATCH 24/72] Add beatmap background to multiplayer --- .../Multi/Lounge/Components/FilterControl.cs | 3 +- .../Screens/Multi/Match/MatchSubScreen.cs | 21 ----- osu.Game/Screens/Multi/Multiplayer.cs | 92 +++++++++++++++---- 3 files changed, 73 insertions(+), 43 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs index 9f93afec9d..666051ba8e 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs @@ -5,7 +5,6 @@ using System.ComponentModel; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Threading; -using osu.Game.Graphics; using osu.Game.Overlays.SearchableList; using osu.Game.Rulesets; using osuTK.Graphics; @@ -14,7 +13,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components { public class FilterControl : SearchableListFilterControl { - protected override Color4 BackgroundColour => OsuColour.FromHex(@"362e42"); + protected override Color4 BackgroundColour => Color4.Transparent; protected override PrimaryFilter DefaultTab => PrimaryFilter.Open; protected override SecondaryFilter DefaultCategory => SecondaryFilter.Public; diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index a8630b79b1..5258d8429e 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -5,22 +5,17 @@ using System; using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; -using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; -using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Screens; using osu.Game.Audio; using osu.Game.Beatmaps; -using osu.Game.Beatmaps.Drawables; using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.GameTypes; using osu.Game.Rulesets.Mods; -using osu.Game.Screens.Multi.Components; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Play; using osu.Game.Screens.Select; -using osuTK.Graphics; using Footer = osu.Game.Screens.Multi.Match.Components.Footer; namespace osu.Game.Screens.Multi.Match @@ -64,12 +59,6 @@ namespace osu.Game.Screens.Multi.Match { InternalChildren = new Drawable[] { - new HeaderBackgroundSprite - { - RelativeSizeAxes = Axes.X, - Height = 200, - Colour = ColourInfo.GradientVertical(Color4.White.Opacity(0.4f), Color4.White.Opacity(0)) - }, new GridContainer { RelativeSizeAxes = Axes.Both, @@ -252,15 +241,5 @@ namespace osu.Game.Screens.Multi.Match if (beatmapManager != null) beatmapManager.ItemAdded -= beatmapAdded; } - - private class HeaderBackgroundSprite : MultiplayerBackgroundSprite - { - protected override UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new BackgroundSprite { RelativeSizeAxes = Axes.Both }; - - private class BackgroundSprite : UpdateableBeatmapBackgroundSprite - { - protected override double TransformDuration => 200; - } - } } } diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 2277157134..13537e2be8 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -4,14 +4,16 @@ using System; using osu.Framework.Allocation; using osu.Framework.Bindables; +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.Logging; using osu.Framework.Screens; using osu.Game.Beatmaps; +using osu.Game.Beatmaps.Drawables; using osu.Game.Graphics; -using osu.Game.Graphics.Backgrounds; using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Input; @@ -19,6 +21,7 @@ using osu.Game.Online.API; using osu.Game.Online.Multiplayer; using osu.Game.Overlays.BeatmapSet.Buttons; using osu.Game.Screens.Menu; +using osu.Game.Screens.Multi.Components; using osu.Game.Screens.Multi.Lounge; using osu.Game.Screens.Multi.Lounge.Components; using osu.Game.Screens.Multi.Match; @@ -62,6 +65,9 @@ namespace osu.Game.Screens.Multi [Resolved(CanBeNull = true)] private OsuLogo logo { get; set; } + private readonly Drawable header; + private readonly Drawable headerBackground; + public Multiplayer() { Anchor = Anchor.Centre; @@ -74,31 +80,51 @@ namespace osu.Game.Screens.Multi RelativeSizeAxes = Axes.Both, Children = new Drawable[] { - new Container + new Box { RelativeSizeAxes = Axes.Both, - Masking = true, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex(@"3e3a44"), - }, - new Triangles - { - RelativeSizeAxes = Axes.Both, - ColourLight = OsuColour.FromHex(@"3c3842"), - ColourDark = OsuColour.FromHex(@"393540"), - TriangleScale = 5, - }, - }, + Colour = OsuColour.FromHex(@"3e3a44"), }, new Container { RelativeSizeAxes = Axes.Both, Padding = new MarginPadding { Top = Header.HEIGHT }, - Child = screenStack = new MultiplayerSubScreenStack { RelativeSizeAxes = Axes.Both } + Children = new[] + { + header = new Container + { + RelativeSizeAxes = Axes.X, + Height = 400, + Children = new[] + { + headerBackground = new Container + { + RelativeSizeAxes = Axes.Both, + Width = 1.25f, + Masking = true, + Children = new Drawable[] + { + new HeaderBackgroundSprite + { + RelativeSizeAxes = Axes.X, + Height = 400 // Keep a static height so the header doesn't change as it's resized + }, + } + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Bottom = -1 }, // 1px padding to avoid a 1px gap due to masking + Child = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourInfo.GradientVertical(OsuColour.FromHex(@"3e3a44").Opacity(0.6f), OsuColour.FromHex(@"3e3a44")) + }, + } + } + }, + screenStack = new MultiplayerSubScreenStack { RelativeSizeAxes = Axes.Both } + } }, new Header(screenStack), createButton = new HeaderButton @@ -259,7 +285,10 @@ namespace osu.Game.Screens.Multi Beatmap.ValueChanged -= updateTrack; } - private void screenPushed(IScreen lastScreen, IScreen newScreen) => subScreenChanged(newScreen); + private void screenPushed(IScreen lastScreen, IScreen newScreen) + { + subScreenChanged(newScreen); + } private void screenExited(IScreen lastScreen, IScreen newScreen) { @@ -271,6 +300,19 @@ namespace osu.Game.Screens.Multi private void subScreenChanged(IScreen newScreen) { + switch (newScreen) + { + case LoungeSubScreen _: + header.ResizeHeightTo(400, WaveContainer.APPEAR_DURATION, Easing.OutQuint); + headerBackground.MoveToX(0, WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); + break; + + case MatchSubScreen _: + header.ResizeHeightTo(135, WaveContainer.APPEAR_DURATION, Easing.OutQuint); + headerBackground.MoveToX(-200, WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); + break; + } + updatePollingRate(isIdle.Value); createButton.FadeTo(newScreen is LoungeSubScreen ? 1 : 0, 200); @@ -327,5 +369,15 @@ namespace osu.Game.Screens.Multi FourthWaveColour = OsuColour.FromHex(@"392850"); } } + + private class HeaderBackgroundSprite : MultiplayerBackgroundSprite + { + protected override UpdateableBeatmapBackgroundSprite CreateBackgroundSprite() => new BackgroundSprite { RelativeSizeAxes = Axes.Both }; + + private class BackgroundSprite : UpdateableBeatmapBackgroundSprite + { + protected override double TransformDuration => 200; + } + } } } From 33382416327e95b1bb0ddfee86fe1f32d1f4a0bd Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Feb 2020 19:48:34 +0900 Subject: [PATCH 25/72] Add back filter control background, adjust opacity --- osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs | 3 ++- osu.Game/Screens/Multi/Multiplayer.cs | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs index 666051ba8e..300418441e 100644 --- a/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs +++ b/osu.Game/Screens/Multi/Lounge/Components/FilterControl.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using osu.Framework.Allocation; using osu.Framework.Bindables; +using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Threading; using osu.Game.Overlays.SearchableList; using osu.Game.Rulesets; @@ -13,7 +14,7 @@ namespace osu.Game.Screens.Multi.Lounge.Components { public class FilterControl : SearchableListFilterControl { - protected override Color4 BackgroundColour => Color4.Transparent; + protected override Color4 BackgroundColour => Color4.Black.Opacity(0.5f); protected override PrimaryFilter DefaultTab => PrimaryFilter.Open; protected override SecondaryFilter DefaultCategory => SecondaryFilter.Public; diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 13537e2be8..07d930fa75 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -75,6 +75,8 @@ namespace osu.Game.Screens.Multi RelativeSizeAxes = Axes.Both; Padding = new MarginPadding { Horizontal = -HORIZONTAL_OVERFLOW_PADDING }; + var backgroundColour = OsuColour.FromHex(@"3e3a44"); + InternalChild = waves = new MultiplayerWaveContainer { RelativeSizeAxes = Axes.Both, @@ -83,7 +85,7 @@ namespace osu.Game.Screens.Multi new Box { RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex(@"3e3a44"), + Colour = backgroundColour, }, new Container { @@ -118,7 +120,7 @@ namespace osu.Game.Screens.Multi Child = new Box { RelativeSizeAxes = Axes.Both, - Colour = ColourInfo.GradientVertical(OsuColour.FromHex(@"3e3a44").Opacity(0.6f), OsuColour.FromHex(@"3e3a44")) + Colour = ColourInfo.GradientVertical(backgroundColour.Opacity(0.7f), backgroundColour) }, } } From f53349ac9d83dd65bed12cf3feba6ca82ad0509d Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Wed, 19 Feb 2020 19:54:07 +0900 Subject: [PATCH 26/72] Reduce size of participants tiles --- osu.Game/Screens/Multi/Components/ParticipantsList.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Multi/Components/ParticipantsList.cs b/osu.Game/Screens/Multi/Components/ParticipantsList.cs index 81d530ce68..e383e0414b 100644 --- a/osu.Game/Screens/Multi/Components/ParticipantsList.cs +++ b/osu.Game/Screens/Multi/Components/ParticipantsList.cs @@ -18,7 +18,7 @@ namespace osu.Game.Screens.Multi.Components { public class ParticipantsList : MultiplayerComposite { - public const float TILE_SIZE = 70; + public const float TILE_SIZE = 35; public override Axes RelativeSizeAxes { @@ -113,7 +113,7 @@ namespace osu.Game.Screens.Multi.Components public UserTile(User user) { this.user = user; - Size = new Vector2(70f); + Size = new Vector2(TILE_SIZE); CornerRadius = 5f; Masking = true; From 7b0c3281c29938ef01ff40949a954884bea87357 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 19 Feb 2020 16:49:39 +0300 Subject: [PATCH 27/72] Make country names clickable --- .../Rankings/Tables/CountriesTable.cs | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs index 32ac1404bc..0b9a48ce0e 100644 --- a/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs +++ b/osu.Game/Overlays/Rankings/Tables/CountriesTable.cs @@ -9,6 +9,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics; using System.Collections.Generic; using osu.Framework.Allocation; +using osu.Game.Graphics.Containers; namespace osu.Game.Overlays.Rankings.Tables { @@ -61,18 +62,35 @@ namespace osu.Game.Overlays.Rankings.Tables } }; - private class CountryName : OsuSpriteText + private class CountryName : OsuHoverContainer { + protected override IEnumerable EffectTargets => new[] { text }; + + [Resolved(canBeNull: true)] + private RankingsOverlay rankings { get; set; } + + private readonly OsuSpriteText text; + private readonly Country country; + public CountryName(Country country) { - Font = OsuFont.GetFont(size: 12); - Text = country.FullName ?? string.Empty; + this.country = country; + + AutoSizeAxes = Axes.Both; + Add(text = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 12), + Text = country.FullName ?? string.Empty, + }); } [BackgroundDependencyLoader] private void load(OverlayColourProvider colourProvider) { - Colour = colourProvider.Light2; + IdleColour = colourProvider.Light2; + HoverColour = colourProvider.Content2; + + Action = () => rankings?.ShowCountry(country); } } } From a79398ddbd698d165ee7b0e35242c7c4bd3f4641 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 19 Feb 2020 17:09:22 +0300 Subject: [PATCH 28/72] Fix incorrect caching in TestSceneRankingsOverlay --- osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs index a769ebe4a9..47582e5486 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs @@ -29,8 +29,9 @@ namespace osu.Game.Tests.Visual.Online typeof(RankingsOverlayHeader) }; - [Cached] - private RankingsOverlay rankingsOverlay; + [Cached(typeof(RankingsOverlay))] + + private readonly RankingsOverlay rankingsOverlay; private readonly Bindable countryBindable = new Bindable(); private readonly Bindable scope = new Bindable(); From 1417c901738a5be99f56629d02f055f91598e996 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 19 Feb 2020 17:24:44 +0300 Subject: [PATCH 29/72] Remove redundant blank line --- osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs index 47582e5486..83e5cd0fe7 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs @@ -30,7 +30,6 @@ namespace osu.Game.Tests.Visual.Online }; [Cached(typeof(RankingsOverlay))] - private readonly RankingsOverlay rankingsOverlay; private readonly Bindable countryBindable = new Bindable(); From 98654586de78a3d4ace7cd3ef4d60d7af26580b4 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 19 Feb 2020 17:28:14 +0300 Subject: [PATCH 30/72] Implement BeatmapListingHeader component --- .../BeatmapListing/BeatmapListingHeader.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs new file mode 100644 index 0000000000..5af92914de --- /dev/null +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs @@ -0,0 +1,24 @@ +// 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.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Overlays.BeatmapListing +{ + public class BeatmapListingHeader : OverlayHeader + { + protected override ScreenTitle CreateTitle() => new BeatmapListingTitle(); + + private class BeatmapListingTitle : ScreenTitle + { + public BeatmapListingTitle() + { + Title = @"beatmap"; + Section = @"listing"; + } + + protected override Drawable CreateIcon() => new ScreenTitleTextureIcon(@"Icons/changelog"); + } + } +} From 1442f5e0db37185c88fae5744d30e2c130904249 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 19 Feb 2020 17:30:26 +0300 Subject: [PATCH 31/72] Use DirectSortCriteria for BeatmapListingSortTabControl --- .../BeatmapListingSortTabControl.cs | 24 ++++++------------- osu.Game/Overlays/Direct/FilterControl.cs | 3 +-- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs index cb41b33bc4..27c43b092a 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs @@ -8,16 +8,17 @@ using osu.Framework.Graphics; using osuTK.Graphics; using osuTK; using osu.Framework.Input.Events; +using osu.Game.Overlays.Direct; namespace osu.Game.Overlays.BeatmapListing { - public class BeatmapListingSortTabControl : OverlaySortTabControl + public class BeatmapListingSortTabControl : OverlaySortTabControl { public readonly Bindable SortDirection = new Bindable(Overlays.SortDirection.Descending); public BeatmapListingSortTabControl() { - Current.Value = BeatmapSortCriteria.Ranked; + Current.Value = DirectSortCriteria.Ranked; } protected override SortTabControl CreateControl() => new BeatmapSortTabControl @@ -29,7 +30,7 @@ namespace osu.Game.Overlays.BeatmapListing { public readonly Bindable SortDirection = new Bindable(); - protected override TabItem CreateTabItem(BeatmapSortCriteria value) => new BeatmapSortTabItem(value) + protected override TabItem CreateTabItem(DirectSortCriteria value) => new BeatmapSortTabItem(value) { SortDirection = { BindTarget = SortDirection } }; @@ -39,12 +40,12 @@ namespace osu.Game.Overlays.BeatmapListing { public readonly Bindable SortDirection = new Bindable(); - public BeatmapSortTabItem(BeatmapSortCriteria value) + public BeatmapSortTabItem(DirectSortCriteria value) : base(value) { } - protected override TabButton CreateTabButton(BeatmapSortCriteria value) => new BeatmapTabButton(value) + protected override TabButton CreateTabButton(DirectSortCriteria value) => new BeatmapTabButton(value) { Active = { BindTarget = Active }, SortDirection = { BindTarget = SortDirection } @@ -66,7 +67,7 @@ namespace osu.Game.Overlays.BeatmapListing private readonly SpriteIcon icon; - public BeatmapTabButton(BeatmapSortCriteria value) + public BeatmapTabButton(DirectSortCriteria value) : base(value) { Add(icon = new SpriteIcon @@ -104,15 +105,4 @@ namespace osu.Game.Overlays.BeatmapListing } } } - - public enum BeatmapSortCriteria - { - Title, - Artist, - Difficulty, - Ranked, - Rating, - Plays, - Favourites, - } } diff --git a/osu.Game/Overlays/Direct/FilterControl.cs b/osu.Game/Overlays/Direct/FilterControl.cs index 8b04bf0387..70a3ab54fb 100644 --- a/osu.Game/Overlays/Direct/FilterControl.cs +++ b/osu.Game/Overlays/Direct/FilterControl.cs @@ -34,14 +34,13 @@ namespace osu.Game.Overlays.Direct public enum DirectSortCriteria { - Relevance, Title, Artist, - Creator, Difficulty, Ranked, Rating, Plays, Favourites, + Relevance, } } From 01202f09bec882209c314a34cf05543c3acaa0a0 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 19 Feb 2020 17:32:43 +0300 Subject: [PATCH 32/72] Expand SearchBeatmapSetsResponse --- osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs index 28863cb0e0..845c84430f 100644 --- a/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs +++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs @@ -2,12 +2,20 @@ // See the LICENCE file in the repository root for full licence text. using System.Collections.Generic; +using Newtonsoft.Json; using osu.Game.Online.API.Requests.Responses; namespace osu.Game.Online.API.Requests { public class SearchBeatmapSetsResponse : ResponseWithCursor { + [JsonProperty("beatmapsets")] public IEnumerable BeatmapSets; + + [JsonProperty("error")] + public string Error; + + [JsonProperty("total")] + public int Total; } } From 255c8d3a1306149ff396c96a1a7997ba6a3e9912 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 19 Feb 2020 17:33:48 +0300 Subject: [PATCH 33/72] Adjust SearchBeatmapSetsRequest for new usage --- .../API/Requests/SearchBeatmapSetsRequest.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs index 5652b8d2bd..930ca8fdf1 100644 --- a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs +++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System.ComponentModel; +using osu.Framework.IO.Network; using osu.Game.Overlays; using osu.Game.Overlays.Direct; using osu.Game.Rulesets; @@ -26,8 +27,21 @@ namespace osu.Game.Online.API.Requests this.direction = direction; } - // ReSharper disable once ImpureMethodCallOnReadonlyValueField - protected override string Target => $@"beatmapsets/search?q={query}&m={ruleset.ID ?? 0}&s={searchCategory.ToString().ToLowerInvariant()}&sort={sortCriteria.ToString().ToLowerInvariant()}_{directionString}"; + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + req.AddParameter("q", query); + + if (ruleset.ID.HasValue) + req.AddParameter("m", ruleset.ID.Value.ToString()); + + req.AddParameter("s", searchCategory.ToString().ToLowerInvariant()); + req.AddParameter("sort", $"{sortCriteria.ToString().ToLowerInvariant()}_{directionString}"); + + return req; + } + + protected override string Target => @"beatmapsets/search"; } public enum BeatmapSearchCategory From 8fcfb73d722b54380bd9b8b525eb38c38197b0ce Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 19 Feb 2020 17:40:54 +0300 Subject: [PATCH 34/72] Implement BeatmapListingOverlay --- .../Online/TestSceneBeatmapListingOverlay.cs | 39 +++ osu.Game/Overlays/BeatmapListingOverlay.cs | 229 ++++++++++++++++++ 2 files changed, 268 insertions(+) create mode 100644 osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs create mode 100644 osu.Game/Overlays/BeatmapListingOverlay.cs diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs new file mode 100644 index 0000000000..7c05d99c59 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs @@ -0,0 +1,39 @@ +// 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 osu.Game.Overlays; +using NUnit.Framework; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneBeatmapListingOverlay : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(BeatmapListingOverlay), + }; + + protected override bool UseOnlineAPI => true; + + private readonly BeatmapListingOverlay overlay; + + public TestSceneBeatmapListingOverlay() + { + Add(overlay = new BeatmapListingOverlay()); + } + + [Test] + public void TestShow() + { + AddStep("Show", overlay.Show); + } + + [Test] + public void TestHide() + { + AddStep("Hide", overlay.Hide); + } + } +} diff --git a/osu.Game/Overlays/BeatmapListingOverlay.cs b/osu.Game/Overlays/BeatmapListingOverlay.cs new file mode 100644 index 0000000000..971a1b46d2 --- /dev/null +++ b/osu.Game/Overlays/BeatmapListingOverlay.cs @@ -0,0 +1,229 @@ +// 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.Extensions.Color4Extensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Effects; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Threading; +using osu.Game.Audio; +using osu.Game.Beatmaps; +using osu.Game.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using osu.Game.Online.API.Requests; +using osu.Game.Overlays.BeatmapListing; +using osu.Game.Overlays.Direct; +using osu.Game.Rulesets; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Overlays +{ + public class BeatmapListingOverlay : FullscreenOverlay + { + [Resolved] + private PreviewTrackManager previewTrackManager { get; set; } + + [Resolved] + private RulesetStore rulesets { get; set; } + + private SearchBeatmapSetsRequest getSetsRequest; + private Container panelsPlaceholder; + private BeatmapListingSearchSection searchSection; + private BeatmapListingSortTabControl sortControl; + + public BeatmapListingOverlay() + : base(OverlayColourScheme.Blue) + { + } + + [BackgroundDependencyLoader] + private void load() + { + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourProvider.Background6 + }, + new BasicScrollContainer + { + RelativeSizeAxes = Axes.Both, + ScrollbarVisible = false, + Child = new ReverseChildIDFillFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 10), + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + Masking = true, + EdgeEffect = new EdgeEffectParameters + { + Colour = Color4.Black.Opacity(0.25f), + Type = EdgeEffectType.Shadow, + Radius = 3, + Offset = new Vector2(0f, 1f), + }, + Children = new Drawable[] + { + new BeatmapListingHeader(), + searchSection = new BeatmapListingSearchSection(), + } + }, + new Container + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourProvider.Background4, + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new Container + { + RelativeSizeAxes = Axes.X, + Height = 40, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = ColourProvider.Background5 + }, + sortControl = new BeatmapListingSortTabControl + { + Anchor = Anchor.CentreLeft, + Origin = Anchor.CentreLeft, + Margin = new MarginPadding { Left = 20 } + } + } + }, + panelsPlaceholder = new Container + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Padding = new MarginPadding { Vertical = 15, Horizontal = 20 }, + } + } + } + } + } + } + } + } + }; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + var sortCriteria = sortControl.Current; + var sortDirection = sortControl.SortDirection; + + searchSection.Query.BindValueChanged(query => + { + sortCriteria.Value = string.IsNullOrEmpty(query.NewValue) ? DirectSortCriteria.Ranked : DirectSortCriteria.Relevance; + sortDirection.Value = SortDirection.Descending; + + Scheduler.AddOnce(updateSearch); + }); + + searchSection.Query.BindValueChanged(_ => Scheduler.AddOnce(updateSearch)); + searchSection.Ruleset.BindValueChanged(_ => Scheduler.AddOnce(updateSearch)); + searchSection.Category.BindValueChanged(_ => Scheduler.AddOnce(updateSearch)); + sortCriteria.BindValueChanged(_ => Scheduler.AddOnce(updateSearch)); + sortDirection.BindValueChanged(_ => Scheduler.AddOnce(updateSearch)); + } + + private void updateSearch() + { + if (!IsLoaded) + return; + + if (State.Value == Visibility.Hidden) + return; + + if (API == null) + return; + + getSetsRequest?.Cancel(); + previewTrackManager.StopAnyPlaying(this); + + panelsPlaceholder.FadeColour(Color4.DimGray, 400, Easing.OutQuint); + + getSetsRequest = new SearchBeatmapSetsRequest( + searchSection.Query.Value, + searchSection.Ruleset.Value, + searchSection.Category.Value, + sortControl.Current.Value, + sortControl.SortDirection.Value); + + getSetsRequest.Success += response => Schedule(() => recreatePanels(response)); + + API.Queue(getSetsRequest); + } + + private void recreatePanels(SearchBeatmapSetsResponse response) + { + var beatmaps = response.BeatmapSets.Select(r => r.ToBeatmapSet(rulesets)).ToList(); + + var hasError = !string.IsNullOrEmpty(response.Error); + + if (response.Total == 0 || hasError) + { + searchSection.BeatmapSet = null; + panelsPlaceholder.Clear(); + panelsPlaceholder.FadeColour(Color4.White); + panelsPlaceholder.Add(new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = hasError ? response.Error : @"... nope, nothing found." + }); + return; + } + + var newPanels = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(10), + Alpha = 0, + ChildrenEnumerable = beatmaps.Select(b => new DirectGridPanel(b) + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + }) + }; + + LoadComponentAsync(newPanels, loaded => + { + panelsPlaceholder.Clear(); + panelsPlaceholder.FadeColour(Color4.White); + panelsPlaceholder.Add(loaded); + loaded.FadeIn(600, Easing.OutQuint); + searchSection.BeatmapSet = beatmaps.First(); + }); + } + } +} From 0c78c8cb4f19283c2b680e1db1d173fbc8fef07d Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 19 Feb 2020 17:44:15 +0300 Subject: [PATCH 35/72] Update resources --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index b9b127309a..b9ef783b2a 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -53,7 +53,7 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index bd5219b872..6b8f8fee8c 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -22,7 +22,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 2c1aff7d3c..f68bedc57f 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -73,7 +73,7 @@ - + From 237be50e37159c0a7f3f97fc434c76a2f1e0c4aa Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 19 Feb 2020 18:17:02 +0300 Subject: [PATCH 36/72] Implement DrawableErrorHandler component --- osu.Game/Overlays/BeatmapListingOverlay.cs | 90 ++++++++++++++++++---- 1 file changed, 76 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/BeatmapListingOverlay.cs b/osu.Game/Overlays/BeatmapListingOverlay.cs index 971a1b46d2..eacf883339 100644 --- a/osu.Game/Overlays/BeatmapListingOverlay.cs +++ b/osu.Game/Overlays/BeatmapListingOverlay.cs @@ -2,12 +2,15 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; +using System.Threading; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; using osu.Framework.Threading; using osu.Game.Audio; using osu.Game.Beatmaps; @@ -31,6 +34,8 @@ namespace osu.Game.Overlays private RulesetStore rulesets { get; set; } private SearchBeatmapSetsRequest getSetsRequest; + private CancellationTokenSource cancellationToken; + private Container panelsPlaceholder; private BeatmapListingSearchSection searchSection; private BeatmapListingSortTabControl sortControl; @@ -121,7 +126,7 @@ namespace osu.Game.Overlays { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, - Padding = new MarginPadding { Vertical = 15, Horizontal = 20 }, + Padding = new MarginPadding { Horizontal = 20 }, } } } @@ -167,6 +172,7 @@ namespace osu.Game.Overlays return; getSetsRequest?.Cancel(); + cancellationToken?.Cancel(); previewTrackManager.StopAnyPlaying(this); panelsPlaceholder.FadeColour(Color4.DimGray, 400, Easing.OutQuint); @@ -185,30 +191,28 @@ namespace osu.Game.Overlays private void recreatePanels(SearchBeatmapSetsResponse response) { - var beatmaps = response.BeatmapSets.Select(r => r.ToBeatmapSet(rulesets)).ToList(); - var hasError = !string.IsNullOrEmpty(response.Error); if (response.Total == 0 || hasError) { searchSection.BeatmapSet = null; - panelsPlaceholder.Clear(); - panelsPlaceholder.FadeColour(Color4.White); - panelsPlaceholder.Add(new OsuSpriteText + + LoadComponentAsync(new DrawableErrorHandler(hasError ? response.Error : @"... nope, nothing found."), loaded => { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Text = hasError ? response.Error : @"... nope, nothing found." - }); + addContentToPlaceholder(loaded); + }, (cancellationToken = new CancellationTokenSource()).Token); return; } + var beatmaps = response.BeatmapSets.Select(r => r.ToBeatmapSet(rulesets)).ToList(); + var newPanels = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Spacing = new Vector2(10), Alpha = 0, + Margin = new MarginPadding { Vertical = 15 }, ChildrenEnumerable = beatmaps.Select(b => new DirectGridPanel(b) { Anchor = Anchor.TopCentre, @@ -218,12 +222,70 @@ namespace osu.Game.Overlays LoadComponentAsync(newPanels, loaded => { - panelsPlaceholder.Clear(); - panelsPlaceholder.FadeColour(Color4.White); - panelsPlaceholder.Add(loaded); + addContentToPlaceholder(loaded); loaded.FadeIn(600, Easing.OutQuint); searchSection.BeatmapSet = beatmaps.First(); - }); + }, (cancellationToken = new CancellationTokenSource()).Token); + } + + private void addContentToPlaceholder(Drawable content) + { + panelsPlaceholder.Clear(); + panelsPlaceholder.FadeColour(Color4.White); + panelsPlaceholder.Add(content); + } + + protected override void Dispose(bool isDisposing) + { + getSetsRequest?.Cancel(); + cancellationToken?.Cancel(); + + base.Dispose(isDisposing); + } + + private class DrawableErrorHandler : CompositeDrawable + { + private readonly string error; + + public DrawableErrorHandler(string error) + { + this.error = error; + + RelativeSizeAxes = Axes.X; + Height = 250; + Margin = new MarginPadding { Top = 15 }; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + AddInternal(new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Y, + AutoSizeAxes = Axes.X, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new Drawable[] + { + new Sprite + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fit, + Texture = textures.Get(@"Online/not-found") + }, + new OsuSpriteText + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Text = error, + } + } + }); + } } } } From 2ef3c7873605f8dcb7b61bacc5cf90bfe2359b3a Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 19 Feb 2020 18:19:15 +0300 Subject: [PATCH 37/72] Remove query binding duplicate --- osu.Game/Overlays/BeatmapListingOverlay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapListingOverlay.cs b/osu.Game/Overlays/BeatmapListingOverlay.cs index eacf883339..143e20d69f 100644 --- a/osu.Game/Overlays/BeatmapListingOverlay.cs +++ b/osu.Game/Overlays/BeatmapListingOverlay.cs @@ -153,7 +153,6 @@ namespace osu.Game.Overlays Scheduler.AddOnce(updateSearch); }); - searchSection.Query.BindValueChanged(_ => Scheduler.AddOnce(updateSearch)); searchSection.Ruleset.BindValueChanged(_ => Scheduler.AddOnce(updateSearch)); searchSection.Category.BindValueChanged(_ => Scheduler.AddOnce(updateSearch)); sortCriteria.BindValueChanged(_ => Scheduler.AddOnce(updateSearch)); From edef84d9c388588749a390be116240653f80bd8c Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Wed, 19 Feb 2020 19:15:18 +0300 Subject: [PATCH 38/72] CI fixes --- osu.Game/Overlays/BeatmapListingOverlay.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/BeatmapListingOverlay.cs b/osu.Game/Overlays/BeatmapListingOverlay.cs index 143e20d69f..546d0bc9bb 100644 --- a/osu.Game/Overlays/BeatmapListingOverlay.cs +++ b/osu.Game/Overlays/BeatmapListingOverlay.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.Threading; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; @@ -196,10 +195,9 @@ namespace osu.Game.Overlays { searchSection.BeatmapSet = null; - LoadComponentAsync(new DrawableErrorHandler(hasError ? response.Error : @"... nope, nothing found."), loaded => - { - addContentToPlaceholder(loaded); - }, (cancellationToken = new CancellationTokenSource()).Token); + LoadComponentAsync(new DrawableErrorHandler(hasError ? response.Error : @"... nope, nothing found."), + addContentToPlaceholder, + (cancellationToken = new CancellationTokenSource()).Token); return; } From 62227ad856efb44cf4cb26c31d2965b9e30e277e Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Wed, 19 Feb 2020 17:58:10 +0100 Subject: [PATCH 39/72] Add MaxCombo to BeatmapInfo --- osu.Game/Beatmaps/BeatmapInfo.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapInfo.cs b/osu.Game/Beatmaps/BeatmapInfo.cs index bcc9ab885e..68d113ce40 100644 --- a/osu.Game/Beatmaps/BeatmapInfo.cs +++ b/osu.Game/Beatmaps/BeatmapInfo.cs @@ -51,6 +51,9 @@ namespace osu.Game.Beatmaps [NotMapped] public BeatmapOnlineInfo OnlineInfo { get; set; } + [NotMapped] + public int? MaxCombo { get; set; } + /// /// The playable length in milliseconds of this beatmap. /// From 23c9782f509c5af8f543bedcf57a7c5d1c8e2154 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Wed, 19 Feb 2020 17:58:41 +0100 Subject: [PATCH 40/72] Add maxCombo to APIBeatmap --- osu.Game/Online/API/Requests/Responses/APIBeatmap.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs index f4d67a56aa..e023a2502f 100644 --- a/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs +++ b/osu.Game/Online/API/Requests/Responses/APIBeatmap.cs @@ -61,6 +61,9 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"failtimes")] private BeatmapMetrics metrics { get; set; } + [JsonProperty(@"max_combo")] + private int? maxCombo { get; set; } + public BeatmapInfo ToBeatmap(RulesetStore rulesets) { var set = BeatmapSet?.ToBeatmapSet(rulesets); @@ -76,6 +79,7 @@ namespace osu.Game.Online.API.Requests.Responses Status = Status, BeatmapSet = set, Metrics = metrics, + MaxCombo = maxCombo, BaseDifficulty = new BeatmapDifficulty { DrainRate = drainRate, From 7ea67aa6726428198498d299e17f7a16c360caad Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Wed, 19 Feb 2020 17:58:59 +0100 Subject: [PATCH 41/72] Highlight max combo on beatmap leaderboards --- osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 43a45bd2fc..cf7ecd7408 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -146,7 +146,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores new OsuSpriteText { Text = $@"{score.MaxCombo:N0}x", - Font = OsuFont.GetFont(size: text_size) + Font = OsuFont.GetFont(size: text_size), + Colour = score.MaxCombo == score.Beatmap.MaxCombo ? highAccuracyColour : Color4.White } }); From 84d6a8ae2ade456f1f4b4e71f2c43b1e4fe980b4 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Wed, 19 Feb 2020 19:42:56 +0100 Subject: [PATCH 42/72] Add null check --- osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index cf7ecd7408..954eada612 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -147,7 +147,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { Text = $@"{score.MaxCombo:N0}x", Font = OsuFont.GetFont(size: text_size), - Colour = score.MaxCombo == score.Beatmap.MaxCombo ? highAccuracyColour : Color4.White + Colour = score.MaxCombo == score.Beatmap?.MaxCombo ? highAccuracyColour : Color4.White } }); From b2d9004212c5221f751d4bba813f2d4630acf375 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Feb 2020 08:37:23 +0900 Subject: [PATCH 43/72] Fix possible test failures due to async loads --- .../TestSceneDrawableRoomPlaylist.cs | 57 ++++++++++++------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs index 4f54e451b7..9fbe8f7ffe 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneDrawableRoomPlaylist.cs @@ -28,7 +28,7 @@ namespace osu.Game.Tests.Visual.Multiplayer typeof(DrawableRoomPlaylistItem) }; - private DrawableRoomPlaylist playlist; + private TestPlaylist playlist; [Test] public void TestNonEditableNonSelectable() @@ -211,30 +211,45 @@ namespace osu.Game.Tests.Visual.Multiplayer private void assertDeleteButtonVisibility(int index, bool visible) => AddAssert($"delete button {index} {(visible ? "is" : "is not")} visible", () => (playlist.ChildrenOfType().ElementAt(2 + index * 2).Alpha > 0) == visible); - private void createPlaylist(bool allowEdit, bool allowSelection) => AddStep("create playlist", () => + private void createPlaylist(bool allowEdit, bool allowSelection) { - Child = playlist = new DrawableRoomPlaylist(allowEdit, allowSelection) + AddStep("create playlist", () => { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(500, 300) - }; - - for (int i = 0; i < 20; i++) - { - playlist.Items.Add(new PlaylistItem + Child = playlist = new TestPlaylist(allowEdit, allowSelection) { - ID = i, - Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, - Ruleset = { Value = new OsuRuleset().RulesetInfo }, - RequiredMods = + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(500, 300) + }; + + for (int i = 0; i < 20; i++) + { + playlist.Items.Add(new PlaylistItem { - new OsuModHardRock(), - new OsuModDoubleTime(), - new OsuModAutoplay() - } - }); + ID = i, + Beatmap = { Value = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo }, + Ruleset = { Value = new OsuRuleset().RulesetInfo }, + RequiredMods = + { + new OsuModHardRock(), + new OsuModDoubleTime(), + new OsuModAutoplay() + } + }); + } + }); + + AddUntilStep("wait for items to load", () => playlist.ItemMap.Values.All(i => i.IsLoaded)); + } + + private class TestPlaylist : DrawableRoomPlaylist + { + public new IReadOnlyDictionary> ItemMap => base.ItemMap; + + public TestPlaylist(bool allowEdit, bool allowSelection) + : base(allowEdit, allowSelection) + { } - }); + } } } From 7550685a614eaff25adef260a5344e254944be69 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 20 Feb 2020 02:43:13 +0300 Subject: [PATCH 44/72] DrawableErrorHandler -> NotFoundDrawable --- .../API/Requests/SearchBeatmapSetsResponse.cs | 3 --- osu.Game/Overlays/BeatmapListingOverlay.cs | 18 +++++------------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs index 845c84430f..3c4fb11ed1 100644 --- a/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs +++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs @@ -12,9 +12,6 @@ namespace osu.Game.Online.API.Requests [JsonProperty("beatmapsets")] public IEnumerable BeatmapSets; - [JsonProperty("error")] - public string Error; - [JsonProperty("total")] public int Total; } diff --git a/osu.Game/Overlays/BeatmapListingOverlay.cs b/osu.Game/Overlays/BeatmapListingOverlay.cs index 546d0bc9bb..414e911f2e 100644 --- a/osu.Game/Overlays/BeatmapListingOverlay.cs +++ b/osu.Game/Overlays/BeatmapListingOverlay.cs @@ -189,15 +189,11 @@ namespace osu.Game.Overlays private void recreatePanels(SearchBeatmapSetsResponse response) { - var hasError = !string.IsNullOrEmpty(response.Error); - - if (response.Total == 0 || hasError) + if (response.Total == 0) { searchSection.BeatmapSet = null; - LoadComponentAsync(new DrawableErrorHandler(hasError ? response.Error : @"... nope, nothing found."), - addContentToPlaceholder, - (cancellationToken = new CancellationTokenSource()).Token); + LoadComponentAsync(new NotFoundDrawable(), addContentToPlaceholder, (cancellationToken = new CancellationTokenSource()).Token); return; } @@ -240,14 +236,10 @@ namespace osu.Game.Overlays base.Dispose(isDisposing); } - private class DrawableErrorHandler : CompositeDrawable + private class NotFoundDrawable : CompositeDrawable { - private readonly string error; - - public DrawableErrorHandler(string error) + public NotFoundDrawable() { - this.error = error; - RelativeSizeAxes = Axes.X; Height = 250; Margin = new MarginPadding { Top = 15 }; @@ -278,7 +270,7 @@ namespace osu.Game.Overlays { Anchor = Anchor.Centre, Origin = Anchor.Centre, - Text = error, + Text = @"... nope, nothing found.", } } }); From 66ea7949358fe9ae9a7dd0c4e5839c39e63ca903 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 20 Feb 2020 02:54:35 +0300 Subject: [PATCH 45/72] Add debounce to the querying --- osu.Game/Overlays/BeatmapListingOverlay.cs | 32 +++++++++++++--------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/osu.Game/Overlays/BeatmapListingOverlay.cs b/osu.Game/Overlays/BeatmapListingOverlay.cs index 414e911f2e..2a812ddf96 100644 --- a/osu.Game/Overlays/BeatmapListingOverlay.cs +++ b/osu.Game/Overlays/BeatmapListingOverlay.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using System.Linq; -using System.Threading; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; @@ -11,6 +10,7 @@ using osu.Framework.Graphics.Effects; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; +using osu.Framework.Threading; using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Graphics.Containers; @@ -33,7 +33,6 @@ namespace osu.Game.Overlays private RulesetStore rulesets { get; set; } private SearchBeatmapSetsRequest getSetsRequest; - private CancellationTokenSource cancellationToken; private Container panelsPlaceholder; private BeatmapListingSearchSection searchSection; @@ -149,13 +148,23 @@ namespace osu.Game.Overlays sortCriteria.Value = string.IsNullOrEmpty(query.NewValue) ? DirectSortCriteria.Ranked : DirectSortCriteria.Relevance; sortDirection.Value = SortDirection.Descending; - Scheduler.AddOnce(updateSearch); + queueUpdateSearch(true); }); - searchSection.Ruleset.BindValueChanged(_ => Scheduler.AddOnce(updateSearch)); - searchSection.Category.BindValueChanged(_ => Scheduler.AddOnce(updateSearch)); - sortCriteria.BindValueChanged(_ => Scheduler.AddOnce(updateSearch)); - sortDirection.BindValueChanged(_ => Scheduler.AddOnce(updateSearch)); + searchSection.Ruleset.BindValueChanged(_ => queueUpdateSearch()); + searchSection.Category.BindValueChanged(_ => queueUpdateSearch()); + sortCriteria.BindValueChanged(_ => queueUpdateSearch()); + sortDirection.BindValueChanged(_ => queueUpdateSearch()); + } + + private ScheduledDelegate queryChangedDebounce; + + private void queueUpdateSearch(bool queryTextChanged = false) + { + getSetsRequest?.Cancel(); + + queryChangedDebounce?.Cancel(); + queryChangedDebounce = Scheduler.AddDelayed(updateSearch, queryTextChanged ? 500 : 100); } private void updateSearch() @@ -169,8 +178,6 @@ namespace osu.Game.Overlays if (API == null) return; - getSetsRequest?.Cancel(); - cancellationToken?.Cancel(); previewTrackManager.StopAnyPlaying(this); panelsPlaceholder.FadeColour(Color4.DimGray, 400, Easing.OutQuint); @@ -192,8 +199,7 @@ namespace osu.Game.Overlays if (response.Total == 0) { searchSection.BeatmapSet = null; - - LoadComponentAsync(new NotFoundDrawable(), addContentToPlaceholder, (cancellationToken = new CancellationTokenSource()).Token); + LoadComponentAsync(new NotFoundDrawable(), addContentToPlaceholder); return; } @@ -218,7 +224,7 @@ namespace osu.Game.Overlays addContentToPlaceholder(loaded); loaded.FadeIn(600, Easing.OutQuint); searchSection.BeatmapSet = beatmaps.First(); - }, (cancellationToken = new CancellationTokenSource()).Token); + }); } private void addContentToPlaceholder(Drawable content) @@ -231,7 +237,7 @@ namespace osu.Game.Overlays protected override void Dispose(bool isDisposing) { getSetsRequest?.Cancel(); - cancellationToken?.Cancel(); + queryChangedDebounce?.Cancel(); base.Dispose(isDisposing); } From a8c735b66d7268f1eadeee59cacf8ae345839010 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 20 Feb 2020 04:19:50 +0300 Subject: [PATCH 46/72] Change default category value --- osu.Game/Overlays/BeatmapListing/BeatmapListingSearchSection.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchSection.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchSection.cs index f47144e5d8..f9799d8a6b 100644 --- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchSection.cs +++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchSection.cs @@ -104,6 +104,8 @@ namespace osu.Game.Overlays.BeatmapListing } } }); + + Category.Value = BeatmapSearchCategory.Leaderboard; } [BackgroundDependencyLoader] From 907c1b3d1c73d9eaca1c2d022ee27653ce13c111 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Feb 2020 10:48:12 +0900 Subject: [PATCH 47/72] Add missing test banana resources --- .../old-skin/fruit-bananas-overlay.png | Bin 0 -> 7823 bytes .../Resources/old-skin/fruit-bananas.png | Bin 0 -> 14274 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 osu.Game.Rulesets.Catch.Tests/Resources/old-skin/fruit-bananas-overlay.png create mode 100644 osu.Game.Rulesets.Catch.Tests/Resources/old-skin/fruit-bananas.png diff --git a/osu.Game.Rulesets.Catch.Tests/Resources/old-skin/fruit-bananas-overlay.png b/osu.Game.Rulesets.Catch.Tests/Resources/old-skin/fruit-bananas-overlay.png new file mode 100644 index 0000000000000000000000000000000000000000..3a6612378e5cc655ec5d9d8ea7c53486c5a6270b GIT binary patch literal 7823 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 a2zU=&wPGnM{AV5mfVTP*wOSSX=>GxIE#JKW literal 0 HcmV?d00001 diff --git a/osu.Game.Rulesets.Catch.Tests/Resources/old-skin/fruit-bananas.png b/osu.Game.Rulesets.Catch.Tests/Resources/old-skin/fruit-bananas.png new file mode 100644 index 0000000000000000000000000000000000000000..afb8698b2d8ff7285d53e140bcf0c5379ef8a6c6 GIT binary patch literal 14274 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 literal 0 HcmV?d00001 From 1935a14288c3c9fedb9e73e45ffd1d7a77a20c92 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Thu, 20 Feb 2020 05:08:42 +0300 Subject: [PATCH 48/72] Adjust animations to be much smoother --- osu.Game/Overlays/BeatmapListingOverlay.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/osu.Game/Overlays/BeatmapListingOverlay.cs b/osu.Game/Overlays/BeatmapListingOverlay.cs index 2a812ddf96..da67226eac 100644 --- a/osu.Game/Overlays/BeatmapListingOverlay.cs +++ b/osu.Game/Overlays/BeatmapListingOverlay.cs @@ -35,6 +35,7 @@ namespace osu.Game.Overlays private SearchBeatmapSetsRequest getSetsRequest; private Container panelsPlaceholder; + private Drawable currentContent; private BeatmapListingSearchSection searchSection; private BeatmapListingSortTabControl sortControl; @@ -124,6 +125,8 @@ namespace osu.Game.Overlays { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, + AutoSizeEasing = Easing.Out, + AutoSizeDuration = 200, Padding = new MarginPadding { Horizontal = 20 }, } } @@ -180,7 +183,7 @@ namespace osu.Game.Overlays previewTrackManager.StopAnyPlaying(this); - panelsPlaceholder.FadeColour(Color4.DimGray, 400, Easing.OutQuint); + currentContent?.FadeColour(Color4.DimGray, 400, Easing.OutQuint); getSetsRequest = new SearchBeatmapSetsRequest( searchSection.Query.Value, @@ -222,16 +225,15 @@ namespace osu.Game.Overlays LoadComponentAsync(newPanels, loaded => { addContentToPlaceholder(loaded); - loaded.FadeIn(600, Easing.OutQuint); searchSection.BeatmapSet = beatmaps.First(); }); } private void addContentToPlaceholder(Drawable content) { - panelsPlaceholder.Clear(); - panelsPlaceholder.FadeColour(Color4.White); - panelsPlaceholder.Add(content); + currentContent?.FadeOut(100, Easing.OutQuint).Expire(); + panelsPlaceholder.Add(currentContent = content); + currentContent.FadeIn(200, Easing.OutQuint); } protected override void Dispose(bool isDisposing) @@ -248,6 +250,7 @@ namespace osu.Game.Overlays { RelativeSizeAxes = Axes.X; Height = 250; + Alpha = 0; Margin = new MarginPadding { Top = 15 }; } From 00d8be92356065111503c18f444e6a5c5b5d9931 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Feb 2020 13:48:34 +0900 Subject: [PATCH 49/72] Adjust height transition --- osu.Game/Overlays/BeatmapListingOverlay.cs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/BeatmapListingOverlay.cs b/osu.Game/Overlays/BeatmapListingOverlay.cs index da67226eac..213e9a4244 100644 --- a/osu.Game/Overlays/BeatmapListingOverlay.cs +++ b/osu.Game/Overlays/BeatmapListingOverlay.cs @@ -125,8 +125,6 @@ namespace osu.Game.Overlays { AutoSizeAxes = Axes.Y, RelativeSizeAxes = Axes.X, - AutoSizeEasing = Easing.Out, - AutoSizeDuration = 200, Padding = new MarginPadding { Horizontal = 20 }, } } @@ -231,7 +229,19 @@ namespace osu.Game.Overlays private void addContentToPlaceholder(Drawable content) { - currentContent?.FadeOut(100, Easing.OutQuint).Expire(); + Drawable lastContent = currentContent; + + if (lastContent != null) + { + lastContent.FadeOut(100, Easing.OutQuint).Expire(); + + // Consider the case when the new content is smaller than the last content. + // If the auto-size computation is delayed until fade out completes, the background remain high for too long making the resulting transition to the smaller height look weird. + // At the same time, if the last content's height is bypassed immediately, there is a period where the new content is at Alpha = 0 when the auto-sized height will be 0. + // To resolve both of these issues, the bypass is delayed until a point when the content transitions (fade-in and fade-out) overlap and it looks good to do so. + lastContent.Delay(25).Schedule(() => lastContent.BypassAutoSizeAxes = Axes.Y); + } + panelsPlaceholder.Add(currentContent = content); currentContent.FadeIn(200, Easing.OutQuint); } From 51f03d0f075489ecb67c4946d55a8cab5cd07ecd Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Thu, 20 Feb 2020 14:28:38 +0900 Subject: [PATCH 50/72] Adjust comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bartłomiej Dach --- osu.Game/Screens/Multi/Multiplayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 07d930fa75..54af8ab107 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -109,7 +109,7 @@ namespace osu.Game.Screens.Multi new HeaderBackgroundSprite { RelativeSizeAxes = Axes.X, - Height = 400 // Keep a static height so the header doesn't change as it's resized + Height = 400 // Keep a static height so the header doesn't change as it's resized between subscreens }, } }, From 17b669fdf74c456515dbd1daca4d0a1a86625c75 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Feb 2020 14:32:16 +0900 Subject: [PATCH 51/72] Refactor to detail the sizing mode setting --- .../Screens/Multi/Components/OverlinedDisplay.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/osu.Game/Screens/Multi/Components/OverlinedDisplay.cs b/osu.Game/Screens/Multi/Components/OverlinedDisplay.cs index 600fa99a9a..71cabd8b50 100644 --- a/osu.Game/Screens/Multi/Components/OverlinedDisplay.cs +++ b/osu.Game/Screens/Multi/Components/OverlinedDisplay.cs @@ -104,15 +104,13 @@ namespace osu.Game.Screens.Multi.Components new Dimension(AutoSizeAxes.HasFlag(Axes.Y) ? GridSizeMode.AutoSize : GridSizeMode.Distributed), }; - grid.AutoSizeAxes = Axes.None; - grid.RelativeSizeAxes = Axes.None; - grid.AutoSizeAxes = AutoSizeAxes; - grid.RelativeSizeAxes = ~AutoSizeAxes; + // Assigning to none is done so that setting auto and relative size modes doesn't cause exceptions to be thrown + grid.AutoSizeAxes = Content.AutoSizeAxes = Axes.None; + grid.RelativeSizeAxes = Content.RelativeSizeAxes = Axes.None; - Content.AutoSizeAxes = Axes.None; - Content.RelativeSizeAxes = Axes.None; - Content.AutoSizeAxes = grid.AutoSizeAxes; - Content.RelativeSizeAxes = grid.RelativeSizeAxes; + // Auto-size when required, otherwise eagerly relative-size + grid.AutoSizeAxes = Content.AutoSizeAxes = AutoSizeAxes; + grid.RelativeSizeAxes = Content.RelativeSizeAxes = ~AutoSizeAxes; } } } From c5fd969568c1c9c2e22acde5559007d55d5325ba Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Feb 2020 14:33:13 +0900 Subject: [PATCH 52/72] Fix 0 size in test scene --- .../Visual/Multiplayer/TestSceneOverlinedPlaylist.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs index 4e38f6d2c2..9a6273d075 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs @@ -27,12 +27,11 @@ namespace osu.Game.Tests.Visual.Multiplayer }); } - Add(new Container + Add(new OverlinedPlaylist(false) { Anchor = Anchor.Centre, Origin = Anchor.Centre, Size = new Vector2(500), - Child = new OverlinedPlaylist(false) }); } } From 177935d644be16be513d48b9baa724aaf4b64a10 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Feb 2020 14:45:35 +0900 Subject: [PATCH 53/72] Remove unused using --- osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs index 9a6273d075..14b7934dc7 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneOverlinedPlaylist.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Graphics; -using osu.Framework.Graphics.Containers; using osu.Game.Online.Multiplayer; using osu.Game.Rulesets.Osu; using osu.Game.Screens.Multi.Components; From 1a689231c2d14326d5b9b5525e9669e11d1fdaa7 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Feb 2020 14:51:25 +0900 Subject: [PATCH 54/72] Support null leaderboard position --- .../SongSelect/TestSceneBeatmapLeaderboard.cs | 27 +++++++++++++++++++ .../API/Requests/Responses/APILegacyScores.cs | 2 +- .../Online/Leaderboards/LeaderboardScore.cs | 6 ++--- .../BeatmapSet/Scores/ScoresContainer.cs | 6 ++++- 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index 3eff75b020..1198488bda 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -59,6 +59,33 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep(@"None selected", () => leaderboard.SetRetrievalState(PlaceholderState.NoneSelected)); foreach (BeatmapSetOnlineStatus status in Enum.GetValues(typeof(BeatmapSetOnlineStatus))) AddStep($"{status} beatmap", () => showBeatmapWithStatus(status)); + AddStep("null personal best position", showPersonalBestWithNullPosition); + } + + private void showPersonalBestWithNullPosition() + { + leaderboard.TopScore = new APILegacyUserTopScoreInfo + { + Position = null, + Score = new APILegacyScoreInfo + { + Rank = ScoreRank.XH, + Accuracy = 1, + MaxCombo = 244, + TotalScore = 1707827, + Mods = new[] { new OsuModHidden().Acronym, new OsuModHardRock().Acronym, }, + User = new User + { + Id = 6602580, + Username = @"waaiiru", + Country = new Country + { + FullName = @"Spain", + FlagName = @"ES", + }, + }, + } + }; } private void showPersonalBest() diff --git a/osu.Game/Online/API/Requests/Responses/APILegacyScores.cs b/osu.Game/Online/API/Requests/Responses/APILegacyScores.cs index 318fcb00de..75be9171b0 100644 --- a/osu.Game/Online/API/Requests/Responses/APILegacyScores.cs +++ b/osu.Game/Online/API/Requests/Responses/APILegacyScores.cs @@ -18,7 +18,7 @@ namespace osu.Game.Online.API.Requests.Responses public class APILegacyUserTopScoreInfo { [JsonProperty(@"position")] - public int Position; + public int? Position; [JsonProperty(@"score")] public APILegacyScoreInfo Score; diff --git a/osu.Game/Online/Leaderboards/LeaderboardScore.cs b/osu.Game/Online/Leaderboards/LeaderboardScore.cs index 1f52a4481b..ba92b993a2 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardScore.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardScore.cs @@ -41,7 +41,7 @@ namespace osu.Game.Online.Leaderboards protected Container RankContainer { get; private set; } private readonly ScoreInfo score; - private readonly int rank; + private readonly int? rank; private readonly bool allowHighlight; private Box background; @@ -58,7 +58,7 @@ namespace osu.Game.Online.Leaderboards [Resolved(CanBeNull = true)] private DialogOverlay dialogOverlay { get; set; } - public LeaderboardScore(ScoreInfo score, int rank, bool allowHighlight = true) + public LeaderboardScore(ScoreInfo score, int? rank, bool allowHighlight = true) { this.score = score; this.rank = rank; @@ -90,7 +90,7 @@ namespace osu.Game.Online.Leaderboards Anchor = Anchor.Centre, Origin = Anchor.Centre, Font = OsuFont.GetFont(size: 20, italics: true), - Text = rank.ToMetric(decimals: rank < 100000 ? 1 : 0), + Text = rank == null ? "-" : rank.Value.ToMetric(decimals: rank < 100000 ? 1 : 0), }, }, }, diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 2d8bd10b13..0d0dd08a0f 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.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.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -70,7 +71,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores topScoresContainer.Add(new DrawableTopScore(topScore)); if (userScoreInfo != null && userScoreInfo.OnlineScoreID != topScore.OnlineScoreID) - topScoresContainer.Add(new DrawableTopScore(userScoreInfo, userScore.Position)); + { + Debug.Assert(userScore.Position != null); + topScoresContainer.Add(new DrawableTopScore(userScoreInfo, userScore.Position.Value)); + } }); } From d79ca97fe901affe1c91172d18e246a78a840c2c Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Thu, 20 Feb 2020 15:04:12 +0900 Subject: [PATCH 55/72] Make beatmap scores also support null position --- .../Visual/Online/TestSceneScoresContainer.cs | 29 +++++++++++++++++++ .../BeatmapSet/Scores/DrawableTopScore.cs | 2 +- .../BeatmapSet/Scores/ScoresContainer.cs | 6 +--- .../BeatmapSet/Scores/TopScoreUserSection.cs | 4 +-- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs index 3c959e05c1..51f4089058 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneScoresContainer.cs @@ -195,6 +195,29 @@ namespace osu.Game.Tests.Visual.Online Position = 1337, }; + var myBestScoreWithNullPosition = new APILegacyUserTopScoreInfo + { + Score = new APILegacyScoreInfo + { + User = new User + { + Id = 7151382, + Username = @"Mayuri Hana", + Country = new Country + { + FullName = @"Thailand", + FlagName = @"TH", + }, + }, + Rank = ScoreRank.D, + PP = 160, + MaxCombo = 1234, + TotalScore = 123456, + Accuracy = 0.6543, + }, + Position = null, + }; + var oneScore = new APILegacyScores { Scores = new List @@ -250,6 +273,12 @@ namespace osu.Game.Tests.Visual.Online allScores.UserScore = myBestScore; scoresContainer.Scores = allScores; }); + + AddStep("Load scores with null my best position", () => + { + allScores.UserScore = myBestScoreWithNullPosition; + scoresContainer.Scores = allScores; + }); } private class TestScoresContainer : ScoresContainer diff --git a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs index bb85b4a37b..cad37dd082 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/DrawableTopScore.cs @@ -17,7 +17,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores { private readonly Box background; - public DrawableTopScore(ScoreInfo score, int position = 1) + public DrawableTopScore(ScoreInfo score, int? position = 1) { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index 0d0dd08a0f..2d8bd10b13 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Diagnostics; using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; @@ -71,10 +70,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores topScoresContainer.Add(new DrawableTopScore(topScore)); if (userScoreInfo != null && userScoreInfo.OnlineScoreID != topScore.OnlineScoreID) - { - Debug.Assert(userScore.Position != null); - topScoresContainer.Add(new DrawableTopScore(userScoreInfo, userScore.Position.Value)); - } + topScoresContainer.Add(new DrawableTopScore(userScoreInfo, userScore.Position)); }); } diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs index 8a368aa535..9a67ea2b24 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs @@ -112,9 +112,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores }; } - public int ScorePosition + public int? ScorePosition { - set => rankText.Text = $"#{value}"; + set => rankText.Text = value == null ? "-" : $"#{value}"; } /// From 5970c102b4e25f7573d4375358a51a79cc4617c7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Feb 2020 15:14:40 +0900 Subject: [PATCH 56/72] Change API to be easier to understand --- .../Objects/Drawables/DrawableOsuHitObject.cs | 4 ---- .../Objects/Drawables/DrawableHitObject.cs | 23 ++++++++++++------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index 1bb72a3176..a677cb6a72 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -1,13 +1,11 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System.Collections.Generic; using osu.Game.Rulesets.Objects.Drawables; using osu.Framework.Graphics; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Graphics.Containers; -using osuTK.Graphics; namespace osu.Game.Rulesets.Osu.Objects.Drawables { @@ -56,8 +54,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables } } - protected override void UpdateComboColour(Color4 proposedColour, IReadOnlyList comboColours) => AccentColour.Value = proposedColour; - protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(HitObject, judgement); } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index c5ce490845..67fe18e8dd 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -346,20 +346,27 @@ namespace osu.Game.Rulesets.Objects.Drawables private void updateComboColour() { - if (HitObject is IHasComboInformation combo) - { - var comboColours = CurrentSkin.GetConfig>(GlobalSkinColours.ComboColours)?.Value; - UpdateComboColour(comboColours?.Count > 0 ? comboColours[combo.ComboIndex % comboColours.Count] : Color4.White, comboColours); - } + if (!(HitObject is IHasComboInformation)) return; + + var comboColours = CurrentSkin.GetConfig>(GlobalSkinColours.ComboColours)?.Value; + + AccentColour.Value = GetComboColour(comboColours); } /// - /// Called when a combo colour change is proposed. + /// Called to retrieve the combo colour. Automatically assigned to . + /// Defaults to using to decide on a colour. /// - /// The proposed combo colour, based off the combo index. + /// + /// This will only be called if the implements . + /// /// A list of combo colours provided by the beatmap or skin. Can be null if not available. - protected virtual void UpdateComboColour(Color4 proposedColour, IReadOnlyList comboColours) + protected virtual Color4 GetComboColour(IReadOnlyList comboColours) { + if (!(HitObject is IHasComboInformation combo)) + throw new InvalidOperationException($"{nameof(HitObject)} must implement {nameof(IHasComboInformation)}"); + + return comboColours?.Count > 0 ? comboColours[combo.ComboIndex % comboColours.Count] : Color4.White; } /// From 337a7986cf7ca5492bf9a0eaf1616e616faee12d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Feb 2020 15:19:12 +0900 Subject: [PATCH 57/72] Fix reference in test scene --- osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs index 7469771e0b..17dc27543d 100644 --- a/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs @@ -76,8 +76,6 @@ namespace osu.Game.Tests.Gameplay : base(new TestHitObjectWithCombo()) { } - - protected override void UpdateComboColour(Color4 proposedColour, IReadOnlyList comboColours) => AccentColour.Value = proposedColour; } private class TestHitObjectWithCombo : HitObject, IHasComboInformation From 2869128e1165b1436c6ee4140dfa9e68554ed6b3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Feb 2020 15:37:15 +0900 Subject: [PATCH 58/72] Update in line with combo colour API changes --- osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBanana.cs | 4 ++-- .../Objects/Drawable/DrawableCatchHitObject.cs | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBanana.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBanana.cs index 8625b93786..672ff2cb3a 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBanana.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableBanana.cs @@ -16,10 +16,10 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable private Color4? colour; - protected override void UpdateComboColour(Color4 proposedColour, IReadOnlyList comboColours) + protected override Color4 GetComboColour(IReadOnlyList comboColours) { // override any external colour changes with banananana - AccentColour.Value = (colour ??= getBananaColour()); + return colour ??= getBananaColour(); } private Color4 getBananaColour() diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 188de6a6ae..3293f41eab 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -45,11 +45,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable ScaleContainer.Scale = new Vector2(HitObject.Scale); } - protected override void UpdateComboColour(Color4 proposedColour, IReadOnlyList comboColours) - { - // ignore the incoming combo colour as we use a custom lookup - AccentColour.Value = comboColours[(HitObject.IndexInBeatmap + 1) % comboColours.Count]; - } + protected override Color4 GetComboColour(IReadOnlyList comboColours) => + comboColours[(HitObject.IndexInBeatmap + 1) % comboColours.Count]; } public abstract class DrawableCatchHitObject : DrawableCatchHitObject From 5551343cf34c235326c75547234dab714f73a7ce Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Feb 2020 15:45:25 +0900 Subject: [PATCH 59/72] Throw instead of null return --- osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs index f76055e1ea..e1e6708bd8 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableJuiceStream.cs @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable ((DrawableCatchHitObject)o).CheckPosition = p => CheckPosition?.Invoke(p) ?? false); } - return null; + throw new ArgumentException($"{nameof(hitObject)} must be of type {nameof(CatchHitObject)}."); } } } From 8f5d3896f65f2ee79d0d18b18ee66b0f378b87c8 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Feb 2020 15:45:47 +0900 Subject: [PATCH 60/72] Remove unnecessary cast by changing method siganture --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 9ded0ff891..49e535890d 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -221,9 +221,9 @@ namespace osu.Game.Rulesets.Catch.UI /// Add a caught fruit to the catcher's stack. /// /// The fruit that was caught. - public void PlaceOnPlate(DrawableHitObject fruit) + public void PlaceOnPlate(DrawableCatchHitObject fruit) { - float ourRadius = ((DrawableCatchHitObject)fruit).DisplayRadius; + float ourRadius = fruit.DisplayRadius; float theirRadius = 0; const float allowance = 6; From 049975b5a46bce96baee5132d12157a01d2a7653 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Feb 2020 15:45:54 +0900 Subject: [PATCH 61/72] Use kebaberize shorthand --- osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs b/osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs index f8d0880c72..36164c5543 100644 --- a/osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Catch/Skinning/CatchLegacySkinTransformer.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Catch.Skinning case CatchSkinComponents.FruitOrange: case CatchSkinComponents.FruitGrapes: case CatchSkinComponents.FruitPear: - var lookupName = catchSkinComponent.Component.ToString().Underscore().Hyphenate(); + var lookupName = catchSkinComponent.Component.ToString().Kebaberize(); if (GetTexture(lookupName) != null) return new LegacyFruitPiece(lookupName); From a11862ba0da03fa909642d770a0450c48b4bd1ba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Feb 2020 18:03:53 +0900 Subject: [PATCH 62/72] Improve transition between multiplayer screens (and share constants) --- osu.Game/Screens/Multi/Multiplayer.cs | 8 ++--- .../Screens/Multi/MultiplayerSubScreen.cs | 29 ++++++++++++------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 54af8ab107..27ad7c9bc1 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -305,13 +305,13 @@ namespace osu.Game.Screens.Multi switch (newScreen) { case LoungeSubScreen _: - header.ResizeHeightTo(400, WaveContainer.APPEAR_DURATION, Easing.OutQuint); - headerBackground.MoveToX(0, WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); + header.Delay(MultiplayerSubScreen.RESUME_TRANSITION_DELAY).ResizeHeightTo(400, MultiplayerSubScreen.APPEAR_DURATION, Easing.OutQuint); + headerBackground.MoveToX(0, MultiplayerSubScreen.X_MOVE_DURATION, Easing.OutQuint); break; case MatchSubScreen _: - header.ResizeHeightTo(135, WaveContainer.APPEAR_DURATION, Easing.OutQuint); - headerBackground.MoveToX(-200, WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); + header.ResizeHeightTo(135, MultiplayerSubScreen.APPEAR_DURATION, Easing.OutQuint); + headerBackground.MoveToX(-MultiplayerSubScreen.X_SHIFT, MultiplayerSubScreen.X_MOVE_DURATION, Easing.OutQuint); break; } diff --git a/osu.Game/Screens/Multi/MultiplayerSubScreen.cs b/osu.Game/Screens/Multi/MultiplayerSubScreen.cs index ff94f63f01..8e46de1a95 100644 --- a/osu.Game/Screens/Multi/MultiplayerSubScreen.cs +++ b/osu.Game/Screens/Multi/MultiplayerSubScreen.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Screens; -using osu.Game.Graphics.Containers; namespace osu.Game.Screens.Multi { @@ -24,31 +23,41 @@ namespace osu.Game.Screens.Multi RelativeSizeAxes = Axes.Both; } + public const float X_SHIFT = 200; + + public const double X_MOVE_DURATION = 800; + + public const double RESUME_TRANSITION_DELAY = DISAPPEAR_DURATION / 2; + + public const double APPEAR_DURATION = 800; + + public const double DISAPPEAR_DURATION = 500; + public override void OnEntering(IScreen last) { - this.FadeInFromZero(WaveContainer.APPEAR_DURATION, Easing.OutQuint); - this.FadeInFromZero(WaveContainer.APPEAR_DURATION, Easing.OutQuint); - this.MoveToX(200).MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint); + this.FadeInFromZero(APPEAR_DURATION, Easing.OutQuint); + this.FadeInFromZero(APPEAR_DURATION, Easing.OutQuint); + this.MoveToX(X_SHIFT).MoveToX(0, X_MOVE_DURATION, Easing.OutQuint); } public override bool OnExiting(IScreen next) { - this.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); - this.MoveToX(200, WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); + this.FadeOut(DISAPPEAR_DURATION, Easing.OutQuint); + this.MoveToX(X_SHIFT, X_MOVE_DURATION, Easing.OutQuint); return false; } public override void OnResuming(IScreen last) { - this.FadeIn(WaveContainer.APPEAR_DURATION, Easing.OutQuint); - this.MoveToX(0, WaveContainer.APPEAR_DURATION, Easing.OutQuint); + this.Delay(RESUME_TRANSITION_DELAY).FadeIn(APPEAR_DURATION, Easing.OutQuint); + this.MoveToX(0, X_MOVE_DURATION, Easing.OutQuint); } public override void OnSuspending(IScreen next) { - this.FadeOut(WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); - this.MoveToX(-200, WaveContainer.DISAPPEAR_DURATION, Easing.OutQuint); + this.FadeOut(DISAPPEAR_DURATION, Easing.OutQuint); + this.MoveToX(-X_SHIFT, X_MOVE_DURATION, Easing.OutQuint); } public override string ToString() => Title; From 063fe191ef3ade3f2dff7f62ec33d29cb61a4859 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Feb 2020 18:15:40 +0900 Subject: [PATCH 63/72] Add back missing using --- osu.Game/Screens/Multi/Match/MatchSubScreen.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs index 38a1e8092c..eef53126c0 100644 --- a/osu.Game/Screens/Multi/Match/MatchSubScreen.cs +++ b/osu.Game/Screens/Multi/Match/MatchSubScreen.cs @@ -13,6 +13,7 @@ using osu.Game.Beatmaps; using osu.Game.Online.Multiplayer; using osu.Game.Online.Multiplayer.GameTypes; using osu.Game.Rulesets.Mods; +using osu.Game.Screens.Multi.Components; using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Multi.Play; using osu.Game.Screens.Select; From 973093b5220ff8cee9b02f5e11ee43447466551d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Feb 2020 18:32:28 +0900 Subject: [PATCH 64/72] Fix non-selectable playlist items not forwarding clicks to children --- osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs b/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs index ca85aec4e4..a7ed1f5846 100644 --- a/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs +++ b/osu.Game/Screens/Multi/DrawableRoomPlaylistItem.cs @@ -52,7 +52,7 @@ namespace osu.Game.Screens.Multi private readonly bool allowEdit; private readonly bool allowSelection; - protected override bool ShouldBeConsideredForInput(Drawable child) => allowEdit || SelectedItem.Value == Model; + protected override bool ShouldBeConsideredForInput(Drawable child) => allowEdit || !allowSelection || SelectedItem.Value == Model; public DrawableRoomPlaylistItem(PlaylistItem item, bool allowEdit, bool allowSelection) : base(item) From 76c57a695bec92daa773801203f130f2daf54a2c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Feb 2020 18:28:20 +0900 Subject: [PATCH 65/72] Change create room button colouring to match design --- osu.Game/Screens/Multi/Multiplayer.cs | 45 ++++++++++++++++++--------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 27ad7c9bc1..235ca9ec04 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -19,7 +19,6 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Input; using osu.Game.Online.API; using osu.Game.Online.Multiplayer; -using osu.Game.Overlays.BeatmapSet.Buttons; using osu.Game.Screens.Menu; using osu.Game.Screens.Multi.Components; using osu.Game.Screens.Multi.Lounge; @@ -129,22 +128,11 @@ namespace osu.Game.Screens.Multi } }, new Header(screenStack), - createButton = new HeaderButton + createButton = new CreateRoomButton { Anchor = Anchor.TopRight, Origin = Anchor.TopRight, - RelativeSizeAxes = Axes.None, - Size = new Vector2(150, Header.HEIGHT - 20), - Margin = new MarginPadding - { - Top = 10, - Right = 10 + HORIZONTAL_OVERFLOW_PADDING, - }, - Text = "Create room", - Action = () => loungeSubScreen.Open(new Room - { - Name = { Value = $"{api.LocalUser}'s awesome room" } - }), + Action = createRoom }, roomManager = new RoomManager() } @@ -276,6 +264,11 @@ namespace osu.Game.Screens.Multi logo.Delay(WaveContainer.DISAPPEAR_DURATION / 2).FadeOut(); } + private void createRoom() + { + loungeSubScreen.Open(new Room { Name = { Value = $"{api.LocalUser}'s awesome room" } }); + } + private void beginHandlingTrack() { Beatmap.BindValueChanged(updateTrack, true); @@ -381,5 +374,29 @@ namespace osu.Game.Screens.Multi protected override double TransformDuration => 200; } } + + public class CreateRoomButton : TriangleButton + { + public CreateRoomButton() + { + Size = new Vector2(150, Header.HEIGHT - 20); + Margin = new MarginPadding + { + Top = 10, + Right = 10 + HORIZONTAL_OVERFLOW_PADDING, + }; + } + + [BackgroundDependencyLoader] + private void load() + { + BackgroundColour = OsuColour.FromHex(@"593790"); + Triangles.ColourLight = OsuColour.FromHex(@"7247b6"); + Triangles.ColourDark = OsuColour.FromHex(@"593790"); + Triangles.TriangleScale = 1.5f; + + Text = "Create room"; + } + } } } From e7fca689b1ec13bf4ec0d4581badabb992dd598b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Feb 2020 18:34:24 +0900 Subject: [PATCH 66/72] Change text on playlist add button to be nicer --- osu.Game/Screens/Multi/Components/MatchBeatmapDetailArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Multi/Components/MatchBeatmapDetailArea.cs b/osu.Game/Screens/Multi/Components/MatchBeatmapDetailArea.cs index 8e085d6979..2c5fd2d397 100644 --- a/osu.Game/Screens/Multi/Components/MatchBeatmapDetailArea.cs +++ b/osu.Game/Screens/Multi/Components/MatchBeatmapDetailArea.cs @@ -53,7 +53,7 @@ namespace osu.Game.Screens.Multi.Components { new TriangleButton { - Text = "create new item", + Text = "Add new playlist entry", RelativeSizeAxes = Axes.Both, Size = Vector2.One, Action = () => CreateNewItem?.Invoke() From a0b578082e459e706ebec315109324b6f1ffffc3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Feb 2020 18:39:10 +0900 Subject: [PATCH 67/72] Make ready button also have triangles --- osu.Game/Screens/Multi/Match/Components/Footer.cs | 1 - osu.Game/Screens/Multi/Match/Components/ReadyButton.cs | 9 +++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Multi/Match/Components/Footer.cs b/osu.Game/Screens/Multi/Match/Components/Footer.cs index 93430d9131..199563c698 100644 --- a/osu.Game/Screens/Multi/Match/Components/Footer.cs +++ b/osu.Game/Screens/Multi/Match/Components/Footer.cs @@ -47,7 +47,6 @@ namespace osu.Game.Screens.Multi.Match.Components private void load(OsuColour colours) { background.Colour = OsuColour.FromHex(@"28242d"); - startButton.BackgroundColour = colours.Green; } } } diff --git a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs index d39217db5d..8f484d3672 100644 --- a/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs +++ b/osu.Game/Screens/Multi/Match/Components/ReadyButton.cs @@ -6,12 +6,13 @@ using System.Linq; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Game.Beatmaps; +using osu.Game.Graphics; using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; namespace osu.Game.Screens.Multi.Match.Components { - public class ReadyButton : OsuButton + public class ReadyButton : TriangleButton { public readonly Bindable SelectedItem = new Bindable(); @@ -32,12 +33,16 @@ namespace osu.Game.Screens.Multi.Match.Components } [BackgroundDependencyLoader] - private void load() + private void load(OsuColour colours) { beatmaps.ItemAdded += beatmapAdded; beatmaps.ItemRemoved += beatmapRemoved; SelectedItem.BindValueChanged(item => updateSelectedItem(item.NewValue), true); + + BackgroundColour = colours.Green; + Triangles.ColourDark = colours.Green; + Triangles.ColourLight = colours.GreenLight; } private void updateSelectedItem(PlaylistItem item) From 4a3f281855784ffaf7bf67f3c1ce5eaa335b8445 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Feb 2020 18:43:47 +0900 Subject: [PATCH 68/72] Make buttons purple --- .../Screens/Multi/Match/Components/Footer.cs | 4 +--- .../Match/Components/MatchSettingsOverlay.cs | 7 ++----- .../Match/Components/PurpleTriangleButton.cs | 20 +++++++++++++++++++ osu.Game/Screens/Multi/Multiplayer.cs | 6 ++---- 4 files changed, 25 insertions(+), 12 deletions(-) create mode 100644 osu.Game/Screens/Multi/Match/Components/PurpleTriangleButton.cs diff --git a/osu.Game/Screens/Multi/Match/Components/Footer.cs b/osu.Game/Screens/Multi/Match/Components/Footer.cs index 199563c698..c0c866d815 100644 --- a/osu.Game/Screens/Multi/Match/Components/Footer.cs +++ b/osu.Game/Screens/Multi/Match/Components/Footer.cs @@ -8,7 +8,6 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics; -using osu.Game.Graphics.UserInterface; using osu.Game.Online.Multiplayer; using osuTK; @@ -22,7 +21,6 @@ namespace osu.Game.Screens.Multi.Match.Components public readonly Bindable SelectedItem = new Bindable(); private readonly Drawable background; - private readonly OsuButton startButton; public Footer() { @@ -32,7 +30,7 @@ namespace osu.Game.Screens.Multi.Match.Components InternalChildren = new[] { background = new Box { RelativeSizeAxes = Axes.Both }, - startButton = new ReadyButton + new ReadyButton { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index e3110cdfc8..97485cd5a1 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -226,7 +226,7 @@ namespace osu.Game.Screens.Multi.Match.Components }, new Drawable[] { - new OsuButton + new PurpleTriangleButton { RelativeSizeAxes = Axes.X, Height = 40, @@ -447,10 +447,7 @@ namespace osu.Game.Screens.Multi.Match.Components Menu.MaxHeight = 100; } - protected override string GenerateItemText(TimeSpan item) - { - return item.Humanize(); - } + protected override string GenerateItemText(TimeSpan item) => item.Humanize(); } } } diff --git a/osu.Game/Screens/Multi/Match/Components/PurpleTriangleButton.cs b/osu.Game/Screens/Multi/Match/Components/PurpleTriangleButton.cs new file mode 100644 index 0000000000..8a0369ceba --- /dev/null +++ b/osu.Game/Screens/Multi/Match/Components/PurpleTriangleButton.cs @@ -0,0 +1,20 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; + +namespace osu.Game.Screens.Multi.Match.Components +{ + public class PurpleTriangleButton : TriangleButton + { + [BackgroundDependencyLoader] + private void load() + { + BackgroundColour = OsuColour.FromHex(@"593790"); + Triangles.ColourLight = OsuColour.FromHex(@"7247b6"); + Triangles.ColourDark = OsuColour.FromHex(@"593790"); + } + } +} diff --git a/osu.Game/Screens/Multi/Multiplayer.cs b/osu.Game/Screens/Multi/Multiplayer.cs index 235ca9ec04..1219919425 100644 --- a/osu.Game/Screens/Multi/Multiplayer.cs +++ b/osu.Game/Screens/Multi/Multiplayer.cs @@ -24,6 +24,7 @@ using osu.Game.Screens.Multi.Components; using osu.Game.Screens.Multi.Lounge; using osu.Game.Screens.Multi.Lounge.Components; using osu.Game.Screens.Multi.Match; +using osu.Game.Screens.Multi.Match.Components; using osu.Game.Screens.Play; using osuTK; @@ -375,7 +376,7 @@ namespace osu.Game.Screens.Multi } } - public class CreateRoomButton : TriangleButton + public class CreateRoomButton : PurpleTriangleButton { public CreateRoomButton() { @@ -390,9 +391,6 @@ namespace osu.Game.Screens.Multi [BackgroundDependencyLoader] private void load() { - BackgroundColour = OsuColour.FromHex(@"593790"); - Triangles.ColourLight = OsuColour.FromHex(@"7247b6"); - Triangles.ColourDark = OsuColour.FromHex(@"593790"); Triangles.TriangleScale = 1.5f; Text = "Create room"; From 3380dbbd71ed950d07c006947c1d7b1ef0cec227 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 20 Feb 2020 19:47:50 +0900 Subject: [PATCH 69/72] Improve visual appearance of ProcessingOverlay --- .../TestSceneProcessingOverlay.cs | 86 +++++ .../UserInterface/ProcessingOverlay.cs | 58 ++- .../Overlays/AccountCreation/ScreenEntry.cs | 6 +- .../Screens/Multi/Lounge/LoungeSubScreen.cs | 6 +- .../Match/Components/MatchSettingsOverlay.cs | 359 +++++++++--------- 5 files changed, 323 insertions(+), 192 deletions(-) create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneProcessingOverlay.cs diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneProcessingOverlay.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneProcessingOverlay.cs new file mode 100644 index 0000000000..2424078e5a --- /dev/null +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneProcessingOverlay.cs @@ -0,0 +1,86 @@ +// 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.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osuTK; +using osuTK.Graphics; + +namespace osu.Game.Tests.Visual.UserInterface +{ + public class TestSceneProcessingOverlay : OsuTestScene + { + private Drawable dimContent; + private ProcessingOverlay overlay; + + [SetUp] + public void SetUp() => Schedule(() => + { + Children = new[] + { + new Container + { + Size = new Vector2(300), + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new[] + { + new Box + { + Colour = Color4.SlateGray, + RelativeSizeAxes = Axes.Both, + }, + dimContent = new FillFlowContainer + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Direction = FillDirection.Vertical, + Spacing = new Vector2(10), + RelativeSizeAxes = Axes.Both, + Size = new Vector2(0.9f), + Children = new Drawable[] + { + new OsuSpriteText { Text = "Sample content" }, + new TriangleButton { Text = "can't puush me", Width = 200, }, + new TriangleButton { Text = "puush me", Width = 200, Action = () => { } }, + } + }, + overlay = new ProcessingOverlay(dimContent), + } + }, + }; + }); + + [Test] + public void ShowHide() + { + AddAssert("not visible", () => !overlay.IsPresent); + + AddStep("show", () => overlay.Show()); + + AddUntilStep("wait for content dim", () => dimContent.Colour != Color4.White); + + AddStep("hide", () => overlay.Hide()); + + AddUntilStep("wait for content restore", () => dimContent.Colour == Color4.White); + } + + [Test] + public void ContentRestoreOnDispose() + { + AddAssert("not visible", () => !overlay.IsPresent); + + AddStep("show", () => overlay.Show()); + + AddUntilStep("wait for content dim", () => dimContent.Colour != Color4.White); + + AddStep("hide", () => overlay.Expire()); + + AddUntilStep("wait for content restore", () => dimContent.Colour == Color4.White); + } + } +} diff --git a/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs b/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs index d75e78e2d9..181cfd831e 100644 --- a/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs +++ b/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs @@ -6,20 +6,27 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; +using osuTK; using osuTK.Graphics; namespace osu.Game.Graphics.UserInterface { /// - /// An overlay that will consume all available space and block input when required. + /// An overlay that will show a loading overlay and completely block input to an area. + /// Also optionally dims target elements. /// Useful for disabling all elements in a form and showing we are waiting on a response, for instance. /// public class ProcessingOverlay : VisibilityContainer { - private const float transition_duration = 200; + private readonly Drawable dimTarget; - public ProcessingOverlay() + private Container loadingBox; + + private const float transition_duration = 600; + + public ProcessingOverlay(Drawable dimTarget = null) { + this.dimTarget = dimTarget; RelativeSizeAxes = Axes.Both; } @@ -28,29 +35,54 @@ namespace osu.Game.Graphics.UserInterface { InternalChildren = new Drawable[] { - new Box + loadingBox = new Container { - Colour = Color4.Black, - RelativeSizeAxes = Axes.Both, - Alpha = 0.9f, + Size = new Vector2(80), + Scale = new Vector2(0.8f), + Masking = true, + CornerRadius = 15, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Children = new Drawable[] + { + new Box + { + Colour = Color4.Black, + RelativeSizeAxes = Axes.Both, + }, + new LoadingAnimation { State = { Value = Visibility.Visible } } + } }, - new LoadingAnimation { State = { Value = Visibility.Visible } } }; } - protected override bool Handle(UIEvent e) - { - return true; - } + protected override bool Handle(UIEvent e) => true; protected override void PopIn() { - this.FadeIn(transition_duration * 2, Easing.OutQuint); + this.FadeIn(transition_duration, Easing.OutQuint); + loadingBox.ScaleTo(1, transition_duration, Easing.OutElastic); + + dimTarget?.FadeColour(OsuColour.Gray(0.5f), transition_duration, Easing.OutQuint); } protected override void PopOut() { this.FadeOut(transition_duration, Easing.OutQuint); + loadingBox.ScaleTo(0.8f, transition_duration / 2, Easing.In); + + dimTarget?.FadeColour(Color4.White, transition_duration, Easing.OutQuint); + } + + protected override void Dispose(bool isDisposing) + { + base.Dispose(isDisposing); + + if (State.Value == Visibility.Visible) + { + // ensure we don't leave the targetin a bad state. + dimTarget?.FadeColour(Color4.White, transition_duration); + } } } } diff --git a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs index be3a84ca00..454fce0261 100644 --- a/osu.Game/Overlays/AccountCreation/ScreenEntry.cs +++ b/osu.Game/Overlays/AccountCreation/ScreenEntry.cs @@ -48,9 +48,11 @@ namespace osu.Game.Overlays.AccountCreation [BackgroundDependencyLoader] private void load(OsuColour colours) { + FillFlowContainer mainContent; + InternalChildren = new Drawable[] { - new FillFlowContainer + mainContent = new FillFlowContainer { RelativeSizeAxes = Axes.Both, Direction = FillDirection.Vertical, @@ -122,7 +124,7 @@ namespace osu.Game.Overlays.AccountCreation }, }, }, - processingOverlay = new ProcessingOverlay { Alpha = 0 } + processingOverlay = new ProcessingOverlay(mainContent) }; textboxes = new[] { usernameTextBox, emailTextBox, passwordTextBox }; diff --git a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs index 3709b85fcb..58e4548ee2 100644 --- a/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs +++ b/osu.Game/Screens/Multi/Lounge/LoungeSubScreen.cs @@ -30,6 +30,8 @@ namespace osu.Game.Screens.Multi.Lounge public LoungeSubScreen() { + SearchContainer searchContainer; + InternalChildren = new Drawable[] { Filter = new FilterControl { Depth = -1 }, @@ -49,14 +51,14 @@ namespace osu.Game.Screens.Multi.Lounge RelativeSizeAxes = Axes.Both, ScrollbarOverlapsContent = false, Padding = new MarginPadding(10), - Child = new SearchContainer + Child = searchContainer = new SearchContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Child = new RoomsContainer { JoinRequested = joinRequested } }, }, - processingOverlay = new ProcessingOverlay { Alpha = 0 } + processingOverlay = new ProcessingOverlay(searchContainer), } }, new RoomInspector diff --git a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs index 97485cd5a1..8c005a2647 100644 --- a/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs +++ b/osu.Game/Screens/Multi/Match/Components/MatchSettingsOverlay.cs @@ -79,226 +79,235 @@ namespace osu.Game.Screens.Multi.Match.Components [BackgroundDependencyLoader] private void load(OsuColour colours) { + Container dimContent; + InternalChildren = new Drawable[] { - new Box + dimContent = new Container { RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex(@"28242d"), - }, - new GridContainer - { - RelativeSizeAxes = Axes.Both, - RowDimensions = new[] + Children = new Drawable[] { - new Dimension(GridSizeMode.Distributed), - new Dimension(GridSizeMode.AutoSize), - }, - Content = new[] - { - new Drawable[] + new Box { - new OsuScrollContainer + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"28242d"), + }, + new GridContainer + { + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] { - Padding = new MarginPadding + new Dimension(GridSizeMode.Distributed), + new Dimension(GridSizeMode.AutoSize), + }, + Content = new[] + { + new Drawable[] { - Horizontal = OsuScreen.HORIZONTAL_OVERFLOW_PADDING, - Vertical = 10 - }, - RelativeSizeAxes = Axes.Both, - Children = new[] - { - new Container + new OsuScrollContainer { - Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING }, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] + Padding = new MarginPadding { - new SectionContainer + Horizontal = OsuScreen.HORIZONTAL_OVERFLOW_PADDING, + Vertical = 10 + }, + RelativeSizeAxes = Axes.Both, + Children = new[] + { + new Container { - Padding = new MarginPadding { Right = field_padding / 2 }, - Children = new[] + Padding = new MarginPadding { Horizontal = SearchableListOverlay.WIDTH_PADDING }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] { - new Section("Room name") + new SectionContainer { - Child = NameField = new SettingsTextBox + Padding = new MarginPadding { Right = field_padding / 2 }, + Children = new[] { - RelativeSizeAxes = Axes.X, - TabbableContentContainer = this, - OnCommit = (sender, text) => apply(), - }, - }, - new Section("Duration") - { - Child = DurationField = new DurationDropdown - { - RelativeSizeAxes = Axes.X, - Items = new[] + new Section("Room name") { - TimeSpan.FromMinutes(30), - TimeSpan.FromHours(1), - TimeSpan.FromHours(2), - TimeSpan.FromHours(4), - TimeSpan.FromHours(8), - TimeSpan.FromHours(12), - //TimeSpan.FromHours(16), - TimeSpan.FromHours(24), - TimeSpan.FromDays(3), - TimeSpan.FromDays(7) - } - } - }, - new Section("Room visibility") - { - Alpha = disabled_alpha, - Child = AvailabilityPicker = new RoomAvailabilityPicker - { - Enabled = { Value = false } - }, - }, - new Section("Game type") - { - Alpha = disabled_alpha, - Child = new FillFlowContainer - { - AutoSizeAxes = Axes.Y, - RelativeSizeAxes = Axes.X, - Direction = FillDirection.Vertical, - Spacing = new Vector2(7), - Children = new Drawable[] - { - TypePicker = new GameTypePicker + Child = NameField = new SettingsTextBox { RelativeSizeAxes = Axes.X, - Enabled = { Value = false } - }, - typeLabel = new OsuSpriteText - { - Font = OsuFont.GetFont(size: 14), - Colour = colours.Yellow + TabbableContentContainer = this, + OnCommit = (sender, text) => apply(), }, }, - }, - }, - new Section("Max participants") - { - Alpha = disabled_alpha, - Child = MaxParticipantsField = new SettingsNumberTextBox - { - RelativeSizeAxes = Axes.X, - TabbableContentContainer = this, - ReadOnly = true, - OnCommit = (sender, text) => apply() - }, - }, - new Section("Password (optional)") - { - Alpha = disabled_alpha, - Child = new SettingsPasswordTextBox - { - RelativeSizeAxes = Axes.X, - TabbableContentContainer = this, - ReadOnly = true, - OnCommit = (sender, text) => apply() - }, - }, - }, - }, - new SectionContainer - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Padding = new MarginPadding { Left = field_padding / 2 }, - Children = new[] - { - new Section("Playlist") - { - Child = new GridContainer - { - RelativeSizeAxes = Axes.X, - Height = 300, - Content = new[] + new Section("Duration") { - new Drawable[] + Child = DurationField = new DurationDropdown { - playlist = new DrawableRoomPlaylist(true, true) { RelativeSizeAxes = Axes.Both } - }, - new Drawable[] - { - new PurpleTriangleButton + RelativeSizeAxes = Axes.X, + Items = new[] { - RelativeSizeAxes = Axes.X, - Height = 40, - Text = "Edit playlist", - Action = () => EditPlaylist?.Invoke() + TimeSpan.FromMinutes(30), + TimeSpan.FromHours(1), + TimeSpan.FromHours(2), + TimeSpan.FromHours(4), + TimeSpan.FromHours(8), + TimeSpan.FromHours(12), + //TimeSpan.FromHours(16), + TimeSpan.FromHours(24), + TimeSpan.FromDays(3), + TimeSpan.FromDays(7) } } }, - RowDimensions = new[] + new Section("Room visibility") { - new Dimension(), - new Dimension(GridSizeMode.AutoSize), - } - } + Alpha = disabled_alpha, + Child = AvailabilityPicker = new RoomAvailabilityPicker + { + Enabled = { Value = false } + }, + }, + new Section("Game type") + { + Alpha = disabled_alpha, + Child = new FillFlowContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + Direction = FillDirection.Vertical, + Spacing = new Vector2(7), + Children = new Drawable[] + { + TypePicker = new GameTypePicker + { + RelativeSizeAxes = Axes.X, + Enabled = { Value = false } + }, + typeLabel = new OsuSpriteText + { + Font = OsuFont.GetFont(size: 14), + Colour = colours.Yellow + }, + }, + }, + }, + new Section("Max participants") + { + Alpha = disabled_alpha, + Child = MaxParticipantsField = new SettingsNumberTextBox + { + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this, + ReadOnly = true, + OnCommit = (sender, text) => apply() + }, + }, + new Section("Password (optional)") + { + Alpha = disabled_alpha, + Child = new SettingsPasswordTextBox + { + RelativeSizeAxes = Axes.X, + TabbableContentContainer = this, + ReadOnly = true, + OnCommit = (sender, text) => apply() + }, + }, + }, + }, + new SectionContainer + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Padding = new MarginPadding { Left = field_padding / 2 }, + Children = new[] + { + new Section("Playlist") + { + Child = new GridContainer + { + RelativeSizeAxes = Axes.X, + Height = 300, + Content = new[] + { + new Drawable[] + { + playlist = new DrawableRoomPlaylist(true, true) { RelativeSizeAxes = Axes.Both } + }, + new Drawable[] + { + new PurpleTriangleButton + { + RelativeSizeAxes = Axes.X, + Height = 40, + Text = "Edit playlist", + Action = () => EditPlaylist?.Invoke() + } + } + }, + RowDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.AutoSize), + } + } + }, + }, }, }, - }, + } }, - } - }, - }, - }, - new Drawable[] - { - new Container - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - Y = 2, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Children = new Drawable[] - { - new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.FromHex(@"28242d").Darken(0.5f).Opacity(1f), }, - new FillFlowContainer + }, + new Drawable[] + { + new Container { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Y = 2, RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Spacing = new Vector2(0, 20), - Margin = new MarginPadding { Vertical = 20 }, - Padding = new MarginPadding { Horizontal = OsuScreen.HORIZONTAL_OVERFLOW_PADDING }, Children = new Drawable[] { - ApplyButton = new CreateRoomButton + new Box { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Size = new Vector2(230, 55), - Enabled = { Value = false }, - Action = apply, + RelativeSizeAxes = Axes.Both, + Colour = OsuColour.FromHex(@"28242d").Darken(0.5f).Opacity(1f), }, - ErrorText = new OsuSpriteText + new FillFlowContainer { - Anchor = Anchor.BottomCentre, - Origin = Anchor.BottomCentre, - Alpha = 0, - Depth = 1, - Colour = colours.RedDark + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Spacing = new Vector2(0, 20), + Margin = new MarginPadding { Vertical = 20 }, + Padding = new MarginPadding { Horizontal = OsuScreen.HORIZONTAL_OVERFLOW_PADDING }, + Children = new Drawable[] + { + ApplyButton = new CreateRoomButton + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Size = new Vector2(230, 55), + Enabled = { Value = false }, + Action = apply, + }, + ErrorText = new OsuSpriteText + { + Anchor = Anchor.BottomCentre, + Origin = Anchor.BottomCentre, + Alpha = 0, + Depth = 1, + Colour = colours.RedDark + } + } } } } } } - } + }, } }, - processingOverlay = new ProcessingOverlay { Alpha = 0 } + processingOverlay = new ProcessingOverlay(dimContent) }; TypePicker.Current.BindValueChanged(type => typeLabel.Text = type.NewValue?.Name ?? string.Empty, true); From 7adedcb7b973a59ead594a0fdfa1d74035ff2405 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 21 Feb 2020 08:34:51 +0900 Subject: [PATCH 70/72] Fix typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bartłomiej Dach --- osu.Game/Graphics/UserInterface/ProcessingOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs b/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs index 181cfd831e..8109f3bd94 100644 --- a/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs +++ b/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs @@ -80,7 +80,7 @@ namespace osu.Game.Graphics.UserInterface if (State.Value == Visibility.Visible) { - // ensure we don't leave the targetin a bad state. + // ensure we don't leave the target in a bad state. dimTarget?.FadeColour(Color4.White, transition_duration); } } From 6c21cc3926f2b0d523a08dadb6cc74dc43d61a21 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 21 Feb 2020 08:55:12 +0900 Subject: [PATCH 71/72] Adjust easing type to match in disposal clause Co-Authored-By: Dan Balasescu --- osu.Game/Graphics/UserInterface/ProcessingOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs b/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs index 8109f3bd94..c65801a82e 100644 --- a/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs +++ b/osu.Game/Graphics/UserInterface/ProcessingOverlay.cs @@ -81,7 +81,7 @@ namespace osu.Game.Graphics.UserInterface if (State.Value == Visibility.Visible) { // ensure we don't leave the target in a bad state. - dimTarget?.FadeColour(Color4.White, transition_duration); + dimTarget?.FadeColour(Color4.White, transition_duration, Easing.OutQuint); } } } From 6468bfa54324231bae6325e149ea445c3eddfb07 Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Fri, 21 Feb 2020 10:01:38 +0900 Subject: [PATCH 72/72] Apply adjustments --- .../Objects/Drawable/DrawableCatchHitObject.cs | 2 +- .../Objects/Drawable/DrawableDroplet.cs | 12 +++++------- .../Objects/Drawable/DrawableTinyDroplet.cs | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs index 3293f41eab..ed9e797154 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableCatchHitObject.cs @@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable { public override bool CanBePlated => true; - protected Container ScaleContainer; + protected Container ScaleContainer { get; private set; } protected PalpableCatchHitObject(TObject hitObject) : base(hitObject) diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs index 4e8faed091..ef3be7e2ba 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableDroplet.cs @@ -4,7 +4,6 @@ using osu.Framework.Allocation; using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces; using osu.Game.Skinning; -using osuTK.Graphics; namespace osu.Game.Rulesets.Catch.Objects.Drawable { @@ -20,12 +19,11 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable [BackgroundDependencyLoader] private void load() { - ScaleContainer.Child = new SkinnableDrawable( - new CatchSkinComponent(CatchSkinComponents.Droplet), _ => new Pulp - { - Size = Size / 4, - AccentColour = { Value = Color4.White } - }); + ScaleContainer.Child = new SkinnableDrawable(new CatchSkinComponent(CatchSkinComponents.Droplet), _ => new Pulp + { + Size = Size / 4, + AccentColour = { BindTarget = AccentColour } + }); } } } diff --git a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableTinyDroplet.cs b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableTinyDroplet.cs index 4fe1f86f2b..873e5a3ebb 100644 --- a/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableTinyDroplet.cs +++ b/osu.Game.Rulesets.Catch/Objects/Drawable/DrawableTinyDroplet.cs @@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable [BackgroundDependencyLoader] private void load() { - Scale /= 2; + ScaleContainer.Scale /= 2; } } }