diff --git a/osu-framework b/osu-framework
index 13af08782c..dd9faf4609 160000
--- a/osu-framework
+++ b/osu-framework
@@ -1 +1 @@
-Subproject commit 13af08782cfb4de054b2fb11a2cf8311ff895949
+Subproject commit dd9faf46095a761558abc6cb11ecd0e7498dba4e
diff --git a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs
index 69b56ef17d..a3ae103f28 100644
--- a/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs
+++ b/osu.Desktop.VisualTests/Tests/TestCasePlayer.cs
@@ -44,11 +44,14 @@ namespace osu.Desktop.VisualTests.Tests
time += 500;
}
- Add(new Player()
+ Add(new Player
{
- Beatmap = new Beatmap
+ Beatmap = new WorkingBeatmap
{
- HitObjects = objects
+ Beatmap = new Beatmap
+ {
+ HitObjects = objects
+ }
}
});
}
diff --git a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs
index d48019c446..2d854ab3b7 100644
--- a/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs
+++ b/osu.Game.Tests/Beatmaps/Formats/OsuLegacyDecoderTest.cs
@@ -15,7 +15,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
[TestFixture]
public class OsuLegacyDecoderTest
{
- [TestFixtureSetUp]
+ [OneTimeSetUpAttribute]
public void SetUp()
{
OsuLegacyDecoder.Register();
diff --git a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs
index caa56c26c2..568c08cfc6 100644
--- a/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs
+++ b/osu.Game.Tests/Beatmaps/IO/OszArchiveReaderTest.cs
@@ -10,7 +10,7 @@ namespace osu.Game.Tests.Beatmaps.IO
[TestFixture]
public class OszArchiveReaderTest
{
- [TestFixtureSetUp]
+ [OneTimeSetUpAttribute]
public void SetUp()
{
OszArchiveReader.Register();
diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj
index 04c09b3a2c..af6fa91661 100644
--- a/osu.Game.Tests/osu.Game.Tests.csproj
+++ b/osu.Game.Tests/osu.Game.Tests.csproj
@@ -33,7 +33,7 @@
- $(SolutionDir)\packages\NUnit.2.6.4\lib\nunit.framework.dll
+ $(SolutionDir)\packages\NUnit.3.5.0\lib\nunit.framework.dll
$(SolutionDir)\packages\ppy.OpenTK.2.0.50727.1339\lib\net45\OpenTK.dll
diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs
index c2b6b5932f..4769e2fb64 100644
--- a/osu.Game/Beatmaps/Beatmap.cs
+++ b/osu.Game/Beatmaps/Beatmap.cs
@@ -1,7 +1,6 @@
//Copyright (c) 2007-2016 ppy Pty Ltd .
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-using System;
using System.Collections.Generic;
using OpenTK.Graphics;
using osu.Game.Beatmaps.Objects;
@@ -13,6 +12,7 @@ namespace osu.Game.Beatmaps
public class Beatmap
{
public BeatmapInfo BeatmapInfo { get; set; }
+ public BeatmapMetadata Metadata => BeatmapInfo?.Metadata ?? BeatmapInfo?.BeatmapSet?.Metadata;
public List HitObjects { get; set; }
public List ControlPoints { get; set; }
public List ComboColors { get; set; }
diff --git a/osu.Game/Beatmaps/Drawable/BeatmapGroup.cs b/osu.Game/Beatmaps/Drawable/BeatmapGroup.cs
index 57ca1190e3..ebc2ab447c 100644
--- a/osu.Game/Beatmaps/Drawable/BeatmapGroup.cs
+++ b/osu.Game/Beatmaps/Drawable/BeatmapGroup.cs
@@ -2,6 +2,7 @@
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
+using System.Collections.Generic;
using System.Linq;
using osu.Framework;
using osu.Framework.Graphics;
@@ -27,6 +28,8 @@ namespace osu.Game.Beatmaps.Drawable
private BeatmapGroupState state;
+ public List BeatmapPanels;
+
public BeatmapGroupState State
{
get { return state; }
@@ -40,9 +43,6 @@ namespace osu.Game.Beatmaps.Drawable
difficulties.Show();
header.State = PanelSelectedState.Selected;
-
- if (SelectedPanel == null)
- ((BeatmapPanel)difficulties.Children.FirstOrDefault()).State = PanelSelectedState.Selected;
break;
case BeatmapGroupState.Collapsed:
FadeTo(0.5f, 250);
@@ -62,6 +62,16 @@ namespace osu.Game.Beatmaps.Drawable
AutoSizeAxes = Axes.Y;
RelativeSizeAxes = Axes.X;
+ BeatmapPanels = beatmapSet.Beatmaps.Select(b =>
+ new BeatmapPanel(b)
+ {
+ GainedSelection = panelGainedSelection,
+ Anchor = Anchor.TopRight,
+ Origin = Anchor.TopRight,
+ RelativeSizeAxes = Axes.X,
+ }).ToList();
+
+
Children = new[]
{
new FlowContainer
@@ -87,15 +97,7 @@ namespace osu.Game.Beatmaps.Drawable
Spacing = new Vector2(0, 5),
Direction = FlowDirection.VerticalOnly,
Alpha = 0,
- Children = this.beatmapSet.Beatmaps.Select(b =>
- new BeatmapPanel(this.beatmapSet, b)
- {
- GainedSelection = panelGainedSelection,
- Anchor = Anchor.TopRight,
- Origin = Anchor.TopRight,
- RelativeSizeAxes = Axes.X,
- }
- )
+ Children = BeatmapPanels
}
}
}
@@ -112,17 +114,28 @@ namespace osu.Game.Beatmaps.Drawable
{
State = BeatmapGroupState.Expanded;
- SelectionChanged?.Invoke(this, SelectedPanel.Beatmap);
+ //we want to make sure one of our children is selected in the case none have been selected yet.
+ if (SelectedPanel == null)
+ BeatmapPanels.First().State = PanelSelectedState.Selected;
+ else
+ SelectionChanged?.Invoke(this, SelectedPanel.Beatmap);
}
private void panelGainedSelection(BeatmapPanel panel)
{
- State = BeatmapGroupState.Expanded;
-
- if (SelectedPanel != null) SelectedPanel.State = PanelSelectedState.NotSelected;
- SelectedPanel = panel;
+ try
+ {
+ if (SelectedPanel == panel) return;
- SelectionChanged?.Invoke(this, panel.Beatmap);
+ if (SelectedPanel != null)
+ SelectedPanel.State = PanelSelectedState.NotSelected;
+ SelectedPanel = panel;
+ }
+ finally
+ {
+ State = BeatmapGroupState.Expanded;
+ SelectionChanged?.Invoke(this, panel.Beatmap);
+ }
}
}
diff --git a/osu.Game/Beatmaps/Drawable/BeatmapPanel.cs b/osu.Game/Beatmaps/Drawable/BeatmapPanel.cs
index 62b5f63335..cd28e909a8 100644
--- a/osu.Game/Beatmaps/Drawable/BeatmapPanel.cs
+++ b/osu.Game/Beatmaps/Drawable/BeatmapPanel.cs
@@ -26,7 +26,7 @@ namespace osu.Game.Beatmaps.Drawable
GainedSelection?.Invoke(this);
}
- public BeatmapPanel(BeatmapSetInfo set, BeatmapInfo beatmap)
+ public BeatmapPanel(BeatmapInfo beatmap)
{
Beatmap = beatmap;
Height *= 0.75f;
@@ -67,7 +67,7 @@ namespace osu.Game.Beatmaps.Drawable
},
new SpriteText
{
- Text = $" mapped by {(beatmap.Metadata ?? set.Metadata).Author}",
+ Text = $" mapped by {(beatmap.Metadata ?? beatmap.BeatmapSet.Metadata).Author}",
TextSize = 16,
},
}
diff --git a/osu.Game/Beatmaps/Drawable/Panel.cs b/osu.Game/Beatmaps/Drawable/Panel.cs
index 430c23836d..b0c0821197 100644
--- a/osu.Game/Beatmaps/Drawable/Panel.cs
+++ b/osu.Game/Beatmaps/Drawable/Panel.cs
@@ -37,7 +37,6 @@ namespace osu.Game.Beatmaps.Drawable
set
{
if (state == value) return;
-
state = value;
switch (state)
diff --git a/osu.Game/Beatmaps/Objects/Catch/Drawable/DrawableFruit.cs b/osu.Game/Beatmaps/Objects/Catch/Drawable/DrawableFruit.cs
index 028afff5cc..3a3883ab3b 100644
--- a/osu.Game/Beatmaps/Objects/Catch/Drawable/DrawableFruit.cs
+++ b/osu.Game/Beatmaps/Objects/Catch/Drawable/DrawableFruit.cs
@@ -34,8 +34,8 @@ namespace osu.Game.Beatmaps.Objects.Catch.Drawable
Texture = game.Textures.Get(@"Menu/logo");
- Transforms.Add(new TransformPosition(Clock) { StartTime = h.StartTime - 200, EndTime = h.StartTime, StartValue = new Vector2(h.Position, -0.1f), EndValue = new Vector2(h.Position, 0.9f) });
- Transforms.Add(new TransformAlpha(Clock) { StartTime = h.StartTime + h.Duration + 200, EndTime = h.StartTime + h.Duration + 400, StartValue = 1, EndValue = 0 });
+ Transforms.Add(new TransformPosition { StartTime = h.StartTime - 200, EndTime = h.StartTime, StartValue = new Vector2(h.Position, -0.1f), EndValue = new Vector2(h.Position, 0.9f) });
+ Transforms.Add(new TransformAlpha { StartTime = h.StartTime + h.Duration + 200, EndTime = h.StartTime + h.Duration + 400, StartValue = 1, EndValue = 0 });
Expire(true);
}
}
diff --git a/osu.Game/Beatmaps/Objects/Mania/Drawable/DrawableNote.cs b/osu.Game/Beatmaps/Objects/Mania/Drawable/DrawableNote.cs
index 132fb6ce36..939dc645cd 100644
--- a/osu.Game/Beatmaps/Objects/Mania/Drawable/DrawableNote.cs
+++ b/osu.Game/Beatmaps/Objects/Mania/Drawable/DrawableNote.cs
@@ -25,8 +25,8 @@ namespace osu.Game.Beatmaps.Objects.Mania.Drawable
base.Load(game);
Texture = game.Textures.Get(@"Menu/logo");
- Transforms.Add(new TransformPositionY(Clock) { StartTime = note.StartTime - 200, EndTime = note.StartTime, StartValue = -0.1f, EndValue = 0.9f });
- Transforms.Add(new TransformAlpha(Clock) { StartTime = note.StartTime + note.Duration + 200, EndTime = note.StartTime + note.Duration + 400, StartValue = 1, EndValue = 0 });
+ Transforms.Add(new TransformPositionY() { StartTime = note.StartTime - 200, EndTime = note.StartTime, StartValue = -0.1f, EndValue = 0.9f });
+ Transforms.Add(new TransformAlpha() { StartTime = note.StartTime + note.Duration + 200, EndTime = note.StartTime + note.Duration + 400, StartValue = 1, EndValue = 0 });
Expire(true);
}
}
diff --git a/osu.Game/Beatmaps/Objects/Osu/Drawable/DrawableCircle.cs b/osu.Game/Beatmaps/Objects/Osu/Drawable/DrawableCircle.cs
index bbfcac9d39..be2b7495f6 100644
--- a/osu.Game/Beatmaps/Objects/Osu/Drawable/DrawableCircle.cs
+++ b/osu.Game/Beatmaps/Objects/Osu/Drawable/DrawableCircle.cs
@@ -77,36 +77,36 @@ namespace osu.Game.Beatmaps.Objects.Osu.Drawable
Flush(); //move to DrawableHitObject
- Transforms.Add(new TransformAlpha(Clock) { StartTime = h.StartTime - 1000, EndTime = h.StartTime - 800, StartValue = 0, EndValue = 1 });
+ Transforms.Add(new TransformAlpha { StartTime = h.StartTime - 1000, EndTime = h.StartTime - 800, StartValue = 0, EndValue = 1 });
- approachCircle.Transforms.Add(new TransformScale(Clock) { StartTime = h.StartTime - 1000, EndTime = h.StartTime, StartValue = new Vector2(2f), EndValue = new Vector2(0.6f) });
- approachCircle.Transforms.Add(new TransformAlpha(Clock) { StartTime = h.StartTime, EndTime = h.StartTime, StartValue = 1, EndValue = 0 });
+ approachCircle.Transforms.Add(new TransformScale { StartTime = h.StartTime - 1000, EndTime = h.StartTime, StartValue = new Vector2(2f), EndValue = new Vector2(0.6f) });
+ approachCircle.Transforms.Add(new TransformAlpha { StartTime = h.StartTime, EndTime = h.StartTime, StartValue = 1, EndValue = 0 });
- glow.Transforms.Add(new TransformAlpha(Clock) { StartTime = h.StartTime, EndTime = h.StartTime + 400, StartValue = glow.Alpha, EndValue = 0 });
+ glow.Transforms.Add(new TransformAlpha { StartTime = h.StartTime, EndTime = h.StartTime + 400, StartValue = glow.Alpha, EndValue = 0 });
switch (state)
{
case ArmedState.Disarmed:
- Transforms.Add(new TransformAlpha(Clock) { StartTime = h.StartTime + h.Duration + 200, EndTime = h.StartTime + h.Duration + 400, StartValue = 1, EndValue = 0 });
+ Transforms.Add(new TransformAlpha { StartTime = h.StartTime + h.Duration + 200, EndTime = h.StartTime + h.Duration + 400, StartValue = 1, EndValue = 0 });
break;
case ArmedState.Armed:
const float flashIn = 30;
const float fadeOut = 800;
- //Transforms.Add(new TransformScale(Clock) { StartTime = h.StartTime, EndTime = h.StartTime + 400, StartValue = Scale, EndValue = Scale * 1.1f });
+ //Transforms.Add(new TransformScale() { StartTime = h.StartTime, EndTime = h.StartTime + 400, StartValue = Scale, EndValue = Scale * 1.1f });
- ring.Transforms.Add(new TransformAlpha(Clock) { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 0 });
- circle.Transforms.Add(new TransformAlpha(Clock) { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 0 });
- number.Transforms.Add(new TransformAlpha(Clock) { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 0 });
+ ring.Transforms.Add(new TransformAlpha { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 0 });
+ circle.Transforms.Add(new TransformAlpha { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 0 });
+ number.Transforms.Add(new TransformAlpha { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 0 });
- flash.Transforms.Add(new TransformAlpha(Clock) { StartTime = h.StartTime, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 0.8f });
- flash.Transforms.Add(new TransformAlpha(Clock) { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn + 100, StartValue = 0.8f, EndValue = 0 });
+ flash.Transforms.Add(new TransformAlpha { StartTime = h.StartTime, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 0.8f });
+ flash.Transforms.Add(new TransformAlpha { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn + 100, StartValue = 0.8f, EndValue = 0 });
- explode.Transforms.Add(new TransformAlpha(Clock) { StartTime = h.StartTime, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 1 });
+ explode.Transforms.Add(new TransformAlpha { StartTime = h.StartTime, EndTime = h.StartTime + flashIn, StartValue = 0, EndValue = 1 });
- Transforms.Add(new TransformAlpha(Clock) { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn + fadeOut, StartValue = 1, EndValue = 0 });
+ Transforms.Add(new TransformAlpha { StartTime = h.StartTime + flashIn, EndTime = h.StartTime + flashIn + fadeOut, StartValue = 1, EndValue = 0 });
- Transforms.Add(new TransformScale(Clock) { StartTime = h.StartTime + h.Duration, EndTime = h.StartTime + h.Duration + 400, StartValue = Scale, EndValue = Scale * 1.5f, Easing = EasingTypes.OutQuad });
+ Transforms.Add(new TransformScale { StartTime = h.StartTime + h.Duration, EndTime = h.StartTime + h.Duration + 400, StartValue = Scale, EndValue = Scale * 1.5f, Easing = EasingTypes.OutQuad });
break;
}
}
diff --git a/osu.Game/Beatmaps/Objects/Taiko/Drawable/DrawableTaikoHit.cs b/osu.Game/Beatmaps/Objects/Taiko/Drawable/DrawableTaikoHit.cs
index dafbe33415..c0354124c7 100644
--- a/osu.Game/Beatmaps/Objects/Taiko/Drawable/DrawableTaikoHit.cs
+++ b/osu.Game/Beatmaps/Objects/Taiko/Drawable/DrawableTaikoHit.cs
@@ -29,8 +29,8 @@ namespace osu.Game.Beatmaps.Objects.Taiko.Drawable
Texture = game.Textures.Get(@"Menu/logo");
- Transforms.Add(new TransformPositionX(Clock) { StartTime = h.StartTime - 200, EndTime = h.StartTime, StartValue = 1.1f, EndValue = 0.1f });
- Transforms.Add(new TransformAlpha(Clock) { StartTime = h.StartTime + h.Duration + 200, EndTime = h.StartTime + h.Duration + 400, StartValue = 1, EndValue = 0 });
+ Transforms.Add(new TransformPositionX { StartTime = h.StartTime - 200, EndTime = h.StartTime, StartValue = 1.1f, EndValue = 0.1f });
+ Transforms.Add(new TransformAlpha { StartTime = h.StartTime + h.Duration + 200, EndTime = h.StartTime + h.Duration + 400, StartValue = 1, EndValue = 0 });
Expire(true);
}
}
diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs
new file mode 100644
index 0000000000..4deed53465
--- /dev/null
+++ b/osu.Game/Beatmaps/WorkingBeatmap.cs
@@ -0,0 +1,87 @@
+//Copyright (c) 2007-2016 ppy Pty Ltd .
+//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System;
+using System.IO;
+using osu.Framework.Audio.Track;
+using osu.Game.Beatmaps.Formats;
+using osu.Game.Beatmaps.IO;
+using osu.Game.Database;
+
+namespace osu.Game.Beatmaps
+{
+ public class WorkingBeatmap : IDisposable
+ {
+ public BeatmapInfo BeatmapInfo;
+
+ public readonly ArchiveReader Reader;
+
+ private Beatmap beatmap;
+ public Beatmap Beatmap
+ {
+ get
+ {
+ if (beatmap != null) return beatmap;
+
+ try
+ {
+ using (var stream = new StreamReader(Reader.ReadFile(BeatmapInfo.Path)))
+ beatmap = BeatmapDecoder.GetDecoder(stream)?.Decode(stream);
+ }
+ catch { }
+
+ return beatmap;
+ }
+ set { beatmap = value; }
+ }
+
+ private AudioTrack track;
+ public AudioTrack Track
+ {
+ get
+ {
+ if (track != null) return track;
+
+ try
+ {
+ var trackData = Reader.ReadFile(BeatmapInfo.Metadata.AudioFile);
+ if (trackData != null)
+ track = new AudioTrackBass(trackData);
+ }
+ catch { }
+
+ return track;
+ }
+ set { track = value; }
+ }
+
+ public WorkingBeatmap(BeatmapInfo beatmapInfo = null, ArchiveReader reader = null)
+ {
+ this.BeatmapInfo = beatmapInfo;
+ Reader = reader;
+ }
+
+ private bool isDisposed;
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!isDisposed)
+ {
+ track?.Dispose();
+ Reader?.Dispose();
+ isDisposed = true;
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ public void TransferTo(WorkingBeatmap working)
+ {
+ if (track != null && working.BeatmapInfo.Metadata.AudioFile == BeatmapInfo.Metadata.AudioFile && working.BeatmapInfo.BeatmapSet.Path == BeatmapInfo.BeatmapSet.Path)
+ working.track = track;
+ }
+ }
+}
diff --git a/osu.Game/Database/BeatmapDatabase.cs b/osu.Game/Database/BeatmapDatabase.cs
index 1b55b0eeaf..5d0834bad7 100644
--- a/osu.Game/Database/BeatmapDatabase.cs
+++ b/osu.Game/Database/BeatmapDatabase.cs
@@ -130,43 +130,56 @@ namespace osu.Game.Database
{
return ArchiveReader.GetReader(storage, beatmapSet.Path);
}
-
+
public BeatmapSetInfo GetBeatmapSet(int id)
{
return Query().Where(s => s.BeatmapSetID == id).FirstOrDefault();
}
-
+
+ public WorkingBeatmap GetWorkingBeatmap(BeatmapInfo beatmapInfo, WorkingBeatmap previous = null)
+ {
+ var beatmapSetInfo = Query().FirstOrDefault(s => s.BeatmapSetID == beatmapInfo.BeatmapSetID);
+
+ //we need metadata
+ GetChildren(beatmapSetInfo);
+
+ if (beatmapSetInfo == null)
+ throw new InvalidOperationException($@"Beatmap set {beatmapInfo.BeatmapSetID} is not in the local database.");
+
+ var reader = GetReader(beatmapSetInfo);
+
+ if (beatmapInfo.Metadata == null)
+ beatmapInfo.Metadata = beatmapSetInfo.Metadata;
+
+ var working = new WorkingBeatmap(beatmapInfo, reader);
+
+ previous?.TransferTo(working);
+
+ return working;
+ }
+
public Beatmap GetBeatmap(BeatmapInfo beatmapInfo)
{
- var beatmapSet = Query()
- .Where(s => s.BeatmapSetID == beatmapInfo.BeatmapSetID).FirstOrDefault();
- if (beatmapSet == null)
- throw new InvalidOperationException(
- $@"Beatmap set {beatmapInfo.BeatmapSetID} is not in the local database.");
- using (var reader = GetReader(beatmapSet))
- using (var stream = new StreamReader(reader.ReadFile(beatmapInfo.Path)))
- {
- var decoder = BeatmapDecoder.GetDecoder(stream);
- return decoder.Decode(stream);
- }
+ using (WorkingBeatmap data = GetWorkingBeatmap(beatmapInfo))
+ return data.Beatmap;
}
-
+
public TableQuery Query() where T : class
{
return connection.Table();
}
-
+
public T GetWithChildren(object id) where T : class
{
return connection.GetWithChildren(id);
}
-
+
public List GetAllWithChildren(Expression> filter = null,
bool recursive = true) where T : class
{
return connection.GetAllWithChildren(filter, recursive);
}
-
+
public T GetChildren(T item, bool recursive = true)
{
if (item == null) return default(T);
diff --git a/osu.Game/Database/BeatmapInfo.cs b/osu.Game/Database/BeatmapInfo.cs
index 5b1d0c323c..4d18976ef0 100644
--- a/osu.Game/Database/BeatmapInfo.cs
+++ b/osu.Game/Database/BeatmapInfo.cs
@@ -7,7 +7,7 @@ using SQLiteNetExtensions.Attributes;
namespace osu.Game.Database
{
- public class BeatmapInfo
+ public class BeatmapInfo : IEquatable
{
[PrimaryKey]
public int BeatmapID { get; set; }
@@ -64,5 +64,10 @@ namespace osu.Game.Database
// Metadata
public string Version { get; set; }
+
+ public bool Equals(BeatmapInfo other)
+ {
+ return BeatmapID == other?.BeatmapID;
+ }
}
}
\ No newline at end of file
diff --git a/osu.Game/GameModes/Menu/Button.cs b/osu.Game/GameModes/Menu/Button.cs
index b278cefbd9..5599f25ad3 100644
--- a/osu.Game/GameModes/Menu/Button.cs
+++ b/osu.Game/GameModes/Menu/Button.cs
@@ -117,7 +117,7 @@ namespace osu.Game.GameModes.Menu
icon.RotateTo(10, offset, EasingTypes.InOutSine);
icon.ScaleTo(new Vector2(1, 0.9f), offset, EasingTypes.Out);
- icon.Transforms.Add(new TransformRotation(Clock)
+ icon.Transforms.Add(new TransformRotation
{
StartValue = -10,
EndValue = 10,
@@ -128,7 +128,7 @@ namespace osu.Game.GameModes.Menu
LoopDelay = duration * 2
});
- icon.Transforms.Add(new TransformPosition(Clock)
+ icon.Transforms.Add(new TransformPosition
{
StartValue = Vector2.Zero,
EndValue = new Vector2(0, -10),
@@ -139,7 +139,7 @@ namespace osu.Game.GameModes.Menu
LoopDelay = duration
});
- icon.Transforms.Add(new TransformScale(Clock)
+ icon.Transforms.Add(new TransformScale
{
StartValue = new Vector2(1, 0.9f),
EndValue = Vector2.One,
@@ -150,7 +150,7 @@ namespace osu.Game.GameModes.Menu
LoopDelay = duration
});
- icon.Transforms.Add(new TransformPosition(Clock)
+ icon.Transforms.Add(new TransformPosition
{
StartValue = new Vector2(0, -10),
EndValue = Vector2.Zero,
@@ -161,7 +161,7 @@ namespace osu.Game.GameModes.Menu
LoopDelay = duration
});
- icon.Transforms.Add(new TransformScale(Clock)
+ icon.Transforms.Add(new TransformScale
{
StartValue = Vector2.One,
EndValue = new Vector2(1, 0.9f),
@@ -172,7 +172,7 @@ namespace osu.Game.GameModes.Menu
LoopDelay = duration
});
- icon.Transforms.Add(new TransformRotation(Clock)
+ icon.Transforms.Add(new TransformRotation
{
StartValue = 10,
EndValue = -10,
diff --git a/osu.Game/GameModes/Menu/Intro.cs b/osu.Game/GameModes/Menu/Intro.cs
index f0bba5bddb..2973f83b6b 100644
--- a/osu.Game/GameModes/Menu/Intro.cs
+++ b/osu.Game/GameModes/Menu/Intro.cs
@@ -10,6 +10,8 @@ using osu.Framework.Graphics.Transformations;
using osu.Game.GameModes.Backgrounds;
using OpenTK.Graphics;
using osu.Framework;
+using osu.Framework.Configuration;
+using osu.Game.Beatmaps;
namespace osu.Game.GameModes.Menu
{
diff --git a/osu.Game/GameModes/OsuGameMode.cs b/osu.Game/GameModes/OsuGameMode.cs
index b0928d8214..d8b73f5f07 100644
--- a/osu.Game/GameModes/OsuGameMode.cs
+++ b/osu.Game/GameModes/OsuGameMode.cs
@@ -3,17 +3,20 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using osu.Framework.Configuration;
using osu.Framework.GameModes;
using osu.Framework.Graphics.Containers;
+using osu.Game.Beatmaps;
using osu.Game.Graphics.Background;
using osu.Game.Graphics.Containers;
namespace osu.Game.GameModes
{
- public class OsuGameMode : GameMode
+ public abstract class OsuGameMode : GameMode
{
internal BackgroundMode Background { get; private set; }
@@ -23,6 +26,64 @@ namespace osu.Game.GameModes
///
protected virtual BackgroundMode CreateBackground() => null;
+ private bool boundToBeatmap;
+ private Bindable beatmap;
+
+ public WorkingBeatmap Beatmap
+ {
+ get
+ {
+ bindBeatmap();
+ return beatmap.Value;
+ }
+ set
+ {
+ bindBeatmap();
+ beatmap.Value = value;
+ }
+ }
+
+ private void bindBeatmap()
+ {
+ if (beatmap == null)
+ beatmap = new Bindable();
+
+ if (!boundToBeatmap)
+ {
+ beatmap.ValueChanged += beatmap_ValueChanged;
+ boundToBeatmap = true;
+ }
+ }
+
+ protected override void Dispose(bool isDisposing)
+ {
+ if (boundToBeatmap)
+ beatmap.ValueChanged -= beatmap_ValueChanged;
+
+ base.Dispose(isDisposing);
+ }
+
+ private void beatmap_ValueChanged(object sender, EventArgs e)
+ {
+ OnBeatmapChanged(beatmap.Value);
+ }
+
+ public override bool Push(GameMode mode)
+ {
+ OsuGameMode nextOsu = mode as OsuGameMode;
+ if (nextOsu != null)
+ {
+ nextOsu.beatmap = beatmap;
+ }
+
+ return base.Push(mode);
+ }
+
+ protected virtual void OnBeatmapChanged(WorkingBeatmap beatmap)
+ {
+
+ }
+
protected override void OnEntering(GameMode last)
{
OsuGameMode lastOsu = last as OsuGameMode;
diff --git a/osu.Game/GameModes/Play/ComboCounter.cs b/osu.Game/GameModes/Play/ComboCounter.cs
index c40d7a4964..ebc89c102e 100644
--- a/osu.Game/GameModes/Play/ComboCounter.cs
+++ b/osu.Game/GameModes/Play/ComboCounter.cs
@@ -174,7 +174,7 @@ namespace osu.Game.GameModes.Play
protected virtual void OnCountRolling(ulong currentValue, ulong newValue)
{
- transformRoll(new TransformComboRoll(Clock), currentValue, newValue);
+ transformRoll(new TransformComboRoll(), currentValue, newValue);
}
protected virtual void OnCountIncrement(ulong currentValue, ulong newValue) {
@@ -248,11 +248,11 @@ namespace osu.Game.GameModes.Play
protected class TransformComboRoll : Transform
{
- public override ulong CurrentValue
+ protected override ulong CurrentValue
{
get
{
- double time = Time;
+ double time = CurrentTime ?? 0;
if (time < StartTime) return StartValue;
if (time >= EndTime) return EndValue;
@@ -265,11 +265,6 @@ namespace osu.Game.GameModes.Play
base.Apply(d);
(d as ComboCounter).DisplayedCount = CurrentValue;
}
-
- public TransformComboRoll(IClock clock)
- : base(clock)
- {
- }
}
}
}
diff --git a/osu.Game/GameModes/Play/ComboResultCounter.cs b/osu.Game/GameModes/Play/ComboResultCounter.cs
index a07e35b263..fd96906d18 100644
--- a/osu.Game/GameModes/Play/ComboResultCounter.cs
+++ b/osu.Game/GameModes/Play/ComboResultCounter.cs
@@ -41,11 +41,11 @@ namespace osu.Game.GameModes.Play
protected class TransformComboResult : Transform
{
- public override ulong CurrentValue
+ protected override ulong CurrentValue
{
get
{
- double time = Time;
+ double time = CurrentTime ?? 0;
if (time < StartTime) return StartValue;
if (time >= EndTime) return EndValue;
@@ -58,11 +58,6 @@ namespace osu.Game.GameModes.Play
base.Apply(d);
(d as ComboResultCounter).DisplayedCount = CurrentValue;
}
-
- public TransformComboResult(IClock clock)
- : base(clock)
- {
- }
}
}
}
diff --git a/osu.Game/GameModes/Play/PlaySongSelect.cs b/osu.Game/GameModes/Play/PlaySongSelect.cs
index b4d675fc0b..309cd3119b 100644
--- a/osu.Game/GameModes/Play/PlaySongSelect.cs
+++ b/osu.Game/GameModes/Play/PlaySongSelect.cs
@@ -16,8 +16,11 @@ using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Graphics.UserInterface;
using System.Threading.Tasks;
+using osu.Framework.Audio.Track;
using osu.Game.Beatmaps.Drawable;
using osu.Framework.Extensions.IEnumerableExtensions;
+using osu.Game.Beatmaps;
+using osu.Framework.GameModes;
namespace osu.Game.GameModes.Play
{
@@ -26,10 +29,12 @@ namespace osu.Game.GameModes.Play
private Bindable playMode;
private BeatmapDatabase database;
private BeatmapGroup selectedBeatmapGroup;
+ private BeatmapInfo selectedBeatmapInfo;
// TODO: use currently selected track as bg
protected override BackgroundMode CreateBackground() => new BackgroundModeCustom(@"Backgrounds/bg4");
private ScrollContainer scrollContainer;
- private FlowContainer setList;
+ private FlowContainer beatmapSetFlow;
+ private TrackManager trackManager;
/// Optionally provide a database to use instead of the OsuGame one.
public PlaySongSelect(BeatmapDatabase database = null)
@@ -73,7 +78,7 @@ namespace osu.Game.GameModes.Play
Origin = Anchor.CentreRight,
Children = new Drawable[]
{
- setList = new FlowContainer
+ beatmapSetFlow = new FlowContainer
{
Padding = new MarginPadding { Left = 25, Top = 25, Bottom = 25 + bottomToolHeight },
RelativeSizeAxes = Axes.X,
@@ -107,7 +112,7 @@ namespace osu.Game.GameModes.Play
Colour = new Color4(238, 51, 153, 255),
Action = () => Push(new Player {
BeatmapInfo = selectedBeatmapGroup.SelectedPanel.Beatmap,
- PlayMode = playMode.Value
+ PreferredPlayMode = playMode.Value
}),
},
}
@@ -123,7 +128,7 @@ namespace osu.Game.GameModes.Play
if (osuGame != null)
{
playMode = osuGame.PlayMode;
- playMode.ValueChanged += PlayMode_ValueChanged;
+ playMode.ValueChanged += playMode_ValueChanged;
// Temporary:
scrollContainer.Padding = new MarginPadding { Top = osuGame.Toolbar.Height };
}
@@ -133,22 +138,76 @@ namespace osu.Game.GameModes.Play
database.BeatmapSetAdded += s => Schedule(() => addBeatmapSet(s));
+ trackManager = game.Audio.Track;
+
Task.Factory.StartNew(addBeatmapSets);
}
+ protected override void OnEntering(GameMode last)
+ {
+ base.OnEntering(last);
+ ensurePlayingSelected();
+ }
+
+ protected override void OnResuming(GameMode last)
+ {
+ ensurePlayingSelected();
+ base.OnResuming(last);
+ }
+
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
if (playMode != null)
- playMode.ValueChanged -= PlayMode_ValueChanged;
+ playMode.ValueChanged -= playMode_ValueChanged;
}
- private void PlayMode_ValueChanged(object sender, EventArgs e)
+ private void playMode_ValueChanged(object sender, EventArgs e)
{
}
- private void selectBeatmap(BeatmapGroup group, BeatmapInfo beatmap)
+ ///
+ /// The global Beatmap was changed.
+ ///
+ protected override void OnBeatmapChanged(WorkingBeatmap beatmap)
{
+ base.OnBeatmapChanged(beatmap);
+ selectBeatmap(beatmap.BeatmapInfo);
+ }
+
+ private void selectBeatmap(BeatmapInfo beatmap)
+ {
+ if (beatmap.Equals(selectedBeatmapInfo))
+ return;
+
+ //this is VERY temporary logic.
+ beatmapSetFlow.Children.Cast().Any(b =>
+ {
+ var panel = b.BeatmapPanels.FirstOrDefault(p => p.Beatmap.Equals(beatmap));
+ if (panel != null)
+ {
+ panel.State = PanelSelectedState.Selected;
+ return true;
+ }
+
+ return false;
+ });
+ }
+
+ ///
+ /// selection has been changed as the result of interaction with the carousel.
+ ///
+ private void selectionChanged(BeatmapGroup group, BeatmapInfo beatmap)
+ {
+ selectedBeatmapInfo = beatmap;
+
+ if (!beatmap.Equals(Beatmap?.BeatmapInfo))
+ {
+ Beatmap = database.GetWorkingBeatmap(beatmap, Beatmap);
+ }
+
+ ensurePlayingSelected();
+
if (selectedBeatmapGroup == group)
return;
@@ -158,6 +217,17 @@ namespace osu.Game.GameModes.Play
selectedBeatmapGroup = group;
}
+ private void ensurePlayingSelected()
+ {
+ var track = Beatmap?.Track;
+
+ if (track != null)
+ {
+ trackManager.SetExclusive(track);
+ track.Start();
+ }
+ }
+
private void addBeatmapSet(BeatmapSetInfo beatmapSet)
{
beatmapSet = database.GetWithChildren(beatmapSet.BeatmapSetID);
@@ -165,10 +235,22 @@ namespace osu.Game.GameModes.Play
beatmapSet.Beatmaps = beatmapSet.Beatmaps.OrderBy(b => b.BaseDifficulty.OverallDifficulty).ToList();
Schedule(() =>
{
- var group = new BeatmapGroup(beatmapSet) { SelectionChanged = selectBeatmap };
- setList.Add(group);
- if (setList.Children.Count() == 1)
- group.State = BeatmapGroupState.Expanded;
+ var group = new BeatmapGroup(beatmapSet) { SelectionChanged = selectionChanged };
+ beatmapSetFlow.Add(group);
+ if (Beatmap == null)
+ {
+ if (beatmapSetFlow.Children.Count() == 1)
+ group.State = BeatmapGroupState.Expanded;
+ }
+ else
+ {
+ if (selectedBeatmapInfo?.Equals(Beatmap.BeatmapInfo) != true)
+ {
+ var panel = group.BeatmapPanels.FirstOrDefault(p => p.Beatmap.Equals(Beatmap.BeatmapInfo));
+ if (panel != null)
+ panel.State = PanelSelectedState.Selected;
+ }
+ }
});
}
diff --git a/osu.Game/GameModes/Play/Player.cs b/osu.Game/GameModes/Play/Player.cs
index 4e18f06f5b..5f3e2954a5 100644
--- a/osu.Game/GameModes/Play/Player.cs
+++ b/osu.Game/GameModes/Play/Player.cs
@@ -1,7 +1,6 @@
//Copyright (c) 2007-2016 ppy Pty Ltd .
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-using System.Collections.Generic;
using osu.Framework.Graphics;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Objects;
@@ -12,6 +11,9 @@ using osu.Game.GameModes.Play.Osu;
using osu.Game.GameModes.Play.Taiko;
using osu.Framework;
using osu.Game.Database;
+using osu.Framework.Timing;
+using osu.Framework.GameModes;
+using osu.Framework.Audio.Track;
namespace osu.Game.GameModes.Play
{
@@ -20,9 +22,13 @@ namespace osu.Game.GameModes.Play
protected override BackgroundMode CreateBackground() => new BackgroundModeCustom(@"Backgrounds/bg4");
public BeatmapInfo BeatmapInfo;
- public Beatmap Beatmap;
- public PlayMode PlayMode;
+ public PlayMode PreferredPlayMode;
+
+ protected override IFrameBasedClock Clock => playerClock;
+
+ private InterpolatingFramedClock playerClock;
+ private IAdjustableClock sourceClock;
public override void Load(BaseGame game)
{
@@ -31,7 +37,7 @@ namespace osu.Game.GameModes.Play
try
{
if (Beatmap == null)
- Beatmap = ((OsuGame)game).Beatmaps.GetBeatmap(BeatmapInfo);
+ Beatmap = ((OsuGame)game).Beatmaps.GetWorkingBeatmap(BeatmapInfo);
}
catch
{
@@ -40,17 +46,45 @@ namespace osu.Game.GameModes.Play
return;
}
+ AudioTrack track = Beatmap.Track;
+
+ if (track != null)
+ {
+ game.Audio.Track.SetExclusive(track);
+ sourceClock = track;
+ }
+
+ sourceClock = (IAdjustableClock)track ?? new StopwatchClock();
+ playerClock = new InterpolatingFramedClock(sourceClock);
+
+ Schedule(() =>
+ {
+ sourceClock.Reset();
+ sourceClock.Start();
+ });
+
HitRenderer hitRenderer;
ScoreOverlay scoreOverlay;
- switch (PlayMode)
+ var beatmap = Beatmap.Beatmap;
+
+ if (beatmap.BeatmapInfo?.Mode > PlayMode.Osu)
+ {
+ //we only support osu! mode for now because the hitobject parsing is crappy and needs a refactor.
+ Exit();
+ return;
+ }
+
+ PlayMode usablePlayMode = beatmap.BeatmapInfo?.Mode > PlayMode.Osu ? beatmap.BeatmapInfo.Mode : PreferredPlayMode;
+
+ switch (usablePlayMode)
{
default:
scoreOverlay = new ScoreOverlayOsu();
hitRenderer = new OsuHitRenderer
{
- Objects = Beatmap.HitObjects,
+ Objects = beatmap.HitObjects,
Anchor = Anchor.Centre,
Origin = Anchor.Centre
};
@@ -60,7 +94,7 @@ namespace osu.Game.GameModes.Play
hitRenderer = new TaikoHitRenderer
{
- Objects = Beatmap.HitObjects,
+ Objects = beatmap.HitObjects,
Anchor = Anchor.Centre,
Origin = Anchor.Centre
};
@@ -70,7 +104,7 @@ namespace osu.Game.GameModes.Play
hitRenderer = new CatchHitRenderer
{
- Objects = Beatmap.HitObjects,
+ Objects = beatmap.HitObjects,
Anchor = Anchor.Centre,
Origin = Anchor.Centre
};
@@ -80,7 +114,7 @@ namespace osu.Game.GameModes.Play
hitRenderer = new ManiaHitRenderer
{
- Objects = Beatmap.HitObjects,
+ Objects = beatmap.HitObjects,
Anchor = Anchor.Centre,
Origin = Anchor.Centre
};
@@ -96,5 +130,11 @@ namespace osu.Game.GameModes.Play
scoreOverlay,
};
}
+
+ protected override void Update()
+ {
+ base.Update();
+ playerClock.ProcessFrame();
+ }
}
}
\ No newline at end of file
diff --git a/osu.Game/GameModes/Play/Results.cs b/osu.Game/GameModes/Ranking/Results.cs
similarity index 80%
rename from osu.Game/GameModes/Play/Results.cs
rename to osu.Game/GameModes/Ranking/Results.cs
index 4974966aa9..2ffb1660c1 100644
--- a/osu.Game/GameModes/Play/Results.cs
+++ b/osu.Game/GameModes/Ranking/Results.cs
@@ -1,16 +1,11 @@
//Copyright (c) 2007-2016 ppy Pty Ltd .
//Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using osu.Framework.GameModes;
using osu.Game.GameModes.Backgrounds;
using OpenTK.Graphics;
-namespace osu.Game.GameModes.Play
+namespace osu.Game.GameModes.Ranking
{
class Results : GameModeWhiteBox
{
diff --git a/osu.Game/Graphics/UserInterface/PercentageCounter.cs b/osu.Game/Graphics/UserInterface/PercentageCounter.cs
index b12126deb6..b045089dcd 100644
--- a/osu.Game/Graphics/UserInterface/PercentageCounter.cs
+++ b/osu.Game/Graphics/UserInterface/PercentageCounter.cs
@@ -57,11 +57,6 @@ namespace osu.Game.Graphics.UserInterface
base.Apply(d);
(d as PercentageCounter).DisplayedCount = CurrentValue;
}
-
- public TransformAccuracy(IClock clock)
- : base(clock)
- {
- }
}
}
}
diff --git a/osu.Game/Graphics/UserInterface/RollingCounter.cs b/osu.Game/Graphics/UserInterface/RollingCounter.cs
index 69e7b6e495..33a1677bd9 100644
--- a/osu.Game/Graphics/UserInterface/RollingCounter.cs
+++ b/osu.Game/Graphics/UserInterface/RollingCounter.cs
@@ -194,14 +194,12 @@ namespace osu.Game.Graphics.UserInterface
///
protected virtual void TransformCount(T currentValue, T newValue)
{
- object[] parameters = { Clock };
-
Debug.Assert(
TransformType.IsSubclassOf(typeof(Transform)) || TransformType == typeof(Transform),
@"transformType should be a subclass of Transform."
);
- TransformCount((Transform)Activator.CreateInstance(TransformType, parameters), currentValue, newValue);
+ TransformCount((Transform)Activator.CreateInstance(TransformType), currentValue, newValue);
}
///
diff --git a/osu.Game/Graphics/UserInterface/ScoreCounter.cs b/osu.Game/Graphics/UserInterface/ScoreCounter.cs
index eb857a3207..48f4da1fcf 100644
--- a/osu.Game/Graphics/UserInterface/ScoreCounter.cs
+++ b/osu.Game/Graphics/UserInterface/ScoreCounter.cs
@@ -56,11 +56,11 @@ namespace osu.Game.Graphics.UserInterface
protected class TransformScore : Transform
{
- public override ulong CurrentValue
+ protected override ulong CurrentValue
{
get
{
- double time = Time;
+ double time = CurrentTime ?? 0;
if (time < StartTime) return StartValue;
if (time >= EndTime) return EndValue;
@@ -73,11 +73,6 @@ namespace osu.Game.Graphics.UserInterface
base.Apply(d);
(d as ScoreCounter).DisplayedCount = CurrentValue;
}
-
- public TransformScore(IClock clock)
- : base(clock)
- {
- }
}
}
}
diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs
index 549e79b800..2515ace38e 100644
--- a/osu.Game/OsuGame.cs
+++ b/osu.Game/OsuGame.cs
@@ -70,7 +70,10 @@ namespace osu.Game
RelativeSizeAxes = Axes.Both,
ActivateRequested = delegate { volume.Show(); }
},
- intro = new Intro(),
+ intro = new Intro
+ {
+ Beatmap = Beatmap
+ },
Toolbar = new Toolbar
{
OnHome = delegate { MainMenu?.MakeCurrent(); },
diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs
index 4df5683493..bfa07d72c8 100644
--- a/osu.Game/OsuGameBase.cs
+++ b/osu.Game/OsuGameBase.cs
@@ -1,10 +1,13 @@
-using osu.Framework;
+using System;
+using osu.Framework;
+using osu.Framework.Configuration;
using osu.Framework.GameModes;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Textures;
using osu.Framework.IO.Stores;
+using osu.Game.Beatmaps;
using osu.Game.Beatmaps.IO;
using osu.Game.Configuration;
using osu.Game.Database;
@@ -32,6 +35,8 @@ namespace osu.Game
public CursorContainer Cursor;
+ public readonly Bindable Beatmap = new Bindable();
+
public OsuGameBase()
{
AddInternal(ratioContainer = new RatioAdjust());
@@ -41,6 +46,13 @@ namespace osu.Game
Options = new Options(),
Cursor = new OsuCursorContainer()
};
+
+ Beatmap.ValueChanged += Beatmap_ValueChanged;
+ }
+
+ private void Beatmap_ValueChanged(object sender, EventArgs e)
+ {
+ throw new NotImplementedException();
}
public override void Load(BaseGame game)
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index f044ef9a6e..b73bc8ffda 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -64,6 +64,7 @@
+
@@ -124,7 +125,7 @@
-
+