From 3aa1f35127d18b005bc222a9ebef222ba2bb3e42 Mon Sep 17 00:00:00 2001
From: DrabWeb <sethunity@gmail.com>
Date: Tue, 30 May 2017 05:12:11 -0300
Subject: [PATCH 01/20] Basic layout

---
 .../Tests/TestCaseDrawableRoom.cs             |  18 +-
 .../Tests/TestCaseRoomInspector.cs            | 101 ++++
 .../osu.Desktop.VisualTests.csproj            |   1 +
 osu.Game/Online/Multiplayer/Room.cs           |   4 +-
 .../Overlays/Toolbar/ToolbarModeButton.cs     |   2 +-
 osu.Game/Screens/Multiplayer/DrawableRoom.cs  |   6 +-
 osu.Game/Screens/Multiplayer/RoomInspector.cs | 502 ++++++++++++++++++
 osu.Game/Users/User.cs                        |   4 +
 osu.Game/osu.Game.csproj                      |   1 +
 9 files changed, 632 insertions(+), 7 deletions(-)
 create mode 100644 osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
 create mode 100644 osu.Game/Screens/Multiplayer/RoomInspector.cs

diff --git a/osu.Desktop.VisualTests/Tests/TestCaseDrawableRoom.cs b/osu.Desktop.VisualTests/Tests/TestCaseDrawableRoom.cs
index de58323abe..32af330f44 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseDrawableRoom.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseDrawableRoom.cs
@@ -38,12 +38,26 @@ namespace osu.Desktop.VisualTests.Tests
             first.Room.Name.Value = @"Great Room Right Here";
             first.Room.Host.Value = new User { Username = @"Naeferith", Id = 9492835, Country = new Country { FlagName = @"FR" }};
             first.Room.Status.Value = new RoomStatusOpen();
-            first.Room.Beatmap.Value = new BeatmapMetadata { Title = @"Seiryu", Artist = @"Critical Crystal" };
+            first.Room.Beatmap.Value = new BeatmapInfo
+            {
+                Metadata = new BeatmapMetadata
+                {
+                    Title = @"Seiryu",
+                    Artist = @"Critical Crystal",
+                },
+            };
 
             second.Room.Name.Value = @"Relax It's The Weekend";
             second.Room.Host.Value = new User { Username = @"peppy", Id = 2, Country = new Country { FlagName = @"AU" }};
             second.Room.Status.Value = new RoomStatusPlaying();
-            second.Room.Beatmap.Value = new BeatmapMetadata { Title = @"ZAQ", Artist = @"Serendipity" };
+            second.Room.Beatmap.Value = new BeatmapInfo
+            {
+                Metadata = new BeatmapMetadata
+                {
+                    Title = @"Serendipity",
+                    Artist = @"ZAQ",
+                },
+            };
 
             AddStep(@"change state", () =>
             {
diff --git a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
new file mode 100644
index 0000000000..8ec1f66f8b
--- /dev/null
+++ b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
@@ -0,0 +1,101 @@
+// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using osu.Framework.Testing;
+using osu.Framework.Graphics;
+using osu.Game.Screens.Multiplayer;
+using osu.Game.Database;
+using osu.Game.Online.Multiplayer;
+using osu.Game.Users;
+using osu.Framework.Allocation;
+
+namespace osu.Desktop.VisualTests.Tests
+{
+    internal class TestCaseRoomInspector : TestCase
+    {
+        public override string Description => @"from the multiplayer lobby";
+
+        private RulesetDatabase rulesets;
+
+        public override void Reset()
+        {
+            base.Reset();
+
+            var room = new Room();
+            room.Name.Value = @"My Awesome Room";
+            room.Host.Value = new User { Username = @"flyte", Id = 3103765, Country = new Country { FlagName = @"JP" }};
+            room.Status.Value = new RoomStatusOpen();
+            room.Beatmap.Value = new BeatmapInfo
+            {
+                StarDifficulty = 3.7,
+                Ruleset = rulesets.GetRuleset(3),
+                Metadata = new BeatmapMetadata
+                {
+                    Title = @"Platina",
+                    Artist = @"Maaya Sakamoto",
+                    Author = @"uwutm8",
+                },
+            };
+            room.MaxParticipants.Value = 200;
+            room.Participants.Value = new[] { new User { Username = @"flyte", Id = 3103765, GlobalRank = 1425 },
+                                              new User { Username = @"Cookiezi", Id = 124493, GlobalRank = 5466 },
+                                              new User { Username = @"Angelsim", Id = 1777162, GlobalRank = 2873 },
+                                              new User { Username = @"Rafis", Id = 2558286, GlobalRank = 4687 },
+                                              new User { Username = @"hvick225", Id = 50265, GlobalRank = 3258 },
+                                              new User { Username = @"peppy", Id = 2, GlobalRank = 6251 }};
+
+            RoomInspector inspector;
+            Add(inspector = new RoomInspector
+            {
+                Anchor = Anchor.Centre,
+                Origin = Anchor.Centre,
+                Room = room,
+            });
+
+            AddStep(@"change title", () => room.Name.Value = @"A Better Room Than The Above");
+            AddStep(@"change host", () => room.Host.Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" }});
+            AddStep(@"change status", () => room.Status.Value = new RoomStatusPlaying());
+            AddStep(@"change beatmap", () => room.Beatmap.Value = null);
+            AddStep(@"change max participants", () => room.MaxParticipants.Value = null);
+            AddStep(@"change participants", () => room.Participants.Value = new[]
+            {
+                new User { Username = @"filsdelama", Id = 2831793, GlobalRank = 8542 },
+                new User { Username = @"_index", Id = 652457, GlobalRank = 15024 }
+            });
+
+            AddStep(@"change room", () =>
+            {
+                var newRoom = new Room();
+                newRoom.Name.Value = @"My New, Better Than Ever Room";
+                newRoom.Host.Value = new User { Username = @"Angelsim", Id = 1777162, Country = new Country { FlagName = @"KR" }};
+                newRoom.Status.Value = new RoomStatusOpen();
+                newRoom.Beatmap.Value = new BeatmapInfo
+                {
+                    StarDifficulty = 7.07,
+                    Ruleset = rulesets.GetRuleset(0),
+                    Metadata = new BeatmapMetadata
+                    {
+                        Title = @"xi",
+                        Artist = @"FREEDOM DIVE",
+                        Author = @"Nakagawa-Kanon",
+                    },
+                };
+                newRoom.MaxParticipants.Value = 10;
+                newRoom.Participants.Value = new[]
+                {
+                    new User { Username = @"Angelsim", Id = 1777162, GlobalRank = 4 },
+                    new User { Username = @"HappyStick", Id = 256802, GlobalRank = 752 },
+                    new User { Username = @"-Konpaku-", Id = 2258797, GlobalRank = 571 }
+                };
+
+                inspector.Room = newRoom;
+            });
+        }
+
+        [BackgroundDependencyLoader]
+        private void load(RulesetDatabase rulesets)
+        {
+            this.rulesets = rulesets;
+        }
+    }
+}
diff --git a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj
index 5a532d7234..466c9336f0 100644
--- a/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj
+++ b/osu.Desktop.VisualTests/osu.Desktop.VisualTests.csproj
@@ -224,6 +224,7 @@
     <Compile Include="Tests\TestCaseUserPanel.cs" />
     <Compile Include="Tests\TestCaseDirect.cs" />
     <Compile Include="Tests\TestCaseBreadcrumbs.cs" />
+    <Compile Include="Tests\TestCaseRoomInspector.cs" />
   </ItemGroup>
   <ItemGroup />
   <ItemGroup />
diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs
index c82025f902..fe3378f4a6 100644
--- a/osu.Game/Online/Multiplayer/Room.cs
+++ b/osu.Game/Online/Multiplayer/Room.cs
@@ -12,6 +12,8 @@ namespace osu.Game.Online.Multiplayer
         public Bindable<string> Name = new Bindable<string>();
         public Bindable<User> Host = new Bindable<User>();
         public Bindable<RoomStatus> Status = new Bindable<RoomStatus>();
-        public Bindable<BeatmapMetadata> Beatmap = new Bindable<BeatmapMetadata>();
+        public Bindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>();
+        public Bindable<int?> MaxParticipants = new Bindable<int?>();
+        public Bindable<User[]> Participants = new Bindable<User[]>();
     }
 }
diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs b/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs
index dd70289f7d..5f0ab3991d 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarModeButton.cs
@@ -55,4 +55,4 @@ namespace osu.Game.Overlays.Toolbar
             DrawableIcon.TextSize *= 1.4f;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/osu.Game/Screens/Multiplayer/DrawableRoom.cs b/osu.Game/Screens/Multiplayer/DrawableRoom.cs
index 7365963085..bbe279946a 100644
--- a/osu.Game/Screens/Multiplayer/DrawableRoom.cs
+++ b/osu.Game/Screens/Multiplayer/DrawableRoom.cs
@@ -227,13 +227,13 @@ namespace osu.Game.Screens.Multiplayer
                 d.FadeColour(value.GetAppropriateColour(colours), 100);
         }
 
