From c9d600b69c0320967e65aff73d8fd53d7c76cafe Mon Sep 17 00:00:00 2001 From: Lucas A Date: Sat, 22 Feb 2020 09:39:17 +0100 Subject: [PATCH 01/26] Show RankingsOverlay when clicking on charts button --- osu.Game/Screens/Charts/ChartInfo.cs | 9 --------- osu.Game/Screens/Charts/ChartListing.cs | 16 ---------------- osu.Game/Screens/Menu/MainMenu.cs | 5 ++--- 3 files changed, 2 insertions(+), 28 deletions(-) delete mode 100644 osu.Game/Screens/Charts/ChartInfo.cs delete mode 100644 osu.Game/Screens/Charts/ChartListing.cs diff --git a/osu.Game/Screens/Charts/ChartInfo.cs b/osu.Game/Screens/Charts/ChartInfo.cs deleted file mode 100644 index d9a9ad5eeb..0000000000 --- a/osu.Game/Screens/Charts/ChartInfo.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) ppy Pty Ltd . 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 - { - } -} diff --git a/osu.Game/Screens/Charts/ChartListing.cs b/osu.Game/Screens/Charts/ChartListing.cs deleted file mode 100644 index 18bba6433f..0000000000 --- a/osu.Game/Screens/Charts/ChartListing.cs +++ /dev/null @@ -1,16 +0,0 @@ -// 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.Collections.Generic; - -namespace osu.Game.Screens.Charts -{ - public class ChartListing : ScreenWhiteBox - { - protected override IEnumerable PossibleChildren => new[] - { - typeof(ChartInfo) - }; - } -} diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index c70fbb67a4..af5db4ce8c 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -18,7 +18,6 @@ using osu.Game.Online.API; using osu.Game.Overlays; using osu.Game.Overlays.Dialog; using osu.Game.Screens.Backgrounds; -using osu.Game.Screens.Charts; using osu.Game.Screens.Edit; using osu.Game.Screens.Multi; using osu.Game.Screens.Select; @@ -73,7 +72,7 @@ namespace osu.Game.Screens.Menu private SongTicker songTicker; [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(OsuSetting.UIHoldActivationDelay); loginDisplayed = statics.GetBindable(Static.LoginOverlayDisplayed); @@ -101,7 +100,6 @@ namespace osu.Game.Screens.Menu { buttons = new ButtonSystem { - OnChart = delegate { this.Push(new ChartListing()); }, OnEdit = delegate { this.Push(new Editor()); }, OnSolo = onSolo, OnMulti = delegate { this.Push(new Multiplayer()); }, @@ -136,6 +134,7 @@ namespace osu.Game.Screens.Menu buttons.OnSettings = () => settings?.ToggleVisibility(); buttons.OnDirect = () => direct?.ToggleVisibility(); + buttons.OnChart = () => rankings?.ToggleVisibility(); LoadComponentAsync(background = new BackgroundScreenDefault()); preloadSongSelect(); From 5aa5a1bbdd0aab61055ff5d4d9224b201e32e860 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 23 Feb 2020 03:36:15 +0900 Subject: [PATCH 02/26] Reduce transform time of judgement lines (visually looks almost the same) --- osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index 208bdd17ad..d54d4abd14 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -228,7 +228,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters private class JudgementLine : CompositeDrawable { - private const int judgement_fade_duration = 10000; + private const int judgement_fade_duration = 5000; public JudgementLine() { @@ -255,7 +255,7 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters Width = 0; 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(); } } } From 3daa49f1bd2eb6be3881995c337cb3c8a57fc22e Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 23 Feb 2020 03:39:12 +0900 Subject: [PATCH 03/26] Clean up old judgement lines if too many are already present --- osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index d54d4abd14..48c74886a1 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -207,11 +207,16 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters private double floatingAverage; private Container colourBars; + private const int max_concurrent_judgements = 50; + public override void OnNewJudgement(JudgementResult judgement) { if (!judgement.IsHit) return; + if (judgementsContainer.Count >= max_concurrent_judgements) + judgementsContainer.FirstOrDefault(j => j.LifetimeEnd > Clock.CurrentTime + 100)?.FadeOut(100).Expire(); + judgementsContainer.Add(new JudgementLine { Y = getRelativeJudgementPosition(judgement.TimeOffset), From e8ebb315175c994c47e1c53f70ee2c93efd532a9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 23 Feb 2020 03:53:51 +0900 Subject: [PATCH 04/26] Expire old judgement lines if too many exist --- .../Visual/Gameplay/TestSceneHitErrorMeter.cs | 17 +++++++++++++++++ .../Play/HUD/HitErrorMeters/BarHitErrorMeter.cs | 12 +++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs index 8904b54b0d..5f2200b049 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs @@ -9,6 +9,7 @@ using osu.Game.Rulesets.Judgements; using osu.Framework.Utils; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; +using osu.Framework.Threading; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Mania.Scoring; @@ -43,6 +44,22 @@ namespace osu.Game.Tests.Visual.Gameplay AddRepeatStep("New max negative", () => newJudgement(-hitWindows.WindowFor(HitResult.Meh)), 20); AddRepeatStep("New max positive", () => newJudgement(hitWindows.WindowFor(HitResult.Meh)), 20); 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] diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index 48c74886a1..c297ddc981 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -215,7 +215,17 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters return; if (judgementsContainer.Count >= max_concurrent_judgements) - judgementsContainer.FirstOrDefault(j => j.LifetimeEnd > Clock.CurrentTime + 100)?.FadeOut(100).Expire(); + { + const double quick_fade_time = 100; + + var old = judgementsContainer.FirstOrDefault(j => j.LifetimeEnd > Clock.CurrentTime + quick_fade_time); + + if (old != null) + { + old.ClearTransforms(); + old.FadeOut(quick_fade_time).Expire(); + } + } judgementsContainer.Add(new JudgementLine { From cb9a7ee0bb9366caf92e4994825d9554d73a8862 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 23 Feb 2020 04:05:37 +0900 Subject: [PATCH 05/26] Give FollowPointConnections a valid lifetime --- .../Connections/FollowPointConnection.cs | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs index a5e89210f6..7165697022 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs @@ -20,6 +20,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections private const int spacing = 32; private const double preempt = 800; + public override bool RemoveWhenNotAlive => false; + /// /// The start time of . /// @@ -79,27 +81,31 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections drawableObject.HitObject.DefaultsApplied += scheduleRefresh; } - private void scheduleRefresh() => Scheduler.AddOnce(refresh); + private void scheduleRefresh() + { + Scheduler.AddOnce(refresh); + } private void refresh() { ClearInternal(); - if (End == null) - return; - OsuHitObject osuStart = Start.HitObject; - OsuHitObject osuEnd = End.HitObject; + double startTime = osuStart.GetEndTime(); - if (osuEnd.NewCombo) - return; + LifetimeStart = startTime; - 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; + } Vector2 startPosition = osuStart.EndPosition; Vector2 endPosition = osuEnd.Position; - double startTime = osuStart.GetEndTime(); double endTime = osuEnd.StartTime; Vector2 distanceVector = endPosition - startPosition; @@ -107,6 +113,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections float rotation = (float)(Math.Atan2(distanceVector.Y, distanceVector.X) * (180 / Math.PI)); double duration = endTime - startTime; + double finalTransformEndTime = startTime; + for (int d = (int)(spacing * 1.5); d < distance - spacing; d += spacing) { float fraction = (float)d / distance; @@ -131,10 +139,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections fp.ScaleTo(osuEnd.Scale, osuEnd.TimeFadeIn, Easing.Out); fp.MoveTo(pointEndPosition, osuEnd.TimeFadeIn, Easing.Out); fp.Delay(fadeOutTime - fadeInTime).FadeOut(osuEnd.TimeFadeIn); - } - fp.Expire(true); + finalTransformEndTime = fadeOutTime + osuEnd.TimeFadeIn; + } } + + LifetimeStart = startTime; + LifetimeEnd = finalTransformEndTime; } } } From 090d9d93506a8a8e658b1e0bd990f6f9107eebc6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 23 Feb 2020 04:37:04 +0900 Subject: [PATCH 06/26] Make FollowPointRenderer a LifetimeManagementContainer --- .../Objects/Drawables/Connections/FollowPointRenderer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index be192080f9..4d73e711bb 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections /// /// Visualises connections between s. /// - public class FollowPointRenderer : CompositeDrawable + public class FollowPointRenderer : LifetimeManagementContainer { /// /// All the s contained by this . @@ -45,8 +45,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections /// The index of in . 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 int index = connections.AddInPlace(connection, Comparer.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]; previousConnection.End = connection.Start; } + + AddInternal(connection); } /// From 8dbcdebd287b5d1a9b73c4d6f499a481c0d47eeb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 23 Feb 2020 04:58:52 +0900 Subject: [PATCH 07/26] Use LoadingLayer at player loading screen --- osu.Game/Graphics/UserInterface/LoadingLayer.cs | 2 +- osu.Game/Screens/Play/BeatmapMetadataDisplay.cs | 9 +-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/LoadingLayer.cs b/osu.Game/Graphics/UserInterface/LoadingLayer.cs index 25a62acaba..35b33c3d03 100644 --- a/osu.Game/Graphics/UserInterface/LoadingLayer.cs +++ b/osu.Game/Graphics/UserInterface/LoadingLayer.cs @@ -64,7 +64,7 @@ namespace osu.Game.Graphics.UserInterface protected override void 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) diff --git a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs index 77ee52f23e..a84a85ea47 100644 --- a/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs +++ b/osu.Game/Screens/Play/BeatmapMetadataDisplay.cs @@ -15,7 +15,6 @@ using osu.Game.Graphics.UserInterface; using osu.Game.Rulesets.Mods; using osu.Game.Screens.Play.HUD; using osuTK; -using osuTK.Graphics; namespace osu.Game.Screens.Play { @@ -63,15 +62,9 @@ namespace osu.Game.Screens.Play set { if (value) - { loading.Show(); - backgroundSprite.FadeColour(OsuColour.Gray(0.5f), 400, Easing.OutQuint); - } else - { loading.Hide(); - backgroundSprite.FadeColour(Color4.White, 400, Easing.OutQuint); - } } } @@ -138,7 +131,7 @@ namespace osu.Game.Screens.Play Anchor = Anchor.Centre, FillMode = FillMode.Fill, }, - loading = new LoadingSpinner { Scale = new Vector2(1.3f) } + loading = new LoadingLayer(backgroundSprite) } }, new OsuSpriteText From aaa888a7c14b25aef453e4de785b835b73d26013 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 23 Feb 2020 05:00:38 +0900 Subject: [PATCH 08/26] Adjust spin duration to make rotation more variable --- osu.Game/Graphics/UserInterface/LoadingSpinner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/UserInterface/LoadingSpinner.cs b/osu.Game/Graphics/UserInterface/LoadingSpinner.cs index b5a235f9d8..36d429b8c1 100644 --- a/osu.Game/Graphics/UserInterface/LoadingSpinner.cs +++ b/osu.Game/Graphics/UserInterface/LoadingSpinner.cs @@ -93,7 +93,7 @@ namespace osu.Game.Graphics.UserInterface private void rotate() { - spinner.Spin(spin_duration * 4, RotationDirection.Clockwise); + spinner.Spin(spin_duration * 3.5f, RotationDirection.Clockwise); MainContents.RotateTo(0).Then() .RotateTo(90, spin_duration, Easing.InOutQuart).Then() From 560cf21b12af41a100aa276f1a589263b7baed75 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 23 Feb 2020 05:28:59 +0900 Subject: [PATCH 09/26] Add lenience to comparison Noticed that they could still stack up on maps with hitcircles at the same point in time (centipede). --- osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs index c297ddc981..9edbddc0b1 100644 --- a/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs +++ b/osu.Game/Screens/Play/HUD/HitErrorMeters/BarHitErrorMeter.cs @@ -214,11 +214,12 @@ namespace osu.Game.Screens.Play.HUD.HitErrorMeters if (!judgement.IsHit) return; - if (judgementsContainer.Count >= max_concurrent_judgements) + if (judgementsContainer.Count > max_concurrent_judgements) { const double quick_fade_time = 100; - var old = judgementsContainer.FirstOrDefault(j => j.LifetimeEnd > Clock.CurrentTime + quick_fade_time); + // 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) { From ffc7eaa3f212d50a44bf1692b6111bd007f8eb72 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 23 Feb 2020 13:01:30 +0900 Subject: [PATCH 10/26] Fix hitobjects with unknown lifetimes by enforcing non-null judgement We've seen multiple cases where DrawableHitObject are stuck in the lifetime management container due to not implementing a judgement (meaning they are never "hit" or "missed"). To avoid this going forward CreateJudgement() must be implemented and return a non-null judgement. This fixes BananaShower and JuiceStreams in osu!catch. This also makes HitObject abstract and cleans up convert HitObject implementations. --- .../Objects/BananaShower.cs | 3 +++ osu.Game.Rulesets.Catch/Objects/JuiceStream.cs | 3 +++ .../TestSceneDrawableJudgement.cs | 2 +- .../Judgements/HoldNoteJudgement.cs | 14 -------------- osu.Game.Rulesets.Mania/Objects/BarLine.cs | 3 +++ osu.Game.Rulesets.Mania/Objects/HoldNote.cs | 3 +-- .../TestSceneDrawableJudgement.cs | 2 +- .../Judgements/OsuSliderTailJudgement.cs | 14 -------------- .../Objects/SliderTailCircle.cs | 3 +-- .../TestSceneSwellJudgements.cs | 3 +-- .../TestSceneTaikoPlayfield.cs | 8 ++++---- osu.Game.Rulesets.Taiko/Objects/SwellTick.cs | 3 +-- .../TestSceneDrainingHealthProcessor.cs | 1 + .../Gameplay/TestSceneHitObjectAccentColour.cs | 2 +- .../Gameplay/TestSceneHitObjectContainer.cs | 12 ++++++------ .../TestSceneDrawableScrollingRuleset.cs | 4 ++-- .../Visual/Gameplay/TestSceneHitErrorMeter.cs | 2 +- .../Gameplay/TestSceneScrollingHitObjects.cs | 4 ++-- .../Visual/Gameplay/TestSceneSongProgress.cs | 4 ++-- .../SongSelect/TestSceneBeatmapInfoWedge.cs | 2 +- .../Rulesets/Judgements/IgnoreJudgement.cs | 6 +++--- osu.Game/Rulesets/Objects/ConvertHitObject.cs | 18 ++++++++++++++++++ osu.Game/Rulesets/Objects/HitObject.cs | 11 ++++++----- .../Objects/Legacy/Catch/ConvertHit.cs | 2 +- .../Objects/Legacy/Catch/ConvertSpinner.cs | 2 +- .../Rulesets/Objects/Legacy/ConvertSlider.cs | 2 +- .../Objects/Legacy/Mania/ConvertHit.cs | 5 +---- .../Objects/Legacy/Mania/ConvertHold.cs | 5 +---- .../Objects/Legacy/Mania/ConvertSlider.cs | 3 --- .../Objects/Legacy/Mania/ConvertSpinner.cs | 5 +---- .../Rulesets/Objects/Legacy/Osu/ConvertHit.cs | 5 +---- .../Objects/Legacy/Osu/ConvertSlider.cs | 3 --- .../Objects/Legacy/Osu/ConvertSpinner.cs | 5 +---- .../Objects/Legacy/Taiko/ConvertHit.cs | 5 +---- .../Objects/Legacy/Taiko/ConvertSlider.cs | 3 --- .../Objects/Legacy/Taiko/ConvertSpinner.cs | 5 +---- 36 files changed, 72 insertions(+), 105 deletions(-) delete mode 100644 osu.Game.Rulesets.Mania/Judgements/HoldNoteJudgement.cs delete mode 100644 osu.Game.Rulesets.Osu/Judgements/OsuSliderTailJudgement.cs rename osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs => osu.Game/Rulesets/Judgements/IgnoreJudgement.cs (63%) create mode 100644 osu.Game/Rulesets/Objects/ConvertHitObject.cs diff --git a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs index 0c754412e5..c3488aec11 100644 --- a/osu.Game.Rulesets.Catch/Objects/BananaShower.cs +++ b/osu.Game.Rulesets.Catch/Objects/BananaShower.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . 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.Objects.Types; namespace osu.Game.Rulesets.Catch.Objects @@ -11,6 +12,8 @@ namespace osu.Game.Rulesets.Catch.Objects public override bool LastInCombo => true; + public override Judgement CreateJudgement() => new IgnoreJudgement(); + protected override void CreateNestedHitObjects() { base.CreateNestedHitObjects(); diff --git a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs index 11e2466275..642ff0246e 100644 --- a/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs +++ b/osu.Game.Rulesets.Catch/Objects/JuiceStream.cs @@ -7,6 +7,7 @@ using osu.Game.Audio; using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Catch.UI; +using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; @@ -19,6 +20,8 @@ namespace osu.Game.Rulesets.Catch.Objects /// private const float base_scoring_distance = 100; + public override Judgement CreateJudgement() => new IgnoreJudgement(); + public int RepeatCount { get; set; } public double Velocity; diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableJudgement.cs index 692d079c16..7b71f2feda 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableJudgement.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Mania.Tests foreach (HitResult result in Enum.GetValues(typeof(HitResult)).OfType().Skip(1)) { AddStep("Show " + result.GetDescription(), () => SetContents(() => - new DrawableManiaJudgement(new JudgementResult(new HitObject(), new Judgement()) { Type = result }, null) + new DrawableManiaJudgement(new JudgementResult(new ConvertHitObject(), new Judgement()) { Type = result }, null) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Mania/Judgements/HoldNoteJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/HoldNoteJudgement.cs deleted file mode 100644 index e8b48768a1..0000000000 --- a/osu.Game.Rulesets.Mania/Judgements/HoldNoteJudgement.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) ppy Pty Ltd . 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; - } -} diff --git a/osu.Game.Rulesets.Mania/Objects/BarLine.cs b/osu.Game.Rulesets.Mania/Objects/BarLine.cs index 0981b028b2..09a746042b 100644 --- a/osu.Game.Rulesets.Mania/Objects/BarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/BarLine.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . 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.Objects; namespace osu.Game.Rulesets.Mania.Objects @@ -8,5 +9,7 @@ namespace osu.Game.Rulesets.Mania.Objects public class BarLine : ManiaHitObject, IBarLine { public bool Major { get; set; } + + public override Judgement CreateJudgement() => new IgnoreJudgement(); } } diff --git a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs index 86d3d2b2b0..049bf55f90 100644 --- a/osu.Game.Rulesets.Mania/Objects/HoldNote.cs +++ b/osu.Game.Rulesets.Mania/Objects/HoldNote.cs @@ -4,7 +4,6 @@ using osu.Game.Beatmaps; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Mania.Judgements; using osu.Game.Rulesets.Objects.Types; 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; } diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs index 02d4406809..8f72e2f60d 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Tests foreach (HitResult result in Enum.GetValues(typeof(HitResult)).OfType().Skip(1)) { AddStep("Show " + result.GetDescription(), () => SetContents(() => - new DrawableOsuJudgement(new JudgementResult(new HitObject(), new Judgement()) { Type = result }, null) + new DrawableOsuJudgement(new JudgementResult(new ConvertHitObject(), new Judgement()) { Type = result }, null) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuSliderTailJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuSliderTailJudgement.cs deleted file mode 100644 index 5104d9494b..0000000000 --- a/osu.Game.Rulesets.Osu/Judgements/OsuSliderTailJudgement.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) ppy Pty Ltd . 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; - } -} diff --git a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs index c17d2275b8..127c36fcc0 100644 --- a/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/SliderTailCircle.cs @@ -4,7 +4,6 @@ using osu.Framework.Bindables; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; -using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Osu.Objects @@ -23,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Objects pathVersion.BindValueChanged(_ => Position = slider.EndPosition); } - public override Judgement CreateJudgement() => new OsuSliderTailJudgement(); + public override Judgement CreateJudgement() => new IgnoreJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; } diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs index f27e329e8e..ccacc50de1 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneSwellJudgements.cs @@ -8,7 +8,6 @@ using osu.Framework.Allocation; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Screens.Play; using osu.Game.Tests.Visual; @@ -28,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.Tests public void TestZeroTickTimeOffsets() { 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; diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs index c01eef5252..c8c4d004d6 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs @@ -148,7 +148,7 @@ namespace osu.Game.Rulesets.Taiko.Tests var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) }; - ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new HitObject(), new TaikoJudgement()) { Type = hitResult }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new ConvertHitObject(), new TaikoJudgement()) { Type = hitResult }); } private void addStrongHitJudgement(bool kiai) @@ -163,13 +163,13 @@ namespace osu.Game.Rulesets.Taiko.Tests var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) }; - ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new HitObject(), new TaikoJudgement()) { Type = hitResult }); - ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new TestStrongNestedHit(h), new JudgementResult(new HitObject(), new TaikoStrongJudgement()) { Type = HitResult.Great }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new ConvertHitObject(), new TaikoJudgement()) { Type = hitResult }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new TestStrongNestedHit(h), new JudgementResult(new ConvertHitObject(), new TaikoStrongJudgement()) { Type = HitResult.Great }); } private void addMissJudgement() { - ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new DrawableTestHit(new Hit()), new JudgementResult(new HitObject(), new TaikoJudgement()) { Type = HitResult.Miss }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new DrawableTestHit(new Hit()), new JudgementResult(new ConvertHitObject(), new TaikoJudgement()) { Type = HitResult.Miss }); } private void addBarLine(bool major, double delay = scroll_time) diff --git a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs index 91f4d3dbe7..bdc0478195 100644 --- a/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs +++ b/osu.Game.Rulesets.Taiko/Objects/SwellTick.cs @@ -3,13 +3,12 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Judgements; namespace osu.Game.Rulesets.Taiko.Objects { public class SwellTick : TaikoHitObject { - public override Judgement CreateJudgement() => new TaikoSwellTickJudgement(); + public override Judgement CreateJudgement() => new IgnoreJudgement(); protected override HitWindows CreateHitWindows() => HitWindows.Empty; } diff --git a/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs b/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs index 244e37f017..885abb61b5 100644 --- a/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs +++ b/osu.Game.Tests/Gameplay/TestSceneDrainingHealthProcessor.cs @@ -154,6 +154,7 @@ namespace osu.Game.Tests.Gameplay private class JudgeableHitObject : HitObject { public override Judgement CreateJudgement() => new Judgement(); + protected override HitWindows CreateHitWindows() => new HitWindows(); } } } diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs index 17dc27543d..e99a10524e 100644 --- a/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs @@ -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 int ComboOffset { get; } = 0; diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs index f2bfccb6de..6452857bad 100644 --- a/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs @@ -27,9 +27,9 @@ namespace osu.Game.Tests.Gameplay { DrawableHitObject hitObject = null; - AddStep("setup", () => container.Add(new TestDrawableHitObject(new HitObject { StartTime = 500 }))); + AddStep("setup", () => container.Add(new TestDrawableHitObject(new ConvertHitObject { StartTime = 500 }))); - AddStep("add late hitobject", () => container.Add(hitObject = new TestDrawableHitObject(new HitObject { StartTime = 1000 }))); + AddStep("add late hitobject", () => container.Add(hitObject = new TestDrawableHitObject(new ConvertHitObject { StartTime = 1000 }))); AddAssert("hitobject index is 0", () => container.IndexOf(hitObject) == 0); } @@ -39,9 +39,9 @@ namespace osu.Game.Tests.Gameplay { DrawableHitObject hitObject = null; - AddStep("setup", () => container.Add(new TestDrawableHitObject(new HitObject { StartTime = 500 }))); + AddStep("setup", () => container.Add(new TestDrawableHitObject(new ConvertHitObject { StartTime = 500 }))); - AddStep("add early hitobject", () => container.Add(hitObject = new TestDrawableHitObject(new HitObject()))); + AddStep("add early hitobject", () => container.Add(hitObject = new TestDrawableHitObject(new ConvertHitObject()))); AddAssert("hitobject index is 0", () => container.IndexOf(hitObject) == 1); } @@ -54,8 +54,8 @@ namespace osu.Game.Tests.Gameplay AddStep("setup", () => { - container.Add(firstObject = new TestDrawableHitObject(new HitObject())); - container.Add(secondObject = new TestDrawableHitObject(new HitObject { StartTime = 1000 })); + container.Add(firstObject = new TestDrawableHitObject(new ConvertHitObject())); + container.Add(secondObject = new TestDrawableHitObject(new ConvertHitObject { StartTime = 1000 })); }); AddStep("move first object after second", () => firstObject.HitObject.StartTime = 2000); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index 46f62b9541..d350c3d58d 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -163,7 +163,7 @@ namespace osu.Game.Tests.Visual.Gameplay var beatmap = new Beatmap { BeatmapInfo = { Ruleset = new OsuRuleset().RulesetInfo } }; for (int i = 0; i < 10; i++) - beatmap.HitObjects.Add(new HitObject { StartTime = i * time_range }); + beatmap.HitObjects.Add(new ConvertHitObject { StartTime = i * time_range }); return beatmap; } @@ -289,7 +289,7 @@ namespace osu.Game.Tests.Visual.Gameplay #region HitObject - private class TestHitObject : HitObject, IHasEndTime + private class TestHitObject : ConvertHitObject, IHasEndTime { public double EndTime { get; set; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs index 8904b54b0d..494611d414 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs @@ -124,7 +124,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void newJudgement(double offset = 0) { - var judgement = new JudgementResult(new HitObject(), new Judgement()) + var judgement = new JudgementResult(new ConvertHitObject(), new Judgement()) { TimeOffset = offset == 0 ? RNG.Next(-150, 150) : offset, Type = HitResult.Perfect, diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs index d03716db2e..c2a71eadae 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs @@ -224,7 +224,7 @@ namespace osu.Game.Tests.Visual.Gameplay private class TestDrawableControlPoint : DrawableHitObject { public TestDrawableControlPoint(ScrollingDirection direction, double time) - : base(new HitObject { StartTime = time }) + : base(new ConvertHitObject { StartTime = time }) { Origin = Anchor.Centre; @@ -255,7 +255,7 @@ namespace osu.Game.Tests.Visual.Gameplay private class TestDrawableHitObject : DrawableHitObject { public TestDrawableHitObject(double time) - : base(new HitObject { StartTime = time }) + : base(new ConvertHitObject { StartTime = time }) { Origin = Anchor.Custom; OriginPosition = new Vector2(75 / 4.0f); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index b9b13d7bd8..6a60ae110b 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -123,7 +123,7 @@ namespace osu.Game.Tests.Visual.Gameplay { var objects = new List(); for (double i = 0; i < 5000; i += RNG.NextDouble() * 10 + i / 1000) - objects.Add(new HitObject { StartTime = i }); + objects.Add(new ConvertHitObject { StartTime = i }); replaceObjects(objects); } @@ -132,7 +132,7 @@ namespace osu.Game.Tests.Visual.Gameplay { var objects = new List(); for (double i = 0; i < 5000; i++) - objects.Add(new HitObject { StartTime = i }); + objects.Add(new ConvertHitObject { StartTime = i }); replaceObjects(objects); } diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index f49d7a14a6..5cac897200 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -194,7 +194,7 @@ namespace osu.Game.Tests.Visual.SongSelect public new BufferedWedgeInfo Info => base.Info; } - private class TestHitObject : HitObject, IHasPosition + private class TestHitObject : ConvertHitObject, IHasPosition { public float X { get; } = 0; public float Y { get; } = 0; diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs b/osu.Game/Rulesets/Judgements/IgnoreJudgement.cs similarity index 63% rename from osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs rename to osu.Game/Rulesets/Judgements/IgnoreJudgement.cs index b28b6a0d17..1871249c94 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoSwellTickJudgement.cs +++ b/osu.Game/Rulesets/Judgements/IgnoreJudgement.cs @@ -1,11 +1,11 @@ -// 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.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; diff --git a/osu.Game/Rulesets/Objects/ConvertHitObject.cs b/osu.Game/Rulesets/Objects/ConvertHitObject.cs new file mode 100644 index 0000000000..81a88615a3 --- /dev/null +++ b/osu.Game/Rulesets/Objects/ConvertHitObject.cs @@ -0,0 +1,18 @@ +// Copyright (c) ppy Pty Ltd . 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 +{ + /// + /// A hit object only used for conversion, not actual gameplay. + /// + public class ConvertHitObject : HitObject + { + public override Judgement CreateJudgement() => new IgnoreJudgement(); + + protected override HitWindows CreateHitWindows() => HitWindows.Empty; + } +} diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index c09844e0c6..bef48f0ced 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Objects /// HitObjects may contain more properties for which you should be checking through the IHas* types. /// /// - public class HitObject + public abstract class HitObject { /// /// A small adjustment to the start time of control points to account for rounding/precision errors. @@ -83,7 +83,7 @@ namespace osu.Game.Rulesets.Objects [JsonIgnore] public IReadOnlyList NestedHitObjects => nestedHitObjects; - public HitObject() + protected HitObject() { StartTimeBindable.ValueChanged += time => { @@ -144,9 +144,10 @@ namespace osu.Game.Rulesets.Objects /// /// Creates the that represents the scoring information for this . - /// May be null. + /// Used to decide on drawable object lifetimes. /// - public virtual Judgement CreateJudgement() => null; + [NotNull] + public abstract Judgement CreateJudgement(); /// /// Creates the for this . @@ -156,7 +157,7 @@ namespace osu.Game.Rulesets.Objects /// /// [NotNull] - protected virtual HitWindows CreateHitWindows() => new HitWindows(); + protected abstract HitWindows CreateHitWindows(); } public static class HitObjectExtensions diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs index febfd3696c..19722fb796 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertHit.cs @@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch /// /// Legacy osu!catch Hit-type, used for parsing Beatmaps. /// - internal sealed class ConvertHit : HitObject, IHasCombo, IHasXPosition + internal sealed class ConvertHit : ConvertHitObject, IHasCombo, IHasXPosition { public float X { get; set; } diff --git a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs index 0089d1eb88..9de311c9d7 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Catch/ConvertSpinner.cs @@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch /// /// Legacy osu!catch Spinner-type, used for parsing Beatmaps. /// - internal sealed class ConvertSpinner : HitObject, IHasEndTime, IHasXPosition, IHasCombo + internal sealed class ConvertSpinner : ConvertHitObject, IHasEndTime, IHasXPosition, IHasCombo { public double EndTime { get; set; } diff --git a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs index 53cdf457c4..924182b265 100644 --- a/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertSlider.cs @@ -9,7 +9,7 @@ using osu.Game.Beatmaps.ControlPoints; namespace osu.Game.Rulesets.Objects.Legacy { - internal abstract class ConvertSlider : HitObject, IHasCurve, IHasLegacyLastTickOffset + internal abstract class ConvertSlider : ConvertHitObject, IHasCurve, IHasLegacyLastTickOffset { /// /// Scoring distance with a speed-adjusted beat length of 1 second. diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs index 883ef55df0..0b69817c13 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHit.cs @@ -2,17 +2,14 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; -using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Objects.Legacy.Mania { /// /// Legacy osu!mania Hit-type, used for parsing Beatmaps. /// - internal sealed class ConvertHit : HitObject, IHasXPosition + internal sealed class ConvertHit : ConvertHitObject, IHasXPosition { public float X { get; set; } - - protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs index 69e6f8379d..1d92d638dd 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertHold.cs @@ -2,18 +2,15 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; -using osu.Game.Rulesets.Scoring; 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 double EndTime { get; set; } public double Duration => EndTime - StartTime; - - protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs index 4486c5d906..84cde5fa95 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSlider.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; -using osu.Game.Rulesets.Scoring; 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 { public float X { get; set; } - - protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs index c6d1f1922c..7dc13e27cd 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Mania/ConvertSpinner.cs @@ -2,21 +2,18 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; -using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Objects.Legacy.Mania { /// /// Legacy osu!mania Spinner-type, used for parsing Beatmaps. /// - internal sealed class ConvertSpinner : HitObject, IHasEndTime, IHasXPosition + internal sealed class ConvertSpinner : ConvertHitObject, IHasEndTime, IHasXPosition { public double EndTime { get; set; } public double Duration => EndTime - StartTime; public float X { get; set; } - - protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs index e40b5b4505..069366bad3 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertHit.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; -using osu.Game.Rulesets.Scoring; using osuTK; namespace osu.Game.Rulesets.Objects.Legacy.Osu @@ -10,7 +9,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu /// /// Legacy osu! Hit-type, used for parsing Beatmaps. /// - internal sealed class ConvertHit : HitObject, IHasPosition, IHasCombo + internal sealed class ConvertHit : ConvertHitObject, IHasPosition, IHasCombo { public Vector2 Position { get; set; } @@ -21,7 +20,5 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu public bool NewCombo { get; set; } public int ComboOffset { get; set; } - - protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs index a163329d47..e947690668 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSlider.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; -using osu.Game.Rulesets.Scoring; using osuTK; namespace osu.Game.Rulesets.Objects.Legacy.Osu @@ -21,7 +20,5 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu public bool NewCombo { get; set; } public int ComboOffset { get; set; } - - protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs index 5d96a61633..8b21aab411 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Osu/ConvertSpinner.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; -using osu.Game.Rulesets.Scoring; using osuTK; namespace osu.Game.Rulesets.Objects.Legacy.Osu @@ -10,7 +9,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu /// /// Legacy osu! Spinner-type, used for parsing Beatmaps. /// - internal sealed class ConvertSpinner : HitObject, IHasEndTime, IHasPosition, IHasCombo + internal sealed class ConvertSpinner : ConvertHitObject, IHasEndTime, IHasPosition, IHasCombo { public double EndTime { get; set; } @@ -22,8 +21,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu public float Y => Position.Y; - protected override HitWindows CreateHitWindows() => HitWindows.Empty; - public bool NewCombo { get; set; } public int ComboOffset { get; set; } diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs index efb9810927..cb5178ce48 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertHit.cs @@ -1,15 +1,12 @@ // Copyright (c) ppy Pty Ltd . 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.Objects.Legacy.Taiko { /// /// Legacy osu!taiko Hit-type, used for parsing Beatmaps. /// - internal sealed class ConvertHit : HitObject + internal sealed class ConvertHit : ConvertHitObject { - protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs index b365fd34ae..821554f7ee 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSlider.cs @@ -1,8 +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 osu.Game.Rulesets.Scoring; - namespace osu.Game.Rulesets.Objects.Legacy.Taiko { /// @@ -10,6 +8,5 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko /// internal sealed class ConvertSlider : Legacy.ConvertSlider { - protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } diff --git a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs index 840ba51ac2..8e28487f2f 100644 --- a/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs +++ b/osu.Game/Rulesets/Objects/Legacy/Taiko/ConvertSpinner.cs @@ -2,19 +2,16 @@ // See the LICENCE file in the repository root for full licence text. using osu.Game.Rulesets.Objects.Types; -using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Objects.Legacy.Taiko { /// /// Legacy osu!taiko Spinner-type, used for parsing Beatmaps. /// - internal sealed class ConvertSpinner : HitObject, IHasEndTime + internal sealed class ConvertSpinner : ConvertHitObject, IHasEndTime { public double EndTime { get; set; } public double Duration => EndTime - StartTime; - - protected override HitWindows CreateHitWindows() => HitWindows.Empty; } } From 0e29d3c4a2173eecc9681b36d66985518dcd2cda Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 23 Feb 2020 13:50:05 +0900 Subject: [PATCH 11/26] Correctly expire bar lines in osu!taiko and osu!mania --- osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs | 4 +--- osu.Game.Rulesets.Taiko/Objects/BarLine.cs | 3 +++ osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs | 2 ++ osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs index 56bc797c7f..08b5b75f9c 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableBarLine.cs @@ -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); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs index 2afbbc737c..6306195704 100644 --- a/osu.Game.Rulesets.Taiko/Objects/BarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/BarLine.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . 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.Objects; namespace osu.Game.Rulesets.Taiko.Objects @@ -8,5 +9,7 @@ namespace osu.Game.Rulesets.Taiko.Objects public class BarLine : TaikoHitObject, IBarLine { public bool Major { get; set; } + + public override Judgement CreateJudgement() => new IgnoreJudgement(); } } diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs index 1a5a797f28..e9caabbcc8 100644 --- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs +++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableBarLine.cs @@ -54,5 +54,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables Alpha = 0.75f }); } + + protected override void UpdateStateTransforms(ArmedState state) => this.FadeOut(150); } } diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 67fe18e8dd..d8614c9d3d 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -265,7 +265,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(); } else From 401bf1c92811158cf752aac264953324d3b2f761 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 23 Feb 2020 14:30:08 +0900 Subject: [PATCH 12/26] Remove unnecessary checks on NotNull attributes --- osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 9 +++------ osu.Game/Rulesets/Scoring/JudgementProcessor.cs | 2 -- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 67fe18e8dd..369bda3fc2 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -99,12 +99,9 @@ namespace osu.Game.Rulesets.Objects.Drawables { var judgement = HitObject.CreateJudgement(); - if (judgement != null) - { - Result = CreateResult(judgement); - if (Result == null) - throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); - } + Result = CreateResult(judgement); + if (Result == null) + throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}."); loadSamples(); } diff --git a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs index 3016007f98..334b95f808 100644 --- a/osu.Game/Rulesets/Scoring/JudgementProcessor.cs +++ b/osu.Game/Rulesets/Scoring/JudgementProcessor.cs @@ -125,8 +125,6 @@ namespace osu.Game.Rulesets.Scoring simulate(nested); var judgement = obj.CreateJudgement(); - if (judgement == null) - return; var result = CreateResult(obj, judgement); if (result == null) From 575946d92367f6d98fd198d1e3ddfa236718eca7 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 23 Feb 2020 20:47:14 +0900 Subject: [PATCH 13/26] Expose save and export options in editor to non-dekstop platforms --- osu.Game/Screens/Edit/Editor.cs | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 3bec4b8f6f..d84151f5af 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -20,8 +20,6 @@ using osu.Game.Screens.Edit.Components; using osu.Game.Screens.Edit.Components.Menus; using osu.Game.Screens.Edit.Design; using osuTK.Input; -using System.Collections.Generic; -using osu.Framework; using osu.Framework.Input.Bindings; using osu.Game.Beatmaps; using osu.Game.Graphics.Cursor; @@ -93,17 +91,6 @@ namespace osu.Game.Screens.Edit EditorMenuBar menuBar; - var fileMenuItems = new List(); - - if (RuntimeInfo.IsDesktop) - { - fileMenuItems.Add(new EditorMenuItem("Save", MenuItemType.Standard, saveBeatmap)); - fileMenuItems.Add(new EditorMenuItem("Export package", MenuItemType.Standard, exportBeatmap)); - fileMenuItems.Add(new EditorMenuItemSpacer()); - } - - fileMenuItems.Add(new EditorMenuItem("Exit", MenuItemType.Standard, this.Exit)); - AddInternal(new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, @@ -134,7 +121,13 @@ namespace osu.Game.Screens.Edit { new MenuItem("File") { - Items = fileMenuItems + Items = new[] + { + new EditorMenuItem("Save", MenuItemType.Standard, saveBeatmap), + new EditorMenuItem("Export package", MenuItemType.Standard, exportBeatmap), + new EditorMenuItemSpacer(), + new EditorMenuItem("Exit", MenuItemType.Standard, this.Exit), + } } } } From b0b52146eafd10c442c6809d1f4d9f6cb0e1ee56 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 24 Feb 2020 05:53:33 +0300 Subject: [PATCH 14/26] Fix crash when clicking on ShowMore button --- osu.Game/Overlays/Comments/CommentsPage.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/CommentsPage.cs b/osu.Game/Overlays/Comments/CommentsPage.cs index 4f82ee5a19..591400f741 100644 --- a/osu.Game/Overlays/Comments/CommentsPage.cs +++ b/osu.Game/Overlays/Comments/CommentsPage.cs @@ -96,12 +96,17 @@ namespace osu.Game.Overlays.Comments { var orphaned = new List(); + // Exclude possible duplicated comments. foreach (var topLevel in bundle.Comments) + { + if (commentDictionary.ContainsKey(topLevel.Id)) + continue; + addNewComment(topLevel); + } foreach (var child in bundle.IncludedComments) { - // Included comments can contain the parent comment, which already exists in the hierarchy. if (commentDictionary.ContainsKey(child.Id)) continue; From e6cfafffe9966aee9fc9cb68b4b6d8a373c143fe Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 24 Feb 2020 12:24:15 +0900 Subject: [PATCH 15/26] Fix incorrect LifetimeStart and add todo regarding Expire usage --- .../Objects/Drawables/Connections/FollowPointConnection.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs index 7165697022..921b23cb13 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointConnection.cs @@ -113,6 +113,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections float rotation = (float)(Math.Atan2(distanceVector.Y, distanceVector.X) * (180 / Math.PI)); double duration = endTime - startTime; + double? firstTransformStartTime = null; double finalTransformEndTime = startTime; for (int d = (int)(spacing * 1.5); d < distance - spacing; d += spacing) @@ -133,6 +134,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections Scale = new Vector2(1.5f * osuEnd.Scale), }); + if (firstTransformStartTime == null) + firstTransformStartTime = fadeInTime; + using (fp.BeginAbsoluteSequence(fadeInTime)) { fp.FadeIn(osuEnd.TimeFadeIn); @@ -144,7 +148,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections } } - LifetimeStart = startTime; + // 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; } } From fe1f2858c19e8e5bf7726abe121b61c8fc9d13ca Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Mon, 24 Feb 2020 23:10:37 +0300 Subject: [PATCH 16/26] Refactor to avoid duplicated code --- osu.Game/Overlays/Comments/CommentsPage.cs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/osu.Game/Overlays/Comments/CommentsPage.cs b/osu.Game/Overlays/Comments/CommentsPage.cs index 591400f741..1fb6032924 100644 --- a/osu.Game/Overlays/Comments/CommentsPage.cs +++ b/osu.Game/Overlays/Comments/CommentsPage.cs @@ -97,20 +97,12 @@ namespace osu.Game.Overlays.Comments var orphaned = new List(); // Exclude possible duplicated comments. - foreach (var topLevel in bundle.Comments) + foreach (var comment in bundle.Comments.Concat(bundle.IncludedComments)) { - if (commentDictionary.ContainsKey(topLevel.Id)) + if (commentDictionary.ContainsKey(comment.Id)) continue; - addNewComment(topLevel); - } - - foreach (var child in bundle.IncludedComments) - { - if (commentDictionary.ContainsKey(child.Id)) - continue; - - addNewComment(child); + addNewComment(comment); } // Comments whose parents were seen later than themselves can now be added. From 4cbb2a2f591f07f6a748aa57434bf78554a9c4ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Mon, 24 Feb 2020 21:30:27 +0100 Subject: [PATCH 17/26] Move comment to more pertinent place --- osu.Game/Overlays/Comments/CommentsPage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Comments/CommentsPage.cs b/osu.Game/Overlays/Comments/CommentsPage.cs index 1fb6032924..f3a774908c 100644 --- a/osu.Game/Overlays/Comments/CommentsPage.cs +++ b/osu.Game/Overlays/Comments/CommentsPage.cs @@ -96,9 +96,9 @@ namespace osu.Game.Overlays.Comments { var orphaned = new List(); - // Exclude possible duplicated comments. foreach (var comment in bundle.Comments.Concat(bundle.IncludedComments)) { + // Exclude possible duplicated comments. if (commentDictionary.ContainsKey(comment.Id)) continue; From c1455be85592c3ccf8c0ab95b27c23830927ca53 Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Tue, 25 Feb 2020 10:29:03 +0300 Subject: [PATCH 18/26] Add tests --- .../Visual/Online/TestSceneCommentsPage.cs | 52 +++++++++++++++++-- osu.Game/Overlays/Comments/CommentsPage.cs | 16 +++--- 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsPage.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsPage.cs index 0ed8864860..a28a0107a1 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsPage.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsPage.cs @@ -13,6 +13,8 @@ using osu.Framework.Bindables; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics; using osuTK; +using JetBrains.Annotations; +using NUnit.Framework; namespace osu.Game.Tests.Visual.Online { @@ -30,6 +32,8 @@ namespace osu.Game.Tests.Visual.Online private readonly BindableBool showDeleted = new BindableBool(); private readonly Container content; + private TestCommentsPage commentsPage; + public TestSceneCommentsPage() { Add(new FillFlowContainer @@ -57,15 +61,29 @@ namespace osu.Game.Tests.Visual.Online } } }); + } - AddStep("load comments", () => createPage(getCommentBundle())); - AddStep("load empty comments", () => createPage(getEmptyCommentBundle())); + [Test] + 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) { + commentsPage = null; content.Clear(); - content.Add(new CommentsPage(commentBundle) + content.Add(commentsPage = new TestCommentsPage(commentBundle) { ShowDeleted = { BindTarget = showDeleted } }); @@ -182,5 +200,33 @@ namespace osu.Game.Tests.Visual.Online } }, }; + + private CommentBundle getCommentSubBundle() => new CommentBundle + { + Comments = new List + { + new Comment + { + Id = 1, + Message = "Simple test comment", + LegacyName = "TestUser1", + CreatedAt = DateTimeOffset.Now, + VotesCount = 5 + }, + }, + IncludedComments = new List(), + }; + + 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; + } } } diff --git a/osu.Game/Overlays/Comments/CommentsPage.cs b/osu.Game/Overlays/Comments/CommentsPage.cs index f3a774908c..9b146b0a7d 100644 --- a/osu.Game/Overlays/Comments/CommentsPage.cs +++ b/osu.Game/Overlays/Comments/CommentsPage.cs @@ -61,15 +61,15 @@ namespace osu.Game.Overlays.Comments return; } - appendComments(commentBundle); + AppendComments(commentBundle); } private DrawableComment getDrawableComment(Comment comment) { - if (commentDictionary.TryGetValue(comment.Id, out var existing)) + if (CommentDictionary.TryGetValue(comment.Id, out var existing)) return existing; - return commentDictionary[comment.Id] = new DrawableComment(comment) + return CommentDictionary[comment.Id] = new DrawableComment(comment) { ShowDeleted = { BindTarget = ShowDeleted }, Sort = { BindTarget = Sort }, @@ -81,25 +81,25 @@ namespace osu.Game.Overlays.Comments { 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); } - private readonly Dictionary commentDictionary = new Dictionary(); + protected readonly Dictionary CommentDictionary = new Dictionary(); /// /// Appends retrieved comments to the subtree rooted of comments in this page. /// /// The bundle of comments to add. - private void appendComments([NotNull] CommentBundle bundle) + protected void AppendComments([NotNull] CommentBundle bundle) { var orphaned = new List(); foreach (var comment in bundle.Comments.Concat(bundle.IncludedComments)) { // Exclude possible duplicated comments. - if (commentDictionary.ContainsKey(comment.Id)) + if (CommentDictionary.ContainsKey(comment.Id)) continue; addNewComment(comment); @@ -118,7 +118,7 @@ namespace osu.Game.Overlays.Comments // Comments that have no parent are added as top-level comments to the flow. 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. comment.ParentComment = parentDrawable.Comment; From d6046abe700722023b2325ea1c6ba19664a2e8ac Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Feb 2020 18:59:16 +0900 Subject: [PATCH 19/26] Only expose save for now --- osu.Game/Screens/Edit/Editor.cs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index d84151f5af..8d3b8849bc 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -20,6 +20,8 @@ using osu.Game.Screens.Edit.Components; using osu.Game.Screens.Edit.Components.Menus; using osu.Game.Screens.Edit.Design; using osuTK.Input; +using System.Collections.Generic; +using osu.Framework; using osu.Framework.Input.Bindings; using osu.Game.Beatmaps; using osu.Game.Graphics.Cursor; @@ -91,6 +93,16 @@ namespace osu.Game.Screens.Edit EditorMenuBar menuBar; + var fileMenuItems = new List(); + + fileMenuItems.Add(new EditorMenuItem("Save", MenuItemType.Standard, saveBeatmap)); + + if (RuntimeInfo.IsDesktop) + fileMenuItems.Add(new EditorMenuItem("Export package", MenuItemType.Standard, exportBeatmap)); + + fileMenuItems.Add(new EditorMenuItemSpacer()); + fileMenuItems.Add(new EditorMenuItem("Exit", MenuItemType.Standard, this.Exit)); + AddInternal(new OsuContextMenuContainer { RelativeSizeAxes = Axes.Both, @@ -121,13 +133,7 @@ namespace osu.Game.Screens.Edit { new MenuItem("File") { - Items = new[] - { - new EditorMenuItem("Save", MenuItemType.Standard, saveBeatmap), - new EditorMenuItem("Export package", MenuItemType.Standard, exportBeatmap), - new EditorMenuItemSpacer(), - new EditorMenuItem("Exit", MenuItemType.Standard, this.Exit), - } + Items = fileMenuItems } } } From a0474563545ed534f1fd6e15172be38662993705 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Feb 2020 19:07:15 +0900 Subject: [PATCH 20/26] Revert changes to make HitObject abstract --- .../TestSceneDrawableJudgement.cs | 2 +- .../TestSceneDrawableJudgement.cs | 2 +- .../TestSceneTaikoPlayfield.cs | 8 ++++---- .../Gameplay/TestSceneHitObjectAccentColour.cs | 2 +- .../Gameplay/TestSceneHitObjectContainer.cs | 12 ++++++------ .../Gameplay/TestSceneDrawableScrollingRuleset.cs | 3 ++- .../Visual/Gameplay/TestSceneHitErrorMeter.cs | 4 ++-- .../Visual/Gameplay/TestSceneScrollingHitObjects.cs | 4 ++-- .../Visual/Gameplay/TestSceneSongProgress.cs | 4 ++-- .../Visual/SongSelect/TestSceneBeatmapInfoWedge.cs | 1 + osu.Game/Rulesets/Objects/HitObject.cs | 8 ++++---- .../Objects/{ => Legacy}/ConvertHitObject.cs | 4 ++-- 12 files changed, 28 insertions(+), 26 deletions(-) rename osu.Game/Rulesets/Objects/{ => Legacy}/ConvertHitObject.cs (83%) diff --git a/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableJudgement.cs index 7b71f2feda..692d079c16 100644 --- a/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Mania.Tests/TestSceneDrawableJudgement.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Mania.Tests foreach (HitResult result in Enum.GetValues(typeof(HitResult)).OfType().Skip(1)) { AddStep("Show " + result.GetDescription(), () => SetContents(() => - new DrawableManiaJudgement(new JudgementResult(new ConvertHitObject(), new Judgement()) { Type = result }, null) + new DrawableManiaJudgement(new JudgementResult(new HitObject(), new Judgement()) { Type = result }, null) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs index 8f72e2f60d..02d4406809 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneDrawableJudgement.cs @@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Tests foreach (HitResult result in Enum.GetValues(typeof(HitResult)).OfType().Skip(1)) { AddStep("Show " + result.GetDescription(), () => SetContents(() => - new DrawableOsuJudgement(new JudgementResult(new ConvertHitObject(), new Judgement()) { Type = result }, null) + new DrawableOsuJudgement(new JudgementResult(new HitObject(), new Judgement()) { Type = result }, null) { Anchor = Anchor.Centre, Origin = Anchor.Centre, diff --git a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs index c8c4d004d6..c01eef5252 100644 --- a/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko.Tests/TestSceneTaikoPlayfield.cs @@ -148,7 +148,7 @@ namespace osu.Game.Rulesets.Taiko.Tests var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) }; - ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new ConvertHitObject(), new TaikoJudgement()) { Type = hitResult }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new HitObject(), new TaikoJudgement()) { Type = hitResult }); } private void addStrongHitJudgement(bool kiai) @@ -163,13 +163,13 @@ namespace osu.Game.Rulesets.Taiko.Tests var h = new DrawableTestHit(hit) { X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f) }; - ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new ConvertHitObject(), new TaikoJudgement()) { Type = hitResult }); - ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new TestStrongNestedHit(h), new JudgementResult(new ConvertHitObject(), new TaikoStrongJudgement()) { Type = HitResult.Great }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(h, new JudgementResult(new HitObject(), new TaikoJudgement()) { Type = hitResult }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new TestStrongNestedHit(h), new JudgementResult(new HitObject(), new TaikoStrongJudgement()) { Type = HitResult.Great }); } private void addMissJudgement() { - ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new DrawableTestHit(new Hit()), new JudgementResult(new ConvertHitObject(), new TaikoJudgement()) { Type = HitResult.Miss }); + ((TaikoPlayfield)drawableRuleset.Playfield).OnNewResult(new DrawableTestHit(new Hit()), new JudgementResult(new HitObject(), new TaikoJudgement()) { Type = HitResult.Miss }); } private void addBarLine(bool major, double delay = scroll_time) diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs index e99a10524e..7a89642e11 100644 --- a/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs @@ -11,8 +11,8 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Textures; using osu.Framework.Testing; using osu.Game.Audio; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Legacy; using osu.Game.Rulesets.Objects.Types; using osu.Game.Skinning; using osu.Game.Tests.Visual; diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs index 6452857bad..f2bfccb6de 100644 --- a/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectContainer.cs @@ -27,9 +27,9 @@ namespace osu.Game.Tests.Gameplay { DrawableHitObject hitObject = null; - AddStep("setup", () => container.Add(new TestDrawableHitObject(new ConvertHitObject { StartTime = 500 }))); + AddStep("setup", () => container.Add(new TestDrawableHitObject(new HitObject { StartTime = 500 }))); - AddStep("add late hitobject", () => container.Add(hitObject = new TestDrawableHitObject(new ConvertHitObject { StartTime = 1000 }))); + AddStep("add late hitobject", () => container.Add(hitObject = new TestDrawableHitObject(new HitObject { StartTime = 1000 }))); AddAssert("hitobject index is 0", () => container.IndexOf(hitObject) == 0); } @@ -39,9 +39,9 @@ namespace osu.Game.Tests.Gameplay { DrawableHitObject hitObject = null; - AddStep("setup", () => container.Add(new TestDrawableHitObject(new ConvertHitObject { StartTime = 500 }))); + AddStep("setup", () => container.Add(new TestDrawableHitObject(new HitObject { StartTime = 500 }))); - AddStep("add early hitobject", () => container.Add(hitObject = new TestDrawableHitObject(new ConvertHitObject()))); + AddStep("add early hitobject", () => container.Add(hitObject = new TestDrawableHitObject(new HitObject()))); AddAssert("hitobject index is 0", () => container.IndexOf(hitObject) == 1); } @@ -54,8 +54,8 @@ namespace osu.Game.Tests.Gameplay AddStep("setup", () => { - container.Add(firstObject = new TestDrawableHitObject(new ConvertHitObject())); - container.Add(secondObject = new TestDrawableHitObject(new ConvertHitObject { StartTime = 1000 })); + container.Add(firstObject = new TestDrawableHitObject(new HitObject())); + container.Add(secondObject = new TestDrawableHitObject(new HitObject { StartTime = 1000 })); }); AddStep("move first object after second", () => firstObject.HitObject.StartTime = 2000); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs index d350c3d58d..b25b81c9af 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneDrawableScrollingRuleset.cs @@ -20,6 +20,7 @@ using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Drawables; +using osu.Game.Rulesets.Objects.Legacy; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.UI; @@ -163,7 +164,7 @@ namespace osu.Game.Tests.Visual.Gameplay var beatmap = new Beatmap { BeatmapInfo = { Ruleset = new OsuRuleset().RulesetInfo } }; for (int i = 0; i < 10; i++) - beatmap.HitObjects.Add(new ConvertHitObject { StartTime = i * time_range }); + beatmap.HitObjects.Add(new HitObject { StartTime = i * time_range }); return beatmap; } diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs index 494611d414..ddad337c66 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneHitErrorMeter.cs @@ -2,7 +2,6 @@ // See the LICENCE file in the repository root for full licence text. using NUnit.Framework; -using osu.Game.Rulesets.Objects; using System; using System.Collections.Generic; using osu.Game.Rulesets.Judgements; @@ -12,6 +11,7 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Mania.Scoring; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Osu.Scoring; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Scoring; @@ -124,7 +124,7 @@ namespace osu.Game.Tests.Visual.Gameplay private void newJudgement(double offset = 0) { - var judgement = new JudgementResult(new ConvertHitObject(), new Judgement()) + var judgement = new JudgementResult(new HitObject(), new Judgement()) { TimeOffset = offset == 0 ? RNG.Next(-150, 150) : offset, Type = HitResult.Perfect, diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs index c2a71eadae..d03716db2e 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneScrollingHitObjects.cs @@ -224,7 +224,7 @@ namespace osu.Game.Tests.Visual.Gameplay private class TestDrawableControlPoint : DrawableHitObject { public TestDrawableControlPoint(ScrollingDirection direction, double time) - : base(new ConvertHitObject { StartTime = time }) + : base(new HitObject { StartTime = time }) { Origin = Anchor.Centre; @@ -255,7 +255,7 @@ namespace osu.Game.Tests.Visual.Gameplay private class TestDrawableHitObject : DrawableHitObject { public TestDrawableHitObject(double time) - : base(new ConvertHitObject { StartTime = time }) + : base(new HitObject { StartTime = time }) { Origin = Anchor.Custom; OriginPosition = new Vector2(75 / 4.0f); diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs index 6a60ae110b..b9b13d7bd8 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneSongProgress.cs @@ -123,7 +123,7 @@ namespace osu.Game.Tests.Visual.Gameplay { var objects = new List(); for (double i = 0; i < 5000; i += RNG.NextDouble() * 10 + i / 1000) - objects.Add(new ConvertHitObject { StartTime = i }); + objects.Add(new HitObject { StartTime = i }); replaceObjects(objects); } @@ -132,7 +132,7 @@ namespace osu.Game.Tests.Visual.Gameplay { var objects = new List(); for (double i = 0; i < 5000; i++) - objects.Add(new ConvertHitObject { StartTime = i }); + objects.Add(new HitObject { StartTime = i }); replaceObjects(objects); } diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs index 5cac897200..e02ebf3be1 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs @@ -13,6 +13,7 @@ using osu.Game.Rulesets; using osu.Game.Rulesets.Catch; using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Objects.Legacy; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Taiko; diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index bef48f0ced..477d025253 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Objects /// HitObjects may contain more properties for which you should be checking through the IHas* types. /// /// - public abstract class HitObject + public class HitObject { /// /// A small adjustment to the start time of control points to account for rounding/precision errors. @@ -83,7 +83,7 @@ namespace osu.Game.Rulesets.Objects [JsonIgnore] public IReadOnlyList NestedHitObjects => nestedHitObjects; - protected HitObject() + public HitObject() { StartTimeBindable.ValueChanged += time => { @@ -147,7 +147,7 @@ namespace osu.Game.Rulesets.Objects /// Used to decide on drawable object lifetimes. /// [NotNull] - public abstract Judgement CreateJudgement(); + public virtual Judgement CreateJudgement() => new Judgement(); /// /// Creates the for this . @@ -157,7 +157,7 @@ namespace osu.Game.Rulesets.Objects /// /// [NotNull] - protected abstract HitWindows CreateHitWindows(); + protected virtual HitWindows CreateHitWindows() => new HitWindows(); } public static class HitObjectExtensions diff --git a/osu.Game/Rulesets/Objects/ConvertHitObject.cs b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs similarity index 83% rename from osu.Game/Rulesets/Objects/ConvertHitObject.cs rename to osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs index 81a88615a3..e3b0d8a498 100644 --- a/osu.Game/Rulesets/Objects/ConvertHitObject.cs +++ b/osu.Game/Rulesets/Objects/Legacy/ConvertHitObject.cs @@ -4,12 +4,12 @@ using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; -namespace osu.Game.Rulesets.Objects +namespace osu.Game.Rulesets.Objects.Legacy { /// /// A hit object only used for conversion, not actual gameplay. /// - public class ConvertHitObject : HitObject + internal abstract class ConvertHitObject : HitObject { public override Judgement CreateJudgement() => new IgnoreJudgement(); From 36079236e6d96ea1c3a688e662cee9de4e6e0fe4 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Feb 2020 19:22:51 +0900 Subject: [PATCH 21/26] Remove pointless comment Co-Authored-By: Dan Balasescu --- osu.Game/Rulesets/Objects/HitObject.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Rulesets/Objects/HitObject.cs b/osu.Game/Rulesets/Objects/HitObject.cs index 477d025253..9a8efdde84 100644 --- a/osu.Game/Rulesets/Objects/HitObject.cs +++ b/osu.Game/Rulesets/Objects/HitObject.cs @@ -144,7 +144,6 @@ namespace osu.Game.Rulesets.Objects /// /// Creates the that represents the scoring information for this . - /// Used to decide on drawable object lifetimes. /// [NotNull] public virtual Judgement CreateJudgement() => new Judgement(); From b872f782e7eae6fe381c2c9f32666626326e4d49 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Feb 2020 20:04:39 +0900 Subject: [PATCH 22/26] Update framework --- osu.Android.props | 2 +- osu.Game/osu.Game.csproj | 2 +- osu.iOS.props | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 939d179b1d..24afbb86fb 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -54,6 +54,6 @@ - + diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 24ee25c4de..c5ebf0f712 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -23,7 +23,7 @@ - + diff --git a/osu.iOS.props b/osu.iOS.props index 3743138c1a..9574b8cba9 100644 --- a/osu.iOS.props +++ b/osu.iOS.props @@ -74,7 +74,7 @@ - + @@ -82,7 +82,7 @@ - + From 9557a2cd9659fdc565fa95510d7f6b49c71337d3 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 25 Feb 2020 20:52:33 +0900 Subject: [PATCH 23/26] Use object initialiser --- osu.Game/Screens/Edit/Editor.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs index 8d3b8849bc..3a6f02f811 100644 --- a/osu.Game/Screens/Edit/Editor.cs +++ b/osu.Game/Screens/Edit/Editor.cs @@ -93,9 +93,10 @@ namespace osu.Game.Screens.Edit EditorMenuBar menuBar; - var fileMenuItems = new List(); - - fileMenuItems.Add(new EditorMenuItem("Save", MenuItemType.Standard, saveBeatmap)); + var fileMenuItems = new List + { + new EditorMenuItem("Save", MenuItemType.Standard, saveBeatmap) + }; if (RuntimeInfo.IsDesktop) fileMenuItems.Add(new EditorMenuItem("Export package", MenuItemType.Standard, exportBeatmap)); From 535a7989d613538564df1ed650968bf56d49d965 Mon Sep 17 00:00:00 2001 From: Lucas A Date: Tue, 25 Feb 2020 20:57:15 +0100 Subject: [PATCH 24/26] Open rankings overlay on spotlights page. --- osu.Game/Overlays/RankingsOverlay.cs | 6 ++++++ osu.Game/Screens/Menu/MainMenu.cs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/RankingsOverlay.cs b/osu.Game/Overlays/RankingsOverlay.cs index 3304c6ebec..afb23883ac 100644 --- a/osu.Game/Overlays/RankingsOverlay.cs +++ b/osu.Game/Overlays/RankingsOverlay.cs @@ -138,6 +138,12 @@ namespace osu.Game.Overlays Country.Value = requested; } + public void ShowSpotlights() + { + Scope.Value = RankingsScope.Spotlights; + Show(); + } + private void loadNewContent() { loading.Show(); diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index af5db4ce8c..127270f521 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -134,7 +134,7 @@ namespace osu.Game.Screens.Menu buttons.OnSettings = () => settings?.ToggleVisibility(); buttons.OnDirect = () => direct?.ToggleVisibility(); - buttons.OnChart = () => rankings?.ToggleVisibility(); + buttons.OnChart = () => rankings?.ShowSpotlights(); LoadComponentAsync(background = new BackgroundScreenDefault()); preloadSongSelect(); From 88ec31c262e7d8fefe84d90babb7358a9ebd13c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 25 Feb 2020 22:39:20 +0100 Subject: [PATCH 25/26] Add tests demonstrating crash --- .../TestSceneBananaShower.cs | 8 ++- .../TestSceneJuiceStream.cs | 56 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs index 56e378d19e..20911b8d06 100644 --- a/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneBananaShower.cs @@ -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) { 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; } diff --git a/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs new file mode 100644 index 0000000000..cbc87459e1 --- /dev/null +++ b/osu.Game.Rulesets.Catch.Tests/TestSceneJuiceStream.cs @@ -0,0 +1,56 @@ +// Copyright (c) ppy Pty Ltd . 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 + { + 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 + } + } + }; + } +} From bf36dc10a561b02bad1399a6c3a0991572173a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Tue, 25 Feb 2020 23:13:32 +0100 Subject: [PATCH 26/26] Fix invalid cast Since introduction of IgnoreJudgement and its usage in JuiceStream and BananaShower the hard cast in CatcherArea that was used to check if the drawable hit object should cause the fruits on the plate explode at the end of combo caused a hard crash instead, since IgnoreJudgement was no longer deriving from CatchJudgement. Replace the hard cast with a soft pattern-matched cast. --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index ff2471f8bf..0b3809150a 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -89,7 +89,7 @@ namespace osu.Game.Rulesets.Catch.UI if (fruit.HitObject.LastInCombo) { - if (((CatchJudgement)result.Judgement).ShouldExplodeFor(result)) + if (result.Judgement is CatchJudgement catchJudgement && catchJudgement.ShouldExplodeFor(result)) runAfterLoaded(() => MovableCatcher.Explode()); else MovableCatcher.Drop();