Implement filtering with strings

This commit is contained in:
Drew DeVault 2017-01-17 19:18:15 -05:00
parent 75de03bd88
commit 678f0aaa16
4 changed files with 113 additions and 38 deletions

View File

@ -29,7 +29,9 @@ namespace osu.Game.Beatmaps.Drawables
private BeatmapGroupState state; private BeatmapGroupState state;
public List<BeatmapPanel> BeatmapPanels; public List<BeatmapPanel> BeatmapPanels;
public BeatmapSetInfo BeatmapSet;
public BeatmapGroupState State public BeatmapGroupState State
{ {
@ -73,7 +75,9 @@ namespace osu.Game.Beatmaps.Drawables
GainedSelection = panelGainedSelection, GainedSelection = panelGainedSelection,
StartRequested = p => { StartRequested?.Invoke(p.Beatmap); }, StartRequested = p => { StartRequested?.Invoke(p.Beatmap); },
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
}).ToList(); }).ToList();
BeatmapSet = set;
} }
private void headerGainedSelection(BeatmapSetHeader panel) private void headerGainedSelection(BeatmapSetHeader panel)

View File

@ -16,10 +16,11 @@ using osu.Game.Beatmaps.Drawables;
using osu.Framework.Timing; using osu.Framework.Timing;
using osu.Framework.Input; using osu.Framework.Input;
using OpenTK.Input; using OpenTK.Input;
using System.Collections;
namespace osu.Game.Screens.Select namespace osu.Game.Screens.Select
{ {
class CarouselContainer : ScrollContainer class CarouselContainer : ScrollContainer, IEnumerable<BeatmapGroup>
{ {
private Container<Panel> scrollableContent; private Container<Panel> scrollableContent;
private List<BeatmapGroup> groups = new List<BeatmapGroup>(); private List<BeatmapGroup> groups = new List<BeatmapGroup>();
@ -27,29 +28,29 @@ namespace osu.Game.Screens.Select
public BeatmapGroup SelectedGroup { get; private set; } public BeatmapGroup SelectedGroup { get; private set; }
public BeatmapPanel SelectedPanel { get; private set; } public BeatmapPanel SelectedPanel { get; private set; }
private List<float> yPositions = new List<float>(); private List<float> yPositions = new List<float>();
private CarouselLifetimeList<Panel> Lifetime; private CarouselLifetimeList<Panel> Lifetime;
public CarouselContainer() public CarouselContainer()
{ {
DistanceDecayJump = 0.01; DistanceDecayJump = 0.01;
Add(scrollableContent = new Container<Panel>(Lifetime = new CarouselLifetimeList<Panel>(DepthComparer)) Add(scrollableContent = new Container<Panel>(Lifetime = new CarouselLifetimeList<Panel>(DepthComparer))
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
}); });
} }
internal class CarouselLifetimeList<T> : LifetimeList<Panel> internal class CarouselLifetimeList<T> : LifetimeList<Panel>
{ {
public CarouselLifetimeList(IComparer<Panel> comparer) public CarouselLifetimeList(IComparer<Panel> comparer)
: base(comparer) : base(comparer)
{ {
} }
public int StartIndex; public int StartIndex;
public int EndIndex; public int EndIndex;
public override bool Update(FrameTimeInfo time) public override bool Update(FrameTimeInfo time)
{ {
bool anyAliveChanged = false; bool anyAliveChanged = false;
@ -75,9 +76,9 @@ namespace osu.Game.Screens.Select
} }
return anyAliveChanged; return anyAliveChanged;
} }
} }
public void AddGroup(BeatmapGroup group) public void AddGroup(BeatmapGroup group)
{ {
group.State = BeatmapGroupState.Collapsed; group.State = BeatmapGroupState.Collapsed;
@ -100,7 +101,7 @@ namespace osu.Game.Screens.Select
yPositions.Add(currentY); yPositions.Add(currentY);
panel.MoveToY(currentY, 750, EasingTypes.OutExpo); panel.MoveToY(currentY, 750, EasingTypes.OutExpo);
if (advance) if (advance && panel.IsVisible)
currentY += panel.DrawHeight + 5; currentY += panel.DrawHeight + 5;
} }
@ -200,7 +201,9 @@ namespace osu.Game.Screens.Select
/// <param name="halfHeight">Half the draw height of the carousel container.</param> /// <param name="halfHeight">Half the draw height of the carousel container.</param>
private void updatePanel(Panel p, float halfHeight) private void updatePanel(Panel p, float halfHeight)
{ {
float panelDrawY = p.Position.Y - Current + p.DrawHeight / 2; var height = p.IsVisible ? p.DrawHeight : 0;
float panelDrawY = p.Position.Y - Current + height / 2;
float dist = Math.Abs(1f - panelDrawY / halfHeight); float dist = Math.Abs(1f - panelDrawY / halfHeight);
// Setting the origin position serves as an additive position on top of potential // Setting the origin position serves as an additive position on top of potential
@ -222,11 +225,11 @@ namespace osu.Game.Screens.Select
float drawHeight = DrawHeight; float drawHeight = DrawHeight;
float halfHeight = drawHeight / 2; float halfHeight = drawHeight / 2;
foreach (Panel p in Lifetime.AliveItems) foreach (Panel p in Lifetime.AliveItems)
{ {
float panelPosY = p.Position.Y; float panelPosY = p.Position.Y;
p.IsOnScreen = panelPosY >= Current - p.DrawHeight && panelPosY <= Current + drawHeight; p.IsOnScreen = panelPosY >= Current - p.DrawHeight && panelPosY <= Current + drawHeight;
updatePanel(p, halfHeight); updatePanel(p, halfHeight);
} }
// Determine range of indices for items that are now definitely on screen to be added // Determine range of indices for items that are now definitely on screen to be added
@ -247,6 +250,13 @@ namespace osu.Game.Screens.Select
} }
} }
public void InvalidateVisible()
{
Lifetime.StartIndex = 0;
Lifetime.EndIndex = groups.Count - 1;
computeYPositions();
}
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
{ {
int direction = 0; int direction = 0;
@ -288,5 +298,15 @@ namespace osu.Game.Screens.Select
return base.OnKeyDown(state, args); return base.OnKeyDown(state, args);
} }
public IEnumerator<BeatmapGroup> GetEnumerator()
{
return groups.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
} }
} }

