1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-22 02:15:37 +08:00

Merge branch 'master' into user-list-toolbar

This commit is contained in:
Dan Balasescu 2020-02-26 10:11:21 +09:00 committed by GitHub
commit 37e9c2a683
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 273 additions and 180 deletions

View File

@ -54,6 +54,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.221.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2020.221.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.221.0" /> <PackageReference Include="ppy.osu.Framework.Android" Version="2020.225.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -29,6 +29,12 @@ namespace osu.Game.Rulesets.Catch.Tests
{ {
} }
[Test]
public void TestBananaShower()
{
AddUntilStep("player is done", () => !Player.ValidForResume);
}
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
{ {
var beatmap = new Beatmap var beatmap = new Beatmap
@ -40,7 +46,7 @@ namespace osu.Game.Rulesets.Catch.Tests
} }
}; };
beatmap.HitObjects.Add(new BananaShower { StartTime = 200, Duration = 5000, NewCombo = true }); beatmap.HitObjects.Add(new BananaShower { StartTime = 200, Duration = 3000, NewCombo = true });
return beatmap; return beatmap;
} }

View File

@ -0,0 +1,56 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using NUnit.Framework;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Tests.Visual;
using osuTK;
namespace osu.Game.Rulesets.Catch.Tests
{
public class TestSceneJuiceStream : PlayerTestScene
{
public TestSceneJuiceStream()
: base(new CatchRuleset())
{
}
[Test]
public void TestJuiceStreamEndingCombo()
{
AddUntilStep("player is done", () => !Player.ValidForResume);
}
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new Beatmap
{
BeatmapInfo = new BeatmapInfo
{
BaseDifficulty = new BeatmapDifficulty { CircleSize = 5, SliderMultiplier = 2 },
Ruleset = ruleset
},
HitObjects = new List<HitObject>
{
new JuiceStream
{
X = 0.5f,
Path = new SliderPath(PathType.Linear, new[]
{
Vector2.Zero,
new Vector2(0, 100)
}),
StartTime = 200
},
new Banana
{
X = 0.5f,
StartTime = 1000,
NewCombo = true
}
}
};
}
}

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Rulesets.Catch.Objects namespace osu.Game.Rulesets.Catch.Objects
@ -11,6 +12,8 @@ namespace osu.Game.Rulesets.Catch.Objects
public override bool LastInCombo => true; public override bool LastInCombo => true;
public override Judgement CreateJudgement() => new IgnoreJudgement();
protected override void CreateNestedHitObjects() protected override void CreateNestedHitObjects()
{ {
base.CreateNestedHitObjects(); base.CreateNestedHitObjects();

View File

@ -7,6 +7,7 @@ using osu.Game.Audio;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Catch.UI;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
@ -19,6 +20,8 @@ namespace osu.Game.Rulesets.Catch.Objects
/// </summary> /// </summary>
private const float base_scoring_distance = 100; private const float base_scoring_distance = 100;
public override Judgement CreateJudgement() => new IgnoreJudgement();
public int RepeatCount { get; set; } public int RepeatCount { get; set; }
public double Velocity; public double Velocity;

View File

@ -89,7 +89,7 @@ namespace osu.Game.Rulesets.Catch.UI
if (fruit.HitObject.LastInCombo) if (fruit.HitObject.LastInCombo)
{ {
if (((CatchJudgement)result.Judgement).ShouldExplodeFor(result)) if (result.Judgement is CatchJudgement catchJudgement && catchJudgement.ShouldExplodeFor(result))
runAfterLoaded(() => MovableCatcher.Explode()); runAfterLoaded(() => MovableCatcher.Explode());
else else
MovableCatcher.Drop(); MovableCatcher.Drop();

View File

@ -1,14 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mania.Judgements
{
public class HoldNoteJudgement : ManiaJudgement
{
public override bool AffectsCombo => false;
protected override int NumericResultFor(HitResult result) => 0;
}
}

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
namespace osu.Game.Rulesets.Mania.Objects namespace osu.Game.Rulesets.Mania.Objects
@ -8,5 +9,7 @@ namespace osu.Game.Rulesets.Mania.Objects
public class BarLine : ManiaHitObject, IBarLine public class BarLine : ManiaHitObject, IBarLine
{ {
public bool Major { get; set; } public bool Major { get; set; }
public override Judgement CreateJudgement() => new IgnoreJudgement();
} }
} }

View File

@ -71,8 +71,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
{ {
} }
protected override void UpdateStateTransforms(ArmedState state) protected override void UpdateStateTransforms(ArmedState state) => this.FadeOut(150);
{
}
} }
} }

View File

@ -4,7 +4,6 @@
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mania.Judgements;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
@ -103,7 +102,7 @@ namespace osu.Game.Rulesets.Mania.Objects
} }
} }
public override Judgement CreateJudgement() => new HoldNoteJudgement(); public override Judgement CreateJudgement() => new IgnoreJudgement();
protected override HitWindows CreateHitWindows() => HitWindows.Empty; protected override HitWindows CreateHitWindows() => HitWindows.Empty;
} }

View File

@ -1,14 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Judgements
{
public class OsuSliderTailJudgement : OsuJudgement
{
public override bool AffectsCombo => false;
protected override int NumericResultFor(HitResult result) => 0;
}
}

View File

