mirror of
https://github.com/ppy/osu.git
synced 2024-12-15 05:02:55 +08:00
Merge pull request #7924 from EVAST9919/beatmap-listing-expanded
Implement sorting by genre and language in BeatmapListingOverlay
This commit is contained in:
commit
c3b36d8f20
@ -5,6 +5,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Game.Overlays.BeatmapListing;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Online
|
namespace osu.Game.Tests.Visual.Online
|
||||||
{
|
{
|
||||||
@ -13,6 +14,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
{
|
{
|
||||||
typeof(BeatmapListingOverlay),
|
typeof(BeatmapListingOverlay),
|
||||||
|
typeof(BeatmapListingFilterControl)
|
||||||
};
|
};
|
||||||
|
|
||||||
protected override bool UseOnlineAPI => true;
|
protected override bool UseOnlineAPI => true;
|
||||||
|
@ -15,25 +15,27 @@ using osuTK;
|
|||||||
|
|
||||||
namespace osu.Game.Tests.Visual.UserInterface
|
namespace osu.Game.Tests.Visual.UserInterface
|
||||||
{
|
{
|
||||||
public class TestSceneBeatmapListingSearchSection : OsuTestScene
|
public class TestSceneBeatmapListingSearchControl : OsuTestScene
|
||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
{
|
{
|
||||||
typeof(BeatmapListingSearchSection),
|
typeof(BeatmapListingSearchControl),
|
||||||
};
|
};
|
||||||
|
|
||||||
[Cached]
|
[Cached]
|
||||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||||
|
|
||||||
private readonly BeatmapListingSearchSection section;
|
private readonly BeatmapListingSearchControl control;
|
||||||
|
|
||||||
public TestSceneBeatmapListingSearchSection()
|
public TestSceneBeatmapListingSearchControl()
|
||||||
{
|
{
|
||||||
OsuSpriteText query;
|
OsuSpriteText query;
|
||||||
OsuSpriteText ruleset;
|
OsuSpriteText ruleset;
|
||||||
OsuSpriteText category;
|
OsuSpriteText category;
|
||||||
|
OsuSpriteText genre;
|
||||||
|
OsuSpriteText language;
|
||||||
|
|
||||||
Add(section = new BeatmapListingSearchSection
|
Add(control = new BeatmapListingSearchControl
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
@ -49,20 +51,24 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
query = new OsuSpriteText(),
|
query = new OsuSpriteText(),
|
||||||
ruleset = new OsuSpriteText(),
|
ruleset = new OsuSpriteText(),
|
||||||
category = new OsuSpriteText(),
|
category = new OsuSpriteText(),
|
||||||
|
genre = new OsuSpriteText(),
|
||||||
|
language = new OsuSpriteText(),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
section.Query.BindValueChanged(q => query.Text = $"Query: {q.NewValue}", true);
|
control.Query.BindValueChanged(q => query.Text = $"Query: {q.NewValue}", true);
|
||||||
section.Ruleset.BindValueChanged(r => ruleset.Text = $"Ruleset: {r.NewValue}", true);
|
control.Ruleset.BindValueChanged(r => ruleset.Text = $"Ruleset: {r.NewValue}", true);
|
||||||
section.Category.BindValueChanged(c => category.Text = $"Category: {c.NewValue}", true);
|
control.Category.BindValueChanged(c => category.Text = $"Category: {c.NewValue}", true);
|
||||||
|
control.Genre.BindValueChanged(g => genre.Text = $"Genre: {g.NewValue}", true);
|
||||||
|
control.Language.BindValueChanged(l => language.Text = $"Language: {l.NewValue}", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCovers()
|
public void TestCovers()
|
||||||
{
|
{
|
||||||
AddStep("Set beatmap", () => section.BeatmapSet = beatmap_set);
|
AddStep("Set beatmap", () => control.BeatmapSet = beatmap_set);
|
||||||
AddStep("Set beatmap (no cover)", () => section.BeatmapSet = no_cover_beatmap_set);
|
AddStep("Set beatmap (no cover)", () => control.BeatmapSet = no_cover_beatmap_set);
|
||||||
AddStep("Set null beatmap", () => section.BeatmapSet = null);
|
AddStep("Set null beatmap", () => control.BeatmapSet = null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly BeatmapSetInfo beatmap_set = new BeatmapSetInfo
|
private static readonly BeatmapSetInfo beatmap_set = new BeatmapSetInfo
|
@ -13,18 +13,17 @@ using osuTK;
|
|||||||
|
|
||||||
namespace osu.Game.Tests.Visual.UserInterface
|
namespace osu.Game.Tests.Visual.UserInterface
|
||||||
{
|
{
|
||||||
public class TestSceneBeatmapListingSort : OsuTestScene
|
public class TestSceneBeatmapListingSortTabControl : OsuTestScene
|
||||||
{
|
{
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
{
|
{
|
||||||
typeof(BeatmapListingSortTabControl),
|
|
||||||
typeof(OverlaySortTabControl<>),
|
typeof(OverlaySortTabControl<>),
|
||||||
};
|
};
|
||||||
|
|
||||||
[Cached]
|
[Cached]
|
||||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||||
|
|
||||||
public TestSceneBeatmapListingSort()
|
public TestSceneBeatmapListingSortTabControl()
|
||||||
{
|
{
|
||||||
BeatmapListingSortTabControl control;
|
BeatmapListingSortTabControl control;
|
||||||
OsuSpriteText current;
|
OsuSpriteText current;
|
@ -8,7 +8,6 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Online.API.Requests;
|
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Overlays.BeatmapListing;
|
using osu.Game.Overlays.BeatmapListing;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -20,8 +19,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
{
|
{
|
||||||
typeof(BeatmapSearchFilterRow<>),
|
typeof(BeatmapSearchFilterRow<>),
|
||||||
typeof(BeatmapSearchRulesetFilterRow),
|
typeof(BeatmapSearchRulesetFilterRow)
|
||||||
typeof(BeatmapSearchSmallFilterRow<>),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
[Cached]
|
[Cached]
|
||||||
@ -42,8 +40,8 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new BeatmapSearchRulesetFilterRow(),
|
new BeatmapSearchRulesetFilterRow(),
|
||||||
new BeatmapSearchFilterRow<BeatmapSearchCategory>("Categories"),
|
new BeatmapSearchFilterRow<SearchCategory>("Categories"),
|
||||||
new BeatmapSearchSmallFilterRow<BeatmapSearchCategory>("Header Name")
|
new BeatmapSearchFilterRow<SearchCategory>("Header Name")
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System.ComponentModel;
|
|
||||||
using osu.Framework.IO.Network;
|
using osu.Framework.IO.Network;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
|
using osu.Game.Overlays.BeatmapListing;
|
||||||
using osu.Game.Overlays.Direct;
|
using osu.Game.Overlays.Direct;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
|
||||||
@ -11,20 +11,31 @@ namespace osu.Game.Online.API.Requests
|
|||||||
{
|
{
|
||||||
public class SearchBeatmapSetsRequest : APIRequest<SearchBeatmapSetsResponse>
|
public class SearchBeatmapSetsRequest : APIRequest<SearchBeatmapSetsResponse>
|
||||||
{
|
{
|
||||||
|
public SearchCategory SearchCategory { get; set; }
|
||||||
|
|
||||||
|
public DirectSortCriteria SortCriteria { get; set; }
|
||||||
|
|
||||||
|
public SortDirection SortDirection { get; set; }
|
||||||
|
|
||||||
|
public SearchGenre Genre { get; set; }
|
||||||
|
|
||||||
|
public SearchLanguage Language { get; set; }
|
||||||
|
|
||||||
private readonly string query;
|
private readonly string query;
|
||||||
private readonly RulesetInfo ruleset;
|
private readonly RulesetInfo ruleset;
|
||||||
private readonly BeatmapSearchCategory searchCategory;
|
|
||||||
private readonly DirectSortCriteria sortCriteria;
|
|
||||||
private readonly SortDirection direction;
|
|
||||||
private string directionString => direction == SortDirection.Descending ? @"desc" : @"asc";
|
|
||||||
|
|
||||||
public SearchBeatmapSetsRequest(string query, RulesetInfo ruleset, BeatmapSearchCategory searchCategory = BeatmapSearchCategory.Any, DirectSortCriteria sortCriteria = DirectSortCriteria.Ranked, SortDirection direction = SortDirection.Descending)
|
private string directionString => SortDirection == SortDirection.Descending ? @"desc" : @"asc";
|
||||||
|
|
||||||
|
public SearchBeatmapSetsRequest(string query, RulesetInfo ruleset)
|
||||||
{
|
{
|
||||||
this.query = string.IsNullOrEmpty(query) ? string.Empty : System.Uri.EscapeDataString(query);
|
this.query = string.IsNullOrEmpty(query) ? string.Empty : System.Uri.EscapeDataString(query);
|
||||||
this.ruleset = ruleset;
|
this.ruleset = ruleset;
|
||||||
this.searchCategory = searchCategory;
|
|
||||||
this.sortCriteria = sortCriteria;
|
SearchCategory = SearchCategory.Any;
|
||||||
this.direction = direction;
|
SortCriteria = DirectSortCriteria.Ranked;
|
||||||
|
SortDirection = SortDirection.Descending;
|
||||||
|
Genre = SearchGenre.Any;
|
||||||
|
Language = SearchLanguage.Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override WebRequest CreateWebRequest()
|
protected override WebRequest CreateWebRequest()
|
||||||
@ -35,31 +46,19 @@ namespace osu.Game.Online.API.Requests
|
|||||||
if (ruleset.ID.HasValue)
|
if (ruleset.ID.HasValue)
|
||||||
req.AddParameter("m", ruleset.ID.Value.ToString());
|
req.AddParameter("m", ruleset.ID.Value.ToString());
|
||||||
|
|
||||||
req.AddParameter("s", searchCategory.ToString().ToLowerInvariant());
|
req.AddParameter("s", SearchCategory.ToString().ToLowerInvariant());
|
||||||
req.AddParameter("sort", $"{sortCriteria.ToString().ToLowerInvariant()}_{directionString}");
|
|
||||||
|
if (Genre != SearchGenre.Any)
|
||||||
|
req.AddParameter("g", ((int)Genre).ToString());
|
||||||
|
|
||||||
|
if (Language != SearchLanguage.Any)
|
||||||
|
req.AddParameter("l", ((int)Language).ToString());
|
||||||
|
|
||||||
|
req.AddParameter("sort", $"{SortCriteria.ToString().ToLowerInvariant()}_{directionString}");
|
||||||
|
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string Target => @"beatmapsets/search";
|
protected override string Target => @"beatmapsets/search";
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum BeatmapSearchCategory
|
|
||||||
{
|
|
||||||
Any,
|
|
||||||
|
|
||||||
[Description("Has Leaderboard")]
|
|
||||||
Leaderboard,
|
|
||||||
Ranked,
|
|
||||||
Qualified,
|
|
||||||
Loved,
|
|
||||||
Favourites,
|
|
||||||
|
|
||||||
[Description("Pending & WIP")]
|
|
||||||
Pending,
|
|
||||||
Graveyard,
|
|
||||||
|
|
||||||
[Description("My Maps")]
|
|
||||||
Mine,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
163
osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs
Normal file
163
osu.Game/Overlays/BeatmapListing/BeatmapListingFilterControl.cs
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.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.Beatmaps;
|
||||||
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Online.API.Requests;
|
||||||
|
using osu.Game.Overlays.Direct;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Overlays.BeatmapListing
|
||||||
|
{
|
||||||
|
public class BeatmapListingFilterControl : CompositeDrawable
|
||||||
|
{
|
||||||
|
public Action<List<BeatmapSetInfo>> SearchFinished;
|
||||||
|
public Action SearchStarted;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private IAPIProvider api { get; set; }
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private RulesetStore rulesets { get; set; }
|
||||||
|
|
||||||
|
private readonly BeatmapListingSearchControl searchControl;
|
||||||
|
private readonly BeatmapListingSortTabControl sortControl;
|
||||||
|
private readonly Box sortControlBackground;
|
||||||
|
|
||||||
|
private SearchBeatmapSetsRequest getSetsRequest;
|
||||||
|
|
||||||
|
public BeatmapListingFilterControl()
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
AutoSizeAxes = Axes.Y;
|
||||||
|
InternalChild = new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Spacing = new Vector2(0, 10),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Masking = true,
|
||||||
|
EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Colour = Color4.Black.Opacity(0.25f),
|
||||||
|
Type = EdgeEffectType.Shadow,
|
||||||
|
Radius = 3,
|
||||||
|
Offset = new Vector2(0f, 1f),
|
||||||
|
},
|
||||||
|
Child = searchControl = new BeatmapListingSearchControl(),
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Height = 40,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
sortControlBackground = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
},
|
||||||
|
sortControl = new BeatmapListingSortTabControl
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Margin = new MarginPadding { Left = 20 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OverlayColourProvider colourProvider)
|
||||||
|
{
|
||||||
|
sortControlBackground.Colour = colourProvider.Background5;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
var sortCriteria = sortControl.Current;
|
||||||
|
var sortDirection = sortControl.SortDirection;
|
||||||
|
|
||||||
|
searchControl.Query.BindValueChanged(query =>
|
||||||
|
{
|
||||||
|
sortCriteria.Value = string.IsNullOrEmpty(query.NewValue) ? DirectSortCriteria.Ranked : DirectSortCriteria.Relevance;
|
||||||
|
sortDirection.Value = SortDirection.Descending;
|
||||||
|
queueUpdateSearch(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
searchControl.Ruleset.BindValueChanged(_ => queueUpdateSearch());
|
||||||
|
searchControl.Category.BindValueChanged(_ => queueUpdateSearch());
|
||||||
|
searchControl.Genre.BindValueChanged(_ => queueUpdateSearch());
|
||||||
|
searchControl.Language.BindValueChanged(_ => queueUpdateSearch());
|
||||||
|
|
||||||
|
sortCriteria.BindValueChanged(_ => queueUpdateSearch());
|
||||||
|
sortDirection.BindValueChanged(_ => queueUpdateSearch());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ScheduledDelegate queryChangedDebounce;
|
||||||
|
|
||||||
|
private void queueUpdateSearch(bool queryTextChanged = false)
|
||||||
|
{
|
||||||
|
SearchStarted?.Invoke();
|
||||||
|
|
||||||
|
getSetsRequest?.Cancel();
|
||||||
|
|
||||||
|
queryChangedDebounce?.Cancel();
|
||||||
|
queryChangedDebounce = Scheduler.AddDelayed(updateSearch, queryTextChanged ? 500 : 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateSearch()
|
||||||
|
{
|
||||||
|
getSetsRequest = new SearchBeatmapSetsRequest(searchControl.Query.Value, searchControl.Ruleset.Value)
|
||||||
|
{
|
||||||
|
SearchCategory = searchControl.Category.Value,
|
||||||
|
SortCriteria = sortControl.Current.Value,
|
||||||
|
SortDirection = sortControl.SortDirection.Value,
|
||||||
|
Genre = searchControl.Genre.Value,
|
||||||
|
Language = searchControl.Language.Value
|
||||||
|
};
|
||||||
|
|
||||||
|
getSetsRequest.Success += response => Schedule(() => onSearchFinished(response));
|
||||||
|
|
||||||
|
api.Queue(getSetsRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onSearchFinished(SearchBeatmapSetsResponse response)
|
||||||
|
{
|
||||||
|
var beatmaps = response.BeatmapSets.Select(r => r.ToBeatmapSet(rulesets)).ToList();
|
||||||
|
|
||||||
|
searchControl.BeatmapSet = response.Total == 0 ? null : beatmaps.First();
|
||||||
|
|
||||||
|
SearchFinished?.Invoke(beatmaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
getSetsRequest?.Cancel();
|
||||||
|
queryChangedDebounce?.Cancel();
|
||||||
|
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,8 +5,6 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Game.Online.API.Requests;
|
|
||||||
using osu.Game.Rulesets;
|
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Game.Beatmaps.Drawables;
|
using osu.Game.Beatmaps.Drawables;
|
||||||
@ -14,16 +12,21 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.BeatmapListing
|
namespace osu.Game.Overlays.BeatmapListing
|
||||||
{
|
{
|
||||||
public class BeatmapListingSearchSection : CompositeDrawable
|
public class BeatmapListingSearchControl : CompositeDrawable
|
||||||
{
|
{
|
||||||
public Bindable<string> Query => textBox.Current;
|
public Bindable<string> Query => textBox.Current;
|
||||||
|
|
||||||
public Bindable<RulesetInfo> Ruleset => modeFilter.Current;
|
public Bindable<RulesetInfo> Ruleset => modeFilter.Current;
|
||||||
|
|
||||||
public Bindable<BeatmapSearchCategory> Category => categoryFilter.Current;
|
public Bindable<SearchCategory> Category => categoryFilter.Current;
|
||||||
|
|
||||||
|
public Bindable<SearchGenre> Genre => genreFilter.Current;
|
||||||
|
|
||||||
|
public Bindable<SearchLanguage> Language => languageFilter.Current;
|
||||||
|
|
||||||
public BeatmapSetInfo BeatmapSet
|
public BeatmapSetInfo BeatmapSet
|
||||||
{
|
{
|
||||||
@ -42,12 +45,14 @@ namespace osu.Game.Overlays.BeatmapListing
|
|||||||
|
|
||||||
private readonly BeatmapSearchTextBox textBox;
|
private readonly BeatmapSearchTextBox textBox;
|
||||||
private readonly BeatmapSearchRulesetFilterRow modeFilter;
|
private readonly BeatmapSearchRulesetFilterRow modeFilter;
|
||||||
private readonly BeatmapSearchFilterRow<BeatmapSearchCategory> categoryFilter;
|
private readonly BeatmapSearchFilterRow<SearchCategory> categoryFilter;
|
||||||
|
private readonly BeatmapSearchFilterRow<SearchGenre> genreFilter;
|
||||||
|
private readonly BeatmapSearchFilterRow<SearchLanguage> languageFilter;
|
||||||
|
|
||||||
private readonly Box background;
|
private readonly Box background;
|
||||||
private readonly UpdateableBeatmapSetCover beatmapCover;
|
private readonly UpdateableBeatmapSetCover beatmapCover;
|
||||||
|
|
||||||
public BeatmapListingSearchSection()
|
public BeatmapListingSearchControl()
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Y;
|
AutoSizeAxes = Axes.Y;
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
@ -97,7 +102,9 @@ namespace osu.Game.Overlays.BeatmapListing
|
|||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
modeFilter = new BeatmapSearchRulesetFilterRow(),
|
modeFilter = new BeatmapSearchRulesetFilterRow(),
|
||||||
categoryFilter = new BeatmapSearchFilterRow<BeatmapSearchCategory>(@"Categories"),
|
categoryFilter = new BeatmapSearchFilterRow<SearchCategory>(@"Categories"),
|
||||||
|
genreFilter = new BeatmapSearchFilterRow<SearchGenre>(@"Genre"),
|
||||||
|
languageFilter = new BeatmapSearchFilterRow<SearchLanguage>(@"Language"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,7 +112,7 @@ namespace osu.Game.Overlays.BeatmapListing
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Category.Value = BeatmapSearchCategory.Leaderboard;
|
categoryFilter.Current.Value = SearchCategory.Leaderboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
@ -15,6 +15,8 @@ using osu.Game.Graphics.Sprites;
|
|||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
using Humanizer;
|
||||||
|
using osu.Game.Utils;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.BeatmapListing
|
namespace osu.Game.Overlays.BeatmapListing
|
||||||
{
|
{
|
||||||
@ -53,8 +55,8 @@ namespace osu.Game.Overlays.BeatmapListing
|
|||||||
{
|
{
|
||||||
Anchor = Anchor.BottomLeft,
|
Anchor = Anchor.BottomLeft,
|
||||||
Origin = Anchor.BottomLeft,
|
Origin = Anchor.BottomLeft,
|
||||||
Font = OsuFont.GetFont(size: 10),
|
Font = OsuFont.GetFont(size: 13),
|
||||||
Text = headerName.ToUpper()
|
Text = headerName.Titleize()
|
||||||
},
|
},
|
||||||
CreateFilter().With(f =>
|
CreateFilter().With(f =>
|
||||||
{
|
{
|
||||||
@ -81,7 +83,7 @@ namespace osu.Game.Overlays.BeatmapListing
|
|||||||
|
|
||||||
if (typeof(T).IsEnum)
|
if (typeof(T).IsEnum)
|
||||||
{
|
{
|
||||||
foreach (var val in (T[])Enum.GetValues(typeof(T)))
|
foreach (var val in OrderAttributeUtils.GetValuesInOrder<T>())
|
||||||
AddItem(val);
|
AddItem(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
|
||||||
|
|
||||||
using osu.Framework.Graphics.UserInterface;
|
|
||||||
|
|
||||||
namespace osu.Game.Overlays.BeatmapListing
|
|
||||||
{
|
|
||||||
public class BeatmapSearchSmallFilterRow<T> : BeatmapSearchFilterRow<T>
|
|
||||||
{
|
|
||||||
public BeatmapSearchSmallFilterRow(string headerName)
|
|
||||||
: base(headerName)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override BeatmapSearchFilter CreateFilter() => new SmallBeatmapSearchFilter();
|
|
||||||
|
|
||||||
private class SmallBeatmapSearchFilter : BeatmapSearchFilter
|
|
||||||
{
|
|
||||||
protected override TabItem<T> CreateTabItem(T value) => new SmallTabItem(value);
|
|
||||||
|
|
||||||
private class SmallTabItem : FilterTabItem
|
|
||||||
{
|
|
||||||
public SmallTabItem(T value)
|
|
||||||
: base(value)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override float TextSize => 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
26
osu.Game/Overlays/BeatmapListing/SearchCategory.cs
Normal file
26
osu.Game/Overlays/BeatmapListing/SearchCategory.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace osu.Game.Overlays.BeatmapListing
|
||||||
|
{
|
||||||
|
public enum SearchCategory
|
||||||
|
{
|
||||||
|
Any,
|
||||||
|
|
||||||
|
[Description("Has Leaderboard")]
|
||||||
|
Leaderboard,
|
||||||
|
Ranked,
|
||||||
|
Qualified,
|
||||||
|
Loved,
|
||||||
|
Favourites,
|
||||||
|
|
||||||
|
[Description("Pending & WIP")]
|
||||||
|
Pending,
|
||||||
|
Graveyard,
|
||||||
|
|
||||||
|
[Description("My Maps")]
|
||||||
|
Mine,
|
||||||
|
}
|
||||||
|
}
|
25
osu.Game/Overlays/BeatmapListing/SearchGenre.cs
Normal file
25
osu.Game/Overlays/BeatmapListing/SearchGenre.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace osu.Game.Overlays.BeatmapListing
|
||||||
|
{
|
||||||
|
public enum SearchGenre
|
||||||
|
{
|
||||||
|
Any = 0,
|
||||||
|
Unspecified = 1,
|
||||||
|
|
||||||
|
[Description("Video Game")]
|
||||||
|
VideoGame = 2,
|
||||||
|
Anime = 3,
|
||||||
|
Rock = 4,
|
||||||
|
Pop = 5,
|
||||||
|
Other = 6,
|
||||||
|
Novelty = 7,
|
||||||
|
|
||||||
|
[Description("Hip Hop")]
|
||||||
|
HipHop = 9,
|
||||||
|
Electronic = 10
|
||||||
|
}
|
||||||
|
}
|
47
osu.Game/Overlays/BeatmapListing/SearchLanguage.cs
Normal file
47
osu.Game/Overlays/BeatmapListing/SearchLanguage.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Game.Utils;
|
||||||
|
|
||||||
|
namespace osu.Game.Overlays.BeatmapListing
|
||||||
|
{
|
||||||
|
[HasOrderedElements]
|
||||||
|
public enum SearchLanguage
|
||||||
|
{
|
||||||
|
[Order(0)]
|
||||||
|
Any,
|
||||||
|
|
||||||
|
[Order(11)]
|
||||||
|
Other,
|
||||||
|
|
||||||
|
[Order(1)]
|
||||||
|
English,
|
||||||
|
|
||||||
|
[Order(6)]
|
||||||
|
Japanese,
|
||||||
|
|
||||||
|
[Order(2)]
|
||||||
|
Chinese,
|
||||||
|
|
||||||
|
[Order(10)]
|
||||||
|
Instrumental,
|
||||||
|
|
||||||
|
[Order(7)]
|
||||||
|
Korean,
|
||||||
|
|
||||||
|
[Order(3)]
|
||||||
|
French,
|
||||||
|
|
||||||
|
[Order(4)]
|
||||||
|
German,
|
||||||
|
|
||||||
|
[Order(9)]
|
||||||
|
Swedish,
|
||||||
|
|
||||||
|
[Order(8)]
|
||||||
|
Spanish,
|
||||||
|
|
||||||
|
[Order(5)]
|
||||||
|
Italian
|
||||||
|
}
|
||||||
|
}
|
@ -1,27 +1,23 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Effects;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Framework.Threading;
|
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Online.API.Requests;
|
|
||||||
using osu.Game.Overlays.BeatmapListing;
|
using osu.Game.Overlays.BeatmapListing;
|
||||||
using osu.Game.Overlays.Direct;
|
using osu.Game.Overlays.Direct;
|
||||||
using osu.Game.Rulesets;
|
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Overlays
|
namespace osu.Game.Overlays
|
||||||
{
|
{
|
||||||
@ -30,14 +26,9 @@ namespace osu.Game.Overlays
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private PreviewTrackManager previewTrackManager { get; set; }
|
private PreviewTrackManager previewTrackManager { get; set; }
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private RulesetStore rulesets { get; set; }
|
|
||||||
|
|
||||||
private SearchBeatmapSetsRequest getSetsRequest;
|
|
||||||
|
|
||||||
private Drawable currentContent;
|
private Drawable currentContent;
|
||||||
private BeatmapListingSearchSection searchSection;
|
private LoadingLayer loadingLayer;
|
||||||
private BeatmapListingSortTabControl sortControl;
|
private Container panelTarget;
|
||||||
|
|
||||||
public BeatmapListingOverlay()
|
public BeatmapListingOverlay()
|
||||||
: base(OverlayColourScheme.Blue)
|
: base(OverlayColourScheme.Blue)
|
||||||
@ -63,27 +54,13 @@ namespace osu.Game.Overlays
|
|||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Direction = FillDirection.Vertical,
|
Direction = FillDirection.Vertical,
|
||||||
Spacing = new Vector2(0, 10),
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new FillFlowContainer
|
new BeatmapListingHeader(),
|
||||||
|
new BeatmapListingFilterControl
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Y,
|
SearchStarted = onSearchStarted,
|
||||||
RelativeSizeAxes = Axes.X,
|
SearchFinished = onSearchFinished,
|
||||||
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
|
new Container
|
||||||
{
|
{
|
||||||
@ -96,128 +73,41 @@ namespace osu.Game.Overlays
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = ColourProvider.Background4,
|
Colour = ColourProvider.Background4,
|
||||||
},
|
},
|
||||||
new FillFlowContainer
|
panelTarget = new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
Children = new Drawable[]
|
RelativeSizeAxes = Axes.X,
|
||||||
{
|
Padding = new MarginPadding { Horizontal = 20 }
|
||||||
new Container
|
},
|
||||||
{
|
loadingLayer = new LoadingLayer(panelTarget)
|
||||||
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 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new Container
|
|
||||||
{
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Padding = new MarginPadding { Horizontal = 20 },
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
panelTarget = new Container
|
|
||||||
{
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
},
|
|
||||||
loadingLayer = new LoadingLayer(panelTarget),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
private CancellationTokenSource cancellationToken;
|
||||||
|
|
||||||
|
private void onSearchStarted()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
cancellationToken?.Cancel();
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
queueUpdateSearch(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
searchSection.Ruleset.BindValueChanged(_ => queueUpdateSearch());
|
|
||||||
searchSection.Category.BindValueChanged(_ => queueUpdateSearch());
|
|
||||||
sortCriteria.BindValueChanged(_ => queueUpdateSearch());
|
|
||||||
sortDirection.BindValueChanged(_ => queueUpdateSearch());
|
|
||||||
}
|
|
||||||
|
|
||||||
private ScheduledDelegate queryChangedDebounce;
|
|
||||||
|
|
||||||
private LoadingLayer loadingLayer;
|
|
||||||
private Container panelTarget;
|
|
||||||
|
|
||||||
private void queueUpdateSearch(bool queryTextChanged = false)
|
|
||||||
{
|
|
||||||
getSetsRequest?.Cancel();
|
|
||||||
|
|
||||||
queryChangedDebounce?.Cancel();
|
|
||||||
queryChangedDebounce = Scheduler.AddDelayed(updateSearch, queryTextChanged ? 500 : 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateSearch()
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (State.Value == Visibility.Hidden)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (API == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
previewTrackManager.StopAnyPlaying(this);
|
previewTrackManager.StopAnyPlaying(this);
|
||||||
|
|
||||||
loadingLayer.Show();
|
if (panelTarget.Any())
|
||||||
|
loadingLayer.Show();
|
||||||
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)
|
private void onSearchFinished(List<BeatmapSetInfo> beatmaps)
|
||||||
{
|
{
|
||||||
if (response.Total == 0)
|
if (!beatmaps.Any())
|
||||||
{
|
{
|
||||||
searchSection.BeatmapSet = null;
|
LoadComponentAsync(new NotFoundDrawable(), addContentToPlaceholder, (cancellationToken = new CancellationTokenSource()).Token);
|
||||||
LoadComponentAsync(new NotFoundDrawable(), addContentToPlaceholder);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var beatmaps = response.BeatmapSets.Select(r => r.ToBeatmapSet(rulesets)).ToList();
|
|
||||||
|
|
||||||
var newPanels = new FillFlowContainer<DirectPanel>
|
var newPanels = new FillFlowContainer<DirectPanel>
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
@ -232,18 +122,14 @@ namespace osu.Game.Overlays
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
LoadComponentAsync(newPanels, loaded =>
|
LoadComponentAsync(newPanels, addContentToPlaceholder, (cancellationToken = new CancellationTokenSource()).Token);
|
||||||
{
|
|
||||||
addContentToPlaceholder(loaded);
|
|
||||||
searchSection.BeatmapSet = beatmaps.First();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addContentToPlaceholder(Drawable content)
|
private void addContentToPlaceholder(Drawable content)
|
||||||
{
|
{
|
||||||
loadingLayer.Hide();
|
loadingLayer.Hide();
|
||||||
|
|
||||||
Drawable lastContent = currentContent;
|
var lastContent = currentContent;
|
||||||
|
|
||||||
if (lastContent != null)
|
if (lastContent != null)
|
||||||
{
|
{
|
||||||
@ -262,9 +148,7 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
getSetsRequest?.Cancel();
|
cancellationToken?.Cancel();
|
||||||
queryChangedDebounce?.Cancel();
|
|
||||||
|
|
||||||
base.Dispose(isDisposing);
|
base.Dispose(isDisposing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,20 +6,20 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Online.API.Requests;
|
using osu.Game.Overlays.BeatmapListing;
|
||||||
using osu.Game.Overlays.SearchableList;
|
using osu.Game.Overlays.SearchableList;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Direct
|
namespace osu.Game.Overlays.Direct
|
||||||
{
|
{
|
||||||
public class FilterControl : SearchableListFilterControl<DirectSortCriteria, BeatmapSearchCategory>
|
public class FilterControl : SearchableListFilterControl<DirectSortCriteria, SearchCategory>
|
||||||
{
|
{
|
||||||
private DirectRulesetSelector rulesetSelector;
|
private DirectRulesetSelector rulesetSelector;
|
||||||
|
|
||||||
protected override Color4 BackgroundColour => Color4Extensions.FromHex(@"384552");
|
protected override Color4 BackgroundColour => Color4Extensions.FromHex(@"384552");
|
||||||
protected override DirectSortCriteria DefaultTab => DirectSortCriteria.Ranked;
|
protected override DirectSortCriteria DefaultTab => DirectSortCriteria.Ranked;
|
||||||
protected override BeatmapSearchCategory DefaultCategory => BeatmapSearchCategory.Leaderboard;
|
protected override SearchCategory DefaultCategory => SearchCategory.Leaderboard;
|
||||||
|
|
||||||
protected override Drawable CreateSupplementaryControls() => rulesetSelector = new DirectRulesetSelector();
|
protected override Drawable CreateSupplementaryControls() => rulesetSelector = new DirectRulesetSelector();
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Online.API.Requests;
|
using osu.Game.Online.API.Requests;
|
||||||
|
using osu.Game.Overlays.BeatmapListing;
|
||||||
using osu.Game.Overlays.Direct;
|
using osu.Game.Overlays.Direct;
|
||||||
using osu.Game.Overlays.SearchableList;
|
using osu.Game.Overlays.SearchableList;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
@ -24,7 +25,7 @@ using osuTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Overlays
|
namespace osu.Game.Overlays
|
||||||
{
|
{
|
||||||
public class DirectOverlay : SearchableListOverlay<DirectTab, DirectSortCriteria, BeatmapSearchCategory>
|
public class DirectOverlay : SearchableListOverlay<DirectTab, DirectSortCriteria, SearchCategory>
|
||||||
{
|
{
|
||||||
private const float panel_padding = 10f;
|
private const float panel_padding = 10f;
|
||||||
|
|
||||||
@ -40,7 +41,7 @@ namespace osu.Game.Overlays
|
|||||||
protected override Color4 TrianglesColourDark => Color4Extensions.FromHex(@"3f5265");
|
protected override Color4 TrianglesColourDark => Color4Extensions.FromHex(@"3f5265");
|
||||||
|
|
||||||
protected override SearchableListHeader<DirectTab> CreateHeader() => new Header();
|
protected override SearchableListHeader<DirectTab> CreateHeader() => new Header();
|
||||||
protected override SearchableListFilterControl<DirectSortCriteria, BeatmapSearchCategory> CreateFilterControl() => new FilterControl();
|
protected override SearchableListFilterControl<DirectSortCriteria, SearchCategory> CreateFilterControl() => new FilterControl();
|
||||||
|
|
||||||
private IEnumerable<BeatmapSetInfo> beatmapSets;
|
private IEnumerable<BeatmapSetInfo> beatmapSets;
|
||||||
|
|
||||||
@ -255,11 +256,11 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
previewTrackManager.StopAnyPlaying(this);
|
previewTrackManager.StopAnyPlaying(this);
|
||||||
|
|
||||||
getSetsRequest = new SearchBeatmapSetsRequest(
|
getSetsRequest = new SearchBeatmapSetsRequest(currentQuery.Value, ((FilterControl)Filter).Ruleset.Value)
|
||||||
currentQuery.Value,
|
{
|
||||||
((FilterControl)Filter).Ruleset.Value,
|
SearchCategory = Filter.DisplayStyleControl.Dropdown.Current.Value,
|
||||||
Filter.DisplayStyleControl.Dropdown.Current.Value,
|
SortCriteria = Filter.Tabs.Current.Value
|
||||||
Filter.Tabs.Current.Value); //todo: sort direction (?)
|
};
|
||||||
|
|
||||||
getSetsRequest.Success += response =>
|
getSetsRequest.Success += response =>
|
||||||
{
|
{
|
||||||
|
52
osu.Game/Utils/OrderAttribute.cs
Normal file
52
osu.Game/Utils/OrderAttribute.cs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace osu.Game.Utils
|
||||||
|
{
|
||||||
|
public static class OrderAttributeUtils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get values of an enum in order. Supports custom ordering via <see cref="OrderAttribute"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static IEnumerable<T> GetValuesInOrder<T>()
|
||||||
|
{
|
||||||
|
var type = typeof(T);
|
||||||
|
|
||||||
|
if (!type.IsEnum)
|
||||||
|
throw new InvalidOperationException("T must be an enum");
|
||||||
|
|
||||||
|
IEnumerable<T> items = (T[])Enum.GetValues(type);
|
||||||
|
|
||||||
|
if (Attribute.GetCustomAttribute(type, typeof(HasOrderedElementsAttribute)) == null)
|
||||||
|
return items;
|
||||||
|
|
||||||
|
return items.OrderBy(i =>
|
||||||
|
{
|
||||||
|
if (type.GetField(i.ToString()).GetCustomAttributes(typeof(OrderAttribute), false).FirstOrDefault() is OrderAttribute attr)
|
||||||
|
return attr.Order;
|
||||||
|
|
||||||
|
throw new ArgumentException($"Not all values of {nameof(T)} have {nameof(OrderAttribute)} specified.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Field)]
|
||||||
|
public class OrderAttribute : Attribute
|
||||||
|
{
|
||||||
|
public readonly int Order;
|
||||||
|
|
||||||
|
public OrderAttribute(int order)
|
||||||
|
{
|
||||||
|
Order = order;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Enum)]
|
||||||
|
public class HasOrderedElementsAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user