diff --git a/osu.Game/Screens/Select/FilterSongSelect.cs b/osu.Game/Screens/Select/FilterSongSelect.cs
new file mode 100644
index 0000000000..a2d2c75d27
--- /dev/null
+++ b/osu.Game/Screens/Select/FilterSongSelect.cs
@@ -0,0 +1,218 @@
+using System;
+using OpenTK;
+using OpenTK.Graphics;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Primitives;
+using osu.Framework.Graphics.Sprites;
+using osu.Framework.Graphics.UserInterface;
+using osu.Game.Graphics;
+
+namespace osu.Game.Screens.Select
+{
+ public class FilterSongSelect : Container
+ {
+ public enum SortMode
+ {
+ Arist,
+ BPM,
+ Creator,
+ DateAdded,
+ Difficulty,
+ Length,
+ RankAchieved,
+ Title
+ }
+
+ public enum GroupMode
+ {
+ NoGrouping,
+ Arist,
+ BPM,
+ Creator,
+ DateAdded,
+ Difficulty,
+ Length,
+ RankAchieved,
+ Title,
+ Collections,
+ Favorites,
+ MyMaps,
+ RankedStatus,
+ RecentlyPlayed
+ }
+
+ public Action FilterChanged;
+
+ public string Search { get; private set; } = string.Empty;
+ public SortMode Sort { get; private set; } = SortMode.Title;
+
+ public FilterSongSelect()
+ {
+ AutoSizeAxes = Axes.Y;
+
+ Children = new Drawable[]
+ {
+ new Box
+ {
+ Colour = Color4.Black,
+ Alpha = 0.6f,
+ RelativeSizeAxes = Axes.Both,
+ },
+ new FlowContainer
+ {
+ Padding = new MarginPadding(20),
+ AutoSizeAxes = Axes.Y,
+ RelativeSizeAxes = Axes.X,
+ Anchor = Anchor.TopRight,
+ Origin = Anchor.TopRight,
+ Width = 0.4f, // TODO: InnerWidth property or something
+ Direction = FlowDirection.VerticalOnly,
+ Children = new Drawable[]
+ {
+ new SearchTextBox { RelativeSizeAxes = Axes.X },
+ new GroupSortTabs()
+ }
+ }
+ };
+ }
+
+ private class GroupSortItem : ClickableContainer
+ {
+ public string Text
+ {
+ get { return text.Text; }
+ set { text.Text = value; }
+ }
+
+ public bool Active
+ {
+ get { return box.Alpha != 0; }
+ set
+ {
+ if (value)
+ {
+ box.FadeIn(300);
+ text.FadeColour(Color4.White, 300);
+ }
+ else
+ {
+ box.FadeOut(300);
+ text.FadeColour(new Color4(102, 204, 255, 255), 300);
+ }
+ }
+ }
+
+ private SpriteText text;
+ private Box box;
+
+ public GroupSortItem()
+ {
+ AutoSizeAxes = Axes.Both;
+ Children = new Drawable[]
+ {
+ text = new SpriteText
+ {
+ Colour = new Color4(102, 204, 255, 255),
+ Margin = new MarginPadding(5),
+ TextSize = 14,
+ },
+ box = new Box
+ {
+ RelativeSizeAxes = Axes.X,
+ Height = 1,
+ Alpha = 0,
+ Colour = Color4.White,
+ Origin = Anchor.BottomLeft,
+ Anchor = Anchor.BottomLeft,
+ }
+ };
+ }
+ }
+
+ private class GroupSortTabs : Container
+ {
+ public GroupSortTabs()
+ {
+ RelativeSizeAxes = Axes.X;
+ AutoSizeAxes = Axes.Y;
+ Children = new Drawable[]
+ {
+ new Box
+ {
+ RelativeSizeAxes = Axes.X,
+ Height = 1,
+ Colour = new Color4(80, 80, 80, 255),
+ Origin = Anchor.BottomLeft,
+ Anchor = Anchor.BottomLeft,
+ },
+ new FlowContainer
+ {
+ AutoSizeAxes = Axes.Both,
+ Direction = FlowDirection.HorizontalOnly,
+ Spacing = new Vector2(10, 0),
+ Children = new Drawable[]
+ {
+ new GroupSortItem
+ {
+ Text = "All",
+ Active = true,
+ },
+ new GroupSortItem
+ {
+ Text = "Recently Played",
+ Active = false,
+ },
+ new GroupSortItem
+ {
+ Text = "Collections",
+ Active = false,
+ },
+ new TextAwesome
+ {
+ Icon = FontAwesome.fa_ellipsis_h,
+ Colour = new Color4(102, 204, 255, 255),
+ TextSize = 14,
+ Margin = new MarginPadding { Top = 5, Bottom = 5 },
+ Origin = Anchor.BottomLeft,
+ Anchor = Anchor.BottomLeft,
+ }
+ }
+ },
+ new FlowContainer
+ {
+ AutoSizeAxes = Axes.Both,
+ Direction = FlowDirection.HorizontalOnly,
+ Spacing = new Vector2(10, 0),
+ Origin = Anchor.TopRight,
+ Anchor = Anchor.TopRight,
+ Children = new Drawable[]
+ {
+ new SpriteText
+ {
+ Text = "Sort results by",
+ Colour = new Color4(165, 204, 0, 255),
+ TextSize = 14,
+ Margin = new MarginPadding { Top = 5, Bottom = 5 },
+ },
+ new GroupSortItem
+ {
+ Text = "Artist",
+ Active = true,
+ },
+ new TextAwesome
+ {
+ Icon = FontAwesome.fa_ellipsis_h,
+ Colour = new Color4(165, 204, 0, 255),
+ TextSize = 14,
+ Margin = new MarginPadding { Top = 5, Bottom = 5 },
+ Origin = Anchor.BottomLeft,
+ Anchor = Anchor.BottomLeft,
+ }
+ }
+ },
+ };
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs
index e0860fda4c..ca559f1931 100644
--- a/osu.Game/Screens/Select/PlaySongSelect.cs
+++ b/osu.Game/Screens/Select/PlaySongSelect.cs
@@ -127,6 +127,11 @@ namespace osu.Game.Screens.Select
},
}
},
+ new FilterSongSelect
+ {
+ Position = wedged_container_start_position,
+ RelativeSizeAxes = Axes.X,
+ },
carousel = new CarouselContainer
{
RelativeSizeAxes = Axes.Y,
diff --git a/osu.Game/Screens/Select/SearchTextBox.cs b/osu.Game/Screens/Select/SearchTextBox.cs
new file mode 100644
index 0000000000..ae8d9e3fde
--- /dev/null
+++ b/osu.Game/Screens/Select/SearchTextBox.cs
@@ -0,0 +1,67 @@
+using System;
+using OpenTK;
+using OpenTK.Graphics;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Primitives;
+using osu.Framework.Graphics.Sprites;
+using osu.Framework.Graphics.UserInterface;
+using osu.Game.Graphics;
+
+namespace osu.Game.Screens.Select
+{
+ public class SearchTextBox : TextBox
+ {
+ protected override Color4 BackgroundUnfocused => new Color4(10, 10, 10, 255);
+ protected override Color4 BackgroundFocused => new Color4(10, 10, 10, 255);
+ public override bool HasFocus => true;
+
+ private SpriteText placeholder;
+
+ protected override string InternalText
+ {
+ get { return base.InternalText; }
+ set
+ {
+ base.InternalText = value;
+ if (placeholder != null)
+ {
+ if (string.IsNullOrEmpty(value))
+ placeholder.Text = "type to search";
+ else
+ placeholder.Text = string.Empty;
+ }
+ }
+ }
+
+ public SearchTextBox()
+ {
+ Height = 35;
+ TextContainer.Padding = new MarginPadding(5);
+ Add(new Drawable[]
+ {
+ placeholder = new SpriteText
+ {
+ Font = @"Exo2.0-MediumItalic",
+ Text = "type to search",
+ Colour = new Color4(180, 180, 180, 255),
+ Anchor = Anchor.CentreLeft,
+ Origin = Anchor.CentreLeft,
+ Margin = new MarginPadding { Left = 10 },
+ },
+ new TextAwesome
+ {
+ Icon = FontAwesome.fa_search,
+ Origin = Anchor.CentreRight,
+ Anchor = Anchor.CentreRight,
+ Margin = new MarginPadding { Right = 10 },
+ }
+ });
+ }
+
+ protected override void LoadComplete()
+ {
+ base.LoadComplete();
+ OnFocus(null);
+ }
+ }
+}
\ No newline at end of file
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index a4da659718..2320f16f68 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -232,6 +232,8 @@
+
+