@ -20,6 +20,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
private const int spacing = 32; private const int spacing = 32;
private const double preempt = 800; private const double preempt = 800;
public override bool RemoveWhenNotAlive => false;
/// <summary> /// <summary>
/// The start time of <see cref="Start"/>. /// The start time of <see cref="Start"/>.
/// </summary> /// </summary>
@ -79,27 +81,31 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
drawableObject.HitObject.DefaultsApplied += scheduleRefresh; drawableObject.HitObject.DefaultsApplied += scheduleRefresh;
} }
private void scheduleRefresh() => Scheduler.AddOnce(refresh); private void scheduleRefresh()
{
Scheduler.AddOnce(refresh);
}
private void refresh() private void refresh()
{ {
ClearInternal(); ClearInternal();
if (End == null)
return;
OsuHitObject osuStart = Start.HitObject; OsuHitObject osuStart = Start.HitObject;
OsuHitObject osuEnd = End.HitObject; double startTime = osuStart.GetEndTime();
if (osuEnd.NewCombo) LifetimeStart = startTime;
return;
if (osuStart is Spinner || osuEnd is Spinner) OsuHitObject osuEnd = End?.HitObject;
if (osuEnd == null || osuEnd.NewCombo || osuStart is Spinner || osuEnd is Spinner)
{
// ensure we always set a lifetime for full LifetimeManagementContainer benefits
LifetimeEnd = LifetimeStart;
return; return;
}
Vector2 startPosition = osuStart.EndPosition; Vector2 startPosition = osuStart.EndPosition;
Vector2 endPosition = osuEnd.Position; Vector2 endPosition = osuEnd.Position;
double startTime = osuStart.GetEndTime();
double endTime = osuEnd.StartTime; double endTime = osuEnd.StartTime;
Vector2 distanceVector = endPosition - startPosition; Vector2 distanceVector = endPosition - startPosition;
@ -107,6 +113,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
float rotation = (float)(Math.Atan2(distanceVector.Y, distanceVector.X) * (180 / Math.PI)); float rotation = (float)(Math.Atan2(distanceVector.Y, distanceVector.X) * (180 / Math.PI));
double duration = endTime - startTime; double duration = endTime - startTime;
double? firstTransformStartTime = null;
double finalTransformEndTime = startTime;
for (int d = (int)(spacing * 1.5); d < distance - spacing; d += spacing) for (int d = (int)(spacing * 1.5); d < distance - spacing; d += spacing)
{ {
float fraction = (float)d / distance; float fraction = (float)d / distance;
@ -125,16 +134,23 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
Scale = new Vector2(1.5f * osuEnd.Scale), Scale = new Vector2(1.5f * osuEnd.Scale),
}); });
if (firstTransformStartTime == null)
firstTransformStartTime = fadeInTime;
using (fp.BeginAbsoluteSequence(fadeInTime)) using (fp.BeginAbsoluteSequence(fadeInTime))
{ {
fp.FadeIn(osuEnd.TimeFadeIn); fp.FadeIn(osuEnd.TimeFadeIn);
fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out); fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out);
fp.MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out); fp.MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out);
fp.Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn); fp.Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn);
}
fp.Expire(true); finalTransformEndTime = fadeOutTime + osuEnd.TimeFadeIn;
}
} }
// todo: use Expire() on FollowPoints and take lifetime from them when https://github.com/ppy/osu-framework/issues/3300 is fixed.
LifetimeStart = firstTransformStartTime ?? startTime;
LifetimeEnd = finalTransformEndTime;
} }
} }
} }

View File

@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
/// <summary> /// <summary>
/// Visualises connections between <see cref="DrawableOsuHitObject"/>s. /// Visualises connections between <see cref="DrawableOsuHitObject"/>s.
/// </summary> /// </summary>
public class FollowPointRenderer : CompositeDrawable public class FollowPointRenderer : LifetimeManagementContainer
{ {
/// <summary> /// <summary>
/// All the <see cref="FollowPointConnection"/>s contained by this <see cref="FollowPointRenderer"/>. /// All the <see cref="FollowPointConnection"/>s contained by this <see cref="FollowPointRenderer"/>.
@ -45,8 +45,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
/// <returns>The index of <paramref name="connection"/> in <see cref="connections"/>.</returns> /// <returns>The index of <paramref name="connection"/> in <see cref="connections"/>.</returns>
private void addConnection(FollowPointConnection connection) private void addConnection(FollowPointConnection connection)
{ {
AddInternal(connection);
// Groups are sorted by their start time when added such that the index can be used to post-process other surrounding connections // Groups are sorted by their start time when added such that the index can be used to post-process other surrounding connections
int index = connections.AddInPlace(connection, Comparer<FollowPointConnection>.Create((g1, g2) => g1.StartTime.Value.CompareTo(g2.StartTime.Value))); int index = connections.AddInPlace(connection, Comparer<FollowPointConnection>.Create((g1, g2) => g1.StartTime.Value.CompareTo(g2.StartTime.Value)));
@ -74,6 +72,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
FollowPointConnection previousConnection = connections[index - 1]; FollowPointConnection previousConnection = connections[index - 1];
previousConnection.End = connection.Start; previousConnection.End = connection.Start;
} }
AddInternal(connection);
} }
/// <summary> /// <summary>

View File

