From 907236e475a6ee341e0993de94176413fd538340 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 17 Mar 2017 19:54:51 +0900 Subject: [PATCH] Move filtering to BeatmapCarousel (but actual logic is now in FilterCriteria. --- osu.Game/Beatmaps/Drawables/BeatmapGroup.cs | 2 +- osu.Game/Beatmaps/Drawables/BeatmapPanel.cs | 2 +- .../Beatmaps/Drawables/BeatmapSetHeader.cs | 2 +- osu.Game/Beatmaps/Drawables/Panel.cs | 4 +- osu.Game/Screens/Select/BeatmapCarousel.cs | 63 ++++++++++-------- osu.Game/Screens/Select/FilterControl.cs | 35 ++++++---- osu.Game/Screens/Select/FilterCriteria.cs | 62 ++++++++++++++++++ osu.Game/Screens/Select/SongSelect.cs | 64 ++----------------- osu.Game/osu.Game.csproj | 1 + 9 files changed, 131 insertions(+), 104 deletions(-) create mode 100644 osu.Game/Screens/Select/FilterCriteria.cs diff --git a/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs b/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs index a2824f01e3..ac0ab9966f 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapGroup.cs @@ -10,7 +10,7 @@ using osu.Game.Database; namespace osu.Game.Beatmaps.Drawables { - internal class BeatmapGroup : IStateful + public class BeatmapGroup : IStateful { public BeatmapPanel SelectedPanel; diff --git a/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs b/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs index f04d35efc3..67ebb2fcb9 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapPanel.cs @@ -18,7 +18,7 @@ using osu.Game.Graphics.Sprites; namespace osu.Game.Beatmaps.Drawables { - internal class BeatmapPanel : Panel + public class BeatmapPanel : Panel { public BeatmapInfo Beatmap; private Sprite background; diff --git a/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs b/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs index cb6fa02553..3dc5fdedc9 100644 --- a/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs +++ b/osu.Game/Beatmaps/Drawables/BeatmapSetHeader.cs @@ -17,7 +17,7 @@ using OpenTK.Graphics; namespace osu.Game.Beatmaps.Drawables { - internal class BeatmapSetHeader : Panel + public class BeatmapSetHeader : Panel { public Action GainedSelection; private SpriteText title, artist; diff --git a/osu.Game/Beatmaps/Drawables/Panel.cs b/osu.Game/Beatmaps/Drawables/Panel.cs index fba586bc05..c51ae8680e 100644 --- a/osu.Game/Beatmaps/Drawables/Panel.cs +++ b/osu.Game/Beatmaps/Drawables/Panel.cs @@ -12,7 +12,7 @@ using osu.Framework.Extensions.Color4Extensions; namespace osu.Game.Beatmaps.Drawables { - internal class Panel : Container, IStateful + public class Panel : Container, IStateful { public const float MAX_HEIGHT = 80; @@ -117,7 +117,7 @@ namespace osu.Game.Beatmaps.Drawables } } - internal enum PanelSelectedState + public enum PanelSelectedState { Hidden, NotSelected, diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs index 885ca8bfbe..20ebfb3837 100644 --- a/osu.Game/Screens/Select/BeatmapCarousel.cs +++ b/osu.Game/Screens/Select/BeatmapCarousel.cs @@ -17,7 +17,7 @@ using osu.Framework.MathUtils; using System.Diagnostics; using System.Threading.Tasks; using osu.Framework.Allocation; -using osu.Game.Screens.Select.Filter; +using osu.Framework.Threading; namespace osu.Game.Screens.Select { @@ -40,19 +40,20 @@ namespace osu.Game.Screens.Select panels.Clear(); groups.Clear(); - IEnumerable newGroups = null; + List newGroups = null; Task.Run(() => { newGroups = value.Select(createGroup).ToList(); + criteria.Filter(newGroups); }).ContinueWith(t => { Schedule(() => { foreach (var g in newGroups) addGroup(g); - computeYPositions(); + computeYPositions(); BeatmapsChanged?.Invoke(); }); }); @@ -173,36 +174,42 @@ namespace osu.Game.Screens.Select selectGroup(group, panel); } - public void Sort(SortMode mode) + private FilterCriteria criteria = new FilterCriteria(); + + private ScheduledDelegate filterTask; + + public void Filter(FilterCriteria newCriteria = null, bool debounce = true) { - List sortedGroups = new List(groups); - switch (mode) + if (!IsLoaded) return; + + criteria = newCriteria ?? criteria ?? new FilterCriteria(); + + Action perform = delegate { - case SortMode.Artist: - sortedGroups.Sort((x, y) => string.Compare(x.BeatmapSet.Metadata.Artist, y.BeatmapSet.Metadata.Artist, StringComparison.InvariantCultureIgnoreCase)); - break; - case SortMode.Title: - sortedGroups.Sort((x, y) => string.Compare(x.BeatmapSet.Metadata.Title, y.BeatmapSet.Metadata.Title, StringComparison.InvariantCultureIgnoreCase)); - break; - case SortMode.Author: - sortedGroups.Sort((x, y) => string.Compare(x.BeatmapSet.Metadata.Author, y.BeatmapSet.Metadata.Author, StringComparison.InvariantCultureIgnoreCase)); - break; - case SortMode.Difficulty: - sortedGroups.Sort((x, y) => x.BeatmapSet.MaxStarDifficulty.CompareTo(y.BeatmapSet.MaxStarDifficulty)); - break; - default: - Sort(SortMode.Artist); // Temporary - break; - } + filterTask = null; - scrollableContent.Clear(false); - panels.Clear(); - groups.Clear(); + criteria.Filter(groups); - foreach (var g in sortedGroups) - addGroup(g); + var filtered = new List(groups); - computeYPositions(); + scrollableContent.Clear(false); + panels.Clear(); + groups.Clear(); + + foreach (var g in filtered) + addGroup(g); + + computeYPositions(); + + if (selectedGroup.State == BeatmapGroupState.Hidden) + SelectNext(); + }; + + filterTask?.Cancel(); + if (debounce) + filterTask = Scheduler.AddDelayed(perform, 250); + else + perform(); } public IEnumerator GetEnumerator() => groups.GetEnumerator(); diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs index 2a25928dc7..9658509981 100644 --- a/osu.Game/Screens/Select/FilterControl.cs +++ b/osu.Game/Screens/Select/FilterControl.cs @@ -5,6 +5,7 @@ using System; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; +using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; @@ -15,14 +16,13 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Screens.Select.Filter; using Container = osu.Framework.Graphics.Containers.Container; using osu.Framework.Input; +using osu.Game.Modes; namespace osu.Game.Screens.Select { public class FilterControl : Container { - public Action FilterChanged; - - public string Search => searchTextBox.Text; + public Action FilterChanged; private OsuTabControl sortTabs; @@ -30,16 +30,16 @@ namespace osu.Game.Screens.Select private SortMode sort = SortMode.Title; public SortMode Sort - { - get { return sort; } + { + get { return sort; } set { if (sort != value) { sort = value; - FilterChanged?.Invoke(); + FilterChanged?.Invoke(Criteria); } - } + } } private GroupMode group = GroupMode.All; @@ -51,11 +51,19 @@ namespace osu.Game.Screens.Select if (group != value) { group = value; - FilterChanged?.Invoke(); + FilterChanged?.Invoke(Criteria); } } } + public FilterCriteria Criteria => new FilterCriteria + { + Group = group, + Sort = sort, + SearchText = searchTextBox.Text, + Mode = playMode + }; + public Action Exit; private SearchTextBox searchTextBox; @@ -88,7 +96,7 @@ namespace osu.Game.Screens.Select OnChange = (sender, newText) => { if (newText) - FilterChanged?.Invoke(); + FilterChanged?.Invoke(Criteria); }, Exit = () => Exit?.Invoke(), }, @@ -152,16 +160,21 @@ namespace osu.Game.Screens.Select searchTextBox.HoldFocus = false; searchTextBox.TriggerFocusLost(); } - + public void Activate() { searchTextBox.HoldFocus = true; } + private readonly Bindable playMode = new Bindable(); + [BackgroundDependencyLoader] - private void load(OsuColour colours) + private void load(OsuColour colours, OsuGame osu) { sortTabs.AccentColour = colours.GreenLight; + + if (osu != null) + playMode.BindTo(osu.PlayMode); } protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true; diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs new file mode 100644 index 0000000000..f5afafa709 --- /dev/null +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Game.Beatmaps.Drawables; +using osu.Game.Modes; +using osu.Game.Screens.Select.Filter; + +namespace osu.Game.Screens.Select +{ + public class FilterCriteria + { + public GroupMode Group; + public SortMode Sort; + public string SearchText; + public PlayMode Mode; + + public void Filter(List groups) + { + foreach (var g in groups) + { + var set = g.BeatmapSet; + + bool hasCurrentMode = set.Beatmaps.Any(bm => bm.Mode == Mode); + + bool match = hasCurrentMode; + + match &= string.IsNullOrEmpty(SearchText) + || (set.Metadata.Artist ?? string.Empty).IndexOf(SearchText, StringComparison.InvariantCultureIgnoreCase) != -1 + || (set.Metadata.ArtistUnicode ?? string.Empty).IndexOf(SearchText, StringComparison.InvariantCultureIgnoreCase) != -1 + || (set.Metadata.Title ?? string.Empty).IndexOf(SearchText, StringComparison.InvariantCultureIgnoreCase) != -1 + || (set.Metadata.TitleUnicode ?? string.Empty).IndexOf(SearchText, StringComparison.InvariantCultureIgnoreCase) != -1; + + switch (g.State) + { + case BeatmapGroupState.Hidden: + if (match) g.State = BeatmapGroupState.Collapsed; + break; + default: + if (!match) g.State = BeatmapGroupState.Hidden; + break; + } + } + + switch (Sort) + { + default: + case SortMode.Artist: + groups.Sort((x, y) => string.Compare(x.BeatmapSet.Metadata.Artist, y.BeatmapSet.Metadata.Artist, StringComparison.InvariantCultureIgnoreCase)); + break; + case SortMode.Title: + groups.Sort((x, y) => string.Compare(x.BeatmapSet.Metadata.Title, y.BeatmapSet.Metadata.Title, StringComparison.InvariantCultureIgnoreCase)); + break; + case SortMode.Author: + groups.Sort((x, y) => string.Compare(x.BeatmapSet.Metadata.Author, y.BeatmapSet.Metadata.Author, StringComparison.InvariantCultureIgnoreCase)); + break; + case SortMode.Difficulty: + groups.Sort((x, y) => x.BeatmapSet.MaxStarDifficulty.CompareTo(y.BeatmapSet.MaxStarDifficulty)); + break; + } + } + } +} \ No newline at end of file diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index 58a633b682..60017bfbd8 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -17,7 +17,6 @@ using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Transforms; using osu.Framework.Input; using osu.Framework.Screens; -using osu.Framework.Threading; using osu.Game.Beatmaps; using osu.Game.Beatmaps.Drawables; using osu.Game.Database; @@ -95,7 +94,7 @@ namespace osu.Game.Screens.Select { RelativeSizeAxes = Axes.X, Height = filter_height, - FilterChanged = () => filterChanged(), + FilterChanged = criteria => filterChanged(criteria), Exit = Exit, }); Add(beatmapInfoWedge = new BeatmapInfoWedge @@ -181,61 +180,9 @@ namespace osu.Game.Screens.Select protected abstract void OnSelected(); - private ScheduledDelegate filterTask; - - private void filterChanged(bool debounce = true, bool eagerSelection = true) + private void filterChanged(FilterCriteria criteria, bool debounce = true) { - if (!carousel.IsLoaded) return; - - if (Beatmap == null) return; - - filterTask?.Cancel(); - filterTask = Scheduler.AddDelayed(() => - { - filterTask = null; - var search = FilterControl.Search; - BeatmapGroup newSelection = null; - - carousel.Sort(FilterControl.Sort); - foreach (var beatmapGroup in carousel) - { - var set = beatmapGroup.BeatmapSet; - - bool hasCurrentMode = set.Beatmaps.Any(bm => bm.Mode == playMode); - - bool match = hasCurrentMode; - - match &= string.IsNullOrEmpty(search) - || (set.Metadata.Artist ?? "").IndexOf(search, StringComparison.InvariantCultureIgnoreCase) != -1 - || (set.Metadata.ArtistUnicode ?? "").IndexOf(search, StringComparison.InvariantCultureIgnoreCase) != -1 - || (set.Metadata.Title ?? "").IndexOf(search, StringComparison.InvariantCultureIgnoreCase) != -1 - || (set.Metadata.TitleUnicode ?? "").IndexOf(search, StringComparison.InvariantCultureIgnoreCase) != -1; - - if (match) - { - if (newSelection == null || beatmapGroup.BeatmapSet.OnlineBeatmapSetID == Beatmap.BeatmapSetInfo.OnlineBeatmapSetID) - { - if (newSelection != null) - newSelection.State = BeatmapGroupState.Collapsed; - newSelection = beatmapGroup; - } - else - beatmapGroup.State = BeatmapGroupState.Collapsed; - } - else - { - beatmapGroup.State = BeatmapGroupState.Hidden; - } - } - - if (newSelection != null) - { - if (newSelection.BeatmapPanels.Any(b => b.Beatmap.ID == Beatmap.BeatmapInfo.ID)) - carousel.SelectBeatmap(Beatmap.BeatmapInfo, false); - else if (eagerSelection) - carousel.SelectBeatmap(newSelection.BeatmapSet.Beatmaps[0], false); - } - }, debounce ? 250 : 0); + carousel.Filter(criteria, debounce); } private void onBeatmapSetAdded(BeatmapSetInfo s) => carousel.AddBeatmap(s); @@ -299,10 +246,7 @@ namespace osu.Game.Screens.Select initialAddSetsTask.Cancel(); } - private void playMode_ValueChanged(object sender, EventArgs e) - { - filterChanged(false); - } + private void playMode_ValueChanged(object sender, EventArgs e) => carousel.Filter(); private void changeBackground(WorkingBeatmap beatmap) { diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 1864260e2c..2f6aa2734e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -197,6 +197,7 @@ +