diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj
index e4e9807754..4a1798feb4 100644
--- a/osu.Desktop/osu.Desktop.csproj
+++ b/osu.Desktop/osu.Desktop.csproj
@@ -135,8 +135,8 @@
$(SolutionDir)\packages\squirrel.windows.1.7.8\lib\Net45\NuGet.Squirrel.dll
True
-
- $(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll
+
+ $(SolutionDir)\packages\OpenTK.3.0.0-git00021\lib\net20\OpenTK.dll
True
diff --git a/osu.Desktop/packages.config b/osu.Desktop/packages.config
index 6b6361b578..e7233a42ac 100644
--- a/osu.Desktop/packages.config
+++ b/osu.Desktop/packages.config
@@ -6,7 +6,7 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
-
+
diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs
index 8e496c3b0c..7d0d80a0ce 100644
--- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs
+++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs
@@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Catch.Objects
StartTime = lastTickTime,
ComboColour = ComboColour,
X = Curve.PositionAt(distanceProgress).X / CatchPlayfield.BASE_WIDTH,
- Samples = new SampleInfoList(Samples.Select(s => new SampleInfo
+ Samples = new List(Samples.Select(s => new SampleInfo
{
Bank = s.Bank,
Name = @"slidertick",
@@ -108,7 +108,7 @@ namespace osu.Game.Rulesets.Catch.Objects
StartTime = repeatStartTime + t,
ComboColour = ComboColour,
X = Curve.PositionAt(progress).X / CatchPlayfield.BASE_WIDTH,
- Samples = new SampleInfoList(Samples.Select(s => new SampleInfo
+ Samples = new List(Samples.Select(s => new SampleInfo
{
Bank = s.Bank,
Name = @"slidertick",
@@ -147,7 +147,7 @@ namespace osu.Game.Rulesets.Catch.Objects
set { Curve.ControlPoints = value; }
}
- public List RepeatSamples { get; set; } = new List();
+ public List> RepeatSamples { get; set; } = new List>();
public CurveType CurveType
{
diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj
index b03c8d2eea..578d8eb34d 100644
--- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj
+++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj
@@ -36,8 +36,8 @@
$(SolutionDir)\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll
True
-
- $(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll
+
+ $(SolutionDir)\packages\OpenTK.3.0.0-git00021\lib\net20\OpenTK.dll
True
diff --git a/osu.Game.Rulesets.Catch/packages.config b/osu.Game.Rulesets.Catch/packages.config
index cde428acea..2369f7529b 100644
--- a/osu.Game.Rulesets.Catch/packages.config
+++ b/osu.Game.Rulesets.Catch/packages.config
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs
index d5a799b4ed..407d4db143 100644
--- a/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs
+++ b/osu.Game.Rulesets.Mania/Beatmaps/ManiaBeatmapConverter.cs
@@ -192,7 +192,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
///
/// The time to retrieve the sample info list from.
///
- private SampleInfoList sampleInfoListAt(double time)
+ private List sampleInfoListAt(double time)
{
var curveData = HitObject as IHasCurve;
diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs
index 270c264e0c..8251dea5f7 100644
--- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.cs
+++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/DistanceObjectPatternGenerator.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.Game.Audio;
using osu.Game.Beatmaps;
@@ -435,7 +436,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
///
/// The time to retrieve the sample info list from.
///
- private SampleInfoList sampleInfoListAt(double time)
+ private List sampleInfoListAt(double time)
{
var curveData = HitObject as IHasCurve;
diff --git a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs
index 3e9fc1ae27..8e832960df 100644
--- a/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.cs
+++ b/osu.Game.Rulesets.Mania/Beatmaps/Patterns/Legacy/EndTimeObjectPatternGenerator.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.Collections.Generic;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mania.MathUtils;
using osu.Game.Rulesets.Objects;
@@ -77,7 +78,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
};
if (hold.Head.Samples == null)
- hold.Head.Samples = new SampleInfoList();
+ hold.Head.Samples = new List();
hold.Head.Samples.Add(new SampleInfo { Name = SampleInfo.HIT_NORMAL });
diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj
index 26181164f9..bdd6656ed9 100644
--- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj
+++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj
@@ -36,8 +36,8 @@
$(SolutionDir)\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll
True
-
- $(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll
+
+ $(SolutionDir)\packages\OpenTK.3.0.0-git00021\lib\net20\OpenTK.dll
True
diff --git a/osu.Game.Rulesets.Mania/packages.config b/osu.Game.Rulesets.Mania/packages.config
index cde428acea..2369f7529b 100644
--- a/osu.Game.Rulesets.Mania/packages.config
+++ b/osu.Game.Rulesets.Mania/packages.config
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Osu/Objects/Slider.cs b/osu.Game.Rulesets.Osu/Objects/Slider.cs
index 4f5a44e61d..5f9f11c783 100644
--- a/osu.Game.Rulesets.Osu/Objects/Slider.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Slider.cs
@@ -57,7 +57,7 @@ namespace osu.Game.Rulesets.Osu.Objects
///
internal float LazyTravelDistance;
- public List RepeatSamples { get; set; } = new List();
+ public List> RepeatSamples { get; set; } = new List>();
public int RepeatCount { get; set; } = 1;
private int stackHeight;
@@ -138,7 +138,7 @@ namespace osu.Game.Rulesets.Osu.Objects
StackHeight = StackHeight,
Scale = Scale,
ComboColour = ComboColour,
- Samples = new SampleInfoList(Samples.Select(s => new SampleInfo
+ Samples = new List(Samples.Select(s => new SampleInfo
{
Bank = s.Bank,
Name = @"slidertick",
@@ -170,7 +170,7 @@ namespace osu.Game.Rulesets.Osu.Objects
StackHeight = StackHeight,
Scale = Scale,
ComboColour = ComboColour,
- Samples = new SampleInfoList(RepeatSamples[repeat])
+ Samples = new List(RepeatSamples[repeat])
});
}
}
diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
index ec71869adb..6e61d7fb2d 100644
--- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
+++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
@@ -37,8 +37,8 @@
$(SolutionDir)\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll
True
-
- $(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll
+
+ $(SolutionDir)\packages\OpenTK.3.0.0-git00021\lib\net20\OpenTK.dll
True
diff --git a/osu.Game.Rulesets.Osu/packages.config b/osu.Game.Rulesets.Osu/packages.config
index cde428acea..2369f7529b 100644
--- a/osu.Game.Rulesets.Osu/packages.config
+++ b/osu.Game.Rulesets.Osu/packages.config
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs
new file mode 100644
index 0000000000..9d0037b97a
--- /dev/null
+++ b/osu.Game.Rulesets.Taiko/Audio/DrumSampleMapping.cs
@@ -0,0 +1,47 @@
+// Copyright (c) 2007-2017 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System.Collections.Generic;
+using System.Linq;
+using osu.Framework.Audio;
+using osu.Framework.Audio.Sample;
+using osu.Game.Audio;
+using osu.Game.Beatmaps.ControlPoints;
+
+namespace osu.Game.Rulesets.Taiko.Audio
+{
+ public class DrumSampleMapping
+ {
+ private readonly ControlPointInfo controlPoints;
+ private readonly Dictionary mappings = new Dictionary();
+
+ public DrumSampleMapping(ControlPointInfo controlPoints, AudioManager audio)
+ {
+ this.controlPoints = controlPoints;
+
+ IEnumerable samplePoints;
+ if (controlPoints.SamplePoints.Count == 0)
+ // Get the default sample point
+ samplePoints = new[] { controlPoints.SamplePointAt(double.MinValue) };
+ else
+ samplePoints = controlPoints.SamplePoints;
+
+ foreach (var s in samplePoints.Distinct())
+ {
+ mappings[s] = new DrumSample
+ {
+ Centre = s.GetSampleInfo().GetChannel(audio.Sample),
+ Rim = s.GetSampleInfo(SampleInfo.HIT_CLAP).GetChannel(audio.Sample)
+ };
+ }
+ }
+
+ public DrumSample SampleAt(double time) => mappings[controlPoints.SamplePointAt(time)];
+
+ public class DrumSample
+ {
+ public SampleChannel Centre;
+ public SampleChannel Rim;
+ }
+ }
+}
diff --git a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs
index 9b4a6c47a9..690b80b12c 100644
--- a/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs
+++ b/osu.Game.Rulesets.Taiko/Beatmaps/TaikoBeatmapConverter.cs
@@ -78,7 +78,7 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
var curveData = obj as IHasCurve;
// Old osu! used hit sounding to determine various hit type information
- SampleInfoList samples = obj.Samples;
+ List samples = obj.Samples;
bool strong = samples.Any(s => s.Name == SampleInfo.HIT_FINISH);
@@ -115,12 +115,12 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
if (!isForCurrentRuleset && tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength)
{
- List allSamples = curveData != null ? curveData.RepeatSamples : new List(new[] { samples });
+ List> allSamples = curveData != null ? curveData.RepeatSamples : new List>(new[] { samples });
int i = 0;
for (double j = obj.StartTime; j <= obj.StartTime + taikoDuration + tickSpacing / 8; j += tickSpacing)
{
- SampleInfoList currentSamples = allSamples[i];
+ List currentSamples = allSamples[i];
bool isRim = currentSamples.Any(s => s.Name == SampleInfo.HIT_CLAP || s.Name == SampleInfo.HIT_WHISTLE);
strong = currentSamples.Any(s => s.Name == SampleInfo.HIT_FINISH);
diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs
index df33aae94e..fd35f0eaec 100644
--- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs
+++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs
@@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
validKeyPressed = HitActions.Contains(action);
// Only count this as handled if the new judgement is a hit
- return UpdateJudgement(true) && Judgements.LastOrDefault()?.IsHit == true;
+ return UpdateJudgement(true);
}
protected override void Update()
diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs
index 81b23af1a9..cda82afe0e 100644
--- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs
+++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHitStrong.cs
@@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
if (!userTriggered)
{
if (timeOffset > second_hit_window)
- AddJudgement(new TaikoStrongHitJudgement { Result = HitResult.Miss });
+ AddJudgement(new TaikoStrongHitJudgement { Result = HitResult.None });
return;
}
@@ -83,7 +83,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
return false;
// Assume the intention was to hit the strong hit with both keys only if the first key is still being held down
- return firstKeyHeld && UpdateJudgement(true) && Judgements.LastOrDefault()?.IsHit == true;
+ return firstKeyHeld && UpdateJudgement(true);
}
}
}
diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs
index 738902846b..5ca33aaea2 100644
--- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs
+++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs
@@ -34,10 +34,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
private readonly CircularContainer targetRing;
private readonly CircularContainer expandingRing;
- private readonly TaikoAction[] rimActions = { TaikoAction.LeftRim, TaikoAction.RightRim };
- private readonly TaikoAction[] centreActions = { TaikoAction.LeftCentre, TaikoAction.RightCentre };
- private TaikoAction[] lastAction;
-
///
/// The amount of times the user has hit this swell.
///
@@ -205,19 +201,20 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
}
}
+ private bool? lastWasCentre;
+
public override bool OnPressed(TaikoAction action)
{
// Don't handle keys before the swell starts
if (Time.Current < HitObject.StartTime)
return false;
- // Find the keyset which this key corresponds to
- var keySet = rimActions.Contains(action) ? rimActions : centreActions;
+ var isCentre = action == TaikoAction.LeftCentre || action == TaikoAction.RightCentre;
- // Ensure alternating keysets
- if (keySet == lastAction)
+ // Ensure alternating centre and rim hits
+ if (lastWasCentre == isCentre)
return false;
- lastAction = keySet;
+ lastWasCentre = isCentre;
UpdateJudgement(true);
diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs
index 7976cbbbc1..92da3fe09e 100644
--- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs
+++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableTaikoHitObject.cs
@@ -6,6 +6,9 @@ using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces;
using OpenTK;
+using System.Linq;
+using osu.Game.Audio;
+using System.Collections.Generic;
namespace osu.Game.Rulesets.Taiko.Objects.Drawables
{
@@ -35,6 +38,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
MainPiece.KiaiMode = HitObject.Kiai;
}
+ // Normal and clap samples are handled by the drum
+ protected override IEnumerable GetSamples() => HitObject.Samples.Where(s => s.Name != SampleInfo.HIT_NORMAL && s.Name != SampleInfo.HIT_CLAP);
+
protected virtual TaikoPiece CreateMainPiece() => new CirclePiece();
public abstract bool OnPressed(TaikoAction action);
diff --git a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs
index 4104b59979..5a566fd091 100644
--- a/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs
+++ b/osu.Game.Rulesets.Taiko/Objects/DrumRoll.cs
@@ -3,6 +3,7 @@
using osu.Game.Rulesets.Objects.Types;
using System;
+using System.Collections.Generic;
using System.Linq;
using osu.Game.Audio;
using osu.Game.Beatmaps;
@@ -75,7 +76,7 @@ namespace osu.Game.Rulesets.Taiko.Objects
TickSpacing = tickSpacing,
StartTime = t,
IsStrong = IsStrong,
- Samples = new SampleInfoList(Samples.Select(s => new SampleInfo
+ Samples = new List(Samples.Select(s => new SampleInfo
{
Bank = s.Bank,
Name = @"slidertick",
diff --git a/osu.Game.Rulesets.Taiko/Objects/Swell.cs b/osu.Game.Rulesets.Taiko/Objects/Swell.cs
index f74a543ca9..cd2876ea2d 100644
--- a/osu.Game.Rulesets.Taiko/Objects/Swell.cs
+++ b/osu.Game.Rulesets.Taiko/Objects/Swell.cs
@@ -16,4 +16,4 @@ namespace osu.Game.Rulesets.Taiko.Objects
///
public int RequiredHits = 10;
}
-}
\ No newline at end of file
+}
diff --git a/osu.Game.Rulesets.Taiko/Tests/TestCaseTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/Tests/TestCaseTaikoPlayfield.cs
index bca4806108..b1e6e9c4ce 100644
--- a/osu.Game.Rulesets.Taiko/Tests/TestCaseTaikoPlayfield.cs
+++ b/osu.Game.Rulesets.Taiko/Tests/TestCaseTaikoPlayfield.cs
@@ -165,11 +165,15 @@ namespace osu.Game.Rulesets.Taiko.Tests
private void addSwell(double duration = default_duration)
{
- rulesetContainer.Playfield.Add(new DrawableSwell(new Swell
+ var swell = new Swell
{
StartTime = rulesetContainer.Playfield.Time.Current + scroll_time,
Duration = duration,
- }));
+ };
+
+ swell.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
+
+ rulesetContainer.Playfield.Add(new DrawableSwell(swell));
}
private void addDrumRoll(bool strong, double duration = default_duration)
@@ -184,6 +188,8 @@ namespace osu.Game.Rulesets.Taiko.Tests
Duration = duration,
};
+ d.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
+
rulesetContainer.Playfield.Add(new DrawableDrumRoll(d));
}
@@ -195,6 +201,8 @@ namespace osu.Game.Rulesets.Taiko.Tests
IsStrong = strong
};
+ h.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
+
if (strong)
rulesetContainer.Playfield.Add(new DrawableCentreHitStrong(h));
else
@@ -209,6 +217,8 @@ namespace osu.Game.Rulesets.Taiko.Tests
IsStrong = strong
};
+ h.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty());
+
if (strong)
rulesetContainer.Playfield.Add(new DrawableRimHitStrong(h));
else
diff --git a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs
index 5e79166bec..bf1274256b 100644
--- a/osu.Game.Rulesets.Taiko/UI/InputDrum.cs
+++ b/osu.Game.Rulesets.Taiko/UI/InputDrum.cs
@@ -4,12 +4,15 @@
using System;
using OpenTK;
using osu.Framework.Allocation;
+using osu.Framework.Audio;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Framework.Input.Bindings;
+using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Graphics;
+using osu.Game.Rulesets.Taiko.Audio;
namespace osu.Game.Rulesets.Taiko.UI
{
@@ -18,16 +21,26 @@ namespace osu.Game.Rulesets.Taiko.UI
///
internal class InputDrum : Container
{
- public InputDrum()
+ private const float middle_split = 0.025f;
+
+ private readonly ControlPointInfo controlPoints;
+
+ public InputDrum(ControlPointInfo controlPoints)
{
+ this.controlPoints = controlPoints;
+
RelativeSizeAxes = Axes.Both;
FillMode = FillMode.Fit;
+ }
- const float middle_split = 0.025f;
+ [BackgroundDependencyLoader]
+ private void load(AudioManager audio)
+ {
+ var sampleMappings = new DrumSampleMapping(controlPoints, audio);
Children = new Drawable[]
{
- new TaikoHalfDrum(false)
+ new TaikoHalfDrum(false, sampleMappings)
{
Name = "Left Half",
Anchor = Anchor.Centre,
@@ -38,7 +51,7 @@ namespace osu.Game.Rulesets.Taiko.UI
RimAction = TaikoAction.LeftRim,
CentreAction = TaikoAction.LeftCentre
},
- new TaikoHalfDrum(true)
+ new TaikoHalfDrum(true, sampleMappings)
{
Name = "Right Half",
Anchor = Anchor.Centre,
@@ -72,8 +85,12 @@ namespace osu.Game.Rulesets.Taiko.UI
private readonly Sprite centre;
private readonly Sprite centreHit;
- public TaikoHalfDrum(bool flipped)
+ private readonly DrumSampleMapping sampleMappings;
+
+ public TaikoHalfDrum(bool flipped, DrumSampleMapping sampleMappings)
{
+ this.sampleMappings = sampleMappings;
+
Masking = true;
Children = new Drawable[]
@@ -128,15 +145,21 @@ namespace osu.Game.Rulesets.Taiko.UI
Drawable target = null;
Drawable back = null;
+ var drumSample = sampleMappings.SampleAt(Time.Current);
+
if (action == CentreAction)
{
target = centreHit;
back = centre;
+
+ drumSample.Centre.Play();
}
else if (action == RimAction)
{
target = rimHit;
back = rim;
+
+ drumSample.Rim.Play();
}
if (target != null)
diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs
index 2cc95fc981..3fdbd056ce 100644
--- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs
+++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs
@@ -16,17 +16,11 @@ using osu.Framework.Extensions.Color4Extensions;
using System.Linq;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Taiko.Objects.Drawables;
-using osu.Framework.Input.Bindings;
using osu.Game.Beatmaps.ControlPoints;
-using osu.Framework.Audio;
-using osu.Framework.Audio.Sample;
-using System.Collections.Generic;
-using osu.Game.Audio;
-using System;
namespace osu.Game.Rulesets.Taiko.UI
{
- public class TaikoPlayfield : ScrollingPlayfield, IKeyBindingHandler
+ public class TaikoPlayfield : ScrollingPlayfield
{
///
/// Default height of a when inside a .
@@ -61,13 +55,9 @@ namespace osu.Game.Rulesets.Taiko.UI
private readonly Box overlayBackground;
private readonly Box background;
- private readonly ControlPointInfo controlPointInfo;
- private Dictionary drumSampleMappings;
-
- public TaikoPlayfield(ControlPointInfo controlPointInfo)
+ public TaikoPlayfield(ControlPointInfo controlPoints)
: base(Axes.X)
{
- this.controlPointInfo = controlPointInfo;
AddRangeInternal(new Drawable[]
{
backgroundContainer = new Container
@@ -160,7 +150,7 @@ namespace osu.Game.Rulesets.Taiko.UI
{
RelativeSizeAxes = Axes.Both,
},
- new InputDrum
+ new InputDrum(controlPoints)
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
@@ -205,19 +195,8 @@ namespace osu.Game.Rulesets.Taiko.UI
}
[BackgroundDependencyLoader]
- private void load(OsuColour colours, AudioManager audio)
+ private void load(OsuColour colours)
{
- drumSampleMappings = new Dictionary();
- foreach (var s in controlPointInfo.SamplePoints)
- {
- drumSampleMappings.Add(s,
- new DrumSamples
- {
- Centre = s.GetSampleInfo().GetChannel(audio.Sample),
- Rim = s.GetSampleInfo(SampleInfo.HIT_CLAP).GetChannel(audio.Sample)
- });
- }
-
overlayBackgroundContainer.BorderColour = colours.Gray0;
overlayBackground.Colour = colours.Gray1;
@@ -282,28 +261,5 @@ namespace osu.Game.Rulesets.Taiko.UI
kiaiExplosionContainer.Add(new KiaiHitExplosion(judgedObject, isRim));
}
}
-
- public bool OnPressed(TaikoAction action)
- {
- var samplePoint = controlPointInfo.SamplePointAt(Clock.CurrentTime);
-
- if (!drumSampleMappings.TryGetValue(samplePoint, out var samples))
- throw new InvalidOperationException("Current sample set not found.");
-
- if (action == TaikoAction.LeftCentre || action == TaikoAction.RightCentre)
- samples.Centre.Play();
- else
- samples.Rim.Play();
-
- return true;
- }
-
- public bool OnReleased(TaikoAction action) => false;
-
- private class DrumSamples
- {
- public SampleChannel Centre;
- public SampleChannel Rim;
- }
}
}
diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj
index bb02db62b9..f73831a952 100644
--- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj
+++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj
@@ -36,14 +36,15 @@
$(SolutionDir)\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll
True
-
- $(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll
+
+ $(SolutionDir)\packages\OpenTK.3.0.0-git00021\lib\net20\OpenTK.dll
True
+
diff --git a/osu.Game.Rulesets.Taiko/packages.config b/osu.Game.Rulesets.Taiko/packages.config
index cde428acea..2369f7529b 100644
--- a/osu.Game.Rulesets.Taiko/packages.config
+++ b/osu.Game.Rulesets.Taiko/packages.config
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs
index 0168cedc86..3a50e43239 100644
--- a/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs
+++ b/osu.Game.Tests/Visual/TestCaseBeatmapInfoWedge.cs
@@ -1,69 +1,161 @@
// 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 System.Linq;
using OpenTK;
using osu.Framework.Allocation;
using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
+using osu.Game.Graphics.Sprites;
+using osu.Game.Rulesets;
+using osu.Game.Rulesets.Objects;
+using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Select;
+using osu.Game.Tests.Beatmaps;
namespace osu.Game.Tests.Visual
{
public class TestCaseBeatmapInfoWedge : OsuTestCase
{
- private BeatmapManager beatmaps;
- private readonly Random random;
- private readonly BeatmapInfoWedge infoWedge;
+ private RulesetStore rulesets;
+ private TestBeatmapInfoWedge infoWedge;
+ private readonly List beatmaps = new List();
private readonly Bindable beatmap = new Bindable();
- public TestCaseBeatmapInfoWedge()
+ [BackgroundDependencyLoader]
+ private void load(OsuGameBase game, RulesetStore rulesets)
{
- random = new Random(0123);
+ this.rulesets = rulesets;
- Add(infoWedge = new BeatmapInfoWedge
+ beatmap.BindTo(game.Beatmap);
+ }
+
+ protected override void LoadComplete()
+ {
+ base.LoadComplete();
+
+ Add(infoWedge = new TestBeatmapInfoWedge
{
Size = new Vector2(0.5f, 245),
RelativeSizeAxes = Axes.X,
- Margin = new MarginPadding
- {
- Top = 20,
- },
+ Margin = new MarginPadding { Top = 20 }
});
AddStep("show", () =>
{
- Content.FadeInFromZero(250);
infoWedge.State = Visibility.Visible;
infoWedge.UpdateBeatmap(beatmap);
});
- AddStep("hide", () =>
+
+ AddWaitStep(3);
+
+ AddStep("hide", () => { infoWedge.State = Visibility.Hidden; });
+
+ AddWaitStep(3);
+
+ AddStep("show", () => { infoWedge.State = Visibility.Visible; });
+
+ foreach (var rulesetInfo in rulesets.AvailableRulesets)
{
- infoWedge.State = Visibility.Hidden;
- Content.FadeOut(100);
+ var ruleset = rulesetInfo.CreateInstance();
+ beatmaps.Add(createTestBeatmap(rulesetInfo));
+
+ var name = rulesetInfo.ShortName;
+ selectBeatmap(name);
+
+ // TODO: adjust cases once more info is shown for other gamemodes
+ switch (ruleset)
+ {
+ case OsuRuleset osu:
+ testOsuBeatmap(osu);
+ testInfoLabels(5);
+ break;
+ default:
+ testInfoLabels(2);
+ break;
+ }
+ }
+
+ testNullBeatmap();
+ }
+
+ private void testOsuBeatmap(OsuRuleset ruleset)
+ {
+ AddAssert("check version", () => infoWedge.Info.VersionLabel.Text == $"{ruleset.ShortName}Version");
+ AddAssert("check title", () => infoWedge.Info.TitleLabel.Text == $"{ruleset.ShortName}Source — {ruleset.ShortName}Title");
+ AddAssert("check artist", () => infoWedge.Info.ArtistLabel.Text == $"{ruleset.ShortName}Artist");
+ AddAssert("check author", () => infoWedge.Info.MapperContainer.Children.OfType().Any(s => s.Text == $"{ruleset.ShortName}Author"));
+ }
+
+ private void testInfoLabels(int expectedCount)
+ {
+ AddAssert("check infolabels exists", () => infoWedge.Info.InfoLabelContainer.Children.Any());
+ AddAssert("check infolabels count", () => infoWedge.Info.InfoLabelContainer.Children.Count == expectedCount);
+ }
+
+ private void testNullBeatmap()
+ {
+ selectNullBeatmap();
+ AddAssert("check empty version", () => string.IsNullOrEmpty(infoWedge.Info.VersionLabel.Text));
+ AddAssert("check default title", () => infoWedge.Info.TitleLabel.Text == beatmap.Default.BeatmapInfo.Metadata.Title);
+ AddAssert("check default artist", () => infoWedge.Info.ArtistLabel.Text == beatmap.Default.BeatmapInfo.Metadata.Artist);
+ AddAssert("check empty author", () => !infoWedge.Info.MapperContainer.Children.Any());
+ AddAssert("check no infolabels", () => !infoWedge.Info.InfoLabelContainer.Children.Any());
+ }
+
+ private void selectBeatmap(string name)
+ {
+ var infoBefore = infoWedge.Info;
+
+ AddStep($"select {name} beatmap", () =>
+ {
+ beatmap.Value = new TestWorkingBeatmap(beatmaps.First(b => b.BeatmapInfo.Ruleset.ShortName == name));
+ infoWedge.UpdateBeatmap(beatmap);
});
- AddStep("random beatmap", randomBeatmap);
- AddStep("null beatmap", () => infoWedge.UpdateBeatmap(beatmap.Default));
+
+ AddUntilStep(() => infoWedge.Info != infoBefore, "wait for async load");
}
- [BackgroundDependencyLoader]
- private void load(OsuGameBase game, BeatmapManager beatmaps)
+ private void selectNullBeatmap()
{
- this.beatmaps = beatmaps;
- beatmap.BindTo(game.Beatmap);
+ AddStep("select null beatmap", () =>
+ {
+ beatmap.Value = beatmap.Default;
+ infoWedge.UpdateBeatmap(beatmap);
+ });
}
- private void randomBeatmap()
+ private Beatmap createTestBeatmap(RulesetInfo ruleset)
{
- var sets = beatmaps.GetAllUsableBeatmapSets();
- if (sets.Count == 0)
- return;
+ List objects = new List();
+ for (double i = 0; i < 50000; i += 1000)
+ objects.Add(new HitObject { StartTime = i });
- var b = sets[random.Next(0, sets.Count)].Beatmaps[0];
- beatmap.Value = beatmaps.GetWorkingBeatmap(b);
- infoWedge.UpdateBeatmap(beatmap);
+ return new Beatmap
+ {
+ BeatmapInfo = new BeatmapInfo
+ {
+ Metadata = new BeatmapMetadata
+ {
+ AuthorString = $"{ruleset.ShortName}Author",
+ Artist = $"{ruleset.ShortName}Artist",
+ Source = $"{ruleset.ShortName}Source",
+ Title = $"{ruleset.ShortName}Title"
+ },
+ Ruleset = ruleset,
+ StarDifficulty = 6,
+ Version = $"{ruleset.ShortName}Version"
+ },
+ HitObjects = objects
+ };
+ }
+
+ private class TestBeatmapInfoWedge : BeatmapInfoWedge
+ {
+ public new BufferedWedgeInfo Info => base.Info;
}
}
}
diff --git a/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs b/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs
index b93c2d812f..a83cead213 100644
--- a/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs
+++ b/osu.Game.Tests/Visual/TestCaseNotificationOverlay.cs
@@ -1,9 +1,11 @@
// 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 System.Linq;
using osu.Framework.Graphics;
+using osu.Framework.Graphics.Sprites;
using osu.Framework.MathUtils;
using osu.Game.Overlays;
using osu.Game.Overlays.Notifications;
@@ -15,6 +17,15 @@ namespace osu.Game.Tests.Visual
private readonly NotificationOverlay manager;
private readonly List progressingNotifications = new List();
+ public override IReadOnlyList RequiredTypes => new[]
+ {
+ typeof(Notification),
+ typeof(ProgressNotification),
+ typeof(ProgressCompletionNotification),
+ typeof(SimpleNotification),
+ typeof(IHasCompletionTarget),
+ };
+
public TestCaseNotificationOverlay()
{
progressingNotifications.Clear();
@@ -25,6 +36,12 @@ namespace osu.Game.Tests.Visual
Origin = Anchor.TopRight
});
+ SpriteText displayedCount = new SpriteText();
+
+ Content.Add(displayedCount);
+
+ manager.UnreadCount.ValueChanged += count => { displayedCount.Text = $"displayed count: {count}"; };
+
AddStep(@"toggle", manager.ToggleVisibility);
AddStep(@"simple #1", sendHelloNotification);
AddStep(@"simple #2", sendAmazingNotification);
diff --git a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs b/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs
index 6435df7c2c..18e40db064 100644
--- a/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs
+++ b/osu.Game.Tests/Visual/TestCasePlaySongSelect.cs
@@ -26,6 +26,7 @@ namespace osu.Game.Tests.Visual
private RulesetStore rulesets;
private DependencyContainer dependencies;
+ private WorkingBeatmap defaultBeatmap;
public override IReadOnlyList RequiredTypes => new[]
{
@@ -47,31 +48,61 @@ namespace osu.Game.Tests.Visual
protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(parent);
+ private class TestSongSelect : PlaySongSelect
+ {
+ public WorkingBeatmap CurrentBeatmap => Beatmap.Value;
+ public new BeatmapCarousel Carousel => base.Carousel;
+ }
+
[BackgroundDependencyLoader]
private void load(BeatmapManager baseManager)
{
- PlaySongSelect songSelect;
+ TestSongSelect songSelect = null;
- if (manager == null)
+ var storage = new TestStorage(@"TestCasePlaySongSelect");
+
+ // this is by no means clean. should be replacing inside of OsuGameBase somehow.
+ var context = new OsuDbContext();
+
+ Func contextFactory = () => context;
+
+ dependencies.Cache(rulesets = new RulesetStore(contextFactory));
+ dependencies.Cache(manager = new BeatmapManager(storage, contextFactory, rulesets, null)
{
- var storage = new TestStorage(@"TestCasePlaySongSelect");
+ DefaultBeatmap = defaultBeatmap = baseManager.GetWorkingBeatmap(null)
+ });
- // this is by no means clean. should be replacing inside of OsuGameBase somehow.
- var context = new OsuDbContext();
+ void loadNewSongSelect(bool deleteMaps = false) => AddStep("reload song select", () =>
+ {
+ if (deleteMaps) manager.DeleteAll();
- Func contextFactory = () => context;
-
- dependencies.Cache(rulesets = new RulesetStore(contextFactory));
- dependencies.Cache(manager = new BeatmapManager(storage, contextFactory, rulesets, null)
+ if (songSelect != null)
{
- DefaultBeatmap = baseManager.GetWorkingBeatmap(null)
- });
+ Remove(songSelect);
+ songSelect.Dispose();
+ }
+ Add(songSelect = new TestSongSelect());
+ });
+
+ loadNewSongSelect(true);
+
+ AddWaitStep(3);
+
+ AddAssert("dummy selected", () => songSelect.CurrentBeatmap == defaultBeatmap);
+
+ AddStep("import test maps", () =>
+ {
for (int i = 0; i < 100; i += 10)
manager.Import(createTestBeatmapSet(i));
- }
+ });
- Add(songSelect = new PlaySongSelect());
+ AddWaitStep(3);
+ AddAssert("random map selected", () => songSelect.CurrentBeatmap != defaultBeatmap);
+
+ loadNewSongSelect();
+ AddWaitStep(3);
+ AddAssert("random map selected", () => songSelect.CurrentBeatmap != defaultBeatmap);
AddStep(@"Sort by Artist", delegate { songSelect.FilterControl.Sort = SortMode.Artist; });
AddStep(@"Sort by Title", delegate { songSelect.FilterControl.Sort = SortMode.Title; });
diff --git a/osu.Game.Tests/Visual/TestCasePopupDialog.cs b/osu.Game.Tests/Visual/TestCasePopupDialog.cs
new file mode 100644
index 0000000000..ed9c47a253
--- /dev/null
+++ b/osu.Game.Tests/Visual/TestCasePopupDialog.cs
@@ -0,0 +1,37 @@
+// Copyright (c) 2007-2017 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using osu.Framework.Graphics;
+using osu.Game.Graphics;
+using osu.Game.Overlays.Dialog;
+
+namespace osu.Game.Tests.Visual
+{
+ public class TestCasePopupDialog : OsuTestCase
+ {
+ public TestCasePopupDialog()
+ {
+ var popup = new PopupDialog
+ {
+ RelativeSizeAxes = Axes.Both,
+ State = Framework.Graphics.Containers.Visibility.Visible,
+ Icon = FontAwesome.fa_assistive_listening_systems,
+ HeaderText = @"This is a test popup",
+ BodyText = "I can say lots of stuff and even wrap my words!",
+ Buttons = new PopupDialogButton[]
+ {
+ new PopupDialogCancelButton
+ {
+ Text = @"Yes. That you can.",
+ },
+ new PopupDialogOkButton
+ {
+ Text = @"You're a fake!",
+ },
+ }
+ };
+
+ Add(popup);
+ }
+ }
+}
diff --git a/osu.Game.Tests/Visual/TestCaseToolbar.cs b/osu.Game.Tests/Visual/TestCaseToolbar.cs
new file mode 100644
index 0000000000..9f538af09b
--- /dev/null
+++ b/osu.Game.Tests/Visual/TestCaseToolbar.cs
@@ -0,0 +1,39 @@
+// 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 System.Linq;
+using osu.Framework.Graphics.Containers;
+using osu.Game.Overlays.Toolbar;
+
+namespace osu.Game.Tests.Visual
+{
+ public class TestCaseToolbar : OsuTestCase
+ {
+ public override IReadOnlyList RequiredTypes => new[]
+ {
+ typeof(ToolbarButton),
+ typeof(ToolbarModeSelector),
+ typeof(ToolbarModeButton),
+ typeof(ToolbarNotificationButton),
+ };
+
+ public TestCaseToolbar()
+ {
+ var toolbar = new Toolbar { State = Visibility.Visible };
+
+ Add(toolbar);
+
+ var notificationButton = toolbar.Children.OfType().Last().Children.OfType().First();
+
+ void setNotifications(int count) => AddStep($"set notification count to {count}", () => notificationButton.NotificationCount.Value = count);
+
+ setNotifications(1);
+ setNotifications(2);
+ setNotifications(3);
+ setNotifications(0);
+ setNotifications(144);
+ }
+ }
+}
diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj
index ff012bb6e2..df66896d9b 100644
--- a/osu.Game.Tests/osu.Game.Tests.csproj
+++ b/osu.Game.Tests/osu.Game.Tests.csproj
@@ -37,8 +37,8 @@
$(SolutionDir)\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll
True
-
- $(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll
+
+ $(SolutionDir)\packages\OpenTK.3.0.0-git00021\lib\net20\OpenTK.dll
True
@@ -134,6 +134,7 @@
+
@@ -148,6 +149,7 @@
+
diff --git a/osu.Game.Tests/packages.config b/osu.Game.Tests/packages.config
index e09f2a07ba..c2056e09a8 100644
--- a/osu.Game.Tests/packages.config
+++ b/osu.Game.Tests/packages.config
@@ -6,6 +6,6 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
-
+
\ No newline at end of file
diff --git a/osu.Game/Audio/SampleInfoList.cs b/osu.Game/Audio/SampleInfoList.cs
deleted file mode 100644
index 06dd716a4a..0000000000
--- a/osu.Game/Audio/SampleInfoList.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2007-2017 ppy Pty Ltd .
-// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-
-using System.Collections.Generic;
-
-namespace osu.Game.Audio
-{
- public class SampleInfoList : List
- {
- public SampleInfoList()
- {
- }
-
- public SampleInfoList(IEnumerable elements) : base(elements)
- {
- }
- }
-}
\ No newline at end of file
diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs
index 0325785016..c86860f7b0 100644
--- a/osu.Game/Beatmaps/BeatmapManager.cs
+++ b/osu.Game/Beatmaps/BeatmapManager.cs
@@ -697,10 +697,12 @@ namespace osu.Game.Beatmaps
}
}
+ public bool StableInstallationAvailable => GetStableStorage?.Invoke() != null;
+
///
/// This is a temporary method and will likely be replaced by a full-fledged (and more correctly placed) migration process in the future.
///
- public void ImportFromStable()
+ public async Task ImportFromStable()
{
var stable = GetStableStorage?.Invoke();
@@ -710,7 +712,7 @@ namespace osu.Game.Beatmaps
return;
}
- Import(stable.GetDirectories("Songs"));
+ await Task.Factory.StartNew(() => Import(stable.GetDirectories("Songs")), TaskCreationOptions.LongRunning);
}
public void DeleteAll()
diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs
index 1434943da0..3ec83ed8d5 100644
--- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs
+++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs
@@ -21,8 +21,7 @@ namespace osu.Game.Beatmaps
Metadata = new BeatmapMetadata
{
Artist = "please load a beatmap!",
- Title = "no beatmaps available!",
- AuthorString = "no one",
+ Title = "no beatmaps available!"
},
BeatmapSet = new BeatmapSetInfo(),
BaseDifficulty = new BeatmapDifficulty
diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs
index fe7ca77d44..1dc4c487f3 100644
--- a/osu.Game/OsuGame.cs
+++ b/osu.Game/OsuGame.cs
@@ -16,6 +16,7 @@ using osu.Game.Screens;
using osu.Game.Screens.Menu;
using OpenTK;
using System.Linq;
+using System.Threading;
using System.Threading.Tasks;
using osu.Framework.Input.Bindings;
using osu.Framework.Platform;
@@ -220,15 +221,7 @@ namespace osu.Game
Depth = -6,
}, overlayContent.Add);
- Logger.NewEntry += entry =>
- {
- if (entry.Level < LogLevel.Important) return;
-
- notifications.Post(new SimpleNotification
- {
- Text = $@"{entry.Level}: {entry.Message}"
- });
- };
+ forwardLoggedErrorsToNotifications();
dependencies.Cache(settings);
dependencies.Cache(social);
@@ -290,6 +283,36 @@ namespace osu.Game
Cursor.State = Visibility.Hidden;
}
+ private void forwardLoggedErrorsToNotifications()
+ {
+ int recentErrorCount = 0;
+
+ const double debounce = 5000;
+
+ Logger.NewEntry += entry =>
+ {
+ if (entry.Level < LogLevel.Error || entry.Target == null) return;
+
+ if (recentErrorCount < 2)
+ {
+ notifications.Post(new SimpleNotification
+ {
+ Icon = FontAwesome.fa_bomb,
+ Text = (recentErrorCount == 0 ? entry.Message : "Subsequent errors occurred and have been logged.") + "\nClick to view log files.",
+ Activated = () =>
+ {
+ Host.Storage.GetStorageForDirectory("logs").OpenInNativeExplorer();
+ return true;
+ }
+ });
+ }
+
+ Interlocked.Increment(ref recentErrorCount);
+
+ Scheduler.AddDelayed(() => Interlocked.Decrement(ref recentErrorCount), debounce);
+ };
+ }
+
private Task asyncLoadStream;
private void loadComponentSingleFile(T d, Action add)
diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs
index 0ddff5e5aa..ea0bf22112 100644
--- a/osu.Game/OsuGameBase.cs
+++ b/osu.Game/OsuGameBase.cs
@@ -177,8 +177,7 @@ namespace osu.Game
}
catch (MigrationFailedException e)
{
- Logger.Log((e.InnerException ?? e).ToString(), LoggingTarget.Database, LogLevel.Error);
- Logger.Log("Migration failed! We'll be starting with a fresh database.", LoggingTarget.Database, LogLevel.Error);
+ Logger.Error(e.InnerException ?? e, "Migration failed! We'll be starting with a fresh database.", LoggingTarget.Database);
// if we failed, let's delete the database and start fresh.
// todo: we probably want a better (non-destructive) migrations/recovery process at a later point than this.
diff --git a/osu.Game/Overlays/BeatmapSet/Info.cs b/osu.Game/Overlays/BeatmapSet/Info.cs
index bd108a193b..b4aea898b2 100644
--- a/osu.Game/Overlays/BeatmapSet/Info.cs
+++ b/osu.Game/Overlays/BeatmapSet/Info.cs
@@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
+using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using OpenTK;
using OpenTK.Graphics;
@@ -176,7 +177,7 @@ namespace osu.Game.Overlays.BeatmapSet
Shadow = false,
Margin = new MarginPadding { Top = 20 },
},
- textFlow = new TextFlowContainer
+ textFlow = new OsuTextFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
diff --git a/osu.Game/Overlays/Dialog/PopupDialog.cs b/osu.Game/Overlays/Dialog/PopupDialog.cs
index 9b19b8150e..d2bd50cad6 100644
--- a/osu.Game/Overlays/Dialog/PopupDialog.cs
+++ b/osu.Game/Overlays/Dialog/PopupDialog.cs
@@ -32,7 +32,7 @@ namespace osu.Game.Overlays.Dialog
private readonly FillFlowContainer buttonsContainer;
private readonly SpriteIcon icon;
private readonly SpriteText header;
- private readonly SpriteText body;
+ private readonly TextFlowContainer body;
public FontAwesome Icon
{
@@ -48,7 +48,6 @@ namespace osu.Game.Overlays.Dialog
public string BodyText
{
- get { return body.Text; }
set { body.Text = value; }
}
@@ -220,17 +219,15 @@ namespace osu.Game.Overlays.Dialog
{
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
- Text = @"Header",
TextSize = 25,
Shadow = true,
},
- body = new OsuSpriteText
+ body = new OsuTextFlowContainer(t => t.TextSize = 18)
{
- Origin = Anchor.TopCentre,
- Anchor = Anchor.TopCentre,
- Text = @"Body",
- TextSize = 18,
- Shadow = true,
+ Padding = new MarginPadding(15),
+ RelativeSizeAxes = Axes.X,
+ AutoSizeAxes = Axes.Y,
+ TextAnchor = Anchor.TopCentre,
},
},
},
diff --git a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs
index 53d77dab6c..c6be428987 100644
--- a/osu.Game/Overlays/MedalSplash/DrawableMedal.cs
+++ b/osu.Game/Overlays/MedalSplash/DrawableMedal.cs
@@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Game.Graphics;
+using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Users;
@@ -88,7 +89,7 @@ namespace osu.Game.Overlays.MedalSplash
Alpha = 0f,
Scale = new Vector2(1f / scale_when_full),
},
- description = new TextFlowContainer
+ description = new OsuTextFlowContainer
{
TextAnchor = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
diff --git a/osu.Game/Overlays/NotificationOverlay.cs b/osu.Game/Overlays/NotificationOverlay.cs
index a4b5486596..2f1c3285ef 100644
--- a/osu.Game/Overlays/NotificationOverlay.cs
+++ b/osu.Game/Overlays/NotificationOverlay.cs
@@ -11,6 +11,7 @@ using OpenTK.Graphics;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics.Containers;
using System;
+using osu.Framework.Configuration;
namespace osu.Game.Overlays
{
@@ -75,34 +76,38 @@ namespace osu.Game.Overlays
};
}
+ private int totalCount => sections.Select(c => c.DisplayedCount).Sum();
+ private int unreadCount => sections.Select(c => c.UnreadCount).Sum();
+
+ public readonly BindableInt UnreadCount = new BindableInt();
+
private int runningDepth;
private void notificationClosed()
{
// hide ourselves if all notifications have been dismissed.
- if (sections.Select(c => c.DisplayedCount).Sum() == 0)
+ if (totalCount == 0)
State = Visibility.Hidden;
+
+ updateCounts();
}
- public void Post(Notification notification)
+ public void Post(Notification notification) => Schedule(() =>
{
- Schedule(() =>
- {
- State = Visibility.Visible;
+ ++runningDepth;
+ notification.Depth = notification.DisplayOnTop ? runningDepth : -runningDepth;
- ++runningDepth;
- notification.Depth = notification.DisplayOnTop ? runningDepth : -runningDepth;
+ notification.Closed += notificationClosed;
- notification.Closed += notificationClosed;
+ var hasCompletionTarget = notification as IHasCompletionTarget;
+ if (hasCompletionTarget != null)
+ hasCompletionTarget.CompletionTarget = Post;
- var hasCompletionTarget = notification as IHasCompletionTarget;
- if (hasCompletionTarget != null)
- hasCompletionTarget.CompletionTarget = Post;
+ var ourType = notification.GetType();
+ sections.Children.FirstOrDefault(s => s.AcceptTypes.Any(accept => accept.IsAssignableFrom(ourType)))?.Add(notification);
- var ourType = notification.GetType();
- sections.Children.FirstOrDefault(s => s.AcceptTypes.Any(accept => accept.IsAssignableFrom(ourType)))?.Add(notification);
- });
- }
+ updateCounts();
+ });
protected override void PopIn()
{
@@ -122,9 +127,16 @@ namespace osu.Game.Overlays
this.FadeTo(0, TRANSITION_LENGTH, Easing.OutQuint);
}
+ private void updateCounts()
+ {
+ UnreadCount.Value = unreadCount;
+ }
+
private void markAllRead()
{
sections.Children.ForEach(s => s.MarkAllRead());
+
+ updateCounts();
}
protected override void UpdateAfterChildren()
diff --git a/osu.Game/Overlays/Notifications/Notification.cs b/osu.Game/Overlays/Notifications/Notification.cs
index 422051364e..dc2dcf2d74 100644
--- a/osu.Game/Overlays/Notifications/Notification.cs
+++ b/osu.Game/Overlays/Notifications/Notification.cs
@@ -91,7 +91,6 @@ namespace osu.Game.Overlays.Notifications
AutoSizeAxes = Axes.Y,
Padding = new MarginPadding
{
- Top = 5,
Left = 45,
Right = 30
},
@@ -261,4 +260,4 @@ namespace osu.Game.Overlays.Notifications
}
}
}
-}
\ No newline at end of file
+}
diff --git a/osu.Game/Overlays/Notifications/NotificationSection.cs b/osu.Game/Overlays/Notifications/NotificationSection.cs
index 09768ba0ea..2bd0321d12 100644
--- a/osu.Game/Overlays/Notifications/NotificationSection.cs
+++ b/osu.Game/Overlays/Notifications/NotificationSection.cs
@@ -26,6 +26,8 @@ namespace osu.Game.Overlays.Notifications
public int DisplayedCount => notifications.Count(n => !n.WasClosed);
+ public int UnreadCount => notifications.Count(n => !n.WasClosed && !n.Read);
+
public void Add(Notification notification) => notifications.Add(notification);
public IEnumerable AcceptTypes;
@@ -157,4 +159,4 @@ namespace osu.Game.Overlays.Notifications
notifications?.Children.ForEach(n => n.Read = true);
}
}
-}
\ No newline at end of file
+}
diff --git a/osu.Game/Overlays/Notifications/ProgressNotification.cs b/osu.Game/Overlays/Notifications/ProgressNotification.cs
index 12c7fe64ba..c39c630858 100644
--- a/osu.Game/Overlays/Notifications/ProgressNotification.cs
+++ b/osu.Game/Overlays/Notifications/ProgressNotification.cs
@@ -7,6 +7,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
+using osu.Game.Graphics.Containers;
using OpenTK;
using OpenTK.Graphics;
@@ -94,7 +95,7 @@ namespace osu.Game.Overlays.Notifications
protected virtual void Completed()
{
- Expire();
+ base.Close();
CompletionTarget?.Invoke(CreateCompletionNotification());
}
@@ -114,7 +115,7 @@ namespace osu.Game.Overlays.Notifications
RelativeSizeAxes = Axes.Both,
});
- Content.Add(textDrawable = new TextFlowContainer(t =>
+ Content.Add(textDrawable = new OsuTextFlowContainer(t =>
{
t.TextSize = 16;
})
diff --git a/osu.Game/Overlays/Notifications/SimpleNotification.cs b/osu.Game/Overlays/Notifications/SimpleNotification.cs
index daf1ac838d..1e691e2a5a 100644
--- a/osu.Game/Overlays/Notifications/SimpleNotification.cs
+++ b/osu.Game/Overlays/Notifications/SimpleNotification.cs
@@ -7,6 +7,7 @@ using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
+using osu.Game.Graphics.Containers;
using OpenTK;
namespace osu.Game.Overlays.Notifications
@@ -58,7 +59,7 @@ namespace osu.Game.Overlays.Notifications
}
});
- Content.Add(textDrawable = new TextFlowContainer(t => t.TextSize = 16)
+ Content.Add(textDrawable = new OsuTextFlowContainer(t => t.TextSize = 16)
{
Colour = OsuColour.Gray(128),
AutoSizeAxes = Axes.Y,
@@ -82,9 +83,11 @@ namespace osu.Game.Overlays.Notifications
set
{
+ if (value == base.Read) return;
+
base.Read = value;
- Light.FadeTo(value ? 1 : 0, 100);
+ Light.FadeTo(value ? 0 : 1, 100);
}
}
}
-}
\ No newline at end of file
+}
diff --git a/osu.Game/Overlays/OnScreenDisplay.cs b/osu.Game/Overlays/OnScreenDisplay.cs
index dcab942522..ce0feeb4c6 100644
--- a/osu.Game/Overlays/OnScreenDisplay.cs
+++ b/osu.Game/Overlays/OnScreenDisplay.cs
@@ -14,6 +14,7 @@ using osu.Game.Graphics;
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Extensions.Color4Extensions;
+using osu.Game.Graphics.Sprites;
namespace osu.Game.Overlays
{
@@ -63,7 +64,7 @@ namespace osu.Game.Overlays
Width = 240,
RelativeSizeAxes = Axes.Y,
},
- textLine1 = new SpriteText
+ textLine1 = new OsuSpriteText
{
Padding = new MarginPadding(10),
Font = @"Exo2.0-Black",
@@ -72,7 +73,7 @@ namespace osu.Game.Overlays
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
},
- textLine2 = new SpriteText
+ textLine2 = new OsuSpriteText
{
TextSize = 24,
Font = @"Exo2.0-Light",
@@ -97,7 +98,7 @@ namespace osu.Game.Overlays
Origin = Anchor.TopCentre,
AutoSizeAxes = Axes.Both
},
- textLine3 = new SpriteText
+ textLine3 = new OsuSpriteText
{
Padding = new MarginPadding { Bottom = 15 },
Font = @"Exo2.0-Bold",
diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs
index f000ca74d4..18e77cf186 100644
--- a/osu.Game/Overlays/Profile/ProfileHeader.cs
+++ b/osu.Game/Overlays/Profile/ProfileHeader.cs
@@ -456,7 +456,7 @@ namespace osu.Game.Overlays.Profile
Width = width,
Height = 26
});
- Add(numberText = new SpriteText
+ Add(numberText = new OsuSpriteText
{
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs
index 8a835634b8..904ed609e8 100644
--- a/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs
+++ b/osu.Game/Overlays/Profile/Sections/Kudosu/KudosuInfo.cs
@@ -10,6 +10,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input;
using osu.Game.Graphics;
+using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Users;
@@ -120,7 +121,7 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu
}
}
},
- new TextFlowContainer(t => { t.TextSize = 19; })
+ new OsuTextFlowContainer(t => { t.TextSize = 19; })
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs
index e288445c6d..9ab4143613 100644
--- a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs
+++ b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs
@@ -30,8 +30,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
Action = () =>
{
importButton.Enabled.Value = false;
- Task.Factory.StartNew(beatmaps.ImportFromStable)
- .ContinueWith(t => Schedule(() => importButton.Enabled.Value = true), TaskContinuationOptions.LongRunning);
+ beatmaps.ImportFromStable().ContinueWith(t => Schedule(() => importButton.Enabled.Value = true));
}
},
deleteButton = new DangerousSettingsButton
diff --git a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs
index ed206e7e1d..b0171feb30 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarChatButton.cs
@@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Toolbar
SetIcon(FontAwesome.fa_comments);
}
- [BackgroundDependencyLoader]
+ [BackgroundDependencyLoader(true)]
private void load(ChatOverlay chat)
{
StateContainer = chat;
diff --git a/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs b/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs
index 7d25440e2c..5c64ae69ec 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarDirectButton.cs
@@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Toolbar
SetIcon(FontAwesome.fa_osu_chevron_down_o);
}
- [BackgroundDependencyLoader]
+ [BackgroundDependencyLoader(true)]
private void load(DirectOverlay direct)
{
StateContainer = direct;
diff --git a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs
index 319dd63bc9..f38c772890 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarModeSelector.cs
@@ -64,7 +64,7 @@ namespace osu.Game.Overlays.Toolbar
};
}
- [BackgroundDependencyLoader]
+ [BackgroundDependencyLoader(true)]
private void load(RulesetStore rulesets, OsuGame game)
{
foreach (var r in rulesets.AvailableRulesets)
@@ -81,7 +81,10 @@ namespace osu.Game.Overlays.Toolbar
ruleset.ValueChanged += rulesetChanged;
ruleset.DisabledChanged += disabledChanged;
- ruleset.BindTo(game.Ruleset);
+ if (game != null)
+ ruleset.BindTo(game.Ruleset);
+ else
+ ruleset.Value = rulesets.AvailableRulesets.FirstOrDefault();
}
public override bool HandleInput => !ruleset.Disabled;
diff --git a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs
index d150aacdf9..81c57a984f 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarMusicButton.cs
@@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Toolbar
Icon = FontAwesome.fa_music;
}
- [BackgroundDependencyLoader]
+ [BackgroundDependencyLoader(true)]
private void load(MusicController music)
{
StateContainer = music;
diff --git a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs
index e11a22d675..c093767e52 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarNotificationButton.cs
@@ -2,8 +2,14 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Allocation;
+using osu.Framework.Configuration;
using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics;
+using osu.Game.Graphics.Sprites;
+using OpenTK;
+using OpenTK.Graphics;
namespace osu.Game.Overlays.Toolbar
{
@@ -11,17 +17,96 @@ namespace osu.Game.Overlays.Toolbar
{
protected override Anchor TooltipAnchor => Anchor.TopRight;
+ public BindableInt NotificationCount = new BindableInt();
+
+ private readonly CountCircle countDisplay;
+
public ToolbarNotificationButton()
{
Icon = FontAwesome.fa_bars;
TooltipMain = "Notifications";
TooltipSub = "Waiting for 'ya";
+
+ Add(countDisplay = new CountCircle
+ {
+ Alpha = 0,
+ Height = 16,
+ RelativePositionAxes = Axes.Both,
+ Origin = Anchor.Centre,
+ Position = new Vector2(0.7f, 0.25f),
+ });
}
- [BackgroundDependencyLoader]
+ [BackgroundDependencyLoader(true)]
private void load(NotificationOverlay notificationOverlay)
{
StateContainer = notificationOverlay;
+
+ if (notificationOverlay != null)
+ NotificationCount.BindTo(notificationOverlay.UnreadCount);
+
+ NotificationCount.ValueChanged += count =>
+ {
+ if (count == 0)
+ countDisplay.FadeOut(200, Easing.OutQuint);
+ else
+ {
+ countDisplay.Count = count;
+ countDisplay.FadeIn(200, Easing.OutQuint);
+ }
+ };
+ }
+
+ private class CountCircle : CompositeDrawable
+ {
+ private readonly OsuSpriteText countText;
+ private readonly Circle circle;
+
+ private int count;
+
+ public int Count
+ {
+ get { return count; }
+ set
+ {
+ if (count == value)
+ return;
+
+ if (value > count)
+ {
+ circle.FlashColour(Color4.White, 600, Easing.OutQuint);
+ this.ScaleTo(1.1f).Then().ScaleTo(1, 600, Easing.OutElastic);
+ }
+
+ count = value;
+ countText.Text = value.ToString("#,0");
+ }
+ }
+
+ public CountCircle()
+ {
+ AutoSizeAxes = Axes.X;
+
+ InternalChildren = new Drawable[]
+ {
+ circle = new Circle
+ {
+ RelativeSizeAxes = Axes.Both,
+ Colour = Color4.Red
+ },
+ countText = new OsuSpriteText
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ Y = -1,
+ TextSize = 14,
+ Padding = new MarginPadding(5),
+ Colour = Color4.White,
+ UseFullGlyphHeight = true,
+ Font = "Exo2.0-Bold",
+ }
+ };
+ }
}
}
}
diff --git a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs
index 69fdd27d5d..59314b8771 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarOverlayToggleButton.cs
@@ -21,8 +21,11 @@ namespace osu.Game.Overlays.Toolbar
set
{
stateContainer = value;
- Action = stateContainer.ToggleVisibility;
- stateContainer.StateChanged += stateChanged;
+ if (stateContainer != null)
+ {
+ Action = stateContainer.ToggleVisibility;
+ stateContainer.StateChanged += stateChanged;
+ }
}
}
diff --git a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs
index cf4f664e81..d0d76dd5d2 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarSettingsButton.cs
@@ -15,7 +15,7 @@ namespace osu.Game.Overlays.Toolbar
TooltipSub = "Change your settings";
}
- [BackgroundDependencyLoader]
+ [BackgroundDependencyLoader(true)]
private void load(SettingsOverlay settings)
{
StateContainer = settings;
diff --git a/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs b/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs
index 234d6f0f9a..74d1da4384 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarSocialButton.cs
@@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Toolbar
Icon = FontAwesome.fa_users;
}
- [BackgroundDependencyLoader]
+ [BackgroundDependencyLoader(true)]
private void load(SocialOverlay chat)
{
StateContainer = chat;
diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs
index 4487f74364..36740b96cb 100644
--- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs
+++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs
@@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Edit
}
catch (Exception e)
{
- Logger.Log($"Could not load this beatmap sucessfully ({e})!", LoggingTarget.Runtime, LogLevel.Error);
+ Logger.Error(e, "Could not load beatmap sucessfully!");
return;
}
diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
index d960ab6b48..ab4c04be3f 100644
--- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
+++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
@@ -72,6 +72,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
public IReadOnlyList Judgements => judgements;
protected List Samples = new List();
+ protected virtual IEnumerable GetSamples() => HitObject.Samples;
public readonly Bindable State = new Bindable();
@@ -84,12 +85,14 @@ namespace osu.Game.Rulesets.Objects.Drawables
[BackgroundDependencyLoader]
private void load(AudioManager audio)
{
- if (HitObject.Samples != null)
+ var samples = GetSamples();
+ if (samples.Any())
{
if (HitObject.SampleControlPoint == null)
- throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)} must always have an attached {nameof(HitObject.SampleControlPoint)}.");
+ throw new ArgumentNullException(nameof(HitObject.SampleControlPoint), $"{nameof(HitObject)}s must always have an attached {nameof(HitObject.SampleControlPoint)}."
+ + $" This is an indication that {nameof(HitObject.ApplyDefaults)} has not been invoked on {this}.");
- foreach (SampleInfo s in HitObject.Samples)
+ foreach (SampleInfo s in samples)
{
SampleInfo localSampleInfo = new SampleInfo
{
@@ -174,7 +177,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
{
judgementOccurred = false;
- if (AllJudged || State != ArmedState.Idle)
+ if (AllJudged)
return false;
if (NestedHitObjects != null)
diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs
index e950516bf4..4f06f6afe1 100644
--- a/osu.Game/Rulesets/Objects/HitObject.cs
+++ b/osu.Game/Rulesets/Objects/HitObject.cs
@@ -25,6 +25,8 @@ namespace osu.Game.Rulesets.Objects
///
public virtual double StartTime { get; set; }
+ private List samples;
+
///
/// The samples to be played when this hit object is hit.
///
@@ -32,7 +34,11 @@ namespace osu.Game.Rulesets.Objects
/// and can be treated as the default samples for the hit object.
///
///
- public SampleInfoList Samples;
+ public List Samples
+ {
+ get => samples ?? (samples = new List());
+ set => samples = value;
+ }
[JsonIgnore]
public SampleControlPoint SampleControlPoint;
diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs
index 667f921e04..fbf02f5345 100644
--- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs
+++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs
@@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch
};
}
- protected override HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount, List repeatSamples)
+ protected override HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples)
{
return new ConvertSlider
{
diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs
index 0d7d617405..bdbd7a9e65 100644
--- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs
+++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs
@@ -127,7 +127,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
}
// Generate the final per-node samples
- var nodeSamples = new List(nodes);
+ var nodeSamples = new List>(nodes);
for (int i = 0; i <= repeatCount; i++)
nodeSamples.Add(convertSoundType(nodeSoundTypes[i], nodeBankInfos[i]));
@@ -216,7 +216,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
/// The slider repeat count.
/// The samples to be played when the repeat nodes are hit. This includes the head and tail of the slider.
/// The hit object.
- protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount, List repeatSamples);
+ protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples);
///
/// Creates a legacy Spinner-type hit object.
@@ -234,9 +234,9 @@ namespace osu.Game.Rulesets.Objects.Legacy
/// The hold end time.
protected abstract HitObject CreateHold(Vector2 position, bool newCombo, double endTime);
- private SampleInfoList convertSoundType(LegacySoundType type, SampleBankInfo bankInfo)
+ private List convertSoundType(LegacySoundType type, SampleBankInfo bankInfo)
{
- var soundTypes = new SampleInfoList
+ var soundTypes = new List
{
new SampleInfo
{
diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs
index 698b74cc28..6dc8a07630 100644
--- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs
+++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs
@@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
public double Distance { get; set; }
- public List RepeatSamples { get; set; }
+ public List> RepeatSamples { get; set; }
public int RepeatCount { get; set; } = 1;
public double EndTime => StartTime + RepeatCount * Distance / Velocity;
diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs
index 86dd40b06e..2060b84222 100644
--- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs
+++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs
@@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania
};
}
- protected override HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount, List repeatSamples)
+ protected override HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples)
{
return new ConvertSlider
{
diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs
index 24c205db13..0062d29446 100644
--- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs
+++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs
@@ -2,9 +2,9 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
-using osu.Game.Audio;
using osu.Game.Rulesets.Objects.Types;
using System.Collections.Generic;
+using osu.Game.Audio;
namespace osu.Game.Rulesets.Objects.Legacy.Osu
{
@@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
};
}
- protected override HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount, List repeatSamples)
+ protected override HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples)
{
return new ConvertSlider
{
diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs
index 0554cfd97d..529a28ac15 100644
--- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs
+++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs
@@ -2,9 +2,9 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
-using osu.Game.Audio;
using osu.Game.Rulesets.Objects.Types;
using System.Collections.Generic;
+using osu.Game.Audio;
namespace osu.Game.Rulesets.Objects.Legacy.Taiko
{
@@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko
};
}
- protected override HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount, List repeatSamples)
+ protected override HitObject CreateSlider(Vector2 position, bool newCombo, List controlPoints, double length, CurveType curveType, int repeatCount, List> repeatSamples)
{
return new ConvertSlider
{
diff --git a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs
index 5abad2d661..2fe2424d49 100644
--- a/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs
+++ b/osu.Game/Rulesets/Objects/Types/IHasRepeats.cs
@@ -19,6 +19,6 @@ namespace osu.Game.Rulesets.Objects.Types
///
/// The samples to be played when each repeat node is hit (0 -> first repeat node, 1 -> second repeat node, etc).
///
- List RepeatSamples { get; }
+ List> RepeatSamples { get; }
}
}
diff --git a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs
index 367cf4337d..b2308aca71 100644
--- a/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs
+++ b/osu.Game/Screens/Edit/Components/Timelines/Summary/Parts/MarkerPart.cs
@@ -47,6 +47,8 @@ namespace osu.Game.Screens.Edit.Components.Timelines.Summary.Parts
if (Beatmap.Value == null)
return;
+ if (Beatmap.Value.Track.Length == double.PositiveInfinity) return;
+
float markerPos = MathHelper.Clamp(ToLocalSpace(screenPosition).X, 0, DrawWidth);
seekTo(markerPos / DrawWidth * Beatmap.Value.Track.Length);
}
diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs
index 531913470f..546bb0dcff 100644
--- a/osu.Game/Screens/Play/Player.cs
+++ b/osu.Game/Screens/Play/Player.cs
@@ -127,7 +127,7 @@ namespace osu.Game.Screens.Play
}
catch (Exception e)
{
- Logger.Log($"Could not load this beatmap sucessfully ({e})!", LoggingTarget.Runtime, LogLevel.Error);
+ Logger.Error(e, "Could not load beatmap sucessfully!");
//couldn't load, hard abort!
Exit();
diff --git a/osu.Game/Screens/Play/PlayerLoader.cs b/osu.Game/Screens/Play/PlayerLoader.cs
index de67bef004..a220dcee0e 100644
--- a/osu.Game/Screens/Play/PlayerLoader.cs
+++ b/osu.Game/Screens/Play/PlayerLoader.cs
@@ -250,7 +250,7 @@ namespace osu.Game.Screens.Play
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
},
- new MetadataLine("Mapper", metadata.Author.Username)
+ new MetadataLine("Mapper", metadata.AuthorString)
{
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs
index 8e27cb235c..406887624c 100644
--- a/osu.Game/Screens/Ranking/Results.cs
+++ b/osu.Game/Screens/Ranking/Results.cs
@@ -17,6 +17,7 @@ using OpenTK.Graphics;
using osu.Game.Graphics;
using osu.Game.Graphics.UserInterface;
using osu.Framework.Graphics.Shapes;
+using osu.Game.Graphics.Sprites;
namespace osu.Game.Screens.Ranking
{
@@ -183,7 +184,7 @@ namespace osu.Game.Screens.Ranking
Height = 50,
Margin = new MarginPadding { Bottom = 110 },
},
- new SpriteText
+ new OsuSpriteText
{
Text = $"{score.MaxCombo}x",
TextSize = 40,
@@ -194,7 +195,7 @@ namespace osu.Game.Screens.Ranking
Anchor = Anchor.CentreLeft,
Origin = Anchor.BottomCentre,
},
- new SpriteText
+ new OsuSpriteText
{
Text = "max combo",
TextSize = 20,
@@ -204,7 +205,7 @@ namespace osu.Game.Screens.Ranking
Anchor = Anchor.CentreLeft,
Origin = Anchor.TopCentre,
},
- new SpriteText
+ new OsuSpriteText
{
Text = $"{score.Accuracy:P2}",
TextSize = 40,
@@ -215,7 +216,7 @@ namespace osu.Game.Screens.Ranking
Anchor = Anchor.CentreLeft,
Origin = Anchor.BottomCentre,
},
- new SpriteText
+ new OsuSpriteText
{
Text = "accuracy",
TextSize = 20,
diff --git a/osu.Game/Screens/Ranking/ResultsPageScore.cs b/osu.Game/Screens/Ranking/ResultsPageScore.cs
index 911b688669..25a42cae1c 100644
--- a/osu.Game/Screens/Ranking/ResultsPageScore.cs
+++ b/osu.Game/Screens/Ranking/ResultsPageScore.cs
@@ -201,14 +201,14 @@ namespace osu.Game.Screens.Ranking
{
Children = new Drawable[]
{
- new SpriteText {
+ new OsuSpriteText {
Text = statistic.Value.ToString().PadLeft(4, '0'),
Colour = colours.Gray7,
TextSize = 30,
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
},
- new SpriteText {
+ new OsuSpriteText {
Text = statistic.Key,
Colour = colours.Gray7,
Font = @"Exo2.0-Bold",
@@ -324,7 +324,14 @@ namespace osu.Game.Screens.Ranking
title.Colour = artist.Colour = colours.BlueDarker;
versionMapper.Colour = colours.Gray8;
- versionMapper.Text = $"{beatmap.Version} - mapped by {beatmap.Metadata.Author.Username}";
+ var creator = beatmap.Metadata.Author?.Username;
+ if (!string.IsNullOrEmpty(creator)) {
+ versionMapper.Text = $"mapped by {creator}";
+
+ if (!string.IsNullOrEmpty(beatmap.Version))
+ versionMapper.Text = $"{beatmap.Version} - " + versionMapper.Text;
+ }
+
title.Current = localisation.GetUnicodePreference(beatmap.Metadata.TitleUnicode, beatmap.Metadata.Title);
artist.Current = localisation.GetUnicodePreference(beatmap.Metadata.ArtistUnicode, beatmap.Metadata.Artist);
}
diff --git a/osu.Game/Screens/Select/BeatmapCarousel.cs b/osu.Game/Screens/Select/BeatmapCarousel.cs
index 87edfe9692..9d7867659d 100644
--- a/osu.Game/Screens/Select/BeatmapCarousel.cs
+++ b/osu.Game/Screens/Select/BeatmapCarousel.cs
@@ -75,7 +75,8 @@ namespace osu.Game.Screens.Select
scrollableContent.Clear(false);
itemsCache.Invalidate();
scrollPositionCache.Invalidate();
- BeatmapSetsChanged?.Invoke();
+
+ Schedule(() => BeatmapSetsChanged?.Invoke());
}));
}
}
@@ -154,6 +155,7 @@ namespace osu.Game.Screens.Select
select((CarouselItem)newSet.Beatmaps.FirstOrDefault(b => b.Beatmap.ID == selectedBeatmap?.Beatmap.ID) ?? newSet);
itemsCache.Invalidate();
+ Schedule(() => BeatmapSetsChanged?.Invoke());
});
}
@@ -511,7 +513,7 @@ namespace osu.Game.Screens.Select
currentY += DrawHeight / 2;
scrollableContent.Height = currentY;
- if (selectedBeatmapSet != null && (selectedBeatmap == null || selectedBeatmapSet.State.Value != CarouselItemState.Selected))
+ if (selectedBeatmapSet == null || selectedBeatmap == null || selectedBeatmapSet.State.Value != CarouselItemState.Selected)
{
selectedBeatmapSet = null;
SelectionChanged?.Invoke(null);
diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs
index a9a778fe17..79d76dd00e 100644
--- a/osu.Game/Screens/Select/BeatmapDetails.cs
+++ b/osu.Game/Screens/Select/BeatmapDetails.cs
@@ -17,6 +17,7 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.Extensions.Color4Extensions;
using osu.Game.Screens.Select.Details;
using osu.Game.Beatmaps;
+using osu.Game.Graphics.Containers;
namespace osu.Game.Screens.Select
{
@@ -334,7 +335,7 @@ namespace osu.Game.Screens.Select
TextSize = 14,
},
},
- textFlow = new TextFlowContainer
+ textFlow = new OsuTextFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
@@ -359,7 +360,7 @@ namespace osu.Game.Screens.Select
private void setTextAsync(string text)
{
- LoadComponentAsync(new TextFlowContainer(s => s.TextSize = 14)
+ LoadComponentAsync(new OsuTextFlowContainer(s => s.TextSize = 14)
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs
index 3ef6ceeaeb..fa1326de8c 100644
--- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs
+++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs
@@ -27,7 +27,7 @@ namespace osu.Game.Screens.Select
{
private static readonly Vector2 wedged_container_shear = new Vector2(0.15f, 0);
- private Drawable info;
+ protected BufferedWedgeInfo Info;
public BeatmapInfoWedge()
{
@@ -35,6 +35,7 @@ namespace osu.Game.Screens.Select
Masking = true;
BorderColour = new Color4(221, 255, 255, 255);
BorderThickness = 2.5f;
+ Alpha = 0;
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Glow,
@@ -50,12 +51,14 @@ namespace osu.Game.Screens.Select
{
this.MoveToX(0, 800, Easing.OutQuint);
this.RotateTo(0, 800, Easing.OutQuint);
+ this.FadeIn(250);
}
protected override void PopOut()
{
- this.MoveToX(-100, 800, Easing.InQuint);
- this.RotateTo(10, 800, Easing.InQuint);
+ this.MoveToX(-100, 800, Easing.In);
+ this.RotateTo(10, 800, Easing.In);
+ this.FadeOut(500, Easing.In);
}
public void UpdateBeatmap(WorkingBeatmap beatmap)
@@ -63,23 +66,30 @@ namespace osu.Game.Screens.Select
LoadComponentAsync(new BufferedWedgeInfo(beatmap)
{
Shear = -Shear,
- Depth = info?.Depth + 1 ?? 0,
+ Depth = Info?.Depth + 1 ?? 0,
}, newInfo =>
{
+ State = beatmap == null ? Visibility.Hidden : Visibility.Visible;
+
// ensure we ourselves are visible if not already.
if (!IsPresent)
- this.FadeIn(250);
+ State = Visibility.Visible;
- info?.FadeOut(250);
- info?.Expire();
+ Info?.FadeOut(250);
+ Info?.Expire();
- Add(info = newInfo);
+ Add(Info = newInfo);
});
}
public class BufferedWedgeInfo : BufferedContainer
{
private readonly WorkingBeatmap working;
+ public OsuSpriteText VersionLabel { get; private set; }
+ public OsuSpriteText TitleLabel { get; private set; }
+ public OsuSpriteText ArtistLabel { get; private set; }
+ public FillFlowContainer MapperContainer { get; private set; }
+ public FillFlowContainer InfoLabelContainer { get; private set; }
public BufferedWedgeInfo(WorkingBeatmap working)
{
@@ -89,34 +99,8 @@ namespace osu.Game.Screens.Select
[BackgroundDependencyLoader]
private void load()
{
- BeatmapInfo beatmapInfo = working.BeatmapInfo;
- BeatmapMetadata metadata = beatmapInfo.Metadata ?? working.BeatmapSetInfo?.Metadata ?? new BeatmapMetadata();
- Beatmap beatmap = working.Beatmap;
-
- List labels = new List();
-
- if (beatmap != null)
- {
- HitObject lastObject = beatmap.HitObjects.LastOrDefault();
- double endTime = (lastObject as IHasEndTime)?.EndTime ?? lastObject?.StartTime ?? 0;
-
- labels.Add(new InfoLabel(new BeatmapStatistic
- {
- Name = "Length",
- Icon = FontAwesome.fa_clock_o,
- Content = beatmap.HitObjects.Count == 0 ? "-" : TimeSpan.FromMilliseconds(endTime - beatmap.HitObjects.First().StartTime).ToString(@"m\:ss"),
- }));
-
- labels.Add(new InfoLabel(new BeatmapStatistic
- {
- Name = "BPM",
- Icon = FontAwesome.fa_circle,
- Content = getBPMRange(beatmap),
- }));
-
- //get statistics from the current ruleset.
- labels.AddRange(beatmapInfo.Ruleset.CreateInstance().GetBeatmapStatistics(working).Select(s => new InfoLabel(s)));
- }
+ var beatmapInfo = working.BeatmapInfo;
+ var metadata = beatmapInfo.Metadata ?? working.BeatmapSetInfo?.Metadata ?? new BeatmapMetadata();
PixelSnapping = true;
CacheDrawnFrameBuffer = true;
@@ -165,7 +149,7 @@ namespace osu.Game.Screens.Select
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
- new OsuSpriteText
+ VersionLabel = new OsuSpriteText
{
Font = @"Exo2.0-MediumItalic",
Text = beatmapInfo.Version,
@@ -175,69 +159,112 @@ namespace osu.Game.Screens.Select
},
new FillFlowContainer
{
- Name = "Bottom-aligned metadata",
- Anchor = Anchor.BottomLeft,
- Origin = Anchor.BottomLeft,
+ Name = "Centre-aligned metadata",
+ Anchor = Anchor.CentreLeft,
+ Origin = Anchor.TopLeft,
+ Y = -22,
Direction = FillDirection.Vertical,
Margin = new MarginPadding { Top = 15, Left = 25, Right = 10, Bottom = 20 },
AutoSizeAxes = Axes.Both,
Children = new Drawable[]
{
- new OsuSpriteText
+ TitleLabel = new OsuSpriteText
{
Font = @"Exo2.0-MediumItalic",
- Text = !string.IsNullOrEmpty(metadata.Source) ? metadata.Source + " — " + metadata.Title : metadata.Title,
+ Text = string.IsNullOrEmpty(metadata.Source) ? metadata.Title : metadata.Source + " — " + metadata.Title,
TextSize = 28,
},
- new OsuSpriteText
+ ArtistLabel = new OsuSpriteText
{
Font = @"Exo2.0-MediumItalic",
Text = metadata.Artist,
TextSize = 17,
},
- new FillFlowContainer
+ MapperContainer = new FillFlowContainer
{
Margin = new MarginPadding { Top = 10 },
Direction = FillDirection.Horizontal,
AutoSizeAxes = Axes.Both,
- Children = new[]
- {
- new OsuSpriteText
- {
- Font = @"Exo2.0-Medium",
- Text = "mapped by ",
- TextSize = 15,
- },
- new OsuSpriteText
- {
- Font = @"Exo2.0-Bold",
- Text = metadata.Author.Username,
- TextSize = 15,
- },
- }
+ Children = getMapper(metadata)
},
- new FillFlowContainer
+ InfoLabelContainer = new FillFlowContainer
{
Margin = new MarginPadding { Top = 20 },
Spacing = new Vector2(20, 0),
AutoSizeAxes = Axes.Both,
- Children = labels
- },
+ Children = getInfoLabels()
+ }
}
- },
+ }
};
}
+ private InfoLabel[] getInfoLabels()
+ {
+ var beatmap = working.Beatmap;
+ var info = working.BeatmapInfo;
+
+ List labels = new List();
+
+ if (beatmap?.HitObjects?.Count > 0)
+ {
+ HitObject lastObject = beatmap.HitObjects.LastOrDefault();
+ double endTime = (lastObject as IHasEndTime)?.EndTime ?? lastObject?.StartTime ?? 0;
+
+ labels.Add(new InfoLabel(new BeatmapStatistic
+ {
+ Name = "Length",
+ Icon = FontAwesome.fa_clock_o,
+ Content = beatmap.HitObjects.Count == 0 ? "-" : TimeSpan.FromMilliseconds(endTime - beatmap.HitObjects.First().StartTime).ToString(@"m\:ss"),
+ }));
+
+ labels.Add(new InfoLabel(new BeatmapStatistic
+ {
+ Name = "BPM",
+ Icon = FontAwesome.fa_circle,
+ Content = getBPMRange(beatmap),
+ }));
+
+ //get statistics from the current ruleset.
+ labels.AddRange(info.Ruleset.CreateInstance().GetBeatmapStatistics(working).Select(s => new InfoLabel(s)));
+ }
+
+ return labels.ToArray();
+ }
+
private string getBPMRange(Beatmap beatmap)
{
double bpmMax = beatmap.ControlPointInfo.BPMMaximum;
double bpmMin = beatmap.ControlPointInfo.BPMMinimum;
- if (Precision.AlmostEquals(bpmMin, bpmMax)) return $"{bpmMin:0}";
+ if (Precision.AlmostEquals(bpmMin, bpmMax))
+ return $"{bpmMin:0}";
return $"{bpmMin:0}-{bpmMax:0} (mostly {beatmap.ControlPointInfo.BPMMode:0})";
}
+ private OsuSpriteText[] getMapper(BeatmapMetadata metadata)
+ {
+ if (string.IsNullOrEmpty(metadata.Author?.Username))
+ return Array.Empty();
+
+ return new[]
+ {
+ new OsuSpriteText
+ {
+ Font = @"Exo2.0-Medium",
+ Text = "mapped by ",
+ TextSize = 15,
+ },
+ new OsuSpriteText
+ {
+ Font = @"Exo2.0-Bold",
+ Text = metadata.Author.Username,
+ TextSize = 15,
+ }
+ };
+ }
+
public class InfoLabel : Container, IHasTooltip
{
public string TooltipText { get; private set; }
diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs
index 1b86cec613..2dbd63f77b 100644
--- a/osu.Game/Screens/Select/FilterControl.cs
+++ b/osu.Game/Screens/Select/FilterControl.cs
@@ -75,7 +75,7 @@ namespace osu.Game.Screens.Select
{
Children = new Drawable[]
{
- new Box
+ Background = new Box
{
Colour = Color4.Black,
Alpha = 0.8f,
@@ -167,6 +167,8 @@ namespace osu.Game.Screens.Select
private Bindable showConverted;
+ public readonly Box Background;
+
[BackgroundDependencyLoader(permitNulls: true)]
private void load(OsuColour colours, OsuGame osu, OsuConfigManager config)
{
diff --git a/osu.Game/Screens/Select/ImportFromStablePopup.cs b/osu.Game/Screens/Select/ImportFromStablePopup.cs
new file mode 100644
index 0000000000..489ab79fa4
--- /dev/null
+++ b/osu.Game/Screens/Select/ImportFromStablePopup.cs
@@ -0,0 +1,33 @@
+// Copyright (c) 2007-2017 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System;
+using osu.Game.Graphics;
+using osu.Game.Overlays.Dialog;
+
+namespace osu.Game.Screens.Select
+{
+ public class ImportFromStablePopup : PopupDialog
+ {
+ public ImportFromStablePopup(Action importFromStable)
+ {
+ HeaderText = @"You have no beatmaps!";
+ BodyText = "An existing copy of osu! was found, though.\nWould you like to import your beatmaps?";
+
+ Icon = FontAwesome.fa_trash_o;
+
+ Buttons = new PopupDialogButton[]
+ {
+ new PopupDialogOkButton
+ {
+ Text = @"Yes please!",
+ Action = importFromStable
+ },
+ new PopupDialogCancelButton
+ {
+ Text = @"No, I'd like to start from scratch",
+ },
+ };
+ }
+ }
+}
diff --git a/osu.Game/Screens/Select/PlaySongSelect.cs b/osu.Game/Screens/Select/PlaySongSelect.cs
index 4a0ee31fbb..727cdb9959 100644
--- a/osu.Game/Screens/Select/PlaySongSelect.cs
+++ b/osu.Game/Screens/Select/PlaySongSelect.cs
@@ -11,6 +11,7 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Screens;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
+using osu.Game.Overlays;
using osu.Game.Overlays.Mods;
using osu.Game.Screens.Edit;
using osu.Game.Screens.Play;
@@ -45,8 +46,8 @@ namespace osu.Game.Screens.Select
private SampleChannel sampleConfirm;
- [BackgroundDependencyLoader]
- private void load(OsuColour colours, AudioManager audio)
+ [BackgroundDependencyLoader(true)]
+ private void load(OsuColour colours, AudioManager audio, BeatmapManager beatmaps, DialogOverlay dialogOverlay)
{
sampleConfirm = audio.Sample.Get(@"SongSelect/confirm-selection");
@@ -59,6 +60,16 @@ namespace osu.Game.Screens.Select
ValidForResume = false;
Push(new Editor());
}, Key.Number3);
+
+ if (dialogOverlay != null)
+ {
+ Schedule(() =>
+ {
+ // if we have no beatmaps but osu-stable is found, let's prompt the user to import.
+ if (!beatmaps.GetAllUsableBeatmapSets().Any() && beatmaps.StableInstallationAvailable)
+ dialogOverlay.Push(new ImportFromStablePopup(() => beatmaps.ImportFromStable()));
+ });
+ }
}
protected override void UpdateBeatmap(WorkingBeatmap beatmap)
diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs
index 68ee08e721..9e5a2fa633 100644
--- a/osu.Game/Screens/Select/SongSelect.cs
+++ b/osu.Game/Screens/Select/SongSelect.cs
@@ -55,7 +55,7 @@ namespace osu.Game.Screens.Select
protected Container LeftContent;
- private readonly BeatmapCarousel carousel;
+ protected readonly BeatmapCarousel Carousel;
private readonly BeatmapInfoWedge beatmapInfoWedge;
private DialogOverlay dialogOverlay;
private BeatmapManager beatmaps;
@@ -103,25 +103,44 @@ namespace osu.Game.Screens.Select
Right = left_area_padding * 2,
}
},
- carousel = new BeatmapCarousel
+ new Container
{
- RelativeSizeAxes = Axes.Y,
- Size = new Vector2(carousel_width, 1),
- Anchor = Anchor.CentreRight,
- Origin = Anchor.CentreRight,
- SelectionChanged = carouselSelectionChanged,
- BeatmapSetsChanged = carouselBeatmapsLoaded,
- },
- FilterControl = new FilterControl
- {
- RelativeSizeAxes = Axes.X,
- Height = filter_height,
- FilterChanged = c => carousel.Filter(c),
- Exit = Exit,
+ RelativeSizeAxes = Axes.Both,
+ Masking = true,
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ Width = 2, //avoid horizontal masking so the panels don't clip when screen stack is pushed.
+ Child = new Container
+ {
+ RelativeSizeAxes = Axes.Both,
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ Width = 0.5f,
+ Children = new Drawable[]
+ {
+ Carousel = new BeatmapCarousel
+ {
+ Masking = false,
+ RelativeSizeAxes = Axes.Y,
+ Size = new Vector2(carousel_width, 1),
+ Anchor = Anchor.CentreRight,
+ Origin = Anchor.CentreRight,
+ SelectionChanged = carouselSelectionChanged,
+ BeatmapSetsChanged = carouselBeatmapsLoaded,
+ },
+ FilterControl = new FilterControl
+ {
+ RelativeSizeAxes = Axes.X,
+ Height = filter_height,
+ FilterChanged = c => Carousel.Filter(c),
+ Background = { Width = 2 },
+ Exit = Exit,
+ },
+ }
+ },
},
beatmapInfoWedge = new BeatmapInfoWedge
{
- Alpha = 0,
Size = wedged_container_size,
RelativeSizeAxes = Axes.X,
Margin = new MarginPadding
@@ -130,7 +149,7 @@ namespace osu.Game.Screens.Select
Right = left_area_padding,
},
},
- new ResetScrollContainer(() => carousel.ScrollToSelected())
+ new ResetScrollContainer(() => Carousel.ScrollToSelected())
{
RelativeSizeAxes = Axes.Y,
Width = 250,
@@ -190,15 +209,15 @@ namespace osu.Game.Screens.Select
initialAddSetsTask = new CancellationTokenSource();
- carousel.BeatmapSets = this.beatmaps.GetAllUsableBeatmapSets();
+ Carousel.BeatmapSets = this.beatmaps.GetAllUsableBeatmapSets();
- Beatmap.DisabledChanged += disabled => carousel.AllowSelection = !disabled;
+ Beatmap.DisabledChanged += disabled => Carousel.AllowSelection = !disabled;
Beatmap.TriggerChange();
Beatmap.ValueChanged += b =>
{
if (IsCurrentScreen)
- carousel.SelectBeatmap(b?.BeatmapInfo);
+ Carousel.SelectBeatmap(b?.BeatmapInfo);
};
}
@@ -212,9 +231,9 @@ namespace osu.Game.Screens.Select
{
// if we have a pending filter operation, we want to run it now.
// it could change selection (ie. if the ruleset has been changed).
- carousel.FlushPendingFilterOperations();
+ Carousel.FlushPendingFilterOperations();
- carousel.SelectBeatmap(beatmap);
+ Carousel.SelectBeatmap(beatmap);
if (selectionChangedDebounce?.Completed == false)
{
@@ -282,9 +301,9 @@ namespace osu.Game.Screens.Select
private void triggerRandom()
{
if (GetContainingInputManager().CurrentState.Keyboard.ShiftPressed)
- carousel.SelectPreviousRandom();
+ Carousel.SelectPreviousRandom();
else
- carousel.SelectNextRandom();
+ Carousel.SelectNextRandom();
}
protected override void OnEntering(Screen last)
@@ -399,7 +418,6 @@ namespace osu.Game.Screens.Select
backgroundModeBeatmap.FadeTo(1, 250);
}
- beatmapInfoWedge.State = Visibility.Visible;
beatmapInfoWedge.UpdateBeatmap(beatmap);
}
@@ -417,17 +435,17 @@ namespace osu.Game.Screens.Select
}
}
- private void onBeatmapSetAdded(BeatmapSetInfo s) => carousel.UpdateBeatmapSet(s);
- private void onBeatmapSetRemoved(BeatmapSetInfo s) => carousel.RemoveBeatmapSet(s);
- private void onBeatmapRestored(BeatmapInfo b) => carousel.UpdateBeatmapSet(beatmaps.QueryBeatmapSet(s => s.ID == b.BeatmapSetInfoID));
- private void onBeatmapHidden(BeatmapInfo b) => carousel.UpdateBeatmapSet(beatmaps.QueryBeatmapSet(s => s.ID == b.BeatmapSetInfoID));
+ private void onBeatmapSetAdded(BeatmapSetInfo s) => Carousel.UpdateBeatmapSet(s);
+ private void onBeatmapSetRemoved(BeatmapSetInfo s) => Carousel.RemoveBeatmapSet(s);
+ private void onBeatmapRestored(BeatmapInfo b) => Carousel.UpdateBeatmapSet(beatmaps.QueryBeatmapSet(s => s.ID == b.BeatmapSetInfoID));
+ private void onBeatmapHidden(BeatmapInfo b) => Carousel.UpdateBeatmapSet(beatmaps.QueryBeatmapSet(s => s.ID == b.BeatmapSetInfoID));
private void carouselBeatmapsLoaded()
{
- if (Beatmap.Value.BeatmapSetInfo?.DeletePending == false)
- carousel.SelectBeatmap(Beatmap.Value.BeatmapInfo);
- else
- carousel.SelectNextRandom();
+ if (!Beatmap.IsDefault && Beatmap.Value.BeatmapSetInfo?.DeletePending == false)
+ Carousel.SelectBeatmap(Beatmap.Value.BeatmapInfo);
+ else if (Carousel.SelectedBeatmapSet == null)
+ Carousel.SelectNextRandom();
}
private void delete(BeatmapSetInfo beatmap)
diff --git a/osu.Game/Tests/Visual/TestCasePerformancePoints.cs b/osu.Game/Tests/Visual/TestCasePerformancePoints.cs
index f71bece279..8984fc843f 100644
--- a/osu.Game/Tests/Visual/TestCasePerformancePoints.cs
+++ b/osu.Game/Tests/Visual/TestCasePerformancePoints.cs
@@ -12,7 +12,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes;
-using osu.Framework.Graphics.Sprites;
using osu.Framework.Input;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Sprites;
@@ -224,7 +223,7 @@ namespace osu.Game.Tests.Visual
if (!api.IsLoggedIn)
{
- InternalChild = new SpriteText
+ InternalChild = new OsuSpriteText
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 18134582f3..7d146c0a12 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -143,8 +143,8 @@
$(SolutionDir)\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll
True
-
- $(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll
+
+ $(SolutionDir)\packages\OpenTK.3.0.0-git00021\lib\net20\OpenTK.dll
True
@@ -239,7 +239,6 @@
-
@@ -311,6 +310,7 @@
+
diff --git a/osu.Game/packages.config b/osu.Game/packages.config
index 02ace918de..3ba50388e8 100644
--- a/osu.Game/packages.config
+++ b/osu.Game/packages.config
@@ -66,7 +66,7 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste
-
+
diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings
index 2f52881d6d..20007e3306 100644
--- a/osu.sln.DotSettings
+++ b/osu.sln.DotSettings
@@ -172,6 +172,7 @@
NEXT_LINE
NEXT_LINE
True
+ NEVER
False
False
True
@@ -655,7 +656,11 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-frame
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
True
+ True
+ True
+ True
True
True
+ True
True
True