@ -4,7 +4,6 @@
using osu.Framework.Bindables; using osu.Framework.Bindables;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects namespace osu.Game.Rulesets.Osu.Objects
@ -23,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Objects
pathVersion.BindValueChanged(_ => Position = slider.EndPosition); pathVersion.BindValueChanged(_ => Position = slider.EndPosition);
} }
public override Judgement CreateJudgement() => new OsuSliderTailJudgement(); public override Judgement CreateJudgement() => new IgnoreJudgement();
protected override HitWindows CreateHitWindows() => HitWindows.Empty; protected override HitWindows CreateHitWindows() => HitWindows.Empty;
} }

View File

@ -8,7 +8,6 @@ using osu.Framework.Allocation;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Judgements;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
using osu.Game.Tests.Visual; using osu.Game.Tests.Visual;
@ -28,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
public void TestZeroTickTimeOffsets() public void TestZeroTickTimeOffsets()
{ {
AddUntilStep("gameplay finished", () => Player.ScoreProcessor.HasCompleted); AddUntilStep("gameplay finished", () => Player.ScoreProcessor.HasCompleted);
AddAssert("all tick offsets are 0", () => Player.Results.Where(r => r.Judgement is TaikoSwellTickJudgement).All(r => r.TimeOffset == 0)); AddAssert("all tick offsets are 0", () => Player.Results.Where(r => r.HitObject is SwellTick).All(r => r.TimeOffset == 0));
} }
protected override bool Autoplay => true; protected override bool Autoplay => true;

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
namespace osu.Game.Rulesets.Taiko.Objects namespace osu.Game.Rulesets.Taiko.Objects
@ -8,5 +9,7 @@ namespace osu.Game.Rulesets.Taiko.Objects
public class BarLine : TaikoHitObject, IBarLine public class BarLine : TaikoHitObject, IBarLine
{ {
public bool Major { get; set; } public bool Major { get; set; }
public override Judgement CreateJudgement() => new IgnoreJudgement();
} }
} }

View File

@ -54,5 +54,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
Alpha = 0.75f Alpha = 0.75f
}); });
} }
protected override void UpdateStateTransforms(ArmedState state) => this.FadeOut(150);
} }
} }

View File

@ -3,13 +3,12 @@
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Judgements;
namespace osu.Game.Rulesets.Taiko.Objects namespace osu.Game.Rulesets.Taiko.Objects
{ {
public class SwellTick : TaikoHitObject public class SwellTick : TaikoHitObject
{ {
public override Judgement CreateJudgement() => new TaikoSwellTickJudgement(); public override Judgement CreateJudgement() => new IgnoreJudgement();
protected override HitWindows CreateHitWindows() => HitWindows.Empty; protected override HitWindows CreateHitWindows() => HitWindows.Empty;
} }

View File

@ -154,6 +154,7 @@ namespace osu.Game.Tests.Gameplay
private class JudgeableHitObject : HitObject private class JudgeableHitObject : HitObject
{ {
public override Judgement CreateJudgement() => new Judgement(); public override Judgement CreateJudgement() => new Judgement();
protected override HitWindows CreateHitWindows() => new HitWindows();
} }
} }
} }

View File