-        private void displayBeatmap(BeatmapMetadata value)
+        private void displayBeatmap(BeatmapInfo value)
         {
             if (value != null)
             {
-                beatmapTitle.Current = localisation.GetUnicodePreference(value.TitleUnicode, value.Title);
+                beatmapTitle.Current = localisation.GetUnicodePreference(value.Metadata.TitleUnicode, value.Metadata.Title);
                 beatmapDash.Text = @" - ";
-                beatmapArtist.Current = localisation.GetUnicodePreference(value.ArtistUnicode, value.Artist);
+                beatmapArtist.Current = localisation.GetUnicodePreference(value.Metadata.ArtistUnicode, value.Metadata.Artist);
             }
             else
             {
diff --git a/osu.Game/Screens/Multiplayer/RoomInspector.cs b/osu.Game/Screens/Multiplayer/RoomInspector.cs
new file mode 100644
index 0000000000..1471e2ed26
--- /dev/null
+++ b/osu.Game/Screens/Multiplayer/RoomInspector.cs
@@ -0,0 +1,502 @@
+// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System.Linq;
+using OpenTK;
+using OpenTK.Graphics;
+using osu.Framework.Allocation;
+using osu.Framework.Configuration;
+using osu.Framework.Extensions.Color4Extensions;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Colour;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Sprites;
+using osu.Framework.Graphics.Textures;
+using osu.Framework.Localisation;
+using osu.Game.Beatmaps.Drawables;
+using osu.Game.Database;
+using osu.Game.Graphics;
+using osu.Game.Graphics.Sprites;
+using osu.Game.Online.Multiplayer;
+using osu.Game.Users;
+
+namespace osu.Game.Screens.Multiplayer
+{
+    public class RoomInspector : Container
+    {
+        private readonly MarginPadding content_padding = new MarginPadding { Horizontal = 20, Vertical = 10 };
+
+        private readonly FillFlowContainer topFlow;
+        private readonly Box statusStrip;
+        private readonly OsuSpriteText participants, participantsSlash, maxParticipants, name, status, beatmapTitle, beatmapDash, beatmapArtist, beatmapAuthor, host, levelRangeLower, levelRangeHigher;
+        private readonly Sprite cover;
+        private readonly FillFlowContainer levelRangeContainer;
+        private readonly ScrollContainer participantsScroll;
+        private readonly FillFlowContainer participantsFlow;
+        private readonly Container rulesetContainer;
+        private readonly Container flagContainer;
+
+        private Bindable<string> nameBind = new Bindable<string>();
+        private Bindable<User> hostBind = new Bindable<User>();
+        private Bindable<RoomStatus> statusBind = new Bindable<RoomStatus>();
+        private Bindable<BeatmapInfo> beatmapBind = new Bindable<BeatmapInfo>();
+        private Bindable<int?> maxParticipantsBind = new Bindable<int?>();
+        private Bindable<User[]> participantsBind = new Bindable<User[]>();
+
+        private OsuColour colours;
+        private LocalisationEngine localisation;
+
+        private Room room;
+        public Room Room
+        {
+            get { return room; }
+            set
+            {
+                if (value == room) return;
+                room = value;
+
+                nameBind.BindTo(Room.Name);
+                hostBind.BindTo(Room.Host);
+                statusBind.BindTo(Room.Status);
+                beatmapBind.BindTo(Room.Beatmap);
+                maxParticipantsBind.BindTo(Room.MaxParticipants);
+                participantsBind.BindTo(Room.Participants);
+            }
+        }
+
+        public RoomInspector()
+        {
+            Width = 520;
+            RelativeSizeAxes = Axes.Y;
+
+            Children = new Drawable[]
+            {
+                new Box
+                {
+                    RelativeSizeAxes = Axes.Both,
+                    Colour = OsuColour.FromHex(@"343138"),
+                },
+                topFlow = new FillFlowContainer
+                {
+                    RelativeSizeAxes = Axes.X,
+                    AutoSizeAxes = Axes.Y,
+                    Direction = FillDirection.Vertical,
+                    Children = new Drawable[]
+                    {
+                        new Container
+                        {
+                            RelativeSizeAxes = Axes.X,
+                            Height = 200,
+                            Masking = true,
+                            Children = new Drawable[]
+                            {
+                                cover = new Sprite
+                                {
+                                    Anchor = Anchor.Centre,
+                                    Origin = Anchor.Centre,
+                                    FillMode = FillMode.Fill,
+                                },
+                                new Box
+                                {
+                                    RelativeSizeAxes = Axes.Both,
+                                    ColourInfo = ColourInfo.GradientVertical(Color4.Black.Opacity(0.5f), Color4.Black.Opacity(0)),
+                                },
+                                new Container
+                                {
+                                    RelativeSizeAxes = Axes.Both,
+                                    Padding = new MarginPadding(20),
+                                    Children = new Drawable[]
+                                    {
+                                        new FillFlowContainer
+                                        {
+                                            Anchor = Anchor.TopRight,
+                                            Origin = Anchor.TopRight,
+                                            AutoSizeAxes = Axes.Both,
+                                            Direction = FillDirection.Horizontal,
+                                            LayoutDuration = 100,
+                                            Children = new[]
+                                            {
+                                                participants = new OsuSpriteText
+                                                {
+                                                    TextSize = 30,
+                                                    Font = @"Exo2.0-Bold"
+                                                },
+                                                participantsSlash = new OsuSpriteText
+                                                {
+                                                    Text = @"/",
+                                                    TextSize = 30,
+                                                    Font = @"Exo2.0-Light"
+                                                },
+                                                maxParticipants = new OsuSpriteText
+                                                {
+                                                    TextSize = 30,
+                                                    Font = @"Exo2.0-Light"
+                                                },
+                                            },
+                                        },
+                                        name = new OsuSpriteText
+                                        {
+                                            Anchor = Anchor.BottomLeft,
+                                            Origin = Anchor.BottomLeft,
+                                            TextSize = 30,
+                                        },
+                                    },
+                                },
+                            },
+                        },
+                        statusStrip = new Box
+                        {
+                            RelativeSizeAxes = Axes.X,
+                            Height = 5,
+                        },
+                        new Container
+                        {
+                            RelativeSizeAxes = Axes.X,
+                            AutoSizeAxes = Axes.Y,
+                            Children = new Drawable[]
+                            {
+                                new Box
+                                {
+                                    RelativeSizeAxes = Axes.Both,
+                                    Colour = OsuColour.FromHex(@"28242d"),
+                                },
+                                new FillFlowContainer
+                                {
+                                    RelativeSizeAxes = Axes.X,
+                                    AutoSizeAxes = Axes.Y,
+                                    Direction = FillDirection.Vertical,
+                                    Padding = content_padding,
+                                    Spacing = new Vector2(0f, 5f),
+                                    Children = new Drawable[]
+                                    {
+                                        status = new OsuSpriteText
+                                        {
+                                            TextSize = 14,
+                                            Font = @"Exo2.0-Bold",
+                                        },
+                                        new FillFlowContainer
+                                        {
+                                            AutoSizeAxes = Axes.Both,
+                                            Direction = FillDirection.Horizontal,
+                                            LayoutDuration = 100,
+                                            Spacing = new Vector2(5f, 0f),
+                                            Children = new Drawable[]
+                                            {
+                                                rulesetContainer = new Container
+                                                {
+                                                    Size = new Vector2(30f),
+                                                },
+                                                new Container //todo: game type icon
+                                                {
+                                                    Size = new Vector2(30f),
+                                                    CornerRadius = 15f,
+                                                    Masking = true,
+                                                    Children = new[]
+                                                    {
+                                                        new Box
+                                                        {
+                                                            RelativeSizeAxes = Axes.Both,
+                                                            Colour = OsuColour.FromHex(@"545454"),
+                                                        },
+                                                    },
+                                                },
+                                                new Container
+                                                {
+                                                    AutoSizeAxes = Axes.X,
+                                                    Height = 30f,
+                                                    Margin = new MarginPadding { Left = 5 },
+                                                    Children = new[]
+                                                    {
+                                                        new FillFlowContainer
+                                                        {
+                                                            AutoSizeAxes = Axes.Both,
+                                                            Direction = FillDirection.Horizontal,
+                                                            Children = new[]
+                                                            {
+                                                                beatmapTitle = new OsuSpriteText
+                                                                {
+                                                                    Font = @"Exo2.0-BoldItalic",
+                                                                },
+                                                                beatmapDash = new OsuSpriteText
+                                                                {
+                                                                    Font = @"Exo2.0-BoldItalic",
+                                                                },
+                                                                beatmapArtist = new OsuSpriteText
+                                                                {
+                                                                    Font = @"Exo2.0-RegularItalic",
+                                                                },
+                                                            },
+                                                        },
+                                                        beatmapAuthor = new OsuSpriteText
+                                                        {
+                                                            Anchor = Anchor.BottomLeft,
+                                                            Origin = Anchor.BottomLeft,
+                                                            TextSize = 14,
+                                                        },
+                                                    },
+                                                },
+                                            },
+                                        },
+                                    },
+                                },
+                            },
+                        },
+                        new Container
+                        {
+                            RelativeSizeAxes = Axes.X,
+                            AutoSizeAxes = Axes.Y,
+                            Padding = content_padding,
+                            Children = new Drawable[]
+                            {
+                                new FillFlowContainer
+                                {
+                                    AutoSizeAxes = Axes.X,
+                                    Height = 15f,
+                                    Direction = FillDirection.Horizontal,
+                                    Spacing = new Vector2(5f, 0f),
+                                    Children = new Drawable[]
+                                    {
+                                        flagContainer = new Container
+                                        {
+                                            Width = 22f,
+                                            RelativeSizeAxes = Axes.Y,
+                                        },
+                                        new Container
+                                        {
+                                            Width = 38f,
+                                            RelativeSizeAxes = Axes.Y,
+                                            CornerRadius = 2f,
+                                            Masking = true,
+                                            Children = new[]
+                                            {
+                                                new Box
+                                                {
+                                                    RelativeSizeAxes = Axes.Both,
+                                                    Colour = OsuColour.FromHex(@"ad387e"),
+                                                },
+                                            },
+                                        },
+                                        new OsuSpriteText
+                                        {
+                                            Text = "hosted by",
+                                            Anchor = Anchor.CentreLeft,
+                                            Origin = Anchor.CentreLeft,
+                                            TextSize = 14,
+                                        },
+                                        host = new OsuSpriteText
+                                        {
+                                            Anchor = Anchor.CentreLeft,
+                                            Origin = Anchor.CentreLeft,
+                                            TextSize = 14,
+                                            Font = @"Exo2.0-BoldItalic",
+                                        },
+                                    },
+                                },
+                                levelRangeContainer = new FillFlowContainer
+                                {
+                                    Anchor = Anchor.CentreRight,
+                                    Origin = Anchor.CentreRight,
+                                    AutoSizeAxes = Axes.Both,
+                                    Direction = FillDirection.Horizontal,
+                                    Children = new[]
+                                    {
+                                        new OsuSpriteText
+                                        {
+                                            Text = "Level Range ",
+                                            TextSize = 14,
+                                        },
+                                        new OsuSpriteText
+                                        {
+                                            Text = "#",
+                                            TextSize = 14,
+                                        },
+                                        levelRangeLower = new OsuSpriteText
+                                        {
+                                            TextSize = 14,
+                                            Font = @"Exo2.0-Bold",
+                                        },
+                                        new OsuSpriteText
+                                        {
+                                            Text = " - ",
+                                            TextSize = 14,
+                                        },
+                                        new OsuSpriteText
+                                        {
+                                            Text = "#",
+                                            TextSize = 14,
+                                        },
+                                        levelRangeHigher = new OsuSpriteText
+                                        {
+                                            Text = "6251",
+                                            TextSize = 14,
+                                            Font = @"Exo2.0-Bold",
+                                        },
+                                    },
+                                },
+                            },
+                        },
+                    },
+                },
+                participantsScroll = new ScrollContainer
+                {
+                    Anchor = Anchor.BottomLeft,
+                    Origin = Anchor.BottomLeft,
+                    RelativeSizeAxes = Axes.X,
+                    Padding = new MarginPadding { Top = content_padding.Top, Left = 38, Right = 37 },
+                    Children = new[]
+                    {
+                        participantsFlow = new FillFlowContainer
+                        {
+                            RelativeSizeAxes = Axes.X,
+                            AutoSizeAxes = Axes.Y,
+                            LayoutDuration = 100,
+                            Spacing = new Vector2(5f),
+                        },
+                    },
+                },
+            };
+
+            nameBind.ValueChanged += displayName;
+            hostBind.ValueChanged += displayUser;
+            maxParticipantsBind.ValueChanged += displayMaxParticipants;
+            participantsBind.ValueChanged += displayParticipants;
+        }
+
+        [BackgroundDependencyLoader]
+        private void load(OsuColour colours, LocalisationEngine localisation, TextureStore textures, RulesetDatabase rulesets)
+        {
+            this.localisation = localisation;
+            this.colours = colours;
+
+            beatmapAuthor.Colour = levelRangeContainer.Colour = colours.Gray9;
+            host.Colour = colours.Blue;
+
+            cover.Texture = textures.Get(@"https://a.pomf.cat/mvduor.png");
+
+            rulesetContainer.Add(new DifficultyIcon(new BeatmapInfo
+            {
+                Ruleset = rulesets.GetRuleset(0),
+                StarDifficulty = 3.7,
+            }) { Size = new Vector2(30f) });
+
+            //binded here instead of ctor because dependencies are needed
+            statusBind.ValueChanged += displayStatus;
+            beatmapBind.ValueChanged += displayBeatmap;
+
+            statusBind.TriggerChange();
+            beatmapBind.TriggerChange();
+        }
+
+        protected override void Update()
+        {
+            base.Update();
+
+            participantsScroll.Height = DrawHeight - topFlow.DrawHeight;
+        }
+
+        private void displayName(string value)
+        {
+            name.Text = value;
+        }
+
+        private void displayUser(User value)
+        {
+            host.Text = value.Username;
+            flagContainer.Children = new[] { new DrawableFlag(value.Country?.FlagName ?? @"__") { RelativeSizeAxes = Axes.Both } };
+        }
+
+        private void displayStatus(RoomStatus value)
+        {
+            if (value == null) return;
+            status.Text = value.Message;
+
+            foreach (Drawable d in new Drawable[] { statusStrip, status })
+                d.FadeColour(value.GetAppropriateColour(colours), 100);
+        }
+
+        private void displayBeatmap(BeatmapInfo value)
+        {
+            if (value != null)
+            {
+                rulesetContainer.FadeIn(100);
+                rulesetContainer.Children = new[]
+                {
+                    new DifficultyIcon(value)
+                    {
+                        Size = new Vector2(rulesetContainer.DrawHeight),
+                    }
+                };
+
+                beatmapTitle.Current = localisation.GetUnicodePreference(value.Metadata.TitleUnicode, value.Metadata.Title);
+                beatmapDash.Text = @" - ";
+                beatmapArtist.Current = localisation.GetUnicodePreference(value.Metadata.ArtistUnicode, value.Metadata.Artist);
+                beatmapAuthor.Text = $"mapped by {value.Metadata.Author}";
+            }
+            else
+            {
+                rulesetContainer.FadeOut(100);
+
+                beatmapTitle.Current = null;
+                beatmapArtist.Current = null;
+
+                beatmapTitle.Text = "Changing map";
+                beatmapDash.Text = beatmapArtist.Text = beatmapAuthor.Text = string.Empty;
+            }
+        }
+
+        private void displayMaxParticipants(int? value)
+        {
+            if (value == null)
+            {
+                participantsSlash.FadeOut(100);
+                maxParticipants.FadeOut(100);
+            }
+            else
+            {
+                participantsSlash.FadeIn(100);
+                maxParticipants.FadeIn(100);
+                maxParticipants.Text = value.ToString();
+            }
+        }
+
+        private void displayParticipants(User[] value)
+        {
+            participants.Text = value.Length.ToString();
+
+            var ranks = value.Select(u => u.GlobalRank);
+            levelRangeLower.Text = ranks.Min().ToString();
+            levelRangeHigher.Text = ranks.Max().ToString();
+
+            participantsFlow.Children = value.Select(u => new UserTile(u));
+        }
+
+        private class UserTile : Container, IHasTooltip
+        {
+            private readonly User user;
+
+            public string TooltipText => user.Username;
+
+            public UserTile(User user)
+            {
+                this.user = user;
+                Size = new Vector2(70f);
+                CornerRadius = 5f;
+                Masking = true;
+
+                Children = new Drawable[]
+                {
+                    new Box
+                    {
+                        RelativeSizeAxes = Axes.Both,
+                        Colour = OsuColour.FromHex(@"27252d"),
+                    },
+                    new UpdateableAvatar
+                    {
+                        RelativeSizeAxes = Axes.Both,
+                        User = user,
+                    },
+                };
+            }
+        }
+    }
+}
diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs
index 93933c8fe9..8c5ab29736 100644
--- a/osu.Game/Users/User.cs
+++ b/osu.Game/Users/User.cs
@@ -22,6 +22,10 @@ namespace osu.Game.Users
 
         public Bindable<UserStatus> Status = new Bindable<UserStatus>();
 
+        public int GlobalRank;
+
+        public int CountryRank;
+
         //public Team Team;
 
         [JsonProperty(@"profile_colour")]
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 0ec0624978..d233d1e28b 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -452,6 +452,7 @@
     <Compile Include="Graphics\Containers\ReverseDepthFillFlowContainer.cs" />
     <Compile Include="Database\RankStatus.cs" />
     <Compile Include="Graphics\UserInterface\BreadcrumbControl.cs" />
+    <Compile Include="Screens\Multiplayer\RoomInspector.cs" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\osu-framework\osu.Framework\osu.Framework.csproj">

From 774d37a05897d68fab316f7c3ca322f69e37e10b Mon Sep 17 00:00:00 2001
From: DrabWeb <sethunity@gmail.com>
Date: Tue, 30 May 2017 19:13:05 -0300
Subject: [PATCH 02/20] Add transition_duration, remove testing DifficultyIcon

---
 osu.Game/Screens/Multiplayer/RoomInspector.cs | 29 ++++++++-----------
 1 file changed, 12 insertions(+), 17 deletions(-)

diff --git a/osu.Game/Screens/Multiplayer/RoomInspector.cs b/osu.Game/Screens/Multiplayer/RoomInspector.cs
index 1471e2ed26..485ebf63b0 100644
--- a/osu.Game/Screens/Multiplayer/RoomInspector.cs
+++ b/osu.Game/Screens/Multiplayer/RoomInspector.cs
@@ -25,6 +25,7 @@ namespace osu.Game.Screens.Multiplayer
     public class RoomInspector : Container
     {
         private readonly MarginPadding content_padding = new MarginPadding { Horizontal = 20, Vertical = 10 };
+        private const float transition_duration = 100;
 
         private readonly FillFlowContainer topFlow;
         private readonly Box statusStrip;
@@ -113,7 +114,7 @@ namespace osu.Game.Screens.Multiplayer
                                             Origin = Anchor.TopRight,
                                             AutoSizeAxes = Axes.Both,
                                             Direction = FillDirection.Horizontal,
-                                            LayoutDuration = 100,
+                                            LayoutDuration = transition_duration,
                                             Children = new[]
                                             {
                                                 participants = new OsuSpriteText
@@ -178,7 +179,7 @@ namespace osu.Game.Screens.Multiplayer
                                         {
                                             AutoSizeAxes = Axes.Both,
                                             Direction = FillDirection.Horizontal,
-                                            LayoutDuration = 100,
+                                            LayoutDuration = transition_duration,
                                             Spacing = new Vector2(5f, 0f),
                                             Children = new Drawable[]
                                             {
@@ -349,7 +350,7 @@ namespace osu.Game.Screens.Multiplayer
                         {
                             RelativeSizeAxes = Axes.X,
                             AutoSizeAxes = Axes.Y,
-                            LayoutDuration = 100,
+                            LayoutDuration = transition_duration,
                             Spacing = new Vector2(5f),
                         },
                     },
@@ -363,7 +364,7 @@ namespace osu.Game.Screens.Multiplayer
         }
 
         [BackgroundDependencyLoader]
-        private void load(OsuColour colours, LocalisationEngine localisation, TextureStore textures, RulesetDatabase rulesets)
+        private void load(OsuColour colours, LocalisationEngine localisation, TextureStore textures)
         {
             this.localisation = localisation;
             this.colours = colours;
@@ -373,12 +374,6 @@ namespace osu.Game.Screens.Multiplayer
 
             cover.Texture = textures.Get(@"https://a.pomf.cat/mvduor.png");
 
-            rulesetContainer.Add(new DifficultyIcon(new BeatmapInfo
-            {
-                Ruleset = rulesets.GetRuleset(0),
-                StarDifficulty = 3.7,
-            }) { Size = new Vector2(30f) });
-
             //binded here instead of ctor because dependencies are needed
             statusBind.ValueChanged += displayStatus;
             beatmapBind.ValueChanged += displayBeatmap;
@@ -411,14 +406,14 @@ namespace osu.Game.Screens.Multiplayer
             status.Text = value.Message;
 
             foreach (Drawable d in new Drawable[] { statusStrip, status })
-                d.FadeColour(value.GetAppropriateColour(colours), 100);
+                d.FadeColour(value.GetAppropriateColour(colours), transition_duration);
         }
 
         private void displayBeatmap(BeatmapInfo value)
         {
             if (value != null)
             {
-                rulesetContainer.FadeIn(100);
+                rulesetContainer.FadeIn(transition_duration);
                 rulesetContainer.Children = new[]
                 {
                     new DifficultyIcon(value)
@@ -434,7 +429,7 @@ namespace osu.Game.Screens.Multiplayer
             }
             else
             {
-                rulesetContainer.FadeOut(100);
+                rulesetContainer.FadeOut(transition_duration);
 
                 beatmapTitle.Current = null;
                 beatmapArtist.Current = null;
@@ -448,13 +443,13 @@ namespace osu.Game.Screens.Multiplayer
         {
             if (value == null)
             {
-                participantsSlash.FadeOut(100);
-                maxParticipants.FadeOut(100);
+                participantsSlash.FadeOut(transition_duration);
+                maxParticipants.FadeOut(transition_duration);
             }
             else
             {
-                participantsSlash.FadeIn(100);
-                maxParticipants.FadeIn(100);
+                participantsSlash.FadeIn(transition_duration);
+                maxParticipants.FadeIn(transition_duration);
                 maxParticipants.Text = value.ToString();
             }
         }

From 5d6534031e72cd271cab797d1fae631baecd8627 Mon Sep 17 00:00:00 2001
From: DrabWeb <sethunity@gmail.com>
Date: Tue, 30 May 2017 19:35:37 -0300
Subject: [PATCH 03/20] Proper cover loading

---
 .../Tests/TestCaseRoomInspector.cs            |  8 ++++
 osu.Game/Screens/Multiplayer/RoomInspector.cs | 43 +++++++++++++------
 2 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
index 8ec1f66f8b..ac685d8b99 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
@@ -35,6 +35,10 @@ namespace osu.Desktop.VisualTests.Tests
                     Artist = @"Maaya Sakamoto",
                     Author = @"uwutm8",
                 },
+                OnlineInfo = new BeatmapOnlineInfo
+                {
+                    Covers = new[] { @"https://assets.ppy.sh//beatmaps/560573/covers/cover.jpg?1492722343" },
+                },
             };
             room.MaxParticipants.Value = 200;
             room.Participants.Value = new[] { new User { Username = @"flyte", Id = 3103765, GlobalRank = 1425 },
@@ -79,6 +83,10 @@ namespace osu.Desktop.VisualTests.Tests
                         Artist = @"FREEDOM DIVE",
                         Author = @"Nakagawa-Kanon",
                     },
+                    OnlineInfo = new BeatmapOnlineInfo
+                    {
+                        Covers = new[] { @"https://assets.ppy.sh//beatmaps/39804/covers/cover.jpg?1456506845" },
+                    },
                 };
                 newRoom.MaxParticipants.Value = 10;
                 newRoom.Participants.Value = new[]
diff --git a/osu.Game/Screens/Multiplayer/RoomInspector.cs b/osu.Game/Screens/Multiplayer/RoomInspector.cs
index 485ebf63b0..4c706cc630 100644
--- a/osu.Game/Screens/Multiplayer/RoomInspector.cs
+++ b/osu.Game/Screens/Multiplayer/RoomInspector.cs
@@ -27,15 +27,11 @@ namespace osu.Game.Screens.Multiplayer
         private readonly MarginPadding content_padding = new MarginPadding { Horizontal = 20, Vertical = 10 };
         private const float transition_duration = 100;
 
-        private readonly FillFlowContainer topFlow;
         private readonly Box statusStrip;
+        private readonly Container coverContainer, rulesetContainer, flagContainer;
+        private readonly FillFlowContainer topFlow, levelRangeContainer, participantsFlow;
         private readonly OsuSpriteText participants, participantsSlash, maxParticipants, name, status, beatmapTitle, beatmapDash, beatmapArtist, beatmapAuthor, host, levelRangeLower, levelRangeHigher;
-        private readonly Sprite cover;
-        private readonly FillFlowContainer levelRangeContainer;
         private readonly ScrollContainer participantsScroll;
-        private readonly FillFlowContainer participantsFlow;
-        private readonly Container rulesetContainer;
-        private readonly Container flagContainer;
 
         private Bindable<string> nameBind = new Bindable<string>();
         private Bindable<User> hostBind = new Bindable<User>();
@@ -46,6 +42,7 @@ namespace osu.Game.Screens.Multiplayer
 
         private OsuColour colours;
         private LocalisationEngine localisation;
+        private TextureStore textures;
 
         private Room room;
         public Room Room
@@ -91,11 +88,21 @@ namespace osu.Game.Screens.Multiplayer
                             Masking = true,
                             Children = new Drawable[]
                             {
-                                cover = new Sprite
+                                new Container
                                 {
-                                    Anchor = Anchor.Centre,
-                                    Origin = Anchor.Centre,
-                                    FillMode = FillMode.Fill,
+                                    RelativeSizeAxes = Axes.Both,
+                                    Children = new Drawable[]
+                                    {
+                                        new Box
+                                        {
+                                            RelativeSizeAxes = Axes.Both,
+                                            Colour = Color4.Black,
+                                        },
+                                        coverContainer = new Container
+                                        {
+                                            RelativeSizeAxes = Axes.Both,
+                                        },
+                                    },
                                 },
                                 new Box
                                 {
@@ -368,12 +375,11 @@ namespace osu.Game.Screens.Multiplayer
         {
             this.localisation = localisation;
             this.colours = colours;
+            this.textures = textures;
 
             beatmapAuthor.Colour = levelRangeContainer.Colour = colours.Gray9;
             host.Colour = colours.Blue;
 
-            cover.Texture = textures.Get(@"https://a.pomf.cat/mvduor.png");
-
             //binded here instead of ctor because dependencies are needed
             statusBind.ValueChanged += displayStatus;
             beatmapBind.ValueChanged += displayBeatmap;
@@ -413,6 +419,18 @@ namespace osu.Game.Screens.Multiplayer
         {
             if (value != null)
             {
+                coverContainer.FadeIn(transition_duration);
+                coverContainer.Children = new[]
+                {
+                    new AsyncLoadWrapper(new BeatmapBackgroundSprite(new OnlineWorkingBeatmap(value, textures, null))
+                    {
+                        Anchor = Anchor.Centre,
+                        Origin = Anchor.Centre,
+                        FillMode = FillMode.Fill,
+                        OnLoadComplete = d => d.FadeInFromZero(400, EasingTypes.Out),
+                    }) { RelativeSizeAxes = Axes.Both }
+                };
+
                 rulesetContainer.FadeIn(transition_duration);
                 rulesetContainer.Children = new[]
                 {
@@ -429,6 +447,7 @@ namespace osu.Game.Screens.Multiplayer
             }
             else
             {
+                coverContainer.FadeOut(transition_duration);
                 rulesetContainer.FadeOut(transition_duration);
 
                 beatmapTitle.Current = null;

From b97691100f94bc9f5ff5c63e7ce307b8577ead15 Mon Sep 17 00:00:00 2001
From: DrabWeb <sethunity@gmail.com>
Date: Tue, 30 May 2017 19:53:06 -0300
Subject: [PATCH 04/20] Add ruleset_height to remove magic numbers

---
 osu.Game/Screens/Multiplayer/RoomInspector.cs | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/osu.Game/Screens/Multiplayer/RoomInspector.cs b/osu.Game/Screens/Multiplayer/RoomInspector.cs
index 4c706cc630..7f0cf409d2 100644
--- a/osu.Game/Screens/Multiplayer/RoomInspector.cs
+++ b/osu.Game/Screens/Multiplayer/RoomInspector.cs
@@ -26,6 +26,7 @@ namespace osu.Game.Screens.Multiplayer
     {
         private readonly MarginPadding content_padding = new MarginPadding { Horizontal = 20, Vertical = 10 };
         private const float transition_duration = 100;
+        private const float ruleset_height = 30;
 
         private readonly Box statusStrip;
         private readonly Container coverContainer, rulesetContainer, flagContainer;
@@ -192,11 +193,11 @@ namespace osu.Game.Screens.Multiplayer
                                             {
                                                 rulesetContainer = new Container
                                                 {
-                                                    Size = new Vector2(30f),
+                                                    Size = new Vector2(ruleset_height),
                                                 },
                                                 new Container //todo: game type icon
                                                 {
-                                                    Size = new Vector2(30f),
+                                                    Size = new Vector2(ruleset_height),
                                                     CornerRadius = 15f,
                                                     Masking = true,
                                                     Children = new[]
@@ -211,7 +212,7 @@ namespace osu.Game.Screens.Multiplayer
                                                 new Container
                                                 {
                                                     AutoSizeAxes = Axes.X,
-                                                    Height = 30f,
+                                                    Height = ruleset_height,
                                                     Margin = new MarginPadding { Left = 5 },
                                                     Children = new[]
                                                     {
@@ -436,7 +437,7 @@ namespace osu.Game.Screens.Multiplayer
                 {
                     new DifficultyIcon(value)
                     {
-                        Size = new Vector2(rulesetContainer.DrawHeight),
+                        Size = new Vector2(ruleset_height),
                     }
                 };
 

From d331aa3b301bb4b374d3663c72587f17566ba42f Mon Sep 17 00:00:00 2001
From: DrabWeb <sethunity@gmail.com>
Date: Tue, 30 May 2017 20:02:05 -0300
Subject: [PATCH 05/20] Fix random layout animations when loaded

---
 osu.Game/Screens/Multiplayer/RoomInspector.cs | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/osu.Game/Screens/Multiplayer/RoomInspector.cs b/osu.Game/Screens/Multiplayer/RoomInspector.cs
index 7f0cf409d2..c771777d27 100644
--- a/osu.Game/Screens/Multiplayer/RoomInspector.cs
+++ b/osu.Game/Screens/Multiplayer/RoomInspector.cs
@@ -185,7 +185,8 @@ namespace osu.Game.Screens.Multiplayer
                                         },
                                         new FillFlowContainer
                                         {
-                                            AutoSizeAxes = Axes.Both,
+                                            AutoSizeAxes = Axes.X,
+                                            Height = ruleset_height,
                                             Direction = FillDirection.Horizontal,
                                             LayoutDuration = transition_duration,
                                             Spacing = new Vector2(5f, 0f),
@@ -212,7 +213,7 @@ namespace osu.Game.Screens.Multiplayer
                                                 new Container
                                                 {
                                                     AutoSizeAxes = Axes.X,
-                                                    Height = ruleset_height,
+                                                    RelativeSizeAxes = Axes.Y,
                                                     Margin = new MarginPadding { Left = 5 },
                                                     Children = new[]
                                                     {
@@ -389,9 +390,9 @@ namespace osu.Game.Screens.Multiplayer
             beatmapBind.TriggerChange();
         }
 
-        protected override void Update()
+        protected override void UpdateAfterChildren()
         {
-            base.Update();
+            base.UpdateAfterChildren();
 
             participantsScroll.Height = DrawHeight - topFlow.DrawHeight;
         }

From 9e01074852a5b4bd78357522e62f797cb3d63b77 Mon Sep 17 00:00:00 2001
From: DrabWeb <sethunity@gmail.com>
Date: Tue, 30 May 2017 21:41:20 -0300
Subject: [PATCH 06/20] Add GameType and DrawableGameType

---
 .../Tests/TestCaseRoomInspector.cs            |   3 +
 osu.Game/Online/Multiplayer/GameType.cs       | 127 ++++++++++++++++++
 osu.Game/Online/Multiplayer/Room.cs           |   1 +
 .../Screens/Multiplayer/DrawableGameType.cs   |  43 ++++++
 osu.Game/Screens/Multiplayer/RoomInspector.cs |  29 ++--
 osu.Game/osu.Game.csproj                      |   2 +
 6 files changed, 193 insertions(+), 12 deletions(-)
 create mode 100644 osu.Game/Online/Multiplayer/GameType.cs
 create mode 100644 osu.Game/Screens/Multiplayer/DrawableGameType.cs

diff --git a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
index ac685d8b99..7ec78cd136 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
@@ -25,6 +25,7 @@ namespace osu.Desktop.VisualTests.Tests
             room.Name.Value = @"My Awesome Room";
             room.Host.Value = new User { Username = @"flyte", Id = 3103765, Country = new Country { FlagName = @"JP" }};
             room.Status.Value = new RoomStatusOpen();
+            room.Type.Value = new GameTypeTeamVersus();
             room.Beatmap.Value = new BeatmapInfo
             {
                 StarDifficulty = 3.7,
@@ -59,6 +60,7 @@ namespace osu.Desktop.VisualTests.Tests
             AddStep(@"change title", () => room.Name.Value = @"A Better Room Than The Above");
             AddStep(@"change host", () => room.Host.Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" }});
             AddStep(@"change status", () => room.Status.Value = new RoomStatusPlaying());
+            AddStep(@"change type", () => room.Type.Value = new GameTypeTag());
             AddStep(@"change beatmap", () => room.Beatmap.Value = null);
             AddStep(@"change max participants", () => room.MaxParticipants.Value = null);
             AddStep(@"change participants", () => room.Participants.Value = new[]
@@ -73,6 +75,7 @@ namespace osu.Desktop.VisualTests.Tests
                 newRoom.Name.Value = @"My New, Better Than Ever Room";
                 newRoom.Host.Value = new User { Username = @"Angelsim", Id = 1777162, Country = new Country { FlagName = @"KR" }};
                 newRoom.Status.Value = new RoomStatusOpen();
+                newRoom.Type.Value = new GameTypeTagTeam();
                 newRoom.Beatmap.Value = new BeatmapInfo
                 {
                     StarDifficulty = 7.07,
diff --git a/osu.Game/Online/Multiplayer/GameType.cs b/osu.Game/Online/Multiplayer/GameType.cs
new file mode 100644
index 0000000000..0b9633a752
--- /dev/null
+++ b/osu.Game/Online/Multiplayer/GameType.cs
@@ -0,0 +1,127 @@
+// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using OpenTK;
+using OpenTK.Graphics;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Sprites;
+using osu.Game.Graphics;
+
+namespace osu.Game.Online.Multiplayer
+{
+    public abstract class GameType
+    {
+        public abstract string Name { get; }
+        public abstract Drawable GetIcon(OsuColour colours, float size);
+    }
+
+    public class GameTypeTag : GameType
+    {
+        public override string Name => "Tag";
+        public override Drawable GetIcon(OsuColour colours, float size)
+        {
+            return new TextAwesome
+            {
+                Anchor = Anchor.Centre,
+                Origin = Anchor.Centre,
+                Icon = FontAwesome.fa_refresh,
+                TextSize = size,
+                Colour = colours.Blue,
+                Shadow = false,
+                UseFullGlyphHeight = false,
+            };
+        }
+    }
+
+    public class GameTypeVersus : GameType
+    {
+        public override string Name => "Versus";
+        public override Drawable GetIcon(OsuColour colours, float size)
+        {
+            return new VersusRow(colours.Blue, colours.Blue, size * 0.6f)
+            {
+                Anchor = Anchor.Centre,
+                Origin = Anchor.Centre,
+            };
+        }
+    }
+
+    public class GameTypeTagTeam : GameType
+    {
+        public override string Name => "Tag Team";
+        public override Drawable GetIcon(OsuColour colours, float size)
+        {
+            return new VersusRow(colours.Blue, colours.Blue, size * 0.6f)
+            {
+                Anchor = Anchor.Centre,
+                Origin = Anchor.Centre,
+            };
+        }
+    }
+
+    public class GameTypeTeamVersus : GameType
+    {
+        public override string Name => "Team Versus";
+        public override Drawable GetIcon(OsuColour colours, float size)
+        {
+            return new FillFlowContainer
+            {
+                Anchor = Anchor.Centre,
+                Origin = Anchor.Centre,
+                AutoSizeAxes = Axes.Both,
+                Direction = FillDirection.Vertical,
+                Spacing = new Vector2(2f),
+                Children = new[]
+                {
+                    new VersusRow(colours.Blue, colours.Pink, size * 0.5f),
+                    new VersusRow(colours.Blue, colours.Pink, size * 0.5f),
+                },
+            };
+        }
+    }
+
+    internal class VersusRow : FillFlowContainer
+    {
+        public VersusRow(Color4 first, Color4 second, float size)
+        {
+            var triangle_size = new Vector2(size);
+            AutoSizeAxes = Axes.Both;
+            Spacing = new Vector2(2f, 0f);
+
+            Children = new[]
+            {
+                new Container
+                {
+                    Size = triangle_size,
+                    Colour = first,
+                    Children = new[]
+                    {
+                        new EquilateralTriangle
+                        {
+                            Origin = Anchor.BottomLeft,
+                            RelativeSizeAxes = Axes.Both,
+                            Rotation = 90,
+                            EdgeSmoothness = new Vector2(1f),
+                        },
+                    },
+                },
+                new Container
+                {
+                    Size = triangle_size,
+                    Colour = second,
+                    Children = new[]
+                    {
+                        new EquilateralTriangle
+                        {
+                            Anchor = Anchor.BottomLeft,
+                            RelativeSizeAxes = Axes.Both,
+                            Rotation = -90,
+                            EdgeSmoothness = new Vector2(1f),
+                        },
+                    },
+                },
+            };
+        }
+    }
+}
diff --git a/osu.Game/Online/Multiplayer/Room.cs b/osu.Game/Online/Multiplayer/Room.cs
index fe3378f4a6..26b9dbc88a 100644
--- a/osu.Game/Online/Multiplayer/Room.cs
+++ b/osu.Game/Online/Multiplayer/Room.cs
@@ -12,6 +12,7 @@ namespace osu.Game.Online.Multiplayer
         public Bindable<string> Name = new Bindable<string>();
         public Bindable<User> Host = new Bindable<User>();
         public Bindable<RoomStatus> Status = new Bindable<RoomStatus>();
+        public Bindable<GameType> Type = new Bindable<GameType>();
         public Bindable<BeatmapInfo> Beatmap = new Bindable<BeatmapInfo>();
         public Bindable<int?> MaxParticipants = new Bindable<int?>();
         public Bindable<User[]> Participants = new Bindable<User[]>();
diff --git a/osu.Game/Screens/Multiplayer/DrawableGameType.cs b/osu.Game/Screens/Multiplayer/DrawableGameType.cs
new file mode 100644
index 0000000000..6e7458b3dc
--- /dev/null
+++ b/osu.Game/Screens/Multiplayer/DrawableGameType.cs
@@ -0,0 +1,43 @@
+// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using OpenTK;
+using OpenTK.Graphics;
+using osu.Framework.Allocation;
+using osu.Framework.Extensions.Color4Extensions;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Sprites;
+using osu.Game.Graphics;
+using osu.Game.Online.Multiplayer;
+
+namespace osu.Game.Screens.Multiplayer
+{
+    public class DrawableGameType : CircularContainer, IHasTooltip
+    {
+        private readonly GameType type;
+
+        public string TooltipText => type.Name;
+
+        public DrawableGameType(GameType type)
+        {
+            this.type = type;
+            Masking = true;
+
+            Children = new[]
+            {
+                new Box
+                {
+                    RelativeSizeAxes = Axes.Both,
+                    Colour = OsuColour.FromHex(@"545454"),
+                },
+            };
+        }
+
+        [BackgroundDependencyLoader]
+        private void load(OsuColour colours)
+        {
+            Add(type.GetIcon(colours, Height / 2));
+        }
+    }
+}
diff --git a/osu.Game/Screens/Multiplayer/RoomInspector.cs b/osu.Game/Screens/Multiplayer/RoomInspector.cs
index c771777d27..89b71bf9b9 100644
--- a/osu.Game/Screens/Multiplayer/RoomInspector.cs
+++ b/osu.Game/Screens/Multiplayer/RoomInspector.cs
@@ -29,7 +29,7 @@ namespace osu.Game.Screens.Multiplayer
         private const float ruleset_height = 30;
 
         private readonly Box statusStrip;
-        private readonly Container coverContainer, rulesetContainer, flagContainer;
+        private readonly Container coverContainer, rulesetContainer, gameTypeContainer, flagContainer;
         private readonly FillFlowContainer topFlow, levelRangeContainer, participantsFlow;
         private readonly OsuSpriteText participants, participantsSlash, maxParticipants, name, status, beatmapTitle, beatmapDash, beatmapArtist, beatmapAuthor, host, levelRangeLower, levelRangeHigher;
         private readonly ScrollContainer participantsScroll;
@@ -37,6 +37,7 @@ namespace osu.Game.Screens.Multiplayer
         private Bindable<string> nameBind = new Bindable<string>();
         private Bindable<User> hostBind = new Bindable<User>();
         private Bindable<RoomStatus> statusBind = new Bindable<RoomStatus>();
+        private Bindable<GameType> typeBind = new Bindable<GameType>();
         private Bindable<BeatmapInfo> beatmapBind = new Bindable<BeatmapInfo>();
         private Bindable<int?> maxParticipantsBind = new Bindable<int?>();
         private Bindable<User[]> participantsBind = new Bindable<User[]>();
@@ -57,6 +58,7 @@ namespace osu.Game.Screens.Multiplayer
                 nameBind.BindTo(Room.Name);
                 hostBind.BindTo(Room.Host);
                 statusBind.BindTo(Room.Status);
+                typeBind.BindTo(Room.Type);
                 beatmapBind.BindTo(Room.Beatmap);
                 maxParticipantsBind.BindTo(Room.MaxParticipants);
                 participantsBind.BindTo(Room.Participants);
@@ -196,19 +198,9 @@ namespace osu.Game.Screens.Multiplayer
                                                 {
                                                     Size = new Vector2(ruleset_height),
                                                 },
-                                                new Container //todo: game type icon
+                                                gameTypeContainer = new Container
                                                 {
                                                     Size = new Vector2(ruleset_height),
-                                                    CornerRadius = 15f,
-                                                    Masking = true,
-                                                    Children = new[]
-                                                    {
-                                                        new Box
-                                                        {
-                                                            RelativeSizeAxes = Axes.Both,
-                                                            Colour = OsuColour.FromHex(@"545454"),
-                                                        },
-                                                    },
                                                 },
                                                 new Container
                                                 {
@@ -384,9 +376,11 @@ namespace osu.Game.Screens.Multiplayer
 
             //binded here instead of ctor because dependencies are needed
             statusBind.ValueChanged += displayStatus;
+            typeBind.ValueChanged += displayGameType;
             beatmapBind.ValueChanged += displayBeatmap;
 
             statusBind.TriggerChange();
+            typeBind.TriggerChange();
             beatmapBind.TriggerChange();
         }
 
@@ -417,6 +411,17 @@ namespace osu.Game.Screens.Multiplayer
                 d.FadeColour(value.GetAppropriateColour(colours), transition_duration);
         }
 
+        private void displayGameType(GameType value)
+        {
+            gameTypeContainer.Children = new[]
+            {
+                new DrawableGameType(value)
+                {
+                    Size = new Vector2(ruleset_height),
+                },
+            };
+        }
+
         private void displayBeatmap(BeatmapInfo value)
         {
             if (value != null)
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index d233d1e28b..5e673e0477 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -453,6 +453,8 @@
     <Compile Include="Database\RankStatus.cs" />
     <Compile Include="Graphics\UserInterface\BreadcrumbControl.cs" />
     <Compile Include="Screens\Multiplayer\RoomInspector.cs" />
+    <Compile Include="Online\Multiplayer\GameType.cs" />
+    <Compile Include="Screens\Multiplayer\DrawableGameType.cs" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\osu-framework\osu.Framework\osu.Framework.csproj">

From 185a4c4d2e65dbf7c669f2fa5845d875b681ac15 Mon Sep 17 00:00:00 2001
From: DrabWeb <sethunity@gmail.com>
Date: Tue, 30 May 2017 22:00:27 -0300
Subject: [PATCH 07/20] Unused usings

---
 osu.Game/Screens/Multiplayer/DrawableGameType.cs | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/osu.Game/Screens/Multiplayer/DrawableGameType.cs b/osu.Game/Screens/Multiplayer/DrawableGameType.cs
index 6e7458b3dc..ccc98c3ccd 100644
--- a/osu.Game/Screens/Multiplayer/DrawableGameType.cs
+++ b/osu.Game/Screens/Multiplayer/DrawableGameType.cs
@@ -1,10 +1,7 @@
 // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
 // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
 
-using OpenTK;
-using OpenTK.Graphics;
 using osu.Framework.Allocation;
-using osu.Framework.Extensions.Color4Extensions;
 using osu.Framework.Graphics;
 using osu.Framework.Graphics.Containers;
 using osu.Framework.Graphics.Sprites;

From 7ba32f20215d6e24132db952e1911e5426c84572 Mon Sep 17 00:00:00 2001
From: DrabWeb <sethunity@gmail.com>
Date: Tue, 30 May 2017 22:11:45 -0300
Subject: [PATCH 08/20] Cleanup

---
 osu.Game/Screens/Multiplayer/RoomInspector.cs | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/osu.Game/Screens/Multiplayer/RoomInspector.cs b/osu.Game/Screens/Multiplayer/RoomInspector.cs
index 89b71bf9b9..6b68c396c9 100644
--- a/osu.Game/Screens/Multiplayer/RoomInspector.cs
+++ b/osu.Game/Screens/Multiplayer/RoomInspector.cs
@@ -196,11 +196,11 @@ namespace osu.Game.Screens.Multiplayer
                                             {
                                                 rulesetContainer = new Container
                                                 {
-                                                    Size = new Vector2(ruleset_height),
+                                                    AutoSizeAxes = Axes.Both,
                                                 },
                                                 gameTypeContainer = new Container
                                                 {
-                                                    Size = new Vector2(ruleset_height),
+                                                    AutoSizeAxes = Axes.Both,
                                                 },
                                                 new Container
                                                 {
@@ -263,7 +263,7 @@ namespace osu.Game.Screens.Multiplayer
                                             Width = 22f,
                                             RelativeSizeAxes = Axes.Y,
                                         },
-                                        new Container
+                                        new Container //todo: team banners
                                         {
                                             Width = 38f,
                                             RelativeSizeAxes = Axes.Y,
@@ -399,12 +399,17 @@ namespace osu.Game.Screens.Multiplayer
         private void displayUser(User value)
         {
             host.Text = value.Username;
-            flagContainer.Children = new[] { new DrawableFlag(value.Country?.FlagName ?? @"__") { RelativeSizeAxes = Axes.Both } };
+            flagContainer.Children = new[]
+            {
+                new DrawableFlag(value.Country?.FlagName ?? @"__")
+                {
+                    RelativeSizeAxes = Axes.Both,
+                },
+            };
         }
 
         private void displayStatus(RoomStatus value)
         {
-            if (value == null) return;
             status.Text = value.Message;
 
             foreach (Drawable d in new Drawable[] { statusStrip, status })

From a483422b44e430162a505c9fcea698a9f94c52c3 Mon Sep 17 00:00:00 2001
From: DrabWeb <sethunity@gmail.com>
Date: Tue, 30 May 2017 22:23:00 -0300
Subject: [PATCH 09/20] CI fixes

---
 osu.Game/Online/Multiplayer/GameType.cs       |  6 ++---
 osu.Game/Screens/Multiplayer/RoomInspector.cs | 22 +++++++++----------
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/osu.Game/Online/Multiplayer/GameType.cs b/osu.Game/Online/Multiplayer/GameType.cs
index 0b9633a752..2f4c92d289 100644
--- a/osu.Game/Online/Multiplayer/GameType.cs
+++ b/osu.Game/Online/Multiplayer/GameType.cs
@@ -85,7 +85,7 @@ namespace osu.Game.Online.Multiplayer
     {
         public VersusRow(Color4 first, Color4 second, float size)
         {
-            var triangle_size = new Vector2(size);
+            var triangleSize = new Vector2(size);
             AutoSizeAxes = Axes.Both;
             Spacing = new Vector2(2f, 0f);
 
@@ -93,7 +93,7 @@ namespace osu.Game.Online.Multiplayer
             {
                 new Container
                 {
-                    Size = triangle_size,
+                    Size = triangleSize,
                     Colour = first,
                     Children = new[]
                     {
@@ -108,7 +108,7 @@ namespace osu.Game.Online.Multiplayer
                 },
                 new Container
                 {
-                    Size = triangle_size,
+                    Size = triangleSize,
                     Colour = second,
                     Children = new[]
                     {
diff --git a/osu.Game/Screens/Multiplayer/RoomInspector.cs b/osu.Game/Screens/Multiplayer/RoomInspector.cs
index 6b68c396c9..fc4c1e1159 100644
--- a/osu.Game/Screens/Multiplayer/RoomInspector.cs
+++ b/osu.Game/Screens/Multiplayer/RoomInspector.cs
@@ -24,7 +24,7 @@ namespace osu.Game.Screens.Multiplayer
 {
     public class RoomInspector : Container
     {
-        private readonly MarginPadding content_padding = new MarginPadding { Horizontal = 20, Vertical = 10 };
+        private readonly MarginPadding contentPadding = new MarginPadding { Horizontal = 20, Vertical = 10 };
         private const float transition_duration = 100;
         private const float ruleset_height = 30;
 
@@ -34,13 +34,13 @@ namespace osu.Game.Screens.Multiplayer
         private readonly OsuSpriteText participants, participantsSlash, maxParticipants, name, status, beatmapTitle, beatmapDash, beatmapArtist, beatmapAuthor, host, levelRangeLower, levelRangeHigher;
         private readonly ScrollContainer participantsScroll;
 
-        private Bindable<string> nameBind = new Bindable<string>();
-        private Bindable<User> hostBind = new Bindable<User>();
-        private Bindable<RoomStatus> statusBind = new Bindable<RoomStatus>();
-        private Bindable<GameType> typeBind = new Bindable<GameType>();
-        private Bindable<BeatmapInfo> beatmapBind = new Bindable<BeatmapInfo>();
-        private Bindable<int?> maxParticipantsBind = new Bindable<int?>();
-        private Bindable<User[]> participantsBind = new Bindable<User[]>();
+        private readonly Bindable<string> nameBind = new Bindable<string>();
+        private readonly Bindable<User> hostBind = new Bindable<User>();
+        private readonly Bindable<RoomStatus> statusBind = new Bindable<RoomStatus>();
+        private readonly Bindable<GameType> typeBind = new Bindable<GameType>();
+        private readonly Bindable<BeatmapInfo> beatmapBind = new Bindable<BeatmapInfo>();
+        private readonly Bindable<int?> maxParticipantsBind = new Bindable<int?>();
+        private readonly Bindable<User[]> participantsBind = new Bindable<User[]>();
 
         private OsuColour colours;
         private LocalisationEngine localisation;
@@ -176,7 +176,7 @@ namespace osu.Game.Screens.Multiplayer
                                     RelativeSizeAxes = Axes.X,
                                     AutoSizeAxes = Axes.Y,
                                     Direction = FillDirection.Vertical,
-                                    Padding = content_padding,
+                                    Padding = contentPadding,
                                     Spacing = new Vector2(0f, 5f),
                                     Children = new Drawable[]
                                     {
@@ -247,7 +247,7 @@ namespace osu.Game.Screens.Multiplayer
                         {
                             RelativeSizeAxes = Axes.X,
                             AutoSizeAxes = Axes.Y,
-                            Padding = content_padding,
+                            Padding = contentPadding,
                             Children = new Drawable[]
                             {
                                 new FillFlowContainer
@@ -344,7 +344,7 @@ namespace osu.Game.Screens.Multiplayer
                     Anchor = Anchor.BottomLeft,
                     Origin = Anchor.BottomLeft,
                     RelativeSizeAxes = Axes.X,
-                    Padding = new MarginPadding { Top = content_padding.Top, Left = 38, Right = 37 },
+                    Padding = new MarginPadding { Top = contentPadding.Top, Left = 38, Right = 37 },
                     Children = new[]
                     {
                         participantsFlow = new FillFlowContainer

From ecece2bc29f0874ccd5be1d720f37f3140f7949d Mon Sep 17 00:00:00 2001
From: DrabWeb <sethunity@gmail.com>
Date: Tue, 30 May 2017 22:28:15 -0300
Subject: [PATCH 10/20] "Use" object initializers in visual test

---
 osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
index 7ec78cd136..0e3ed7c1a9 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
@@ -21,7 +21,7 @@ namespace osu.Desktop.VisualTests.Tests
         {
             base.Reset();
 
-            var room = new Room();
+            var room = new Room { };
             room.Name.Value = @"My Awesome Room";
             room.Host.Value = new User { Username = @"flyte", Id = 3103765, Country = new Country { FlagName = @"JP" }};
             room.Status.Value = new RoomStatusOpen();
@@ -71,7 +71,7 @@ namespace osu.Desktop.VisualTests.Tests
 
             AddStep(@"change room", () =>
             {
-                var newRoom = new Room();
+                var newRoom = new Room { };
                 newRoom.Name.Value = @"My New, Better Than Ever Room";
                 newRoom.Host.Value = new User { Username = @"Angelsim", Id = 1777162, Country = new Country { FlagName = @"KR" }};
                 newRoom.Status.Value = new RoomStatusOpen();

From e708cdf41a3d1e8be0e2cff41892d752577da097 Mon Sep 17 00:00:00 2001
From: DrabWeb <sethunity@gmail.com>
Date: Tue, 30 May 2017 22:34:02 -0300
Subject: [PATCH 11/20] Level Range -> Range Range, don't use empty object
 initializers

---
 osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs | 4 ++--
 osu.Game/Screens/Multiplayer/RoomInspector.cs          | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
index 0e3ed7c1a9..7ec78cd136 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
@@ -21,7 +21,7 @@ namespace osu.Desktop.VisualTests.Tests
         {
             base.Reset();
 
-            var room = new Room { };
+            var room = new Room();
             room.Name.Value = @"My Awesome Room";
             room.Host.Value = new User { Username = @"flyte", Id = 3103765, Country = new Country { FlagName = @"JP" }};
             room.Status.Value = new RoomStatusOpen();
@@ -71,7 +71,7 @@ namespace osu.Desktop.VisualTests.Tests
 
             AddStep(@"change room", () =>
             {
-                var newRoom = new Room { };
+                var newRoom = new Room();
                 newRoom.Name.Value = @"My New, Better Than Ever Room";
                 newRoom.Host.Value = new User { Username = @"Angelsim", Id = 1777162, Country = new Country { FlagName = @"KR" }};
                 newRoom.Status.Value = new RoomStatusOpen();
diff --git a/osu.Game/Screens/Multiplayer/RoomInspector.cs b/osu.Game/Screens/Multiplayer/RoomInspector.cs
index fc4c1e1159..25a4740698 100644
--- a/osu.Game/Screens/Multiplayer/RoomInspector.cs
+++ b/osu.Game/Screens/Multiplayer/RoomInspector.cs
@@ -304,7 +304,7 @@ namespace osu.Game.Screens.Multiplayer
                                     {
                                         new OsuSpriteText
                                         {
-                                            Text = "Level Range ",
+                                            Text = "Rank Range ",
                                             TextSize = 14,
                                         },
                                         new OsuSpriteText

From 1a8f207db32c1ea14241285b1cedc7b4a4cb706a Mon Sep 17 00:00:00 2001
From: Dean Herbert <pe@ppy.sh>
Date: Fri, 23 Jun 2017 22:14:56 +0900
Subject: [PATCH 12/20] Code formatting

---
 .../Tests/TestCaseRoomInspector.cs            | 21 +++++++++++--------
 osu.Game/Screens/Multiplayer/RoomInspector.cs |  1 +
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
index 7ec78cd136..c5fac3afe8 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
@@ -23,7 +23,7 @@ namespace osu.Desktop.VisualTests.Tests
 
             var room = new Room();
             room.Name.Value = @"My Awesome Room";
-            room.Host.Value = new User { Username = @"flyte", Id = 3103765, Country = new Country { FlagName = @"JP" }};
+            room.Host.Value = new User { Username = @"flyte", Id = 3103765, Country = new Country { FlagName = @"JP" } };
             room.Status.Value = new RoomStatusOpen();
             room.Type.Value = new GameTypeTeamVersus();
             room.Beatmap.Value = new BeatmapInfo
@@ -42,12 +42,15 @@ namespace osu.Desktop.VisualTests.Tests
                 },
             };
             room.MaxParticipants.Value = 200;
-            room.Participants.Value = new[] { new User { Username = @"flyte", Id = 3103765, GlobalRank = 1425 },
-                                              new User { Username = @"Cookiezi", Id = 124493, GlobalRank = 5466 },
-                                              new User { Username = @"Angelsim", Id = 1777162, GlobalRank = 2873 },
-                                              new User { Username = @"Rafis", Id = 2558286, GlobalRank = 4687 },
-                                              new User { Username = @"hvick225", Id = 50265, GlobalRank = 3258 },
-                                              new User { Username = @"peppy", Id = 2, GlobalRank = 6251 }};
+            room.Participants.Value = new[]
+            {
+                new User { Username = @"flyte", Id = 3103765, GlobalRank = 1425 },
+                new User { Username = @"Cookiezi", Id = 124493, GlobalRank = 5466 },
+                new User { Username = @"Angelsim", Id = 1777162, GlobalRank = 2873 },
+                new User { Username = @"Rafis", Id = 2558286, GlobalRank = 4687 },
+                new User { Username = @"hvick225", Id = 50265, GlobalRank = 3258 },
+                new User { Username = @"peppy", Id = 2, GlobalRank = 6251 }
+            };
 
             RoomInspector inspector;
             Add(inspector = new RoomInspector
@@ -58,7 +61,7 @@ namespace osu.Desktop.VisualTests.Tests
             });
 
             AddStep(@"change title", () => room.Name.Value = @"A Better Room Than The Above");
-            AddStep(@"change host", () => room.Host.Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" }});
+            AddStep(@"change host", () => room.Host.Value = new User { Username = @"DrabWeb", Id = 6946022, Country = new Country { FlagName = @"CA" } });
             AddStep(@"change status", () => room.Status.Value = new RoomStatusPlaying());
             AddStep(@"change type", () => room.Type.Value = new GameTypeTag());
             AddStep(@"change beatmap", () => room.Beatmap.Value = null);
@@ -73,7 +76,7 @@ namespace osu.Desktop.VisualTests.Tests
             {
                 var newRoom = new Room();
                 newRoom.Name.Value = @"My New, Better Than Ever Room";
-                newRoom.Host.Value = new User { Username = @"Angelsim", Id = 1777162, Country = new Country { FlagName = @"KR" }};
+                newRoom.Host.Value = new User { Username = @"Angelsim", Id = 1777162, Country = new Country { FlagName = @"KR" } };
                 newRoom.Status.Value = new RoomStatusOpen();
                 newRoom.Type.Value = new GameTypeTagTeam();
                 newRoom.Beatmap.Value = new BeatmapInfo
diff --git a/osu.Game/Screens/Multiplayer/RoomInspector.cs b/osu.Game/Screens/Multiplayer/RoomInspector.cs
index b7eca2dc8a..2181f37be9 100644
--- a/osu.Game/Screens/Multiplayer/RoomInspector.cs
+++ b/osu.Game/Screens/Multiplayer/RoomInspector.cs
@@ -48,6 +48,7 @@ namespace osu.Game.Screens.Multiplayer
         private TextureStore textures;
 
         private Room room;
+
         public Room Room
         {
             get { return room; }

From f314f5f7ea8aa5f0c93f9475f7c8dfb0f83acc79 Mon Sep 17 00:00:00 2001
From: Dean Herbert <pe@ppy.sh>
Date: Fri, 23 Jun 2017 22:34:36 +0900
Subject: [PATCH 13/20] CI fixes

---
 .../Tests/TestCaseRoomInspector.cs            | 110 ++++++++++--------
 1 file changed, 63 insertions(+), 47 deletions(-)

diff --git a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
index c5fac3afe8..beb664e7ff 100644
--- a/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCaseRoomInspector.cs
@@ -21,35 +21,43 @@ namespace osu.Desktop.VisualTests.Tests
         {
             base.Reset();
 
-            var room = new Room();
-            room.Name.Value = @"My Awesome Room";
-            room.Host.Value = new User { Username = @"flyte", Id = 3103765, Country = new Country { FlagName = @"JP" } };
-            room.Status.Value = new RoomStatusOpen();
-            room.Type.Value = new GameTypeTeamVersus();
-            room.Beatmap.Value = new BeatmapInfo
+            var room = new Room
             {
-                StarDifficulty = 3.7,
-                Ruleset = rulesets.GetRuleset(3),
-                Metadata = new BeatmapMetadata
+                Name = { Value = @"My Awesome Room" },
+                Host = { Value = new User { Username = @"flyte", Id = 3103765, Country = new Country { FlagName = @"JP" } } },
+                Status = { Value = new RoomStatusOpen() },
+                Type = { Value = new GameTypeTeamVersus() },
+                Beatmap =
                 {
-                    Title = @"Platina",
-                    Artist = @"Maaya Sakamoto",
-                    Author = @"uwutm8",
+                    Value = new BeatmapInfo
+                    {
+                        StarDifficulty = 3.7,
+                        Ruleset = rulesets.GetRuleset(3),
+                        Metadata = new BeatmapMetadata
+                        {
+                            Title = @"Platina",
+                            Artist = @"Maaya Sakamoto",
+                            Author = @"uwutm8",
+                        },
+                        OnlineInfo = new BeatmapOnlineInfo
+                        {
+                            Covers = new[] { @"https://assets.ppy.sh//beatmaps/560573/covers/cover.jpg?1492722343" },
+                        },
+                    }
                 },
-                OnlineInfo = new BeatmapOnlineInfo
+                MaxParticipants = { Value = 200 },
+                Participants =
                 {
-                    Covers = new[] { @"https://assets.ppy.sh//beatmaps/560573/covers/cover.jpg?1492722343" },
-                },
-            };
-            room.MaxParticipants.Value = 200;
-            room.Participants.Value = new[]
-            {
-                new User { Username = @"flyte", Id = 3103765, GlobalRank = 1425 },
-                new User { Username = @"Cookiezi", Id = 124493, GlobalRank = 5466 },
-                new User { Username = @"Angelsim", Id = 1777162, GlobalRank = 2873 },
-                new User { Username = @"Rafis", Id = 2558286, GlobalRank = 4687 },
-                new User { Username = @"hvick225", Id = 50265, GlobalRank = 3258 },
-                new User { Username = @"peppy", Id = 2, GlobalRank = 6251 }
+                    Value = new[]
+                    {
+                        new User { Username = @"flyte", Id = 3103765, GlobalRank = 1425 },
+                        new User { Username = @"Cookiezi", Id = 124493, GlobalRank = 5466 },
+                        new User { Username = @"Angelsim", Id = 1777162, GlobalRank = 2873 },
+                        new User { Username = @"Rafis", Id = 2558286, GlobalRank = 4687 },
+                        new User { Username = @"hvick225", Id = 50265, GlobalRank = 3258 },
+                        new User { Username = @"peppy", Id = 2, GlobalRank = 6251 }
+                    }
+                }
             };
 
             RoomInspector inspector;
@@ -74,32 +82,40 @@ namespace osu.Desktop.VisualTests.Tests
 
             AddStep(@"change room", () =>
             {
-                var newRoom = new Room();
-                newRoom.Name.Value = @"My New, Better Than Ever Room";
-                newRoom.Host.Value = new User { Username = @"Angelsim", Id = 1777162, Country = new Country { FlagName = @"KR" } };
-                newRoom.Status.Value = new RoomStatusOpen();
-                newRoom.Type.Value = new GameTypeTagTeam();
-                newRoom.Beatmap.Value = new BeatmapInfo
+                var newRoom = new Room
                 {
-                    StarDifficulty = 7.07,
-                    Ruleset = rulesets.GetRuleset(0),
-                    Metadata = new BeatmapMetadata
+                    Name = { Value = @"My New, Better Than Ever Room" },
+                    Host = { Value = new User { Username = @"Angelsim", Id = 1777162, Country = new Country { FlagName = @"KR" } } },
+                    Status = { Value = new RoomStatusOpen() },
+                    Type = { Value = new GameTypeTagTeam() },
+                    Beatmap =
                     {
-                        Title = @"xi",
-                        Artist = @"FREEDOM DIVE",
-                        Author = @"Nakagawa-Kanon",
+                        Value = new BeatmapInfo
+                        {
+                            StarDifficulty = 7.07,
+                            Ruleset = rulesets.GetRuleset(0),
+                            Metadata = new BeatmapMetadata
+                            {
+                                Title = @"xi",
+                                Artist = @"FREEDOM DIVE",
+                                Author = @"Nakagawa-Kanon",
+                            },
+                            OnlineInfo = new BeatmapOnlineInfo
+                            {
+                                Covers = new[] { @"https://assets.ppy.sh//beatmaps/39804/covers/cover.jpg?1456506845" },
+                            },
+                        }
                     },
-                    OnlineInfo = new BeatmapOnlineInfo
+                    MaxParticipants = { Value = 10 },
+                    Participants =
                     {
-                        Covers = new[] { @"https://assets.ppy.sh//beatmaps/39804/covers/cover.jpg?1456506845" },
-                    },
-                };
-                newRoom.MaxParticipants.Value = 10;
-                newRoom.Participants.Value = new[]
-                {
-                    new User { Username = @"Angelsim", Id = 1777162, GlobalRank = 4 },
-                    new User { Username = @"HappyStick", Id = 256802, GlobalRank = 752 },
-                    new User { Username = @"-Konpaku-", Id = 2258797, GlobalRank = 571 }
+                        Value = new[]
+                        {
+                            new User { Username = @"Angelsim", Id = 1777162, GlobalRank = 4 },
+                            new User { Username = @"HappyStick", Id = 256802, GlobalRank = 752 },
+                            new User { Username = @"-Konpaku-", Id = 2258797, GlobalRank = 571 }
+                        }
+                    }
                 };
 
                 inspector.Room = newRoom;

From f5829860a2241a767a5500de9b31637f19dc8554 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20M=C3=BCller?= <thomas94@gmx.net>
Date: Fri, 23 Jun 2017 18:02:24 +0200
Subject: [PATCH 14/20] Get rid of AlwaysReceiveInput

---
 osu-framework                                        |  2 +-
 .../Objects/Drawables/DrawableSlider.cs              |  4 ----
 .../Objects/Drawables/DrawableSpinner.cs             |  2 --
 .../Objects/Drawables/Pieces/SpinnerDisc.cs          |  3 ++-
 osu.Game/Graphics/Containers/ParallaxContainer.cs    |  2 --
 osu.Game/Graphics/Cursor/CursorTrail.cs              |  3 ++-
 osu.Game/Graphics/Processing/RatioAdjust.cs          |  1 -
 osu.Game/OsuGameBase.cs                              |  1 -
 .../Overlays/SearchableList/SearchableListOverlay.cs |  1 -
 osu.Game/Overlays/Toolbar/Toolbar.cs                 |  3 ---
 osu.Game/Overlays/Toolbar/ToolbarUserArea.cs         |  2 --
 osu.Game/Rulesets/UI/Playfield.cs                    | 12 ------------
 osu.Game/Screens/Play/KeyCounterCollection.cs        |  6 +++---
 osu.Game/Screens/Play/KeyCounterMouse.cs             |  4 +++-
 osu.Game/Screens/Play/MenuOverlay.cs                 |  1 -
 osu.Game/Screens/Play/SkipButton.cs                  |  2 --
 osu.Game/Screens/Select/FilterControl.cs             |  2 --
 17 files changed, 11 insertions(+), 40 deletions(-)

diff --git a/osu-framework b/osu-framework
index 97ff3376d1..6a81d52ba2 160000
--- a/osu-framework
+++ b/osu-framework
@@ -1 +1 @@
-Subproject commit 97ff3376d1bdac3703d442e62f5ee6a36eb3b73f
+Subproject commit 6a81d52ba24c4c4bcd83bf1062143ad93d8f4545
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
index b80f1d7178..395e496b61 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
@@ -28,10 +28,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
 
         public DrawableSlider(Slider s) : base(s)
         {
-            // Since the DrawableSlider itself is just a container without a size we need to
-            // pass all input through.
-            AlwaysReceiveInput = true;
-
             SliderBouncer bouncer1;
             slider = s;
 
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
index 3722d13ffc..840acb8221 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
@@ -38,8 +38,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
 
         public DrawableSpinner(Spinner s) : base(s)
         {
-            AlwaysReceiveInput = true;
-
             Origin = Anchor.Centre;
             Position = s.Position;
 
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs
index 29d6d1f147..86dfe8e95e 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs
@@ -31,7 +31,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
         {
             spinner = s;
 
-            AlwaysReceiveInput = true;
             RelativeSizeAxes = Axes.Both;
 
             Children = new Drawable[]
@@ -40,6 +39,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
             };
         }
 
+        protected override bool InternalContains(Vector2 screenSpacePos) => true;
+
         private bool tracking;
         public bool Tracking
         {
diff --git a/osu.Game/Graphics/Containers/ParallaxContainer.cs b/osu.Game/Graphics/Containers/ParallaxContainer.cs
index 2d5952a3ce..19475b00c9 100644
--- a/osu.Game/Graphics/Containers/ParallaxContainer.cs
+++ b/osu.Game/Graphics/Containers/ParallaxContainer.cs
@@ -19,8 +19,6 @@ namespace osu.Game.Graphics.Containers
 
         public ParallaxContainer()
         {
-            AlwaysReceiveInput = true;
-
             RelativeSizeAxes = Axes.Both;
             AddInternal(content = new Container
             {
diff --git a/osu.Game/Graphics/Cursor/CursorTrail.cs b/osu.Game/Graphics/Cursor/CursorTrail.cs
index 183679fbd3..d3386c2bbf 100644
--- a/osu.Game/Graphics/Cursor/CursorTrail.cs
+++ b/osu.Game/Graphics/Cursor/CursorTrail.cs
@@ -65,7 +65,6 @@ namespace osu.Game.Graphics.Cursor
             // as we are currently very dependent on having a running clock, let's make our own clock for the time being.
             Clock = new FramedClock();
 
-            AlwaysReceiveInput = true;
             RelativeSizeAxes = Axes.Both;
 
             for (int i = 0; i < max_sprites; i++)
@@ -75,6 +74,8 @@ namespace osu.Game.Graphics.Cursor
             }
         }
 
+        protected override bool InternalContains(Vector2 screenSpacePos) => true;
+
         [BackgroundDependencyLoader]
         private void load(ShaderManager shaders, TextureStore textures)
         {
diff --git a/osu.Game/Graphics/Processing/RatioAdjust.cs b/osu.Game/Graphics/Processing/RatioAdjust.cs
index dd039d5144..640814d8e1 100644
--- a/osu.Game/Graphics/Processing/RatioAdjust.cs
+++ b/osu.Game/Graphics/Processing/RatioAdjust.cs
@@ -12,7 +12,6 @@ namespace osu.Game.Graphics.Processing
     {
         public RatioAdjust()
         {
-            AlwaysReceiveInput = true;
             RelativeSizeAxes = Axes.Both;
         }
 
diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs
index 306cdaddf0..5e73ea55e6 100644
--- a/osu.Game/OsuGameBase.cs
+++ b/osu.Game/OsuGameBase.cs
@@ -152,7 +152,6 @@ namespace osu.Game
                 {
                     new Container
                     {
-                        AlwaysReceiveInput = true,
                         RelativeSizeAxes = Axes.Both,
                         Depth = float.MinValue,
                         Children = new Drawable[]
diff --git a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs
index 05ee38153d..25f6b4f60b 100644
--- a/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs
+++ b/osu.Game/Overlays/SearchableList/SearchableListOverlay.cs
@@ -82,7 +82,6 @@ namespace osu.Game.Overlays.SearchableList
                     RelativeSizeAxes = Axes.X,
                     AutoSizeAxes = Axes.Y,
                     Direction = FillDirection.Vertical,
-                    AlwaysReceiveInput = true,
                     Children = new Drawable[]
                     {
                         Header = CreateHeader(),
diff --git a/osu.Game/Overlays/Toolbar/Toolbar.cs b/osu.Game/Overlays/Toolbar/Toolbar.cs
index 16e4f22ec8..a7e5f8dcc4 100644
--- a/osu.Game/Overlays/Toolbar/Toolbar.cs
+++ b/osu.Game/Overlays/Toolbar/Toolbar.cs
@@ -33,8 +33,6 @@ namespace osu.Game.Overlays.Toolbar
 
         public Toolbar()
         {
-            AlwaysReceiveInput = true;
-
             Children = new Drawable[]
             {
                 new ToolbarBackground(),
@@ -55,7 +53,6 @@ namespace osu.Game.Overlays.Toolbar
                 },
                 new FillFlowContainer
                 {
-                    AlwaysReceiveInput = true,
                     Anchor = Anchor.TopRight,
                     Origin = Anchor.TopRight,
                     Direction = FillDirection.Horizontal,
diff --git a/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs b/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs
index 1928c0fc1f..c1fd234628 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarUserArea.cs
@@ -17,8 +17,6 @@ namespace osu.Game.Overlays.Toolbar
 
         public ToolbarUserArea()
         {
-            AlwaysReceiveInput = true;
-
             RelativeSizeAxes = Axes.Y;
             AutoSizeAxes = Axes.X;
 
diff --git a/osu.Game/Rulesets/UI/Playfield.cs b/osu.Game/Rulesets/UI/Playfield.cs
index 612569a9ae..ff321a18a5 100644
--- a/osu.Game/Rulesets/UI/Playfield.cs
+++ b/osu.Game/Rulesets/UI/Playfield.cs
@@ -37,8 +37,6 @@ namespace osu.Game.Rulesets.UI
         /// <param name="customWidth">Whether we want our internal coordinate system to be scaled to a specified width.</param>
         protected Playfield(float? customWidth = null)
         {
-            AlwaysReceiveInput = true;
-
             // Default height since we force relative size axes
             Size = Vector2.One;
 
@@ -50,7 +48,6 @@ namespace osu.Game.Rulesets.UI
                 {
                     content = new Container
                     {
-                        AlwaysReceiveInput = true,
                         RelativeSizeAxes = Axes.Both,
                     }
                 }
@@ -100,19 +97,10 @@ namespace osu.Game.Rulesets.UI
 
             //dividing by the customwidth will effectively scale our content to the required container size.
             protected override Vector2 DrawScale => CustomWidth.HasValue ? new Vector2(DrawSize.X / CustomWidth.Value) : base.DrawScale;
-
-            public ScaledContainer()
-            {
-                AlwaysReceiveInput = true;
-            }
         }
 
         public class HitObjectContainer<U> : Container<U> where U : Drawable
         {
-            public HitObjectContainer()
-            {
-                AlwaysReceiveInput = true;
-            }
         }
     }
 }
diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs
index 25cbfc14b7..8d70a0f1a9 100644
--- a/osu.Game/Screens/Play/KeyCounterCollection.cs
+++ b/osu.Game/Screens/Play/KeyCounterCollection.cs
@@ -9,6 +9,7 @@ using osu.Framework.Input;
 using osu.Framework.Configuration;
 using osu.Framework.Allocation;
 using osu.Game.Configuration;
+using OpenTK;
 
 namespace osu.Game.Screens.Play
 {
@@ -20,8 +21,6 @@ namespace osu.Game.Screens.Play
 
         public KeyCounterCollection()
         {
-            AlwaysReceiveInput = true;
-
             Direction = FillDirection.Horizontal;
             AutoSizeAxes = Axes.Both;
         }
@@ -124,11 +123,12 @@ namespace osu.Game.Screens.Play
 
             public Receptor(KeyCounterCollection target)
             {
-                AlwaysReceiveInput = true;
                 RelativeSizeAxes = Axes.Both;
                 this.target = target;
             }
 
+            protected override bool InternalContains(Vector2 screenSpacePos) => true;
+
             public override bool HandleInput => true;
 
             protected override bool OnKeyDown(InputState state, KeyDownEventArgs args) => target.Children.Any(c => c.TriggerOnKeyDown(state, args));
diff --git a/osu.Game/Screens/Play/KeyCounterMouse.cs b/osu.Game/Screens/Play/KeyCounterMouse.cs
index 744cb905d9..49d669aef9 100644
--- a/osu.Game/Screens/Play/KeyCounterMouse.cs
+++ b/osu.Game/Screens/Play/KeyCounterMouse.cs
@@ -3,6 +3,7 @@
 
 using osu.Framework.Input;
 using OpenTK.Input;
+using OpenTK;
 
 namespace osu.Game.Screens.Play
 {
@@ -12,10 +13,11 @@ namespace osu.Game.Screens.Play
 
         public KeyCounterMouse(MouseButton button) : base(getStringRepresentation(button))
         {
-            AlwaysReceiveInput = true;
             Button = button;
         }
 
+        protected override bool InternalContains(Vector2 screenSpacePos) => true;
+
         private static string getStringRepresentation(MouseButton button)
         {
             switch (button)
diff --git a/osu.Game/Screens/Play/MenuOverlay.cs b/osu.Game/Screens/Play/MenuOverlay.cs
index 1d557269c4..adfa1a736b 100644
--- a/osu.Game/Screens/Play/MenuOverlay.cs
+++ b/osu.Game/Screens/Play/MenuOverlay.cs
@@ -186,7 +186,6 @@ namespace osu.Game.Screens.Play
 
         protected MenuOverlay()
         {
-            AlwaysReceiveInput = true;
             RelativeSizeAxes = Axes.Both;
         }
 
diff --git a/osu.Game/Screens/Play/SkipButton.cs b/osu.Game/Screens/Play/SkipButton.cs
index d110f8ecac..b38a9b4934 100644
--- a/osu.Game/Screens/Play/SkipButton.cs
+++ b/osu.Game/Screens/Play/SkipButton.cs
@@ -34,8 +34,6 @@ namespace osu.Game.Screens.Play
 
         public SkipButton(double startTime)
         {
-            AlwaysReceiveInput = true;
-
             this.startTime = startTime;
 
             RelativePositionAxes = Axes.Both;
diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs
index 51937df189..531c78c17e 100644
--- a/osu.Game/Screens/Select/FilterControl.cs
+++ b/osu.Game/Screens/Select/FilterControl.cs
@@ -82,7 +82,6 @@ namespace osu.Game.Screens.Select
                 new Container
                 {
                     Padding = new MarginPadding(20),
-                    AlwaysReceiveInput = true,
                     RelativeSizeAxes = Axes.Both,
                     Width = 0.5f,
                     Anchor = Anchor.TopRight,
@@ -109,7 +108,6 @@ namespace osu.Game.Screens.Select
                             Direction = FillDirection.Horizontal,
                             RelativeSizeAxes = Axes.X,
                             AutoSizeAxes = Axes.Y,
-                            AlwaysReceiveInput = true,
                             Children = new Drawable[]
                             {
                                 groupTabs = new OsuTabControl<GroupMode>

From 817d2c3da1996fdc816a15b9329097c282b4e6e0 Mon Sep 17 00:00:00 2001
From: EVAST9919 <megaman9919@gmail.com>
Date: Fri, 23 Jun 2017 23:57:57 +0300
Subject: [PATCH 15/20] Fixed logo heartbeat playing even without beating

---
 osu.Game/Screens/Menu/OsuLogo.cs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs
index 78bcbc5c63..12b6b994d0 100644
--- a/osu.Game/Screens/Menu/OsuLogo.cs
+++ b/osu.Game/Screens/Menu/OsuLogo.cs
@@ -227,9 +227,6 @@ namespace osu.Game.Screens.Menu
         {
             base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes);
 
-            if (Hovering)
-                sampleBeat.Play();
-
             lastBeatIndex = beatIndex;
 
             var beatLength = timingPoint.BeatLength;
@@ -238,6 +235,9 @@ namespace osu.Game.Screens.Menu
 
             if (beatIndex < 0) return;
 
+            if (Hovering)
+                sampleBeat.Play();
+
             logoBeatContainer.ScaleTo(1 - 0.02f * amplitudeAdjust, beat_in_time, EasingTypes.Out);
             using (logoBeatContainer.BeginDelayedSequence(beat_in_time))
                 logoBeatContainer.ScaleTo(1, beatLength * 2, EasingTypes.OutQuint);

From e3489928b788e26ee7228f27f16d69291f3507c4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20M=C3=BCller?= <thomas94@gmx.net>
Date: Sat, 24 Jun 2017 09:21:08 +0200
Subject: [PATCH 16/20] Remove now obsolete InternalContains

---
 osu-framework                                                   | 2 +-
 osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs   | 2 +-
 osu.Game/Graphics/Cursor/CursorTrail.cs                         | 2 +-
 osu.Game/Graphics/UserInterface/BreadcrumbControl.cs            | 2 +-
 osu.Game/Graphics/UserInterface/DialogButton.cs                 | 2 +-
 osu.Game/Graphics/UserInterface/OsuTabControl.cs                | 2 +-
 osu.Game/Graphics/UserInterface/TwoLayerButton.cs               | 2 +-
 osu.Game/Overlays/ChatOverlay.cs                                | 2 +-
 osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs | 2 +-
 osu.Game/Screens/Menu/Button.cs                                 | 2 +-
 osu.Game/Screens/Menu/OsuLogo.cs                                | 2 +-
 osu.Game/Screens/Play/KeyCounterCollection.cs                   | 2 +-
 osu.Game/Screens/Play/KeyCounterMouse.cs                        | 2 +-
 osu.Game/Screens/Select/FilterControl.cs                        | 2 +-
 osu.Game/Screens/Select/Footer.cs                               | 2 +-
 osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs         | 2 +-
 16 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/osu-framework b/osu-framework
index 6a81d52ba2..f832f77c04 160000
--- a/osu-framework
+++ b/osu-framework
@@ -1 +1 @@
-Subproject commit 6a81d52ba24c4c4bcd83bf1062143ad93d8f4545
+Subproject commit f832f77c04dd2c64063763a4283831ff95854aab
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs
index 86dfe8e95e..234aa8d055 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs
@@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
             };
         }
 
-        protected override bool InternalContains(Vector2 screenSpacePos) => true;
+        public override bool Contains(Vector2 screenSpacePos) => true;
 
         private bool tracking;
         public bool Tracking
diff --git a/osu.Game/Graphics/Cursor/CursorTrail.cs b/osu.Game/Graphics/Cursor/CursorTrail.cs
index d3386c2bbf..bbebc7e1b1 100644
--- a/osu.Game/Graphics/Cursor/CursorTrail.cs
+++ b/osu.Game/Graphics/Cursor/CursorTrail.cs
@@ -74,7 +74,7 @@ namespace osu.Game.Graphics.Cursor
             }
         }
 
-        protected override bool InternalContains(Vector2 screenSpacePos) => true;
+        public override bool Contains(Vector2 screenSpacePos) => true;
 
         [BackgroundDependencyLoader]
         private void load(ShaderManager shaders, TextureStore textures)
diff --git a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs
index 8d113f4918..c284398240 100644
--- a/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs
+++ b/osu.Game/Graphics/UserInterface/BreadcrumbControl.cs
@@ -38,7 +38,7 @@ namespace osu.Game.Graphics.UserInterface
             public readonly TextAwesome Chevron;
 
             //don't allow clicking between transitions and don't make the chevron clickable
-            protected override bool InternalContains(Vector2 screenSpacePos) => Alpha == 1f && Text.Contains(screenSpacePos);
+            public override bool Contains(Vector2 screenSpacePos) => Alpha == 1f && Text.Contains(screenSpacePos);
             public override bool HandleInput => State == Visibility.Visible;
 
             private Visibility state;
diff --git a/osu.Game/Graphics/UserInterface/DialogButton.cs b/osu.Game/Graphics/UserInterface/DialogButton.cs
index 10c821e9bd..47f628f96c 100644
--- a/osu.Game/Graphics/UserInterface/DialogButton.cs
+++ b/osu.Game/Graphics/UserInterface/DialogButton.cs
@@ -93,7 +93,7 @@ namespace osu.Game.Graphics.UserInterface
 
         private bool didClick; // Used for making sure that the OnMouseDown animation can call instead of OnHoverLost's when clicking
 
-        protected override bool InternalContains(Vector2 screenSpacePos) => backgroundContainer.Contains(screenSpacePos);
+        public override bool Contains(Vector2 screenSpacePos) => backgroundContainer.Contains(screenSpacePos);
 
         protected override bool OnClick(Framework.Input.InputState state)
         {
diff --git a/osu.Game/Graphics/UserInterface/OsuTabControl.cs b/osu.Game/Graphics/UserInterface/OsuTabControl.cs
index 37bf30646d..c60a937440 100644
--- a/osu.Game/Graphics/UserInterface/OsuTabControl.cs
+++ b/osu.Game/Graphics/UserInterface/OsuTabControl.cs
@@ -23,7 +23,7 @@ namespace osu.Game.Graphics.UserInterface
 
         protected override TabItem<T> CreateTabItem(T value) => new OsuTabItem(value);
 
-        protected override bool InternalContains(Vector2 screenSpacePos) => base.InternalContains(screenSpacePos) || Dropdown.Contains(screenSpacePos);
+        public override bool Contains(Vector2 screenSpacePos) => base.Contains(screenSpacePos) || Dropdown.Contains(screenSpacePos);
 
         private bool isEnumType => typeof(T).IsEnum;
 
diff --git a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs
index b504c70be7..b188e782e2 100644
--- a/osu.Game/Graphics/UserInterface/TwoLayerButton.cs
+++ b/osu.Game/Graphics/UserInterface/TwoLayerButton.cs
@@ -171,7 +171,7 @@ namespace osu.Game.Graphics.UserInterface
             }
         }
 
-        protected override bool InternalContains(Vector2 screenSpacePos) => IconLayer.Contains(screenSpacePos) || TextLayer.Contains(screenSpacePos);
+        public override bool Contains(Vector2 screenSpacePos) => IconLayer.Contains(screenSpacePos) || TextLayer.Contains(screenSpacePos);
 
         protected override bool OnHover(InputState state)
         {
diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs
index 23b8aac6a7..97c7907874 100644
--- a/osu.Game/Overlays/ChatOverlay.cs
+++ b/osu.Game/Overlays/ChatOverlay.cs
@@ -59,7 +59,7 @@ namespace osu.Game.Overlays
         private readonly Container channelSelectionContainer;
         private readonly ChannelSelectionOverlay channelSelection;
 
-        protected override bool InternalContains(Vector2 screenSpacePos) => chatContainer.Contains(screenSpacePos) || channelSelection.State == Visibility.Visible && channelSelection.Contains(screenSpacePos);
+        public override bool Contains(Vector2 screenSpacePos) => chatContainer.Contains(screenSpacePos) || channelSelection.State == Visibility.Visible && channelSelection.Contains(screenSpacePos);
 
         public ChatOverlay()
         {
diff --git a/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs b/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs
index d5f7683257..b5ec70b9e2 100644
--- a/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs
+++ b/osu.Game/Overlays/SearchableList/SearchableListFilterControl.cs
@@ -29,7 +29,7 @@ namespace osu.Game.Overlays.SearchableList
         protected abstract T DefaultTab { get; }
         protected virtual Drawable CreateSupplementaryControls() => null;
 
-        protected override bool InternalContains(Vector2 screenSpacePos) => base.InternalContains(screenSpacePos) || DisplayStyleControl.Dropdown.Contains(screenSpacePos);
+        public override bool Contains(Vector2 screenSpacePos) => base.Contains(screenSpacePos) || DisplayStyleControl.Dropdown.Contains(screenSpacePos);
 
         protected SearchableListFilterControl()
         {
diff --git a/osu.Game/Screens/Menu/Button.cs b/osu.Game/Screens/Menu/Button.cs
index 19bb084af4..cdff79c94f 100644
--- a/osu.Game/Screens/Menu/Button.cs
+++ b/osu.Game/Screens/Menu/Button.cs
@@ -35,7 +35,7 @@ namespace osu.Game.Screens.Menu
         private readonly Key triggerKey;
         private SampleChannel sampleClick;
 
-        protected override bool InternalContains(Vector2 screenSpacePos) => box.Contains(screenSpacePos);
+        public override bool Contains(Vector2 screenSpacePos) => box.Contains(screenSpacePos);
 
         public Button(string text, string internalName, FontAwesome symbol, Color4 colour, Action clickAction = null, float extraWidth = 0, Key triggerKey = Key.Unknown)
         {
diff --git a/osu.Game/Screens/Menu/OsuLogo.cs b/osu.Game/Screens/Menu/OsuLogo.cs
index 78bcbc5c63..f6eaae01b3 100644
--- a/osu.Game/Screens/Menu/OsuLogo.cs
+++ b/osu.Game/Screens/Menu/OsuLogo.cs
@@ -57,7 +57,7 @@ namespace osu.Game.Screens.Menu
             set { colourAndTriangles.Alpha = value ? 1 : 0; }
         }
 
-        protected override bool InternalContains(Vector2 screenSpacePos) => logoContainer.Contains(screenSpacePos);
+        public override bool Contains(Vector2 screenSpacePos) => logoContainer.Contains(screenSpacePos);
 
         public bool Ripple
         {
diff --git a/osu.Game/Screens/Play/KeyCounterCollection.cs b/osu.Game/Screens/Play/KeyCounterCollection.cs
index 8d70a0f1a9..88522e23ab 100644
--- a/osu.Game/Screens/Play/KeyCounterCollection.cs
+++ b/osu.Game/Screens/Play/KeyCounterCollection.cs
@@ -127,7 +127,7 @@ namespace osu.Game.Screens.Play
                 this.target = target;
             }
 
-            protected override bool InternalContains(Vector2 screenSpacePos) => true;
+            public override bool Contains(Vector2 screenSpacePos) => true;
 
             public override bool HandleInput => true;
 
diff --git a/osu.Game/Screens/Play/KeyCounterMouse.cs b/osu.Game/Screens/Play/KeyCounterMouse.cs
index 49d669aef9..3f3b44aef9 100644
--- a/osu.Game/Screens/Play/KeyCounterMouse.cs
+++ b/osu.Game/Screens/Play/KeyCounterMouse.cs
@@ -16,7 +16,7 @@ namespace osu.Game.Screens.Play
             Button = button;
         }
 
-        protected override bool InternalContains(Vector2 screenSpacePos) => true;
+        public override bool Contains(Vector2 screenSpacePos) => true;
 
         private static string getStringRepresentation(MouseButton button)
         {
diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs
index 531c78c17e..6d732b58e4 100644
--- a/osu.Game/Screens/Select/FilterControl.cs
+++ b/osu.Game/Screens/Select/FilterControl.cs
@@ -67,7 +67,7 @@ namespace osu.Game.Screens.Select
 
         private readonly SearchTextBox searchTextBox;
 
-        protected override bool InternalContains(Vector2 screenSpacePos) => base.InternalContains(screenSpacePos) || groupTabs.Contains(screenSpacePos) || sortTabs.Contains(screenSpacePos);
+        public override bool Contains(Vector2 screenSpacePos) => base.Contains(screenSpacePos) || groupTabs.Contains(screenSpacePos) || sortTabs.Contains(screenSpacePos);
 
         public FilterControl()
         {
diff --git a/osu.Game/Screens/Select/Footer.cs b/osu.Game/Screens/Select/Footer.cs
index 882aa482da..613c666b92 100644
--- a/osu.Game/Screens/Select/Footer.cs
+++ b/osu.Game/Screens/Select/Footer.cs
@@ -124,7 +124,7 @@ namespace osu.Game.Screens.Select
             updateModeLight();
         }
 
-        protected override bool InternalContains(Vector2 screenSpacePos) => base.InternalContains(screenSpacePos) || StartButton.Contains(screenSpacePos);
+        public override bool Contains(Vector2 screenSpacePos) => base.Contains(screenSpacePos) || StartButton.Contains(screenSpacePos);
 
         protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true;
 
diff --git a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs
index db8ab439eb..942d3a6a32 100644
--- a/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs
+++ b/osu.Game/Screens/Select/Options/BeatmapOptionsButton.cs
@@ -83,7 +83,7 @@ namespace osu.Game.Screens.Select.Options
             return false;
         }
 
-        protected override bool InternalContains(Vector2 screenSpacePos) => box.Contains(screenSpacePos);
+        public override bool Contains(Vector2 screenSpacePos) => box.Contains(screenSpacePos);
 
         public BeatmapOptionsButton()
         {

From 494a77aa0d1c2d5918c99f53a1b229ca1d452bef Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20M=C3=BCller?= <thomas94@gmx.net>
Date: Sat, 24 Jun 2017 09:35:54 +0200
Subject: [PATCH 17/20] Update framework

---
 osu-framework | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/osu-framework b/osu-framework
index f832f77c04..2f7ebfcf63 160000
--- a/osu-framework
+++ b/osu-framework
@@ -1 +1 @@
-Subproject commit f832f77c04dd2c64063763a4283831ff95854aab
+Subproject commit 2f7ebfcf637cc1928d8d37f6336e5da77f4926a0

From 1bca9ca0e9e1345b4033bb847a8f6bfbf32f31f2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20M=C3=BCller?= <thomas94@gmx.net>
Date: Sat, 24 Jun 2017 12:56:35 +0200
Subject: [PATCH 18/20] Update framework with better children list

---
 osu.Game/Overlays/Chat/ChannelSection.cs          | 2 +-
 osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs | 2 +-
 osu.Game/Overlays/Dialog/PopupDialog.cs           | 2 +-
 osu.Game/Overlays/Direct/DirectPanel.cs           | 2 +-
 osu.Game/Overlays/DirectOverlay.cs                | 2 +-
 osu.Game/Overlays/SocialOverlay.cs                | 2 +-
 osu.Game/Screens/Multiplayer/RoomInspector.cs     | 2 +-
 osu.Game/Screens/Ranking/ResultsPageScore.cs      | 2 +-
 osu.Game/Screens/Select/BeatmapDetails.cs         | 2 +-
 9 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/osu.Game/Overlays/Chat/ChannelSection.cs b/osu.Game/Overlays/Chat/ChannelSection.cs
index f12ec53605..cafb88b6ac 100644
--- a/osu.Game/Overlays/Chat/ChannelSection.cs
+++ b/osu.Game/Overlays/Chat/ChannelSection.cs
@@ -35,7 +35,7 @@ namespace osu.Game.Overlays.Chat
 
         public IEnumerable<Channel> Channels
         {
-            set { ChannelFlow.Children = value.Select(c => new ChannelListItem(c)); }
+            set { ChannelFlow.ChildrenEnumerable = value.Select(c => new ChannelListItem(c)); }
         }
 
         public ChannelSection()
diff --git a/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs b/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs
index 6ff3cc7be5..7c10c4fb9b 100644
--- a/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs
+++ b/osu.Game/Overlays/Chat/ChannelSelectionOverlay.cs
@@ -38,7 +38,7 @@ namespace osu.Game.Overlays.Chat
         {
             set
             {
-                sectionsFlow.Children = value;
+                sectionsFlow.ChildrenEnumerable = value;
 
                 foreach (ChannelSection s in sectionsFlow.Children)
                 {
diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs
index c8ca50823f..5edb48e136 100644
--- a/osu.Game/Overlays/Dialog/PopupDialog.cs
+++ b/osu.Game/Overlays/Dialog/PopupDialog.cs
@@ -56,7 +56,7 @@ namespace osu.Game.Overlays.Dialog
             get { return buttonsContainer.Children; }
             set
             {
-                buttonsContainer.Children = value;
+                buttonsContainer.ChildrenEnumerable = value;
                 foreach (PopupDialogButton b in value)
                 {
                     var action = b.Action;
diff --git a/osu.Game/Overlays/Direct/DirectPanel.cs b/osu.Game/Overlays/Direct/DirectPanel.cs
index 8a56cf392e..f8acad1f59 100644
--- a/osu.Game/Overlays/Direct/DirectPanel.cs
+++ b/osu.Game/Overlays/Direct/DirectPanel.cs
@@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Direct
             SetInfo = setInfo;
         }
 
-        protected IEnumerable<DifficultyIcon> GetDifficultyIcons()
+        protected List<DifficultyIcon> GetDifficultyIcons()
         {
             var icons = new List<DifficultyIcon>();
 
diff --git a/osu.Game/Overlays/DirectOverlay.cs b/osu.Game/Overlays/DirectOverlay.cs
index 93c440384b..beb1355f36 100644
--- a/osu.Game/Overlays/DirectOverlay.cs
+++ b/osu.Game/Overlays/DirectOverlay.cs
@@ -129,7 +129,7 @@ namespace osu.Game.Overlays
         private void recreatePanels(PanelDisplayStyle displayStyle)
         {
             if (BeatmapSets == null) return;
-            panels.Children = BeatmapSets.Select(b => displayStyle == PanelDisplayStyle.Grid ? (DirectPanel)new DirectGridPanel(b) { Width = 400 } : new DirectListPanel(b));
+            panels.ChildrenEnumerable = BeatmapSets.Select(b => displayStyle == PanelDisplayStyle.Grid ? (DirectPanel)new DirectGridPanel(b) { Width = 400 } : new DirectListPanel(b));
         }
 
         public class ResultCounts
diff --git a/osu.Game/Overlays/SocialOverlay.cs b/osu.Game/Overlays/SocialOverlay.cs
index c6ce20f5cf..1cd2343848 100644
--- a/osu.Game/Overlays/SocialOverlay.cs
+++ b/osu.Game/Overlays/SocialOverlay.cs
@@ -44,7 +44,7 @@ namespace osu.Game.Overlays
                     panelFlow.Clear();
                 else
                 {
-                    panelFlow.Children = users.Select(u =>
+                    panelFlow.ChildrenEnumerable = users.Select(u =>
                     {
                         var p = new UserPanel(u) { Width = 300 };
                         p.Status.BindTo(u.Status);
diff --git a/osu.Game/Screens/Multiplayer/RoomInspector.cs b/osu.Game/Screens/Multiplayer/RoomInspector.cs
index 2181f37be9..f9e015eceb 100644
--- a/osu.Game/Screens/Multiplayer/RoomInspector.cs
+++ b/osu.Game/Screens/Multiplayer/RoomInspector.cs
@@ -495,7 +495,7 @@ namespace osu.Game.Screens.Multiplayer
             levelRangeLower.Text = ranks.Min().ToString();
             levelRangeHigher.Text = ranks.Max().ToString();
 
-            participantsFlow.Children = value.Select(u => new UserTile(u));
+            participantsFlow.ChildrenEnumerable = value.Select(u => new UserTile(u));
         }
 
         private class UserTile : Container, IHasTooltip
diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs
index ac333e47ff..15e8e4bfcd 100644
--- a/osu.Game/Screens/Ranking/ResultsPageScore.cs
+++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs
@@ -164,7 +164,7 @@ namespace osu.Game.Screens.Ranking
                 }
             };
 
-            statisticsContainer.Children = Score.Statistics.Select(s => new DrawableScoreStatistic(s));
+            statisticsContainer.ChildrenEnumerable = Score.Statistics.Select(s => new DrawableScoreStatistic(s));
         }
 
         protected override void LoadComplete()
diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs
index daf28c8f1b..481637e2af 100644
--- a/osu.Game/Screens/Select/BeatmapDetails.cs
+++ b/osu.Game/Screens/Select/BeatmapDetails.cs
@@ -439,7 +439,7 @@ namespace osu.Game.Screens.Select
                     {
                         Show();
                         if (header.Text == "Tags")
-                            content.Children = value.Split(' ').Select(text => new OsuSpriteText
+                            content.ChildrenEnumerable = value.Split(' ').Select(text => new OsuSpriteText
                             {
                                 Text = text,
                                 Font = "Exo2.0-Regular",

From 63aeb42657dc0084cd9a417e8356246e0599629c Mon Sep 17 00:00:00 2001
From: Dean Herbert <pe@ppy.sh>
Date: Sun, 25 Jun 2017 14:38:00 +0900
Subject: [PATCH 19/20] Update framework

---
 osu-framework | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/osu-framework b/osu-framework
index 2f7ebfcf63..a5e66079b9 160000
--- a/osu-framework
+++ b/osu-framework
@@ -1 +1 @@
-Subproject commit 2f7ebfcf637cc1928d8d37f6336e5da77f4926a0
+Subproject commit a5e66079b9df3cf74a8bd1431c1cb7faad3c4d9f

From 7baa2b742175286c6c70b254c8540efab23b2bba Mon Sep 17 00:00:00 2001
From: Dean Herbert <pe@ppy.sh>
Date: Sun, 25 Jun 2017 14:46:59 +0900
Subject: [PATCH 20/20] Fix CI issues

---
 osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs    | 2 +-
 osu.Game/Graphics/UserInterface/BarGraph.cs                  | 2 +-
 osu.Game/Overlays/OnScreenDisplay.cs                         | 5 ++---
 .../Screens/Tournament/Components/VisualiserContainer.cs     | 2 +-
 4 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
index 395e496b61..c6c009e8f2 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
@@ -125,7 +125,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
         {
             if (!userTriggered && Time.Current >= slider.EndTime)
             {
-                var ticksCount = ticks.Children.Count() + 1;
+                var ticksCount = ticks.Children.Count + 1;
                 var ticksHit = ticks.Children.Count(t => t.Judgement.Result == HitResult.Hit);
                 if (initialCircle.Judgement.Result == HitResult.Hit)
                     ticksHit++;
diff --git a/osu.Game/Graphics/UserInterface/BarGraph.cs b/osu.Game/Graphics/UserInterface/BarGraph.cs
index d0965a1861..e4a471bbba 100644
--- a/osu.Game/Graphics/UserInterface/BarGraph.cs
+++ b/osu.Game/Graphics/UserInterface/BarGraph.cs
@@ -29,7 +29,7 @@ namespace osu.Game.Graphics.UserInterface
                 base.Direction = (direction & BarDirection.Horizontal) > 0 ? FillDirection.Vertical : FillDirection.Horizontal;
                 foreach (var bar in Children)
                 {
-                    bar.Size = (direction & BarDirection.Horizontal) > 0 ? new Vector2(1, 1.0f / Children.Count()) : new Vector2(1.0f / Children.Count(), 1);
+                    bar.Size = (direction & BarDirection.Horizontal) > 0 ? new Vector2(1, 1.0f / Children.Count) : new Vector2(1.0f / Children.Count, 1);
                     bar.Direction = direction;
                 }
             }
diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs
index 2887d4355b..4a616a8685 100644
--- a/osu.Game/Overlays/OnScreenDisplay.cs
+++ b/osu.Game/Overlays/OnScreenDisplay.cs
@@ -3,7 +3,6 @@
 
 using System;
 using System.Collections.Generic;
-using System.Linq;
 using osu.Framework.Allocation;
 using osu.Framework.Configuration;
 using osu.Framework.Extensions;
@@ -182,7 +181,7 @@ namespace osu.Game.Overlays
                 textLine2.Origin = optionCount > 0 ? Anchor.BottomCentre : Anchor.Centre;
                 textLine2.Y = optionCount > 0 ? 0 : 5;
 
-                if (optionLights.Children.Count() != optionCount)
+                if (optionLights.Children.Count != optionCount)
                 {
                     optionLights.Clear();
                     for (int i = 0; i < optionCount; i++)
@@ -190,7 +189,7 @@ namespace osu.Game.Overlays
                 }
 
                 for (int i = 0; i < optionCount; i++)
-                    optionLights.Children.Skip(i).First().Glowing = i == selectedOption;
+                    optionLights.Children[i].Glowing = i == selectedOption;
             });
         }
 
diff --git a/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs b/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs
index 373934f775..3dd7207607 100644
--- a/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs
+++ b/osu.Game/Screens/Tournament/Components/VisualiserContainer.cs
@@ -84,7 +84,7 @@ namespace osu.Game.Screens.Tournament.Components
             {
                 base.UpdateAfterChildren();
 
-                while (Children.Count() < 3)
+                while (Children.Count < 3)
                     addLine();
 
                 float pos = leftPos;