diff --git a/osu.Game/Overlays/Mods/ModButton.cs b/osu.Game/Overlays/Mods/ModButton.cs
index e3d26cba06..b07bb7d2fb 100644
--- a/osu.Game/Overlays/Mods/ModButton.cs
+++ b/osu.Game/Overlays/Mods/ModButton.cs
@@ -19,7 +19,11 @@ using System.Linq;
namespace osu.Game.Overlays.Mods
{
- public class ModButton : FillFlowContainer
+
+ ///
+ /// Represents a clickable button which can cycle through one of more mods.
+ ///
+ public class ModButton : ModButtonEmpty
{
private ModIcon foregroundIcon { get; set; }
private readonly SpriteText text;
@@ -116,7 +120,7 @@ namespace osu.Game.Overlays.Mods
// the mods from Mod, only multiple if Mod is a MultiMod
- public Mod SelectedMod => Mods.ElementAtOrDefault(selectedIndex);
+ public override Mod SelectedMod => Mods.ElementAtOrDefault(selectedIndex);
[BackgroundDependencyLoader]
private void load(AudioManager audio)
@@ -198,13 +202,8 @@ namespace osu.Game.Overlays.Mods
buttonColour = foregroundIcon.Colour;
}
- public ModButton(Mod m)
+ public ModButton(Mod mod)
{
- Direction = FillDirection.Vertical;
- Spacing = new Vector2(0f, -5f);
- Size = new Vector2(100f);
- AlwaysPresent = true;
-
Children = new Drawable[]
{
new Container
@@ -224,13 +223,14 @@ namespace osu.Game.Overlays.Mods
},
text = new OsuSpriteText
{
+ Y = 75,
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
TextSize = 18,
},
};
- Mod = m;
+ Mod = mod;
}
}
}
diff --git a/osu.Game/Overlays/Mods/ModButtonEmpty.cs b/osu.Game/Overlays/Mods/ModButtonEmpty.cs
new file mode 100644
index 0000000000..638c2a0e47
--- /dev/null
+++ b/osu.Game/Overlays/Mods/ModButtonEmpty.cs
@@ -0,0 +1,23 @@
+// Copyright (c) 2007-2017 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using OpenTK;
+using osu.Framework.Graphics.Containers;
+using osu.Game.Rulesets.Mods;
+
+namespace osu.Game.Overlays.Mods
+{
+ ///
+ /// A mod button used exclusively for providing an empty space the size of a mod button.
+ ///
+ public class ModButtonEmpty : Container
+ {
+ public virtual Mod SelectedMod => null;
+
+ public ModButtonEmpty()
+ {
+ Size = new Vector2(100f);
+ AlwaysPresent = true;
+ }
+ }
+}
diff --git a/osu.Game/Overlays/Mods/ModSection.cs b/osu.Game/Overlays/Mods/ModSection.cs
index b70323fb63..40bd1e8b07 100644
--- a/osu.Game/Overlays/Mods/ModSection.cs
+++ b/osu.Game/Overlays/Mods/ModSection.cs
@@ -11,6 +11,8 @@ using osu.Framework.Input;
using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Mods;
using System;
+using System.Linq;
+using System.Collections.Generic;
namespace osu.Game.Overlays.Mods
{
@@ -18,7 +20,7 @@ namespace osu.Game.Overlays.Mods
{
private readonly OsuSpriteText headerLabel;
- public FillFlowContainer ButtonsContainer { get; }
+ public FillFlowContainer ButtonsContainer { get; }
public Action Action;
protected abstract Key[] ToggleKeys { get; }
@@ -36,28 +38,31 @@ namespace osu.Game.Overlays.Mods
}
}
- private ModButton[] buttons = { };
- public ModButton[] Buttons
+ public IEnumerable SelectedMods => buttons.Select(b => b.SelectedMod).Where(m => m != null);
+
+ public IEnumerable Mods
{
- get
- {
- return buttons;
- }
set
{
- if (value == buttons) return;
- buttons = value;
-
- foreach (ModButton button in value)
+ var modContainers = value.Select(m =>
{
- button.SelectedColour = selectedColour;
- button.Action = Action;
- }
+ if (m == null)
+ return new ModButtonEmpty();
+ else
+ return new ModButton(m)
+ {
+ SelectedColour = selectedColour,
+ Action = Action,
+ };
+ }).ToArray();
- ButtonsContainer.Children = value;
+ ButtonsContainer.Children = modContainers;
+ buttons = modContainers.OfType().ToArray();
}
}
+ private ModButton[] buttons = { };
+
private Color4 selectedColour = Color4.White;
public Color4 SelectedColour
{
@@ -71,17 +76,15 @@ namespace osu.Game.Overlays.Mods
selectedColour = value;
foreach (ModButton button in buttons)
- {
button.SelectedColour = value;
- }
}
}
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
{
var index = Array.IndexOf(ToggleKeys, args.Key);
- if (index > -1 && index < Buttons.Length)
- Buttons[index].SelectNext();
+ if (index > -1 && index < buttons.Length)
+ buttons[index].SelectNext();
return base.OnKeyDown(state, args);
}
@@ -89,8 +92,18 @@ namespace osu.Game.Overlays.Mods
public void DeselectAll()
{
foreach (ModButton button in buttons)
- {
button.Deselect();
+ }
+
+ public void DeselectTypes(Type[] modTypes)
+ {
+ foreach (var button in buttons)
+ {
+ Mod selected = button.SelectedMod;
+ if (selected == null) continue;
+ foreach (Type type in modTypes)
+ if (type.IsInstanceOfType(selected))
+ button.Deselect();
}
}
@@ -107,7 +120,7 @@ namespace osu.Game.Overlays.Mods
Position = new Vector2(0f, 0f),
Font = @"Exo2.0-Bold"
},
- ButtonsContainer = new FillFlowContainer
+ ButtonsContainer = new FillFlowContainer
{
AutoSizeAxes = Axes.Both,
Origin = Anchor.BottomLeft,
diff --git a/osu.Game/Overlays/Mods/ModSelectOverlay.cs b/osu.Game/Overlays/Mods/ModSelectOverlay.cs
index dadfb808f7..2840ffd1e4 100644
--- a/osu.Game/Overlays/Mods/ModSelectOverlay.cs
+++ b/osu.Game/Overlays/Mods/ModSelectOverlay.cs
@@ -44,7 +44,7 @@ namespace osu.Game.Overlays.Mods
var instance = newRuleset.CreateInstance();
foreach (ModSection section in modSectionsContainer.Children)
- section.Buttons = instance.GetModsFor(section.ModType).Select(m => new ModButton(m)).ToArray();
+ section.Mods = instance.GetModsFor(section.ModType);
refreshSelectedMods();
}
@@ -103,14 +103,7 @@ namespace osu.Game.Overlays.Mods
{
if (modTypes.Length == 0) return;
foreach (ModSection section in modSectionsContainer.Children)
- foreach (ModButton button in section.Buttons)
- {
- Mod selected = button.SelectedMod;
- if (selected == null) continue;
- foreach (Type type in modTypes)
- if (type.IsInstanceOfType(selected))
- button.Deselect();
- }
+ section.DeselectTypes(modTypes);
}
private void modButtonPressed(Mod selectedMod)
@@ -122,7 +115,7 @@ namespace osu.Game.Overlays.Mods
private void refreshSelectedMods()
{
- SelectedMods.Value = modSectionsContainer.Children.SelectMany(s => s.Buttons.Select(x => x.SelectedMod).Where(x => x != null)).ToArray();
+ SelectedMods.Value = modSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray();
double multiplier = 1.0;
bool ranked = true;
diff --git a/osu.Game/Rulesets/UI/ModIcon.cs b/osu.Game/Rulesets/UI/ModIcon.cs
index 19efdb0175..497c71f0d5 100644
--- a/osu.Game/Rulesets/UI/ModIcon.cs
+++ b/osu.Game/Rulesets/UI/ModIcon.cs
@@ -1,6 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd .
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+using System;
using OpenTK.Graphics;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@@ -42,6 +43,8 @@ namespace osu.Game.Rulesets.UI
public ModIcon(Mod mod)
{
+ if (mod == null) throw new ArgumentNullException(nameof(mod));
+
Children = new Drawable[]
{
background = new TextAwesome
@@ -59,7 +62,7 @@ namespace osu.Game.Rulesets.UI
Anchor = Anchor.Centre,
Colour = OsuColour.Gray(84),
TextSize = 20,
- Icon = (mod != null) ? mod.Icon : FontAwesome.fa_question,
+ Icon = mod.Icon
},
};
@@ -74,7 +77,7 @@ namespace osu.Game.Rulesets.UI
private Color4 getBackgroundColourFromMod(Mod mod)
{
- switch (mod?.Type)
+ switch (mod.Type)
{
case ModType.DifficultyIncrease:
return OsuColour.FromHex(@"ffcc22");
@@ -87,4 +90,4 @@ namespace osu.Game.Rulesets.UI
}
}
}
-}
\ No newline at end of file
+}
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 98f9a8a52b..c06ba0b1ea 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -391,6 +391,7 @@
+