@ -11,8 +11,8 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Textures; using osu.Framework.Graphics.Textures;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Audio; using osu.Game.Audio;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Legacy;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Skinning; using osu.Game.Skinning;
using osu.Game.Tests.Visual; using osu.Game.Tests.Visual;
@ -78,7 +78,7 @@ namespace osu.Game.Tests.Gameplay
} }
} }
private class TestHitObjectWithCombo : HitObject, IHasComboInformation private class TestHitObjectWithCombo : ConvertHitObject, IHasComboInformation
{ {
public bool NewCombo { get; } = false; public bool NewCombo { get; } = false;
public int ComboOffset { get; } = 0; public int ComboOffset { get; } = 0;

View File

@ -20,6 +20,7 @@ using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Legacy;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
@ -289,7 +290,7 @@ namespace osu.Game.Tests.Visual.Gameplay
#region HitObject #region HitObject
private class TestHitObject : HitObject, IHasEndTime private class TestHitObject : ConvertHitObject, IHasEndTime
{ {
public double EndTime { get; set; } public double EndTime { get; set; }

View File

@ -2,16 +2,17 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using NUnit.Framework; using NUnit.Framework;
using osu.Game.Rulesets.Objects;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Framework.Utils; using osu.Framework.Utils;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Threading;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Catch.Scoring;
using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mania.Scoring;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Osu.Scoring;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Scoring; using osu.Game.Rulesets.Taiko.Scoring;
@ -43,6 +44,22 @@ namespace osu.Game.Tests.Visual.Gameplay
AddRepeatStep("New max negative", () => newJudgement(-hitWindows.WindowFor(HitResult.Meh)), 20); AddRepeatStep("New max negative", () => newJudgement(-hitWindows.WindowFor(HitResult.Meh)), 20);
AddRepeatStep("New max positive", () => newJudgement(hitWindows.WindowFor(HitResult.Meh)), 20); AddRepeatStep("New max positive", () => newJudgement(hitWindows.WindowFor(HitResult.Meh)), 20);
AddStep("New fixed judgement (50ms)", () => newJudgement(50)); AddStep("New fixed judgement (50ms)", () => newJudgement(50));
AddStep("Judgement barrage", () =>
{
int runCount = 0;
ScheduledDelegate del = null;
del = Scheduler.AddDelayed(() =>
{
newJudgement(runCount++ / 10f);
if (runCount == 500)
// ReSharper disable once AccessToModifiedClosure
del?.Cancel();
}, 10, true);
});
} }
[Test] [Test]

View File

@ -13,6 +13,8 @@ using osu.Framework.Bindables;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osuTK; using osuTK;
using JetBrains.Annotations;
using NUnit.Framework;
namespace osu.Game.Tests.Visual.Online namespace osu.Game.Tests.Visual.Online
{ {
@ -30,6 +32,8 @@ namespace osu.Game.Tests.Visual.Online
private readonly BindableBool showDeleted = new BindableBool(); private readonly BindableBool showDeleted = new BindableBool();
private readonly Container content; private readonly Container content;
private TestCommentsPage commentsPage;
public TestSceneCommentsPage() public TestSceneCommentsPage()
{ {
Add(new FillFlowContainer Add(new FillFlowContainer
@ -57,15 +61,29 @@ namespace osu.Game.Tests.Visual.Online
} }
} }
}); });
}
AddStep("load comments", () => createPage(getCommentBundle())); [Test]
AddStep("load empty comments", () => createPage(getEmptyCommentBundle())); public void TestAppendDuplicatedComment()
{
AddStep("Create page", () => createPage(getCommentBundle()));
AddAssert("Dictionary length is 10", () => commentsPage?.DictionaryLength == 10);
AddStep("Append existing comment", () => commentsPage?.AppendComments(getCommentSubBundle()));
AddAssert("Dictionary length is 10", () => commentsPage?.DictionaryLength == 10);
}
[Test]
public void TestEmptyBundle()
{
AddStep("Create page", () => createPage(getEmptyCommentBundle()));
AddAssert("Dictionary length is 0", () => commentsPage?.DictionaryLength == 0);
} }
private void createPage(CommentBundle commentBundle) private void createPage(CommentBundle commentBundle)
{ {
commentsPage = null;
content.Clear(); content.Clear();
content.Add(new CommentsPage(commentBundle) content.Add(commentsPage = new TestCommentsPage(commentBundle)
{ {
ShowDeleted = { BindTarget = showDeleted } ShowDeleted = { BindTarget = showDeleted }
}); });
@ -182,5 +200,33 @@ namespace osu.Game.Tests.Visual.Online
} }
}, },
}; };
private CommentBundle getCommentSubBundle() => new CommentBundle
{
Comments = new List<Comment>
{
new Comment
{
Id = 1,
Message = "Simple test comment",
LegacyName = "TestUser1",
CreatedAt = DateTimeOffset.Now,
VotesCount = 5
},
},
IncludedComments = new List<Comment>(),
};
private class TestCommentsPage : CommentsPage
{
public TestCommentsPage(CommentBundle commentBundle)
: base(commentBundle)
{
}
public new void AppendComments([NotNull] CommentBundle bundle) => base.AppendComments(bundle);
public int DictionaryLength => CommentDictionary.Count;
}
} }
} }

View File

