diff --git a/osu.Desktop.VisualTests/Tests/TestCaseDirect.cs b/osu.Desktop.VisualTests/Tests/TestCaseDirect.cs index 6b68ffa260..2a20bca836 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseDirect.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseDirect.cs @@ -48,6 +48,17 @@ namespace osu.Desktop.VisualTests.Tests Author = @"RLC", Source = @"", }, + OnlineInfo = new BeatmapSetOnlineInfo + { + Covers = new BeatmapSetOnlineCovers + { + Card = @"https://assets.ppy.sh/beatmaps/578332/covers/card.jpg?1494591390", + Cover = @"https://assets.ppy.sh/beatmaps/578332/covers/cover.jpg?1494591390", + }, + Preview = @"https://b.ppy.sh/preview/578332.mp3", + PlayCount = 97, + FavouriteCount = 72, + }, Beatmaps = new List { new BeatmapInfo @@ -55,13 +66,6 @@ namespace osu.Desktop.VisualTests.Tests Ruleset = ruleset, StarDifficulty = 5.35f, Metadata = new BeatmapMetadata(), - OnlineInfo = new BeatmapOnlineInfo - { - Covers = new[] { @"https://assets.ppy.sh//beatmaps/578332/covers/cover.jpg?1494591390" }, - Preview = @"https://b.ppy.sh/preview/578332.mp3", - PlayCount = 97, - FavouriteCount = 72, - }, }, }, }, @@ -74,6 +78,17 @@ namespace osu.Desktop.VisualTests.Tests Author = @"Sotarks", Source = @"ぎんぎつね", }, + OnlineInfo = new BeatmapSetOnlineInfo + { + Covers = new BeatmapSetOnlineCovers + { + Card = @"https://assets.ppy.sh/beatmaps/599627/covers/card.jpg?1494539318", + Cover = @"https://assets.ppy.sh/beatmaps/599627/covers/cover.jpg?1494539318", + }, + Preview = @"https//b.ppy.sh/preview/599627.mp3", + PlayCount = 3082, + FavouriteCount = 14, + }, Beatmaps = new List { new BeatmapInfo @@ -81,13 +96,6 @@ namespace osu.Desktop.VisualTests.Tests Ruleset = ruleset, StarDifficulty = 5.81f, Metadata = new BeatmapMetadata(), - OnlineInfo = new BeatmapOnlineInfo - { - Covers = new[] { @"https://assets.ppy.sh//beatmaps/599627/covers/cover.jpg?1494539318" }, - Preview = @"https//b.ppy.sh/preview/599627.mp3", - PlayCount = 3082, - FavouriteCount = 14, - }, }, }, }, @@ -100,6 +108,17 @@ namespace osu.Desktop.VisualTests.Tests Author = @"Cerulean Veyron", Source = @"", }, + OnlineInfo = new BeatmapSetOnlineInfo + { + Covers = new BeatmapSetOnlineCovers + { + Card = @"https://assets.ppy.sh/beatmaps/513268/covers/card.jpg?1494502863", + Cover = @"https://assets.ppy.sh/beatmaps/513268/covers/cover.jpg?1494502863", + }, + Preview = @"https//b.ppy.sh/preview/513268.mp3", + PlayCount = 2762, + FavouriteCount = 15, + }, Beatmaps = new List { new BeatmapInfo @@ -107,13 +126,6 @@ namespace osu.Desktop.VisualTests.Tests Ruleset = ruleset, StarDifficulty = 0.9f, Metadata = new BeatmapMetadata(), - OnlineInfo = new BeatmapOnlineInfo - { - Covers = new[] { @"https://assets.ppy.sh//beatmaps/513268/covers/cover.jpg?1494502863" }, - Preview = @"https//b.ppy.sh/preview/513268.mp3", - PlayCount = 2762, - FavouriteCount = 15, - }, }, new BeatmapInfo { @@ -141,6 +153,17 @@ namespace osu.Desktop.VisualTests.Tests Author = @"[Kamiya]", Source = @"小林さんちのメイドラゴン", }, + OnlineInfo = new BeatmapSetOnlineInfo + { + Covers = new BeatmapSetOnlineCovers + { + Card = @"https://assets.ppy.sh/beatmaps/586841/covers/card.jpg?1494052741", + Cover = @"https://assets.ppy.sh/beatmaps/586841/covers/cover.jpg?1494052741", + }, + Preview = @"https//b.ppy.sh/preview/586841.mp3", + PlayCount = 62317, + FavouriteCount = 161, + }, Beatmaps = new List { new BeatmapInfo @@ -148,13 +171,6 @@ namespace osu.Desktop.VisualTests.Tests Ruleset = ruleset, StarDifficulty = 1.26f, Metadata = new BeatmapMetadata(), - OnlineInfo = new BeatmapOnlineInfo - { - Covers = new[] { @"https://assets.ppy.sh//beatmaps/586841/covers/cover.jpg?1494052741" }, - Preview = @"https//b.ppy.sh/preview/586841.mp3", - PlayCount = 62317, - FavouriteCount = 161, - }, }, new BeatmapInfo { diff --git a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs index 00702f7ad0..4d650afed5 100644 --- a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs +++ b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs @@ -39,9 +39,15 @@ namespace osu.Desktop.VisualTests.Tests Artist = @"Maaya Sakamoto", Author = @"uwutm8", }, - OnlineInfo = new BeatmapOnlineInfo + BeatmapSet = new BeatmapSetInfo { - Covers = new[] { @"https://assets.ppy.sh//beatmaps/560573/covers/cover.jpg?1492722343" }, + OnlineInfo = new BeatmapSetOnlineInfo + { + Covers = new BeatmapSetOnlineCovers + { + Cover = @"https://assets.ppy.sh/beatmaps/560573/covers/cover.jpg?1492722343", + }, + }, }, } }, @@ -96,15 +102,21 @@ namespace osu.Desktop.VisualTests.Tests Ruleset = rulesets.GetRuleset(0), Metadata = new BeatmapMetadata { - Title = @"xi", - Artist = @"FREEDOM DIVE", + Title = @"FREEDOM DIVE", + Artist = @"xi", Author = @"Nakagawa-Kanon", }, - OnlineInfo = new BeatmapOnlineInfo + BeatmapSet = new BeatmapSetInfo { - Covers = new[] { @"https://assets.ppy.sh//beatmaps/39804/covers/cover.jpg?1456506845" }, + OnlineInfo = new BeatmapSetOnlineInfo + { + Covers = new BeatmapSetOnlineCovers + { + Cover = @"https://assets.ppy.sh/beatmaps/39804/covers/cover.jpg?1456506845", + }, + }, }, - } + }, }, MaxParticipants = { Value = 10 }, Participants = diff --git a/osu.Game/Database/BeatmapMetadata.cs b/osu.Game/Database/BeatmapMetadata.cs index 04700b3caa..ccf1a99c2c 100644 --- a/osu.Game/Database/BeatmapMetadata.cs +++ b/osu.Game/Database/BeatmapMetadata.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Linq; +using Newtonsoft.Json; using SQLite.Net.Attributes; namespace osu.Game.Database @@ -17,8 +18,13 @@ namespace osu.Game.Database public string TitleUnicode { get; set; } public string Artist { get; set; } public string ArtistUnicode { get; set; } + + [JsonProperty(@"creator")] public string Author { get; set; } + public string Source { get; set; } + + [JsonProperty(@"tags")] public string Tags { get; set; } public int PreviewTime { get; set; } public string AudioFile { get; set; } @@ -35,4 +41,4 @@ namespace osu.Game.Database Tags }.Where(s => !string.IsNullOrEmpty(s)).ToArray(); } -} \ No newline at end of file +} diff --git a/osu.Game/Database/BeatmapOnlineInfo.cs b/osu.Game/Database/BeatmapOnlineInfo.cs index bcb2ef16ac..f4e70388f5 100644 --- a/osu.Game/Database/BeatmapOnlineInfo.cs +++ b/osu.Game/Database/BeatmapOnlineInfo.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using Newtonsoft.Json; -using System.Collections.Generic; namespace osu.Game.Database { @@ -11,28 +10,16 @@ namespace osu.Game.Database /// public class BeatmapOnlineInfo { - /// - /// The different sizes of cover art for this beatmap: cover, cover@2x, card, card@2x, list, list@2x. - /// - [JsonProperty(@"covers")] - public IEnumerable Covers { get; set; } - - /// - /// A small sample clip of this beatmap's song. - /// - [JsonProperty(@"previewUrl")] - public string Preview { get; set; } - /// /// The amount of plays this beatmap has. /// - [JsonProperty(@"play_count")] + [JsonProperty(@"playcount")] public int PlayCount { get; set; } /// - /// The amount of people who have favourited this map. + /// The amount of passes this beatmap has. /// - [JsonProperty(@"favourite_count")] - public int FavouriteCount { get; set; } + [JsonProperty(@"passcount")] + public int PassCount { get; set; } } } diff --git a/osu.Game/Database/BeatmapSetInfo.cs b/osu.Game/Database/BeatmapSetInfo.cs index aa5fa21394..017a489d9e 100644 --- a/osu.Game/Database/BeatmapSetInfo.cs +++ b/osu.Game/Database/BeatmapSetInfo.cs @@ -24,6 +24,9 @@ namespace osu.Game.Database [OneToMany(CascadeOperations = CascadeOperation.All)] public List Beatmaps { get; set; } + [Ignore] + public BeatmapSetOnlineInfo OnlineInfo { get; set; } + public double MaxStarDifficulty => Beatmaps.Max(b => b.StarDifficulty); [Indexed] diff --git a/osu.Game/Database/BeatmapSetOnlineInfo.cs b/osu.Game/Database/BeatmapSetOnlineInfo.cs new file mode 100644 index 0000000000..61d408c94a --- /dev/null +++ b/osu.Game/Database/BeatmapSetOnlineInfo.cs @@ -0,0 +1,55 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using Newtonsoft.Json; + +namespace osu.Game.Database +{ + /// + /// Beatmap set info retrieved for previewing locally without having the set downloaded. + /// + public class BeatmapSetOnlineInfo + { + /// + /// The different sizes of cover art for this beatmap set. + /// + [JsonProperty(@"covers")] + public BeatmapSetOnlineCovers Covers { get; set; } + + /// + /// A small sample clip of this beatmap set's song. + /// + [JsonProperty(@"previewUrl")] + public string Preview { get; set; } + + /// + /// The amount of plays this beatmap set has. + /// + [JsonProperty(@"play_count")] + public int PlayCount { get; set; } + + /// + /// The amount of people who have favourited this beatmap set. + /// + [JsonProperty(@"favourite_count")] + public int FavouriteCount { get; set; } + } + + public class BeatmapSetOnlineCovers + { + public string CoverLowRes { get; set; } + + [JsonProperty(@"cover@2x")] + public string Cover { get; set; } + + public string CardLowRes { get; set; } + + [JsonProperty(@"card@2x")] + public string Card { get; set; } + + public string ListLowRes { get; set; } + + [JsonProperty(@"list@2x")] + public string List { get; set; } + } +} diff --git a/osu.Game/Database/OnlineWorkingBeatmap.cs b/osu.Game/Database/OnlineWorkingBeatmap.cs deleted file mode 100644 index 1465c59434..0000000000 --- a/osu.Game/Database/OnlineWorkingBeatmap.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using System.Linq; -using osu.Framework.Audio.Track; -using osu.Framework.Graphics.Textures; -using osu.Game.Beatmaps; - -namespace osu.Game.Database -{ - internal class OnlineWorkingBeatmap : WorkingBeatmap - { - private readonly TextureStore textures; - private readonly TrackManager tracks; - - public OnlineWorkingBeatmap(BeatmapInfo beatmapInfo, TextureStore textures, TrackManager tracks) : base(beatmapInfo) - { - this.textures = textures; - this.tracks = tracks; - } - - protected override Beatmap GetBeatmap() - { - return new Beatmap(); - } - - protected override Texture GetBackground() - { - return textures.Get(BeatmapInfo.OnlineInfo.Covers.FirstOrDefault()); - } - - protected override Track GetTrack() - { - return tracks.Get(BeatmapInfo.OnlineInfo.Preview); - } - } -} diff --git a/osu.Game/Online/API/Requests/GetBeatmapSetsRequest.cs b/osu.Game/Online/API/Requests/GetBeatmapSetsRequest.cs new file mode 100644 index 0000000000..f6f9bf69fd --- /dev/null +++ b/osu.Game/Online/API/Requests/GetBeatmapSetsRequest.cs @@ -0,0 +1,97 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using System.Collections.Generic; +using System.Linq; +using Newtonsoft.Json; +using osu.Game.Database; +using osu.Game.Overlays; +using osu.Game.Overlays.Direct; + +namespace osu.Game.Online.API.Requests +{ + public class GetBeatmapSetsRequest : APIRequest> + { + private readonly string query; + private readonly RulesetInfo ruleset; + private readonly RankStatus rankStatus; + private readonly DirectSortCriteria sortCriteria; + private readonly SortDirection direction; + private string directionString => direction == SortDirection.Descending ? @"desc" : @"asc"; + + public GetBeatmapSetsRequest(string query, RulesetInfo ruleset, RankStatus rankStatus = RankStatus.Any, DirectSortCriteria sortCriteria = DirectSortCriteria.Ranked, SortDirection direction = SortDirection.Descending) + { + this.query = System.Uri.EscapeDataString(query); + this.ruleset = ruleset; + this.rankStatus = rankStatus; + this.sortCriteria = sortCriteria; + this.direction = direction; + } + + protected override string Target => $@"beatmapsets/search?q={query}&m={ruleset.ID ?? 0}&s={(int)rankStatus}&sort={sortCriteria.ToString().ToLower()}_{directionString}"; + } + + public class GetBeatmapSetsResponse : BeatmapMetadata + { + [JsonProperty(@"covers")] + private BeatmapSetOnlineCovers covers { get; set; } + + [JsonProperty(@"previewUrl")] + private string preview { get; set; } + + [JsonProperty(@"play_count")] + private int playCount { get; set; } + + [JsonProperty(@"favourite_count")] + private int favouriteCount { get; set; } + + [JsonProperty(@"beatmaps")] + private IEnumerable beatmaps { get; set; } + + public BeatmapSetInfo ToBeatmapSet(RulesetDatabase rulesets) + { + return new BeatmapSetInfo + { + Metadata = this, + OnlineInfo = new BeatmapSetOnlineInfo + { + Covers = covers, + Preview = preview, + PlayCount = playCount, + FavouriteCount = favouriteCount, + }, + Beatmaps = beatmaps.Select(b => b.ToBeatmap(rulesets)).ToList(), + }; + } + + private class GetBeatmapSetsBeatmapResponse : BeatmapMetadata + { + [JsonProperty(@"playcount")] + private int playCount { get; set; } + + [JsonProperty(@"passcount")] + private int passCount { get; set; } + + [JsonProperty(@"mode_int")] + private int ruleset { get; set; } + + [JsonProperty(@"difficulty_rating")] + private double starDifficulty { get; set; } + + public BeatmapInfo ToBeatmap(RulesetDatabase rulesets) + { + return new BeatmapInfo + { + Metadata = this, + Ruleset = rulesets.GetRuleset(ruleset), + StarDifficulty = starDifficulty, + OnlineInfo = new BeatmapOnlineInfo + { + PlayCount = playCount, + PassCount = passCount, + }, + }; + } + } + } +} diff --git a/osu.Game/Overlays/Direct/DirectGridPanel.cs b/osu.Game/Overlays/Direct/DirectGridPanel.cs index a670b27540..3c464af05d 100644 --- a/osu.Game/Overlays/Direct/DirectGridPanel.cs +++ b/osu.Game/Overlays/Direct/DirectGridPanel.cs @@ -1,14 +1,12 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System.Linq; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; -using osu.Framework.Graphics.Textures; using osu.Framework.Localisation; using osu.Game.Database; using osu.Game.Graphics; @@ -50,7 +48,7 @@ namespace osu.Game.Overlays.Direct } [BackgroundDependencyLoader] - private void load(OsuColour colours, LocalisationEngine localisation, TextureStore textures) + private void load(OsuColour colours, LocalisationEngine localisation) { Children = new[] { @@ -59,7 +57,7 @@ namespace osu.Game.Overlays.Direct RelativeSizeAxes = Axes.Both, Colour = Color4.Black, }, - GetBackground(textures), + CreateBackground(), new Box { RelativeSizeAxes = Axes.Both, @@ -180,11 +178,11 @@ namespace osu.Game.Overlays.Direct Margin = new MarginPadding { Top = vertical_padding, Right = vertical_padding }, Children = new[] { - new Statistic(FontAwesome.fa_play_circle, SetInfo.Beatmaps.FirstOrDefault()?.OnlineInfo.PlayCount ?? 0) + new Statistic(FontAwesome.fa_play_circle, SetInfo.OnlineInfo?.PlayCount ?? 0) { Margin = new MarginPadding { Right = 1 }, }, - new Statistic(FontAwesome.fa_heart, SetInfo.Beatmaps.FirstOrDefault()?.OnlineInfo.FavouriteCount ?? 0), + new Statistic(FontAwesome.fa_heart, SetInfo.OnlineInfo?.FavouriteCount ?? 0), }, }, }; diff --git a/osu.Game/Overlays/Direct/DirectListPanel.cs b/osu.Game/Overlays/Direct/DirectListPanel.cs index 1e923d79fa..f693998563 100644 --- a/osu.Game/Overlays/Direct/DirectListPanel.cs +++ b/osu.Game/Overlays/Direct/DirectListPanel.cs @@ -12,8 +12,6 @@ using osu.Game.Graphics.Sprites; using osu.Game.Database; using osu.Framework.Allocation; using osu.Framework.Localisation; -using osu.Framework.Graphics.Textures; -using System.Linq; using osu.Framework.Input; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Containers; @@ -49,7 +47,7 @@ namespace osu.Game.Overlays.Direct } [BackgroundDependencyLoader] - private void load(LocalisationEngine localisation, TextureStore textures) + private void load(LocalisationEngine localisation) { Children = new[] { @@ -58,7 +56,7 @@ namespace osu.Game.Overlays.Direct RelativeSizeAxes = Axes.Both, Colour = Color4.Black, }, - GetBackground(textures), + CreateBackground(), new Box { RelativeSizeAxes = Axes.Both, @@ -105,11 +103,11 @@ namespace osu.Game.Overlays.Direct Margin = new MarginPadding { Right = height - vertical_padding * 2 + vertical_padding }, Children = new Drawable[] { - new Statistic(FontAwesome.fa_play_circle, SetInfo.Beatmaps.FirstOrDefault()?.OnlineInfo.PlayCount ?? 0) + new Statistic(FontAwesome.fa_play_circle, SetInfo.OnlineInfo?.PlayCount ?? 0) { Margin = new MarginPadding { Right = 1 }, }, - new Statistic(FontAwesome.fa_heart, SetInfo.Beatmaps.FirstOrDefault()?.OnlineInfo.FavouriteCount ?? 0), + new Statistic(FontAwesome.fa_heart, SetInfo.OnlineInfo?.FavouriteCount ?? 0), new FillFlowContainer { Anchor = Anchor.TopRight, diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs index 3c708bff67..02b6e32192 100644 --- a/osu.Game/Overlays/Direct/DirectPanel.cs +++ b/osu.Game/Overlays/Direct/DirectPanel.cs @@ -2,8 +2,8 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; -using System.Linq; using OpenTK; +using osu.Framework.Allocation; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Sprites; @@ -34,21 +34,25 @@ namespace osu.Game.Overlays.Direct return icons; } - protected Drawable GetBackground(TextureStore textures) + protected Drawable CreateBackground() => new DelayedLoadWrapper(new BeatmapSetBackgroundSprite(SetInfo) { - return new AsyncLoadWrapper(new BeatmapBackgroundSprite(new OnlineWorkingBeatmap(SetInfo.Beatmaps.FirstOrDefault(), textures, null)) - { - RelativeSizeAxes = Axes.Both, - FillMode = FillMode.Fill, - OnLoadComplete = d => d.FadeInFromZero(400, EasingTypes.Out), - }) { RelativeSizeAxes = Axes.Both }; - } + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + RelativeSizeAxes = Axes.Both, + FillMode = FillMode.Fill, + OnLoadComplete = d => d.FadeInFromZero(400, EasingTypes.Out), + }) + { + RelativeSizeAxes = Axes.Both, + TimeBeforeLoad = 300 + }; public class Statistic : FillFlowContainer { private readonly SpriteText text; private int value; + public int Value { get { return value; } @@ -85,5 +89,23 @@ namespace osu.Game.Overlays.Direct Value = value; } } + + private class BeatmapSetBackgroundSprite : Sprite + { + private readonly BeatmapSetInfo set; + public BeatmapSetBackgroundSprite(BeatmapSetInfo set) + { + this.set = set; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + string resource = set.OnlineInfo.Covers.Card; + + if (resource != null) + Texture = textures.Get(resource); + } + } } } diff --git a/osu.Game/Overlays/Direct/FilterControl.cs b/osu.Game/Overlays/Direct/FilterControl.cs index b898d24c31..bb6055dc4f 100644 --- a/osu.Game/Overlays/Direct/FilterControl.cs +++ b/osu.Game/Overlays/Direct/FilterControl.cs @@ -14,12 +14,13 @@ using osu.Game.Overlays.SearchableList; namespace osu.Game.Overlays.Direct { - public class FilterControl : SearchableListFilterControl + public class FilterControl : SearchableListFilterControl { + public readonly Bindable Ruleset = new Bindable(); private FillFlowContainer modeButtons; protected override Color4 BackgroundColour => OsuColour.FromHex(@"384552"); - protected override DirectSortCritera DefaultTab => DirectSortCritera.Title; + protected override DirectSortCriteria DefaultTab => DirectSortCriteria.Ranked; protected override Drawable CreateSupplementaryControls() { modeButtons = new FillFlowContainer @@ -36,10 +37,10 @@ namespace osu.Game.Overlays.Direct { DisplayStyleControl.Dropdown.AccentColour = colours.BlueDark; - var b = new Bindable(); //backup bindable incase the game is null + Ruleset.BindTo(game?.Ruleset ?? new Bindable() { Value = rulesets.GetRuleset(0) }); foreach (var r in rulesets.AllRulesets) { - modeButtons.Add(new RulesetToggleButton(game?.Ruleset ?? b, r)); + modeButtons.Add(new RulesetToggleButton(Ruleset, r)); } } @@ -95,7 +96,7 @@ namespace osu.Game.Overlays.Direct } } - public enum DirectSortCritera + public enum DirectSortCriteria { Title, Artist, @@ -103,5 +104,6 @@ namespace osu.Game.Overlays.Direct Difficulty, Ranked, Rating, + Plays, } } diff --git a/osu.Game/Overlays/Direct/Header.cs b/osu.Game/Overlays/Direct/Header.cs index 000ef473cc..2c50fb453f 100644 --- a/osu.Game/Overlays/Direct/Header.cs +++ b/osu.Game/Overlays/Direct/Header.cs @@ -30,10 +30,10 @@ namespace osu.Game.Overlays.Direct { Search, [Description("Newest Maps")] - NewestMaps, + NewestMaps = DirectSortCriteria.Ranked, [Description("Top Rated")] - TopRated, + TopRated = DirectSortCriteria.Rating, [Description("Most Played")] - MostPlayed + MostPlayed = DirectSortCriteria.Plays, } } diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs index beb1355f36..5fa90ab1d6 100644 --- a/osu.Game/Overlays/DirectOverlay.cs +++ b/osu.Game/Overlays/DirectOverlay.cs @@ -5,21 +5,28 @@ using System.Collections.Generic; using System.Linq; using OpenTK; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Threading; using osu.Game.Database; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; using osu.Game.Overlays.Direct; using osu.Game.Overlays.SearchableList; using OpenTK.Graphics; namespace osu.Game.Overlays { - public class DirectOverlay : SearchableListOverlay + public class DirectOverlay : SearchableListOverlay { private const float panel_padding = 10f; + private APIAccess api; + private RulesetDatabase rulesets; + private readonly FillFlowContainer resultCountsContainer; private readonly OsuSpriteText resultCountsText; private readonly FillFlowContainer panels; @@ -29,7 +36,7 @@ namespace osu.Game.Overlays protected override Color4 TrianglesColourDark => OsuColour.FromHex(@"3f5265"); protected override SearchableListHeader CreateHeader() => new Header(); - protected override SearchableListFilterControl CreateFilterControl() => new FilterControl(); + protected override SearchableListFilterControl CreateFilterControl() => new FilterControl(); private IEnumerable beatmapSets; public IEnumerable BeatmapSets @@ -40,6 +47,17 @@ namespace osu.Game.Overlays if (beatmapSets?.Equals(value) ?? false) return; beatmapSets = value; + if (BeatmapSets == null) + { + foreach (var p in panels.Children) + { + p.FadeOut(200); + p.Expire(); + } + + return; + } + recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value); } } @@ -98,22 +116,60 @@ namespace osu.Game.Overlays }, }; - Header.Tabs.Current.ValueChanged += tab => { if (tab != DirectTab.Search) Filter.Search.Text = string.Empty; }; Filter.Search.Current.ValueChanged += text => { if (text != string.Empty) Header.Tabs.Current.Value = DirectTab.Search; }; + ((FilterControl)Filter).Ruleset.ValueChanged += ruleset => Scheduler.AddOnce(updateSearch); Filter.DisplayStyleControl.DisplayStyle.ValueChanged += recreatePanels; + Filter.DisplayStyleControl.Dropdown.Current.ValueChanged += rankStatus => Scheduler.AddOnce(updateSearch); + + Header.Tabs.Current.ValueChanged += tab => + { + if (tab != DirectTab.Search) + { + currentQuery.Value = string.Empty; + Filter.Tabs.Current.Value = (DirectSortCriteria)Header.Tabs.Current.Value; + Scheduler.AddOnce(updateSearch); + } + }; + + currentQuery.ValueChanged += v => + { + queryChangedDebounce?.Cancel(); + + if (string.IsNullOrEmpty(v)) + Scheduler.AddOnce(updateSearch); + else + { + BeatmapSets = null; + ResultAmounts = null; + + queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500); + } + }; + + currentQuery.BindTo(Filter.Search.Current); + + Filter.Tabs.Current.ValueChanged += sortCriteria => + { + if (Header.Tabs.Current.Value != DirectTab.Search && sortCriteria != (DirectSortCriteria)Header.Tabs.Current.Value) + Header.Tabs.Current.Value = DirectTab.Search; + + Scheduler.AddOnce(updateSearch); + }; updateResultCounts(); } [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OsuColour colours, APIAccess api, RulesetDatabase rulesets) { + this.api = api; + this.rulesets = rulesets; resultCountsContainer.Colour = colours.Yellow; } private void updateResultCounts() { - resultCountsContainer.FadeTo(ResultAmounts == null ? 0f : 1f, 200, EasingTypes.Out); + resultCountsContainer.FadeTo(ResultAmounts == null ? 0f : 1f, 200, EasingTypes.OutQuint); if (ResultAmounts == null) return; resultCountsText.Text = pluralize("Artist", ResultAmounts.Artists) + ", " + @@ -129,9 +185,68 @@ namespace osu.Game.Overlays private void recreatePanels(PanelDisplayStyle displayStyle) { if (BeatmapSets == null) return; - panels.ChildrenEnumerable = BeatmapSets.Select(b => displayStyle == PanelDisplayStyle.Grid ? (DirectPanel)new DirectGridPanel(b) { Width = 400 } : new DirectListPanel(b)); + + panels.ChildrenEnumerable = BeatmapSets.Select(b => + { + switch (displayStyle) + { + case PanelDisplayStyle.Grid: + return new DirectGridPanel(b) { Width = 400 }; + default: + return new DirectListPanel(b); + } + }); } + private GetBeatmapSetsRequest getSetsRequest; + + private readonly Bindable currentQuery = new Bindable(); + + private ScheduledDelegate queryChangedDebounce; + + private void updateSearch() + { + queryChangedDebounce?.Cancel(); + + if (!IsLoaded) return; + + BeatmapSets = null; + ResultAmounts = null; + + getSetsRequest?.Cancel(); + + if (api == null) return; + + if (Header.Tabs.Current.Value == DirectTab.Search && (Filter.Search.Text == string.Empty || currentQuery == string.Empty)) return; + + getSetsRequest = new GetBeatmapSetsRequest(currentQuery, + ((FilterControl)Filter).Ruleset.Value, + Filter.DisplayStyleControl.Dropdown.Current.Value, + Filter.Tabs.Current.Value); //todo: sort direction (?) + + getSetsRequest.Success += r => + { + BeatmapSets = r?.Select(response => response.ToBeatmapSet(rulesets)); + if (BeatmapSets == null) return; + + var artists = new List(); + var songs = new List(); + var tags = new List(); + foreach (var s in BeatmapSets) + { + artists.Add(s.Metadata.Artist); + songs.Add(s.Metadata.Title); + tags.AddRange(s.Metadata.Tags.Split(' ')); + } + + ResultAmounts = new ResultCounts(distinctCount(artists), distinctCount(songs), distinctCount(tags)); + }; + + api.Queue(getSetsRequest); + } + + private int distinctCount(List list) => list.Distinct().ToArray().Length; + public class ResultCounts { public readonly int Artists; diff --git a/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs b/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs index 8db802ad3d..8d7d1ce994 100644 --- a/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs +++ b/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs @@ -120,6 +120,7 @@ namespace osu.Game.Overlays.SearchableList { protected override Color4 BackgroundUnfocused => backgroundColour; protected override Color4 BackgroundFocused => backgroundColour; + protected override bool AllowCommit => true; private Color4 backgroundColour; diff --git a/osu.Game/Overlays/SearchableList/SlimEnumDropdown.cs b/osu.Game/Overlays/SearchableList/SlimEnumDropdown.cs index 6c0887b5df..e2eec0214f 100644 --- a/osu.Game/Overlays/SearchableList/SlimEnumDropdown.cs +++ b/osu.Game/Overlays/SearchableList/SlimEnumDropdown.cs @@ -34,7 +34,7 @@ namespace osu.Game.Overlays.SearchableList { public SlimMenu() { - Background.Colour = Color4.Black.Opacity(0.25f); + Background.Colour = Color4.Black.Opacity(0.7f); } } } diff --git a/osu.Game/Screens/Multiplayer/RoomInspector.cs b/osu.Game/Screens/Multiplayer/RoomInspector.cs index 3a822be791..73783bab12 100644 --- a/osu.Game/Screens/Multiplayer/RoomInspector.cs +++ b/osu.Game/Screens/Multiplayer/RoomInspector.cs @@ -12,6 +12,7 @@ using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using osu.Framework.Localisation; using osu.Game.Beatmaps.Drawables; @@ -45,7 +46,6 @@ namespace osu.Game.Screens.Multiplayer private OsuColour colours; private LocalisationEngine localisation; - private TextureStore textures; private Room room; @@ -367,11 +367,10 @@ namespace osu.Game.Screens.Multiplayer } [BackgroundDependencyLoader] - private void load(OsuColour colours, LocalisationEngine localisation, TextureStore textures) + private void load(OsuColour colours, LocalisationEngine localisation) { this.localisation = localisation; this.colours = colours; - this.textures = textures; beatmapAuthor.Colour = levelRangeContainer.Colour = colours.Gray9; host.Colour = colours.Blue; @@ -436,7 +435,7 @@ namespace osu.Game.Screens.Multiplayer coverContainer.FadeIn(transition_duration); coverContainer.Children = new[] { - new AsyncLoadWrapper(new BeatmapBackgroundSprite(new OnlineWorkingBeatmap(value, textures, null)) + new AsyncLoadWrapper(new CoverSprite(value.BeatmapSet) { RelativeSizeAxes = Axes.Both, Anchor = Anchor.Centre, @@ -527,5 +526,22 @@ namespace osu.Game.Screens.Multiplayer }; } } + + private class CoverSprite : Sprite + { + private readonly BeatmapSetInfo set; + + public CoverSprite(BeatmapSetInfo set) + { + this.set = set; + } + + [BackgroundDependencyLoader] + private void load(TextureStore textures) + { + if (set.OnlineInfo?.Covers?.Cover != null) + Texture = textures.Get(set.OnlineInfo.Covers.Cover); + } + } } } diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 3d84f287f0..959642ce8b 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -473,10 +473,11 @@ - + +