View File

@ -49,6 +49,8 @@ namespace osu.Game.Screens.Select
public string Search { get; private set; } = string.Empty; public string Search { get; private set; } = string.Empty;
public SortMode Sort { get; private set; } = SortMode.Title; public SortMode Sort { get; private set; } = SortMode.Title;
private SearchTextBox searchTextBox;
public FilterControl() public FilterControl()
{ {
AutoSizeAxes = Axes.Y; AutoSizeAxes = Axes.Y;
@ -72,11 +74,17 @@ namespace osu.Game.Screens.Select
Direction = FlowDirection.VerticalOnly, Direction = FlowDirection.VerticalOnly,
Children = new Drawable[] Children = new Drawable[]
{ {
new SearchTextBox { RelativeSizeAxes = Axes.X }, searchTextBox = new SearchTextBox { RelativeSizeAxes = Axes.X },
new GroupSortTabs() new GroupSortTabs()
} }
} }
}; };
searchTextBox.OnChange += (sender, text) =>
{
Search = searchTextBox.Text;
FilterChanged?.Invoke();
};
} }
private class TabItem : ClickableContainer private class TabItem : ClickableContainer

View File

@ -31,6 +31,7 @@ using osu.Game.Graphics.Containers;
using osu.Framework.Input; using osu.Framework.Input;
using OpenTK.Input; using OpenTK.Input;
using osu.Game.Graphics; using osu.Game.Graphics;
using System.Collections.Generic;
namespace osu.Game.Screens.Select namespace osu.Game.Screens.Select
{ {
@ -52,6 +53,8 @@ namespace osu.Game.Screens.Select
private AudioSample sampleChangeDifficulty; private AudioSample sampleChangeDifficulty;
private AudioSample sampleChangeBeatmap; private AudioSample sampleChangeBeatmap;
private List<BeatmapGroup> beatmapGroups;
class WedgeBackground : Container class WedgeBackground : Container
{ {
@ -82,6 +85,7 @@ namespace osu.Game.Screens.Select
} }
Player player; Player player;
FilterControl filter;
private void start() private void start()
{ {
@ -112,6 +116,7 @@ namespace osu.Game.Screens.Select
{ {
const float carouselWidth = 640; const float carouselWidth = 640;
const float bottomToolHeight = 50; const float bottomToolHeight = 50;
beatmapGroups = new List<BeatmapGroup>();
Children = new Drawable[] Children = new Drawable[]
{ {
new ParallaxContainer new ParallaxContainer
@ -134,10 +139,11 @@ namespace osu.Game.Screens.Select
Anchor = Anchor.CentreRight, Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight, Origin = Anchor.CentreRight,
}, },
new FilterControl filter = new FilterControl
{ {
Position = wedged_container_start_position, Position = wedged_container_start_position,
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
FilterChanged = filterChanged,
}, },
beatmapInfoWedge = new BeatmapInfoWedge beatmapInfoWedge = new BeatmapInfoWedge
{ {
@ -203,6 +209,41 @@ namespace osu.Game.Screens.Select
Task.Factory.StartNew(() => addBeatmapSets(game, initialAddSetsTask.Token), initialAddSetsTask.Token); Task.Factory.StartNew(() => addBeatmapSets(game, initialAddSetsTask.Token), initialAddSetsTask.Token);
} }
private void filterChanged()
{
var search = filter.Search;
BeatmapGroup newSelection = null;
bool changed = false;
foreach (var beatmapGroup in carousel)
{
var set = beatmapGroup.BeatmapSet;
if (set == null)
continue;
bool 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)
{
changed = changed && beatmapGroup.Header.Alpha == 1;
beatmapGroup.Header.Alpha = 1;
if (newSelection == null || beatmapGroup.BeatmapSet.OnlineBeatmapSetID == Beatmap.BeatmapSetInfo.OnlineBeatmapSetID)
newSelection = beatmapGroup;
}
else
{
changed = changed && beatmapGroup.Header.Alpha == 0;
beatmapGroup.Header.Alpha = 0;
beatmapGroup.State = BeatmapGroupState.Collapsed;
}
}
if (newSelection != null)
selectBeatmap(newSelection.BeatmapSet.Beatmaps[0]);
if (changed)
carousel.InvalidateVisible();
}
private void onDatabaseOnBeatmapSetAdded(BeatmapSetInfo s) private void onDatabaseOnBeatmapSetAdded(BeatmapSetInfo s)
{ {
Schedule(() => addBeatmapSet(s, Game, true)); Schedule(() => addBeatmapSet(s, Game, true));
@ -347,7 +388,7 @@ namespace osu.Game.Screens.Select
var beatmap = new WorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault(), beatmapSet, database); var beatmap = new WorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault(), beatmapSet, database);
var group = new BeatmapGroup(beatmap) var group = new BeatmapGroup(beatmap, beatmapSet)
{ {
SelectionChanged = selectionChanged, SelectionChanged = selectionChanged,
StartRequested = b => start() StartRequested = b => start()
@ -357,6 +398,8 @@ namespace osu.Game.Screens.Select
//this likely won't scale so well, but allows us to completely async the loading flow. //this likely won't scale so well, but allows us to completely async the loading flow.
Task.WhenAll(group.BeatmapPanels.Select(panel => panel.Preload(game))).ContinueWith(task => Schedule(delegate Task.WhenAll(group.BeatmapPanels.Select(panel => panel.Preload(game))).ContinueWith(task => Schedule(delegate
{ {
beatmapGroups.Add(group);
carousel.AddGroup(group); carousel.AddGroup(group);
if (Beatmap == null || select) if (Beatmap == null || select)