@ -13,6 +13,7 @@ using osu.Game.Rulesets;
using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Catch;
using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mania;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Legacy;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Taiko; using osu.Game.Rulesets.Taiko;
@ -194,7 +195,7 @@ namespace osu.Game.Tests.Visual.SongSelect
public new BufferedWedgeInfo Info => base.Info; public new BufferedWedgeInfo Info => base.Info;
} }
private class TestHitObject : HitObject, IHasPosition private class TestHitObject : ConvertHitObject, IHasPosition
{ {
public float X { get; } = 0; public float X { get; } = 0;
public float Y { get; } = 0; public float Y { get; } = 0;

View File

@ -64,7 +64,7 @@ namespace osu.Game.Graphics.UserInterface
protected override void Update() protected override void Update()
{ {
base.Update(); base.Update();
MainContents.Size = new Vector2(Math.Min(100, Math.Min(DrawWidth, DrawHeight) * 0.25f)); MainContents.Size = new Vector2(Math.Clamp(Math.Min(DrawWidth, DrawHeight) * 0.25f, 30, 100));
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)

View File

@ -93,7 +93,7 @@ namespace osu.Game.Graphics.UserInterface
private void rotate() private void rotate()
{ {
spinner.Spin(spin_duration * 4, RotationDirection.Clockwise); spinner.Spin(spin_duration * 3.5f, RotationDirection.Clockwise);
MainContents.RotateTo(0).Then() MainContents.RotateTo(0).Then()
.RotateTo(90, spin_duration, Easing.InOutQuart).Then() .RotateTo(90, spin_duration, Easing.InOutQuart).Then()

View File

@ -61,15 +61,15 @@ namespace osu.Game.Overlays.Comments
return; return;
} }
appendComments(commentBundle); AppendComments(commentBundle);
} }
private DrawableComment getDrawableComment(Comment comment) private DrawableComment getDrawableComment(Comment comment)
{ {
if (commentDictionary.TryGetValue(comment.Id, out var existing)) if (CommentDictionary.TryGetValue(comment.Id, out var existing))
return existing; return existing;
return commentDictionary[comment.Id] = new DrawableComment(comment) return CommentDictionary[comment.Id] = new DrawableComment(comment)
{ {
ShowDeleted = { BindTarget = ShowDeleted }, ShowDeleted = { BindTarget = ShowDeleted },
Sort = { BindTarget = Sort }, Sort = { BindTarget = Sort },
@ -81,31 +81,28 @@ namespace osu.Game.Overlays.Comments
{ {
var request = new GetCommentsRequest(CommentableId.Value, Type.Value, Sort.Value, page, drawableComment.Comment.Id); var request = new GetCommentsRequest(CommentableId.Value, Type.Value, Sort.Value, page, drawableComment.Comment.Id);
request.Success += response => Schedule(() => appendComments(response)); request.Success += response => Schedule(() => AppendComments(response));
api.PerformAsync(request); api.PerformAsync(request);
} }
private readonly Dictionary<long, DrawableComment> commentDictionary = new Dictionary<long, DrawableComment>(); protected readonly Dictionary<long, DrawableComment> CommentDictionary = new Dictionary<long, DrawableComment>();
/// <summary> /// <summary>
/// Appends retrieved comments to the subtree rooted of comments in this page. /// Appends retrieved comments to the subtree rooted of comments in this page.
/// </summary> /// </summary>
/// <param name="bundle">The bundle of comments to add.</param> /// <param name="bundle">The bundle of comments to add.</param>
private void appendComments([NotNull] CommentBundle bundle) protected void AppendComments([NotNull] CommentBundle bundle)
{ {
var orphaned = new List<Comment>(); var orphaned = new List<Comment>();
foreach (var topLevel in bundle.Comments) foreach (var comment in bundle.Comments.Concat(bundle.IncludedComments))
addNewComment(topLevel);
foreach (var child in bundle.IncludedComments)
{ {
// Included comments can contain the parent comment, which already exists in the hierarchy. // Exclude possible duplicated comments.
if (commentDictionary.ContainsKey(child.Id)) if (CommentDictionary.ContainsKey(comment.Id))
continue; continue;
addNewComment(child); addNewComment(comment);
} }
// Comments whose parents were seen later than themselves can now be added. // Comments whose parents were seen later than themselves can now be added.
@ -121,7 +118,7 @@ namespace osu.Game.Overlays.Comments
// Comments that have no parent are added as top-level comments to the flow. // Comments that have no parent are added as top-level comments to the flow.
flow.Add(drawableComment); flow.Add(drawableComment);
} }
else if (commentDictionary.TryGetValue(comment.ParentId.Value, out var parentDrawable)) else if (CommentDictionary.TryGetValue(comment.ParentId.Value, out var parentDrawable))
{ {
// The comment's parent has already been seen, so the parent<-> child links can be added. // The comment's parent has already been seen, so the parent<-> child links can be added.
comment.ParentComment = parentDrawable.Comment; comment.ParentComment = parentDrawable.Comment;

View File

@ -138,6 +138,12 @@ namespace osu.Game.Overlays
Country.Value = requested; Country.Value = requested;
} }
public void ShowSpotlights()
{
Scope.Value = RankingsScope.Spotlights;
Show();
}
private void loadNewContent() private void loadNewContent()
{ {
loading.Show(); loading.Show();

View File

@ -1,11 +1,11 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Taiko.Judgements namespace osu.Game.Rulesets.Judgements
{ {
public class TaikoSwellTickJudgement : TaikoJudgement public class IgnoreJudgement : Judgement
{ {
public override bool AffectsCombo => false; public override bool AffectsCombo => false;

View File

@ -99,12 +99,9 @@ namespace osu.Game.Rulesets.Objects.Drawables
{ {
var judgement = HitObject.CreateJudgement(); var judgement = HitObject.CreateJudgement();
if (judgement != null) Result = CreateResult(judgement);
{ if (Result == null)
Result = CreateResult(judgement); throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}.");
if (Result == null)
throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}.");
}
loadSamples(); loadSamples();
} }
@ -265,7 +262,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
} }
} }
if (state.Value != ArmedState.Idle && LifetimeEnd == double.MaxValue) if (state.Value != ArmedState.Idle && LifetimeEnd == double.MaxValue || HitObject.HitWindows == null)
Expire(); Expire();
} }
else else

View File

@ -144,9 +144,9 @@ namespace osu.Game.Rulesets.Objects
/// <summary> /// <summary>
/// Creates the <see cref="Judgement"/> that represents the scoring information for this <see cref="HitObject"/>. /// Creates the <see cref="Judgement"/> that represents the scoring information for this <see cref="HitObject"/>.
/// May be null.
/// </summary> /// </summary>
public virtual Judgement CreateJudgement() => null; [NotNull]
public virtual Judgement CreateJudgement() => new Judgement();
/// <summary> /// <summary>
/// Creates the <see cref="HitWindows"/> for this <see cref="HitObject"/>. /// Creates the <see cref="HitWindows"/> for this <see cref="HitObject"/>.

View File

@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch
/// <summary> /// <summary>
/// Legacy osu!catch Hit-type, used for parsing Beatmaps. /// Legacy osu!catch Hit-type, used for parsing Beatmaps.
/// </summary> /// </summary>
internal sealed class ConvertHit : HitObject, IHasCombo, IHasXPosition internal sealed class ConvertHit : ConvertHitObject, IHasCombo, IHasXPosition
{ {
public float X { get; set; } public float X { get; set; }

View File

@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch
/// <summary> /// <summary>
/// Legacy osu!catch Spinner-type, used for parsing Beatmaps. /// Legacy osu!catch Spinner-type, used for parsing Beatmaps.
/// </summary> /// </summary>
internal sealed class ConvertSpinner : HitObject, IHasEndTime, IHasXPosition, IHasCombo internal sealed class ConvertSpinner : ConvertHitObject, IHasEndTime, IHasXPosition, IHasCombo
{ {
public double EndTime { get; set; } public double EndTime { get; set; }

View File

@ -0,0 +1,18 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Objects.Legacy
{
/// <summary>
/// A hit object only used for conversion, not actual gameplay.
/// </summary>
internal abstract class ConvertHitObject : HitObject
{
public override Judgement CreateJudgement() => new IgnoreJudgement();
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
}
}

View File

@ -9,7 +9,7 @@ using osu.Game.Beatmaps.ControlPoints;
namespace osu.Game.Rulesets.Objects.Legacy namespace osu.Game.Rulesets.Objects.Legacy
{ {
internal abstract class ConvertSlider : HitObject, IHasCurve, IHasLegacyLastTickOffset internal abstract class ConvertSlider : ConvertHitObject, IHasCurve, IHasLegacyLastTickOffset
{ {
/// <summary> /// <summary>
/// Scoring distance with a speed-adjusted beat length of 1 second. /// Scoring distance with a speed-adjusted beat length of 1 second.

View File

@ -2,17 +2,14 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Objects.Legacy.Mania namespace osu.Game.Rulesets.Objects.Legacy.Mania
{ {
/// <summary> /// <summary>
/// Legacy osu!mania Hit-type, used for parsing Beatmaps. /// Legacy osu!mania Hit-type, used for parsing Beatmaps.
/// </summary> /// </summary>
internal sealed class ConvertHit : HitObject, IHasXPosition internal sealed class ConvertHit : ConvertHitObject, IHasXPosition
{ {
public float X { get; set; } public float X { get; set; }
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
} }
} }

View File

@ -2,18 +2,15 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Objects.Legacy.Mania namespace osu.Game.Rulesets.Objects.Legacy.Mania
{ {
internal sealed class ConvertHold : HitObject, IHasXPosition, IHasEndTime internal sealed class ConvertHold : ConvertHitObject, IHasXPosition, IHasEndTime
{ {
public float X { get; set; } public float X { get; set; }
public double EndTime { get; set; } public double EndTime { get; set; }
public double Duration => EndTime - StartTime; public double Duration => EndTime - StartTime;
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
} }
} }

View File

@ -2,7 +2,6 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Objects.Legacy.Mania namespace osu.Game.Rulesets.Objects.Legacy.Mania
{ {
@ -12,7 +11,5 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania
internal sealed class ConvertSlider : Legacy.ConvertSlider, IHasXPosition internal sealed class ConvertSlider : Legacy.ConvertSlider, IHasXPosition
{ {
public float X { get; set; } public float X { get; set; }
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
} }
} }

View File

@ -2,21 +2,18 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Objects.Legacy.Mania namespace osu.Game.Rulesets.Objects.Legacy.Mania
{ {
/// <summary> /// <summary>
/// Legacy osu!mania Spinner-type, used for parsing Beatmaps. /// Legacy osu!mania Spinner-type, used for parsing Beatmaps.
/// </summary> /// </summary>
internal sealed class ConvertSpinner : HitObject, IHasEndTime, IHasXPosition internal sealed class ConvertSpinner : ConvertHitObject, IHasEndTime, IHasXPosition
{ {
public double EndTime { get; set; } public double EndTime { get; set; }
public double Duration => EndTime - StartTime; public double Duration => EndTime - StartTime;
public float X { get; set; } public float X { get; set; }
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
} }
} }

View File

@ -2,7 +2,6 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
using osuTK; using osuTK;
namespace osu.Game.Rulesets.Objects.Legacy.Osu namespace osu.Game.Rulesets.Objects.Legacy.Osu
@ -10,7 +9,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
/// <summary> /// <summary>
/// Legacy osu! Hit-type, used for parsing Beatmaps. /// Legacy osu! Hit-type, used for parsing Beatmaps.
/// </summary> /// </summary>
internal sealed class ConvertHit : HitObject, IHasPosition, IHasCombo internal sealed class ConvertHit : ConvertHitObject, IHasPosition, IHasCombo
{ {
public Vector2 Position { get; set; } public Vector2 Position { get; set; }
@ -21,7 +20,5 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
public bool NewCombo { get; set; } public bool NewCombo { get; set; }
public int ComboOffset { get; set; } public int ComboOffset { get; set; }
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
} }
} }

View File

@ -2,7 +2,6 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
using osuTK; using osuTK;
namespace osu.Game.Rulesets.Objects.Legacy.Osu namespace osu.Game.Rulesets.Objects.Legacy.Osu
@ -21,7 +20,5 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
public bool NewCombo { get; set; } public bool NewCombo { get; set; }
public int ComboOffset { get; set; } public int ComboOffset { get; set; }
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
} }
} }

View File

@ -2,7 +2,6 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
using osuTK; using osuTK;
namespace osu.Game.Rulesets.Objects.Legacy.Osu namespace osu.Game.Rulesets.Objects.Legacy.Osu
@ -10,7 +9,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
/// <summary> /// <summary>
/// Legacy osu! Spinner-type, used for parsing Beatmaps. /// Legacy osu! Spinner-type, used for parsing Beatmaps.
/// </summary> /// </summary>
internal sealed class ConvertSpinner : HitObject, IHasEndTime, IHasPosition, IHasCombo internal sealed class ConvertSpinner : ConvertHitObject, IHasEndTime, IHasPosition, IHasCombo
{ {
public double EndTime { get; set; } public double EndTime { get; set; }
@ -22,8 +21,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
public float Y => Position.Y; public float Y => Position.Y;
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
public bool NewCombo { get; set; } public bool NewCombo { get; set; }
public int ComboOffset { get; set; } public int ComboOffset { get; set; }

View File

@ -1,15 +1,12 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Objects.Legacy.Taiko namespace osu.Game.Rulesets.Objects.Legacy.Taiko
{ {
/// <summary> /// <summary>
/// Legacy osu!taiko Hit-type, used for parsing Beatmaps. /// Legacy osu!taiko Hit-type, used for parsing Beatmaps.
/// </summary> /// </summary>
internal sealed class ConvertHit : HitObject internal sealed class ConvertHit : ConvertHitObject
{ {
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
} }
} }

View File

@ -1,8 +1,6 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Objects.Legacy.Taiko namespace osu.Game.Rulesets.Objects.Legacy.Taiko
{ {
/// <summary> /// <summary>
@ -10,6 +8,5 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko
/// </summary> /// </summary>
internal sealed class ConvertSlider : Legacy.ConvertSlider internal sealed class ConvertSlider : Legacy.ConvertSlider
{ {
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
} }
} }

View File

@ -2,19 +2,16 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Objects.Legacy.Taiko namespace osu.Game.Rulesets.Objects.Legacy.Taiko
{ {
/// <summary> /// <summary>
/// Legacy osu!taiko Spinner-type, used for parsing Beatmaps. /// Legacy osu!taiko Spinner-type, used for parsing Beatmaps.
/// </summary> /// </summary>
internal sealed class ConvertSpinner : HitObject, IHasEndTime internal sealed class ConvertSpinner : ConvertHitObject, IHasEndTime
{ {
public double EndTime { get; set; } public double EndTime { get; set; }
public double Duration => EndTime - StartTime; public double Duration => EndTime - StartTime;
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
} }
} }

View File

@ -125,8 +125,6 @@ namespace osu.Game.Rulesets.Scoring
simulate(nested); simulate(nested);
var judgement = obj.CreateJudgement(); var judgement = obj.CreateJudgement();
if (judgement == null)
return;
var result = CreateResult(obj, judgement); var result = CreateResult(obj, judgement);
if (result == null) if (result == null)

View File

@ -1,9 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
namespace osu.Game.Screens.Charts
{
public class ChartInfo : ScreenWhiteBox
{
}
}

View File

@ -1,16 +0,0 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
namespace osu.Game.Screens.Charts
{
public class ChartListing : ScreenWhiteBox
{
protected override IEnumerable<Type> PossibleChildren => new[]
{
typeof(ChartInfo)
};
}
}

View File

@ -93,15 +93,15 @@ namespace osu.Game.Screens.Edit
EditorMenuBar menuBar; EditorMenuBar menuBar;
var fileMenuItems = new List<MenuItem>(); var fileMenuItems = new List<MenuItem>
{
new EditorMenuItem("Save", MenuItemType.Standard, saveBeatmap)
};
if (RuntimeInfo.IsDesktop) if (RuntimeInfo.IsDesktop)
{
fileMenuItems.Add(new EditorMenuItem("Save", MenuItemType.Standard, saveBeatmap));
fileMenuItems.Add(new EditorMenuItem("Export package", MenuItemType.Standard, exportBeatmap)); fileMenuItems.Add(new EditorMenuItem("Export package", MenuItemType.Standard, exportBeatmap));
fileMenuItems.Add(new EditorMenuItemSpacer());
}
fileMenuItems.Add(new EditorMenuItemSpacer());
fileMenuItems.Add(new EditorMenuItem("Exit", MenuItemType.Standard, this.Exit)); fileMenuItems.Add(new EditorMenuItem("Exit", MenuItemType.Standard, this.Exit));
AddInternal(new OsuContextMenuContainer AddInternal(new OsuContextMenuContainer

View File

@ -18,7 +18,6 @@ using osu.Game.Online.API;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Game.Overlays.Dialog; using osu.Game.Overlays.Dialog;
using osu.Game.Screens.Backgrounds; using osu.Game.Screens.Backgrounds;
using osu.Game.Screens.Charts;
using osu.Game.Screens.Edit; using osu.Game.Screens.Edit;
using osu.Game.Screens.Multi; using osu.Game.Screens.Multi;
using osu.Game.Screens.Select; using osu.Game.Screens.Select;
@ -73,7 +72,7 @@ namespace osu.Game.Screens.Menu
private SongTicker songTicker; private SongTicker songTicker;
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(DirectOverlay direct, SettingsOverlay settings, OsuConfigManager config, SessionStatics statics) private void load(DirectOverlay direct, SettingsOverlay settings, RankingsOverlay rankings, OsuConfigManager config, SessionStatics statics)
{ {
holdDelay = config.GetBindable<float>(OsuSetting.UIHoldActivationDelay); holdDelay = config.GetBindable<float>(OsuSetting.UIHoldActivationDelay);
loginDisplayed = statics.GetBindable<bool>(Static.LoginOverlayDisplayed); loginDisplayed = statics.GetBindable<bool>(Static.LoginOverlayDisplayed);
@ -101,7 +100,6 @@ namespace osu.Game.Screens.Menu
{ {
buttons = new ButtonSystem buttons = new ButtonSystem
{ {
OnChart = delegate { this.Push(new ChartListing()); },
OnEdit = delegate { this.Push(new Editor()); }, OnEdit = delegate { this.Push(new Editor()); },
OnSolo = onSolo, OnSolo = onSolo,
OnMulti = delegate { this.Push(new Multiplayer()); }, OnMulti = delegate { this.Push(new Multiplayer()); },
@ -136,6 +134,7 @@ namespace osu.Game.Screens.Menu
buttons.OnSettings = () => settings?.ToggleVisibility(); buttons.OnSettings = () => settings?.ToggleVisibility();
buttons.OnDirect = () => direct?.ToggleVisibility(); buttons.OnDirect = () => direct?.ToggleVisibility();
buttons.OnChart = () => rankings?.ShowSpotlights();
LoadComponentAsync(background = new BackgroundScreenDefault()); LoadComponentAsync(background = new BackgroundScreenDefault());
preloadSongSelect(); preloadSongSelect();

View File

@ -15,7 +15,6 @@ using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Screens.Play.HUD; using osu.Game.Screens.Play.HUD;
using osuTK; using osuTK;
using osuTK.Graphics;
namespace osu.Game.Screens.Play namespace osu.Game.Screens.Play
{ {
@ -63,15 +62,9 @@ namespace osu.Game.Screens.Play
set set
{ {
if (value) if (value)
{
loading.Show(); loading.Show();
backgroundSprite.FadeColour(OsuColour.Gray(0.5f), 400, Easing.OutQuint);
}
else else
{
loading.Hide(); loading.Hide();
backgroundSprite.FadeColour(Color4.White, 400, Easing.OutQuint);
}
} }
} }
@ -138,7 +131,7 @@ namespace osu.Game.Screens.Play
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
FillMode = FillMode.Fill, FillMode = FillMode.Fill,
}, },
loading = new LoadingSpinner { Scale = new Vector2(1.3f) } loading = new LoadingLayer(backgroundSprite)
} }
}, },
new OsuSpriteText new OsuSpriteText

View File

@ -207,11 +207,27 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
private double floatingAverage; private double floatingAverage;
private Container colourBars; private Container colourBars;
private const int max_concurrent_judgements = 50;
public override void OnNewJudgement(JudgementResult judgement) public override void OnNewJudgement(JudgementResult judgement)
{ {
if (!judgement.IsHit) if (!judgement.IsHit)
return; return;
if (judgementsContainer.Count > max_concurrent_judgements)
{
const double quick_fade_time = 100;
// check with a bit of lenience to avoid precision error in comparison.
var old = judgementsContainer.FirstOrDefault(j => j.LifetimeEnd > Clock.CurrentTime + quick_fade_time * 1.1);
if (old != null)
{
old.ClearTransforms();
old.FadeOut(quick_fade_time).Expire();
}
}
judgementsContainer.Add(new JudgementLine judgementsContainer.Add(new JudgementLine
{ {
Y = getRelativeJudgementPosition(judgement.TimeOffset), Y = getRelativeJudgementPosition(judgement.TimeOffset),
@ -228,7 +244,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
private class JudgementLine : CompositeDrawable private class JudgementLine : CompositeDrawable
{ {
private const int judgement_fade_duration = 10000; private const int judgement_fade_duration = 5000;
public JudgementLine() public JudgementLine()
{ {
@ -255,7 +271,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters
Width = 0; Width = 0;
this.ResizeWidthTo(1, 200, Easing.OutElasticHalf); this.ResizeWidthTo(1, 200, Easing.OutElasticHalf);
this.FadeTo(0.8f, 150).Then().FadeOut(judgement_fade_duration, Easing.OutQuint).Expire(); this.FadeTo(0.8f, 150).Then().FadeOut(judgement_fade_duration).Expire();
} }
} }
} }

View File

@ -23,7 +23,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.221.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2020.221.0" />
<PackageReference Include="ppy.osu.Framework" Version="2020.221.0" /> <PackageReference Include="ppy.osu.Framework" Version="2020.225.0" />
<PackageReference Include="Sentry" Version="2.0.3" /> <PackageReference Include="Sentry" Version="2.0.3" />
<PackageReference Include="SharpCompress" Version="0.24.0" /> <PackageReference Include="SharpCompress" Version="0.24.0" />
<PackageReference Include="NUnit" Version="3.12.0" /> <PackageReference Include="NUnit" Version="3.12.0" />

View File

@ -74,7 +74,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.221.0" /> <PackageReference Include="ppy.osu.Game.Resources" Version="2020.221.0" />
<PackageReference Include="ppy.osu.Framework.iOS" Version="2020.221.0" /> <PackageReference Include="ppy.osu.Framework.iOS" Version="2020.225.0" />
</ItemGroup> </ItemGroup>
<!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. --> <!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. -->
<ItemGroup Label="Transitive Dependencies"> <ItemGroup Label="Transitive Dependencies">
@ -82,7 +82,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="ppy.osu.Framework" Version="2020.221.0" /> <PackageReference Include="ppy.osu.Framework" Version="2020.225.0" />
<PackageReference Include="SharpCompress" Version="0.24.0" /> <PackageReference Include="SharpCompress" Version="0.24.0" />
<PackageReference Include="NUnit" Version="3.12.0" /> <PackageReference Include="NUnit" Version="3.12.0" />
<PackageReference Include="SharpRaven" Version="2.4.0" /> <PackageReference Include="SharpRaven" Version="2.4.0" />