mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 15:47:26 +08:00
Move filtering to BeatmapCarousel (but actual logic is now in FilterCriteria.
This commit is contained in:
parent
4b97304603
commit
907236e475
@ -10,7 +10,7 @@ using osu.Game.Database;
|
||||
|
||||
namespace osu.Game.Beatmaps.Drawables
|
||||
{
|
||||
internal class BeatmapGroup : IStateful<BeatmapGroupState>
|
||||
public class BeatmapGroup : IStateful<BeatmapGroupState>
|
||||
{
|
||||
public BeatmapPanel SelectedPanel;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -17,7 +17,7 @@ using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Beatmaps.Drawables
|
||||
{
|
||||
internal class BeatmapSetHeader : Panel
|
||||
public class BeatmapSetHeader : Panel
|
||||
{
|
||||
public Action<BeatmapSetHeader> GainedSelection;
|
||||
private SpriteText title, artist;
|
||||
|
@ -12,7 +12,7 @@ using osu.Framework.Extensions.Color4Extensions;
|
||||
|
||||
namespace osu.Game.Beatmaps.Drawables
|
||||
{
|
||||
internal class Panel : Container, IStateful<PanelSelectedState>
|
||||
public class Panel : Container, IStateful<PanelSelectedState>
|
||||
{
|
||||
public const float MAX_HEIGHT = 80;
|
||||
|
||||
@ -117,7 +117,7 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
}
|
||||
}
|
||||
|
||||
internal enum PanelSelectedState
|
||||
public enum PanelSelectedState
|
||||
{
|
||||
Hidden,
|
||||
NotSelected,
|
||||
|
@ -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<BeatmapGroup> newGroups = null;
|
||||
List<BeatmapGroup> 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<BeatmapGroup> sortedGroups = new List<BeatmapGroup>(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<BeatmapGroup>(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<BeatmapGroup> GetEnumerator() => groups.GetEnumerator();
|
||||
|
@ -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<FilterCriteria> FilterChanged;
|
||||
|
||||
private OsuTabControl<SortMode> 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> playMode = new Bindable<PlayMode>();
|
||||
|
||||
[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;
|
||||
|
62
osu.Game/Screens/Select/FilterCriteria.cs
Normal file
62
osu.Game/Screens/Select/FilterCriteria.cs
Normal file
@ -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<BeatmapGroup> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
@ -197,6 +197,7 @@
|
||||
<Compile Include="Screens\Play\SkipButton.cs" />
|
||||
<Compile Include="Modes\UI\StandardComboCounter.cs" />
|
||||
<Compile Include="Screens\Select\BeatmapCarousel.cs" />
|
||||
<Compile Include="Screens\Select\FilterCriteria.cs" />
|
||||
<Compile Include="Screens\Select\Filter\GroupMode.cs" />
|
||||
<Compile Include="Screens\Select\Filter\SortMode.cs" />
|
||||
<Compile Include="Screens\Select\MatchSongSelect.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user