diff --git a/.vscode/launch.json b/.vscode/launch.json
index b8c026d891..d17dc33669 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -1,7 +1,7 @@
{
"version": "0.2.0",
"configurations": [{
- "name": "osu! (VisualTests)",
+ "name": "osu! VisualTests (Debug)",
"windows": {
"type": "clr"
},
@@ -18,7 +18,24 @@
"console": "internalConsole"
},
{
- "name": "osu! (debug)",
+ "name": "osu! VisualTests (Release)",
+ "windows": {
+ "type": "clr"
+ },
+ "type": "mono",
+ "request": "launch",
+ "program": "${workspaceRoot}/osu.Game/bin/Release/osu!.exe",
+ "args": [
+ "--tests"
+ ],
+ "cwd": "${workspaceRoot}",
+ "preLaunchTask": "Build (Release)",
+ "runtimeExecutable": null,
+ "env": {},
+ "console": "internalConsole"
+ },
+ {
+ "name": "osu! (Debug)",
"windows": {
"type": "clr"
},
@@ -32,7 +49,7 @@
"console": "internalConsole"
},
{
- "name": "osu! (release)",
+ "name": "osu! (Release)",
"windows": {
"type": "clr"
},
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 3db43ca9bb..35bf9e7a0e 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -23,6 +23,7 @@
},
{
"taskName": "Build (Release)",
+ "group": "build",
"args": [
"/property:Configuration=Release"
],
diff --git a/osu-framework b/osu-framework
index ef889b4ec7..07e84f60b0 160000
--- a/osu-framework
+++ b/osu-framework
@@ -1 +1 @@
-Subproject commit ef889b4ec7e6175d52d64411c15f4f195fd16209
+Subproject commit 07e84f60b0d2ee443f366cb2e34bf25b680983dd
diff --git a/osu.Game.Rulesets.Mania/Testing/TestCaseManiaHitObjects.cs b/osu.Game.Rulesets.Mania/Tests/TestCaseManiaHitObjects.cs
similarity index 96%
rename from osu.Game.Rulesets.Mania/Testing/TestCaseManiaHitObjects.cs
rename to osu.Game.Rulesets.Mania/Tests/TestCaseManiaHitObjects.cs
index a5568b7f6d..4230171288 100644
--- a/osu.Game.Rulesets.Mania/Testing/TestCaseManiaHitObjects.cs
+++ b/osu.Game.Rulesets.Mania/Tests/TestCaseManiaHitObjects.cs
@@ -10,7 +10,7 @@ using osu.Game.Tests.Visual;
using OpenTK;
using OpenTK.Graphics;
-namespace osu.Game.Rulesets.Mania.Testing
+namespace osu.Game.Rulesets.Mania.Tests
{
[TestFixture]
internal class TestCaseManiaHitObjects : OsuTestCase
diff --git a/osu.Game.Rulesets.Mania/Testing/TestCaseManiaPlayfield.cs b/osu.Game.Rulesets.Mania/Tests/TestCaseManiaPlayfield.cs
similarity index 96%
rename from osu.Game.Rulesets.Mania/Testing/TestCaseManiaPlayfield.cs
rename to osu.Game.Rulesets.Mania/Tests/TestCaseManiaPlayfield.cs
index 4b68334efb..c1de273a1b 100644
--- a/osu.Game.Rulesets.Mania/Testing/TestCaseManiaPlayfield.cs
+++ b/osu.Game.Rulesets.Mania/Tests/TestCaseManiaPlayfield.cs
@@ -17,7 +17,7 @@ using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Timing;
using osu.Game.Tests.Visual;
-namespace osu.Game.Rulesets.Mania.Testing
+namespace osu.Game.Rulesets.Mania.Tests
{
[TestFixture]
internal class TestCaseManiaPlayfield : OsuTestCase
diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj
index fa8b9d35aa..967f23bfd3 100644
--- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj
+++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj
@@ -80,8 +80,8 @@
-
-
+
+
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs
index 53b3427fc4..8a96640b1e 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs
@@ -22,6 +22,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
public override bool RemoveWhenNotAlive => false;
+ public override bool DisplayJudgement => false;
+
public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick)
{
this.sliderTick = sliderTick;
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
index 98dd40b0e6..054a2067ec 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
@@ -22,6 +22,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
private readonly SpinnerDisc disc;
private readonly SpinnerTicks ticks;
+ private readonly SpinnerSpmCounter spmCounter;
private readonly Container mainContainer;
@@ -103,6 +104,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
},
}
},
+ spmCounter = new SpinnerSpmCounter
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ Y = 120,
+ Alpha = 0
+ }
};
}
@@ -157,6 +165,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
protected override void Update()
{
disc.Tracking = OsuActionInputManager.PressedActions.Any(x => x == OsuAction.LeftButton || x == OsuAction.RightButton);
+ if (!spmCounter.IsPresent && disc.Tracking)
+ spmCounter.FadeIn(TIME_FADEIN);
base.Update();
}
@@ -167,6 +177,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
circle.Rotation = disc.Rotation;
ticks.Rotation = disc.Rotation;
+ spmCounter.SetRotation(disc.RotationAbsolute);
float relativeCircleScale = spinner.Scale * circle.DrawHeight / mainContainer.DrawHeight;
disc.ScaleTo(relativeCircleScale + (1 - relativeCircleScale) * Progress, 200, Easing.OutQuint);
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs
index 6577c7fd50..ca75a61738 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerDisc.cs
@@ -77,7 +77,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
private float lastAngle;
private float currentRotation;
public float RotationAbsolute;
-
private int completeTick;
private bool updateCompleteTick() => completeTick != (completeTick = (int)(RotationAbsolute / 360));
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs
new file mode 100644
index 0000000000..c079d3343b
--- /dev/null
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SpinnerSpmCounter.cs
@@ -0,0 +1,75 @@
+// Copyright (c) 2007-2017 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System;
+using System.Collections.Generic;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Game.Graphics.Sprites;
+
+namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
+{
+ public class SpinnerSpmCounter : Container
+ {
+ private readonly OsuSpriteText spmText;
+
+ public SpinnerSpmCounter()
+ {
+ Children = new Drawable[]
+ {
+ spmText = new OsuSpriteText
+ {
+ Anchor = Anchor.TopCentre,
+ Origin = Anchor.TopCentre,
+ Text = @"0",
+ Font = @"Venera",
+ TextSize = 24
+ },
+ new OsuSpriteText
+ {
+ Anchor = Anchor.TopCentre,
+ Origin = Anchor.TopCentre,
+ Text = @"SPINS PER MINUTE",
+ Font = @"Venera",
+ TextSize = 12,
+ Y = 30
+ }
+ };
+ }
+
+ private double spm;
+
+ public double SpinsPerMinute
+ {
+ get { return spm; }
+ private set
+ {
+ if (value == spm) return;
+ spm = value;
+ spmText.Text = Math.Truncate(value).ToString(@"#0");
+ }
+ }
+
+ private struct RotationRecord
+ {
+ public float Rotation;
+ public double Time;
+ }
+
+ private readonly Queue records = new Queue();
+ private const double spm_count_duration = 595; // not using hundreds to avoid frame rounding issues
+
+ public void SetRotation(float currentRotation)
+ {
+ if (records.Count > 0)
+ {
+ var record = records.Peek();
+ while (Time.Current - records.Peek().Time > spm_count_duration)
+ record = records.Dequeue();
+ SpinsPerMinute = (currentRotation - record.Rotation) / (Time.Current - record.Time) * 1000 * 60 / 360;
+ }
+
+ records.Enqueue(new RotationRecord { Rotation = currentRotation, Time = Time.Current });
+ }
+ }
+}
diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs
index 1bb4e8493b..89f6a4e255 100644
--- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs
+++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs
@@ -91,6 +91,9 @@ namespace osu.Game.Rulesets.Osu.UI
var osuJudgement = (OsuJudgement)judgement;
var osuObject = (OsuHitObject)judgedObject.HitObject;
+ if (!judgedObject.DisplayJudgement)
+ return;
+
DrawableOsuJudgement explosion = new DrawableOsuJudgement(osuJudgement)
{
Origin = Anchor.Centre,
diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
index 300000754c..6bad45b8ca 100644
--- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
+++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
@@ -68,6 +68,7 @@
+
diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs
index 8ac67ba0a6..e662f61bbe 100644
--- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs
+++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs
@@ -21,6 +21,8 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
FillMode = FillMode.Fit;
}
+ public override bool DisplayJudgement => false;
+
protected override void LoadComplete()
{
base.LoadComplete();
diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs
index d9a216bbfc..136da8a532 100644
--- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs
+++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs
@@ -221,7 +221,7 @@ namespace osu.Game.Rulesets.Taiko.UI
public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement)
{
- if (judgementContainer.FirstOrDefault(j => j.JudgedObject == judgedObject) == null)
+ if (judgedObject.DisplayJudgement && judgementContainer.FirstOrDefault(j => j.JudgedObject == judgedObject) == null)
{
judgementContainer.Add(new DrawableTaikoJudgement(judgedObject, judgement)
{
diff --git a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs
index 35bebf2d4f..cd9e765e7f 100644
--- a/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs
+++ b/osu.Game.Tests/Beatmaps/IO/ImportBeatmapTest.cs
@@ -117,18 +117,27 @@ namespace osu.Game.Tests.Beatmaps.IO
//ensure we were stored to beatmap database backing...
Assert.IsTrue(resultSets.Count() == 1, $@"Incorrect result count found ({resultSets.Count()} but should be 1).");
- IEnumerable resultBeatmaps = null;
+ Func> queryBeatmaps = () => store.QueryBeatmaps(s => s.OnlineBeatmapSetID == 241526 && s.BaseDifficultyID > 0);
+ Func> queryBeatmapSets = () => store.QueryBeatmapSets(s => s.OnlineBeatmapSetID == 241526);
//if we don't re-check here, the set will be inserted but the beatmaps won't be present yet.
- waitForOrAssert(() => (resultBeatmaps = store.QueryBeatmaps(s => s.OnlineBeatmapSetID == 241526 && s.BaseDifficultyID > 0)).Count() == 12,
+ waitForOrAssert(() => queryBeatmaps().Count() == 12,
@"Beatmaps did not import to the database in allocated time", timeout);
- var set = store.QueryBeatmapSets(s => s.OnlineBeatmapSetID == 241526).First();
+ waitForOrAssert(() => queryBeatmapSets().Count() == 1,
+ @"BeatmapSet did not import to the database in allocated time", timeout);
- Assert.IsTrue(set.Beatmaps.Count == resultBeatmaps.Count(),
- $@"Incorrect database beatmap count post-import ({resultBeatmaps.Count()} but should be {set.Beatmaps.Count}).");
+ int countBeatmapSetBeatmaps = 0;
+ int countBeatmaps = 0;
- foreach (BeatmapInfo b in resultBeatmaps)
+ waitForOrAssert(() =>
+ (countBeatmapSetBeatmaps = queryBeatmapSets().First().Beatmaps.Count) ==
+ (countBeatmaps = queryBeatmaps().Count()),
+ $@"Incorrect database beatmap count post-import ({countBeatmaps} but should be {countBeatmapSetBeatmaps}).", timeout);
+
+ var set = queryBeatmapSets().First();
+
+ foreach (BeatmapInfo b in set.Beatmaps)
Assert.IsTrue(set.Beatmaps.Any(c => c.OnlineBeatmapID == b.OnlineBeatmapID));
Assert.IsTrue(set.Beatmaps.Count > 0);
diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs
index a1b678392b..ce07b61ee4 100644
--- a/osu.Game/Beatmaps/BeatmapManager.cs
+++ b/osu.Game/Beatmaps/BeatmapManager.cs
@@ -550,7 +550,7 @@ namespace osu.Game.Beatmaps
catch { return null; }
}
- private string getPathForFile(string filename) => BeatmapSetInfo.Files.First(f => f.Filename == filename).FileInfo.StoragePath;
+ private string getPathForFile(string filename) => BeatmapSetInfo.Files.First(f => string.Equals(f.Filename, filename, StringComparison.InvariantCultureIgnoreCase)).FileInfo.StoragePath;
protected override Texture GetBackground()
{
diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs
index 353959582b..2493dab08c 100644
--- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs
+++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs
@@ -611,9 +611,9 @@ namespace osu.Game.Beatmaps.Formats
CommandTimelineGroup timelineGroup = null;
string line;
- while ((line = stream.ReadLine()?.Trim()) != null)
+ while ((line = stream.ReadLine()) != null)
{
- if (string.IsNullOrEmpty(line))
+ if (string.IsNullOrWhiteSpace(line))
continue;
if (line.StartsWith("//"))
@@ -679,10 +679,12 @@ namespace osu.Game.Beatmaps.Formats
private KeyValuePair splitKeyVal(string line, char separator)
{
+ var split = line.Trim().Split(new[] { separator }, 2);
+
return new KeyValuePair
(
- line.Remove(line.IndexOf(separator)).Trim(),
- line.Substring(line.IndexOf(separator) + 1).Trim()
+ split[0].Trim(),
+ split.Length > 1 ? split[1].Trim() : string.Empty
);
}
diff --git a/osu.Game/Graphics/UserInterface/IconButton.cs b/osu.Game/Graphics/UserInterface/IconButton.cs
index 1808dc4b6c..d58f5797a3 100644
--- a/osu.Game/Graphics/UserInterface/IconButton.cs
+++ b/osu.Game/Graphics/UserInterface/IconButton.cs
@@ -15,32 +15,76 @@ namespace osu.Game.Graphics.UserInterface
{
public class IconButton : OsuClickableContainer
{
- private readonly SpriteIcon icon;
- private readonly Box hover;
- private readonly Container content;
+ private const float button_size = 30;
+ private Color4? flashColour;
+ ///
+ /// The colour that should be flashed when the is clicked.
+ ///
+ public Color4 FlashColour
+ {
+ get { return flashColour ?? Color4.White; }
+ set { flashColour = value; }
+ }
+
+ ///
+ /// The icon colour. This does not affect .
+ ///
+ public Color4 IconColour
+ {
+ get { return icon.Colour; }
+ set { icon.Colour = value; }
+ }
+
+ private Color4? hoverColour;
+ ///
+ /// The background colour of the while it is hovered.
+ ///
+ public Color4 HoverColour
+ {
+ get { return hoverColour ?? Color4.White; }
+ set
+ {
+ hoverColour = value;
+ hover.Colour = value;
+ }
+ }
+
+ ///
+ /// The icon.
+ ///
public FontAwesome Icon
{
get { return icon.Icon; }
set { icon.Icon = value; }
}
- private const float button_size = 30;
- private Color4 flashColour;
-
+ ///
+ /// The icon scale. This does not affect .
+ ///
public Vector2 IconScale
{
get { return icon.Scale; }
set { icon.Scale = value; }
}
+ ///
+ /// The size of the while it is not being pressed.
+ ///
+ public Vector2 ButtonSize
+ {
+ get { return content.Size; }
+ set { content.Size = value; }
+ }
+
+ private readonly Container content;
+ private readonly SpriteIcon icon;
+ private readonly Box hover;
+
public IconButton()
{
AutoSizeAxes = Axes.Both;
- Origin = Anchor.Centre;
- Anchor = Anchor.Centre;
-
Children = new Drawable[]
{
content = new Container
@@ -48,7 +92,6 @@ namespace osu.Game.Graphics.UserInterface
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Size = new Vector2(button_size),
-
CornerRadius = 5,
Masking = true,
EdgeEffect = new EdgeEffectParameters
@@ -78,8 +121,11 @@ namespace osu.Game.Graphics.UserInterface
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
- hover.Colour = colours.Yellow.Opacity(0.6f);
- flashColour = colours.Yellow;
+ if (hoverColour == null)
+ HoverColour = colours.Yellow.Opacity(0.6f);
+
+ if (flashColour == null)
+ FlashColour = colours.Yellow;
Enabled.ValueChanged += enabled => this.FadeColour(enabled ? Color4.White : colours.Gray9, 200, Easing.OutQuint);
}
@@ -98,7 +144,7 @@ namespace osu.Game.Graphics.UserInterface
protected override bool OnClick(InputState state)
{
- hover.FlashColour(flashColour, 800, Easing.OutQuint);
+ hover.FlashColour(FlashColour, 800, Easing.OutQuint);
return base.OnClick(state);
}
diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs
index 64d0d628f0..a99ce89a36 100644
--- a/osu.Game/Overlays/MusicController.cs
+++ b/osu.Game/Overlays/MusicController.cs
@@ -161,11 +161,15 @@ namespace osu.Game.Overlays
{
prevButton = new IconButton
{
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
Action = prev,
Icon = FontAwesome.fa_step_backward,
},
playButton = new IconButton
{
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
Scale = new Vector2(1.4f),
IconScale = new Vector2(1.4f),
Action = play,
@@ -173,6 +177,8 @@ namespace osu.Game.Overlays
},
nextButton = new IconButton
{
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
Action = next,
Icon = FontAwesome.fa_step_forward,
},
diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
index 7a26a53c2a..bcd6734af6 100644
--- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
+++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
@@ -25,6 +25,11 @@ namespace osu.Game.Rulesets.Objects.Drawables
///
public virtual Color4 AccentColour { get; set; } = Color4.Gray;
+ ///
+ /// Whether a visible judgement should be displayed when this representation is hit.
+ ///
+ public virtual bool DisplayJudgement => true;
+
protected DrawableHitObject(HitObject hitObject)
{
HitObject = hitObject;
diff --git a/osu.Game/Tests/Visual/TestCaseIconButton.cs b/osu.Game/Tests/Visual/TestCaseIconButton.cs
new file mode 100644
index 0000000000..bec8f8314b
--- /dev/null
+++ b/osu.Game/Tests/Visual/TestCaseIconButton.cs
@@ -0,0 +1,109 @@
+// Copyright (c) 2007-2017 ppy Pty Ltd .
+// 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.Shapes;
+using osu.Game.Graphics;
+using osu.Game.Graphics.Sprites;
+using osu.Game.Graphics.UserInterface;
+
+namespace osu.Game.Tests.Visual
+{
+ public class TestCaseIconButton : OsuTestCase
+ {
+ public override string Description => "Various display modes of icon buttons";
+
+ public TestCaseIconButton()
+ {
+ Child = new FillFlowContainer
+ {
+ RelativeSizeAxes = Axes.Both,
+ Spacing = new Vector2(10, 10),
+ Children = new[]
+ {
+ new NamedIconButton("No change", new IconButton()),
+ new NamedIconButton("Green colours", new IconButton
+ {
+ IconColour = Color4.LightGreen,
+ FlashColour = Color4.DarkGreen,
+ HoverColour = Color4.Green
+ }),
+ new NamedIconButton("Full-width", new IconButton { ButtonSize = new Vector2(200, 30) }),
+ new NamedIconButton("Unchanging size", new IconButton(), false)
+ }
+ };
+ }
+
+ private class NamedIconButton : Container
+ {
+ public NamedIconButton(string name, IconButton button, bool allowSizeChange = true)
+ {
+ AutoSizeAxes = Axes.Y;
+ Width = 200;
+
+ Container iconContainer;
+ Children = new Drawable[]
+ {
+ new Box
+ {
+ RelativeSizeAxes = Axes.Both,
+ Colour = Color4.Black,
+ Alpha = 0.5f,
+ },
+ new FillFlowContainer
+ {
+ RelativeSizeAxes = Axes.X,
+ AutoSizeAxes = Axes.Y,
+ Direction = FillDirection.Vertical,
+ Spacing = new Vector2(0, 10),
+ Children = new Drawable[]
+ {
+ new OsuSpriteText
+ {
+ Anchor = Anchor.TopCentre,
+ Origin = Anchor.TopCentre,
+ Text = name
+ },
+ new Container
+ {
+ Anchor = Anchor.TopCentre,
+ Origin = Anchor.TopCentre,
+ RelativeSizeAxes = Axes.X,
+ AutoSizeAxes = Axes.Y,
+ Children = new Drawable[]
+ {
+ new Box
+ {
+ RelativeSizeAxes = Axes.Both,
+ Alpha = 0.1f,
+ },
+ iconContainer = new Container
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ Child = button
+ }
+ }
+ }
+ }
+ }
+ };
+
+ if (allowSizeChange)
+ iconContainer.AutoSizeAxes = Axes.Both;
+ else
+ {
+ iconContainer.RelativeSizeAxes = Axes.X;
+ iconContainer.Height = 30;
+ }
+
+ button.Anchor = Anchor.Centre;
+ button.Origin = Anchor.Centre;
+ button.Icon = FontAwesome.fa_osu_osu_o;
+ }
+ }
+ }
+}
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index ff5c492fc7..81f360f640 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -759,6 +759,7 @@
+