diff --git a/README.md b/README.md
index 2c330e403c..52fc29cb98 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-
+
# osu!
@@ -100,7 +100,7 @@ Before starting, please make sure you are familiar with the [development and tes
Note that while we already have certain standards in place, nothing is set in stone. If you have an issue with the way code is structured; with any libraries we are using; with any processes involved with contributing, *please* bring it up. We welcome all feedback so we can make contributing to this project as pain-free as possible.
-For those interested, we love to reward quality contributions via bounties, paid out via paypal or osu! supporter tags. Don't hesitate to [request a bounty](https://docs.google.com/forms/d/e/1FAIpQLSet_8iFAgPMG526pBZ2Kic6HSh7XPM3fE8xPcnWNkMzINDdYg/viewform) for your work on this project.
+For those interested, we love to reward quality contributions via [bounties](https://docs.google.com/spreadsheets/d/1jNXfj_S3Pb5PErA-czDdC9DUu4IgUbe1Lt8E7CYUJuE/view?&rm=minimal#gid=523803337), paid out via paypal or osu! supporter tags. Don't hesitate to [request a bounty](https://docs.google.com/forms/d/e/1FAIpQLSet_8iFAgPMG526pBZ2Kic6HSh7XPM3fE8xPcnWNkMzINDdYg/viewform) for your work on this project.
## Licence
diff --git a/assets/lazer.png b/assets/lazer.png
index 075a8e7184..1e40e844cc 100644
Binary files a/assets/lazer.png and b/assets/lazer.png differ
diff --git a/osu.Android.props b/osu.Android.props
index 98f9bf1a42..b9451fc744 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -63,6 +63,6 @@
-
+
diff --git a/osu.Android/Resources/drawable/lazer.png b/osu.Android/Resources/drawable/lazer.png
index 075a8e7184..fc7aa8a092 100644
Binary files a/osu.Android/Resources/drawable/lazer.png and b/osu.Android/Resources/drawable/lazer.png differ
diff --git a/osu.Desktop/lazer.ico b/osu.Desktop/lazer.ico
old mode 100644
new mode 100755
index 0c894dca41..a6aa8abb9f
Binary files a/osu.Desktop/lazer.ico and b/osu.Desktop/lazer.ico differ
diff --git a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs
index e55dc1f902..693faee3b7 100644
--- a/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs
+++ b/osu.Game.Rulesets.Osu.Tests/OsuDifficultyCalculatorTest.cs
@@ -15,6 +15,7 @@ namespace osu.Game.Rulesets.Osu.Tests
protected override string ResourceAssembly => "osu.Game.Rulesets.Osu";
[TestCase(6.931145117263422, "diffcalc-test")]
+ [TestCase(1.0736587013228804d, "zero-length-sliders")]
public void Test(double expected, string name)
=> base.Test(expected, name);
diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs
index 7f6a60c400..fe11ead94d 100644
--- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/Components/HitCirclePiece.cs
@@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles.Components
this.hitCircle = hitCircle;
Origin = Anchor.Centre;
- Size = new Vector2((float)OsuHitObject.OBJECT_RADIUS * 2);
+ Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2);
Scale = new Vector2(hitCircle.Scale);
CornerRadius = Size.X / 2;
diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs
index 957550a051..f1f55731b6 100644
--- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs
+++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/Components/SliderBodyPiece.cs
@@ -24,7 +24,6 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
InternalChild = body = new ManualSliderBody
{
AccentColour = Color4.Transparent,
- PathRadius = slider.Scale * 64
};
}
@@ -34,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components
body.BorderColour = colours.Yellow;
PositionBindable.BindValueChanged(_ => updatePosition(), true);
- ScaleBindable.BindValueChanged(scale => body.PathRadius = scale.NewValue * 64, true);
+ ScaleBindable.BindValueChanged(scale => body.PathRadius = scale.NewValue * OsuHitObject.OBJECT_RADIUS, true);
}
private void updatePosition() => Position = slider.StackedPosition;
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs
index f372cb65ce..4533e08a2b 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs
@@ -29,6 +29,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
ShakeDuration = 30,
RelativeSizeAxes = Axes.Both
});
+
Alpha = 0;
}
@@ -38,6 +39,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
protected override void ClearInternal(bool disposeChildren = true) => shakeContainer.Clear(disposeChildren);
protected override bool RemoveInternal(Drawable drawable) => shakeContainer.Remove(drawable);
+ protected sealed override double InitialLifetimeOffset => HitObject.TimePreempt;
+
protected sealed override void UpdateState(ArmedState state)
{
double transformTime = HitObject.StartTime - HitObject.TimePreempt;
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
index 05cb42d853..56b5decd30 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
@@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
Body = new SnakingSliderBody(s)
{
- PathRadius = s.Scale * 64,
+ PathRadius = s.Scale * OsuHitObject.OBJECT_RADIUS,
},
ticks = new Container { RelativeSizeAxes = Axes.Both },
repeatPoints = new Container { RelativeSizeAxes = Axes.Both },
@@ -156,6 +156,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
}
}
+ public override void OnKilled()
+ {
+ base.OnKilled();
+ Body.RecyclePath();
+ }
+
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
{
base.SkinChanged(skin, allowFallback);
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs
index 786cac7198..dc0b149140 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/CirclePiece.cs
@@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
public CirclePiece()
{
- Size = new Vector2((float)OsuHitObject.OBJECT_RADIUS * 2);
+ Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2);
Masking = true;
CornerRadius = Size.X / 2;
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs
index b960f40578..8ff16f8b84 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/ExplodePiece.cs
@@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{
public ExplodePiece()
{
- Size = new Vector2(128);
+ Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2);
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs
index 8e5eb886aa..c22073f56c 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/FlashPiece.cs
@@ -1,4 +1,4 @@
-// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics;
@@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{
public FlashPiece()
{
- Size = new Vector2(128);
+ Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2);
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs
index 28180a7f71..575f2c92c5 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/RingPiece.cs
@@ -1,4 +1,4 @@
-// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Graphics;
@@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{
public RingPiece()
{
- Size = new Vector2(128);
+ Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2);
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs
index 7d1d77ae96..9ba8ad3474 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBall.cs
@@ -17,8 +17,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{
public class SliderBall : CircularContainer, ISliderProgress, IRequireHighFrequencyMousePosition
{
- private const float width = 128;
-
private Color4 accentColour = Color4.Black;
public Func GetInitialHitAction;
@@ -57,8 +55,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
- Width = width,
- Height = width,
+ Width = OsuHitObject.OBJECT_RADIUS * 2,
+ Height = OsuHitObject.OBJECT_RADIUS * 2,
Alpha = 0,
Child = new SkinnableDrawable("Play/osu/sliderfollowcircle", _ => new CircularContainer
{
@@ -84,8 +82,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
Alpha = 1,
Child = new Container
{
- Width = width,
- Height = width,
+ Width = OsuHitObject.OBJECT_RADIUS * 2,
+ Height = OsuHitObject.OBJECT_RADIUS * 2,
// TODO: support skin filename animation (sliderb0, sliderb1...)
Child = new SkinnableDrawable("Play/osu/sliderb", _ => new CircularContainer
{
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs
index 33b3667c4f..97c7c9cec5 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs
@@ -13,7 +13,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{
public const float DEFAULT_BORDER_SIZE = 1;
- private readonly SliderPath path;
+ private SliderPath path;
+
protected Path Path => path;
public float PathRadius
@@ -77,6 +78,22 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
InternalChild = path = new SliderPath();
}
+ ///
+ /// Initialises a new , releasing all resources retained by the old one.
+ ///
+ public void RecyclePath()
+ {
+ InternalChild = path = new SliderPath
+ {
+ Position = path.Position,
+ PathRadius = path.PathRadius,
+ AccentColour = path.AccentColour,
+ BorderColour = path.BorderColour,
+ BorderSize = path.BorderSize,
+ Vertices = path.Vertices
+ };
+ }
+
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => path.ReceivePositionalInputAt(screenSpacePos);
///
diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs
index 364c182dd4..d1221fd2d3 100644
--- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs
+++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs
@@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Objects
{
public abstract class OsuHitObject : HitObject, IHasComboInformation, IHasPosition
{
- public const double OBJECT_RADIUS = 64;
+ public const float OBJECT_RADIUS = 64;
public double TimePreempt = 600;
public double TimeFadeIn = 400;
diff --git a/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/zero-length-sliders.osu b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/zero-length-sliders.osu
new file mode 100644
index 0000000000..18736043b5
--- /dev/null
+++ b/osu.Game.Rulesets.Osu/Resources/Testing/Beatmaps/zero-length-sliders.osu
@@ -0,0 +1,28 @@
+osu file format v14
+
+[Difficulty]
+HPDrainRate:3
+CircleSize:3
+OverallDifficulty:3
+ApproachRate:4.5
+SliderMultiplier:0.799999999999999
+SliderTickRate:1
+
+[TimingPoints]
+800,260.869565217391,3,2,10,60,1,0
+
+[HitObjects]
+// Linear
+78,193,2365,2,0,L|330:193,1,0
+78,193,3669,2,0,L|330:193,1,0
+78,193,4973,2,0,L|330:193,1,0
+
+// Perfect-curve
+151,206,6278,2,0,P|293:75|345:204,1,0
+151,206,8104,2,0,P|293:75|345:204,1,0
+151,206,9930,2,0,P|293:75|345:204,1,0
+
+// Bezier
+76,191,11756,2,0,B|176:59|358:340|438:190,1,0
+76,191,13582,2,0,B|176:59|358:340|438:190,1,0
+76,191,15408,2,0,B|176:59|358:340|438:190,1,0
diff --git a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs
index b986076593..05eb0ffdbf 100644
--- a/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs
+++ b/osu.Game.Rulesets.Osu/UI/Cursor/CursorTrail.cs
@@ -162,7 +162,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
private readonly TrailPart[] parts = new TrailPart[max_sprites];
private Vector2 size;
- private readonly VertexBatch vertexBatch = new QuadBatch(max_sprites, 1);
+ private readonly TrailBatch vertexBatch = new TrailBatch(max_sprites, 1);
public TrailDrawNode(CursorTrail source)
: base(source)
@@ -196,21 +196,16 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
for (int i = 0; i < parts.Length; ++i)
{
+ vertexBatch.DrawTime = parts[i].Time;
+
Vector2 pos = parts[i].Position;
- float localTime = parts[i].Time;
DrawQuad(
texture,
new Quad(pos.X - size.X / 2, pos.Y - size.Y / 2, size.X, size.Y),
DrawColourInfo.Colour,
null,
- v => vertexBatch.Add(new TexturedTrailVertex
- {
- Position = v.Position,
- TexturePosition = v.TexturePosition,
- Time = localTime + 1,
- Colour = v.Colour,
- }));
+ vertexBatch.AddAction);
}
shader.Unbind();
@@ -222,6 +217,25 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
vertexBatch.Dispose();
}
+
+ // Todo: This shouldn't exist, but is currently used to reduce allocations by caching variable-capturing closures.
+ private class TrailBatch : QuadBatch
+ {
+ public new readonly Action AddAction;
+ public float DrawTime;
+
+ public TrailBatch(int size, int maxBuffers)
+ : base(size, maxBuffers)
+ {
+ AddAction = v => Add(new TexturedTrailVertex
+ {
+ Position = v.Position,
+ TexturePosition = v.TexturePosition,
+ Time = DrawTime + 1,
+ Colour = v.Colour,
+ });
+ }
+ }
}
[StructLayout(LayoutKind.Sequential)]
diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs
index 0cbe0cca85..9037faf606 100644
--- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs
+++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs
@@ -12,6 +12,7 @@ using osu.Game.Rulesets.UI;
using System.Linq;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Osu.UI.Cursor;
+using osu.Game.Skinning;
namespace osu.Game.Rulesets.Osu.UI
{
@@ -39,7 +40,13 @@ namespace osu.Game.Rulesets.Osu.UI
RelativeSizeAxes = Axes.Both,
Depth = 1,
},
- HitObjectContainer,
+ // Todo: This should not exist, but currently helps to reduce LOH allocations due to unbinding skin source events on judgement disposal
+ // Todo: Remove when hitobjects are properly pooled
+ new LocalSkinOverrideContainer(null)
+ {
+ RelativeSizeAxes = Axes.Both,
+ Child = HitObjectContainer,
+ },
approachCircles = new ApproachCircleProxyContainer
{
RelativeSizeAxes = Axes.Both,
diff --git a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs
similarity index 90%
rename from osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs
rename to osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs
index 8b941e4633..dc4ceed59e 100644
--- a/osu.Game.Tests/Visual/Background/TestSceneBackgroundScreenBeatmap.cs
+++ b/osu.Game.Tests/Visual/Background/TestSceneUserDimContainer.cs
@@ -10,6 +10,7 @@ using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
+using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Events;
using osu.Framework.Input.States;
using osu.Framework.Platform;
@@ -36,7 +37,7 @@ using osuTK.Graphics;
namespace osu.Game.Tests.Visual.Background
{
[TestFixture]
- public class TestSceneBackgroundScreenBeatmap : ManualInputManagerTestScene
+ public class TestSceneUserDimContainer : ManualInputManagerTestScene
{
public override IReadOnlyList RequiredTypes => new[]
{
@@ -137,14 +138,14 @@ namespace osu.Game.Tests.Visual.Background
player.StoryboardEnabled.Value = true;
});
waitForDim();
- AddAssert("Background is invisible, storyboard is visible", () => songSelect.IsBackgroundInvisible() && player.IsStoryboardVisible());
+ AddAssert("Background is invisible, storyboard is visible", () => songSelect.IsBackgroundInvisible() && player.IsStoryboardVisible);
AddStep("Storyboard Disabled", () =>
{
player.ReplacesBackground.Value = false;
player.StoryboardEnabled.Value = false;
});
waitForDim();
- AddAssert("Background is visible, storyboard is invisible", () => songSelect.IsBackgroundVisible() && player.IsStoryboardInvisible());
+ AddAssert("Background is visible, storyboard is invisible", () => songSelect.IsBackgroundVisible() && !player.IsStoryboardVisible);
}
///
@@ -241,14 +242,15 @@ namespace osu.Game.Tests.Visual.Background
{
player.StoryboardEnabled.Value = false;
player.ReplacesBackground.Value = false;
- player.CurrentStoryboardContainer.Add(new OsuSpriteText
+ player.DimmableStoryboard.Add(new OsuSpriteText
{
- Size = new Vector2(250, 50),
+ Size = new Vector2(500, 50),
Alpha = 1,
- Colour = Color4.Tomato,
+ Colour = Color4.White,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Text = "THIS IS A STORYBOARD",
+ Font = new FontUsage(size: 50)
});
});
@@ -300,7 +302,7 @@ namespace osu.Game.Tests.Visual.Background
public bool IsBackgroundUndimmed() => ((FadeAccessibleBackground)Background).CurrentColour == Color4.White;
- public bool IsUserBlurApplied() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2((float)BlurLevel.Value * 25);
+ public bool IsUserBlurApplied() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2((float)BlurLevel.Value * BackgroundScreenBeatmap.USER_BLUR_FACTOR);
public bool IsUserBlurDisabled() => ((FadeAccessibleBackground)Background).CurrentBlur == new Vector2(0);
@@ -333,17 +335,7 @@ namespace osu.Game.Tests.Visual.Background
{
protected override BackgroundScreen CreateBackground() => new FadeAccessibleBackground(Beatmap.Value);
- protected override UserDimContainer CreateStoryboardContainer()
- {
- return new TestUserDimContainer(true)
- {
- RelativeSizeAxes = Axes.Both,
- Alpha = 1,
- EnableUserDim = { Value = true }
- };
- }
-
- public UserDimContainer CurrentStoryboardContainer => StoryboardContainer;
+ public new DimmableStoryboard DimmableStoryboard => base.DimmableStoryboard;
// Whether or not the player should be allowed to load.
public bool BlockLoad;
@@ -357,9 +349,7 @@ namespace osu.Game.Tests.Visual.Background
{
}
- public bool IsStoryboardVisible() => ((TestUserDimContainer)CurrentStoryboardContainer).CurrentAlpha == 1;
-
- public bool IsStoryboardInvisible() => ((TestUserDimContainer)CurrentStoryboardContainer).CurrentAlpha <= 1;
+ public bool IsStoryboardVisible => DimmableStoryboard.ContentDisplayed;
[BackgroundDependencyLoader]
private void load(OsuConfigManager config, CancellationToken token)
@@ -392,15 +382,15 @@ namespace osu.Game.Tests.Visual.Background
private class FadeAccessibleBackground : BackgroundScreenBeatmap
{
- protected override UserDimContainer CreateFadeContainer() => fadeContainer = new TestUserDimContainer { RelativeSizeAxes = Axes.Both };
+ protected override DimmableBackground CreateFadeContainer() => dimmable = new TestDimmableBackground { RelativeSizeAxes = Axes.Both };
- public Color4 CurrentColour => fadeContainer.CurrentColour;
+ public Color4 CurrentColour => dimmable.CurrentColour;
- public float CurrentAlpha => fadeContainer.CurrentAlpha;
+ public float CurrentAlpha => dimmable.CurrentAlpha;
public Vector2 CurrentBlur => Background.BlurSigma;
- private TestUserDimContainer fadeContainer;
+ private TestDimmableBackground dimmable;
public FadeAccessibleBackground(WorkingBeatmap beatmap)
: base(beatmap)
@@ -408,15 +398,10 @@ namespace osu.Game.Tests.Visual.Background
}
}
- private class TestUserDimContainer : UserDimContainer
+ private class TestDimmableBackground : BackgroundScreenBeatmap.DimmableBackground
{
- public Color4 CurrentColour => DimContainer.Colour;
- public float CurrentAlpha => DimContainer.Alpha;
-
- public TestUserDimContainer(bool isStoryboard = false)
- : base(isStoryboard)
- {
- }
+ public Color4 CurrentColour => Content.Colour;
+ public float CurrentAlpha => Content.Alpha;
}
}
}
diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs
index 0519660477..b152c21454 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSkipOverlay.cs
@@ -1,19 +1,88 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System.Linq;
using NUnit.Framework;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Timing;
using osu.Game.Screens.Play;
+using osuTK;
+using osuTK.Input;
namespace osu.Game.Tests.Visual.Gameplay
{
[TestFixture]
- public class TestSceneSkipOverlay : OsuTestScene
+ public class TestSceneSkipOverlay : ManualInputManagerTestScene
{
- protected override void LoadComplete()
- {
- base.LoadComplete();
+ private SkipOverlay skip;
+ private int requestCount;
- Add(new SkipOverlay(Clock.CurrentTime + 5000));
+ [SetUp]
+ public void SetUp() => Schedule(() =>
+ {
+ requestCount = 0;
+ Child = new Container
+ {
+ RelativeSizeAxes = Axes.Both,
+ Clock = new FramedOffsetClock(Clock)
+ {
+ Offset = -Clock.CurrentTime,
+ },
+ Children = new Drawable[]
+ {
+ skip = new SkipOverlay(6000)
+ {
+ RequestSeek = _ => requestCount++
+ }
+ },
+ };
+ });
+
+ [Test]
+ public void TestFadeOnIdle()
+ {
+ AddStep("move mouse", () => InputManager.MoveMouseTo(Vector2.Zero));
+ AddUntilStep("fully visible", () => skip.Children.First().Alpha == 1);
+ AddUntilStep("wait for fade", () => skip.Children.First().Alpha < 1);
+
+ AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre));
+ AddUntilStep("fully visible", () => skip.Children.First().Alpha == 1);
+ AddUntilStep("wait for fade", () => skip.Children.First().Alpha < 1);
}
+
+ [Test]
+ public void TestClickableAfterFade()
+ {
+ AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre));
+ AddUntilStep("wait for fade", () => skip.Children.First().Alpha == 0);
+ AddStep("click", () => InputManager.Click(MouseButton.Left));
+ checkRequestCount(1);
+ }
+
+ [Test]
+ public void TestClickOnlyActuatesOnce()
+ {
+ AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre));
+ AddStep("click", () => InputManager.Click(MouseButton.Left));
+ AddStep("click", () => InputManager.Click(MouseButton.Left));
+ AddStep("click", () => InputManager.Click(MouseButton.Left));
+ AddStep("click", () => InputManager.Click(MouseButton.Left));
+ checkRequestCount(1);
+ }
+
+ [Test]
+ public void TestDoesntFadeOnMouseDown()
+ {
+ AddStep("move mouse", () => InputManager.MoveMouseTo(skip.ScreenSpaceDrawQuad.Centre));
+ AddStep("button down", () => InputManager.PressButton(MouseButton.Left));
+ AddUntilStep("wait for overlay disapper", () => !skip.IsAlive);
+ AddAssert("ensure button didn't disappear", () => skip.Children.First().Alpha > 0);
+ AddStep("button up", () => InputManager.ReleaseButton(MouseButton.Left));
+ checkRequestCount(0);
+ }
+
+ private void checkRequestCount(int expected) =>
+ AddAssert($"request count is {expected}", () => requestCount == expected);
}
}
diff --git a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs
index d809dfc994..20928499bf 100644
--- a/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs
+++ b/osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs
@@ -10,7 +10,7 @@ namespace osu.Game.Tournament.Screens.Showcase
[BackgroundDependencyLoader]
private void load()
{
- AddInternal(new TournamentLogo());
+ AddInternal(new TournamentLogo(false));
}
}
}
diff --git a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs
index efe4ee92fc..a0216c5db3 100644
--- a/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs
+++ b/osu.Game.Tournament/Screens/TeamWin/TeamWinScreen.cs
@@ -45,7 +45,7 @@ namespace osu.Game.Tournament.Screens.TeamWin
RelativeSizeAxes = Axes.Both,
Loop = true,
},
- new TournamentLogo
+ new TournamentLogo(false)
{
Y = 40,
},
diff --git a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs
index ea3f0b61b9..df3a45d1cc 100644
--- a/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs
+++ b/osu.Game/Beatmaps/BeatmapSetOnlineInfo.cs
@@ -66,6 +66,11 @@ namespace osu.Game.Beatmaps
///
public int FavouriteCount { get; set; }
+ ///
+ /// Whether this beatmap set has been favourited by the current user.
+ ///
+ public bool HasFavourited { get; set; }
+
///
/// The availability of this beatmap set.
///
diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs
index 37aa0024da..949a2aab6f 100644
--- a/osu.Game/Beatmaps/WorkingBeatmap.cs
+++ b/osu.Game/Beatmaps/WorkingBeatmap.cs
@@ -247,7 +247,7 @@ namespace osu.Game.Beatmaps
// cancelling the beatmap load is safe for now since the retrieval is a synchronous
// operation. if we add an async retrieval method this may need to be reconsidered.
- beatmapCancellation.Cancel();
+ beatmapCancellation?.Cancel();
total_count.Value--;
}
diff --git a/osu.Game/Graphics/Backgrounds/Background.cs b/osu.Game/Graphics/Backgrounds/Background.cs
index 526b3da8a6..d13475189d 100644
--- a/osu.Game/Graphics/Backgrounds/Background.cs
+++ b/osu.Game/Graphics/Backgrounds/Background.cs
@@ -16,7 +16,7 @@ namespace osu.Game.Graphics.Backgrounds
///
public class Background : CompositeDrawable
{
- public Sprite Sprite;
+ public readonly Sprite Sprite;
private readonly string textureName;
@@ -51,7 +51,7 @@ namespace osu.Game.Graphics.Backgrounds
/// A to which further transforms can be added.
public void BlurTo(Vector2 newBlurSigma, double duration = 0, Easing easing = Easing.None)
{
- if (bufferedContainer == null)
+ if (bufferedContainer == null && newBlurSigma != Vector2.Zero)
{
RemoveInternal(Sprite);
@@ -63,7 +63,7 @@ namespace osu.Game.Graphics.Backgrounds
});
}
- bufferedContainer.BlurTo(newBlurSigma, duration, easing);
+ bufferedContainer?.BlurTo(newBlurSigma, duration, easing);
}
}
}
diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs
index 29113e0e2f..2b68e8530d 100644
--- a/osu.Game/Graphics/Backgrounds/Triangles.cs
+++ b/osu.Game/Graphics/Backgrounds/Triangles.cs
@@ -8,7 +8,6 @@ using osuTK.Graphics;
using System;
using osu.Framework.Graphics.Shaders;
using osu.Framework.Graphics.Textures;
-using osuTK.Graphics.ES30;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Primitives;
using osu.Framework.Allocation;
@@ -137,11 +136,13 @@ namespace osu.Game.Graphics.Backgrounds
}
}
+ protected int AimCount;
+
private void addTriangles(bool randomY)
{
- int aimTriangleCount = (int)(DrawWidth * DrawHeight * 0.002f / (triangleScale * triangleScale) * SpawnRatio);
+ AimCount = (int)(DrawWidth * DrawHeight * 0.002f / (triangleScale * triangleScale) * SpawnRatio);
- for (int i = 0; i < aimTriangleCount - parts.Count; i++)
+ for (int i = 0; i < AimCount - parts.Count; i++)
parts.Add(createTriangle(randomY));
}
@@ -190,7 +191,7 @@ namespace osu.Game.Graphics.Backgrounds
private readonly List parts = new List();
private Vector2 size;
- private readonly LinearBatch vertexBatch = new LinearBatch(100 * 3, 10, PrimitiveType.Triangles);
+ private TriangleBatch vertexBatch;
public TrianglesDrawNode(Triangles source)
: base(source)
@@ -213,6 +214,12 @@ namespace osu.Game.Graphics.Backgrounds
{
base.Draw(vertexAction);
+ if (Source.AimCount > 0 && (vertexBatch == null || vertexBatch.Size != Source.AimCount))
+ {
+ vertexBatch?.Dispose();
+ vertexBatch = new TriangleBatch(Source.AimCount, 1);
+ }
+
shader.Bind();
Vector2 localInflationAmount = edge_smoothness * DrawInfo.MatrixInverse.ExtractScale().Xy;
@@ -246,7 +253,7 @@ namespace osu.Game.Graphics.Backgrounds
{
base.Dispose(isDisposing);
- vertexBatch.Dispose();
+ vertexBatch?.Dispose();
}
}
diff --git a/osu.Game/Graphics/Containers/UserDimContainer.cs b/osu.Game/Graphics/Containers/UserDimContainer.cs
index fe9eb7baf4..03de5f651f 100644
--- a/osu.Game/Graphics/Containers/UserDimContainer.cs
+++ b/osu.Game/Graphics/Containers/UserDimContainer.cs
@@ -1,31 +1,26 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-using System;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Configuration;
-using osu.Game.Graphics.Backgrounds;
-using osu.Game.Screens.Play;
-using osuTK;
using osuTK.Graphics;
namespace osu.Game.Graphics.Containers
{
///
/// A container that applies user-configured visual settings to its contents.
- /// This container specifies behavior that applies to both Storyboards and Backgrounds.
///
- public class UserDimContainer : Container
+ public abstract class UserDimContainer : Container
{
- private const float background_fade_duration = 800;
+ protected const float BACKGROUND_FADE_DURATION = 800;
///
/// Whether or not user-configured dim levels should be applied to the container.
///
- public readonly Bindable EnableUserDim = new Bindable();
+ public readonly Bindable EnableUserDim = new Bindable(true);
///
/// Whether or not the storyboard loaded should completely hide the background behind it.
@@ -33,103 +28,58 @@ namespace osu.Game.Graphics.Containers
public readonly Bindable StoryboardReplacesBackground = new Bindable();
///
- /// The amount of blur to be applied to the background in addition to user-specified blur.
+ /// Whether the content of this container is currently being displayed.
///
- ///
- /// Used in contexts where there can potentially be both user and screen-specified blurring occuring at the same time, such as in
- ///
- public readonly Bindable BlurAmount = new Bindable();
+ public bool ContentDisplayed { get; private set; }
- private Bindable userDimLevel { get; set; }
+ protected Bindable UserDimLevel { get; private set; }
- private Bindable userBlurLevel { get; set; }
+ protected Bindable ShowStoryboard { get; private set; }
- private Bindable showStoryboard { get; set; }
+ protected override Container Content => dimContent;
- protected Container DimContainer { get; }
-
- protected override Container Content => DimContainer;
-
- private readonly bool isStoryboard;
-
- ///
- /// As an optimisation, we add the two blur portions to be applied rather than actually applying two separate blurs.
- ///
- private Vector2 blurTarget => EnableUserDim.Value
- ? new Vector2(BlurAmount.Value + (float)userBlurLevel.Value * 25)
- : new Vector2(BlurAmount.Value);
+ private Container dimContent { get; }
///
/// Creates a new .
///
- /// Whether or not this instance contains a storyboard.
- ///
- /// While both backgrounds and storyboards allow user dim levels to be applied, storyboards can be toggled via
- /// and can cause backgrounds to become hidden via . Storyboards are also currently unable to be blurred.
- ///
- ///
- public UserDimContainer(bool isStoryboard = false)
+ protected UserDimContainer()
{
- this.isStoryboard = isStoryboard;
- AddInternal(DimContainer = new Container { RelativeSizeAxes = Axes.Both });
- }
-
- private Background background;
-
- public Background Background
- {
- get => background;
- set
- {
- base.Add(background = value);
- background.BlurTo(blurTarget, 0, Easing.OutQuint);
- }
- }
-
- public override void Add(Drawable drawable)
- {
- if (drawable is Background)
- throw new InvalidOperationException($"Use {nameof(Background)} to set a background.");
-
- base.Add(drawable);
+ AddInternal(dimContent = new Container { RelativeSizeAxes = Axes.Both });
}
[BackgroundDependencyLoader]
private void load(OsuConfigManager config)
{
- userDimLevel = config.GetBindable(OsuSetting.DimLevel);
- userBlurLevel = config.GetBindable(OsuSetting.BlurLevel);
- showStoryboard = config.GetBindable(OsuSetting.ShowStoryboard);
+ UserDimLevel = config.GetBindable(OsuSetting.DimLevel);
+ ShowStoryboard = config.GetBindable(OsuSetting.ShowStoryboard);
- EnableUserDim.ValueChanged += _ => updateVisuals();
- userDimLevel.ValueChanged += _ => updateVisuals();
- userBlurLevel.ValueChanged += _ => updateVisuals();
- showStoryboard.ValueChanged += _ => updateVisuals();
- StoryboardReplacesBackground.ValueChanged += _ => updateVisuals();
- BlurAmount.ValueChanged += _ => updateVisuals();
+ EnableUserDim.ValueChanged += _ => UpdateVisuals();
+ UserDimLevel.ValueChanged += _ => UpdateVisuals();
+ ShowStoryboard.ValueChanged += _ => UpdateVisuals();
+ StoryboardReplacesBackground.ValueChanged += _ => UpdateVisuals();
}
protected override void LoadComplete()
{
base.LoadComplete();
- updateVisuals();
+ UpdateVisuals();
}
- private void updateVisuals()
+ ///
+ /// Whether the content of this container should currently be visible.
+ ///
+ protected virtual bool ShowDimContent => true;
+
+ ///
+ /// Should be invoked when any dependent dim level or user setting is changed and bring the visual state up-to-date.
+ ///
+ protected virtual void UpdateVisuals()
{
- if (isStoryboard)
- {
- DimContainer.FadeTo(!showStoryboard.Value || userDimLevel.Value == 1 ? 0 : 1, background_fade_duration, Easing.OutQuint);
- }
- else
- {
- // The background needs to be hidden in the case of it being replaced by the storyboard
- DimContainer.FadeTo(showStoryboard.Value && StoryboardReplacesBackground.Value ? 0 : 1, background_fade_duration, Easing.OutQuint);
+ ContentDisplayed = ShowDimContent;
- Background?.BlurTo(blurTarget, background_fade_duration, Easing.OutQuint);
- }
-
- DimContainer.FadeColour(EnableUserDim.Value ? OsuColour.Gray(1 - (float)userDimLevel.Value) : Color4.White, background_fade_duration, Easing.OutQuint);
+ dimContent.FadeTo((ContentDisplayed) ? 1 : 0, BACKGROUND_FADE_DURATION, Easing.OutQuint);
+ dimContent.FadeColour(EnableUserDim.Value ? OsuColour.Gray(1 - (float)UserDimLevel.Value) : Color4.White, BACKGROUND_FADE_DURATION, Easing.OutQuint);
}
}
}
diff --git a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs
index 45d751f00e..f3384163b8 100644
--- a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs
+++ b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs
@@ -7,21 +7,20 @@ using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests
{
- public class GetUserBeatmapsRequest : APIRequest>
+ public class GetUserBeatmapsRequest : PaginatedAPIRequest>
{
private readonly long userId;
- private readonly int offset;
+
private readonly BeatmapSetType type;
- public GetUserBeatmapsRequest(long userId, BeatmapSetType type, int offset = 0)
+ public GetUserBeatmapsRequest(long userId, BeatmapSetType type, int page = 0, int itemsPerPage = 6)
+ : base(page, itemsPerPage)
{
this.userId = userId;
- this.offset = offset;
this.type = type;
}
- // ReSharper disable once ImpureMethodCallOnReadonlyValueField
- protected override string Target => $@"users/{userId}/beatmapsets/{type.ToString().Underscore()}?offset={offset}";
+ protected override string Target => $@"users/{userId}/beatmapsets/{type.ToString().Underscore()}";
}
public enum BeatmapSetType
diff --git a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs
index 40e52bdaf6..9f094e51c4 100644
--- a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs
+++ b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs
@@ -6,17 +6,16 @@ using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests
{
- public class GetUserMostPlayedBeatmapsRequest : APIRequest>
+ public class GetUserMostPlayedBeatmapsRequest : PaginatedAPIRequest>
{
private readonly long userId;
- private readonly int offset;
- public GetUserMostPlayedBeatmapsRequest(long userId, int offset = 0)
+ public GetUserMostPlayedBeatmapsRequest(long userId, int page = 0, int itemsPerPage = 5)
+ : base(page, itemsPerPage)
{
this.userId = userId;
- this.offset = offset;
}
- protected override string Target => $@"users/{userId}/beatmapsets/most_played?offset={offset}";
+ protected override string Target => $@"users/{userId}/beatmapsets/most_played";
}
}
diff --git a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs
index 9f80180e70..4908e5ecc2 100644
--- a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs
+++ b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs
@@ -6,18 +6,17 @@ using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests
{
- public class GetUserRecentActivitiesRequest : APIRequest>
+ public class GetUserRecentActivitiesRequest : PaginatedAPIRequest>
{
private readonly long userId;
- private readonly int offset;
- public GetUserRecentActivitiesRequest(long userId, int offset = 0)
+ public GetUserRecentActivitiesRequest(long userId, int page = 0, int itemsPerPage = 5)
+ : base(page, itemsPerPage)
{
this.userId = userId;
- this.offset = offset;
}
- protected override string Target => $"users/{userId}/recent_activity?offset={offset}";
+ protected override string Target => $"users/{userId}/recent_activity";
}
public enum RecentActivityType
diff --git a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs
index 48a43bbbad..d41966fe1b 100644
--- a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs
+++ b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs
@@ -6,21 +6,19 @@ using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests
{
- public class GetUserScoresRequest : APIRequest>
+ public class GetUserScoresRequest : PaginatedAPIRequest>
{
private readonly long userId;
private readonly ScoreType type;
- private readonly int offset;
- public GetUserScoresRequest(long userId, ScoreType type, int offset = 0)
+ public GetUserScoresRequest(long userId, ScoreType type, int page = 0, int itemsPerPage = 5)
+ : base(page, itemsPerPage)
{
this.userId = userId;
this.type = type;
- this.offset = offset;
}
- // ReSharper disable once ImpureMethodCallOnReadonlyValueField
- protected override string Target => $@"users/{userId}/scores/{type.ToString().ToLowerInvariant()}?offset={offset}";
+ protected override string Target => $@"users/{userId}/scores/{type.ToString().ToLowerInvariant()}";
}
public enum ScoreType
diff --git a/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs b/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs
new file mode 100644
index 0000000000..52e12f04ee
--- /dev/null
+++ b/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs
@@ -0,0 +1,30 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System.Globalization;
+using osu.Framework.IO.Network;
+
+namespace osu.Game.Online.API.Requests
+{
+ public abstract class PaginatedAPIRequest : APIRequest
+ {
+ private readonly int page;
+ private readonly int itemsPerPage;
+
+ protected PaginatedAPIRequest(int page, int itemsPerPage)
+ {
+ this.page = page;
+ this.itemsPerPage = itemsPerPage;
+ }
+
+ protected override WebRequest CreateWebRequest()
+ {
+ var req = base.CreateWebRequest();
+
+ req.AddParameter("offset", (page * itemsPerPage).ToString(CultureInfo.InvariantCulture));
+ req.AddParameter("limit", itemsPerPage.ToString(CultureInfo.InvariantCulture));
+
+ return req;
+ }
+ }
+}
diff --git a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs
index 200a705500..e5bfde8f8f 100644
--- a/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs
+++ b/osu.Game/Online/API/Requests/Responses/APIBeatmapSet.cs
@@ -30,6 +30,9 @@ namespace osu.Game.Online.API.Requests.Responses
[JsonProperty(@"preview_url")]
private string preview { get; set; }
+ [JsonProperty(@"has_favourited")]
+ private bool hasFavourited { get; set; }
+
[JsonProperty(@"play_count")]
private int playCount { get; set; }
@@ -91,6 +94,7 @@ namespace osu.Game.Online.API.Requests.Responses
Ranked = ranked,
LastUpdated = lastUpdated,
Availability = availability,
+ HasFavourited = hasFavourited,
},
Beatmaps = beatmaps?.Select(b => b.ToBeatmap(rulesets)).ToList(),
};
diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs
index 35f7ba1c1b..98f15599fc 100644
--- a/osu.Game/Online/Leaderboards/Leaderboard.cs
+++ b/osu.Game/Online/Leaderboards/Leaderboard.cs
@@ -51,7 +51,6 @@ namespace osu.Game.Online.Leaderboards
loading.Hide();
- // schedule because we may not be loaded yet (LoadComponentAsync complains).
showScoresDelegate?.Cancel();
showScoresCancellationSource?.Cancel();
@@ -61,28 +60,22 @@ namespace osu.Game.Online.Leaderboards
// ensure placeholder is hidden when displaying scores
PlaceholderState = PlaceholderState.Successful;
- scrollFlow = CreateScoreFlow();
- scrollFlow.ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1));
+ var sf = CreateScoreFlow();
+ sf.ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1));
- if (!IsLoaded)
- showScoresDelegate = Schedule(showScores);
- else
- showScores();
-
- void showScores() => LoadComponentAsync(scrollFlow, _ =>
+ // schedule because we may not be loaded yet (LoadComponentAsync complains).
+ showScoresDelegate = Schedule(() => LoadComponentAsync(sf, _ =>
{
- scrollContainer.Add(scrollFlow);
+ scrollContainer.Add(scrollFlow = sf);
int i = 0;
foreach (var s in scrollFlow.Children)
- {
using (s.BeginDelayedSequence(i++ * 50, true))
s.Show();
- }
scrollContainer.ScrollTo(0f, false);
- }, (showScoresCancellationSource = new CancellationTokenSource()).Token);
+ }, (showScoresCancellationSource = new CancellationTokenSource()).Token));
}
}
@@ -201,13 +194,17 @@ namespace osu.Game.Online.Leaderboards
private APIRequest getScoresRequest;
+ protected abstract bool IsOnlineScope { get; }
+
public void APIStateChanged(IAPIProvider api, APIState state)
{
switch (state)
{
case APIState.Online:
case APIState.Offline:
- UpdateScores();
+ if (IsOnlineScope)
+ UpdateScores();
+
break;
}
}
diff --git a/osu.Game/OsuGame.cs b/osu.Game/OsuGame.cs
index 1ca4527786..404894a9fd 100644
--- a/osu.Game/OsuGame.cs
+++ b/osu.Game/OsuGame.cs
@@ -249,7 +249,7 @@ namespace osu.Game
}
// Use first beatmap available for current ruleset, else switch ruleset.
- var first = databasedSet.Beatmaps.Find(b => b.Ruleset == Ruleset.Value) ?? databasedSet.Beatmaps.First();
+ var first = databasedSet.Beatmaps.Find(b => b.Ruleset.Equals(Ruleset.Value)) ?? databasedSet.Beatmaps.First();
Ruleset.Value = first.Ruleset;
Beatmap.Value = BeatmapManager.GetWorkingBeatmap(first);
diff --git a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs
index 7207739646..11f56bc163 100644
--- a/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs
+++ b/osu.Game/Overlays/BeatmapSet/Buttons/FavouriteButton.cs
@@ -7,6 +7,7 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
+using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Graphics.Backgrounds;
using osuTK;
@@ -15,7 +16,9 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
{
public class FavouriteButton : HeaderButton
{
- public readonly Bindable Favourited = new Bindable();
+ public readonly Bindable BeatmapSet = new Bindable();
+
+ private readonly Bindable favourited = new Bindable();
[BackgroundDependencyLoader]
private void load()
@@ -54,7 +57,15 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
},
});
- Favourited.ValueChanged += favourited =>
+ BeatmapSet.BindValueChanged(setInfo =>
+ {
+ if (setInfo.NewValue?.OnlineInfo?.HasFavourited == null)
+ return;
+
+ favourited.Value = setInfo.NewValue.OnlineInfo.HasFavourited;
+ });
+
+ favourited.ValueChanged += favourited =>
{
if (favourited.NewValue)
{
@@ -67,8 +78,6 @@ namespace osu.Game.Overlays.BeatmapSet.Buttons
icon.Icon = FontAwesome.Regular.Heart;
}
};
-
- Action = () => Favourited.Value = !Favourited.Value;
}
protected override void UpdateAfterChildren()
diff --git a/osu.Game/Overlays/BeatmapSet/Header.cs b/osu.Game/Overlays/BeatmapSet/Header.cs
index b50eac2c1a..260a989628 100644
--- a/osu.Game/Overlays/BeatmapSet/Header.cs
+++ b/osu.Game/Overlays/BeatmapSet/Header.cs
@@ -161,7 +161,10 @@ namespace osu.Game.Overlays.BeatmapSet
Margin = new MarginPadding { Top = 10 },
Children = new Drawable[]
{
- favouriteButton = new FavouriteButton(),
+ favouriteButton = new FavouriteButton
+ {
+ BeatmapSet = { BindTarget = BeatmapSet }
+ },
downloadButtonsContainer = new FillFlowContainer
{
RelativeSizeAxes = Axes.Both,
diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs
index 22d7ea9c97..a6cc2b0500 100644
--- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs
+++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs
@@ -19,7 +19,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
public class ScoresContainer : CompositeDrawable
{
private const int spacing = 15;
- private const int fade_duration = 200;
private readonly Box background;
private readonly ScoreTable scoreTable;
@@ -53,8 +52,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
{
Schedule(() =>
{
- loading = false;
-
topScoresContainer.Clear();
if (value?.Scores.Any() != true)
@@ -128,11 +125,6 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
background.Colour = colours.Gray2;
}
- private bool loading
- {
- set => loadingAnimation.FadeTo(value ? 1 : 0, fade_duration);
- }
-
private void getScores(BeatmapInfo beatmap)
{
getScoresRequest?.Cancel();
@@ -141,15 +133,16 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
Scores = null;
if (beatmap?.OnlineBeatmapID.HasValue != true)
- {
- loading = false;
return;
- }
+ loadingAnimation.Show();
getScoresRequest = new GetScoresRequest(beatmap, beatmap.Ruleset);
- getScoresRequest.Success += scores => Scores = scores;
+ getScoresRequest.Success += scores =>
+ {
+ loadingAnimation.Hide();
+ Scores = scores;
+ };
api.Queue(getScoresRequest);
- loading = true;
}
}
}
diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs
index a15d3c5fd1..ffc39e5af2 100644
--- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs
+++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreUserSection.cs
@@ -62,7 +62,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
},
}
},
- avatar = new UpdateableAvatar(hideImmediately: true)
+ avatar = new UpdateableAvatar
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
@@ -99,7 +99,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
Origin = Anchor.CentreLeft,
Font = OsuFont.GetFont(size: 15, weight: FontWeight.Bold)
},
- flag = new UpdateableFlag(hideImmediately: true)
+ flag = new UpdateableFlag
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
diff --git a/osu.Game/Overlays/Direct/DirectRulesetSelector.cs b/osu.Game/Overlays/Direct/DirectRulesetSelector.cs
index fdab9f1b90..106aaa616b 100644
--- a/osu.Game/Overlays/Direct/DirectRulesetSelector.cs
+++ b/osu.Game/Overlays/Direct/DirectRulesetSelector.cs
@@ -26,8 +26,13 @@ namespace osu.Game.Overlays.Direct
TabContainer.Masking = false;
TabContainer.Spacing = new Vector2(10, 0);
AutoSizeAxes = Axes.Both;
+ }
- Current.DisabledChanged += value => SelectedTab.FadeColour(value ? Color4.DarkGray : Color4.White, 200, Easing.OutQuint);
+ protected override void LoadComplete()
+ {
+ base.LoadComplete();
+
+ Current.BindDisabledChanged(value => SelectedTab.FadeColour(value ? Color4.DarkGray : Color4.White, 200, Easing.OutQuint), true);
}
protected override TabItem CreateTabItem(RulesetInfo value) => new DirectRulesetTabItem(value);
diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs
index b6b0e605d7..1b6c1c99a6 100644
--- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs
+++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs
@@ -29,7 +29,7 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps
protected override void ShowMore()
{
- request = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage);
+ request = new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage);
request.Success += sets => Schedule(() =>
{
MoreButton.FadeTo(sets.Count == ItemsPerPage ? 1 : 0);
diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs
index 6085b0bc05..9409cd9aeb 100644
--- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs
+++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs
@@ -24,7 +24,7 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
protected override void ShowMore()
{
- request = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++ * ItemsPerPage);
+ request = new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++, ItemsPerPage);
request.Success += beatmaps => Schedule(() =>
{
MoreButton.FadeTo(beatmaps.Count == ItemsPerPage ? 1 : 0);
diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs
index a149cfa12e..4a9ac6e5c7 100644
--- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs
+++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs
@@ -31,7 +31,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
protected override void ShowMore()
{
- request = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++ * ItemsPerPage);
+ request = new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage);
request.Success += scores => Schedule(() =>
{
foreach (var s in scores)
diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs
index b72aec7a44..f2a778a874 100644
--- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs
+++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs
@@ -22,7 +22,7 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
protected override void ShowMore()
{
- request = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++ * ItemsPerPage);
+ request = new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++, ItemsPerPage);
request.Success += activities => Schedule(() =>
{
MoreButton.FadeTo(activities.Count == ItemsPerPage ? 1 : 0);
diff --git a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs
index f4272ab15c..bf0cd91321 100644
--- a/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs
+++ b/osu.Game/Overlays/Toolbar/ToolbarRulesetSelector.cs
@@ -73,7 +73,7 @@ namespace osu.Game.Overlays.Toolbar
{
foreach (var tabItem in TabContainer)
{
- if (tabItem.Value == Current.Value)
+ if (tabItem.Value.Equals(Current.Value))
{
ModeButtonLine.MoveToX(tabItem.DrawPosition.X, !hasInitialPosition ? 0 : 200, Easing.OutQuint);
break;
diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
index 1f6ca4dd73..e61fac679e 100644
--- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
+++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
@@ -7,7 +7,6 @@ using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions.TypeExtensions;
-using osu.Framework.Graphics;
using osu.Framework.Graphics.Primitives;
using osu.Game.Audio;
using osu.Game.Graphics;
@@ -179,6 +178,39 @@ namespace osu.Game.Rulesets.Objects.Drawables
UpdateResult(false);
}
+ private double? lifetimeStart;
+
+ public override double LifetimeStart
+ {
+ get => lifetimeStart ?? (HitObject.StartTime - InitialLifetimeOffset);
+ set
+ {
+ base.LifetimeStart = value;
+ lifetimeStart = value;
+ }
+ }
+
+ ///
+ /// A safe offset prior to the start time of at which this may begin displaying contents.
+ /// By default, s are assumed to display their contents within 10 seconds prior to the start time of .
+ ///
+ ///
+ /// This is only used as an optimisation to delay the initial update of this and may be tuned more aggressively if required.
+ /// A more accurate should be set inside for an state.
+ ///
+ protected virtual double InitialLifetimeOffset => 10000;
+
+ ///
+ /// Will be called at least once after this has become not alive.
+ ///
+ public virtual void OnKilled()
+ {
+ foreach (var nested in NestedHitObjects)
+ nested.OnKilled();
+
+ UpdateResult(false);
+ }
+
protected virtual void AddNested(DrawableHitObject h)
{
h.OnNewResult += (d, r) => OnNewResult?.Invoke(d, r);
@@ -223,16 +255,6 @@ namespace osu.Game.Rulesets.Objects.Drawables
OnNewResult?.Invoke(this, Result);
}
- ///
- /// Will called at least once after the of this has been passed.
- ///
- internal void OnLifetimeEnd()
- {
- foreach (var nested in NestedHitObjects)
- nested.OnLifetimeEnd();
- UpdateResult(false);
- }
-
///
/// Processes this , checking if a scoring result has occurred.
///
diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs
index 6e79d0b766..71e321f205 100644
--- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs
+++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHitObjectParser.cs
@@ -37,7 +37,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch
};
}
- protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples)
+ protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount,
+ List> nodeSamples)
{
newCombo |= forceNewCombo;
comboOffset += extraComboOffset;
diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs
index f5b1cbcebf..d70c1bf7d3 100644
--- a/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs
+++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObjectParser.cs
@@ -72,7 +72,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
else if (type.HasFlag(ConvertHitObjectType.Slider))
{
PathType pathType = PathType.Catmull;
- double length = 0;
+ double? length = null;
string[] pointSplit = split[5].Split('|');
@@ -130,7 +130,11 @@ namespace osu.Game.Rulesets.Objects.Legacy
repeatCount = Math.Max(0, repeatCount - 1);
if (split.Length > 7)
+ {
length = Math.Max(0, Parsing.ParseDouble(split[7]));
+ if (length == 0)
+ length = null;
+ }
if (split.Length > 10)
readCustomSampleBanks(split[10], bankInfo);
@@ -291,7 +295,8 @@ namespace osu.Game.Rulesets.Objects.Legacy
/// The slider repeat count.
/// The samples to be played when the slider nodes are hit. This includes the head and tail of the slider.
/// The hit object.
- protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples);
+ protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount,
+ List> nodeSamples);
///
/// Creates a legacy Spinner-type hit object.
diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs
index b20a027e78..94aba95e90 100644
--- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs
+++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHitObjectParser.cs
@@ -26,7 +26,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania
};
}
- protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples)
+ protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount,
+ List> nodeSamples)
{
return new ConvertSlider
{
diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs
index 0a4e38df02..65102f1e89 100644
--- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs
+++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHitObjectParser.cs
@@ -1,7 +1,6 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
-using System;
using osuTK;
using osu.Game.Rulesets.Objects.Types;
using System.Collections.Generic;
@@ -38,7 +37,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
};
}
- protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples)
+ protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount,
+ List> nodeSamples)
{
newCombo |= forceNewCombo;
comboOffset += extraComboOffset;
@@ -51,7 +51,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
Position = position,
NewCombo = FirstObject || newCombo,
ComboOffset = comboOffset,
- Path = new SliderPath(pathType, controlPoints, Math.Max(0, length)),
+ Path = new SliderPath(pathType, controlPoints, length),
NodeSamples = nodeSamples,
RepeatCount = repeatCount
};
diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs
index 7c1514c1eb..eb598f1368 100644
--- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs
+++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHitObjectParser.cs
@@ -23,7 +23,8 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko
return new ConvertHit();
}
- protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double length, PathType pathType, int repeatCount, List> nodeSamples)
+ protected override HitObject CreateSlider(Vector2 position, bool newCombo, int comboOffset, Vector2[] controlPoints, double? length, PathType pathType, int repeatCount,
+ List> nodeSamples)
{
return new ConvertSlider
{
diff --git a/osu.Game/Rulesets/RulesetInfo.cs b/osu.Game/Rulesets/RulesetInfo.cs
index ca331ec339..d9cff86265 100644
--- a/osu.Game/Rulesets/RulesetInfo.cs
+++ b/osu.Game/Rulesets/RulesetInfo.cs
@@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
+using System.Diagnostics.CodeAnalysis;
using Newtonsoft.Json;
namespace osu.Game.Rulesets
@@ -23,6 +24,21 @@ namespace osu.Game.Rulesets
public bool Equals(RulesetInfo other) => other != null && ID == other.ID && Available == other.Available && Name == other.Name && InstantiationInfo == other.InstantiationInfo;
+ public override bool Equals(object obj) => obj is RulesetInfo rulesetInfo && Equals(rulesetInfo);
+
+ [SuppressMessage("ReSharper", "NonReadonlyMemberInGetHashCode")]
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ var hashCode = ID.HasValue ? ID.GetHashCode() : 0;
+ hashCode = (hashCode * 397) ^ (InstantiationInfo != null ? InstantiationInfo.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ (Name != null ? Name.GetHashCode() : 0);
+ hashCode = (hashCode * 397) ^ Available.GetHashCode();
+ return hashCode;
+ }
+ }
+
public override string ToString() => $"{Name} ({ShortName}) ID: {ID}";
}
}
diff --git a/osu.Game/Rulesets/RulesetStore.cs b/osu.Game/Rulesets/RulesetStore.cs
index fd42f96c92..2d8c9f5b49 100644
--- a/osu.Game/Rulesets/RulesetStore.cs
+++ b/osu.Game/Rulesets/RulesetStore.cs
@@ -32,7 +32,7 @@ namespace osu.Game.Rulesets
public RulesetStore(IDatabaseContextFactory factory)
: base(factory)
{
- AddMissingRulesets();
+ addMissingRulesets();
}
///
@@ -52,13 +52,13 @@ namespace osu.Game.Rulesets
///
/// All available rulesets.
///
- public IEnumerable AvailableRulesets;
+ public IEnumerable AvailableRulesets { get; private set; }
private static Assembly currentDomain_AssemblyResolve(object sender, ResolveEventArgs args) => loaded_assemblies.Keys.FirstOrDefault(a => a.FullName == args.Name);
private const string ruleset_library_prefix = "osu.Game.Rulesets";
- protected void AddMissingRulesets()
+ private void addMissingRulesets()
{
using (var usage = ContextFactory.GetForWrite())
{
diff --git a/osu.Game/Rulesets/UI/HitObjectContainer.cs b/osu.Game/Rulesets/UI/HitObjectContainer.cs
index 2f3a384e95..9485189433 100644
--- a/osu.Game/Rulesets/UI/HitObjectContainer.cs
+++ b/osu.Game/Rulesets/UI/HitObjectContainer.cs
@@ -34,8 +34,14 @@ namespace osu.Game.Rulesets.UI
protected override void OnChildLifetimeBoundaryCrossed(LifetimeBoundaryCrossedEvent e)
{
- if (e.Kind == LifetimeBoundaryKind.End && e.Direction == LifetimeBoundaryCrossingDirection.Forward && e.Child is DrawableHitObject hitObject)
- hitObject.OnLifetimeEnd();
+ if (!(e.Child is DrawableHitObject hitObject))
+ return;
+
+ if ((e.Kind == LifetimeBoundaryKind.End && e.Direction == LifetimeBoundaryCrossingDirection.Forward)
+ || (e.Kind == LifetimeBoundaryKind.Start && e.Direction == LifetimeBoundaryCrossingDirection.Backward))
+ {
+ hitObject.OnKilled();
+ }
}
}
}
diff --git a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs
index b6c2d016d2..5225740d0b 100644
--- a/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs
+++ b/osu.Game/Screens/Backgrounds/BackgroundScreenBeatmap.cs
@@ -1,19 +1,28 @@
-// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System;
using System.Threading;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Textures;
using osu.Game.Beatmaps;
+using osu.Game.Configuration;
using osu.Game.Graphics.Backgrounds;
using osu.Game.Graphics.Containers;
+using osu.Game.Screens.Play;
+using osuTK;
namespace osu.Game.Screens.Backgrounds
{
public class BackgroundScreenBeatmap : BackgroundScreen
{
+ ///
+ /// The amount of blur to apply when full user blur is requested.
+ ///
+ public const float USER_BLUR_FACTOR = 25;
+
protected Background Background;
private WorkingBeatmap beatmap;
@@ -30,16 +39,17 @@ namespace osu.Game.Screens.Backgrounds
///
public readonly Bindable BlurAmount = new Bindable();
- private readonly UserDimContainer fadeContainer;
+ private readonly DimmableBackground dimmable;
- protected virtual UserDimContainer CreateFadeContainer() => new UserDimContainer { RelativeSizeAxes = Axes.Both };
+ protected virtual DimmableBackground CreateFadeContainer() => new DimmableBackground { RelativeSizeAxes = Axes.Both };
public BackgroundScreenBeatmap(WorkingBeatmap beatmap = null)
{
Beatmap = beatmap;
- InternalChild = fadeContainer = CreateFadeContainer();
- fadeContainer.EnableUserDim.BindTo(EnableUserDim);
- fadeContainer.BlurAmount.BindTo(BlurAmount);
+
+ InternalChild = dimmable = CreateFadeContainer();
+ dimmable.EnableUserDim.BindTo(EnableUserDim);
+ dimmable.BlurAmount.BindTo(BlurAmount);
}
[BackgroundDependencyLoader]
@@ -86,8 +96,8 @@ namespace osu.Game.Screens.Backgrounds
}
b.Depth = newDepth;
- fadeContainer.Background = Background = b;
- StoryboardReplacesBackground.BindTo(fadeContainer.StoryboardReplacesBackground);
+ dimmable.Background = Background = b;
+ StoryboardReplacesBackground.BindTo(dimmable.StoryboardReplacesBackground);
}
public override bool Equals(BackgroundScreen other)
@@ -112,5 +122,70 @@ namespace osu.Game.Screens.Backgrounds
Sprite.Texture = Beatmap?.Background ?? textures.Get(@"Backgrounds/bg1");
}
}
+
+ public class DimmableBackground : UserDimContainer
+ {
+ ///
+ /// The amount of blur to be applied to the background in addition to user-specified blur.
+ ///
+ ///
+ /// Used in contexts where there can potentially be both user and screen-specified blurring occuring at the same time, such as in
+ ///
+ public readonly Bindable BlurAmount = new Bindable();
+
+ public Background Background
+ {
+ get => background;
+ set
+ {
+ background?.Expire();
+
+ base.Add(background = value);
+ background.BlurTo(blurTarget, 0, Easing.OutQuint);
+ }
+ }
+
+ private Bindable userBlurLevel { get; set; }
+
+ private Background background;
+
+ public override void Add(Drawable drawable)
+ {
+ if (drawable is Background)
+ throw new InvalidOperationException($"Use {nameof(Background)} to set a background.");
+
+ base.Add(drawable);
+ }
+
+ ///
+ /// As an optimisation, we add the two blur portions to be applied rather than actually applying two separate blurs.
+ ///
+ private Vector2 blurTarget => EnableUserDim.Value
+ ? new Vector2(BlurAmount.Value + (float)userBlurLevel.Value * USER_BLUR_FACTOR)
+ : new Vector2(BlurAmount.Value);
+
+ [BackgroundDependencyLoader]
+ private void load(OsuConfigManager config)
+ {
+ userBlurLevel = config.GetBindable(OsuSetting.BlurLevel);
+ }
+
+ protected override void LoadComplete()
+ {
+ base.LoadComplete();
+
+ userBlurLevel.ValueChanged += _ => UpdateVisuals();
+ BlurAmount.ValueChanged += _ => UpdateVisuals();
+ }
+
+ protected override bool ShowDimContent => !ShowStoryboard.Value || !StoryboardReplacesBackground.Value; // The background needs to be hidden in the case of it being replaced by the storyboard
+
+ protected override void UpdateVisuals()
+ {
+ base.UpdateVisuals();
+
+ Background?.BlurTo(blurTarget, BACKGROUND_FADE_DURATION, Easing.OutQuint);
+ }
+ }
}
}
diff --git a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs
index fff713f026..ae27e53813 100644
--- a/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs
+++ b/osu.Game/Screens/Multi/Match/Components/MatchLeaderboard.cs
@@ -33,6 +33,8 @@ namespace osu.Game.Screens.Multi.Match.Components
}, true);
}
+ protected override bool IsOnlineScope => true;
+
protected override APIRequest FetchScores(Action> scoresCallback)
{
if (roomId.Value == null)
diff --git a/osu.Game/Screens/Play/DimmableStoryboard.cs b/osu.Game/Screens/Play/DimmableStoryboard.cs
new file mode 100644
index 0000000000..45dff039b6
--- /dev/null
+++ b/osu.Game/Screens/Play/DimmableStoryboard.cs
@@ -0,0 +1,55 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Framework.Allocation;
+using osu.Game.Graphics.Containers;
+using osu.Game.Storyboards;
+using osu.Game.Storyboards.Drawables;
+
+namespace osu.Game.Screens.Play
+{
+ ///
+ /// A container that handles loading, as well as applies user-specified visual settings to it.
+ ///
+ public class DimmableStoryboard : UserDimContainer
+ {
+ private readonly Storyboard storyboard;
+ private DrawableStoryboard drawableStoryboard;
+
+ public DimmableStoryboard(Storyboard storyboard)
+ {
+ this.storyboard = storyboard;
+ }
+
+ [BackgroundDependencyLoader]
+ private void load()
+ {
+ initializeStoryboard(false);
+ }
+
+ protected override void LoadComplete()
+ {
+ ShowStoryboard.BindValueChanged(_ => initializeStoryboard(true), true);
+ base.LoadComplete();
+ }
+
+ protected override bool ShowDimContent => ShowStoryboard.Value && UserDimLevel.Value < 1;
+
+ private void initializeStoryboard(bool async)
+ {
+ if (drawableStoryboard != null)
+ return;
+
+ if (!ShowStoryboard.Value)
+ return;
+
+ drawableStoryboard = storyboard.CreateDrawable();
+ drawableStoryboard.Masking = true;
+
+ if (async)
+ LoadComponentAsync(drawableStoryboard, Add);
+ else
+ Add(drawableStoryboard);
+ }
+ }
+}
diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs
index 0da9c77f25..8dc16af575 100644
--- a/osu.Game/Screens/Play/Player.cs
+++ b/osu.Game/Screens/Play/Player.cs
@@ -26,7 +26,6 @@ using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
using osu.Game.Screens.Ranking;
using osu.Game.Skinning;
-using osu.Game.Storyboards.Drawables;
using osu.Game.Users;
namespace osu.Game.Screens.Play
@@ -76,6 +75,8 @@ namespace osu.Game.Screens.Play
protected GameplayClockContainer GameplayClockContainer { get; private set; }
+ protected DimmableStoryboard DimmableStoryboard { get; private set; }
+
[Cached]
[Cached(Type = typeof(IBindable>))]
protected new readonly Bindable> Mods = new Bindable>(Array.Empty());
@@ -109,7 +110,6 @@ namespace osu.Game.Screens.Play
sampleRestart = audio.Samples.Get(@"Gameplay/restart");
mouseWheelDisabled = config.GetBindable(OsuSetting.MouseDisableWheel);
- showStoryboard = config.GetBindable(OsuSetting.ShowStoryboard);
ScoreProcessor = DrawableRuleset.CreateScoreProcessor();
ScoreProcessor.Mods.BindTo(Mods);
@@ -121,7 +121,7 @@ namespace osu.Game.Screens.Play
GameplayClockContainer.Children = new[]
{
- StoryboardContainer = CreateStoryboardContainer(),
+ DimmableStoryboard = new DimmableStoryboard(Beatmap.Value.Storyboard) { RelativeSizeAxes = Axes.Both },
new ScalingContainer(ScalingMode.Gameplay)
{
Child = new LocalSkinOverrideContainer(working.Skin)
@@ -199,9 +199,6 @@ namespace osu.Game.Screens.Play
// bind clock into components that require it
DrawableRuleset.IsPaused.BindTo(GameplayClockContainer.IsPaused);
- // load storyboard as part of player's load if we can
- initializeStoryboard(false);
-
// Bind ScoreProcessor to ourselves
ScoreProcessor.AllJudged += onCompletion;
ScoreProcessor.Failed += onFail;
@@ -334,41 +331,6 @@ namespace osu.Game.Screens.Play
protected virtual Results CreateResults(ScoreInfo score) => new SoloResults(score);
- #region Storyboard
-
- private DrawableStoryboard storyboard;
- protected UserDimContainer StoryboardContainer { get; private set; }
-
- protected virtual UserDimContainer CreateStoryboardContainer() => new UserDimContainer(true)
- {
- RelativeSizeAxes = Axes.Both,
- Alpha = 1,
- EnableUserDim = { Value = true }
- };
-
- private Bindable showStoryboard;
-
- private void initializeStoryboard(bool asyncLoad)
- {
- if (StoryboardContainer == null || storyboard != null)
- return;
-
- if (!showStoryboard.Value)
- return;
-
- var beatmap = Beatmap.Value;
-
- storyboard = beatmap.Storyboard.CreateDrawable();
- storyboard.Masking = true;
-
- if (asyncLoad)
- LoadComponentAsync(storyboard, StoryboardContainer.Add);
- else
- StoryboardContainer.Add(storyboard);
- }
-
- #endregion
-
#region Fail Logic
protected FailOverlay FailOverlay { get; private set; }
@@ -486,13 +448,11 @@ namespace osu.Game.Screens.Play
.Delay(250)
.FadeIn(250);
- showStoryboard.ValueChanged += _ => initializeStoryboard(true);
-
Background.EnableUserDim.Value = true;
Background.BlurAmount.Value = 0;
Background.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground);
- StoryboardContainer.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground);
+ DimmableStoryboard.StoryboardReplacesBackground.BindTo(storyboardReplacesBackground);
storyboardReplacesBackground.Value = Beatmap.Value.Storyboard.ReplacesBackground && Beatmap.Value.Storyboard.HasDrawable;
diff --git a/osu.Game/Screens/Play/SkipOverlay.cs b/osu.Game/Screens/Play/SkipOverlay.cs
index 38dd179f25..d6c2b59d98 100644
--- a/osu.Game/Screens/Play/SkipOverlay.cs
+++ b/osu.Game/Screens/Play/SkipOverlay.cs
@@ -161,6 +161,8 @@ namespace osu.Game.Screens.Play
private Visibility state;
private ScheduledDelegate scheduledHide;
+ public override bool IsPresent => true;
+
public Visibility State
{
get => state;
@@ -201,14 +203,15 @@ namespace osu.Game.Screens.Play
protected override bool OnMouseDown(MouseDownEvent e)
{
+ Show();
scheduledHide?.Cancel();
- return base.OnMouseDown(e);
+ return true;
}
protected override bool OnMouseUp(MouseUpEvent e)
{
Show();
- return base.OnMouseUp(e);
+ return true;
}
public override void Hide() => State = Visibility.Hidden;
diff --git a/osu.Game/Screens/Ranking/Results.cs b/osu.Game/Screens/Ranking/Results.cs
index f53fb75e1a..cac26b3dbf 100644
--- a/osu.Game/Screens/Ranking/Results.cs
+++ b/osu.Game/Screens/Ranking/Results.cs
@@ -256,9 +256,12 @@ namespace osu.Game.Screens.Ranking
}
};
- foreach (var t in CreateResultPages())
- modeChangeButtons.AddItem(t);
- modeChangeButtons.Current.Value = modeChangeButtons.Items.FirstOrDefault();
+ var pages = CreateResultPages();
+
+ foreach (var p in pages)
+ modeChangeButtons.AddItem(p);
+
+ modeChangeButtons.Current.Value = pages.FirstOrDefault();
modeChangeButtons.Current.BindValueChanged(page =>
{
diff --git a/osu.Game/Screens/Select/FilterControl.cs b/osu.Game/Screens/Select/FilterControl.cs
index bd0b0dd5cd..57fe15fd99 100644
--- a/osu.Game/Screens/Select/FilterControl.cs
+++ b/osu.Game/Screens/Select/FilterControl.cs
@@ -120,7 +120,8 @@ namespace osu.Game.Screens.Select
RelativeSizeAxes = Axes.X,
Height = 24,
Width = 0.5f,
- AutoSort = true
+ AutoSort = true,
+ Current = { Value = GroupMode.Title }
},
//spriteText = new OsuSpriteText
//{
@@ -139,6 +140,7 @@ namespace osu.Game.Screens.Select
Width = 0.5f,
Height = 24,
AutoSort = true,
+ Current = { Value = SortMode.Title }
}
}
},
diff --git a/osu.Game/Screens/Select/FooterButtonMods.cs b/osu.Game/Screens/Select/FooterButtonMods.cs
index c96c5022c0..fce4d1b2e2 100644
--- a/osu.Game/Screens/Select/FooterButtonMods.cs
+++ b/osu.Game/Screens/Select/FooterButtonMods.cs
@@ -9,18 +9,25 @@ using osu.Game.Rulesets.Mods;
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
+using osu.Framework.Graphics.UserInterface;
using osu.Game.Graphics;
using osuTK;
using osuTK.Input;
namespace osu.Game.Screens.Select
{
- public class FooterButtonMods : FooterButton
+ public class FooterButtonMods : FooterButton, IHasCurrentValue>
{
- public FooterButtonMods(Bindable> mods)
+ public Bindable> Current
{
- FooterModDisplay modDisplay;
+ get => modDisplay.Current;
+ set => modDisplay.Current = value;
+ }
+ private readonly FooterModDisplay modDisplay;
+
+ public FooterButtonMods()
+ {
Add(new Container
{
Anchor = Anchor.CentreLeft,
@@ -33,9 +40,6 @@ namespace osu.Game.Screens.Select
AutoSizeAxes = Axes.Both,
Margin = new MarginPadding { Left = 70 }
});
-
- if (mods != null)
- modDisplay.Current = mods;
}
[BackgroundDependencyLoader]
diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs
index 0f6d4f3188..cb45c00f66 100644
--- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs
+++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs
@@ -79,6 +79,8 @@ namespace osu.Game.Screens.Select.Leaderboards
};
}
+ protected override bool IsOnlineScope => Scope != BeatmapLeaderboardScope.Local;
+
protected override APIRequest FetchScores(Action> scoresCallback)
{
if (Scope == BeatmapLeaderboardScope.Local)
diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs
index 0eeffda5eb..20dbcf2693 100644
--- a/osu.Game/Screens/Select/SongSelect.cs
+++ b/osu.Game/Screens/Select/SongSelect.cs
@@ -221,11 +221,9 @@ namespace osu.Game.Screens.Select
[BackgroundDependencyLoader(true)]
private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours, SkinManager skins, ScoreManager scores)
{
- mods.BindTo(Mods);
-
if (Footer != null)
{
- Footer.AddButton(new FooterButtonMods(mods), ModSelect);
+ Footer.AddButton(new FooterButtonMods { Current = mods }, ModSelect);
Footer.AddButton(new FooterButtonRandom { Action = triggerRandom });
Footer.AddButton(new FooterButtonOptions(), BeatmapOptions);
@@ -253,7 +251,7 @@ namespace osu.Game.Screens.Select
Schedule(() =>
{
// if we have no beatmaps but osu-stable is found, let's prompt the user to import.
- if (!beatmaps.GetAllUsableBeatmapSets().Any() && beatmaps.StableInstallationAvailable)
+ if (!beatmaps.GetAllUsableBeatmapSetsEnumerable().Any() && beatmaps.StableInstallationAvailable)
dialogOverlay.Push(new ImportFromStablePopup(() =>
{
Task.Run(beatmaps.ImportFromStableAsync).ContinueWith(_ => scores.ImportFromStableAsync(), TaskContinuationOptions.OnlyOnRanToCompletion);
@@ -263,6 +261,13 @@ namespace osu.Game.Screens.Select
}
}
+ protected override void LoadComplete()
+ {
+ base.LoadComplete();
+
+ mods.BindTo(Mods);
+ }
+
private DependencyContainer dependencies;
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
@@ -329,7 +334,7 @@ namespace osu.Game.Screens.Select
if (this.IsCurrentScreen() && !Carousel.SelectBeatmap(e.NewValue?.BeatmapInfo, false))
// If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch
- if (e.NewValue?.BeatmapInfo?.Ruleset != null && e.NewValue.BeatmapInfo.Ruleset != decoupledRuleset.Value)
+ if (e.NewValue?.BeatmapInfo?.Ruleset != null && !e.NewValue.BeatmapInfo.Ruleset.Equals(decoupledRuleset.Value))
{
Ruleset.Value = e.NewValue.BeatmapInfo.Ruleset;
Carousel.SelectBeatmap(e.NewValue.BeatmapInfo);
diff --git a/osu.Game/Skinning/LocalSkinOverrideContainer.cs b/osu.Game/Skinning/LocalSkinOverrideContainer.cs
index 37f4cc28a2..7882e0f31b 100644
--- a/osu.Game/Skinning/LocalSkinOverrideContainer.cs
+++ b/osu.Game/Skinning/LocalSkinOverrideContainer.cs
@@ -34,7 +34,7 @@ namespace osu.Game.Skinning
public Drawable GetDrawableComponent(string componentName)
{
Drawable sourceDrawable;
- if (beatmapSkins.Value && (sourceDrawable = skin.GetDrawableComponent(componentName)) != null)
+ if (beatmapSkins.Value && (sourceDrawable = skin?.GetDrawableComponent(componentName)) != null)
return sourceDrawable;
return fallbackSource?.GetDrawableComponent(componentName);
@@ -43,7 +43,7 @@ namespace osu.Game.Skinning
public Texture GetTexture(string componentName)
{
Texture sourceTexture;
- if (beatmapSkins.Value && (sourceTexture = skin.GetTexture(componentName)) != null)
+ if (beatmapSkins.Value && (sourceTexture = skin?.GetTexture(componentName)) != null)
return sourceTexture;
return fallbackSource.GetTexture(componentName);
@@ -52,7 +52,7 @@ namespace osu.Game.Skinning
public SampleChannel GetSample(string sampleName)
{
SampleChannel sourceChannel;
- if (beatmapHitsounds.Value && (sourceChannel = skin.GetSample(sampleName)) != null)
+ if (beatmapHitsounds.Value && (sourceChannel = skin?.GetSample(sampleName)) != null)
return sourceChannel;
return fallbackSource?.GetSample(sampleName);
diff --git a/osu.Game/Users/Drawables/UpdateableAvatar.cs b/osu.Game/Users/Drawables/UpdateableAvatar.cs
index a49f2d079b..795b90ba11 100644
--- a/osu.Game/Users/Drawables/UpdateableAvatar.cs
+++ b/osu.Game/Users/Drawables/UpdateableAvatar.cs
@@ -5,7 +5,6 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Effects;
-using osu.Framework.Graphics.Transforms;
namespace osu.Game.Users.Drawables
{
@@ -38,8 +37,6 @@ namespace osu.Game.Users.Drawables
set => base.EdgeEffect = value;
}
- protected override bool TransformImmediately { get; }
-
///
/// Whether to show a default guest representation on null user (as opposed to nothing).
///
@@ -50,14 +47,11 @@ namespace osu.Game.Users.Drawables
///
public readonly BindableBool OpenOnClick = new BindableBool(true);
- public UpdateableAvatar(User user = null, bool hideImmediately = false)
+ public UpdateableAvatar(User user = null)
{
- TransformImmediately = hideImmediately;
User = user;
}
- protected override TransformSequence ApplyHideTransforms(Drawable drawable) => TransformImmediately ? drawable?.FadeOut() : base.ApplyHideTransforms(drawable);
-
protected override Drawable CreateDrawable(User user)
{
if (user == null && !ShowGuestOnNull)
diff --git a/osu.Game/Users/Drawables/UpdateableFlag.cs b/osu.Game/Users/Drawables/UpdateableFlag.cs
index 78d1a8de20..abc16b2390 100644
--- a/osu.Game/Users/Drawables/UpdateableFlag.cs
+++ b/osu.Game/Users/Drawables/UpdateableFlag.cs
@@ -3,7 +3,6 @@
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
-using osu.Framework.Graphics.Transforms;
namespace osu.Game.Users.Drawables
{
@@ -15,21 +14,16 @@ namespace osu.Game.Users.Drawables
set => Model = value;
}
- protected override bool TransformImmediately { get; }
-
///
/// Whether to show a place holder on null country.
///
public bool ShowPlaceholderOnNull = true;
- public UpdateableFlag(Country country = null, bool hideImmediately = false)
+ public UpdateableFlag(Country country = null)
{
- TransformImmediately = hideImmediately;
Country = country;
}
- protected override TransformSequence ApplyHideTransforms(Drawable drawable) => TransformImmediately ? drawable?.FadeOut() : base.ApplyHideTransforms(drawable);
-
protected override Drawable CreateDrawable(Country country)
{
if (country == null && !ShowPlaceholderOnNull)
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 436ba90a88..d90b1d36e1 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -15,7 +15,7 @@
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index c24349bcb5..fa2521a19e 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -105,8 +105,8 @@
-
-
+
+
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json
index bbd5f4f3ba..af4b103867 100644
--- a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -1,249 +1 @@
-{
- "images": [
- {
- "filename": "Icon-App-20x20@2x.png",
- "size": "20x20",
- "scale": "2x",
- "idiom": "iphone"
- },
- {
- "filename": "Icon-App-20x20@3x.png",
- "size": "20x20",
- "scale": "3x",
- "idiom": "iphone"
- },
- {
- "filename": "Icon-App-29x29@2x.png",
- "size": "29x29",
- "scale": "2x",
- "idiom": "iphone"
- },
- {
- "filename": "Icon-App-29x29@3x.png",
- "size": "29x29",
- "scale": "3x",
- "idiom": "iphone"
- },
- {
- "filename": "Icon-App-40x40@2x.png",
- "size": "40x40",
- "scale": "2x",
- "idiom": "iphone"
- },
- {
- "filename": "Icon-App-40x40@3x.png",
- "size": "40x40",
- "scale": "3x",
- "idiom": "iphone"
- },
- {
- "filename": "Icon-App-60x60@2x.png",
- "size": "60x60",
- "scale": "2x",
- "idiom": "iphone"
- },
- {
- "filename": "Icon-App-60x60@3x.png",
- "size": "60x60",
- "scale": "3x",
- "idiom": "iphone"
- },
- {
- "filename": "Icon-App-20x20@1x.png",
- "size": "20x20",
- "scale": "1x",
- "idiom": "ipad"
- },
- {
- "filename": "Icon-App-20x20@2x.png",
- "size": "20x20",
- "scale": "2x",
- "idiom": "ipad"
- },
- {
- "filename": "Icon-App-29x29@1x.png",
- "size": "29x29",
- "scale": "1x",
- "idiom": "ipad"
- },
- {
- "filename": "Icon-App-29x29@2x.png",
- "size": "29x29",
- "scale": "2x",
- "idiom": "ipad"
- },
- {
- "filename": "Icon-App-40x40@1x.png",
- "size": "40x40",
- "scale": "1x",
- "idiom": "ipad"
- },
- {
- "filename": "Icon-App-40x40@2x.png",
- "size": "40x40",
- "scale": "2x",
- "idiom": "ipad"
- },
- {
- "filename": "Icon-App-83.5x83.5@2x.png",
- "size": "83.5x83.5",
- "scale": "2x",
- "idiom": "ipad"
- },
- {
- "filename": "Icon-App-76x76@1x.png",
- "size": "76x76",
- "scale": "1x",
- "idiom": "ipad"
- },
- {
- "filename": "Icon-App-76x76@2x.png",
- "size": "76x76",
- "scale": "2x",
- "idiom": "ipad"
- },
- {
- "filename": "ItunesArtwork@2x.png",
- "size": "1024x1024",
- "scale": "1x",
- "idiom": "ios-marketing"
- },
- {
- "size": "60x60",
- "scale": "2x",
- "idiom": "car"
- },
- {
- "size": "60x60",
- "scale": "3x",
- "idiom": "car"
- },
- {
- "role": "notificationCenter",
- "size": "24x24",
- "subtype": "38mm",
- "scale": "2x",
- "idiom": "watch"
- },
- {
- "role": "notificationCenter",
- "size": "27.5x27.5",
- "subtype": "42mm",
- "scale": "2x",
- "idiom": "watch"
- },
- {
- "role": "companionSettings",
- "size": "29x29",
- "scale": "2x",
- "idiom": "watch"
- },
- {
- "role": "companionSettings",
- "size": "29x29",
- "scale": "3x",
- "idiom": "watch"
- },
- {
- "role": "appLauncher",
- "size": "40x40",
- "subtype": "38mm",
- "scale": "2x",
- "idiom": "watch"
- },
- {
- "role": "appLauncher",
- "size": "44x44",
- "subtype": "40mm",
- "scale": "2x",
- "idiom": "watch"
- },
- {
- "role": "appLauncher",
- "size": "50x50",
- "subtype": "44mm",
- "scale": "2x",
- "idiom": "watch"
- },
- {
- "role": "quickLook",
- "size": "86x86",
- "subtype": "38mm",
- "scale": "2x",
- "idiom": "watch"
- },
- {
- "role": "quickLook",
- "size": "98x98",
- "subtype": "42mm",
- "scale": "2x",
- "idiom": "watch"
- },
- {
- "role": "quickLook",
- "size": "108x108",
- "subtype": "44mm",
- "scale": "2x",
- "idiom": "watch"
- },
- {
- "size": "1024x1024",
- "scale": "1x",
- "idiom": "watch-marketing"
- },
- {
- "size": "16x16",
- "scale": "1x",
- "idiom": "mac"
- },
- {
- "size": "16x16",
- "scale": "2x",
- "idiom": "mac"
- },
- {
- "size": "32x32",
- "scale": "1x",
- "idiom": "mac"
- },
- {
- "size": "32x32",
- "scale": "2x",
- "idiom": "mac"
- },
- {
- "size": "128x128",
- "scale": "1x",
- "idiom": "mac"
- },
- {
- "size": "128x128",
- "scale": "2x",
- "idiom": "mac"
- },
- {
- "size": "256x256",
- "scale": "1x",
- "idiom": "mac"
- },
- {
- "size": "256x256",
- "scale": "2x",
- "idiom": "mac"
- },
- {
- "size": "512x512",
- "scale": "1x",
- "idiom": "mac"
- },
- {
- "size": "512x512",
- "scale": "2x",
- "idiom": "mac"
- }
- ],
- "info": {
- "version": 1,
- "author": "xcode"
- }
-}
\ No newline at end of file
+{"images":[{"size":"20x20","idiom":"iphone","filename":"iPhoneNotification2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"iPhoneNotification3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"iPhoneSettings2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"iPhoneSettings3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"iPhoneSpotlight2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"iPhoneSpotlight3x.png","scale":"3x"},{"size":"60x60","idiom":"iphone","filename":"iPhoneApp2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"iPhoneApp3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"iPadNotification1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"iPadNotification2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"iPadSettings1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"iPadSettings2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"iPadSpotlight1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"iPadSpotlight2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"iPadApp1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"iPadApp2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"iPadProApp2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"iOSAppStore.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}}
\ No newline at end of file
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
deleted file mode 100644
index dfcce1297b..0000000000
Binary files a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and /dev/null differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
deleted file mode 100644
index d563e8cf5e..0000000000
Binary files a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and /dev/null differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
deleted file mode 100644
index 8a21d9f81d..0000000000
Binary files a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and /dev/null differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
deleted file mode 100644
index 4477ece73a..0000000000
Binary files a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and /dev/null differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
deleted file mode 100644
index 1fe354a7fa..0000000000
Binary files a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and /dev/null differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
deleted file mode 100644
index 0f8c36a038..0000000000
Binary files a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and /dev/null differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
deleted file mode 100644
index d563e8cf5e..0000000000
Binary files a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and /dev/null differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
deleted file mode 100644
index 0208f80e3b..0000000000
Binary files a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and /dev/null differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
deleted file mode 100644
index f7ad8bb6bb..0000000000
Binary files a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and /dev/null differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
deleted file mode 100644
index f7ad8bb6bb..0000000000
Binary files a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and /dev/null differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
deleted file mode 100644
index 3d85a133aa..0000000000
Binary files a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and /dev/null differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
deleted file mode 100644
index edd53bc954..0000000000
Binary files a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and /dev/null differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
deleted file mode 100644
index b13a6e7a1e..0000000000
Binary files a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and /dev/null differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
deleted file mode 100644
index edff3788f0..0000000000
Binary files a/osu.iOS/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and /dev/null differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png
deleted file mode 100644
index c04f6f3ec4..0000000000
Binary files a/osu.iOS/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png and /dev/null differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iOSAppStore.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iOSAppStore.png
new file mode 100644
index 0000000000..0e8bb029bc
Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iOSAppStore.png differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadApp1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadApp1x.png
new file mode 100644
index 0000000000..42fead2364
Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadApp1x.png differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadApp2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadApp2x.png
new file mode 100644
index 0000000000..785db50cb2
Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadApp2x.png differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadNotification1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadNotification1x.png
new file mode 100644
index 0000000000..8c483a0a7a
Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadNotification1x.png differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadNotification2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadNotification2x.png
new file mode 100644
index 0000000000..a45b01b91c
Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadNotification2x.png differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadProApp2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadProApp2x.png
new file mode 100644
index 0000000000..d2ba8f3a7e
Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadProApp2x.png differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSettings1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSettings1x.png
new file mode 100644
index 0000000000..43d577040e
Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSettings1x.png differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSettings2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSettings2x.png
new file mode 100644
index 0000000000..1ebec1390b
Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSettings2x.png differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSpotlight1x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSpotlight1x.png
new file mode 100644
index 0000000000..a45b01b91c
Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSpotlight1x.png differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSpotlight2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSpotlight2x.png
new file mode 100644
index 0000000000..717603dd68
Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPadSpotlight2x.png differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneApp2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneApp2x.png
new file mode 100644
index 0000000000..6b61c09db5
Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneApp2x.png differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneApp3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneApp3x.png
new file mode 100644
index 0000000000..78ef8d12b7
Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneApp3x.png differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneNotification2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneNotification2x.png
new file mode 100644
index 0000000000..a45b01b91c
Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneNotification2x.png differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneNotification3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneNotification3x.png
new file mode 100644
index 0000000000..46ddf1179d
Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneNotification3x.png differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSettings2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSettings2x.png
new file mode 100644
index 0000000000..1ebec1390b
Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSettings2x.png differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSettings3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSettings3x.png
new file mode 100644
index 0000000000..a8145f0246
Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSettings3x.png differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSpotlight2x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSpotlight2x.png
new file mode 100644
index 0000000000..717603dd68
Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSpotlight2x.png differ
diff --git a/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSpotlight3x.png b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSpotlight3x.png
new file mode 100644
index 0000000000..6b61c09db5
Binary files /dev/null and b/osu.iOS/Assets.xcassets/AppIcon.appiconset/iPhoneSpotlight3x.png differ
diff --git a/osu.iOS/iTunesArtwork b/osu.iOS/iTunesArtwork
index ef7441433a..1939459992 100644
Binary files a/osu.iOS/iTunesArtwork and b/osu.iOS/iTunesArtwork differ
diff --git a/osu.iOS/iTunesArtwork@2x b/osu.iOS/iTunesArtwork@2x
index c04f6f3ec4..0e8bb029bc 100644
Binary files a/osu.iOS/iTunesArtwork@2x and b/osu.iOS/iTunesArtwork@2x differ
diff --git a/osu.iOS/osu.iOS.csproj b/osu.iOS/osu.iOS.csproj
index 9df3ad5516..12505e73e4 100644
--- a/osu.iOS/osu.iOS.csproj
+++ b/osu.iOS/osu.iOS.csproj
@@ -10,25 +10,6 @@
osu.iOS
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -79,6 +60,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file